Render assessed creatures through the shared private viewport with retail heading, bounding-box camera, and light. Build the exact authored nine-row stat list and resolve creature names from the retail EnumMapper while keeping remaining font/sequencer adaptations explicit. Co-authored-by: Codex <codex@openai.com>
86 lines
3.8 KiB
C#
86 lines
3.8 KiB
C#
using System;
|
||
using System.Numerics;
|
||
|
||
namespace AcDream.App.Rendering;
|
||
|
||
/// <summary>
|
||
/// Fixed camera for the paperdoll mini-scene — retail-exact, ported from the gmPaperDollUI viewport
|
||
/// setup (decomp 0x004a5a39–0x004a5a69). The viewport (element <c>0x100001d5</c>) is configured by
|
||
/// <c>UIElement_Viewport::SetCamera(position, direction)</c> with:
|
||
/// <list type="bullet">
|
||
/// <item>position = (0.12, −2.4, 0.88) [hex 0x3df5c28f, 0xc019999a, 0x3f6147ae]</item>
|
||
/// <item>direction = (0, 0, 0) ⇒ <c>CreatureMode::SetCameraDirection</c> resets the view frame to
|
||
/// IDENTITY (<c>euler_set_rotate(0,0,0)</c> then <c>rotate(0,0,0)</c>), so the camera looks
|
||
/// straight down +Y with +Z up — NO yaw, NO pitch.</item>
|
||
/// </list>
|
||
/// The doll is framed purely by camera POSITION + FOV, NOT by aiming at the body: at distance 2.4 with
|
||
/// a π/4 (45°) vertical FOV the visible vertical band is z≈[−0.11, 1.87], which covers the whole ~1.6 m
|
||
/// figure even though the model origin sits at the FEET (z=0). FOV π/4 is <c>CreatureMode</c>'s default
|
||
/// <c>m_fFOVRadians</c> (ctor 0x004543cf, hex 0x3f490fdb); default ambient is (0.3,0.3,0.3); the
|
||
/// paperdoll uses <c>UseSharpMode</c> (not SmartboxFOV) so <c>Render::SetFOVRad(m_fFOVRadians)</c> applies.
|
||
///
|
||
/// <para>An earlier hand-tune aimed the camera at mid-body to "fit the figure", which introduced a
|
||
/// spurious yaw (Target.x ≠ Eye.x) that rotated the view and turned the doll's face away from the
|
||
/// viewer. This restores retail's zero-yaw frame, where full-body framing comes from the eye height +
|
||
/// FOV, not from aiming.</para>
|
||
///
|
||
/// Uses the same <see cref="Matrix4x4.CreateLookAt"/> / <see cref="Matrix4x4.CreatePerspectiveFieldOfView"/>
|
||
/// convention as <see cref="ChaseCamera"/> so the doll's triangle winding + back-face culling match the
|
||
/// world render pass. AC up-axis = +Z.
|
||
/// </summary>
|
||
public sealed class DollCamera : ICamera
|
||
{
|
||
// Retail paperdoll camera origin (decomp 0x004a5a51–0x004a5a61).
|
||
internal static readonly Vector3 RetailEye = new(0.12f, -2.4f, 0.88f);
|
||
// Identity view orientation ⇒ look straight down +Y (no yaw/pitch). Target = Eye + (0,1,0).
|
||
private static readonly Vector3 Target = new(0.12f, -1.4f, 0.88f);
|
||
private static readonly Vector3 Up = Vector3.UnitZ; // AC up-axis = +Z, same as ChaseCamera
|
||
|
||
/// <summary>Vertical field of view — retail <c>CreatureMode</c> default <c>m_fFOVRadians</c> = π/4 (45°).</summary>
|
||
public float FovRadians { get; set; } = MathF.PI / 4f;
|
||
|
||
public float Near { get; set; } = 0.1f; // same near plane as ChaseCamera / retail znear
|
||
public float Far { get; set; } = 50f; // doll scene is small; 50 m is ample
|
||
public float Aspect { get; set; } = 1f;
|
||
|
||
/// <inheritdoc/>
|
||
public Matrix4x4 View =>
|
||
Matrix4x4.CreateLookAt(RetailEye, Target, Up);
|
||
|
||
/// <inheritdoc/>
|
||
public Matrix4x4 Projection =>
|
||
Matrix4x4.CreatePerspectiveFieldOfView(FovRadians, Aspect <= 0f ? 1f : Aspect, Near, Far);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Internal private-viewport adapter that preserves <see cref="DollCamera"/>'s
|
||
/// existing public camera contract.
|
||
/// </summary>
|
||
internal sealed class DollViewportCamera : IPrivateEntityViewportCamera
|
||
{
|
||
private readonly DollCamera _camera = new();
|
||
|
||
public Vector3 Eye => DollCamera.RetailEye;
|
||
public float FovRadians
|
||
{
|
||
get => _camera.FovRadians;
|
||
set => _camera.FovRadians = value;
|
||
}
|
||
public float Near
|
||
{
|
||
get => _camera.Near;
|
||
set => _camera.Near = value;
|
||
}
|
||
public float Far
|
||
{
|
||
get => _camera.Far;
|
||
set => _camera.Far = value;
|
||
}
|
||
public float Aspect
|
||
{
|
||
get => _camera.Aspect;
|
||
set => _camera.Aspect = value;
|
||
}
|
||
public Matrix4x4 View => _camera.View;
|
||
public Matrix4x4 Projection => _camera.Projection;
|
||
}
|