metaforce/Runtime/Camera/CGameCamera.cpp

160 lines
4.6 KiB
C++
Raw Normal View History

2016-04-24 04:03:30 +00:00
#include "CGameCamera.hpp"
2016-09-14 05:45:46 +00:00
#include "CStateManager.hpp"
#include "Camera/CCameraManager.hpp"
2016-04-24 04:03:30 +00:00
#include "World/CActorParameters.hpp"
namespace urde
{
2017-11-13 06:19:18 +00:00
CGameCamera::CGameCamera(TUniqueId uid, bool active, std::string_view name, const CEntityInfo& info,
2017-10-08 02:58:13 +00:00
const zeus::CTransform& xf, float fovy, float znear, float zfar, float aspect,
TUniqueId watchedId, bool disableInput, u32 controllerIdx)
2017-12-19 03:05:50 +00:00
: CActor(uid, active, name, info, xf, CModelData::CModelDataNull(), CMaterialList(EMaterialTypes::NoStepLogic),
2016-09-14 05:45:46 +00:00
CActorParameters::None(), kInvalidUniqueId)
2017-10-08 02:58:13 +00:00
, xe8_watchedObject(watchedId)
2018-06-02 06:06:25 +00:00
, x12c_origXf(xf)
2016-10-31 22:56:44 +00:00
, x15c_currentFov(fovy)
2016-09-14 05:45:46 +00:00
, x160_znear(znear)
, x164_zfar(zfar)
, x168_aspect(aspect)
2017-03-24 05:30:16 +00:00
, x16c_controllerIdx(controllerIdx)
2016-09-14 05:45:46 +00:00
, x170_24_perspDirty(true)
, x170_25_disablesInput(disableInput)
2018-06-02 06:06:25 +00:00
, x180_perspInterpStartFov(fovy)
, x184_perspInterpEndFov(fovy)
2016-04-24 04:03:30 +00:00
{
2016-09-14 05:45:46 +00:00
2018-05-18 04:16:33 +00:00
xe7_29_drawEnabled = false;
2016-09-14 05:45:46 +00:00
}
void CGameCamera::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr)
{
if (msg == EScriptObjectMessage::AddSplashInhabitant)
2016-09-14 05:45:46 +00:00
{
mgr.GetCameraManager()->SetInsideFluid(true, uid);
return;
}
2017-06-12 04:23:34 +00:00
else if (msg == EScriptObjectMessage::RemoveSplashInhabitant)
2016-09-14 05:45:46 +00:00
{
mgr.GetCameraManager()->SetInsideFluid(false, kInvalidUniqueId);
return;
}
CActor::AcceptScriptMsg(msg, uid, mgr);
}
void CGameCamera::SetActive(bool active)
{
CActor::SetActive(active);
2018-05-18 04:16:33 +00:00
xe7_29_drawEnabled = false;
2016-09-14 05:45:46 +00:00
}
zeus::CMatrix4f CGameCamera::GetPerspectiveMatrix() const
{
if (x170_24_perspDirty)
{
const_cast<CGameCamera*>(this)->xec_perspectiveMatrix =
2016-10-31 22:56:44 +00:00
CGraphics::CalculatePerspectiveMatrix(x15c_currentFov, x168_aspect, x160_znear, x164_zfar, false);
2016-09-14 05:45:46 +00:00
const_cast<CGameCamera*>(this)->x170_24_perspDirty = false;
}
return xec_perspectiveMatrix;
}
zeus::CVector3f CGameCamera::ConvertToScreenSpace(const zeus::CVector3f& v) const
{
zeus::CVector3f rVec = x34_transform.transposeRotate(v - x34_transform.origin);
if (rVec.isZero())
2016-09-14 05:45:46 +00:00
return {-1.f, -1.f, 1.f};
rVec = zeus::CVector3f(rVec.x, rVec.z, -rVec.y);
2016-09-14 05:45:46 +00:00
zeus::CMatrix4f mtx = GetPerspectiveMatrix();
return mtx.multiplyOneOverW(rVec);
}
2018-01-07 05:19:49 +00:00
zeus::CTransform CGameCamera::ValidateCameraTransform(const zeus::CTransform& newXf, const zeus::CTransform& oldXf)
2016-09-14 05:45:46 +00:00
{
2018-01-07 05:19:49 +00:00
zeus::CTransform xfCpy(newXf);
if (!zeus::close_enough(newXf.rightVector().magnitude(), 1.f) ||
!zeus::close_enough(newXf.frontVector().magnitude(), 1.f) ||
!zeus::close_enough(newXf.upVector().magnitude(), 1.f))
2016-09-14 05:45:46 +00:00
xfCpy.orthonormalize();
2018-01-07 05:19:49 +00:00
float f2 = zeus::clamp(-1.f, newXf.frontVector().dot(zeus::CVector3f::skUp), 1.f);
2016-09-14 05:45:46 +00:00
if (std::fabs(f2) > 0.999f)
2018-01-07 05:19:49 +00:00
xfCpy = oldXf;
2016-09-14 05:45:46 +00:00
if (xfCpy.upVector().z < -0.2f)
xfCpy = zeus::CQuaternion::fromAxisAngle(xfCpy.frontVector(), M_PIF).toTransform() * xfCpy;
2018-01-07 05:19:49 +00:00
if (!zeus::close_enough(xfCpy.rightVector().z, 0.f) &&
!zeus::close_enough(xfCpy.upVector().z, 0.f))
2016-09-14 05:45:46 +00:00
{
if (xfCpy.frontVector().canBeNormalized())
2018-01-07 05:19:49 +00:00
xfCpy = zeus::lookAt(zeus::CVector3f::skZero, xfCpy.frontVector());
2016-09-14 05:45:46 +00:00
else
2018-01-07 05:19:49 +00:00
xfCpy = oldXf;
2016-09-14 05:45:46 +00:00
}
2018-01-07 05:19:49 +00:00
xfCpy.origin = newXf.origin;
2016-09-14 05:45:46 +00:00
return xfCpy;
2016-04-24 04:03:30 +00:00
}
2016-10-31 22:56:44 +00:00
void CGameCamera::UpdatePerspective(float dt)
{
2017-11-24 08:23:28 +00:00
if (x174_delayTime > 0.f)
{
2017-11-24 08:23:28 +00:00
x174_delayTime -= dt;
return;
}
2018-06-02 06:06:25 +00:00
if (x178_perspInterpRemTime <= 0.f)
return;
2018-06-02 06:06:25 +00:00
x178_perspInterpRemTime -= dt;
if (x178_perspInterpRemTime <= 0.f)
{
2018-06-02 06:06:25 +00:00
x15c_currentFov = x184_perspInterpEndFov;
x170_24_perspDirty = true;
}
else
{
2018-06-02 06:06:25 +00:00
x15c_currentFov = zeus::clamp(0.f, (x178_perspInterpRemTime / x17c_perspInterpDur), 1.f) *
(x180_perspInterpStartFov - x184_perspInterpEndFov) + x184_perspInterpEndFov;
x170_24_perspDirty = true;
}
}
2017-11-24 08:23:28 +00:00
void CGameCamera::SetFovInterpolation(float start, float fov, float time, float delayTime)
{
2017-08-18 01:30:15 +00:00
if (time < 0.f)
{
2016-10-31 22:56:44 +00:00
x15c_currentFov = fov;
x170_24_perspDirty = true;
2018-06-02 06:06:25 +00:00
x184_perspInterpEndFov = fov;
x178_perspInterpRemTime = x174_delayTime = 0.f;
}
else
{
2017-11-24 08:23:28 +00:00
x174_delayTime = std::max(0.f, delayTime);
2018-06-02 06:06:25 +00:00
x17c_perspInterpDur = time;
x178_perspInterpRemTime = time;
x180_perspInterpStartFov = start;
x184_perspInterpEndFov = fov;
2017-08-18 01:30:15 +00:00
x15c_currentFov = start;
x170_24_perspDirty = true;
}
}
2017-10-07 05:32:11 +00:00
void CGameCamera::SkipFovInterpolation()
{
2018-06-02 06:06:25 +00:00
if (x178_perspInterpRemTime > 0)
{
2018-06-02 06:06:25 +00:00
x15c_currentFov = x184_perspInterpEndFov;
x170_24_perspDirty = true;
}
2018-06-02 06:06:25 +00:00
x178_perspInterpRemTime = x174_delayTime = 0.f;
}
2016-04-24 04:03:30 +00:00
}