This commit is contained in:
Phillip Stephens 2017-10-14 22:44:29 -07:00
commit 76acf45e96
14 changed files with 1355 additions and 86 deletions

File diff suppressed because it is too large Load Diff

View File

@ -72,7 +72,7 @@ private:
zeus::CVector3f x6c_;
zeus::CVector3f x78_;
zeus::CVector3f x84_;
std::vector<zeus::CVector3f> x90_;
std::vector<zeus::CVector3f> x90_bezPoints;
};
EBallCameraBehaviour x188_behaviour = EBallCameraBehaviour::Zero;
@ -107,9 +107,7 @@ private:
float x1ac_ = 1.5533431f;
float x1b0_ = 1.5533431f;
zeus::CVector3f x1b4_lookAtOffset;
float x1c0_ = 0.f;
float x1c4_ = 0.f;
float x1c8_ = 0.f;
zeus::CVector3f x1c0_;
zeus::CVector3f x1cc_;
zeus::CVector3f x1d8_;
zeus::CTransform x1e4_;
@ -124,12 +122,12 @@ private:
zeus::CVector3f x2a0_ = zeus::CVector3f::skUp;
zeus::CVector3f x2ac_ = zeus::CVector3f::skUp;
zeus::CVector3f x2b8_ = zeus::CVector3f::skUp;
u32 x2c4_ = 0;
u32 x2c8_ = 0;
u32 x2cc_ = 0;
u32 x2d0_ = 0;
u32 x2d4_ = 0;
u32 x2d8_ = 0;
int x2c4_ = 0;
int x2c8_ = 0;
int x2cc_ = 0;
int x2d0_ = 0;
int x2d4_ = 0;
int x2d8_ = 0;
zeus::CVector3f x2dc_;
float x2e8_ = 0.f;
float x2ec_ = 0.f;
@ -193,7 +191,7 @@ private:
bool ShouldResetSpline(CStateManager& mgr) const;
void UpdatePlayerMovement(float dt, CStateManager& mgr);
void UpdateTransform(const zeus::CVector3f& lookDir, const zeus::CVector3f& pos, float dt, CStateManager& mgr);
zeus::CVector3f ConstrainYawAngle(const CPlayer& player, float angleVel, float maxAngle, float dt,
zeus::CVector3f ConstrainYawAngle(const CPlayer& player, float distance, float yawSpeed, float dt,
CStateManager& mgr) const;
void CheckFailsafe(float dt, CStateManager& mgr);
void UpdateObjectTooCloseId(CStateManager& mgr);
@ -205,16 +203,16 @@ private:
zeus::CVector3f TweenVelocity(const zeus::CVector3f& curVel, const zeus::CVector3f& newVel, float rate, float dt);
zeus::CVector3f MoveCollisionActor(const zeus::CVector3f& pos, float dt, CStateManager& mgr);
void UpdateUsingFreeLook(float dt, CStateManager& mgr);
zeus::CVector3f InterpolateCameraElevation(const zeus::CVector3f& camPos) const;
zeus::CVector3f InterpolateCameraElevation(const zeus::CVector3f& camPos);
zeus::CVector3f CalculateCollidersCentroid(const std::vector<CCameraCollider>& colliderList, int w1) const;
zeus::CVector3f ApplyColliders();
void UpdateColliders(const zeus::CTransform& xf, std::vector<CCameraCollider>& colliderList, int& r6, int r7,
float f1, const rstl::reserved_vector<TUniqueId, 1024>& nearList, float f2,
float f1, const rstl::reserved_vector<TUniqueId, 1024>& nearList, float dt,
CStateManager& mgr);
void AvoidGeometry(const zeus::CTransform& xf, const rstl::reserved_vector<TUniqueId, 1024>& nearList,
float dt, CStateManager& mgr);
void AvoidGeometryFull(const zeus::CTransform& xf, const rstl::reserved_vector<TUniqueId, 1024>& nearList,
float dt, CStateManager& mgr);
zeus::CVector3f AvoidGeometry(const zeus::CTransform& xf, const rstl::reserved_vector<TUniqueId, 1024>& nearList,
float dt, CStateManager& mgr);
zeus::CVector3f AvoidGeometryFull(const zeus::CTransform& xf, const rstl::reserved_vector<TUniqueId, 1024>& nearList,
float dt, CStateManager& mgr);
zeus::CAABox CalculateCollidersBoundingBox(const std::vector<CCameraCollider>& colliderList,
CStateManager& mgr) const;
int CountObscuredColliders(const std::vector<CCameraCollider>& colliderList) const;
@ -222,17 +220,22 @@ private:
void UpdateUsingColliders(float dt, CStateManager& mgr);
void UpdateUsingSpindleCameras(float dt, CStateManager& mgr);
zeus::CVector3f ClampElevationToWater(zeus::CVector3f& pos, CStateManager& mgr) const;
void UpdateTransitionFromBallCamera(CStateManager& mgr);
void UpdateUsingTransitions(float dt, CStateManager& mgr);
zeus::CTransform UpdateCameraPositions(float dt, const zeus::CTransform& oldXf, const zeus::CTransform& newXf);
static zeus::CVector3f GetFailsafeBezierPoint(const std::vector<zeus::CVector3f>& points, float t);
bool CheckFailsafeFromMorphBallState(CStateManager& mgr) const;
bool SplineIntersectTest(CMaterialList& intersectMat, CStateManager& mgr) const;
static bool IsBallNearDoor(const zeus::CVector3f& pos, CStateManager& mgr);
void ActivateFailsafe(float dt, CStateManager& mgr);
void ConstrainElevationAndDistance(float& elevation, float& distance, float f1, CStateManager& mgr);
zeus::CVector3f FindDesiredPosition(float distance, float elevation, const zeus::CVector3f& dir, CStateManager& mgr);
bool ConstrainElevationAndDistance(float& elevation, float& distance, float dt, CStateManager& mgr);
zeus::CVector3f FindDesiredPosition(float distance, float elevation, const zeus::CVector3f& dir,
CStateManager& mgr, bool b);
static bool DetectCollision(const zeus::CVector3f& from, const zeus::CVector3f& to, float margin,
float& d, CStateManager& mgr);
void TeleportColliders(std::vector<CCameraCollider>& colliderList, const zeus::CVector3f& pos);
static bool CheckTransitionLineOfSight(const zeus::CVector3f& eyePos, const zeus::CVector3f& behindPos,
float& eyeToOccDist, float colRadius, CStateManager& mgr);
public:
CBallCamera(TUniqueId uid, TUniqueId watchedId, const zeus::CTransform& xf,
@ -248,7 +251,7 @@ public:
void Think(float dt, CStateManager& mgr);
bool TransitionFromMorphBallState(CStateManager& mgr);
TUniqueId GetTooCloseActorId() const { return x3dc_tooCloseActorId; }
float GetX3E0() const { return x3e0_tooCloseActorDist; }
float GetTooCloseActorDistance() const { return x3e0_tooCloseActorDist; }
void TeleportCamera(const zeus::CVector3f& pos, CStateManager& mgr);
void TeleportCamera(const zeus::CTransform& xf, CStateManager& mgr);
const zeus::CVector3f& GetX1D8() const { return x1d8_; }
@ -258,7 +261,7 @@ public:
void SetX470(float f) { x470_ = f; }
void SetX474(float f) { x474_ = f; }
void ApplyCameraHint(CStateManager& mgr);
void ResetPosition();
void ResetPosition(CStateManager& mgr);
void DoorClosed(TUniqueId doorId);
void DoorClosing(TUniqueId doorId);
};

View File

@ -242,7 +242,7 @@ void CCameraManager::ApplyCameraHint(const CScriptCameraHint& hint, CStateManage
x80_ballCamera->ApplyCameraHint(mgr);
if ((hint.GetHint().GetOverrideFlags() & 0x20) != 0)
x80_ballCamera->ResetPosition();
x80_ballCamera->ResetPosition(mgr);
switch (hint.GetHint().GetBehaviourType())
{

View File

@ -5,7 +5,7 @@
namespace urde
{
CCameraSpline::CCameraSpline(bool b) : x48_(b) {}
CCameraSpline::CCameraSpline(bool b) : x48_closedLoop(b) {}
void CCameraSpline::CalculateKnots(TUniqueId cameraId, const std::vector<SConnection>& connections, CStateManager& mgr)
{
@ -20,19 +20,45 @@ void CCameraSpline::CalculateKnots(TUniqueId cameraId, const std::vector<SConnec
if (lastConn)
{
TCastToPtr<CScriptCameraWaypoint> waypoint = mgr.ObjectById(mgr.GetIdForScript(lastConn->x8_objId));
//if (waypoint)
x14_wpTracker.clear();
x14_wpTracker.reserve(4);
while (waypoint)
{
auto search = std::find_if(x14_wpTracker.begin(), x14_wpTracker.end(),
[&waypoint](const auto& a) { return a == waypoint->GetUniqueId(); });
if (search == x14_wpTracker.end())
{
x14_wpTracker.push_back(waypoint->GetUniqueId());
waypoint = mgr.ObjectById(waypoint->GetRandomNextWaypointId(mgr));
}
}
Reset(x14_wpTracker.size());
x14_wpTracker.clear();
waypoint = mgr.ObjectById(mgr.GetIdForScript(lastConn->x8_objId));
while (waypoint)
{
auto search = std::find_if(x14_wpTracker.begin(), x14_wpTracker.end(),
[&waypoint](const auto& a) { return a == waypoint->GetUniqueId(); });
if (search == x14_wpTracker.end())
{
x14_wpTracker.push_back(waypoint->GetUniqueId());
AddKnot(waypoint->GetTranslation(), waypoint->GetTransform().basis[1]);
waypoint = mgr.ObjectById(waypoint->GetRandomNextWaypointId(mgr));
}
}
}
}
void CCameraSpline::Reset(int size)
{
x4_positions.clear();
x24_.clear();
x24_t.clear();
x34_directions.clear();
if (size != 0)
{
x4_positions.reserve(size);
x24_.reserve(size);
x24_t.reserve(size);
x34_directions.reserve(size);
}
}
@ -50,8 +76,214 @@ void CCameraSpline::SetKnotPosition(int idx, const zeus::CVector3f& pos)
x4_positions[idx] = pos;
}
const zeus::CVector3f& CCameraSpline::GetKnotPosition(int idx) const
{
if (idx >= x4_positions.size())
return zeus::CVector3f::skZero;
return x4_positions[idx];
}
float CCameraSpline::GetKnotT(int idx) const
{
if (idx >= x4_positions.size())
return 0.f;
return x24_t[idx];
}
float CCameraSpline::CalculateSplineLength()
{
float ret = 0.f;
x24_t.clear();
if (x4_positions.size() > 0)
{
zeus::CVector3f prevPoint = x4_positions[0];
float tDiv = 1.f / float(x4_positions.size() - 1);
for (int i=0 ; i<x4_positions.size() ; ++i)
{
float subT = 0.f;
float baseT = i * tDiv;
x24_t.push_back(ret);
while (subT <= tDiv)
{
subT += tDiv * 0.03125f;
zeus::CVector3f nextPoint = GetInterpolatedSplinePointByTime(baseT + subT, 1.f);
zeus::CVector3f delta = nextPoint - prevPoint;
if (delta.canBeNormalized())
{
prevPoint = nextPoint;
ret += delta.magnitude();
}
}
}
x24_t.push_back(ret);
if (x48_closedLoop)
{
zeus::CVector3f delta = x4_positions[0] - x4_positions[x4_positions.size() - 1];
if (delta.canBeNormalized())
ret += delta.magnitude();
}
return ret;
}
return 0.f;
}
bool CCameraSpline::GetSurroundingPoints(int idx, rstl::reserved_vector<zeus::CVector3f, 4>& positions,
rstl::reserved_vector<zeus::CVector3f, 4>& directions) const
{
if (x4_positions.size() <= 3 || idx < 0 || idx >= x4_positions.size())
return false;
if (idx > 0)
{
positions.push_back(x4_positions[idx - 1]);
directions.push_back(x34_directions[idx - 1]);
}
else if (x48_closedLoop)
{
positions.push_back(x4_positions[x4_positions.size() - 1]);
directions.push_back(x34_directions[x4_positions.size() - 1]);
}
else
{
positions.push_back(x4_positions[0] - (x4_positions[1] - x4_positions[0]));
directions.push_back(x34_directions[0]);
}
positions.push_back(x4_positions[idx]);
directions.push_back(x34_directions[idx]);
if (idx + 1 >= x4_positions.size())
{
if (x48_closedLoop)
{
positions.push_back(x4_positions[idx - x4_positions.size()]);
directions.push_back(x34_directions[idx - x4_positions.size()]);
}
else
{
positions.push_back(x4_positions[x4_positions.size() - 1] -
(x4_positions[x4_positions.size() - 2] - x4_positions[x4_positions.size() - 1]));
directions.push_back(x34_directions[x4_positions.size() - 1]);
}
}
else
{
positions.push_back(x4_positions[idx + 1]);
directions.push_back(x34_directions[idx + 1]);
}
if (idx + 2 >= x4_positions.size())
{
if (x48_closedLoop)
{
positions.push_back(x4_positions[idx + 2 - x4_positions.size()]);
directions.push_back(x34_directions[idx + 2 - x4_positions.size()]);
}
else
{
positions.push_back(x4_positions[x4_positions.size() - 1] -
(x4_positions[x4_positions.size() - 2] - x4_positions[x4_positions.size() - 1]));
directions.push_back(x34_directions[x4_positions.size() - 1]);
}
}
else
{
positions.push_back(x4_positions[idx + 2]);
directions.push_back(x34_directions[idx + 2]);
}
return true;
}
zeus::CTransform CCameraSpline::GetInterpolatedSplinePointByLength(float pos) const
{
if (x4_positions.empty())
return zeus::CTransform();
int baseIdx = 0;
int i;
for (i=1 ; i<x4_positions.size() ; ++i)
{
if (x24_t[i] > pos)
{
baseIdx = i - 1;
break;
}
}
if (i == x4_positions.size())
baseIdx = i - 1;
if (pos < 0.f)
baseIdx = 0;
if (pos >= x44_length)
{
if (x48_closedLoop)
{
pos -= x44_length;
baseIdx = 0;
}
else
{
baseIdx = x4_positions.size() - 2;
pos = x44_length;
}
}
float range;
if (baseIdx == x4_positions.size() - 1)
{
if (x48_closedLoop)
range = x44_length - x24_t[baseIdx];
else
range = x44_length - x24_t[x4_positions.size() - 2];
}
else
{
range = x24_t[baseIdx + 1] - x24_t[baseIdx];
}
float t = zeus::clamp(0.f, (pos - x24_t[baseIdx]) / range, 1.f);
rstl::reserved_vector<zeus::CVector3f, 4> positions;
rstl::reserved_vector<zeus::CVector3f, 4> directions;
if (GetSurroundingPoints(baseIdx, positions, directions))
{
float f1 = zeus::clamp(-1.f, directions[1].dot(directions[2]), 1.f);
if (f1 >= 1.f)
{
zeus::CTransform ret = zeus::lookAt(zeus::CVector3f::skZero, directions[2]);
ret.origin = zeus::getCatmullRomSplinePoint(positions[0], positions[1], positions[2], positions[3], t);
return ret;
}
else
{
zeus::CTransform ret = zeus::lookAt(zeus::CVector3f::skZero,
zeus::CQuaternion::lookAt(directions[1], directions[2], std::acos(f1) * t).transform(directions[1]));
ret.origin = zeus::getCatmullRomSplinePoint(positions[0], positions[1], positions[2], positions[3], t);
return ret;
}
}
return zeus::CTransform();
}
zeus::CVector3f CCameraSpline::GetInterpolatedSplinePointByTime(float time, float range) const
{
if (x4_positions.empty())
return {};
rstl::reserved_vector<zeus::CVector3f, 4> positions;
rstl::reserved_vector<zeus::CVector3f, 4> directions;
float rangeFac = range / float(x4_positions.size() - 1);
int baseIdx = std::min(int(x4_positions.size() - 1), int(time / rangeFac));
if (GetSurroundingPoints(baseIdx, positions, directions))
return zeus::getCatmullRomSplinePoint(positions[0], positions[1], positions[2], positions[3],
(time - float(baseIdx) * rangeFac) / rangeFac);
return {};
}
}

View File

@ -10,11 +10,13 @@ class CCameraSpline
{
friend class CBallCamera;
std::vector<zeus::CVector3f> x4_positions;
std::vector<TUniqueId> x14_;
std::vector<float> x24_;
std::vector<TUniqueId> x14_wpTracker;
std::vector<float> x24_t;
std::vector<zeus::CVector3f> x34_directions;
float x44_ = 0.f;
bool x48_ = false;
float x44_length = 0.f;
bool x48_closedLoop = false;
bool GetSurroundingPoints(int idx, rstl::reserved_vector<zeus::CVector3f, 4>& positions,
rstl::reserved_vector<zeus::CVector3f, 4>& directions) const;
public:
CCameraSpline(bool);
void CalculateKnots(TUniqueId, const std::vector<SConnection>&, CStateManager&);
@ -22,7 +24,12 @@ public:
void Reset(int size);
void AddKnot(const zeus::CVector3f& pos, const zeus::CVector3f& dir);
void SetKnotPosition(int idx, const zeus::CVector3f& pos);
const zeus::CVector3f& GetKnotPosition(int idx) const;
float GetKnotT(int idx) const;
float CalculateSplineLength();
void UpdateSplineLength() { x44_length = CalculateSplineLength(); }
zeus::CTransform GetInterpolatedSplinePointByLength(float pos) const;
zeus::CVector3f GetInterpolatedSplinePointByTime(float time, float range) const;
};
}

View File

@ -46,10 +46,7 @@ void CFirstPersonCamera::Think(float dt, CStateManager& mgr)
{
if (player->GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Unmorphing)
return;
float morphFactor = 0.f;
if (player->GetMorphDuration() != 0.f)
morphFactor = zeus::clamp(0.f, player->GetMorphTime() / player->GetMorphDuration(), 1.f);
if (std::fabs(morphFactor - 1.f) >= 0.00001f)
if (std::fabs(player->GetMorphFactor() - 1.f) >= 0.00001f)
return;
}
}

View File

@ -32,6 +32,8 @@ public:
const CMaterialList& GetIncludeList() const { return x0_include; }
const CMaterialList& GetExcludeList() const { return x8_exclude; }
CMaterialList& IncludeList() { return x0_include; }
CMaterialList& ExcludeList() { return x8_exclude; }
bool Passes(const CMaterialList&) const;
};
}

