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 { // Retail projection globals, dumped live from the capture client // (recon 2026-08-30 evening: Render::bw/bh/xinvscale/yinvscale/tx/ty/vdst). public const float RetailViewportWidth = 1024f; public const float RetailViewportHeight = 720f; public const float RetailXInvScale = 0.00025f; public const float RetailYInvScale = 0.00025f; public const float RetailTx = 0.127875f; public const float RetailTy = 0.089875f; public const float RetailVdst = 0.1330766976f; private sealed class RetailRayCaster( Vector3 right, Vector3 forward, Vector3 up) : IWalkRayCaster { // Retail's unproject (copy_view's ray path; equal to // ScreenToViewTransform for these globals): // u = sx·xinvscale − tx; w = sy·yinvscale − ty // ray = Xaxis·u + Yaxis·vdst − Zaxis·w public Vector3 RayThrough(float screenX, float screenY) { float u = screenX * RetailXInvScale - RetailTx; float w = screenY * RetailYInvScale - RetailTy; return right * u + forward * RetailVdst - up * w; } } private readonly Dictionary _cells; private readonly Matrix4x4 _viewProjection; private readonly IWalkRayCaster _rays; public WalkTraceReplayContext(WalkOraclePose pose, Dictionary cells) { _cells = cells; WorldViewpoint = pose.Origin; var rotation = new Quaternion(pose.Q1, pose.Q2, pose.Q3, pose.Q0); // Basis convention RE-pinned 2026-08-30 (second pass): storage // w,x,y,z; forward = rotated +Y — the retail Frame convention. The // motion sweep briefly favored +X, but the walkabout camera was // mouse-turned off the run direction; the terrace-edge fixture's // EXTERNAL ground truth (the ledge faces the F518 vista, east) // decodes east ONLY under +Y-forward, and +Y makes the street // fixture's punch on/off-screen pattern match retail 4-for-4. Vector3 forward = Vector3.Transform(Vector3.UnitY, rotation); Vector3 up = Vector3.Transform(Vector3.UnitZ, rotation); Vector3 right = Vector3.Transform(Vector3.UnitX, rotation); // The exact retail frustum: tan(halfFovY) = ty/vdst, aspect = tx/ty. float fovY = 2f * MathF.Atan(RetailTy / RetailVdst); Matrix4x4 view = Matrix4x4.CreateLookAt(pose.Origin, pose.Origin + forward, up); Matrix4x4 projection = Matrix4x4.CreatePerspectiveFieldOfView( fovY, RetailTx / RetailTy, 0.1f, 5000f); _viewProjection = view * projection; ViewportWidth = RetailViewportWidth; ViewportHeight = RetailViewportHeight; _rays = new RetailRayCaster(right, forward, up); // The retail CY near plane: N = forward, d = −dot(eye, forward) − znear. CyPlane = new WalkPlane(forward, -Vector3.Dot(pose.Origin, forward) - 0.1f); } /// Building placements (camera-block-local) for the landscape /// fixtures; empty for the interior-only ones. public Dictionary Buildings { get; set; } = new(); private Vector2[] _activeViewVerts = new Vector2[32]; private int _activeViewVertCount; 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) { WalkViewPoly poly = views.View.Polys[index]; if (_activeViewVerts.Length < poly.VertexCount) _activeViewVerts = new Vector2[poly.VertexCount]; for (int k = 0; k < poly.VertexCount; k++) _activeViewVerts[k] = views.View.Vertices[poly.VertexIndex + k].Point; _activeViewVertCount = poly.VertexCount; } public Vector3 ViewpointInBuilding(WalkBuilding building) => Vector3.Transform(WorldViewpoint, Buildings[building].InverseWorldTransform); public float ViewerDistanceTo(WalkBuilding building) => Vector3.Distance( WorldViewpoint, Vector3.Transform(building.SortCenter, Buildings[building].WorldTransform)); public int ClipBuildingPolygon( WalkBuilding building, WalkPolygon polygon, int side, Span output) { Matrix4x4 objectToClip = Buildings[building].WorldTransform * _viewProjection; Span projected = stackalloc WalkScreenPoint[polygon.Vertices.Length]; for (int i = 0; i < polygon.Vertices.Length; i++) projected[i] = WalkScreenClip.TransformToScreen( polygon.Vertices[i], objectToClip, ViewportWidth, ViewportHeight); if (side != 0) projected.Reverse(); return WalkScreenClip.ClipAgainstView( projected, _activeViewVerts.AsSpan(0, _activeViewVertCount), output); } // ---- 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")))}", _ => "?", })); }