using System.Numerics; using AcDream.App.Rendering.Walk; namespace AcDream.App.Tests.Rendering.Walk; /// /// The FW1 conformance replay harness: reconstructs the camera state from a /// pose-stamped oracle frame and drives the ported walk over /// adapter-built world data. Convention notes (adjudicate against the /// fixtures, loudly, on any mismatch): /// /// The dumped quaternion is retail Frame storage order w,x,y,z /// (q0=w) — unit-norm verified on the captures. /// Retail's frame axes: +Y forward, +Z up (the camera looks along /// the rotated +Y). /// Pose origin is landblock-local, the same space the adapter's /// cell transforms produce. /// /// public sealed class WalkTraceReplayContext : IWalkFrameContext, IRetailFrameWalkContext { private sealed class BasisRayCaster( Vector3 right, Vector3 forward, Vector3 up, float halfWidth, float halfHeight, float focal) : IWalkRayCaster { public Vector3 RayThrough(float screenX, float screenY) { // Screen origin top-left, y down (the xformStart convention). float nx = (screenX - halfWidth) / halfWidth; float ny = (halfHeight - screenY) / halfHeight; return right * (nx / focal) + forward + up * (ny / focal); } } private readonly Dictionary _cells; private readonly Matrix4x4 _viewProjection; private readonly IWalkRayCaster _rays; public WalkTraceReplayContext( WalkOraclePose pose, Dictionary cells, float viewportWidth = 800f, float viewportHeight = 600f, float verticalFovRadians = 1.0f) { _cells = cells; WorldViewpoint = pose.Origin; var rotation = new Quaternion(pose.Q1, pose.Q2, pose.Q3, pose.Q0); Vector3 forward = Vector3.Transform(Vector3.UnitY, rotation); Vector3 up = Vector3.Transform(Vector3.UnitZ, rotation); Vector3 right = Vector3.Transform(Vector3.UnitX, rotation); Matrix4x4 view = Matrix4x4.CreateLookAt(pose.Origin, pose.Origin + forward, up); Matrix4x4 projection = Matrix4x4.CreatePerspectiveFieldOfView( verticalFovRadians, viewportWidth / viewportHeight, 0.1f, 5000f); _viewProjection = view * projection; ViewportWidth = viewportWidth; ViewportHeight = viewportHeight; float focal = MathF.Tan(verticalFovRadians / 2f); _rays = new BasisRayCaster( right, forward, up, viewportWidth / 2f, viewportHeight / 2f, focal); // The retail CY near plane: N = forward, d = −dot(eye, forward) − znear. CyPlane = new WalkPlane(forward, -Vector3.Dot(pose.Origin, forward) - 0.1f); } public Vector3 ViewpointIn(WalkCell cell) => Vector3.Transform(WorldViewpoint, cell.InverseWorldTransform); public Matrix4x4 ObjectToClip(WalkCell cell) => cell.WorldTransform * _viewProjection; public WalkCell? GetVisible(uint cellId) => _cells.GetValueOrDefault(cellId); public IWalkRayCaster Rays => _rays; public Vector3 WorldViewpoint { get; } public float ViewportWidth { get; } public float ViewportHeight { get; } public WalkPlane CyPlane { get; } public IWalkFrameContext CellContext => this; public void SetActiveView(WalkPortalView views, int index) { } public Vector3 ViewpointInBuilding(WalkBuilding building) => WorldViewpoint; public int ClipBuildingPolygon( WalkBuilding building, WalkPolygon polygon, int side, Span output) => 0; // building look-ins join the conformance surface with the landscape fixtures // ---- signatures for comparing walk output to oracle frames ---- public static string Signature(IEnumerable events) => string.Join("|", events.Select(e => e.Kind switch { WalkEventKind.Landscape => "LS", WalkEventKind.Building => $"BLD:{e.CellId:x8}", WalkEventKind.DrawInside => $"DI:{e.CellId:x8}", WalkEventKind.DrawCells => $"DC:ov={e.OutsideViewCount}:{string.Join(',', e.Cells.Select(c => c.ToString("x8")))}", _ => "?", })); public static string Signature(WalkOracleFrame frame) => string.Join("|", frame.Events.Select(e => e.Kind switch { WalkOracleEventKind.Landscape => "LS", WalkOracleEventKind.Building => $"BLD:{e.CellId!.Value:x8}", WalkOracleEventKind.DrawInside => $"DI:{e.CellId!.Value:x8}", WalkOracleEventKind.DrawCells => $"DC:ov={e.OutsideViewCount}:{string.Join(',', e.Cells.Select(c => c.ToString("x8")))}", _ => "?", })); }