View File

@ -1253,15 +1253,10 @@ void CSamusHud::Update(float dt, const CStateManager& mgr,
morphT = 1.f;
break;
case CPlayer::EPlayerMorphBallState::Morphing:
if (player.GetMorphDuration() == 0.f)
morphT = 0.f;
else
morphT = zeus::clamp(0.f, player.GetMorphTime() / player.GetMorphDuration(), 1.f);
morphT = player.GetMorphFactor();
break;
case CPlayer::EPlayerMorphBallState::Unmorphing:
if (player.GetMorphDuration() != 0.f)
morphT = zeus::clamp(0.f, player.GetMorphTime() / player.GetMorphDuration(), 1.f);
morphT = 1.f - morphT;
morphT = 1.f - player.GetMorphFactor();
break;
default: break;
}

View File

@ -117,6 +117,8 @@ public:
TCastToPtr() = default;
TCastToPtr(CEntity* p);
TCastToPtr(CEntity& p);
TCastToPtr<T>& operator=(CEntity& p);
TCastToPtr<T>& operator=(CEntity* p);
''')
@ -139,6 +141,8 @@ public:
TCastToConstPtr() = default;
TCastToConstPtr(const CEntity* p) : TCastToPtr<T>(const_cast<CEntity*>(p)) {}
TCastToConstPtr(const CEntity& p) : TCastToPtr<T>(const_cast<CEntity&>(p)) {}
TCastToConstPtr<T>& operator=(const CEntity& p) { TCastToPtr<T>::operator=(const_cast<CEntity&>(p)); return *this; }
TCastToConstPtr<T>& operator=(const CEntity* p) { TCastToPtr<T>::operator=(const_cast<CEntity*>(p)); return *this; }
const T* GetPtr() const { return TCastToPtr<T>::ptr; }
operator const T*() const { return GetPtr(); }
const T& operator*() const { return *GetPtr(); }
@ -169,6 +173,12 @@ TCastToPtr<T>::TCastToPtr(CEntity* p) { p->Accept(*this); }
template <class T>
TCastToPtr<T>::TCastToPtr(CEntity& p) { p.Accept(*this); }
template <class T>
TCastToPtr<T>& TCastToPtr<T>::operator=(CEntity* p) { p->Accept(*this); return *this; }
template <class T>
TCastToPtr<T>& TCastToPtr<T>::operator=(CEntity& p) { p.Accept(*this); return *this; }
''')
for tp in CENTITY_TYPES:

View File

@ -281,7 +281,7 @@ void CPlayer::TransitionFromMorphBallState(CStateManager& mgr)
CBallCamera* ballCam = mgr.GetCameraManager()->GetBallCamera();
if (TCastToConstPtr<CActor> act = mgr.GetObjectById(ballCam->GetTooCloseActorId()))
{
if (ballCam->GetX3E0() < 20.f && ballCam->GetX3E0() > 1.f)
if (ballCam->GetTooCloseActorDistance() < 20.f && ballCam->GetTooCloseActorDistance() > 1.f)
{
zeus::CVector3f deltaFlat = act->GetTranslation() - GetTranslation();
deltaFlat.z = 0.f;
@ -5439,7 +5439,7 @@ void CPlayer::BombJump(const zeus::CVector3f& pos, CStateManager& mgr)
else
{
CBallCamera* ballCam = mgr.GetCameraManager()->GetBallCamera();
if (ballCam->GetTooCloseActorId() != kInvalidUniqueId && ballCam->GetX3E0() < 5.f)
if (ballCam->GetTooCloseActorId() != kInvalidUniqueId && ballCam->GetTooCloseActorDistance() < 5.f)
{
x9d0_bombJumpCount = 1;
x9d4_bombJumpCheckDelayFrames = 2;

View File

@ -648,6 +648,12 @@ public:
bool ObjectInScanningRange(TUniqueId id, const CStateManager& mgr) const;
float GetMorphTime() const { return x574_morphTime; }
float GetMorphDuration() const { return x578_morphDuration; }
float GetMorphFactor() const
{
if (0.f != x578_morphDuration)
return zeus::clamp(0.f, x574_morphTime / x578_morphDuration, 1.f);
return 0.f;
}
bool IsInFreeLook() const { return x3dc_inFreeLook; }
bool GetFreeLookStickState() const { return x3de_lookAnalogHeld; }
CPlayerGun* GetPlayerGun() const { return x490_gun.get(); }
@ -678,6 +684,7 @@ public:
const zeus::CVector3f& GetMoveDir() const { return x50c_moveDir; }
const zeus::CVector3f& GetLeaveMorphDir() const { return x518_leaveMorphDir; }
u32 GetBombJumpCount() const { return x9d0_bombJumpCount; }
float GetMoveSpeed() const { return x4f8_moveSpeed; }
};
}

View File

@ -1,6 +1,7 @@
#include "CScriptCameraWaypoint.hpp"
#include "CActorParameters.hpp"
#include "TCastTo.hpp"
#include "CStateManager.hpp"
namespace urde
{
@ -27,4 +28,24 @@ void CScriptCameraWaypoint::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId
SendScriptMsgs(EScriptObjectState::Arrived, mgr, EScriptObjectMessage::None);
}
TUniqueId CScriptCameraWaypoint::GetRandomNextWaypointId(CStateManager& mgr) const
{
std::vector<TUniqueId> candidateIds;
for (const SConnection& conn : x20_conns)
{
if (conn.x0_state == EScriptObjectState::Arrived && conn.x4_msg == EScriptObjectMessage::Next)
{
TUniqueId uid = mgr.GetIdForScript(conn.x8_objId);
if (uid == kInvalidUniqueId)
continue;
candidateIds.push_back(uid);
}
}
if (candidateIds.empty())
return kInvalidUniqueId;
return candidateIds[mgr.GetActiveRandom()->Range(0, s32(candidateIds.size() - 1))];
}
}

View File

@ -18,6 +18,7 @@ public:
void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&);
void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const {}
void Render(const CStateManager&) const {}
TUniqueId GetRandomNextWaypointId(CStateManager& mgr) const;
};
}

@ -1 +1 @@
Subproject commit 1d44b04638cf1ce3947477254ac3255868b650d2
Subproject commit 126de2c01b9acf3ff7917d63b04ba52b2fca3e91