Compare commits
11 Commits
477eb692c5
...
e64448f7e8
Author | SHA1 | Date |
---|---|---|
|
e64448f7e8 | |
|
8ae23eafb6 | |
|
007b4f8f1c | |
|
cae43f12ad | |
|
c28626bf20 | |
|
223aee980e | |
|
3f6ed89667 | |
|
62f2886eb4 | |
|
c97cf31ccb | |
|
b0e4c8dff3 | |
|
6a7ee922b5 |
|
@ -16,7 +16,7 @@
|
||||||
<PackageReference Include="Serilog" Version="4.2.0" />
|
<PackageReference Include="Serilog" Version="4.2.0" />
|
||||||
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
|
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
|
||||||
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
|
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
|
||||||
<PackageReference Include="TinyEmbree" Version="1.1.0" />
|
<PackageReference Include="TinyEmbree" Version="1.1.0.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -34,6 +34,7 @@ public class LightMapper
|
||||||
private DbFile _mission;
|
private DbFile _mission;
|
||||||
private ObjectHierarchy _hierarchy;
|
private ObjectHierarchy _hierarchy;
|
||||||
private Raytracer _scene;
|
private Raytracer _scene;
|
||||||
|
private Raytracer _sceneNoObj;
|
||||||
private List<Light> _lights;
|
private List<Light> _lights;
|
||||||
private SurfaceType[] _triangleTypeMap;
|
private SurfaceType[] _triangleTypeMap;
|
||||||
|
|
||||||
|
@ -56,12 +57,19 @@ public class LightMapper
|
||||||
|
|
||||||
VerifyRequiredChunksExist();
|
VerifyRequiredChunksExist();
|
||||||
|
|
||||||
var mesh = Timing.TimeStage("Build Mesh", BuildMesh);
|
var (noObjMesh, fullMesh) = Timing.TimeStage("Build Meshes", BuildMeshes);
|
||||||
_triangleTypeMap = mesh.TriangleSurfaceMap;
|
_triangleTypeMap = fullMesh.TriangleSurfaceMap;
|
||||||
|
_sceneNoObj = Timing.TimeStage("Build RT NoObj Scene", () =>
|
||||||
|
{
|
||||||
|
var rt = new Raytracer();
|
||||||
|
rt.AddMesh(new TriangleMesh(noObjMesh.Vertices, noObjMesh.Indices));
|
||||||
|
rt.CommitScene();
|
||||||
|
return rt;
|
||||||
|
});
|
||||||
_scene = Timing.TimeStage("Build RT Scene", () =>
|
_scene = Timing.TimeStage("Build RT Scene", () =>
|
||||||
{
|
{
|
||||||
var rt = new Raytracer();
|
var rt = new Raytracer();
|
||||||
rt.AddMesh(new TriangleMesh(mesh.Vertices, mesh.Indices));
|
rt.AddMesh(new TriangleMesh(fullMesh.Vertices, fullMesh.Indices));
|
||||||
rt.CommitScene();
|
rt.CommitScene();
|
||||||
return rt;
|
return rt;
|
||||||
});
|
});
|
||||||
|
@ -180,7 +188,7 @@ public class LightMapper
|
||||||
return new ObjectHierarchy(_mission);
|
return new ObjectHierarchy(_mission);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Mesh BuildMesh()
|
private (Mesh, Mesh) BuildMeshes()
|
||||||
{
|
{
|
||||||
var meshBuilder = new MeshBuilder();
|
var meshBuilder = new MeshBuilder();
|
||||||
|
|
||||||
|
@ -189,12 +197,16 @@ public class LightMapper
|
||||||
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 meshBuilder.Build();
|
return (meshBuilder.Build(), meshBuilder.Build());
|
||||||
}
|
}
|
||||||
|
|
||||||
meshBuilder.AddWorldRepPolys(worldRep);
|
meshBuilder.AddWorldRepPolys(worldRep);
|
||||||
|
var noObjMesh = meshBuilder.Build();
|
||||||
|
|
||||||
meshBuilder.AddObjectPolys(brList, _hierarchy, _campaign);
|
meshBuilder.AddObjectPolys(brList, _hierarchy, _campaign);
|
||||||
return meshBuilder.Build();
|
var fullMesh = meshBuilder.Build();
|
||||||
|
|
||||||
|
return (noObjMesh, fullMesh);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BuildLightList()
|
private void BuildLightList()
|
||||||
|
@ -730,7 +742,7 @@ public class LightMapper
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!TraceOcclusion(light.Position, point))
|
if (!TraceOcclusion(_scene, light.Position, point))
|
||||||
{
|
{
|
||||||
strength += targetWeights[idx] * light.StrengthAtPoint(point, plane, settings.AnimLightCutoff);
|
strength += targetWeights[idx] * light.StrengthAtPoint(point, plane, settings.AnimLightCutoff);
|
||||||
}
|
}
|
||||||
|
@ -812,11 +824,23 @@ public class LightMapper
|
||||||
MathUtils.PlanePointMapper planeMapper,
|
MathUtils.PlanePointMapper planeMapper,
|
||||||
Vector2[] v2ds)
|
Vector2[] v2ds)
|
||||||
{
|
{
|
||||||
|
polyCenter += planeMapper.Normal * 0.25f;
|
||||||
|
|
||||||
|
// All of the traces here are done using the no object scene. We just want to find a point in-world, we don't
|
||||||
|
// care about if an object is in the way
|
||||||
var tracePoints = new Vector3[offsets.Length];
|
var tracePoints = new Vector3[offsets.Length];
|
||||||
for (var i = 0; i < offsets.Length; i++)
|
for (var i = 0; i < offsets.Length; i++)
|
||||||
{
|
{
|
||||||
var offset = offsets[i];
|
var offset = offsets[i];
|
||||||
var pos = basePosition + offset;
|
var pos = basePosition + offset + planeMapper.Normal * MathUtils.Epsilon;
|
||||||
|
|
||||||
|
// If the target lightmap point is in view of the center
|
||||||
|
// then we can use it as-is. Using it straight fixes seams and such.
|
||||||
|
if (!TraceOcclusion(_sceneNoObj, polyCenter, pos))
|
||||||
|
{
|
||||||
|
tracePoints[i] = pos;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// If we can't see our target point from the center of the poly
|
// If we can't see our target point from the center of the poly
|
||||||
// then we need to clip the point to slightly inside the poly
|
// then we need to clip the point to slightly inside the poly
|
||||||
|
@ -825,12 +849,24 @@ public class LightMapper
|
||||||
// the polygon but is partially contained in the polygon
|
// the polygon but is partially contained in the polygon
|
||||||
// 2. Darkened spots from linear filtering of points outside the
|
// 2. Darkened spots from linear filtering of points outside the
|
||||||
// polygon which have missed
|
// polygon which have missed
|
||||||
var occluded = TraceOcclusion(polyCenter + planeMapper.Normal * 0.25f, pos);
|
|
||||||
if (occluded)
|
|
||||||
{
|
|
||||||
var p2d = planeMapper.MapTo2d(pos);
|
var p2d = planeMapper.MapTo2d(pos);
|
||||||
p2d = MathUtils.ClipPointToPoly2d(p2d, v2ds);
|
p2d = MathUtils.ClipPointToPoly2d(p2d, v2ds);
|
||||||
pos = planeMapper.MapTo3d(p2d);
|
pos = planeMapper.MapTo3d(p2d);
|
||||||
|
pos += planeMapper.Normal * MathUtils.Epsilon;
|
||||||
|
|
||||||
|
// If the clipping fails, just say screw it and cast :(
|
||||||
|
if (TraceOcclusion(_sceneNoObj, polyCenter, pos))
|
||||||
|
{
|
||||||
|
var hitResult = _sceneNoObj.Trace(new Ray
|
||||||
|
{
|
||||||
|
Origin = polyCenter,
|
||||||
|
Direction = Vector3.Normalize(pos - polyCenter),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (hitResult)
|
||||||
|
{
|
||||||
|
pos = hitResult.Position;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tracePoints[i] = pos;
|
tracePoints[i] = pos;
|
||||||
|
@ -839,7 +875,7 @@ public class LightMapper
|
||||||
return tracePoints;
|
return tracePoints;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool TraceOcclusion(Vector3 origin, Vector3 target)
|
private static bool TraceOcclusion(Raytracer scene, Vector3 origin, Vector3 target, float epsilon = MathUtils.Epsilon)
|
||||||
{
|
{
|
||||||
var direction = target - origin;
|
var direction = target - origin;
|
||||||
var ray = new Ray
|
var ray = new Ray
|
||||||
|
@ -849,7 +885,7 @@ public class LightMapper
|
||||||
};
|
};
|
||||||
|
|
||||||
// Epsilon is used here to avoid occlusion when origin lies exactly on a poly
|
// Epsilon is used here to avoid occlusion when origin lies exactly on a poly
|
||||||
return _scene.IsOccluded(new ShadowRay(ray, direction.Length() - MathUtils.Epsilon));
|
return scene.IsOccluded(new ShadowRay(ray, direction.Length() - epsilon));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: direction should already be normalised here
|
// TODO: direction should already be normalised here
|
||||||
|
|
|
@ -11,7 +11,7 @@ public enum SurfaceType
|
||||||
{
|
{
|
||||||
Solid,
|
Solid,
|
||||||
Sky,
|
Sky,
|
||||||
Water,
|
Object,
|
||||||
Air,
|
Air,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,7 +144,7 @@ public class MeshBuilder
|
||||||
polyVertices.Add(vertex);
|
polyVertices.Add(vertex);
|
||||||
}
|
}
|
||||||
|
|
||||||
AddPolygon(polyVertices, SurfaceType.Solid);
|
AddPolygon(polyVertices, SurfaceType.Object);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -155,12 +155,13 @@ public class MeshBuilder
|
||||||
var indexOffset = _vertices.Count;
|
var indexOffset = _vertices.Count;
|
||||||
|
|
||||||
// Polygons are n-sided, but fortunately they're convex so we can just do a fan triangulation
|
// Polygons are n-sided, but fortunately they're convex so we can just do a fan triangulation
|
||||||
|
// Embree triangle winding order is reverse of LGS winding order, so we go (0, i+1, i) instead of (0, i+1, i)
|
||||||
_vertices.AddRange(vertices);
|
_vertices.AddRange(vertices);
|
||||||
for (var i = 1; i < vertexCount - 1; i++)
|
for (var i = 1; i < vertexCount - 1; i++)
|
||||||
{
|
{
|
||||||
_indices.Add(indexOffset);
|
_indices.Add(indexOffset);
|
||||||
_indices.Add(indexOffset + i);
|
|
||||||
_indices.Add(indexOffset + i + 1);
|
_indices.Add(indexOffset + i + 1);
|
||||||
|
_indices.Add(indexOffset + i);
|
||||||
_primSurfaceMap.Add(surfaceType);
|
_primSurfaceMap.Add(surfaceType);
|
||||||
_triangleCount++;
|
_triangleCount++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,10 +5,18 @@ namespace KeepersCompound.Lightmapper;
|
||||||
|
|
||||||
public class PotentiallyVisibleSet
|
public class PotentiallyVisibleSet
|
||||||
{
|
{
|
||||||
private struct Edge
|
private struct Node(List<int> edgeIndices)
|
||||||
{
|
{
|
||||||
public int Destination;
|
public bool VisibilityComputed = false;
|
||||||
public Poly Poly;
|
public HashSet<int> VisibleNodes = [];
|
||||||
|
public readonly List<int> EdgeIndices = edgeIndices;
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly struct Edge(int destination, Poly poly)
|
||||||
|
{
|
||||||
|
public readonly HashSet<int> MightSee = [];
|
||||||
|
public readonly int Destination = destination;
|
||||||
|
public readonly Poly Poly = poly;
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
|
@ -44,9 +52,8 @@ public class PotentiallyVisibleSet
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly List<int>[] _portalGraph;
|
private readonly Node[] _graph;
|
||||||
private readonly List<Edge> _edges;
|
private readonly List<Edge> _edges;
|
||||||
private readonly Dictionary<int, HashSet<int>> _visibilitySet;
|
|
||||||
|
|
||||||
private const float Epsilon = 0.1f;
|
private const float Epsilon = 0.1f;
|
||||||
|
|
||||||
|
@ -68,19 +75,19 @@ public class PotentiallyVisibleSet
|
||||||
|
|
||||||
public PotentiallyVisibleSet(WorldRep.Cell[] cells)
|
public PotentiallyVisibleSet(WorldRep.Cell[] cells)
|
||||||
{
|
{
|
||||||
|
_graph = new Node[cells.Length];
|
||||||
_edges = [];
|
_edges = [];
|
||||||
_visibilitySet = new Dictionary<int, HashSet<int>>();
|
|
||||||
|
|
||||||
_portalGraph = new List<int>[cells.Length];
|
|
||||||
for (var i = 0; i < cells.Length; i++)
|
for (var i = 0; i < cells.Length; i++)
|
||||||
{
|
{
|
||||||
_portalGraph[i] = [];
|
|
||||||
var cell = cells[i];
|
var cell = cells[i];
|
||||||
|
var edgeIndices = new List<int>(cell.PortalPolyCount);
|
||||||
|
|
||||||
// If a cell is "blocks vision" flagged, we can never see out of it
|
// If a cell is "blocks vision" flagged, we can never see out of it
|
||||||
// We can see into it though, so we still want the edges coming in
|
// We can see into it though, so we still want the edges coming in
|
||||||
if ((cell.Flags & 8) != 0)
|
if ((cell.Flags & 8) != 0)
|
||||||
{
|
{
|
||||||
|
_graph[i] = new Node(edgeIndices);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,8 +103,6 @@ public class PotentiallyVisibleSet
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var other = poly.Destination;
|
|
||||||
|
|
||||||
// Checking if there's already an edge is super slow. It's much faster to just add a new edge, even with
|
// Checking if there's already an edge is super slow. It's much faster to just add a new edge, even with
|
||||||
// the duplicated poly
|
// the duplicated poly
|
||||||
var vs = new List<Vector3>(poly.VertexCount);
|
var vs = new List<Vector3>(poly.VertexCount);
|
||||||
|
@ -106,33 +111,96 @@ public class PotentiallyVisibleSet
|
||||||
vs.Add(cell.Vertices[cell.Indices[indicesOffset + vIdx]]);
|
vs.Add(cell.Vertices[cell.Indices[indicesOffset + vIdx]]);
|
||||||
}
|
}
|
||||||
|
|
||||||
var edge = new Edge
|
var edge = new Edge(poly.Destination, new Poly(vs, cell.Planes[poly.PlaneId]));
|
||||||
{
|
edgeIndices.Add(_edges.Count);
|
||||||
Destination = other,
|
|
||||||
Poly = new Poly(vs, cell.Planes[poly.PlaneId]),
|
|
||||||
};
|
|
||||||
_edges.Add(edge);
|
_edges.Add(edge);
|
||||||
_portalGraph[i].Add(_edges.Count - 1);
|
|
||||||
indicesOffset += poly.VertexCount;
|
indicesOffset += poly.VertexCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_graph[i] = new Node(edgeIndices);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Parallel.ForEach(_edges, ComputeEdgeMightSee);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int[] GetVisible(int cellIdx)
|
public int[] GetVisible(int cellIdx)
|
||||||
{
|
{
|
||||||
if (_visibilitySet.TryGetValue(cellIdx, out var value))
|
// TODO: Handle out of range indices
|
||||||
|
var node = _graph[cellIdx];
|
||||||
|
if (node.VisibilityComputed)
|
||||||
{
|
{
|
||||||
return [..value];
|
return [..node.VisibleNodes];
|
||||||
}
|
}
|
||||||
|
|
||||||
var visibleCells = ComputeVisibility(cellIdx);
|
var visibleCells = ComputeVisibility(cellIdx);
|
||||||
_visibilitySet.Add(cellIdx, visibleCells);
|
node.VisibilityComputed = true;
|
||||||
|
node.VisibleNodes = visibleCells;
|
||||||
|
_graph[cellIdx] = node;
|
||||||
return [..visibleCells];
|
return [..visibleCells];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ComputeEdgeMightSee(Edge source)
|
||||||
|
{
|
||||||
|
var sourcePlane = source.Poly.Plane;
|
||||||
|
|
||||||
|
var unexploredCells = new Stack<int>();
|
||||||
|
unexploredCells.Push(source.Destination);
|
||||||
|
while (unexploredCells.Count > 0)
|
||||||
|
{
|
||||||
|
var cellIdx = unexploredCells.Pop();
|
||||||
|
|
||||||
|
if (!source.MightSee.Add(cellIdx))
|
||||||
|
{
|
||||||
|
continue; // target is already explored
|
||||||
|
}
|
||||||
|
|
||||||
|
// Target must be partly behind source, source must be partly in front of target, and source and target cannot face each other
|
||||||
|
foreach (var targetEdgeIdx in _graph[cellIdx].EdgeIndices)
|
||||||
|
{
|
||||||
|
var target = _edges[targetEdgeIdx];
|
||||||
|
var targetPlane = target.Poly.Plane;
|
||||||
|
|
||||||
|
var validTarget = false;
|
||||||
|
foreach (var v in target.Poly.Vertices)
|
||||||
|
{
|
||||||
|
if (MathUtils.DistanceFromPlane(sourcePlane, v) < -MathUtils.Epsilon)
|
||||||
|
{
|
||||||
|
validTarget = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!validTarget)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
validTarget = false;
|
||||||
|
foreach (var v in source.Poly.Vertices)
|
||||||
|
{
|
||||||
|
if (MathUtils.DistanceFromPlane(targetPlane, v) > MathUtils.Epsilon)
|
||||||
|
{
|
||||||
|
validTarget = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!validTarget)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Vector3.Dot(sourcePlane.Normal, targetPlane.Normal) > MathUtils.Epsilon - 1)
|
||||||
|
{
|
||||||
|
unexploredCells.Push(target.Destination);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private HashSet<int> ComputeVisibility(int cellIdx)
|
private HashSet<int> ComputeVisibility(int cellIdx)
|
||||||
{
|
{
|
||||||
if (cellIdx >= _portalGraph.Length)
|
if (cellIdx >= _graph.Length)
|
||||||
{
|
{
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
@ -141,86 +209,102 @@ public class PotentiallyVisibleSet
|
||||||
var visible = new HashSet<int>();
|
var visible = new HashSet<int>();
|
||||||
visible.Add(cellIdx);
|
visible.Add(cellIdx);
|
||||||
|
|
||||||
// Additionally a cell can always see it's direct neighbours (obviously)
|
foreach (var edgeIdx in _graph[cellIdx].EdgeIndices)
|
||||||
foreach (var edgeIndex in _portalGraph[cellIdx])
|
|
||||||
{
|
{
|
||||||
var edge = _edges[edgeIndex];
|
var edge = _edges[edgeIdx];
|
||||||
var neighbourIdx = edge.Destination;
|
foreach (var mightSee in edge.MightSee)
|
||||||
visible.Add(neighbourIdx);
|
|
||||||
|
|
||||||
// Neighbours of our direct neighbour are always visible, unless they're coplanar
|
|
||||||
foreach (var innerEdgeIndex in _portalGraph[neighbourIdx])
|
|
||||||
{
|
{
|
||||||
var innerEdge = _edges[innerEdgeIndex];
|
visible.Add(mightSee);
|
||||||
if (innerEdge.Destination == cellIdx || edge.Poly.IsCoplanar(innerEdge.Poly))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
ExplorePortalRecursive(visible, edge.Poly, new Poly(innerEdge.Poly), neighbourIdx, innerEdge.Destination, 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return visible;
|
return visible;
|
||||||
|
|
||||||
|
// if (cellIdx >= _portalGraph.Length)
|
||||||
|
// {
|
||||||
|
// return [];
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Additionally a cell can always see it's direct neighbours (obviously)
|
||||||
|
// foreach (var edgeIndex in _portalGraph[cellIdx])
|
||||||
|
// {
|
||||||
|
// var edge = _edges[edgeIndex];
|
||||||
|
// var neighbourIdx = edge.Destination;
|
||||||
|
// visible.Add(neighbourIdx);
|
||||||
|
//
|
||||||
|
// // Neighbours of our direct neighbour are always visible, unless they're coplanar
|
||||||
|
// foreach (var innerEdgeIndex in _portalGraph[neighbourIdx])
|
||||||
|
// {
|
||||||
|
// var innerEdge = _edges[innerEdgeIndex];
|
||||||
|
// if (innerEdge.Destination == cellIdx || edge.Poly.IsCoplanar(innerEdge.Poly))
|
||||||
|
// {
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// ExplorePortalRecursive(visible, edge.Poly, new Poly(innerEdge.Poly), neighbourIdx, innerEdge.Destination, 0);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ExplorePortalRecursive(
|
// private void ExplorePortalRecursive(
|
||||||
HashSet<int> visible,
|
// HashSet<int> visible,
|
||||||
Poly sourcePoly,
|
// Poly sourcePoly,
|
||||||
Poly previousPoly,
|
// Poly previousPoly,
|
||||||
int previousCellIdx,
|
// int previousCellIdx,
|
||||||
int currentCellIdx,
|
// int currentCellIdx,
|
||||||
int depth)
|
// int depth)
|
||||||
{
|
// {
|
||||||
// TODO: Might need to lose this
|
// // TODO: Might need to lose this
|
||||||
if (depth > 1024)
|
// if (depth > 1024)
|
||||||
{
|
// {
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
visible.Add(currentCellIdx);
|
// visible.Add(currentCellIdx);
|
||||||
|
//
|
||||||
// Only one edge out of the cell means we'd be going back on ourselves
|
// // Only one edge out of the cell means we'd be going back on ourselves
|
||||||
if (_portalGraph[currentCellIdx].Count <= 1)
|
// if (_portalGraph[currentCellIdx].Count <= 1)
|
||||||
{
|
// {
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
// TODO: If all neighbours are already in `visible` skip exploring?
|
// // TODO: If all neighbours are already in `visible` skip exploring?
|
||||||
|
//
|
||||||
var separators = new List<Plane>();
|
// var separators = new List<Plane>();
|
||||||
GetSeparatingPlanes(separators, sourcePoly, previousPoly, false);
|
// GetSeparatingPlanes(separators, sourcePoly, previousPoly, false);
|
||||||
GetSeparatingPlanes(separators, previousPoly, sourcePoly, true);
|
// GetSeparatingPlanes(separators, previousPoly, sourcePoly, true);
|
||||||
|
//
|
||||||
// The case for this occuring is... interesting ( idk )
|
// // The case for this occuring is... interesting ( idk )
|
||||||
if (separators.Count == 0)
|
// if (separators.Count == 0)
|
||||||
{
|
// {
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
// Clip all new polys and recurse
|
// // Clip all new polys and recurse
|
||||||
foreach (var edgeIndex in _portalGraph[currentCellIdx])
|
// foreach (var edgeIndex in _portalGraph[currentCellIdx])
|
||||||
{
|
// {
|
||||||
var edge = _edges[edgeIndex];
|
// var edge = _edges[edgeIndex];
|
||||||
if (edge.Destination == previousCellIdx || previousPoly.IsCoplanar(edge.Poly) || sourcePoly.IsCoplanar(edge.Poly))
|
// if (edge.Destination == previousCellIdx || previousPoly.IsCoplanar(edge.Poly) || sourcePoly.IsCoplanar(edge.Poly))
|
||||||
{
|
// {
|
||||||
continue;
|
// continue;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
var poly = new Poly(edge.Poly);
|
// var poly = new Poly(edge.Poly);
|
||||||
foreach (var separator in separators)
|
// foreach (var separator in separators)
|
||||||
{
|
// {
|
||||||
ClipPolygonByPlane(ref poly, separator);
|
// ClipPolygonByPlane(ref poly, separator);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
if (poly.Vertices.Count == 0)
|
// if (poly.Vertices.Count == 0)
|
||||||
{
|
// {
|
||||||
continue;
|
// continue;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
ExplorePortalRecursive(visible, sourcePoly, poly, currentCellIdx, edge.Destination, depth + 1);
|
// ExplorePortalRecursive(visible, sourcePoly, poly, currentCellIdx, edge.Destination, depth + 1);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
// TODO: We're getting multiple separating planes that are the same, let's not somehow?
|
// TODO: We're getting multiple separating planes that are the same, let's not somehow?
|
||||||
private static void GetSeparatingPlanes(List<Plane> separators, Poly p0, Poly p1, bool flip)
|
private static void GetSeparatingPlanes(List<Plane> separators, Poly p0, Poly p1, bool flip)
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
<configuration>
|
||||||
|
<packageSources>
|
||||||
|
<add key="KeepersCompound.Lightmapper Local" value="./Packages" />
|
||||||
|
</packageSources>
|
||||||
|
</configuration>
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"version": 2,
|
||||||
|
"contentHash": "Uhc3bpe44l6oPT7XPAWg8MBJRZc4iZP8nZpaAM3+35tvwLxjspcuBIMzFatr124Zfm71HQxDf+K1o5Tic/FQYw==",
|
||||||
|
"source": null
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
Uhc3bpe44l6oPT7XPAWg8MBJRZc4iZP8nZpaAM3+35tvwLxjspcuBIMzFatr124Zfm71HQxDf+K1o5Tic/FQYw==
|
|
@ -0,0 +1,18 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
|
||||||
|
<metadata>
|
||||||
|
<id>TinyEmbree</id>
|
||||||
|
<version>1.1.0.1</version>
|
||||||
|
<title>TinyEmbree</title>
|
||||||
|
<authors>Pascal Grittmann</authors>
|
||||||
|
<license type="file">LICENSE</license>
|
||||||
|
<licenseUrl>https://aka.ms/deprecateLicenseUrl</licenseUrl>
|
||||||
|
<description>A very simple C# wrapper around the Embree ray tracing kernels.</description>
|
||||||
|
<copyright>(c) Pascal Grittmann</copyright>
|
||||||
|
<tags>ray tracing Embree</tags>
|
||||||
|
<repository type="git" url="https://github.com/pgrit/TinyEmbree" commit="66e46513777d3046b684f4d6fe796e9f3558b6b0" />
|
||||||
|
<dependencies>
|
||||||
|
<group targetFramework="net9.0" />
|
||||||
|
</dependencies>
|
||||||
|
</metadata>
|
||||||
|
</package>
|
Loading…
Reference in New Issue