2019-12-22 20:04:07 +00:00
|
|
|
#include "Runtime/World/CScriptSpindleCamera.hpp"
|
|
|
|
|
|
|
|
#include "Runtime/CStateManager.hpp"
|
|
|
|
#include "Runtime/Camera/CBallCamera.hpp"
|
|
|
|
#include "Runtime/Camera/CCameraManager.hpp"
|
|
|
|
#include "Runtime/World/CPlayer.hpp"
|
|
|
|
#include "Runtime/World/CScriptCameraHint.hpp"
|
|
|
|
#include "Runtime/World/ScriptLoader.hpp"
|
|
|
|
|
2019-09-21 13:07:13 +00:00
|
|
|
#include "TCastTo.hpp" // Generated file, do not modify include path
|
2017-10-06 07:29:56 +00:00
|
|
|
|
2021-04-10 08:42:06 +00:00
|
|
|
namespace metaforce {
|
2017-10-06 07:29:56 +00:00
|
|
|
|
2019-02-10 04:41:35 +00:00
|
|
|
SSpindleProperty::SSpindleProperty(CInputStream& in) {
|
|
|
|
x4_input = ESpindleInput(in.readUint32Big());
|
|
|
|
x0_flags = ScriptLoader::LoadParameterFlags(in);
|
|
|
|
x8_lowOut = in.readFloatBig();
|
|
|
|
xc_highOut = in.readFloatBig();
|
|
|
|
x10_lowIn = in.readFloatBig();
|
|
|
|
x14_highIn = in.readFloatBig();
|
|
|
|
switch (x4_input) {
|
|
|
|
case ESpindleInput::HintBallAngle:
|
|
|
|
case ESpindleInput::HintBallRightAngle:
|
|
|
|
case ESpindleInput::HintBallLeftAngle:
|
|
|
|
x10_lowIn = zeus::degToRad(x10_lowIn);
|
|
|
|
x14_highIn = zeus::degToRad(x14_highIn);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2017-10-06 07:29:56 +00:00
|
|
|
|
2021-06-07 19:29:18 +00:00
|
|
|
CScriptSpindleCamera::CScriptSpindleCamera(
|
|
|
|
TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, bool active, u32 flags,
|
|
|
|
float hintToCamDistMin, float hintToCamDistMax, float hintToCamVOffMin, float hintToCamVOffMax,
|
|
|
|
const SSpindleProperty& targetHintToCamDeltaAngleVel, const SSpindleProperty& deltaAngleScaleWithCamDist,
|
|
|
|
const SSpindleProperty& hintToCamDist, const SSpindleProperty& distOffsetFromBallDist,
|
|
|
|
const SSpindleProperty& hintBallToCamAzimuth, const SSpindleProperty& unused,
|
|
|
|
const SSpindleProperty& maxHintBallToCamAzimuth, const SSpindleProperty& camLookRelAzimuth,
|
|
|
|
const SSpindleProperty& lookPosZOffset, const SSpindleProperty& camPosZOffset,
|
|
|
|
const SSpindleProperty& clampedAzimuthFromHintDir, const SSpindleProperty& dampingAzimuthSpeed,
|
|
|
|
const SSpindleProperty& targetHintToCamDeltaAngleVelRange, const SSpindleProperty& deleteHintBallDist,
|
|
|
|
const SSpindleProperty& recoverClampedAzimuthFromHintDir)
|
2017-10-06 07:29:56 +00:00
|
|
|
: CGameCamera(uid, active, name, info, xf, CCameraManager::ThirdPersonFOV(), CCameraManager::NearPlane(),
|
2018-12-08 05:30:43 +00:00
|
|
|
CCameraManager::FarPlane(), CCameraManager::Aspect(), kInvalidUniqueId, false, 0)
|
2019-02-10 04:41:35 +00:00
|
|
|
, x188_flags(flags)
|
|
|
|
, x1b0_hintToCamDistMin(hintToCamDistMin)
|
|
|
|
, x1b4_hintToCamDistMax(hintToCamDistMax)
|
|
|
|
, x1b8_hintToCamVOffMin(hintToCamVOffMin)
|
|
|
|
, x1bc_hintToCamVOffMax(hintToCamVOffMax)
|
|
|
|
, x1c0_targetHintToCamDeltaAngleVel(targetHintToCamDeltaAngleVel)
|
|
|
|
, x1d8_deltaAngleScaleWithCamDist(deltaAngleScaleWithCamDist)
|
|
|
|
, x1f0_hintToCamDist(hintToCamDist)
|
|
|
|
, x208_distOffsetFromBallDist(distOffsetFromBallDist)
|
|
|
|
, x220_hintBallToCamAzimuth(hintBallToCamAzimuth)
|
|
|
|
, x238_unused(unused)
|
|
|
|
, x250_maxHintBallToCamAzimuth(maxHintBallToCamAzimuth)
|
|
|
|
, x268_camLookRelAzimuth(camLookRelAzimuth)
|
|
|
|
, x280_lookPosZOffset(lookPosZOffset)
|
|
|
|
, x298_camPosZOffset(camPosZOffset)
|
|
|
|
, x2b0_clampedAzimuthFromHintDir(clampedAzimuthFromHintDir)
|
|
|
|
, x2c8_dampingAzimuthSpeed(dampingAzimuthSpeed)
|
|
|
|
, x2e0_targetHintToCamDeltaAngleVelRange(targetHintToCamDeltaAngleVelRange)
|
|
|
|
, x2f8_deleteHintBallDist(deleteHintBallDist)
|
|
|
|
, x310_recoverClampedAzimuthFromHintDir(recoverClampedAzimuthFromHintDir)
|
2018-12-08 05:30:43 +00:00
|
|
|
, x330_lookDir(xf.basis[1]) {}
|
2017-10-06 07:29:56 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
void CScriptSpindleCamera::Accept(IVisitor& visitor) { visitor.Visit(this); }
|
2017-10-06 07:29:56 +00:00
|
|
|
|
2019-02-10 04:41:35 +00:00
|
|
|
void CScriptSpindleCamera::ProcessInput(const CFinalInput& input, CStateManager& mgr) {
|
|
|
|
// Empty
|
|
|
|
}
|
2017-10-06 07:29:56 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
void CScriptSpindleCamera::Reset(const zeus::CTransform& xf, CStateManager& mgr) {
|
|
|
|
const CScriptCameraHint* hint = mgr.GetCameraManager()->GetCameraHint(mgr);
|
2020-05-07 15:59:29 +00:00
|
|
|
if (!GetActive() || hint == nullptr) {
|
2018-12-08 05:30:43 +00:00
|
|
|
return;
|
2020-05-07 15:59:29 +00:00
|
|
|
}
|
2017-10-06 07:29:56 +00:00
|
|
|
|
2019-02-10 04:41:35 +00:00
|
|
|
x33c_24_inResetThink = true;
|
2018-12-08 05:30:43 +00:00
|
|
|
mgr.GetCameraManager()->GetBallCamera()->UpdateLookAtPosition(0.01f, mgr);
|
2019-02-10 04:41:35 +00:00
|
|
|
Think(0.01f, mgr);
|
|
|
|
x33c_24_inResetThink = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CScriptSpindleCamera::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) {
|
|
|
|
CGameCamera::AcceptScriptMsg(msg, sender, mgr);
|
2017-10-06 07:29:56 +00:00
|
|
|
}
|
|
|
|
|
2019-02-10 04:41:35 +00:00
|
|
|
float SSpindleProperty::GetValue(float inVar) const {
|
2020-05-07 15:59:29 +00:00
|
|
|
if (x4_input == ESpindleInput::Constant) {
|
2019-02-10 04:41:35 +00:00
|
|
|
return x8_lowOut;
|
2020-05-07 15:59:29 +00:00
|
|
|
}
|
2019-02-10 04:41:35 +00:00
|
|
|
|
2020-05-07 15:59:29 +00:00
|
|
|
const float reflectRange = x14_highIn - x10_lowIn;
|
|
|
|
if (zeus::close_enough(reflectRange, 0.f)) {
|
2019-02-10 04:41:35 +00:00
|
|
|
return x8_lowOut;
|
2020-05-07 15:59:29 +00:00
|
|
|
}
|
2019-02-10 04:41:35 +00:00
|
|
|
|
|
|
|
float reflectedVar = inVar;
|
2020-05-07 15:59:29 +00:00
|
|
|
if (x0_flags & 0x1 && inVar > x14_highIn) {
|
2019-02-10 04:41:35 +00:00
|
|
|
reflectedVar = x14_highIn - (inVar - x14_highIn);
|
2020-05-07 15:59:29 +00:00
|
|
|
}
|
|
|
|
if (x0_flags & 0x2 && inVar < x10_lowIn) {
|
2019-02-10 04:41:35 +00:00
|
|
|
reflectedVar = x10_lowIn + (x10_lowIn - inVar);
|
2020-05-07 15:59:29 +00:00
|
|
|
}
|
2019-02-10 04:41:35 +00:00
|
|
|
|
2020-05-07 15:59:29 +00:00
|
|
|
const float outRange = xc_highOut - x8_lowOut;
|
|
|
|
const float res = (reflectedVar - x10_lowIn) * outRange / reflectRange + x8_lowOut;
|
|
|
|
if (x8_lowOut < xc_highOut) {
|
2019-02-10 04:41:35 +00:00
|
|
|
return zeus::clamp(x8_lowOut, res, xc_highOut);
|
2020-05-07 15:59:29 +00:00
|
|
|
} else {
|
2019-02-10 04:41:35 +00:00
|
|
|
return zeus::clamp(xc_highOut, res, x8_lowOut);
|
2020-05-07 15:59:29 +00:00
|
|
|
}
|
2019-02-10 04:41:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CScriptSpindleCamera::Think(float dt, CStateManager& mgr) {
|
|
|
|
const CScriptCameraHint* hint = mgr.GetCameraManager()->GetCameraHint(mgr);
|
2020-05-07 15:59:29 +00:00
|
|
|
if (!GetActive() || hint == nullptr) {
|
2019-02-10 04:41:35 +00:00
|
|
|
return;
|
2020-05-07 15:59:29 +00:00
|
|
|
}
|
2019-02-10 04:41:35 +00:00
|
|
|
|
|
|
|
zeus::CVector3f hintPos = hint->GetTranslation();
|
|
|
|
zeus::CVector2f lookAheadPos = mgr.GetCameraManager()->GetBallCamera()->GetLookPosAhead().toVec2f();
|
|
|
|
zeus::CVector3f hintToCamDir = GetTranslation() - hintPos;
|
|
|
|
hintToCamDir.z() = 0.f;
|
2020-05-07 15:59:29 +00:00
|
|
|
const zeus::CVector3f ballPos = mgr.GetPlayer().GetBallPosition();
|
2019-02-10 04:41:35 +00:00
|
|
|
zeus::CVector3f hintToBallDir = ballPos - hintPos;
|
2020-05-07 15:59:29 +00:00
|
|
|
const float hintToBallVOff = hintToBallDir.z();
|
2019-02-10 04:41:35 +00:00
|
|
|
hintToBallDir.z() = 0.f;
|
2020-05-07 15:59:29 +00:00
|
|
|
|
2019-02-10 04:41:35 +00:00
|
|
|
zeus::CVector3f hintDir = hint->GetTransform().basis[1];
|
|
|
|
hintDir.z() = 0.f;
|
2020-05-07 15:59:29 +00:00
|
|
|
if (hintDir.canBeNormalized()) {
|
2019-02-10 04:41:35 +00:00
|
|
|
hintDir.normalize();
|
2020-05-07 15:59:29 +00:00
|
|
|
} else {
|
2019-02-24 07:15:54 +00:00
|
|
|
hintDir = zeus::skForward;
|
2020-05-07 15:59:29 +00:00
|
|
|
}
|
|
|
|
|
2019-02-10 04:41:35 +00:00
|
|
|
float hintToBallDist = 0.f;
|
|
|
|
if (hintToBallDir.canBeNormalized()) {
|
|
|
|
hintToBallDist = hintToBallDir.magnitude();
|
|
|
|
hintToBallDir.normalize();
|
|
|
|
} else {
|
|
|
|
hintToBallDir = hintDir;
|
|
|
|
}
|
|
|
|
|
|
|
|
x18c_inVars.clear();
|
2021-06-07 19:29:18 +00:00
|
|
|
x18c_inVars.push_back(0.f); // Zero
|
|
|
|
x18c_inVars.push_back(hintToBallDist); // HintToBallDist
|
2019-02-10 04:41:35 +00:00
|
|
|
x18c_inVars.push_back(std::fabs(hintToBallVOff)); // HintToBallVOff
|
2020-05-07 15:59:29 +00:00
|
|
|
const float hintBallAngle = std::fabs(std::acos(zeus::clamp(-1.f, hintToBallDir.dot(hintDir), 1.f)));
|
2019-02-10 04:41:35 +00:00
|
|
|
x18c_inVars.push_back(hintBallAngle); // HintBallAngle
|
2020-05-07 15:59:29 +00:00
|
|
|
const float hintBallCross = hintToBallDir.toVec2f().cross(hintDir.toVec2f());
|
2019-02-10 04:41:35 +00:00
|
|
|
if (hintBallCross >= 0.f) {
|
2021-06-07 19:29:18 +00:00
|
|
|
x18c_inVars.push_back(hintBallAngle); // HintBallRightAngle
|
2019-02-10 04:41:35 +00:00
|
|
|
x18c_inVars.push_back(2.f * M_PIF - hintBallAngle); // HintBallLeftAngle
|
|
|
|
} else {
|
|
|
|
x18c_inVars.push_back(2.f * M_PIF - hintBallAngle); // HintBallRightAngle
|
2021-06-07 19:29:18 +00:00
|
|
|
x18c_inVars.push_back(hintBallAngle); // HintBallLeftAngle
|
2019-02-10 04:41:35 +00:00
|
|
|
}
|
|
|
|
zeus::CVector3f hintDelta = hint->GetTranslation() - hint->GetOriginalTransform().origin;
|
2020-05-07 15:59:29 +00:00
|
|
|
const float hintDeltaVOff = std::fabs(hintDelta.z());
|
2019-02-10 04:41:35 +00:00
|
|
|
hintDelta.z() = 0.f;
|
|
|
|
x18c_inVars.push_back(hintDelta.canBeNormalized() ? hintDelta.magnitude() : 0.f); // HintDeltaDist
|
2021-06-07 19:29:18 +00:00
|
|
|
x18c_inVars.push_back(hintDeltaVOff); // HintDeltaVOff
|
2019-02-10 04:41:35 +00:00
|
|
|
|
2021-06-07 19:29:18 +00:00
|
|
|
if ((x188_flags & 0x2000) && hintToBallDist > x2f8_deleteHintBallDist.GetValue(GetInVar(x2f8_deleteHintBallDist))) {
|
2019-02-10 04:41:35 +00:00
|
|
|
|
2020-05-07 15:59:29 +00:00
|
|
|
if (hint->GetDelegatedCamera() == GetUniqueId()) {
|
2019-02-10 04:41:35 +00:00
|
|
|
mgr.GetCameraManager()->DeleteCameraHint(hint->GetUniqueId(), mgr);
|
2020-05-07 15:59:29 +00:00
|
|
|
}
|
2019-02-10 04:41:35 +00:00
|
|
|
} else {
|
2020-05-07 15:59:29 +00:00
|
|
|
if ((x188_flags & 0x800) == 0) {
|
2019-02-10 04:41:35 +00:00
|
|
|
hintToBallDir = hintDir;
|
2020-05-07 15:59:29 +00:00
|
|
|
}
|
|
|
|
if ((x188_flags & 0x20) != 0) {
|
2019-02-10 04:41:35 +00:00
|
|
|
if (!x32c_outsideClampedAzimuth) {
|
|
|
|
if (hintBallAngle > x2b0_clampedAzimuthFromHintDir.GetValue(GetInVar(x2b0_clampedAzimuthFromHintDir))) {
|
|
|
|
x330_lookDir = hintToBallDir;
|
|
|
|
x32c_outsideClampedAzimuth = true;
|
|
|
|
}
|
|
|
|
} else {
|
2020-05-07 15:59:29 +00:00
|
|
|
const float hintCamCross = hintToCamDir.toVec2f().cross(hintDir.toVec2f());
|
2021-06-07 19:29:18 +00:00
|
|
|
if ((hintBallAngle <
|
|
|
|
x310_recoverClampedAzimuthFromHintDir.GetValue(GetInVar(x310_recoverClampedAzimuthFromHintDir)) &&
|
|
|
|
hintBallCross * hintCamCross < 0.f) ||
|
2019-02-10 04:41:35 +00:00
|
|
|
hintBallAngle <= x2b0_clampedAzimuthFromHintDir.GetValue(GetInVar(x2b0_clampedAzimuthFromHintDir))) {
|
|
|
|
x32c_outsideClampedAzimuth = false;
|
|
|
|
} else {
|
|
|
|
hintToBallDir = x330_lookDir;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
float newHintToCamDist = x1f0_hintToCamDist.GetValue(GetInVar(x1f0_hintToCamDist));
|
2020-05-07 15:59:29 +00:00
|
|
|
if ((x188_flags & 0x40) != 0) {
|
|
|
|
newHintToCamDist = hintToBallDist + x208_distOffsetFromBallDist.GetValue(GetInVar(x208_distOffsetFromBallDist));
|
|
|
|
}
|
2019-02-10 04:41:35 +00:00
|
|
|
newHintToCamDist = zeus::clamp(x1b0_hintToCamDistMin, newHintToCamDist, x1b4_hintToCamDistMax);
|
2020-05-07 15:59:29 +00:00
|
|
|
|
2019-02-10 04:41:35 +00:00
|
|
|
zeus::CVector3f newCamPos = GetTranslation();
|
|
|
|
float hintToCamDist = hintToCamDir.magnitude();
|
|
|
|
if (hintToCamDir.canBeNormalized()) {
|
|
|
|
hintToCamDir.normalize();
|
|
|
|
} else {
|
|
|
|
hintToCamDir = hintDir;
|
|
|
|
hintToCamDist = x1f0_hintToCamDist.GetValue(GetInVar(x1f0_hintToCamDist));
|
|
|
|
}
|
|
|
|
|
2020-05-07 15:59:29 +00:00
|
|
|
float hintBallToCamTargetAzimuth = x220_hintBallToCamAzimuth.GetValue(GetInVar(x220_hintBallToCamAzimuth));
|
|
|
|
if ((x188_flags & 0x4000) == 0 && hintToCamDir.cross(hintToBallDir).z() >= 0.f) {
|
2019-02-10 04:41:35 +00:00
|
|
|
hintBallToCamTargetAzimuth = -hintBallToCamTargetAzimuth;
|
2020-05-07 15:59:29 +00:00
|
|
|
}
|
|
|
|
|
2019-02-10 04:41:35 +00:00
|
|
|
zeus::CQuaternion hintBallToCamTargetAzimuthQuat;
|
|
|
|
hintBallToCamTargetAzimuthQuat.rotateZ(hintBallToCamTargetAzimuth);
|
2020-05-07 15:59:29 +00:00
|
|
|
const zeus::CVector3f targetHintToCam = hintBallToCamTargetAzimuthQuat.transform(hintToBallDir);
|
2019-02-10 04:41:35 +00:00
|
|
|
zeus::CVector3f newHintToCamDir = hintToCamDir;
|
2021-06-07 19:29:18 +00:00
|
|
|
const float hintToCamDeltaAngleRange =
|
|
|
|
std::fabs(std::acos(zeus::clamp(-1.f, hintToCamDir.dot(targetHintToCam), 1.f)));
|
2020-05-07 15:59:29 +00:00
|
|
|
const float hintToCamDeltaAngleSpeedFactor = zeus::clamp(
|
|
|
|
-1.f, hintToCamDeltaAngleRange / x2c8_dampingAzimuthSpeed.GetValue(GetInVar(x2c8_dampingAzimuthSpeed)), 1.f);
|
2019-02-10 04:41:35 +00:00
|
|
|
float targetHintToCamDeltaAngleVel =
|
2020-05-07 15:59:29 +00:00
|
|
|
x1c0_targetHintToCamDeltaAngleVel.GetValue(GetInVar(x1c0_targetHintToCamDeltaAngleVel));
|
|
|
|
if ((x188_flags & 0x100) != 0) {
|
|
|
|
targetHintToCamDeltaAngleVel = zeus::clamp(
|
|
|
|
-targetHintToCamDeltaAngleVel,
|
|
|
|
x1d8_deltaAngleScaleWithCamDist.GetValue(GetInVar(x1d8_deltaAngleScaleWithCamDist)) / hintToCamDist,
|
|
|
|
targetHintToCamDeltaAngleVel);
|
|
|
|
}
|
2019-02-10 04:41:35 +00:00
|
|
|
if ((hintToBallDir.cross(hintToCamDir).z() >= 0.f && targetHintToCam.cross(hintToCamDir).z() < 0.f) ||
|
|
|
|
(hintToBallDir.cross(hintToCamDir).z() < 0.f && targetHintToCam.cross(hintToCamDir).z() >= 0.f)) {
|
2020-05-07 15:59:29 +00:00
|
|
|
const float targetHintToCamDeltaAngleVelRange =
|
|
|
|
x2e0_targetHintToCamDeltaAngleVelRange.GetValue(GetInVar(x2e0_targetHintToCamDeltaAngleVelRange));
|
|
|
|
targetHintToCamDeltaAngleVel = zeus::clamp(-targetHintToCamDeltaAngleVelRange, targetHintToCamDeltaAngleVel,
|
|
|
|
targetHintToCamDeltaAngleVelRange);
|
2019-02-10 04:41:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
zeus::CVector3f camToBall = ballPos - GetTranslation();
|
|
|
|
camToBall.z() = 0.f;
|
|
|
|
float targetHintToCamDeltaAngle = targetHintToCamDeltaAngleVel * dt * hintToCamDeltaAngleSpeedFactor;
|
|
|
|
float camToBallDist = 0.f;
|
2020-05-07 15:59:29 +00:00
|
|
|
if (camToBall.canBeNormalized()) {
|
2019-02-10 04:41:35 +00:00
|
|
|
camToBallDist = camToBall.magnitude();
|
2020-05-07 15:59:29 +00:00
|
|
|
}
|
2019-02-10 04:41:35 +00:00
|
|
|
targetHintToCamDeltaAngle *= (1.f - zeus::clamp(0.f, (camToBallDist - 2.f) * 0.5f, 1.f)) * 10.f + 1.f;
|
2021-06-07 19:29:18 +00:00
|
|
|
targetHintToCamDeltaAngle =
|
|
|
|
zeus::clamp(-hintToCamDeltaAngleRange, targetHintToCamDeltaAngle, hintToCamDeltaAngleRange);
|
2020-05-07 15:59:29 +00:00
|
|
|
if (std::fabs(zeus::clamp(-1.f, hintToCamDir.dot(targetHintToCam), 1.f)) < 0.99999f) {
|
|
|
|
newHintToCamDir =
|
|
|
|
zeus::CQuaternion::lookAt(hintToCamDir, targetHintToCam, targetHintToCamDeltaAngle).transform(hintToCamDir);
|
|
|
|
}
|
|
|
|
const float hintBallToCamAzimuth = std::acos(zeus::clamp(-1.f, hintToBallDir.dot(newHintToCamDir), 1.f));
|
|
|
|
if ((x188_flags & 0x10) != 0) {
|
|
|
|
if (std::fabs(hintBallToCamAzimuth) < x220_hintBallToCamAzimuth.GetValue(GetInVar(x220_hintBallToCamAzimuth)) ||
|
|
|
|
(x188_flags & 0x8) != 0 || x33c_24_inResetThink) {
|
2019-02-10 04:41:35 +00:00
|
|
|
newHintToCamDir = targetHintToCam;
|
2020-05-07 15:59:29 +00:00
|
|
|
}
|
2019-02-10 04:41:35 +00:00
|
|
|
}
|
|
|
|
|
2020-05-07 15:59:29 +00:00
|
|
|
const float maxHintBallToCamAzimuth = x250_maxHintBallToCamAzimuth.GetValue(GetInVar(x250_maxHintBallToCamAzimuth));
|
2019-02-10 04:41:35 +00:00
|
|
|
if (std::fabs(hintBallToCamAzimuth) > maxHintBallToCamAzimuth) {
|
|
|
|
x328_maxAzimuthInterpTimer += dt;
|
|
|
|
if (x328_maxAzimuthInterpTimer < 3.f) {
|
2020-05-07 15:59:29 +00:00
|
|
|
const float ballToCamAzimuthInterp = zeus::clamp(-1.f, x328_maxAzimuthInterpTimer / 3.f, 1.f);
|
2019-02-10 04:41:35 +00:00
|
|
|
float hintBallToCamAzimuthDelta = std::fabs(maxHintBallToCamAzimuth - hintBallToCamAzimuth);
|
2020-05-07 15:59:29 +00:00
|
|
|
if (hintToBallDir.cross(newHintToCamDir).z() > 0.f) {
|
2019-02-10 04:41:35 +00:00
|
|
|
hintBallToCamAzimuthDelta = -hintBallToCamAzimuthDelta;
|
2020-05-07 15:59:29 +00:00
|
|
|
}
|
2019-02-10 04:41:35 +00:00
|
|
|
zeus::CQuaternion hintBallToCamAzimuthQuat;
|
|
|
|
hintBallToCamAzimuthQuat.rotateZ(hintBallToCamAzimuthDelta * ballToCamAzimuthInterp);
|
|
|
|
newHintToCamDir = hintBallToCamAzimuthQuat.transform(newHintToCamDir);
|
|
|
|
} else {
|
|
|
|
zeus::CQuaternion hintBallToCamAzimuthQuat;
|
2020-05-07 15:59:29 +00:00
|
|
|
if (hintBallToCamTargetAzimuth > 0.f) {
|
2019-02-10 04:41:35 +00:00
|
|
|
hintBallToCamAzimuthQuat.rotateZ(maxHintBallToCamAzimuth);
|
2020-05-07 15:59:29 +00:00
|
|
|
} else {
|
2019-02-10 04:41:35 +00:00
|
|
|
hintBallToCamAzimuthQuat.rotateZ(-maxHintBallToCamAzimuth);
|
2020-05-07 15:59:29 +00:00
|
|
|
}
|
2019-02-10 04:41:35 +00:00
|
|
|
newHintToCamDir = hintBallToCamAzimuthQuat.transform(hintToBallDir);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
x328_maxAzimuthInterpTimer = 0.f;
|
|
|
|
}
|
|
|
|
|
2020-05-07 15:59:29 +00:00
|
|
|
if ((x188_flags & 0x20) != 0) {
|
2019-02-10 04:41:35 +00:00
|
|
|
zeus::CVector3f hintDir2 = hint->GetTransform().basis[1];
|
|
|
|
hintDir2.z() = 0.f;
|
|
|
|
if (hintDir2.canBeNormalized()) {
|
|
|
|
hintDir2.normalize();
|
|
|
|
float hintCamAzimuth = std::fabs(std::acos(zeus::clamp(-1.f, hintDir2.dot(newHintToCamDir), 1.f)));
|
2020-05-07 15:59:29 +00:00
|
|
|
const float hintCamAzimuthRange =
|
|
|
|
x2b0_clampedAzimuthFromHintDir.GetValue(GetInVar(x2b0_clampedAzimuthFromHintDir));
|
2019-02-10 04:41:35 +00:00
|
|
|
hintCamAzimuth = zeus::clamp(-hintCamAzimuthRange, hintCamAzimuth, hintCamAzimuthRange);
|
2020-05-07 15:59:29 +00:00
|
|
|
if (hintDir2.cross(newHintToCamDir).z() < 0.f) {
|
2019-02-10 04:41:35 +00:00
|
|
|
hintCamAzimuth = -hintCamAzimuth;
|
2020-05-07 15:59:29 +00:00
|
|
|
}
|
2019-02-10 04:41:35 +00:00
|
|
|
zeus::CQuaternion hintCamAzimuthQuat;
|
|
|
|
hintCamAzimuthQuat.rotateZ(hintCamAzimuth);
|
|
|
|
newHintToCamDir = hintCamAzimuthQuat.transform(hintDir2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
newCamPos = hintPos + newHintToCamDir * newHintToCamDist;
|
2020-05-07 15:59:29 +00:00
|
|
|
if ((x188_flags & 0x80) != 0) {
|
2019-02-10 04:41:35 +00:00
|
|
|
newCamPos.z() = ballPos.z() + x298_camPosZOffset.GetValue(GetInVar(x298_camPosZOffset));
|
2020-05-07 15:59:29 +00:00
|
|
|
} else {
|
2019-02-10 04:41:35 +00:00
|
|
|
newCamPos.z() = hintPos.z() + x298_camPosZOffset.GetValue(GetInVar(x298_camPosZOffset));
|
2020-05-07 15:59:29 +00:00
|
|
|
}
|
|
|
|
newCamPos.z() =
|
|
|
|
zeus::clamp(x1b8_hintToCamVOffMin, newCamPos.z() - hintPos.z(), x1bc_hintToCamVOffMax) + hintPos.z();
|
2019-02-10 04:41:35 +00:00
|
|
|
|
|
|
|
float lookPosZ;
|
2020-05-07 15:59:29 +00:00
|
|
|
if ((x188_flags & 0x200) != 0) {
|
2019-02-10 04:41:35 +00:00
|
|
|
lookPosZ = ballPos.z() + x280_lookPosZOffset.GetValue(GetInVar(x280_lookPosZOffset));
|
2020-05-07 15:59:29 +00:00
|
|
|
} else {
|
2019-02-10 04:41:35 +00:00
|
|
|
lookPosZ = hintPos.z() + x280_lookPosZOffset.GetValue(GetInVar(x280_lookPosZOffset));
|
2020-05-07 15:59:29 +00:00
|
|
|
}
|
2019-02-10 04:41:35 +00:00
|
|
|
|
|
|
|
zeus::CVector3f newLookDelta(lookAheadPos - newCamPos.toVec2f(), lookPosZ - newCamPos.z());
|
|
|
|
zeus::CVector3f newLookDirFlat = newLookDelta;
|
|
|
|
newLookDirFlat.z() = 0.f;
|
|
|
|
if (newLookDirFlat.canBeNormalized()) {
|
2020-05-07 15:59:29 +00:00
|
|
|
const float newLookDistFlat = newLookDirFlat.magnitude();
|
2019-02-10 04:41:35 +00:00
|
|
|
newLookDirFlat.normalize();
|
|
|
|
float camLookRelAzimuth = -x268_camLookRelAzimuth.GetValue(GetInVar(x268_camLookRelAzimuth));
|
|
|
|
zeus::CVector3f newHintToCamDirFlat = newCamPos - hintPos;
|
|
|
|
newHintToCamDirFlat.z() = 0.f;
|
2020-05-07 15:59:29 +00:00
|
|
|
if (newHintToCamDirFlat.canBeNormalized()) {
|
2019-02-10 04:41:35 +00:00
|
|
|
newHintToCamDirFlat.normalize();
|
2020-05-07 15:59:29 +00:00
|
|
|
} else {
|
2019-02-24 07:15:54 +00:00
|
|
|
newHintToCamDirFlat = zeus::skForward;
|
2020-05-07 15:59:29 +00:00
|
|
|
}
|
|
|
|
if (newHintToCamDirFlat.cross(hintToBallDir).z() >= 0.f) {
|
2019-02-10 04:41:35 +00:00
|
|
|
camLookRelAzimuth = -camLookRelAzimuth;
|
2020-05-07 15:59:29 +00:00
|
|
|
}
|
|
|
|
if ((x188_flags & 0x1000) != 0) {
|
|
|
|
camLookRelAzimuth *= zeus::clamp(
|
|
|
|
-1.f,
|
|
|
|
std::acos(std::fabs(zeus::clamp(-1.f, hintToBallDir.dot(newHintToCamDirFlat), 1.f))) / zeus::degToRad(10.f),
|
|
|
|
1.f);
|
|
|
|
}
|
2019-02-10 04:41:35 +00:00
|
|
|
zeus::CQuaternion azimuthQuat;
|
|
|
|
azimuthQuat.rotateZ(camLookRelAzimuth);
|
|
|
|
lookAheadPos = azimuthQuat.transform(newLookDirFlat).toVec2f() * std::cos(camLookRelAzimuth) * newLookDistFlat +
|
2021-06-07 19:29:18 +00:00
|
|
|
newCamPos.toVec2f();
|
2019-02-10 04:41:35 +00:00
|
|
|
}
|
|
|
|
newLookDelta = zeus::CVector3f(lookAheadPos, lookPosZ) - newCamPos;
|
2020-05-07 15:59:29 +00:00
|
|
|
if ((x188_flags & 0x1) != 0) {
|
2019-02-10 04:41:35 +00:00
|
|
|
newLookDelta = zeus::CVector3f(hintPos.toVec2f() - newCamPos.toVec2f(), newLookDelta.z());
|
2020-05-07 15:59:29 +00:00
|
|
|
}
|
|
|
|
if ((x188_flags & 0x2) != 0) {
|
2019-02-10 04:41:35 +00:00
|
|
|
newLookDelta = lookAheadPos - hintPos.toVec2f();
|
2020-05-07 15:59:29 +00:00
|
|
|
}
|
|
|
|
if (newLookDelta.canBeNormalized()) {
|
2019-02-10 04:41:35 +00:00
|
|
|
SetTransform(zeus::lookAt(newCamPos, newCamPos + newLookDelta.normalized()));
|
2020-05-07 15:59:29 +00:00
|
|
|
}
|
2019-02-10 04:41:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-09 17:28:20 +00:00
|
|
|
void CScriptSpindleCamera::Render(CStateManager&) {
|
2019-02-10 04:41:35 +00:00
|
|
|
// Empty
|
|
|
|
}
|
2018-10-11 22:57:05 +00:00
|
|
|
|
2021-04-10 08:42:06 +00:00
|
|
|
} // namespace metaforce
|