You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

120 lines
4.1 KiB

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
public class BrushModel
{
private readonly string name;
private readonly List<Mesh> meshes = new List<Mesh>();
// Reusable temporary data containers
private readonly List<Vector3> tempVertices = new List<Vector3>();
private readonly List<Vector2> tempTextureUVs = new List<Vector2>();
private readonly List<Vector2> tempLightmapUVs = new List<Vector2>();
private readonly List<ushort> tempIndices = new List<ushort>();
private readonly GameObject rootGameObject;
private readonly Material debugMaterial;
public BrushModel(string name)
{
this.name = name;
rootGameObject = new GameObject(name);
rootGameObject.transform.SetPositionAndRotation(Vector3.zero, Quaternion.identity);
debugMaterial = new Material(Shader.Find("Universal Render Pipeline/Simple Lit"));
}
public void ImportMeshData(QModel model)
{
var subModels = model.SubModels;
var surfaces = model.Surfaces;
for (int modelIdx = 0; modelIdx < subModels.Length; ++modelIdx)
{
var modelGO = new GameObject($"SubModel_{modelIdx}");
modelGO.transform.SetParent(rootGameObject.transform);
var headNode = subModels[modelIdx].GetHeadNode(model);
CreateNodeMeshes(headNode, surfaces, modelGO);
}
}
private void CreateNodeMeshes(QNode node, QSurface[] surfaces, GameObject parentGO)
{
if (node.contents < 0) // Leaf node
return;
var nodeGO = new GameObject("Node");
nodeGO.transform.SetParent(parentGO.transform);
CreateSurfaceMeshes(node, surfaces, nodeGO);
foreach (var childNode in node.Children)
{
CreateNodeMeshes(childNode, surfaces, nodeGO);
}
}
private void CreateSurfaceMeshes(QNode node, QSurface[] surfaces, GameObject nodeGO)
{
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.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);
}
var texNum = surface.TextureInfo.Texture.TextureNum;
}
}
private void CreateMeshObject(Mesh mesh, GameObject parentGO)
{
var meshGO = new GameObject(mesh.name);
meshGO.transform.SetParent(parentGO.transform);
var mf = meshGO.AddComponent<MeshFilter>();
mf.sharedMesh = mesh;
var mr = meshGO.AddComponent<MeshRenderer>();
mr.sharedMaterial = debugMaterial;
mr.shadowCastingMode = ShadowCastingMode.Off;
mr.receiveShadows = false;
mr.lightProbeUsage = LightProbeUsage.Off;
mr.reflectionProbeUsage = ReflectionProbeUsage.Off;
}
}