Separate some mesh stuff

This commit is contained in:
Jarrod Doyle 2024-12-09 08:19:50 +00:00
parent 39dbede993
commit a0b287b9fa
Signed by: Jayrude
GPG Key ID: 38B57B16E7C0ADF7
2 changed files with 81 additions and 53 deletions

View File

@ -8,13 +8,6 @@ namespace KeepersCompound.Lightmapper;
public class LightMapper public class LightMapper
{ {
private enum SurfaceType
{
Solid,
Sky,
Water,
}
private class Settings private class Settings
{ {
public Vector3 AmbientLight; public Vector3 AmbientLight;
@ -30,7 +23,7 @@ public class LightMapper
private ObjectHierarchy _hierarchy; private ObjectHierarchy _hierarchy;
private Raytracer _scene; private Raytracer _scene;
private List<Light> _lights; private List<Light> _lights;
private List<SurfaceType> _triangleTypeMap; private SurfaceType[] _triangleTypeMap;
public LightMapper( public LightMapper(
string installPath, string installPath,
@ -42,9 +35,17 @@ public class LightMapper
_misPath = _campaign.GetResourcePath(ResourceType.Mission, missionName); _misPath = _campaign.GetResourcePath(ResourceType.Mission, missionName);
_mission = Timing.TimeStage("Parse DB", () => new DbFile(_misPath)); _mission = Timing.TimeStage("Parse DB", () => new DbFile(_misPath));
_hierarchy = Timing.TimeStage("Build Hierarchy", BuildHierarchy); _hierarchy = Timing.TimeStage("Build Hierarchy", BuildHierarchy);
_triangleTypeMap = [];
_scene = Timing.TimeStage("Build Scene", BuildRaytracingScene);
_lights = []; _lights = [];
var mesh = Timing.TimeStage("Build Mesh", BuildMesh);
_triangleTypeMap = mesh.TriangleSurfaceMap;
_scene = Timing.TimeStage("Build RT Scene", () =>
{
var rt = new Raytracer();
rt.AddMesh(new TriangleMesh(mesh.Vertices, mesh.Indices));
rt.CommitScene();
return rt;
});
} }
public void Light() public void Light()
@ -109,16 +110,17 @@ public class LightMapper
return new ObjectHierarchy(_mission); return new ObjectHierarchy(_mission);
} }
private Raytracer BuildRaytracingScene() private Mesh BuildMesh()
{ {
// TODO: Should this throw? // TODO: Should this throw?
if (!_mission.TryGetChunk<WorldRep>("WREXT", out var worldRep)) if (!_mission.TryGetChunk<WorldRep>("WREXT", out var worldRep) ||
!_mission.TryGetChunk<BrList>("BRLIST", out var brList))
{ {
return null; return new Mesh(0, [], [], []);
} }
var vertices = new List<Vector3>(); var meshBuilder = new MeshBuilder();
var indices = new List<int>(); var polyVertices = new List<Vector3>();
// Worldrep mesh // Worldrep mesh
foreach (var cell in worldRep.Cells) foreach (var cell in worldRep.Cells)
@ -138,12 +140,12 @@ public class LightMapper
for (var polyIdx = 0; polyIdx < numRenderPolys; polyIdx++) for (var polyIdx = 0; polyIdx < numRenderPolys; polyIdx++)
{ {
var poly = cell.Polys[polyIdx]; var poly = cell.Polys[polyIdx];
var meshIndexOffset = vertices.Count;
var numPolyVertices = poly.VertexCount; polyVertices.Clear();
for (var j = 0; j < numPolyVertices; j++) polyVertices.EnsureCapacity(poly.VertexCount);
for (var i = 0; i < poly.VertexCount; i++)
{ {
var vertex = cell.Vertices[cell.Indices[cellIdxOffset + j]]; polyVertices.Add(cell.Vertices[cell.Indices[cellIdxOffset + i]]);
vertices.Add(vertex);
} }
// We need to know what type of surface this poly is so we can map Embree primitive IDs to surface // We need to know what type of surface this poly is so we can map Embree primitive IDs to surface
@ -158,26 +160,12 @@ public class LightMapper
primType = SurfaceType.Water; primType = SurfaceType.Water;
} }
// Cell polygons are n-sided, but fortunately they're convex so we can just do a fan triangulation meshBuilder.AddPolygon(polyVertices, primType);
for (var j = 1; j < numPolyVertices - 1; j++) cellIdxOffset += poly.VertexCount;
{
indices.Add(meshIndexOffset);
indices.Add(meshIndexOffset + j);
indices.Add(meshIndexOffset + j + 1);
_triangleTypeMap.Add(primType);
}
cellIdxOffset += cell.Polys[polyIdx].VertexCount;
} }
} }
// Object meshes?? // Object meshes
// TODO: Should this throw?
if (!_mission.TryGetChunk<BrList>("BRLIST", out var brList))
{
return null;
}
foreach (var brush in brList.Brushes) foreach (var brush in brList.Brushes)
{ {
if (brush.media != BrList.Brush.Media.Object) if (brush.media != BrList.Brush.Media.Object)
@ -198,7 +186,7 @@ public class LightMapper
var renderMode = renderTypeProp?.mode ?? PropRenderType.Mode.Normal; var renderMode = renderTypeProp?.mode ?? PropRenderType.Mode.Normal;
// TODO: Check which rendermodes cast shadows :) // TODO: Check which rendermodes cast shadows :)
if (modelNameProp == null || !castsShadows || renderMode != PropRenderType.Mode.Normal) if (modelNameProp == null || !castsShadows || renderMode == PropRenderType.Mode.CoronaOnly)
{ {
continue; continue;
} }
@ -246,29 +234,21 @@ public class LightMapper
} }
} }
// for each polygon slam it's vertices and indices :) // for each polygon slam its vertices and indices :)
foreach (var poly in model.Polygons) foreach (var poly in model.Polygons)
{ {
var indexOffset = vertices.Count; polyVertices.Clear();
polyVertices.EnsureCapacity(poly.VertexCount);
foreach (var idx in poly.VertexIndices) foreach (var idx in poly.VertexIndices)
{ {
vertices.Add(model.Vertices[idx]); polyVertices.Add(model.Vertices[idx]);
} }
for (int i = 1; i < poly.VertexCount - 1; i++) meshBuilder.AddPolygon(polyVertices, SurfaceType.Solid);
{
indices.Add(indexOffset);
indices.Add(indexOffset + i);
indices.Add(indexOffset + i + 1);
_triangleTypeMap.Add(SurfaceType.Solid);
}
} }
} }
var rt = new Raytracer(); return meshBuilder.Build();
rt.AddMesh(new TriangleMesh([.. vertices], [.. indices]));
rt.CommitScene();
return rt;
} }
private void BuildLightList() private void BuildLightList()

