Browse Source

Recursively traverse the BSP tree and create surface meshes per node

console
Nico de Poel 5 years ago
parent
commit
a615495c25
  1. 6
      Assets/Scripts/Data/QModel.cs
  2. 103
      Assets/Scripts/Modules/BrushModel.cs

6
Assets/Scripts/Data/QModel.cs

@ -238,7 +238,7 @@ public struct QSubModel
public QNode GetHeadNode(QModel model) public QNode GetHeadNode(QModel model)
{ {
IntPtr nodePtr = IntPtr.Add(model.nodes, headNode[0]);
IntPtr nodePtr = IntPtr.Add(model.nodes, headNode[0] * Marshal.SizeOf<QNode>());
return Marshal.PtrToStructure<QNode>(nodePtr); return Marshal.PtrToStructure<QNode>(nodePtr);
} }
} }
@ -249,12 +249,16 @@ public struct QSubModel
[StructLayout(LayoutKind.Sequential, Pack = 0)] [StructLayout(LayoutKind.Sequential, Pack = 0)]
public struct QNode public struct QNode
{ {
// Common with leaf
public int contents; // 0 for nodes, negative for leafs public int contents; // 0 for nodes, negative for leafs
public int visFrame; public int visFrame;
public QVec3 mins, maxs; public QVec3 mins, maxs;
public IntPtr parent; // Pointer to mnode_t public IntPtr parent; // Pointer to mnode_t
// Node specific
public IntPtr plane; // Pointer to mplane_t public IntPtr plane; // Pointer to mplane_t
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public IntPtr[] children; // Array of pointers to mnode_t [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public IntPtr[] children; // Array of pointers to mnode_t
public uint firstSurface; public uint firstSurface;
public uint numSurfaces; public uint numSurfaces;

103
Assets/Scripts/Modules/BrushModel.cs

@ -7,6 +7,12 @@ public class BrushModel
private readonly string name; private readonly string name;
private readonly List<Mesh> meshes = new List<Mesh>(); 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>();
public BrushModel(string name) public BrushModel(string name)
{ {
this.name = name; this.name = name;
@ -17,46 +23,10 @@ public class BrushModel
var subModels = model.SubModels; var subModels = model.SubModels;
var surfaces = model.Surfaces; var surfaces = model.Surfaces;
List<Vector3> vertices = new List<Vector3>();
List<Vector2> textureUVs = new List<Vector2>();
List<Vector2> lightmapUVs = new List<Vector2>();
List<ushort> indices = new List<ushort>();
for (int surfIdx = 0; surfIdx < surfaces.Length; ++surfIdx)
for (int modelIdx = 0; modelIdx < subModels.Length; ++modelIdx)
{ {
foreach (var polyVerts in surfaces[surfIdx].GetPolygons())
{
vertices.Clear();
textureUVs.Clear();
lightmapUVs.Clear();
indices.Clear();
for (int vertIdx = 0; vertIdx < polyVerts.Length; ++vertIdx)
{
vertices.Add(polyVerts[vertIdx].position.ToVector3().ToUnity());
textureUVs.Add(polyVerts[vertIdx].textureUV.ToVector2());
lightmapUVs.Add(polyVerts[vertIdx].lightmapUV.ToVector2());
}
// Reconstruct triangle fan
for (ushort index = 2; index < polyVerts.Length; ++index)
{
indices.Add(0);
indices.Add((ushort)(index - 1));
indices.Add(index);
}
Mesh mesh = new Mesh();
mesh.SetVertices(vertices);
mesh.SetUVs(0, textureUVs);
mesh.SetUVs(1, lightmapUVs);
mesh.SetIndices(indices, MeshTopology.Triangles, 0);
mesh.RecalculateNormals();
mesh.UploadMeshData(true);
meshes.Add(mesh);
}
var texNum = surfaces[surfIdx].TextureInfo.Texture.TextureNum;
var headNode = subModels[modelIdx].GetHeadNode(model);
CreateNodeMeshes(headNode, surfaces);
} }
// DEBUG // DEBUG
@ -83,4 +53,59 @@ public class BrushModel
go.transform.SetPositionAndRotation(Vector3.zero, Quaternion.identity); 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;
}
}
} }
Loading…
Cancel
Save