Move more meshing to MeshBuilder
This commit is contained in:
parent
a0b287b9fa
commit
adf61c0f6f
|
@ -112,142 +112,18 @@ public class LightMapper
|
||||||
|
|
||||||
private Mesh BuildMesh()
|
private Mesh BuildMesh()
|
||||||
{
|
{
|
||||||
|
var meshBuilder = new MeshBuilder();
|
||||||
|
|
||||||
// TODO: Should this throw?
|
// TODO: Should this throw?
|
||||||
|
// TODO: Only do object polys if objcast lighting?
|
||||||
if (!_mission.TryGetChunk<WorldRep>("WREXT", out var worldRep) ||
|
if (!_mission.TryGetChunk<WorldRep>("WREXT", out var worldRep) ||
|
||||||
!_mission.TryGetChunk<BrList>("BRLIST", out var brList))
|
!_mission.TryGetChunk<BrList>("BRLIST", out var brList))
|
||||||
{
|
{
|
||||||
return new Mesh(0, [], [], []);
|
return meshBuilder.Build();
|
||||||
}
|
|
||||||
|
|
||||||
var meshBuilder = new MeshBuilder();
|
|
||||||
var polyVertices = new List<Vector3>();
|
|
||||||
|
|
||||||
// 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<PropLabel>(id, "P$ModelName");
|
|
||||||
var scaleProp = _hierarchy.GetProperty<PropVector>(id, "P$Scale");
|
|
||||||
var renderTypeProp = _hierarchy.GetProperty<PropRenderType>(id, "P$RenderTyp");
|
|
||||||
var jointPosProp = _hierarchy.GetProperty<PropJointPos>(id, "P$JointPos");
|
|
||||||
var immobileProp = _hierarchy.GetProperty<PropBool>(id, "P$Immobile");
|
|
||||||
var staticShadowProp = _hierarchy.GetProperty<PropBool>(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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
meshBuilder.AddWorldRepPolys(worldRep);
|
||||||
|
meshBuilder.AddObjectPolys(brList, _hierarchy, _campaign);
|
||||||
return meshBuilder.Build();
|
return meshBuilder.Build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
using KeepersCompound.LGS;
|
||||||
|
using KeepersCompound.LGS.Database;
|
||||||
|
using KeepersCompound.LGS.Database.Chunks;
|
||||||
|
|
||||||
namespace KeepersCompound.Lightmapper;
|
namespace KeepersCompound.Lightmapper;
|
||||||
|
|
||||||
|
@ -24,7 +27,141 @@ public class MeshBuilder
|
||||||
private readonly List<int> _indices = [];
|
private readonly List<int> _indices = [];
|
||||||
private readonly List<SurfaceType> _primSurfaceMap = [];
|
private readonly List<SurfaceType> _primSurfaceMap = [];
|
||||||
|
|
||||||
public void AddPolygon(List<Vector3> vertices, SurfaceType surfaceType)
|
public void AddWorldRepPolys(WorldRep worldRep)
|
||||||
|
{
|
||||||
|
var polyVertices = new List<Vector3>();
|
||||||
|
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<Vector3>();
|
||||||
|
foreach (var brush in brushList.Brushes)
|
||||||
|
{
|
||||||
|
if (brush.media != BrList.Brush.Media.Object)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var id = (int)brush.brushInfo;
|
||||||
|
var modelNameProp = hierarchy.GetProperty<PropLabel>(id, "P$ModelName");
|
||||||
|
var scaleProp = hierarchy.GetProperty<PropVector>(id, "P$Scale");
|
||||||
|
var renderTypeProp = hierarchy.GetProperty<PropRenderType>(id, "P$RenderTyp");
|
||||||
|
var jointPosProp = hierarchy.GetProperty<PropJointPos>(id, "P$JointPos");
|
||||||
|
var immobileProp = hierarchy.GetProperty<PropBool>(id, "P$Immobile");
|
||||||
|
var staticShadowProp = hierarchy.GetProperty<PropBool>(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<Vector3> vertices, SurfaceType surfaceType)
|
||||||
{
|
{
|
||||||
var vertexCount = vertices.Count;
|
var vertexCount = vertices.Count;
|
||||||
var indexOffset = _vertices.Count;
|
var indexOffset = _vertices.Count;
|
||||||
|
|
Loading…
Reference in New Issue