View File

@ -0,0 +1,48 @@
using System.Numerics;
namespace KeepersCompound.Lightmapper;
public enum SurfaceType
{
Solid,
Sky,
Water,
}
public class Mesh(int triangleCount, List<Vector3> vertices, List<int> indices, List<SurfaceType> triangleSurfaceMap)
{
public int TriangleCount { get; } = triangleCount;
public Vector3[] Vertices { get; } = [..vertices];
public int[] Indices { get; } = [..indices];
public SurfaceType[] TriangleSurfaceMap { get; } = [..triangleSurfaceMap];
}
public class MeshBuilder
{
private int _triangleCount = 0;
private readonly List<Vector3> _vertices = [];
private readonly List<int> _indices = [];
private readonly List<SurfaceType> _primSurfaceMap = [];
public void AddPolygon(List<Vector3> vertices, SurfaceType surfaceType)
{
var vertexCount = vertices.Count;
var indexOffset = _vertices.Count;
// Polygons are n-sided, but fortunately they're convex so we can just do a fan triangulation
_vertices.AddRange(vertices);
for (var i = 1; i < vertexCount - 1; i++)
{
_indices.Add(indexOffset);
_indices.Add(indexOffset + i);
_indices.Add(indexOffset + i + 1);
_primSurfaceMap.Add(surfaceType);
_triangleCount++;
}
}
public Mesh Build()
{
return new Mesh(_triangleCount, _vertices, _indices, _primSurfaceMap);
}
}