2
0
mirror of https://github.com/AxioDL/metaforce.git synced 2025-12-08 13:44:56 +00:00

Finish CInterpolationCamera

This commit is contained in:
Jack Andersen
2018-06-27 15:17:01 -10:00
parent 8df333b29a
commit 680cb7b353
13 changed files with 225 additions and 57 deletions

View File

@@ -215,12 +215,12 @@ void CCameraManager::SetSpindleCamera(TUniqueId id, CStateManager& mgr)
}
void CCameraManager::InterpolateToBallCamera(const zeus::CTransform& xf, TUniqueId camId,
const zeus::CVector3f& lookPos, float f1, float f2, float f3,
bool b1, CStateManager& mgr)
const zeus::CVector3f& lookPos, float maxTime, float positionSpeed,
float rotationSpeed, bool sinusoidal, CStateManager& mgr)
{
if (!IsInFirstPersonCamera())
{
x88_interpCamera->SetInterpolation(xf, lookPos, f1, f2, f3, camId, b1, mgr);
x88_interpCamera->SetInterpolation(xf, lookPos, maxTime, positionSpeed, rotationSpeed, camId, sinusoidal, mgr);
if (!ShouldBypassInterpolation())
SetCurrentCameraId(x88_interpCamera->GetUniqueId(), mgr);
}
@@ -231,6 +231,7 @@ void CCameraManager::RestoreHintlessCamera(CStateManager& mgr)
TCastToPtr<CScriptCameraHint> hint = mgr.ObjectById(xa6_camHintId);
zeus::CTransform ballCamXf = x80_ballCamera->GetTransform();
xa6_camHintId = kInvalidUniqueId;
printf("Setting NULL\n");
xa8_hintPriority = 1000;
if (hint)
{
@@ -256,7 +257,7 @@ void CCameraManager::RestoreHintlessCamera(CStateManager& mgr)
x80_ballCamera->TeleportCamera(x80_ballCamera->UpdateLookDirection(camToPlayerFlat, mgr), mgr);
InterpolateToBallCamera(ballCamXf, x80_ballCamera->GetUniqueId(), x80_ballCamera->GetLookPos(),
hint->GetHint().GetClampVelTime(), hint->GetHint().GetClampVelRange(),
hint->GetHint().GetX50(),
hint->GetHint().GetClampRotRange(),
(hint->GetHint().GetOverrideFlags() & 0x800) != 0, mgr);
}
}
@@ -284,6 +285,7 @@ void CCameraManager::ApplyCameraHint(const CScriptCameraHint& hint, CStateManage
TCastToPtr<CScriptCameraHint> oldHint = mgr.ObjectById(xa6_camHintId);
xa6_camHintId = hint.GetUniqueId();
printf("Setting %08X %s\n", hint.GetEditorId().id, hint.GetName().data());
xa8_hintPriority = hint.GetPriority();
zeus::CTransform camXf = GetCurrentCameraTransform(mgr);
@@ -317,7 +319,8 @@ void CCameraManager::ApplyCameraHint(const CScriptCameraHint& hint, CStateManage
(oldHint && oldHint->GetHint().GetBehaviourType() != CBallCamera::EBallCameraBehaviour::Default)))
{
InterpolateToBallCamera(camXf, x80_ballCamera->GetUniqueId(), x80_ballCamera->GetLookPos(),
hint.GetHint().GetX58(), hint.GetHint().GetClampVelRange(), hint.GetHint().GetX50(),
hint.GetHint().GetInterpolateTime(), hint.GetHint().GetClampVelRange(),
hint.GetHint().GetClampRotRange(),
(hint.GetHint().GetOverrideFlags() & 0x400) != 0, mgr);
}
}
@@ -347,6 +350,7 @@ void CCameraManager::UpdateCameraHints(float, CStateManager& mgr)
{
if (it->second == id)
{
printf("ERASE %08X %s\n", hint->GetEditorId().id, hint->GetName().data());
xac_cameraHints.erase(it);
if (xa6_camHintId == id)
{
@@ -740,6 +744,20 @@ float CCameraManager::GetCameraBobMagnitude() const
bool CCameraManager::HasBallCameraInitialPositionHint(CStateManager& mgr) const
{
if (HasCameraHint(mgr))
{
switch (mgr.GetCameraManager()->GetCameraHint(mgr)->GetHint().GetBehaviourType())
{
case CBallCamera::EBallCameraBehaviour::HintBallToCam:
case CBallCamera::EBallCameraBehaviour::HintFixedPosition:
case CBallCamera::EBallCameraBehaviour::HintFixedTransform:
case CBallCamera::EBallCameraBehaviour::PathCamera:
case CBallCamera::EBallCameraBehaviour::SpindleCamera:
return true;
default:
return false;
}
}
return false;
}
@@ -761,7 +779,10 @@ void CCameraManager::DeleteCameraHint(TUniqueId id, CStateManager& mgr)
hint->ClearIdList();
hint->SetInactive(true);
if (x2b0_inactiveCameraHints.size() != 64)
{
x2b0_inactiveCameraHints.push_back(id);
printf("Delete %08X %s\n", hint->GetEditorId().id, hint->GetName().data());
}
}
}
}
@@ -774,7 +795,10 @@ void CCameraManager::AddInactiveCameraHint(TUniqueId id, CStateManager& mgr)
[id](TUniqueId tid) { return tid == id; });
if (search == x2b0_inactiveCameraHints.end() &&
x2b0_inactiveCameraHints.size() != 64)
{
x2b0_inactiveCameraHints.push_back(id);
printf("Inactive %08X %s\n", hint->GetEditorId().id, hint->GetName().data());
}
}
}
@@ -786,7 +810,10 @@ void CCameraManager::AddActiveCameraHint(TUniqueId id, CStateManager& mgr)
[id](TUniqueId tid) { return tid == id; });
if (search == x334_activeCameraHints.end() && xac_cameraHints.size() != 64 &&
x334_activeCameraHints.size() != 64)
{
x334_activeCameraHints.push_back(id);
printf("Active %08X %s\n", hint->GetEditorId().id, hint->GetName().data());
}
}
}

