|
|
@ -37,7 +37,46 @@ public class BrushModel |
|
|
modelGO.transform.SetParent(rootGameObject.transform); |
|
|
modelGO.transform.SetParent(rootGameObject.transform); |
|
|
|
|
|
|
|
|
var headNode = subModels[modelIdx].GetHeadNode(model); |
|
|
var headNode = subModels[modelIdx].GetHeadNode(model); |
|
|
CreateNodeMeshes(headNode, surfaces, modelGO); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var surfaceGroups = new Dictionary<(string, int), List<QSurface>>(); |
|
|
|
|
|
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<QSurface>> 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<QSurface>(); |
|
|
|
|
|
|
|
|
|
|
|
surfaceGroups[key].Add(surface); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
foreach (var childNode in node.Children) |
|
|
|
|
|
{ |
|
|
|
|
|
GroupSurfaces(childNode, surfaces, surfaceGroups); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -49,7 +88,11 @@ public class BrushModel |
|
|
var nodeGO = new GameObject("Node"); |
|
|
var nodeGO = new GameObject("Node"); |
|
|
nodeGO.transform.SetParent(parentGO.transform); |
|
|
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) |
|
|
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]; |
|
|
|
|
|
|
|
|
tempVertices.Clear(); |
|
|
|
|
|
tempTextureUVs.Clear(); |
|
|
|
|
|
tempLightmapUVs.Clear(); |
|
|
|
|
|
tempIndices.Clear(); |
|
|
|
|
|
|
|
|
foreach (var polyVerts in surface.GetPolygons()) |
|
|
|
|
|
|
|
|
for (int vertIdx = 0; vertIdx < polyVerts.Length; ++vertIdx) |
|
|
{ |
|
|
{ |
|
|
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); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
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); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|