Browse Source

Further cleaned up BrushModel code and moved creation of debug game objects into RenderModule, where the models can be linked to their textures now as well. The result: properly textured maps are being rendered!

console
Nico de Poel 5 years ago
parent
commit
3de63008b7
  1. 95
      Assets/Scripts/Modules/BrushModel.cs
  2. 32
      Assets/Scripts/Modules/RenderModule.cs

95
Assets/Scripts/Modules/BrushModel.cs

@ -1,12 +1,14 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.Rendering;
public class BrushModel
{
private readonly string name;
private readonly List<Mesh> meshes = new List<Mesh>();
public string Name { get; }
private readonly List<SubModel> subModels = new List<SubModel>();
// Reusable temporary data containers
private readonly List<Vector3> tempVertices = new List<Vector3>();
@ -14,53 +16,52 @@ public class BrushModel
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;
Name = name;
}
rootGameObject = new GameObject(name);
rootGameObject.transform.SetPositionAndRotation(Vector3.zero, Quaternion.identity);
public int SubModelCount => subModels.Count;
debugMaterial = new Material(Shader.Find("Universal Render Pipeline/Simple Lit"));
public SubModel GetSubModel(int index)
{
return subModels[index];
}
public void ImportMeshData(QModel model)
{
var subModels = model.SubModels;
var surfaces = model.Surfaces;
var inSubModels = model.SubModels;
var inSurfaces = model.Surfaces;
for (int modelIdx = 0; modelIdx < subModels.Length; ++modelIdx)
for (int modelIdx = 0; modelIdx < inSubModels.Length; ++modelIdx)
{
var modelGO = new GameObject($"SubModel_{modelIdx}");
modelGO.transform.SetParent(rootGameObject.transform);
var headNode = subModels[modelIdx].GetHeadNode(model);
var subModel = new SubModel();
subModels.Add(subModel);
// Traverse the BSP tree and group the surfaces based on their material properties
var headNode = inSubModels[modelIdx].GetHeadNode(model);
var surfaceGroups = new Dictionary<(IntPtr, int), List<QSurface>>();
GroupSurfaces(headNode, surfaces, surfaceGroups);
GroupSurfaces(headNode, inSurfaces, surfaceGroups);
// Create a single mesh for each group of surfaces
foreach (var group in surfaceGroups)
{
var key = group.Key;
var groupGO = new GameObject($"T{key.Item1}_L{key.Item2}");
groupGO.transform.SetParent(modelGO.transform);
var mesh = CreateMeshFromSurfaces(group.Value, $"T{key.Item1}_L{key.Item2}");
CreateMeshFromSurfaces(group.Value, groupGO.name, groupGO);
subModel.AddSurfaceMesh(new SurfaceMesh(mesh, key.Item1, key.Item2));
}
}
}
public void Dispose()
{
foreach (var mesh in meshes)
foreach (var subModel in subModels)
{
UnityEngine.Object.Destroy(mesh);
subModel.Dispose();
}
meshes.Clear();
subModels.Clear();
}
private void GroupSurfaces(QNode node, QSurface[] surfaces, Dictionary<(IntPtr, int), List<QSurface>> surfaceGroups)
@ -88,7 +89,7 @@ public class BrushModel
}
}
private void CreateMeshFromSurfaces(List<QSurface> surfaces, string key, GameObject parentGO)
private Mesh CreateMeshFromSurfaces(List<QSurface> surfaces, string key)
{
tempVertices.Clear();
tempTextureUVs.Clear();
@ -128,21 +129,43 @@ public class BrushModel
mesh.SetIndices(tempIndices, MeshTopology.Triangles, 0);
mesh.RecalculateNormals();
mesh.UploadMeshData(true);
meshes.Add(mesh);
return mesh;
}
public class SubModel
{
public List<SurfaceMesh> SurfaceMeshes { get; } = new List<SurfaceMesh>();
public void AddSurfaceMesh(SurfaceMesh surfaceMesh)
{
SurfaceMeshes.Add(surfaceMesh);
}
CreateMeshObject(mesh, parentGO);
public void Dispose()
{
foreach (var surfaceMesh in SurfaceMeshes)
{
surfaceMesh.Dispose();
}
}
}
private void CreateMeshObject(Mesh mesh, GameObject parentGO)
public class SurfaceMesh
{
var mf = parentGO.AddComponent<MeshFilter>();
mf.sharedMesh = mesh;
var mr = parentGO.AddComponent<MeshRenderer>();
mr.sharedMaterial = debugMaterial;
mr.shadowCastingMode = ShadowCastingMode.Off;
mr.receiveShadows = false;
mr.lightProbeUsage = LightProbeUsage.Off;
mr.reflectionProbeUsage = ReflectionProbeUsage.Off;
public Mesh Mesh { get; }
public QTexture Texture { get; }
public int Lightmap { get; }
public SurfaceMesh(Mesh mesh, IntPtr texturePtr, int lightmap)
{
Mesh = mesh;
Texture = Marshal.PtrToStructure<QTexture>(texturePtr);
Lightmap = lightmap;
}
public void Dispose()
{
UnityEngine.Object.Destroy(Mesh);
}
}
}

32
Assets/Scripts/Modules/RenderModule.cs

@ -137,6 +137,38 @@ public partial class RenderModule
var brushModel = new BrushModel(model.name);
brushModel.ImportMeshData(model);
// DEBUG
var worldGO = new GameObject(model.name);
for (int i = 0; i < brushModel.SubModelCount; ++i)
{
var subModel = brushModel.GetSubModel(i);
var subModelGO = new GameObject($"SubModel_{i}");
subModelGO.transform.SetParent(worldGO.transform);
foreach (var surfaceMesh in subModel.SurfaceMeshes)
{
var meshGO = new GameObject(surfaceMesh.Mesh.name);
meshGO.transform.SetParent(subModelGO.transform);
var mf = meshGO.AddComponent<MeshFilter>();
mf.sharedMesh = surfaceMesh.Mesh;
var material = new Material(Shader.Find("Universal Render Pipeline/Simple Lit"));
uint texNum = surfaceMesh.Texture.TextureNum;
if (texNum > 0 && textures.ContainsKey(texNum))
{
material.mainTexture = textures[texNum];
}
var mr = meshGO.AddComponent<MeshRenderer>();
mr.sharedMaterial = material;
mr.shadowCastingMode = ShadowCastingMode.Off;
mr.receiveShadows = false;
mr.lightProbeUsage = LightProbeUsage.Off;
mr.reflectionProbeUsage = ReflectionProbeUsage.Off;
}
}
brushModels.Add(brushModel);
return brushModels.Count;
}

Loading…
Cancel
Save