using System.Collections.Generic; using UnityEngine; using UnityEngine.Rendering; public class BrushModel { private readonly string name; private readonly List meshes = new List(); // Reusable temporary data containers private readonly List tempVertices = new List(); private readonly List tempTextureUVs = new List(); private readonly List tempLightmapUVs = new List(); private readonly List tempIndices = new List(); public BrushModel(string name) { this.name = name; } public void ImportMeshData(QModel model) { var subModels = model.SubModels; var surfaces = model.Surfaces; for (int modelIdx = 0; modelIdx < subModels.Length; ++modelIdx) { var headNode = subModels[modelIdx].GetHeadNode(model); CreateNodeMeshes(headNode, surfaces); } // DEBUG var go = new GameObject(name); var mat = new Material(Shader.Find("Universal Render Pipeline/Simple Lit")); for (int i = 0; i < meshes.Count; ++i) { var mesh = meshes[i]; var meshGO = new GameObject($"Surface_{i}"); meshGO.transform.SetParent(go.transform); var mf = meshGO.AddComponent(); mf.sharedMesh = mesh; var mr = meshGO.AddComponent(); mr.sharedMaterial = mat; mr.shadowCastingMode = ShadowCastingMode.Off; mr.receiveShadows = false; mr.lightProbeUsage = LightProbeUsage.Off; mr.reflectionProbeUsage = ReflectionProbeUsage.Off; } go.transform.SetPositionAndRotation(Vector3.zero, Quaternion.identity); } private void CreateNodeMeshes(QNode node, QSurface[] surfaces) { if (node.contents < 0) // Leaf node return; CreateSurfaceMeshes(node, surfaces); foreach (var childNode in node.Children) { CreateNodeMeshes(childNode, surfaces); } } private void CreateSurfaceMeshes(QNode node, QSurface[] surfaces) { for (int surfIdx = 0; surfIdx < node.numSurfaces; ++surfIdx) { var surface = surfaces[node.firstSurface + surfIdx]; foreach (var polyVerts in surface.GetPolygons()) { tempVertices.Clear(); tempTextureUVs.Clear(); tempLightmapUVs.Clear(); tempIndices.Clear(); for (int vertIdx = 0; vertIdx < polyVerts.Length; ++vertIdx) { tempVertices.Add(polyVerts[vertIdx].position.ToVector3().ToUnity()); tempTextureUVs.Add(polyVerts[vertIdx].textureUV.ToVector2()); tempLightmapUVs.Add(polyVerts[vertIdx].lightmapUV.ToVector2()); } // Reconstruct triangle fan for (ushort index = 2; index < polyVerts.Length; ++index) { tempIndices.Add(0); tempIndices.Add((ushort) (index - 1)); tempIndices.Add(index); } Mesh mesh = new Mesh(); mesh.SetVertices(tempVertices); mesh.SetUVs(0, tempTextureUVs); mesh.SetUVs(1, tempLightmapUVs); mesh.SetIndices(tempIndices, MeshTopology.Triangles, 0); mesh.RecalculateNormals(); mesh.UploadMeshData(true); meshes.Add(mesh); } var texNum = surface.TextureInfo.Texture.TextureNum; } } }