fix(physics): traverse prepared indoor portal topology
This commit is contained in:
parent
b12d94047c
commit
4d095be286
9 changed files with 400 additions and 5 deletions
|
|
@ -290,4 +290,88 @@ public class CameraCornerSealReplayTests
|
|||
"Viewer sweep through a verified-open doorway path was obstructed or cut short " +
|
||||
"(camera would wrongly pull in at openings) for: " + string.Join(", ", failures));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HoltburgCottageExit_ViewerSweep_AdvancesFromAlcoveToOutdoor()
|
||||
{
|
||||
var datDir = ConformanceDats.ResolveDatDir();
|
||||
if (datDir is null) return;
|
||||
|
||||
using var dats = new DatCollection(datDir, DatAccessType.Read);
|
||||
var graphCache = new PhysicsDataCache();
|
||||
var preparedCache = PhysicsDataCache.CreateProduction();
|
||||
for (uint low = 0x013Fu; low <= 0x0150u; low++)
|
||||
{
|
||||
uint cellId = ConformanceDats.HoltburgLandblock | low;
|
||||
ConformanceDats.LoadEnvCell(
|
||||
dats,
|
||||
graphCache,
|
||||
cellId);
|
||||
|
||||
CellPhysics graphCell = Assert.IsType<CellPhysics>(
|
||||
graphCache.GetCellStruct(cellId));
|
||||
FlatCellCollisionAsset prepared =
|
||||
FlatCollisionAssetBuilder.FlattenCell(graphCell);
|
||||
var datCell = Assert.IsType<DatReaderWriter.DBObjs.EnvCell>(
|
||||
dats.Get<DatReaderWriter.DBObjs.EnvCell>(cellId));
|
||||
preparedCache.CacheCellStruct(
|
||||
cellId,
|
||||
datCell,
|
||||
graphCell.WorldTransform,
|
||||
prepared.Structure,
|
||||
prepared.Topology);
|
||||
}
|
||||
|
||||
var graphEngine = new PhysicsEngine { DataCache = graphCache };
|
||||
var preparedEngine = new PhysicsEngine { DataCache = preparedCache };
|
||||
|
||||
var heights = new byte[81];
|
||||
var heightTable = new float[256];
|
||||
for (int i = 0; i < heightTable.Length; i++)
|
||||
heightTable[i] = -1000f;
|
||||
foreach (PhysicsEngine engine in new[] { graphEngine, preparedEngine })
|
||||
{
|
||||
engine.AddLandblock(
|
||||
ConformanceDats.HoltburgLandblock,
|
||||
new TerrainSurface(heights, heightTable),
|
||||
Array.Empty<CellSurface>(),
|
||||
Array.Empty<PortalPlane>(),
|
||||
0f,
|
||||
0f);
|
||||
}
|
||||
|
||||
// Connected capture indoor-visibility-20260726-220007. The player is
|
||||
// just inside the narrow 0x0150 vestibule, facing into the cottage.
|
||||
// Its chase camera is behind it, outside the open doorway. Retail's
|
||||
// viewer CTransition crosses 0x0150's 0xFFFF portal and carries the
|
||||
// outdoor landcell as viewer_cell.
|
||||
var player = new Vector3(132.70f, 16.80f, 94.00f);
|
||||
var pivot = player + new Vector3(0f, 0f, PivotHeight);
|
||||
var eye = new Vector3(131.30f, 19.97f, 96.25f);
|
||||
|
||||
var graphPivot = graphEngine.AdjustPosition(0xA9B40150u, pivot);
|
||||
var preparedPivot = preparedEngine.AdjustPosition(0xA9B40150u, pivot);
|
||||
Assert.True(graphPivot.found);
|
||||
Assert.True(preparedPivot.found);
|
||||
Assert.Equal(0xA9B40150u, graphPivot.cellId);
|
||||
Assert.Equal(graphPivot.cellId, preparedPivot.cellId);
|
||||
|
||||
ResolveResult graphResult = SweepViewer(
|
||||
graphEngine,
|
||||
pivot,
|
||||
eye,
|
||||
0xA9B40150u);
|
||||
ResolveResult preparedResult = SweepViewer(
|
||||
preparedEngine,
|
||||
pivot,
|
||||
eye,
|
||||
0xA9B40150u);
|
||||
|
||||
_out.WriteLine(FormattableString.Invariant(
|
||||
$"graph=0x{graphResult.CellId:X8} prepared=0x{preparedResult.CellId:X8} graphPos=({graphResult.Position.X:F3},{graphResult.Position.Y:F3},{graphResult.Position.Z:F3}) preparedPos=({preparedResult.Position.X:F3},{preparedResult.Position.Y:F3},{preparedResult.Position.Z:F3})"));
|
||||
|
||||
Assert.Equal(0xA9B40029u, graphResult.CellId);
|
||||
Assert.Equal(graphResult.CellId, preparedResult.CellId);
|
||||
Assert.Equal(graphResult.Position, preparedResult.Position);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue