feat(D.2b): Slice 2 — DollCamera (fixed paperdoll ICamera)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
c5604ff6ad
commit
10cb31223f
2 changed files with 64 additions and 0 deletions
37
src/AcDream.App/Rendering/DollCamera.cs
Normal file
37
src/AcDream.App/Rendering/DollCamera.cs
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
using System.Numerics;
|
||||
|
||||
namespace AcDream.App.Rendering;
|
||||
|
||||
/// <summary>
|
||||
/// Fixed camera for the paperdoll mini-scene. Eye and look-at from
|
||||
/// <c>gmPaperDollUI::PostInit</c> (decomp lines 175521–175527):
|
||||
/// eye (0.12, -2.4, 0.88) looking at the origin, AC up-axis = +Z.
|
||||
///
|
||||
/// Uses the same <see cref="Matrix4x4.CreateLookAt"/> /
|
||||
/// <see cref="Matrix4x4.CreatePerspectiveFieldOfView"/> convention as
|
||||
/// <see cref="ChaseCamera"/> so the doll's triangle winding and back-face
|
||||
/// culling match the world render pass.
|
||||
///
|
||||
/// Per-race camera distance (<c>UpdateForRace</c>) is deferred polish.
|
||||
/// </summary>
|
||||
public sealed class DollCamera : ICamera
|
||||
{
|
||||
private static readonly Vector3 Eye = new(0.12f, -2.4f, 0.88f);
|
||||
private static readonly Vector3 Target = Vector3.Zero;
|
||||
private static readonly Vector3 Up = Vector3.UnitZ; // AC up-axis = +Z, same as ChaseCamera
|
||||
|
||||
/// <summary>Vertical field of view in radians. ~34° default; tune at the visual gate.</summary>
|
||||
public float FovRadians { get; set; } = 0.6f;
|
||||
|
||||
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(Eye, Target, Up);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Matrix4x4 Projection =>
|
||||
Matrix4x4.CreatePerspectiveFieldOfView(FovRadians, Aspect <= 0f ? 1f : Aspect, Near, Far);
|
||||
}
|
||||
27
tests/AcDream.App.Tests/Rendering/DollCameraTests.cs
Normal file
27
tests/AcDream.App.Tests/Rendering/DollCameraTests.cs
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
using System.Numerics;
|
||||
using AcDream.App.Rendering;
|
||||
using Xunit;
|
||||
|
||||
namespace AcDream.App.Tests.Rendering;
|
||||
|
||||
public class DollCameraTests
|
||||
{
|
||||
[Fact]
|
||||
public void Eye_position_is_the_retail_camera_offset()
|
||||
{
|
||||
var cam = new DollCamera { Aspect = 100f / 214f };
|
||||
Assert.True(Matrix4x4.Invert(cam.View, out var inv));
|
||||
var eye = inv.Translation;
|
||||
Assert.Equal(0.12f, eye.X, 3);
|
||||
Assert.Equal(-2.4f, eye.Y, 3);
|
||||
Assert.Equal(0.88f, eye.Z, 3);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Projection_is_finite_and_uses_aspect()
|
||||
{
|
||||
var cam = new DollCamera { Aspect = 1.5f };
|
||||
Assert.True(float.IsFinite(cam.Projection.M11));
|
||||
Assert.NotEqual(0f, cam.Projection.M34); // perspective w = -z term
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue