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")))}",
_ => "?",
}));
}