feat(content): bake and read flat collision assets
Append strict collision/topology payloads to the existing prepared package so later physics cutover can drop parsed DAT graphs without adding a second mapping or changing traversal behavior. The full 2,232,170-key catalog is deterministic across worker counts, exact-byte aliased, corruption-isolated, and cancellation-safe.
This commit is contained in:
parent
d9300c7854
commit
9cd42417a8
29 changed files with 2868 additions and 63 deletions
|
|
@ -43,6 +43,24 @@ public sealed class FlatCollisionInstalledDatTests
|
|||
FlatCollisionAssetBuilder.FlattenCell(source);
|
||||
FlatCellCollisionAsset second =
|
||||
FlatCollisionAssetBuilder.FlattenCell(source);
|
||||
EnvCell datCell = Assert.IsType<EnvCell>(
|
||||
dats.Get<EnvCell>(cellId));
|
||||
var environment =
|
||||
Assert.IsType<DatReaderWriter.DBObjs.Environment>(
|
||||
dats.Get<DatReaderWriter.DBObjs.Environment>(
|
||||
0x0D00_0000u | datCell.EnvironmentId));
|
||||
Assert.True(
|
||||
environment.Cells.TryGetValue(
|
||||
datCell.CellStructure,
|
||||
out CellStruct? cellStruct));
|
||||
Assert.NotNull(cellStruct);
|
||||
FlatCellStructureCollisionAsset directStructure =
|
||||
FlatCollisionAssetBuilder.FlattenCellStructure(cellStruct!);
|
||||
FlatEnvCellTopology directTopology =
|
||||
FlatCollisionAssetBuilder.FlattenEnvCellTopology(
|
||||
cellId,
|
||||
datCell,
|
||||
directStructure.PortalPolygons);
|
||||
|
||||
AssertPhysicsSourceMatches(source.BSP?.Root, source.Resolved, first.Structure.PhysicsBsp);
|
||||
AssertContainmentSourceMatches(
|
||||
|
|
@ -60,6 +78,22 @@ public sealed class FlatCollisionInstalledDatTests
|
|||
Assert.Equal(
|
||||
first.Topology.VisibleCellIds.AsEnumerable(),
|
||||
second.Topology.VisibleCellIds.AsEnumerable());
|
||||
FlatCollisionAssetBuilderTests.AssertFlatPhysicsEqual(
|
||||
first.Structure.PhysicsBsp,
|
||||
directStructure.PhysicsBsp);
|
||||
Assert.Equal(
|
||||
first.Structure.ContainmentBsp.Nodes.AsEnumerable(),
|
||||
directStructure.ContainmentBsp.Nodes.AsEnumerable());
|
||||
AssertPolygonTableEqual(
|
||||
first.Structure.PortalPolygons,
|
||||
directStructure.PortalPolygons);
|
||||
Assert.Equal(
|
||||
first.Topology.Portals.AsEnumerable(),
|
||||
directTopology.Portals.AsEnumerable());
|
||||
Assert.Equal(
|
||||
first.Topology.VisibleCellIds.AsEnumerable(),
|
||||
directTopology.VisibleCellIds.AsEnumerable());
|
||||
Assert.Equal(first.Topology.SeenOutside, directTopology.SeenOutside);
|
||||
|
||||
_output.WriteLine(
|
||||
$"cell 0x{cellId:X8}: physicsNodes={first.Structure.PhysicsBsp.Nodes.Length}, " +
|
||||
|
|
@ -97,6 +131,8 @@ public sealed class FlatCollisionInstalledDatTests
|
|||
FlatCollisionAssetBuilder.FlattenGfxObj(
|
||||
source,
|
||||
cache.GetVisualBounds(gfxObjId));
|
||||
FlatGfxObjCollisionAsset direct =
|
||||
FlatCollisionAssetBuilder.FlattenGfxObj(gfxObj);
|
||||
|
||||
AssertPhysicsSourceMatches(
|
||||
source.BSP.Root,
|
||||
|
|
@ -107,6 +143,15 @@ public sealed class FlatCollisionInstalledDatTests
|
|||
AssertVisualBoundsBits(
|
||||
Assert.IsType<GfxObjVisualBounds>(cache.GetVisualBounds(gfxObjId)),
|
||||
flat.VisualBounds!.Value);
|
||||
FlatCollisionAssetBuilderTests.AssertFlatPhysicsEqual(
|
||||
flat.PhysicsBsp,
|
||||
direct.PhysicsBsp);
|
||||
AssertFlatNullableSphereBits(
|
||||
flat.BoundingSphere,
|
||||
direct.BoundingSphere);
|
||||
AssertFlatNullableVisualBoundsBits(
|
||||
flat.VisualBounds,
|
||||
direct.VisualBounds);
|
||||
|
||||
_output.WriteLine(
|
||||
$"gfx 0x{gfxObjId:X8}: nodes={flat.PhysicsBsp.Nodes.Length}, " +
|
||||
|
|
@ -127,7 +172,10 @@ public sealed class FlatCollisionInstalledDatTests
|
|||
|
||||
FlatSetupCollision flat =
|
||||
FlatCollisionAssetBuilder.FlattenSetup(source);
|
||||
FlatSetupCollision direct =
|
||||
FlatCollisionAssetBuilder.FlattenSetup(setup);
|
||||
AssertSetupSourceMatches(source, flat);
|
||||
AssertSetupFlatEqual(flat, direct);
|
||||
|
||||
_output.WriteLine(
|
||||
$"setup 0x{setupId:X8}: cylinders={flat.Cylinders.Length}, " +
|
||||
|
|
@ -327,4 +375,114 @@ public sealed class FlatCollisionInstalledDatTests
|
|||
source.HalfExtents,
|
||||
flat.HalfExtents);
|
||||
}
|
||||
|
||||
private static void AssertFlatNullableSphereBits(
|
||||
FlatCollisionSphere? expected,
|
||||
FlatCollisionSphere? actual)
|
||||
{
|
||||
Assert.Equal(expected.HasValue, actual.HasValue);
|
||||
if (!expected.HasValue || !actual.HasValue)
|
||||
return;
|
||||
FlatCollisionAssetBuilderTests.AssertVectorBits(
|
||||
expected.Value.Origin,
|
||||
actual.Value.Origin);
|
||||
FlatCollisionAssetBuilderTests.AssertFloatBits(
|
||||
expected.Value.Radius,
|
||||
actual.Value.Radius);
|
||||
}
|
||||
|
||||
private static void AssertFlatNullableVisualBoundsBits(
|
||||
FlatGfxObjVisualBounds? expected,
|
||||
FlatGfxObjVisualBounds? actual)
|
||||
{
|
||||
Assert.Equal(expected.HasValue, actual.HasValue);
|
||||
if (!expected.HasValue || !actual.HasValue)
|
||||
return;
|
||||
FlatCollisionAssetBuilderTests.AssertVectorBits(
|
||||
expected.Value.Min,
|
||||
actual.Value.Min);
|
||||
FlatCollisionAssetBuilderTests.AssertVectorBits(
|
||||
expected.Value.Max,
|
||||
actual.Value.Max);
|
||||
FlatCollisionAssetBuilderTests.AssertVectorBits(
|
||||
expected.Value.Center,
|
||||
actual.Value.Center);
|
||||
FlatCollisionAssetBuilderTests.AssertFloatBits(
|
||||
expected.Value.Radius,
|
||||
actual.Value.Radius);
|
||||
FlatCollisionAssetBuilderTests.AssertVectorBits(
|
||||
expected.Value.HalfExtents,
|
||||
actual.Value.HalfExtents);
|
||||
}
|
||||
|
||||
private static void AssertSetupFlatEqual(
|
||||
FlatSetupCollision expected,
|
||||
FlatSetupCollision actual)
|
||||
{
|
||||
Assert.Equal(expected.Cylinders.Length, actual.Cylinders.Length);
|
||||
Assert.Equal(expected.Spheres.Length, actual.Spheres.Length);
|
||||
for (int i = 0; i < expected.Cylinders.Length; i++)
|
||||
{
|
||||
FlatCollisionAssetBuilderTests.AssertVectorBits(
|
||||
expected.Cylinders[i].Origin,
|
||||
actual.Cylinders[i].Origin);
|
||||
FlatCollisionAssetBuilderTests.AssertFloatBits(
|
||||
expected.Cylinders[i].Radius,
|
||||
actual.Cylinders[i].Radius);
|
||||
FlatCollisionAssetBuilderTests.AssertFloatBits(
|
||||
expected.Cylinders[i].Height,
|
||||
actual.Cylinders[i].Height);
|
||||
}
|
||||
for (int i = 0; i < expected.Spheres.Length; i++)
|
||||
{
|
||||
FlatCollisionAssetBuilderTests.AssertVectorBits(
|
||||
expected.Spheres[i].Origin,
|
||||
actual.Spheres[i].Origin);
|
||||
FlatCollisionAssetBuilderTests.AssertFloatBits(
|
||||
expected.Spheres[i].Radius,
|
||||
actual.Spheres[i].Radius);
|
||||
}
|
||||
FlatCollisionAssetBuilderTests.AssertFloatBits(
|
||||
expected.Height,
|
||||
actual.Height);
|
||||
FlatCollisionAssetBuilderTests.AssertFloatBits(
|
||||
expected.Radius,
|
||||
actual.Radius);
|
||||
FlatCollisionAssetBuilderTests.AssertFloatBits(
|
||||
expected.StepUpHeight,
|
||||
actual.StepUpHeight);
|
||||
FlatCollisionAssetBuilderTests.AssertFloatBits(
|
||||
expected.StepDownHeight,
|
||||
actual.StepDownHeight);
|
||||
}
|
||||
|
||||
private static void AssertPolygonTableEqual(
|
||||
FlatPolygonTable expected,
|
||||
FlatPolygonTable actual)
|
||||
{
|
||||
Assert.Equal(expected.Polygons.Length, actual.Polygons.Length);
|
||||
Assert.Equal(expected.Vertices.Length, actual.Vertices.Length);
|
||||
for (int i = 0; i < expected.Polygons.Length; i++)
|
||||
{
|
||||
Assert.Equal(expected.Polygons[i].Id, actual.Polygons[i].Id);
|
||||
Assert.Equal(
|
||||
expected.Polygons[i].SidesType,
|
||||
actual.Polygons[i].SidesType);
|
||||
Assert.Equal(
|
||||
expected.Polygons[i].NumPoints,
|
||||
actual.Polygons[i].NumPoints);
|
||||
Assert.Equal(
|
||||
expected.Polygons[i].VertexRange,
|
||||
actual.Polygons[i].VertexRange);
|
||||
FlatCollisionAssetBuilderTests.AssertPlaneBits(
|
||||
expected.Polygons[i].Plane,
|
||||
actual.Polygons[i].Plane);
|
||||
}
|
||||
for (int i = 0; i < expected.Vertices.Length; i++)
|
||||
{
|
||||
FlatCollisionAssetBuilderTests.AssertVectorBits(
|
||||
expected.Vertices[i],
|
||||
actual.Vertices[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue