Separate some mesh stuff
This commit is contained in:
parent
39dbede993
commit
a0b287b9fa
|
@ -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()
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue