From adf61c0f6fd916104dc9218f8ba37d85d3cfd387 Mon Sep 17 00:00:00 2001 From: Jarrod Doyle Date: Mon, 9 Dec 2024 08:34:48 +0000 Subject: [PATCH] Move more meshing to MeshBuilder --- KeepersCompound.Lightmapper/LightMapper.cs | 136 +------------------- KeepersCompound.Lightmapper/MeshBuilder.cs | 139 ++++++++++++++++++++- 2 files changed, 144 insertions(+), 131 deletions(-) diff --git a/KeepersCompound.Lightmapper/LightMapper.cs b/KeepersCompound.Lightmapper/LightMapper.cs index 29ac6d1..5592293 100644 --- a/KeepersCompound.Lightmapper/LightMapper.cs +++ b/KeepersCompound.Lightmapper/LightMapper.cs @@ -112,142 +112,18 @@ public class LightMapper private Mesh BuildMesh() { + var meshBuilder = new MeshBuilder(); + // TODO: Should this throw? + // TODO: Only do object polys if objcast lighting? if (!_mission.TryGetChunk("WREXT", out var worldRep) || !_mission.TryGetChunk("BRLIST", out var brList)) { - return new Mesh(0, [], [], []); - } - - var meshBuilder = new MeshBuilder(); - var polyVertices = new List(); - - // Worldrep mesh - foreach (var cell in worldRep.Cells) - { - var numPolys = cell.PolyCount; - var numRenderPolys = cell.RenderPolyCount; - var numPortalPolys = cell.PortalPolyCount; - - // There's nothing to render - if (numRenderPolys == 0 || numPortalPolys >= numPolys) - { - continue; - } - - var solidPolys = numPolys - numPortalPolys; - var cellIdxOffset = 0; - for (var polyIdx = 0; polyIdx < numRenderPolys; polyIdx++) - { - var poly = cell.Polys[polyIdx]; - - polyVertices.Clear(); - polyVertices.EnsureCapacity(poly.VertexCount); - for (var i = 0; i < poly.VertexCount; i++) - { - polyVertices.Add(cell.Vertices[cell.Indices[cellIdxOffset + i]]); - } - - // We need to know what type of surface this poly is so we can map Embree primitive IDs to surface - // types - var renderPoly = cell.RenderPolys[polyIdx]; - var primType = SurfaceType.Solid; - if (renderPoly.TextureId == 249) - { - primType = SurfaceType.Sky; - } else if (polyIdx >= solidPolys) - { - primType = SurfaceType.Water; - } - - meshBuilder.AddPolygon(polyVertices, primType); - cellIdxOffset += poly.VertexCount; - } - } - - // Object meshes - foreach (var brush in brList.Brushes) - { - if (brush.media != BrList.Brush.Media.Object) - { - continue; - } - - var id = (int)brush.brushInfo; - var modelNameProp = _hierarchy.GetProperty(id, "P$ModelName"); - var scaleProp = _hierarchy.GetProperty(id, "P$Scale"); - var renderTypeProp = _hierarchy.GetProperty(id, "P$RenderTyp"); - var jointPosProp = _hierarchy.GetProperty(id, "P$JointPos"); - var immobileProp = _hierarchy.GetProperty(id, "P$Immobile"); - var staticShadowProp = _hierarchy.GetProperty(id, "P$StatShad"); - - var joints = jointPosProp?.Positions ?? [0, 0, 0, 0, 0, 0]; - var castsShadows = (immobileProp?.value ?? false) || (staticShadowProp?.value ?? false); - var renderMode = renderTypeProp?.mode ?? PropRenderType.Mode.Normal; - - // TODO: Check which rendermodes cast shadows :) - if (modelNameProp == null || !castsShadows || renderMode == PropRenderType.Mode.CoronaOnly) - { - continue; - } - - // Let's try and place an object :) - var modelName = modelNameProp.value.ToLower() + ".bin"; - var modelPath = _campaign.GetResourcePath(ResourceType.Object, modelName); - if (modelPath == null) - { - continue; - } - - // TODO: Handle failing to find model more gracefully - var pos = brush.position; - var rot = brush.angle; - var scale = scaleProp?.value ?? Vector3.One; - var model = new ModelFile(modelPath); - pos -= model.Header.Center; - - // for each object modify the vertices - // TODO: Almost perfect transform! - // TODO: Handle nested sub objects - foreach (var subObj in model.Objects) - { - var jointTrans = Matrix4x4.Identity; - if (subObj.Joint != -1) - { - var ang = float.DegreesToRadians(joints[subObj.Joint]); - var jointRot = Matrix4x4.CreateFromYawPitchRoll(0, ang, 0); - var objTrans = subObj.Transform; - jointTrans = jointRot * objTrans; - } - var scalePart = Matrix4x4.CreateScale(scale); - var rotPart = Matrix4x4.CreateFromYawPitchRoll(float.DegreesToRadians(rot.Y), float.DegreesToRadians(rot.X), - float.DegreesToRadians(rot.Z)); - var transPart = Matrix4x4.CreateTranslation(pos); - var transform = jointTrans * scalePart * rotPart * transPart; - - var start = subObj.PointIdx; - var end = start + subObj.PointCount; - for (var i = start; i < end; i++) - { - var v = model.Vertices[i]; - model.Vertices[i] = Vector3.Transform(v, transform); - } - } - - // for each polygon slam its vertices and indices :) - foreach (var poly in model.Polygons) - { - polyVertices.Clear(); - polyVertices.EnsureCapacity(poly.VertexCount); - foreach (var idx in poly.VertexIndices) - { - polyVertices.Add(model.Vertices[idx]); - } - - meshBuilder.AddPolygon(polyVertices, SurfaceType.Solid); - } + return meshBuilder.Build(); } + meshBuilder.AddWorldRepPolys(worldRep); + meshBuilder.AddObjectPolys(brList, _hierarchy, _campaign); return meshBuilder.Build(); } diff --git a/KeepersCompound.Lightmapper/MeshBuilder.cs b/KeepersCompound.Lightmapper/MeshBuilder.cs index 345996d..782c1b6 100644 --- a/KeepersCompound.Lightmapper/MeshBuilder.cs +++ b/KeepersCompound.Lightmapper/MeshBuilder.cs @@ -1,4 +1,7 @@ using System.Numerics; +using KeepersCompound.LGS; +using KeepersCompound.LGS.Database; +using KeepersCompound.LGS.Database.Chunks; namespace KeepersCompound.Lightmapper; @@ -24,7 +27,141 @@ public class MeshBuilder private readonly List _indices = []; private readonly List _primSurfaceMap = []; - public void AddPolygon(List vertices, SurfaceType surfaceType) + public void AddWorldRepPolys(WorldRep worldRep) + { + var polyVertices = new List(); + foreach (var cell in worldRep.Cells) + { + var numPolys = cell.PolyCount; + var numRenderPolys = cell.RenderPolyCount; + var numPortalPolys = cell.PortalPolyCount; + + // There's nothing to render + if (numRenderPolys == 0 || numPortalPolys >= numPolys) + { + continue; + } + + var solidPolys = numPolys - numPortalPolys; + var cellIdxOffset = 0; + for (var polyIdx = 0; polyIdx < numRenderPolys; polyIdx++) + { + var poly = cell.Polys[polyIdx]; + polyVertices.Clear(); + polyVertices.EnsureCapacity(poly.VertexCount); + for (var i = 0; i < poly.VertexCount; i++) + { + polyVertices.Add(cell.Vertices[cell.Indices[cellIdxOffset + i]]); + } + + // We need to know what type of surface this poly is so we can map Embree primitive IDs to surface + // types + var renderPoly = cell.RenderPolys[polyIdx]; + var primType = SurfaceType.Solid; + if (renderPoly.TextureId == 249) + { + primType = SurfaceType.Sky; + } else if (polyIdx >= solidPolys) + { + primType = SurfaceType.Water; + } + + AddPolygon(polyVertices, primType); + cellIdxOffset += poly.VertexCount; + } + } + } + + public void AddObjectPolys( + BrList brushList, + ObjectHierarchy hierarchy, + ResourcePathManager.CampaignResources campaignResources) + { + var polyVertices = new List(); + foreach (var brush in brushList.Brushes) + { + if (brush.media != BrList.Brush.Media.Object) + { + continue; + } + + var id = (int)brush.brushInfo; + var modelNameProp = hierarchy.GetProperty(id, "P$ModelName"); + var scaleProp = hierarchy.GetProperty(id, "P$Scale"); + var renderTypeProp = hierarchy.GetProperty(id, "P$RenderTyp"); + var jointPosProp = hierarchy.GetProperty(id, "P$JointPos"); + var immobileProp = hierarchy.GetProperty(id, "P$Immobile"); + var staticShadowProp = hierarchy.GetProperty(id, "P$StatShad"); + + var joints = jointPosProp?.Positions ?? [0, 0, 0, 0, 0, 0]; + var castsShadows = (immobileProp?.value ?? false) || (staticShadowProp?.value ?? false); + var renderMode = renderTypeProp?.mode ?? PropRenderType.Mode.Normal; + + // TODO: Check which rendermodes cast shadows :) + if (modelNameProp == null || !castsShadows || renderMode == PropRenderType.Mode.CoronaOnly) + { + continue; + } + + // Let's try and place an object :) + var modelName = modelNameProp.value.ToLower() + ".bin"; + var modelPath = campaignResources.GetResourcePath(ResourceType.Object, modelName); + if (modelPath == null) + { + continue; + } + + // TODO: Handle failing to find model more gracefully + var pos = brush.position; + var rot = brush.angle; + var scale = scaleProp?.value ?? Vector3.One; + var model = new ModelFile(modelPath); + pos -= model.Header.Center; + + // for each object modify the vertices + // TODO: Almost perfect transform! + // TODO: Handle nested sub objects + foreach (var subObj in model.Objects) + { + var jointTrans = Matrix4x4.Identity; + if (subObj.Joint != -1) + { + var ang = float.DegreesToRadians(joints[subObj.Joint]); + var jointRot = Matrix4x4.CreateFromYawPitchRoll(0, ang, 0); + var objTrans = subObj.Transform; + jointTrans = jointRot * objTrans; + } + var scalePart = Matrix4x4.CreateScale(scale); + var rotPart = Matrix4x4.CreateFromYawPitchRoll(float.DegreesToRadians(rot.Y), float.DegreesToRadians(rot.X), + float.DegreesToRadians(rot.Z)); + var transPart = Matrix4x4.CreateTranslation(pos); + var transform = jointTrans * scalePart * rotPart * transPart; + + var start = subObj.PointIdx; + var end = start + subObj.PointCount; + for (var i = start; i < end; i++) + { + var v = model.Vertices[i]; + model.Vertices[i] = Vector3.Transform(v, transform); + } + } + + // for each polygon slam its vertices and indices :) + foreach (var poly in model.Polygons) + { + polyVertices.Clear(); + polyVertices.EnsureCapacity(poly.VertexCount); + foreach (var idx in poly.VertexIndices) + { + polyVertices.Add(model.Vertices[idx]); + } + + AddPolygon(polyVertices, SurfaceType.Solid); + } + } + } + + private void AddPolygon(List vertices, SurfaceType surfaceType) { var vertexCount = vertices.Count; var indexOffset = _vertices.Count;