fix(runtime): align portal and movement presentation
Port retail portal viewport projection and reveal behavior, preserve outbound combat style, drive remote and local grounded movement from authored CSequence root frames, and reuse the local prepared pose so animation hooks advance once. User-verified portal, observer movement, combat stance, and short-tap locomotion gates. Release build passed with 5,767 tests and five intentional skips. Co-authored-by: OpenAI Codex <codex@openai.com>
This commit is contained in:
parent
e95f55f25b
commit
124e046976
30 changed files with 1362 additions and 348 deletions
52
src/AcDream.App/Rendering/Sky/SkyProjection.cs
Normal file
52
src/AcDream.App/Rendering/Sky/SkyProjection.cs
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
using System;
|
||||
using System.Numerics;
|
||||
|
||||
namespace AcDream.App.Rendering.Sky;
|
||||
|
||||
/// <summary>
|
||||
/// Builds the temporary sky projection used by retail <c>GameSky::Draw</c>
|
||||
/// (<c>0x00506FF0</c>): preserve the active viewport's field of view and
|
||||
/// projection handedness, changing only its near/far depth mapping.
|
||||
/// </summary>
|
||||
internal static class SkyProjection
|
||||
{
|
||||
public static Matrix4x4 WithDepthRange(
|
||||
in Matrix4x4 activeProjection,
|
||||
float near,
|
||||
float far)
|
||||
{
|
||||
if (!float.IsFinite(near) || !float.IsFinite(far)
|
||||
|| near <= 0f || far <= near)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(
|
||||
nameof(far),
|
||||
"Sky depth range must be finite with 0 < near < far.");
|
||||
}
|
||||
|
||||
var result = activeProjection;
|
||||
|
||||
// System.Numerics perspective matrices use M34=-1 (right-handed).
|
||||
// Keep the source matrix's X/Y scale and offsets verbatim so a
|
||||
// teleport projection remains pixel-aligned with terrain. The
|
||||
// positive branch also preserves a left-handed source should one be
|
||||
// supplied by a future backend.
|
||||
if (activeProjection.M34 < 0f)
|
||||
{
|
||||
result.M33 = far / (near - far);
|
||||
result.M43 = near * far / (near - far);
|
||||
}
|
||||
else if (activeProjection.M34 > 0f)
|
||||
{
|
||||
result.M33 = far / (far - near);
|
||||
result.M43 = -near * far / (far - near);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException(
|
||||
"Sky projection must be perspective (M34 cannot be zero).",
|
||||
nameof(activeProjection));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue