metaforce/Runtime/Camera/CFirstPersonCamera.cpp

273 lines
10 KiB
C++
Raw Normal View History

#include "CFirstPersonCamera.hpp"
#include "GameGlobalObjects.hpp"
2016-08-23 03:12:50 +00:00
#include "Character/CCharLayoutInfo.hpp"
#include "CStateManager.hpp"
#include "World/CPlayer.hpp"
2016-09-16 22:21:19 +00:00
#include "World/CPlayerCameraBob.hpp"
#include "World/CScriptGrapplePoint.hpp"
2017-02-12 04:43:33 +00:00
#include "Particle/CGenDescription.hpp"
2017-01-15 03:07:01 +00:00
#include "TCastTo.hpp"
#include <math.h>
namespace urde
{
2016-09-16 22:21:19 +00:00
CFirstPersonCamera::CFirstPersonCamera(TUniqueId uid, const zeus::CTransform& xf, TUniqueId watchedObj, float f1,
float fov, float nearz, float farz, float aspect)
: CGameCamera(uid, true, "First Person Camera", CEntityInfo(kInvalidAreaId, CEntity::NullConnectionList), xf, fov,
nearz, farz, aspect, watchedObj, false, 0)
{
}
2017-03-24 05:30:16 +00:00
void CFirstPersonCamera::Accept(IVisitor& visitor)
{
visitor.Visit(this);
}
2017-02-18 02:19:50 +00:00
void CFirstPersonCamera::PreThink(float, CStateManager&) {}
void CFirstPersonCamera::Think(float, CStateManager&)
{
}
2016-09-16 22:21:19 +00:00
void CFirstPersonCamera::ProcessInput(const CFinalInput&, CStateManager& mgr) {}
2016-09-16 22:21:19 +00:00
void CFirstPersonCamera::Reset(const zeus::CTransform&, CStateManager& mgr) {}
2017-02-18 02:19:50 +00:00
void CFirstPersonCamera::SkipCinematic()
{
x1c8_ = zeus::CVector3f::skZero;
x1d4_ = 0.f;
}
2016-09-16 22:21:19 +00:00
void CFirstPersonCamera::CalculateGunFollowOrientationAndTransform(zeus::CTransform& gunXf, zeus::CQuaternion& gunQ,
float dt, zeus::CVector3f& rVec)
{
2016-09-16 22:29:38 +00:00
zeus::CVector3f gunFrontVec = x190_gunFollowXf.frontVector();
gunFrontVec.z = 0.f;
2016-09-16 22:21:19 +00:00
2016-09-16 22:29:38 +00:00
if (gunFrontVec.canBeNormalized())
gunFrontVec.normalize();
2016-09-16 22:21:19 +00:00
zeus::CVector3f rVecNoZ = rVec;
rVecNoZ.z = 0.f;
if (rVecNoZ.canBeNormalized())
rVecNoZ.normalize();
2016-09-16 22:29:38 +00:00
gunXf = zeus::CQuaternion::lookAt(rVecNoZ, gunFrontVec, zeus::CRelAngle::FromDegrees(360.f)).toTransform() *
2016-09-16 22:21:19 +00:00
gunXf.getRotation();
2016-09-16 22:29:38 +00:00
zeus::CVector3f newgunFront = gunXf.frontVector();
2016-09-16 22:21:19 +00:00
2016-09-16 22:29:38 +00:00
if (newgunFront.canBeNormalized())
newgunFront.normalize();
2016-09-16 22:21:19 +00:00
2016-09-16 22:29:38 +00:00
float angle = newgunFront.dot(rVec);
2016-09-16 22:21:19 +00:00
if (std::fabs(angle) > 0.f)
angle = (angle > -0.f ? -1.f : 1.f);
2016-09-16 22:29:38 +00:00
gunQ = zeus::CQuaternion::lookAt(rVec, newgunFront, zeus::clamp(0.f, std::acos(angle) / dt, 1.f));
}
2016-09-16 22:21:19 +00:00
void CFirstPersonCamera::UpdateTransform(CStateManager& mgr, float dt)
{
2017-01-15 03:59:37 +00:00
TCastToPtr<CPlayer> player(mgr.ObjectById(GetWatchedObject()));
if (!player)
{
x34_transform = zeus::CTransform::Identity();
xe4_27_ = true;
xe4_28_ = true;
xe4_29_ = true;
return;
}
zeus::CTransform playerXf = player->GetTransform();
2016-09-16 22:21:19 +00:00
zeus::CVector3f rVec =
playerXf.rotate({0.f, std::min(std::fabs(std::cos(x1c0_)), 1.0f), std::min(std::fabs(std::sin(x1c0_)), 1.0f)});
2017-04-07 05:35:09 +00:00
if (player->x3dc_inFreeLook)
2016-09-16 22:21:19 +00:00
{
2017-07-17 03:04:14 +00:00
float angle = player->x3ec_freeLookPitchAngle;
2017-07-31 05:19:05 +00:00
if (std::fabs(player->x3ec_freeLookPitchAngle) > (g_tweakPlayer->GetVerticalFreeLookAngleVel() - std::fabs(x1c0_)))
2017-07-17 03:04:14 +00:00
angle = (player->x3ec_freeLookPitchAngle > -0.f ? -1.f : 1.f);
2016-09-16 22:21:19 +00:00
zeus::CVector3f vec;
vec.z = std::sin(angle);
vec.y = std::cos(-player->x3e4_) * std::cos(angle);
vec.x = std::sin(-player->x3e4_) * std::cos(angle);
2016-10-31 22:56:44 +00:00
if (g_tweakPlayer->GetX228_24() && !zeus::close_enough(vec, zeus::CVector3f::skZero))
2016-09-16 22:21:19 +00:00
vec.normalize();
rVec = zeus::CQuaternion::lookAt({0.f, 1.f, 0.f}, rVec, zeus::CRelAngle::FromDegrees(360.f)).transform(vec);
}
zeus::CVector3f eyePos = player->GetEyePosition();
if (x1d4_ > 0.f)
{
eyePos += zeus::clamp(0.f, 0.5f * x1d4_, 1.f) * x1c8_;
player->GetCameraBob()->ResetCameraBobTime();
player->GetCameraBob()->SetCameraBobTransform(zeus::CTransform::Identity());
}
2017-04-03 01:39:23 +00:00
if (player->GetOrbitState() == CPlayer::EPlayerOrbitState::Four ||
player->GetOrbitState() == CPlayer::EPlayerOrbitState::One)
2016-09-16 22:21:19 +00:00
{
2017-06-12 04:23:34 +00:00
const CActor* act = TCastToConstPtr<CActor>(mgr.GetObjectById(player->x310_orbitTargetId));
2016-12-29 21:38:59 +00:00
if (act && act->GetMaterialList().Intersection(CMaterialList(EMaterialTypes::Lava)) != 0)
2016-09-16 22:21:19 +00:00
{
2017-06-12 04:23:34 +00:00
zeus::CVector3f v = player->x314_orbitPoint.y - eyePos;
2016-09-16 22:21:19 +00:00
if (v.canBeNormalized())
v.normalize();
rVec = v;
}
}
2017-04-03 01:39:23 +00:00
else if (player->GetOrbitState() == CPlayer::EPlayerOrbitState::Zero &&
player->GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphed &&
2017-04-07 05:35:09 +00:00
player->x3dc_inFreeLook && x1c4_pitchId == kInvalidUniqueId)
2016-09-16 22:21:19 +00:00
{
2017-07-17 03:04:14 +00:00
if (player->x294_jumpCameraPitchTimer > 0.f)
2016-09-16 22:21:19 +00:00
{
2017-07-17 03:04:14 +00:00
float angle = zeus::clamp(0.f, (player->x294_jumpCameraPitchTimer - g_tweakPlayer->GetX288()) / g_tweakPlayer->GetX28c(), 1.f) *
2016-10-31 22:56:44 +00:00
g_tweakPlayer->GetX290();
2016-09-16 22:21:19 +00:00
angle += x1c0_;
rVec.x = 0.f;
rVec.y = std::cos(angle);
rVec.z = -std::sin(angle);
rVec = playerXf.rotate(rVec);
}
2017-07-17 03:04:14 +00:00
else if (player->x29c_spaceJumpCameraPitchTimer > 0.f)
2016-09-16 22:21:19 +00:00
{
2017-07-17 03:04:14 +00:00
float angle = zeus::clamp(0.f, (player->x29c_spaceJumpCameraPitchTimer - g_tweakPlayer->GetX294()) / g_tweakPlayer->GetX298(), 1.f) *
2016-10-31 22:56:44 +00:00
g_tweakPlayer->GetX29C();
2016-09-16 22:21:19 +00:00
rVec.x = 0.f;
rVec.y = std::cos(angle);
rVec.z = -std::sin(angle);
rVec = playerXf.rotate(rVec);
}
}
if (rVec.canBeNormalized())
rVec.normalize();
zeus::CTransform gunXf = x190_gunFollowXf;
zeus::CQuaternion qGun = zeus::CQuaternion::skNoRotation;
2017-04-07 05:35:09 +00:00
if (player->x3dc_inFreeLook)
{
2017-04-03 01:39:23 +00:00
if (player->GetOrbitState() == CPlayer::EPlayerOrbitState::Four ||
player->GetOrbitState() == CPlayer::EPlayerOrbitState::One)
2016-09-16 22:21:19 +00:00
{
2016-09-16 22:29:38 +00:00
zeus::CVector3f gunFrontVec = gunXf.frontVector();
2016-09-16 22:21:19 +00:00
2016-09-16 22:29:38 +00:00
if (gunFrontVec.canBeNormalized())
gunFrontVec.normalize();
2016-09-16 22:21:19 +00:00
2016-10-31 22:56:44 +00:00
float scaledDt = (dt * g_tweakPlayer->GetX184());
2016-09-16 22:29:38 +00:00
float angle = gunFrontVec.dot(rVec);
2016-09-16 22:21:19 +00:00
if (std::fabs(angle) > 1.f)
angle = (angle > -0.f ? -1.f : 1.f);
float clampedAngle = zeus::clamp(0.f, std::acos(angle) / scaledDt, 1.f);
2017-07-30 01:06:06 +00:00
if (angle > 0.999f && x18c_ && !player->x374_orbitLockEstablished)
2016-09-16 22:29:38 +00:00
qGun = zeus::CQuaternion::lookAt(rVec, gunFrontVec, zeus::CRelAngle::FromDegrees(360.f));
2016-09-16 22:21:19 +00:00
else
2016-09-16 22:29:38 +00:00
qGun = zeus::CQuaternion::lookAt(rVec, gunFrontVec, scaledDt * clampedAngle);
2016-09-16 22:21:19 +00:00
const CScriptGrapplePoint* gPoint =
2017-06-12 04:23:34 +00:00
TCastToConstPtr<CScriptGrapplePoint>(mgr.GetObjectById(player->x310_orbitTargetId));
2017-07-17 03:04:14 +00:00
if (gPoint && player->x29c_spaceJumpCameraPitchTimer > 0.f)
2016-09-16 22:21:19 +00:00
{
2016-09-16 22:29:38 +00:00
gunFrontVec = x190_gunFollowXf.frontVector();
if (gunFrontVec.canBeNormalized())
gunFrontVec.normalize();
2016-09-16 22:21:19 +00:00
zeus::CVector3f rVecCpy = rVec;
if (rVecCpy.canBeNormalized())
rVecCpy.normalize();
2017-01-15 03:59:37 +00:00
gunXf =
zeus::CQuaternion::lookAt(rVecCpy, gunFrontVec, zeus::CRelAngle::FromDegrees(360.f)).toTransform() *
x190_gunFollowXf.getRotation();
2016-09-16 22:21:19 +00:00
2016-09-16 22:29:38 +00:00
gunFrontVec = gunXf.frontVector();
if (gunFrontVec.canBeNormalized())
gunFrontVec.normalize();
2016-09-16 22:21:19 +00:00
/* BUG: This is exactly what the runtime is doing, should we restore the intended behavior? */
2016-09-16 22:29:38 +00:00
float angle = gunFrontVec.dot(rVec);
2016-10-31 22:56:44 +00:00
float sdt = dt * g_tweakPlayer->GetX2B0();
2016-09-16 22:21:19 +00:00
if (std::fabs(angle) > 1.0f)
angle = (angle > -0.f ? -1.f : 1.f);
angle = zeus::clamp(0.f, std::acos(angle) / sdt, 1.f);
2016-09-16 22:29:38 +00:00
qGun = zeus::CQuaternion::lookAt(rVec, gunFrontVec, zeus::CRelAngle::FromDegrees(360.f));
2016-09-16 22:21:19 +00:00
}
}
2017-04-03 01:39:23 +00:00
else if (player->GetOrbitState() == CPlayer::EPlayerOrbitState::Two ||
player->GetOrbitState() == CPlayer::EPlayerOrbitState::Three)
2016-09-16 22:21:19 +00:00
{
2016-10-31 22:56:44 +00:00
dt *= g_tweakPlayer->GetX184();
2016-09-16 22:21:19 +00:00
CalculateGunFollowOrientationAndTransform(gunXf, qGun, dt, rVec);
}
2017-04-03 01:39:23 +00:00
else if (player->GetOrbitState() == CPlayer::EPlayerOrbitState::Five)
2016-09-16 22:21:19 +00:00
{
2016-10-31 22:56:44 +00:00
dt *= g_tweakPlayer->GetX2B0();
2016-09-16 22:21:19 +00:00
CalculateGunFollowOrientationAndTransform(gunXf, qGun, dt, rVec);
}
else
{
2016-10-31 22:56:44 +00:00
dt *= g_tweakPlayer->GetX280();
2016-09-16 22:21:19 +00:00
CalculateGunFollowOrientationAndTransform(gunXf, qGun, dt, rVec);
}
}
2016-09-16 22:21:19 +00:00
else
{
2016-09-16 22:29:38 +00:00
zeus::CVector3f gunFront = x190_gunFollowXf.frontVector();
if (gunFront.canBeNormalized())
gunFront.normalize();
2016-09-16 22:21:19 +00:00
zeus::CVector3f rVecCpy = rVec;
if (rVecCpy.canBeNormalized())
rVecCpy.normalize();
2016-09-16 22:29:38 +00:00
gunXf = zeus::CQuaternion::lookAt(rVecCpy, gunFront, zeus::CRelAngle::FromDegrees(360.f)).toTransform() *
2016-09-16 22:21:19 +00:00
x190_gunFollowXf.getRotation();
2016-09-16 22:29:38 +00:00
gunFront = gunXf.frontVector();
if (gunFront.canBeNormalized())
gunFront.normalize();
2016-09-16 22:21:19 +00:00
2016-09-16 22:29:38 +00:00
float angle = gunFront.dot(rVec);
2016-09-16 22:21:19 +00:00
if (std::fabs(angle) > 1.f)
angle = (angle > -0.f ? -1.f : 1.f);
2016-10-31 22:56:44 +00:00
float sdt = dt * g_tweakPlayer->GetX138();
2016-09-16 22:21:19 +00:00
qGun = zeus::CQuaternion::lookAt(
2016-10-31 22:56:44 +00:00
rVec, gunFront, sdt * zeus::clamp(0.f, g_tweakPlayer->GetX14C() * (std::acos(angle) / sdt), 1.f));
2016-09-16 22:21:19 +00:00
}
zeus::CTransform bobXf = player->GetCameraBob()->GetCameraBobTransformation();
2017-04-03 01:39:23 +00:00
if (player->GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed ||
player->GetOrbitState() == CPlayer::EPlayerOrbitState::Five ||
2017-07-23 23:45:04 +00:00
player->GetGrappleState() == CPlayer::EGrappleState::None ||
2017-07-17 03:04:14 +00:00
mgr.GetGameState() == CStateManager::EGameState::SoftPaused ||
2017-04-03 01:39:23 +00:00
mgr.GetCameraManager()->IsInCinematicCamera())
2016-09-16 22:21:19 +00:00
{
bobXf = zeus::CTransform::Identity();
player->GetCameraBob()->SetCameraBobTransform(bobXf);
}
x190_gunFollowXf = qGun.toTransform() * gunXf;
x34_transform = x190_gunFollowXf * bobXf.getRotation();
xe4_27_ = true;
xe4_28_ = true;
xe4_28_ = true;
xe4_29_ = true;
2016-09-16 22:21:19 +00:00
CActor::SetTranslation(x190_gunFollowXf.origin + player->GetTransform().rotate(bobXf.origin));
x190_gunFollowXf.orthonormalize();
}
2016-09-16 22:21:19 +00:00
void CFirstPersonCamera::UpdateElevation(CStateManager&) {}
}