fix(world): match retail portal passage and exit warp
This commit is contained in:
parent
eab23cbdd1
commit
842bd89c16
11 changed files with 355 additions and 28 deletions
|
|
@ -6,7 +6,7 @@ namespace AcDream.App.Rendering;
|
|||
/// Retail portal-space camera from <c>gmSmartBoxUI::PostInit</c>
|
||||
/// (<c>0x004D6D8A</c>) and <c>CreatureMode::SetCameraDirection_Degrees</c>
|
||||
/// (<c>0x00453760</c>). Identity looks along AC +Y with +Z up; the animated
|
||||
/// angle rotates that view around +Z.
|
||||
/// angle rolls that view around its own +Y forward axis.
|
||||
/// </summary>
|
||||
public sealed class PortalTunnelCamera : ICamera
|
||||
{
|
||||
|
|
@ -20,8 +20,9 @@ public sealed class PortalTunnelCamera : ICamera
|
|||
|
||||
/// <summary>
|
||||
/// Retail <c>CreatureMode::UseSmartboxFOV</c> reads the active SmartBox
|
||||
/// projection each draw. Recover its vertical field of view from that
|
||||
/// perspective matrix while retaining this private scene's near/far planes.
|
||||
/// projection each draw. Recover its vertical field of view and near
|
||||
/// plane from that perspective matrix while retaining this private
|
||||
/// scene's bounded far plane.
|
||||
/// </summary>
|
||||
public void UseSmartBoxFov(Matrix4x4 smartBoxProjection)
|
||||
{
|
||||
|
|
@ -32,6 +33,15 @@ public sealed class PortalTunnelCamera : ICamera
|
|||
float fov = 2f * MathF.Atan(1f / verticalScale);
|
||||
if (float.IsFinite(fov) && fov > 0f && fov < MathF.PI)
|
||||
FovRadians = fov;
|
||||
|
||||
// System.Numerics perspective matrices encode near as M43/M33.
|
||||
// During teleport fades this carries Render::set_vdst's
|
||||
// max(0.1, viewPlaneDistance * 0.25) result.
|
||||
float near = smartBoxProjection.M33 != 0f
|
||||
? smartBoxProjection.M43 / smartBoxProjection.M33
|
||||
: float.NaN;
|
||||
if (float.IsFinite(near) && near > 0f && near < Far)
|
||||
Near = near;
|
||||
}
|
||||
|
||||
public Matrix4x4 View
|
||||
|
|
@ -39,9 +49,17 @@ public sealed class PortalTunnelCamera : ICamera
|
|||
get
|
||||
{
|
||||
float radians = DirectionDegrees * (MathF.PI / 180f);
|
||||
Quaternion rotation = Quaternion.CreateFromAxisAngle(Vector3.UnitZ, radians);
|
||||
Vector3 forward = Vector3.Transform(Vector3.UnitY, rotation);
|
||||
return Matrix4x4.CreateLookAt(RetailEye, RetailEye + forward, Vector3.UnitZ);
|
||||
// CreatureMode::SetCameraDirection_Degrees (0x00453760) resets
|
||||
// the Frame to identity, converts (0, angle, 0) to radians, and
|
||||
// passes that rotation vector to Frame::rotate (0x004525B0).
|
||||
// Frame::rotate interprets the vector as axis * angle, so this is
|
||||
// a roll around AC +Y -- the identity camera's FORWARD axis --
|
||||
// not a yaw around world +Z. The passage therefore stays ahead
|
||||
// while the authored tunnel rolls around the viewer.
|
||||
Quaternion rotation = Quaternion.CreateFromAxisAngle(Vector3.UnitY, radians);
|
||||
Vector3 forward = Vector3.UnitY;
|
||||
Vector3 up = Vector3.Transform(Vector3.UnitZ, rotation);
|
||||
return Matrix4x4.CreateLookAt(RetailEye, RetailEye + forward, up);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue