fix(camera): complete retail in-head adjustment behavior
This commit is contained in:
parent
11e68aad82
commit
4d0379744b
2 changed files with 86 additions and 7 deletions
|
|
@ -36,6 +36,8 @@ public sealed class RetailChaseCamera : ICamera
|
|||
private const float RetailFirstPersonForward = 0.18f;
|
||||
private const float RetailLeaveHeadBack = 0.6f;
|
||||
private const float RetailLeaveHeadUp = 0.5f;
|
||||
private const float RetailInHeadDirectionStep = 0.200000003f;
|
||||
private const float RetailInHeadDirectionLimit = 0.800000012f;
|
||||
|
||||
// CameraSet::{Farther,Closer,Raise,Lower,Rotate} constants. The named
|
||||
// retail decomp carries CAMERA_MOUSELOOK_INC at 0x0079BC04 and the
|
||||
|
|
@ -199,7 +201,7 @@ public sealed class RetailChaseCamera : ICamera
|
|||
// Keep in View snaps the camera behind the target and disables RMB orbit.
|
||||
float viewerYawOffset = trackedHeading.HasValue ? YawOffset : 0f;
|
||||
(Vector3 targetEye, Vector3 targetForward) = _inHead
|
||||
? ComputeInHeadPose(pivotWorld, heading)
|
||||
? ComputeInHeadPose(pivotWorld, heading, _targetDirectionLocal)
|
||||
: _targetDirectionLocal is { } localDirection
|
||||
? ComputeTargetDirectionPose(
|
||||
pivotWorld, heading, Distance, Pitch, localDirection)
|
||||
|
|
@ -333,9 +335,12 @@ public sealed class RetailChaseCamera : ICamera
|
|||
|
||||
// Farther's exact in-head branch replaces (0,+0.18,0) with
|
||||
// (0,-0.6,+0.5) and returns without applying the ordinary scale.
|
||||
if (_inHead)
|
||||
// Closer has no matching escape branch: its scaled 0.18 m offset
|
||||
// fails the 0.5 m near gate and therefore leaves first-person intact.
|
||||
if (_inHead && adjustment > 0f)
|
||||
{
|
||||
_inHead = false;
|
||||
_targetDirectionLocal = null;
|
||||
SetViewerOffset(RetailLeaveHeadBack, RetailLeaveHeadUp);
|
||||
return;
|
||||
}
|
||||
|
|
@ -366,8 +371,16 @@ public sealed class RetailChaseCamera : ICamera
|
|||
|
||||
if (_inHead)
|
||||
{
|
||||
_inHead = false;
|
||||
SetViewerOffset(RetailLeaveHeadBack, RetailLeaveHeadUp);
|
||||
// CameraSet::{Raise,Lower} modify CameraManager::direction.z by
|
||||
// 0.2 while InHead, clamp it to +/-0.8, and return. The viewer
|
||||
// offset remains the authored +Y*0.18 head position.
|
||||
Vector3 direction = _targetDirectionLocal ?? Vector3.UnitY;
|
||||
direction.Z = Math.Clamp(
|
||||
direction.Z + adjustment * RetailInHeadDirectionStep,
|
||||
-RetailInHeadDirectionLimit,
|
||||
RetailInHeadDirectionLimit);
|
||||
_targetDirectionLocal = direction;
|
||||
return;
|
||||
}
|
||||
|
||||
float candidatePitch = Pitch + adjustment * OffsetAngleRadians;
|
||||
|
|
@ -674,10 +687,22 @@ public sealed class RetailChaseCamera : ICamera
|
|||
/// </summary>
|
||||
internal static (Vector3 eye, Vector3 forward) ComputeInHeadPose(
|
||||
Vector3 pivotWorld,
|
||||
Vector3 heading)
|
||||
Vector3 heading,
|
||||
Vector3? targetDirectionLocal = null)
|
||||
{
|
||||
Vector3 forward = Vector3.Normalize(heading);
|
||||
return (pivotWorld + forward * RetailFirstPersonForward, forward);
|
||||
Vector3 headingForward = Vector3.Normalize(heading);
|
||||
Vector3 targetForward = headingForward;
|
||||
if (targetDirectionLocal is { } local)
|
||||
{
|
||||
var (frameForward, frameRight, frameUp) = BuildBasis(headingForward);
|
||||
targetForward = Vector3.Normalize(
|
||||
frameForward * local.Y
|
||||
- frameRight * local.X
|
||||
+ frameUp * local.Z);
|
||||
}
|
||||
return (
|
||||
pivotWorld + headingForward * RetailFirstPersonForward,
|
||||
targetForward);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue