perf(physics): cut production traversal to flat assets

Make prepared flat BSP data authoritative for gameplay while retaining the parsed graph only as an exact sampled referee. Fail production publication when collision package data is genuinely absent, keep idempotent already-cached publication valid, and move cell membership, floor lookup, camera diagnostics, and live/static shape bounds onto the flat representation.

Validated by 8,402 Release tests, a strict dense-Arwic connected gate with 46,309/46,309 exact referee matches, and graceful shutdown.

Co-authored-by: Codex <codex@openai.com>
This commit is contained in:
Erik 2026-07-25 17:00:04 +02:00
parent d9446030e6
commit 068a06518d
13 changed files with 743 additions and 43 deletions

View file

@ -509,6 +509,39 @@ public sealed class PhysicsEngine
float? best = null;
float bestDist = float.MaxValue;
FlatPhysicsBsp? flat = cp.FlatPhysicsBsp;
if (flat is not null)
{
FlatPolygonTable table = flat.PolygonTable;
for (int i = 0; i < table.Polygons.Length; i++)
{
FlatCollisionPolygon poly = table.Polygons[i];
Vector3 n = poly.Plane.Normal;
if (n.Z < PhysicsGlobals.FloorZ) continue;
if (!PointInPolygonXY(table, poly.VertexRange, local.X, local.Y))
continue;
float lz =
-(n.X * local.X + n.Y * local.Y + poly.Plane.D) / n.Z;
float wz = Vector3.Transform(
new Vector3(local.X, local.Y, lz),
cp.WorldTransform).Z;
float dist = MathF.Abs(wz - referenceZ);
if (dist < bestDist)
{
bestDist = dist;
best = wz;
}
}
return best;
}
if (DataCache!.CollisionTraversalMode == CollisionTraversalMode.Flat)
{
throw new InvalidOperationException(
$"Production CellStruct 0x{cellId:X8} has no prepared physics BSP.");
}
// Explicit graph-oracle fixture path. Production returns above.
foreach (var kv in cp.Resolved)
{
var poly = kv.Value;
@ -524,6 +557,28 @@ public sealed class PhysicsEngine
return best;
}
private static bool PointInPolygonXY(
FlatPolygonTable table,
FlatIndexRange range,
float x,
float y)
{
bool inside = false;
int end = range.EndExclusive;
for (int i = range.Start, j = end - 1; i < end; j = i++)
{
Vector3 vi = table.Vertices[i];
Vector3 vj = table.Vertices[j];
if ((vi.Y > y) != (vj.Y > y)
&& x < (vj.X - vi.X) * (y - vi.Y) /
(vj.Y - vi.Y) + vi.X)
{
inside = !inside;
}
}
return inside;
}
/// <summary>Even-odd XY-projection point-in-polygon test (cell-local frame).</summary>
private static bool PointInPolygonXY(IReadOnlyList<Vector3> verts, float x, float y)
{