diff --git a/Assets/Scripts/Modules/BrushModel.cs b/Assets/Scripts/Modules/BrushModel.cs index 443b8ed..1757cf5 100644 --- a/Assets/Scripts/Modules/BrushModel.cs +++ b/Assets/Scripts/Modules/BrushModel.cs @@ -35,9 +35,48 @@ public class BrushModel { var modelGO = new GameObject($"SubModel_{modelIdx}"); modelGO.transform.SetParent(rootGameObject.transform); - + var headNode = subModels[modelIdx].GetHeadNode(model); - CreateNodeMeshes(headNode, surfaces, modelGO); + + var surfaceGroups = new Dictionary<(string, int), List>(); + GroupSurfaces(headNode, surfaces, surfaceGroups); + + foreach (var group in surfaceGroups) + { + var key = group.Key; + var groupGO = new GameObject($"T{key.Item1}_L{key.Item2}"); + groupGO.transform.SetParent(modelGO.transform); + + for (int i = 0; i < group.Value.Count; ++i) + { + CreateSurfaceMeshes(group.Value[i], $"{i}", groupGO); + } + } + } + } + + private void GroupSurfaces(QNode node, QSurface[] surfaces, Dictionary<(string, int), List> surfaceGroups) + { + if (node.contents < 0) // Leaf node + return; + + for (int surfIdx = 0; surfIdx < node.numSurfaces; ++surfIdx) + { + var surface = surfaces[node.firstSurface + surfIdx]; + + string texName = surface.TextureInfo.Texture.name; + int lightNum = surface.lightmapTextureNum; + var key = (texName, lightNum); + + if (!surfaceGroups.ContainsKey(key)) + surfaceGroups[key] = new List(); + + surfaceGroups[key].Add(surface); + } + + foreach (var childNode in node.Children) + { + GroupSurfaces(childNode, surfaces, surfaceGroups); } } @@ -48,8 +87,12 @@ public class BrushModel var nodeGO = new GameObject("Node"); nodeGO.transform.SetParent(parentGO.transform); - - CreateSurfaceMeshes(node, surfaces, nodeGO); + + for (int surfIdx = 0; surfIdx < node.numSurfaces; ++surfIdx) + { + var surface = surfaces[node.firstSurface + surfIdx]; + CreateSurfaceMeshes(surface, $"{node.firstSurface + surfIdx}", nodeGO); + } foreach (var childNode in node.Children) { @@ -57,48 +100,41 @@ public class BrushModel } } - private void CreateSurfaceMeshes(QNode node, QSurface[] surfaces, GameObject nodeGO) + private void CreateSurfaceMeshes(QSurface surface, string key, GameObject nodeGO) { - for (int surfIdx = 0; surfIdx < node.numSurfaces; ++surfIdx) + foreach (var polyVerts in surface.GetPolygons()) { - 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()); - } + tempVertices.Clear(); + tempTextureUVs.Clear(); + tempLightmapUVs.Clear(); + tempIndices.Clear(); - // Reconstruct triangle fan - for (ushort index = 2; index < polyVerts.Length; ++index) - { - tempIndices.Add(0); - tempIndices.Add((ushort) (index - 1)); - tempIndices.Add(index); - } + 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()); + } - Mesh mesh = new Mesh(); - mesh.name = $"Surface_{node.firstSurface + surfIdx}"; - 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); - - CreateMeshObject(mesh, nodeGO); + // Reconstruct triangle fan + for (ushort index = 2; index < polyVerts.Length; ++index) + { + tempIndices.Add(0); + tempIndices.Add((ushort) (index - 1)); + tempIndices.Add(index); } - var texNum = surface.TextureInfo.Texture.TextureNum; + Mesh mesh = new Mesh(); + mesh.name = $"Surface_{key}"; + 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); + + CreateMeshObject(mesh, nodeGO); } }