View File

@@ -76,8 +76,9 @@ class CCameraManager
void SetPathCamera(TUniqueId id, CStateManager& mgr);
void SetSpindleCamera(TUniqueId id, CStateManager& mgr);
void RestoreHintlessCamera(CStateManager& mgr);
void InterpolateToBallCamera(const zeus::CTransform& xf, TUniqueId camId, const zeus::CVector3f& lookPos,
float f1, float f2, float f3, bool b1, CStateManager& mgr);
void InterpolateToBallCamera(const zeus::CTransform& xf, TUniqueId camId,
const zeus::CVector3f& lookPos, float maxTime, float positionSpeed,
float rotationSpeed, bool sinusoidal, CStateManager& mgr);
void SkipBallCameraCinematic(CStateManager& mgr);
void ApplyCameraHint(const CScriptCameraHint& hint, CStateManager& mgr);

View File

@@ -335,8 +335,7 @@ float CCameraSpline::FindClosestLengthOnSpline(float time, const zeus::CVector3f
extrap = x4_positions.back();
nextDelta = delta + thisPos - extrap;
}
delta.normalize();
nextDelta.normalize();
if (i < x4_positions.size() - 2)
{
@@ -358,12 +357,14 @@ float CCameraSpline::FindClosestLengthOnSpline(float time, const zeus::CVector3f
}
nextRevDelta = revDelta + *nextPos - extrap;
}
nextRevDelta.normalize();
revDelta.normalize();
nextDelta.normalize();
nextRevDelta.normalize();
float proj = (p - thisPos).dot(delta) / delta.dot(nextDelta);
float nextProj = (p - *nextPos).dot(revDelta) / revDelta.dot(nextRevDelta);
zeus::CVector3f ptToPlayer = p - thisPos;
float proj = ptToPlayer.dot(nextDelta) / nextDelta.dot(delta.normalized());
zeus::CVector3f nextPtToPlayer = p - *nextPos;
float nextProj = nextPtToPlayer.dot(nextRevDelta) / nextRevDelta.dot(revDelta.normalized());
float t = proj / (proj + nextProj);
if (!x48_closedLoop)

View File

@@ -72,10 +72,11 @@ void CInterpolationCamera::Think(float dt, CStateManager& mgr)
}
bool deactivate = false;
if (x1d8_24_)
deactivate = sub802654d8(xf, targetOrigin, ballLookPos, x190_maxTime, x18c_time);
if (x1d8_24_sinusoidal)
deactivate = InterpolateSinusoidal(xf, targetOrigin, ballLookPos, x190_maxTime, x18c_time);
else
deactivate = sub802658c0(xf, targetOrigin, ballLookPos, x1d0_, x1d4_, x190_maxTime, x18c_time);
deactivate = InterpolateWithDistance(xf, targetOrigin, ballLookPos,
x1d0_positionSpeed, x1d4_rotationSpeed, dt, x190_maxTime, x18c_time);
SetTransform(xf);
if (deactivate)
@@ -86,16 +87,19 @@ void CInterpolationCamera::Think(float dt, CStateManager& mgr)
}
void CInterpolationCamera::SetInterpolation(const zeus::CTransform& xf, const zeus::CVector3f& lookPos,
float f1, float f2, float f3, TUniqueId camId, bool b1, CStateManager& mgr)
float maxTime, float positionSpeed, float rotationSpeed,
TUniqueId camId, bool sinusoidal, CStateManager& mgr)
{
SetActive(true);
SetTransform(xf);
x1c4_lookPos = lookPos;
x188_targetId = camId;
x1d8_24_ = b1;
x190_maxTime = f1;
x1d0_ = f2;
x1d4_ = f3;
x1d8_24_sinusoidal = sinusoidal;
x190_maxTime = maxTime;
x1d0_positionSpeed = positionSpeed;
x1d4_rotationSpeed = rotationSpeed;
x1dc_closeInAngle = 2.f * M_PIF;
x18c_time = 0.f;
if (TCastToConstPtr<CGameCamera> cam = (mgr.GetObjectById(camId)))
{
@@ -111,14 +115,126 @@ void CInterpolationCamera::DeactivateInterpCamera(CStateManager& mgr)
mgr.GetCameraManager()->SetCurrentCameraId(x188_targetId, mgr);
}
bool CInterpolationCamera::sub802654d8(zeus::CTransform& xf, const zeus::CVector3f& targetOrigin, const zeus::CVector3f& lookPos, float maxTime, float curTime)
bool CInterpolationCamera::InterpolateSinusoidal(zeus::CTransform& xf, const zeus::CVector3f& targetOrigin,
const zeus::CVector3f& lookPos, float maxTime, float curTime)
{
return false;
if (curTime > maxTime)
curTime = maxTime;
float t = zeus::clamp(-1.f, curTime / maxTime, 1.f);
float sinT = std::sin(t * (M_PIF / 2.f));
t *= 2.f;
zeus::CVector3f interpOrigin = (1.f - (t - sinT)) * (GetTranslation() - targetOrigin) + targetOrigin;
zeus::CVector3f lookDir = lookPos - interpOrigin;
if (lookDir.canBeNormalized())
lookDir.normalize();
else
lookDir = x34_transform.basis[1];
zeus::CVector3f lookDirFlat = lookDir;
lookDirFlat.z = 0.f;
if (lookDirFlat.canBeNormalized())
{
t = zeus::clamp(-1.f, t, 1.f);
float lookProj = zeus::clamp(-1.f, x34_transform.basis[1].dot(lookDir), 1.f);
float ang = (1.f - t) * std::acos(lookProj);
if (ang > x1dc_closeInAngle)
ang = x1dc_closeInAngle;
else
x1dc_closeInAngle = ang;
zeus::CTransform lookXf = zeus::lookAt(interpOrigin, interpOrigin + lookDir);
if (std::fabs(lookProj) < 0.999999f)
{
zeus::CVector3f xfLookDir =
zeus::CQuaternion::lookAt(lookDir, x34_transform.basis[1], ang).transform(lookDir);
lookXf = zeus::lookAt(interpOrigin, interpOrigin + xfLookDir);
}
xf = lookXf;
}
else
{
xf = x34_transform;
xf.origin = interpOrigin;
}
return curTime >= maxTime;
}
bool CInterpolationCamera::sub802658c0(zeus::CTransform &, const zeus::CVector3f &, const zeus::CVector3f &, float, float, float, float)
bool CInterpolationCamera::InterpolateWithDistance(zeus::CTransform& xf, const zeus::CVector3f& targetOrigin,
const zeus::CVector3f& lookPos, float positionSpeed,
float rotationSpeed, float dt, float maxTime, float curTime)
{
return false;
zeus::CVector3f interpOrigin = xf.origin;
zeus::CVector3f originDir = targetOrigin - interpOrigin;
float sdt = positionSpeed * dt;
bool ret = false;
bool positionFail = false;
if (originDir.canBeNormalized() && originDir.magnitude() > sdt)
{
float lookDist = originDir.magnitude();
originDir.normalize();
float scale = zeus::clamp(-1.f, lookDist / 0.5f, 1.f) * sdt;
interpOrigin += originDir * scale;
if (lookDist < scale)
{
interpOrigin = targetOrigin;
positionFail = true;
}
}
else
{
interpOrigin = targetOrigin;
positionFail = true;
}
zeus::CVector3f lookPosDelta = lookPos - x1c4_lookPos;
if (lookPosDelta.magnitude() > sdt)
{
float deltaMag = lookPosDelta.magnitude();
lookPosDelta.normalize();
float scale = zeus::clamp(-1.f, deltaMag / 0.5f, 1.f) * sdt;
x1c4_lookPos += lookPosDelta * scale;
}
else
{
x1c4_lookPos = lookPos;
}
zeus::CVector3f lookDir = x1c4_lookPos - interpOrigin;
if (lookDir.canBeNormalized())
lookDir.normalize();
else
lookDir = x34_transform.basis[1];
float lookProj = zeus::clamp(-1.f, xf.basis[1].dot(lookDir), 1.f);
float ang = zeus::clamp(-1.f, std::acos(lookProj) / (M_PIF / 6.f), 1.f) * rotationSpeed * dt;
zeus::CVector3f lookDirFlat = lookDir;
lookDirFlat.z = 0.f;
bool rotationFail = false;
if (lookDirFlat.canBeNormalized())
{
zeus::CTransform lookXf = zeus::lookAt(interpOrigin, interpOrigin + lookDir);
if (lookProj < 0.999999f)
lookXf = zeus::CQuaternion::lookAt(xf.basis[1], lookDir, ang).toTransform() * xf.getRotation();
else
rotationFail = true;
lookXf.origin = interpOrigin;
xf = lookXf;
}
else
{
xf = x34_transform;
xf.origin = interpOrigin;
rotationFail = true;
}
if (positionFail && rotationFail)
ret = true;
if (curTime >= maxTime && lookProj >= 0.9999f)
ret = true;
return ret;
}
}

View File

@@ -13,11 +13,17 @@ class CInterpolationCamera : public CGameCamera
float x190_maxTime = 0.f;
zeus::CTransform x194_;
zeus::CVector3f x1c4_lookPos;
float x1d0_ = 0.f;
float x1d4_ = 0.f;
float x1d0_positionSpeed = 0.f;
float x1d4_rotationSpeed = 0.f;
float x1d8_ = 0.f;
bool x1d8_24_ : 1;
float x1dc_ = M_PIF * 2.f;
bool x1d8_24_sinusoidal : 1;
float x1dc_closeInAngle = M_PIF * 2.f;
bool InterpolateSinusoidal(zeus::CTransform& xf, const zeus::CVector3f& targetOrigin,
const zeus::CVector3f& lookPos, float maxTime, float curTime);
bool InterpolateWithDistance(zeus::CTransform& xf, const zeus::CVector3f& targetOrigin,
const zeus::CVector3f& lookPos, float positionSpeed,
float rotationSpeed, float dt, float maxTime, float curTime);
public:
CInterpolationCamera(TUniqueId uid, const zeus::CTransform& xf);
void Accept(IVisitor& visitor);
@@ -27,10 +33,9 @@ public:
void Reset(const zeus::CTransform&, CStateManager& mgr);
void Think(float, CStateManager &);
void SetInterpolation(const zeus::CTransform& xf, const zeus::CVector3f& lookPos,
float f1, float f2, float f3, TUniqueId camId, bool b1, CStateManager& mgr);
float maxTime, float positionSpeed, float rotationSpeed,
TUniqueId camId, bool sinusoidal, CStateManager& mgr);
void DeactivateInterpCamera(CStateManager&);
bool sub802654d8(zeus::CTransform&, const zeus::CVector3f&, const zeus::CVector3f&, float, float);
bool sub802658c0(zeus::CTransform&, const zeus::CVector3f&, const zeus::CVector3f&, float, float, float, float);
};
}

View File

@@ -168,10 +168,11 @@ zeus::CTransform CPathCamera::MoveAlongSpline(float t, CStateManager& mgr)
zeus::CVector3f splineToPlayer = mgr.GetPlayer().GetTranslation() -
x188_spline.GetInterpolatedSplinePointByLength(x1d8_time).origin;
float distToPlayer = 0.f;
splineToPlayer.z = 0.f;
if (splineToPlayer.canBeNormalized())
distToPlayer = splineToPlayer.magnitude();
f30 *= 1.f - std::sin(zeus::degToRad(zeus::clamp(0.f, (distToPlayer - x1f0_minEaseDist) /
(x1f4_maxEaseDist - x1f0_minEaseDist), 1.f) * 90.f));
float easedDistT = (distToPlayer - x1f0_minEaseDist) / (x1f4_maxEaseDist - x1f0_minEaseDist);
f30 *= 1.f - std::sin(zeus::degToRad(zeus::clamp(0.f, easedDistT, 1.f) * 90.f));
}
float newPos;