From 16f6307642da62ef3f837a658c4093eff6fea16d Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Thu, 12 Oct 2017 21:19:22 -1000 Subject: [PATCH 1/3] More CBallCamera and CCameraSpline work --- Runtime/Camera/CBallCamera.cpp | 169 ++++++++++++++++++-- Runtime/Camera/CCameraSpline.cpp | 212 +++++++++++++++++++++++++- Runtime/Camera/CCameraSpline.hpp | 13 +- Runtime/Collision/CMaterialFilter.hpp | 2 + 4 files changed, 378 insertions(+), 18 deletions(-) diff --git a/Runtime/Camera/CBallCamera.cpp b/Runtime/Camera/CBallCamera.cpp index 774c138f3..3fcedcebf 100644 --- a/Runtime/Camera/CBallCamera.cpp +++ b/Runtime/Camera/CBallCamera.cpp @@ -11,6 +11,7 @@ #include "World/CScriptCameraHint.hpp" #include "World/CScriptDoor.hpp" #include "World/CScriptWater.hpp" +#include "Collision/CGameCollision.hpp" namespace urde { @@ -23,19 +24,19 @@ void CCameraSpring::Reset() float CCameraSpring::ApplyDistanceSpringNoMax(float targetX, float curX, float dt) { - float usePos = xc_tardis * x10_dx * dt + curX; + float useX = xc_tardis * x10_dx * dt + curX; x10_dx += xc_tardis * (x0_k * (targetX - curX) - x4_k2Sqrt * x10_dx) * dt; - return std::max(usePos, targetX); + return std::max(useX, targetX); } float CCameraSpring::ApplyDistanceSpring(float targetX, float curX, float dt) { - float usePos = xc_tardis * x10_dx * dt + curX; + float useX = xc_tardis * x10_dx * dt + curX; x10_dx += xc_tardis * (x0_k * (targetX - curX) - x4_k2Sqrt * x10_dx) * dt; - usePos = std::max(usePos, targetX); - if (usePos - targetX > x8_max) - usePos = targetX + x8_max; - return usePos; + useX = std::max(useX, targetX); + if (useX - targetX > x8_max) + useX = targetX + x8_max; + return useX; } CBallCamera::CBallCamera(TUniqueId uid, TUniqueId watchedId, const zeus::CTransform& xf, @@ -332,7 +333,7 @@ void CBallCamera::ResetSpline(CStateManager& mgr) tmpPoint2Ball = mgr.GetPlayer().GetMoveDir(); zeus::CVector3f desiredPosition = FindDesiredPosition(distance, elevation, tmpPoint2Ball, mgr); x37c_camSpline.AddKnot(desiredPosition, zeus::CVector3f::skForward); - x37c_camSpline.x44_ = x37c_camSpline.CalculateSplineLength(); + x37c_camSpline.UpdateSplineLength(); x3d0_24_ = false; CMaterialList intersectMat; x3c8_ = CMaterialList(EMaterialTypes::Floor, EMaterialTypes::Ceiling); @@ -411,7 +412,7 @@ void CBallCamera::BuildSpline(CStateManager& mgr) mgr.RayWorldIntersection(intersectId, x9ac, -x978.normalized(), x978.magnitude(), BallCameraFilter, nearList); if (result.IsValid() && !result.GetMaterial().HasMaterial(EMaterialTypes::Pillar)) x37c_camSpline.SetKnotPosition(2, result.GetPoint() - x978.normalized() * 0.3f * 1.25f); - x37c_camSpline.x44_ = x37c_camSpline.CalculateSplineLength(); + x37c_camSpline.UpdateSplineLength(); if (!SplineIntersectTest(intersectMat, mgr)) { x36c_ = 0; @@ -420,7 +421,7 @@ void CBallCamera::BuildSpline(CStateManager& mgr) } x374_ = 0.5f; x378_ = 0.5f; - x37c_camSpline.x44_ = x37c_camSpline.CalculateSplineLength(); + x37c_camSpline.UpdateSplineLength(); x3c8_ = CMaterialList(); } @@ -775,17 +776,161 @@ zeus::CVector3f CBallCamera::ComputeVelocity(const zeus::CVector3f& curVel, cons zeus::CVector3f CBallCamera::TweenVelocity(const zeus::CVector3f& curVel, const zeus::CVector3f& newVel, float rate, float dt) { - return {}; + zeus::CVector3f velDelta = newVel - curVel; + if (velDelta.canBeNormalized()) + { + float t = zeus::clamp(-1.f, velDelta.magnitude() / (rate * dt), 1.f); + return velDelta.normalized() * rate * dt * t + curVel; + } + return newVel; } zeus::CVector3f CBallCamera::MoveCollisionActor(const zeus::CVector3f& pos, float dt, CStateManager& mgr) { - return {}; + if (TCastToPtr act = mgr.ObjectById(x46c_collisionActorId)) + { + zeus::CVector3f posDelta = pos - act->GetTranslation(); + if (!posDelta.canBeNormalized() || posDelta.magnitude() < 0.01f) + { + act->Stop(); + return act->GetTranslation(); + } + zeus::CVector3f oldTranslation = act->GetTranslation(); + zeus::CVector3f oldVel = act->GetVelocity(); + zeus::CVector3f newVel = ComputeVelocity(oldVel, posDelta * (1.f / dt)); + act->SetVelocityWR(newVel); + act->SetMovable(true); + act->AddMaterial(EMaterialTypes::Solid, mgr); + CGameCollision::Move(mgr, *act, dt, nullptr); + zeus::CVector3f posDelta2 = act->GetTranslation() - pos; + if (posDelta2.canBeNormalized() && posDelta2.magnitude() > 0.1f) + { + act->SetTranslation(oldTranslation); + act->SetVelocityWR(TweenVelocity(oldVel, newVel, 50.f, dt)); + CGameCollision::Move(mgr, *act, dt, nullptr); + posDelta2 = act->GetTranslation() - pos; + if (posDelta2.magnitude() > 0.1f) + x478_ += 1; + else + x478_ = 0; + } + else + { + act->Stop(); + x478_ = 0; + } + act->SetMovable(false); + act->RemoveMaterial(EMaterialTypes::Solid, mgr); + return act->GetTranslation(); + } + return pos; } void CBallCamera::UpdateUsingFreeLook(float dt, CStateManager& mgr) { + if (x400_state == EBallCameraState::Four || x400_state == EBallCameraState::Five) + { + x36c_ = 0; + return; + } + if (x36c_ == 1 && x188_behaviour <= EBallCameraBehaviour::Eight && + x188_behaviour >= EBallCameraBehaviour::Four) + { + x36c_ = 0; + return; + } + + float elevation = x1a0_elevation; + float distance = x190_curMinDistance; + ConstrainElevationAndDistance(elevation, distance, 0.f, mgr); + + zeus::CVector3f ballPos = mgr.GetPlayer().GetBallPosition(); + zeus::CVector3f knotToBall = ballPos - x37c_camSpline.GetKnotPosition(2); + if (knotToBall.canBeNormalized()) + knotToBall.normalize(); + else + knotToBall = mgr.GetPlayer().GetMoveDir(); + zeus::CVector3f knot3 = x37c_camSpline.GetKnotPosition(3); + zeus::CVector3f desiredPos = FindDesiredPosition(distance, elevation, knotToBall, mgr); + + if (x370_24_) + x37c_camSpline.SetKnotPosition(3, desiredPos); + + x374_ -= dt; + + float f26 = 1.f - zeus::clamp(0.f, x374_ / x378_, 1.f); + if (x36c_ == 1) + { + CMaterialList intersectMat; + if (!SplineIntersectTest(intersectMat, mgr)) + { + x37c_camSpline.SetKnotPosition(3, knot3); + if (intersectMat.HasMaterial(EMaterialTypes::Floor)) + { + x36c_ = 0; + return; + } + } + } + + if (x374_ <= 0.f || (f26 > 0.75f && x18c_31_)) + { + if (x36c_ == 2 && !x18c_31_) + { + CMaterialList intersectMat; + if (!SplineIntersectTest(intersectMat, mgr)) + { + x36c_ = 0; + } + else + { + zeus::CVector3f oldKnot2 = x37c_camSpline.GetKnotPosition(2); + zeus::CVector3f oldKnot1 = x37c_camSpline.GetKnotPosition(1); + BuildSpline(mgr); + x37c_camSpline.SetKnotPosition(3, x37c_camSpline.GetKnotPosition(1)); + x37c_camSpline.SetKnotPosition(2, x37c_camSpline.GetKnotPosition(0)); + x37c_camSpline.SetKnotPosition(1, oldKnot2); + x37c_camSpline.SetKnotPosition(0, oldKnot1); + x37c_camSpline.UpdateSplineLength(); + x374_ = x378_ - x378_ * (x37c_camSpline.GetKnotT(2) / x37c_camSpline.x44_length); + x374_ -= dt; + f26 = zeus::clamp(0.f, x374_ / x378_, 1.f); + } + } + else + { + x36c_ = 0; + } + } + + x37c_camSpline.UpdateSplineLength(); + zeus::CVector3f pos = x37c_camSpline.GetInterpolatedSplinePointByLength(f26 * x37c_camSpline.x44_length).origin; + if (TCastToPtr act = mgr.ObjectById(x46c_collisionActorId)) + { + CMaterialFilter filter = act->GetMaterialFilter(); + CMaterialFilter tmpFilter = filter; + tmpFilter.IncludeList().Add(EMaterialTypes::Wall); + tmpFilter.ExcludeList().Add(x3c8_); + act->SetMaterialFilter(tmpFilter); + MoveCollisionActor(pos, dt, mgr); + act->SetMaterialFilter(filter); + } + + zeus::CVector3f lookDir = x1d8_ - desiredPos; + if (x18d_26_) + lookDir = ballPos - desiredPos; + + if (lookDir.canBeNormalized()) + { + lookDir.normalize(); + UpdateTransform(lookDir, desiredPos, dt, mgr); + } + + TeleportCamera(desiredPos, mgr); + + if (x3d0_24_ && x374_ / x378_ < 0.5f) + x36c_ = 0; } zeus::CVector3f CBallCamera::InterpolateCameraElevation(const zeus::CVector3f& camPos) const diff --git a/Runtime/Camera/CCameraSpline.cpp b/Runtime/Camera/CCameraSpline.cpp index aa9953e80..8d5d91886 100644 --- a/Runtime/Camera/CCameraSpline.cpp +++ b/Runtime/Camera/CCameraSpline.cpp @@ -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& connections, CStateManager& mgr) { @@ -27,12 +27,12 @@ void CCameraSpline::CalculateKnots(TUniqueId cameraId, const std::vector= 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& positions, + rstl::reserved_vector& 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) +{ + if (x4_positions.empty()) + return zeus::CTransform(); + + int baseIdx = 0; + int i; + for (i=1 ; 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 positions; + rstl::reserved_vector 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) +{ + if (x4_positions.empty()) + return {}; + + rstl::reserved_vector positions; + rstl::reserved_vector 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 {}; +} } diff --git a/Runtime/Camera/CCameraSpline.hpp b/Runtime/Camera/CCameraSpline.hpp index 50dd31c06..dc1afa575 100644 --- a/Runtime/Camera/CCameraSpline.hpp +++ b/Runtime/Camera/CCameraSpline.hpp @@ -11,10 +11,12 @@ class CCameraSpline friend class CBallCamera; std::vector x4_positions; std::vector x14_; - std::vector x24_; + std::vector x24_t; std::vector 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& positions, + rstl::reserved_vector& directions) const; public: CCameraSpline(bool); void CalculateKnots(TUniqueId, const std::vector&, 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); + zeus::CVector3f GetInterpolatedSplinePointByTime(float time, float range); }; } diff --git a/Runtime/Collision/CMaterialFilter.hpp b/Runtime/Collision/CMaterialFilter.hpp index a7813caf1..30107ca2c 100644 --- a/Runtime/Collision/CMaterialFilter.hpp +++ b/Runtime/Collision/CMaterialFilter.hpp @@ -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; }; } From 96c17ba729489952f16fbb40c685b94083db3d23 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Fri, 13 Oct 2017 20:34:57 -1000 Subject: [PATCH 2/3] Work on CBallCamera --- Runtime/Camera/CBallCamera.cpp | 495 +++++++++++++++++++++++- Runtime/Camera/CBallCamera.hpp | 28 +- Runtime/Camera/CCameraSpline.cpp | 28 +- Runtime/Camera/CCameraSpline.hpp | 2 +- Runtime/MkCastTo.py | 10 + Runtime/World/CPlayer.hpp | 1 + Runtime/World/CScriptCameraWaypoint.cpp | 21 + Runtime/World/CScriptCameraWaypoint.hpp | 1 + 8 files changed, 552 insertions(+), 34 deletions(-) diff --git a/Runtime/Camera/CBallCamera.cpp b/Runtime/Camera/CBallCamera.cpp index 3fcedcebf..066f99918 100644 --- a/Runtime/Camera/CBallCamera.cpp +++ b/Runtime/Camera/CBallCamera.cpp @@ -536,7 +536,7 @@ void CBallCamera::UpdateTransform(const zeus::CVector3f& lookDir, const zeus::CV SetTranslation(pos); } -zeus::CVector3f CBallCamera::ConstrainYawAngle(const CPlayer& player, float angleVel, float maxAngle, float dt, +zeus::CVector3f CBallCamera::ConstrainYawAngle(const CPlayer& player, float distance, float yawSpeed, float dt, CStateManager& mgr) const { zeus::CVector3f playerToCamFlat = GetTranslation() - player.GetTranslation(); @@ -563,8 +563,8 @@ zeus::CVector3f CBallCamera::ConstrainYawAngle(const CPlayer& player, float angl float angleProj = zeus::clamp(-1.f, playerToCamFlat.dot(-lookDir), 1.f); if (angleProj >= 1.f) return -lookDir; - return zeus::CQuaternion::lookAt(playerToCamFlat, -lookDir, angleVel * dt * - zeus::clamp(0.f, std::acos(angleProj) / maxAngle, 1.f)).transform(playerToCamFlat); + return zeus::CQuaternion::lookAt(playerToCamFlat, -lookDir, distance * dt * + zeus::clamp(0.f, std::acos(angleProj) / yawSpeed, 1.f)).transform(playerToCamFlat); } void CBallCamera::CheckFailsafe(float dt, CStateManager& mgr) @@ -933,44 +933,230 @@ void CBallCamera::UpdateUsingFreeLook(float dt, CStateManager& mgr) x36c_ = 0; } -zeus::CVector3f CBallCamera::InterpolateCameraElevation(const zeus::CVector3f& camPos) const +zeus::CVector3f CBallCamera::InterpolateCameraElevation(const zeus::CVector3f& camPos) { - return {}; + if (x1a0_elevation < 2.f) + return camPos; + + zeus::CVector3f ret = camPos; + if (!x18c_31_ && x350_.HasMaterial(EMaterialTypes::Floor)) + { + x3d4_ = 1.f; + ret.z = x3d8_ = GetTranslation().z; + } + else if (x3d4_ > 0.f) + { + ret.z = (camPos.z - x3d8_) * (1.f - zeus::clamp(0.f, x3d4_, 1.f)) + x3d8_; + } + + return ret; } zeus::CVector3f CBallCamera::CalculateCollidersCentroid(const std::vector& colliderList, int w1) const { - return {}; + if (colliderList.size() < 3) + return zeus::CVector3f::skForward; + + int r10 = 0; + const CCameraCollider* prevCol = &colliderList.back(); + float f6 = 0.f; + float f7 = 0.f; + float f8 = 0.f; + for (const CCameraCollider& col : colliderList) + { + if (prevCol->x4c_occlusionCount < 2 && col.x4c_occlusionCount < 2) + { + float f3 = prevCol->x50_scale * prevCol->x8_.z; + float f1 = prevCol->x50_scale * col.x8_.x; + float f4 = prevCol->x50_scale * prevCol->x8_.x; + float f5 = prevCol->x50_scale * col.x8_.z; + + float f2 = f4 * f5 - f1 * f3; + f6 += f2; + f7 += f2 * (f1 + f4); + f8 += f2 * (f5 + f3); + } + else + { + r10 += 1; + } + prevCol = &col; + } + + if (r10 / float(colliderList.size()) <= x330_) + { + return zeus::CVector3f::skForward; + } + else if (0.f != f6) + { + float f2 = 3.f * f6; + return {f7 / f2, 0.f, f8 / f2}; + } + + return {0.f, 2.f, 0.f}; } zeus::CVector3f CBallCamera::ApplyColliders() { - return {}; + zeus::CVector3f smallCentroid = CalculateCollidersCentroid(x264_smallColliders, x2c4_); + zeus::CVector3f mediumCentroid = CalculateCollidersCentroid(x274_mediumColliders, x2c8_); + zeus::CVector3f largeCentroid = CalculateCollidersCentroid(x284_largeColliders, x2cc_); + + if (smallCentroid.y == 0.f) + x2a0_ = smallCentroid; + else + x2a0_ = zeus::CVector3f::skZero; + + float centroidX = x2a0_.x; + float centroidZ = x2a0_.z; + + if (mediumCentroid.y == 0.f) + x2ac_ = mediumCentroid; + else + x2ac_ = zeus::CVector3f::skZero; + + centroidX += x2ac_.x; + centroidZ += x2ac_.z; + + if (largeCentroid.y == 0.f) + x2b8_ = largeCentroid; + else + x2b8_ = zeus::CVector3f::skZero; + + centroidX += x2b8_.x; + centroidZ += x2b8_.z; + + if (x18c_31_) + centroidX /= 1.5f; + centroidZ /= 3.f; + + if (!x18c_31_ && x368_ == kInvalidUniqueId) + { + float f26 = 1.5f; + float f27 = 1.f; + if (x350_.HasMaterial(EMaterialTypes::Floor)) + f27 += 2.f * x358_; + if (x350_.HasMaterial(EMaterialTypes::Wall)) + f26 += 3.f * zeus::clamp(0.f, x358_ - 0.25f, 1.f); + centroidX *= f26; + centroidZ *= f27; + } + + if (!x18c_28_) + return zeus::CVector3f::skZero; + + if (std::fabs(centroidX) < 0.05f) + centroidX = 0.f; + if (std::fabs(centroidZ) < 0.05f) + centroidZ = 0.f; + + if (x18c_31_) + centroidZ *= 0.5f; + + return {centroidX, 0.f, centroidZ}; } void CBallCamera::UpdateColliders(const zeus::CTransform& xf, std::vector& colliderList, int& r6, - int r7, float f1, const rstl::reserved_vector& nearList, float f2, + int r7, float f1, const rstl::reserved_vector& nearList, float dt, CStateManager& mgr) { - + if (r6 < colliderList.size()) + { + x310_ = {0.f, g_tweakBall->GetBallCameraOffset().y, g_tweakPlayer->GetPlayerBallHalfExtent()}; + x310_.y *= x308_; + x31c_ = mgr.GetPlayer().GetMoveDir() * x310_.y; + x31c_.z = x310_.z; + x31c_ += mgr.GetPlayer().GetTranslation(); + zeus::CTransform xd0 = zeus::lookAt(xf.origin, x31c_); + float f26 = 1.f / f1; + for (int i=0 ; i& nearList, - float dt, CStateManager& mgr) +zeus::CVector3f CBallCamera::AvoidGeometry(const zeus::CTransform& xf, + const rstl::reserved_vector& nearList, + float dt, CStateManager& mgr) { + switch (x328_) + { + case 0: + UpdateColliders(xf, x264_smallColliders, x2d0_, 1, 4.f, nearList, dt, mgr); + break; + case 1: + UpdateColliders(xf, x274_mediumColliders, x2d4_, 3, 4.f, nearList, dt, mgr); + break; + case 2: + UpdateColliders(xf, x284_largeColliders, x2d8_, 4, 4.f, nearList, dt, mgr); + break; + case 3: + UpdateColliders(xf, x284_largeColliders, x2d8_, 4, 4.f, nearList, dt, mgr); + break; + default: + break; + } + x328_ += 1; + if (x328_ >= 4) + x328_ = 0; + + return ApplyColliders(); } -void CBallCamera::AvoidGeometryFull(const zeus::CTransform& xf, const rstl::reserved_vector& nearList, - float dt, CStateManager& mgr) +zeus::CVector3f CBallCamera::AvoidGeometryFull(const zeus::CTransform& xf, + const rstl::reserved_vector& nearList, + float dt, CStateManager& mgr) { - + UpdateColliders(xf, x264_smallColliders, x2d0_, x264_smallColliders.size(), 4.f, nearList, dt, mgr); + UpdateColliders(xf, x274_mediumColliders, x2d4_, x274_mediumColliders.size(), 4.f, nearList, dt, mgr); + UpdateColliders(xf, x284_largeColliders, x2d8_, x284_largeColliders.size(), 4.f, nearList, dt, mgr); + return ApplyColliders(); } zeus::CAABox CBallCamera::CalculateCollidersBoundingBox(const std::vector& colliderList, CStateManager& mgr) const { - return {}; + zeus::CAABox aabb; + for (const CCameraCollider& col : colliderList) + aabb.accumulateBounds(col.x2c_); + aabb.accumulateBounds(mgr.GetPlayer().GetTranslation()); + return aabb; } int CBallCamera::CountObscuredColliders(const std::vector& colliderList) const @@ -984,12 +1170,285 @@ int CBallCamera::CountObscuredColliders(const std::vector& coll void CBallCamera::UpdateCollidersDistances(std::vector& colliderList, float f1, float f2, float f3) { - + float f31 = f3; + for (CCameraCollider& col : colliderList) + { + float f23 = std::cos(f31) * f2; + if (f31 > M_PIF / 2.f) + f23 *= 0.25f; + col.x14_ = {std::sin(f31) * f1, 0.f, f23}; + f31 += 2.f * M_PIF / float(colliderList.size()); + } } void CBallCamera::UpdateUsingColliders(float dt, CStateManager& mgr) { + if (mgr.GetPlayer().GetBombJumpCount() == 1) + return; + zeus::CVector3f ballPos = mgr.GetPlayer().GetBallPosition(); + + if (mgr.GetPlayer().GetBombJumpCount() == 2) + { + zeus::CVector3f xa60 = x1d8_ - GetTranslation(); + if (x18d_26_) + xa60 = ballPos - GetTranslation(); + + if (xa60.canBeNormalized()) + { + xa60.normalize(); + UpdateTransform(xa60, GetTranslation(), dt, mgr); + } + } + else if (mgr.GetPlayer().GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Unmorphed || + x18d_25_) + { + zeus::CTransform x8e0 = x34_transform; + zeus::CVector3f f28 = GetTranslation(); + x2c4_ = CountObscuredColliders(x264_smallColliders); + x2c8_ = CountObscuredColliders(x274_mediumColliders); + x2cc_ = CountObscuredColliders(x284_largeColliders); + zeus::CVector3f xa78 = {0.f, 0.f, GetTranslation().z - ballPos.z}; + zeus::CVector3f xa6c = GetTranslation() - ballPos; + xa6c.z = 0.f; + float f25 = 0.f; + if (xa6c.canBeNormalized()) + f25 = xa6c.magnitude(); + else + xa6c = -mgr.GetPlayer().GetMoveDir(); + xa78 = GetTranslation() - xa78; + zeus::CTransform x910; + if ((xa78 - ballPos).canBeNormalized()) + x910 = zeus::lookAt(ballPos, xa78); + float distance = x214_ballCameraSpring.ApplyDistanceSpring(x190_curMinDistance, f25, (3.f + x308_) * dt); + zeus::CVector3f xa84 = ballPos - GetTranslation(); + xa84.z = 0.f; + if (xa84.canBeNormalized()) + { + xa84.normalize(); + if (std::fabs(std::acos(zeus::clamp(-1.f, xa84.dot(mgr.GetPlayer().GetMoveDir()), 1.f))) > + zeus::degToRad(150.f) && mgr.GetPlayer().GetVelocity().canBeNormalized()) + { + distance = x214_ballCameraSpring. + ApplyDistanceSpring(x308_ * (x19c_backwardsDistance -x190_curMinDistance) + + x190_curMinDistance, f25, 3.f * dt); + } + } + x334_ = CalculateCollidersBoundingBox(x284_largeColliders, mgr); + rstl::reserved_vector nearList; + mgr.BuildNearList(nearList, x334_, BallCameraFilter, + TCastToConstPtr(mgr.GetObjectById(x46c_collisionActorId)).GetPtr()); + if (!x18c_31_ && x368_ == kInvalidUniqueId) + { + if (x34c_ > 0.f || x350_.HasMaterial(EMaterialTypes::Floor) || x350_.HasMaterial(EMaterialTypes::Wall)) + { + x32c_ += 2.f * dt; + if (x32c_ < 2.f) + x32c_ = 2.f; + if (x32c_ > 2.f) + x32c_ = 2.f; + UpdateCollidersDistances(x264_smallColliders, 2.31f * x32c_, 2.31f * x32c_ * 0.5f, -M_PIF / 2.f); + UpdateCollidersDistances(x274_mediumColliders, 4.62f * x32c_, 4.62f * x32c_ * 0.5f, -M_PIF / 2.f); + UpdateCollidersDistances(x284_largeColliders, 7.f * x32c_, 7.f * x32c_ * 0.5f, -M_PIF / 2.f); + } + } + else + { + float f1 = 1.f; + if (x18d_24_ && mgr.GetPlayer().GetMoveSpeed() < 1.f) + f1 = 0.25f; + x32c_ += (f1 - x32c_) * dt * 2.f; + UpdateCollidersDistances(x264_smallColliders, x32c_ * 2.31f, x32c_ * 2.31f, -M_PIF / 2.f); + UpdateCollidersDistances(x274_mediumColliders, x32c_ * 4.62f, x32c_ * 4.62f, -M_PIF / 2.f); + UpdateCollidersDistances(x284_largeColliders, x32c_ * 7.f, x32c_ * 7.f, -M_PIF / 2.f); + } + + float elevation = x1a0_elevation; + bool r27 = !ConstrainElevationAndDistance(elevation, distance, dt, mgr); + zeus::CVector3f xa9c = x910.rotate({0.f, distance, elevation}); + + if (TCastToConstPtr door = mgr.GetObjectById(x3dc_tooCloseActorId)) + { + if (!door->x2a8_26_) + { + if (x400_state == EBallCameraState::Three) + { + zeus::CVector3f xaa8 = GetTranslation() - ballPos; + if (xaa8.canBeNormalized()) + xaa8.normalize(); + else + xaa8 = GetTransform().basis[1]; + if (std::fabs(f25 - x430_boostElevation) < 1.f) + { + xaa8 = ConstrainYawAngle(mgr.GetPlayer(), g_tweakBall->GetBallCameraBoostDistance(), + g_tweakBall->GetBallCameraBoostYawSpeed(), dt, mgr); + } + xaa8.normalize(); + xaa8.z = 0.f; + xaa8 = xaa8 * distance; + xaa8.z = 1.f; + xa9c = xaa8; + r27 = false; + } + if (x18c_25_ && (x400_state == EBallCameraState::Two || x188_behaviour == EBallCameraBehaviour::One)) + { + zeus::CVector3f xab4 = GetTranslation() - ballPos; + if (xab4.canBeNormalized()) + xab4.normalize(); + else + xab4 = GetTransform().basis[1]; + if (std::fabs(f25 - x404_chaseElevation) < 3.f) + { + xab4 = ConstrainYawAngle(mgr.GetPlayer(), g_tweakBall->GetBallCameraChaseDistance(), + g_tweakBall->GetBallCameraChaseYawSpeed(), dt, mgr); + } + xab4.z = 0.f; + xab4.normalize(); + xab4 = xab4 * distance; + xab4.z = 2.736f; + xa9c = xab4; + r27 = false; + } + } + } + + if (x188_behaviour == EBallCameraBehaviour::Two) + { + xa9c = x45c_; + if (x18c_27_) + { + zeus::CVector3f xac0 = x45c_; + if (xac0.canBeNormalized()) + xac0.normalize(); + else + xac0 = -mgr.GetPlayer().GetMoveDir(); + TUniqueId intersectId = kInvalidUniqueId; + CRayCastResult result = + mgr.RayWorldIntersection(intersectId, ballPos, xac0, distance, BallCameraFilter, nearList); + if (result.IsValid()) + xa9c = xac0 * result.GetT() * 0.9f; + } + r27 = false; + } + + distance = xa9c.magnitude(); + zeus::CVector3f xacc = ballPos + xa9c; + float d = 0.f; + if (DetectCollision(ballPos, xacc, 0.3f, d, mgr)) + { + if (d >= 1.f) + { + xa9c = xa9c.normalized() * d; + xacc = ballPos + xa9c; + } + else + { + xa9c = ballPos + GetTranslation(); + xacc = GetTranslation(); + } + } + + zeus::CTransform x940 = zeus::lookAt(xacc, x1d8_); + zeus::CTransform x970 = zeus::lookAt(GetTranslation(), x1d8_); + x1e4_ = x940; + x940 = x970; + zeus::CVector3f xad8; + if (x18d_25_ || !x18c_31_) + xad8 = AvoidGeometryFull(x940, nearList, dt, mgr); + else + xad8 = AvoidGeometry(x940, nearList, dt, mgr); + + zeus::CVector3f xae4 = GetTranslation() - ballPos; + xae4.z = 0.f; + if (xae4.magnitude() < 2.f) + { + if (x18c_31_ && x478_ > 2) + xad8 = xad8 / float(x478_); + if (d < 3.f) + { + xad8 = xad8 * 0.25f; + if (x18c_31_ && x478_ > 0) + xad8 = xad8 * x308_; + } + if (d < 1.f) + xad8 = zeus::CVector3f::skZero; + } + + zeus::CVector3f xaf0 = x940.rotate(xad8) + xacc - ballPos; + if (xaf0.canBeNormalized()) + xaf0.normalize(); + zeus::CVector3f f27 = xaf0 * distance + ballPos; + + if (x188_behaviour == EBallCameraBehaviour::Six) + if (TCastToConstPtr cam = mgr.GetObjectById(mgr.GetCameraManager()->GetPathCameraId())) + f27 = cam->GetTranslation(); + + xaf0 = x294_ - f27; + float f24 = xaf0.magnitude(); + if (xaf0.canBeNormalized()) + xaf0.normalize(); + + x294_ = xaf0 * x228_ballCameraCentroidSpring.ApplyDistanceSpring(0.f, f24, dt) + f27; + zeus::CVector3f xafc = f28 - x294_; + f24 = xafc.magnitude(); + if (xafc.canBeNormalized()) + xafc.normalize(); + + float f1 = x250_ballCameraCentroidDistanceSpring.ApplyDistanceSpring(0.f, f24, (x18d_28_ ? 3.f : 1.f) * dt); + if (x400_state == EBallCameraState::Three) + f1 = x448_ballCameraBoostSpring.ApplyDistanceSpring(0.f, f24, dt); + else if (x18c_25_ && (x400_state == EBallCameraState::Two || x188_behaviour == EBallCameraBehaviour::One)) + f1 = x41c_ballCameraChaseSpring.ApplyDistanceSpring(0.f, f24, dt); + + zeus::CVector3f xb08 = xafc * f1 + x294_; + if (mgr.GetPlayer().GetMorphBall()->GetSpiderBallState() != CMorphBall::ESpiderBallState::Active && + !x18e_24_ && mgr.GetPlayer().GetVelocity().z > 8.f) + { + zeus::CVector3f delta = xb08 - f28; + delta.z = zeus::clamp(-0.1f * dt, delta.z, 0.1f * dt); + xb08 = f28 + delta; + } + + if (r27 && x400_state != EBallCameraState::Four) + xb08 = InterpolateCameraElevation(xb08); + + if (x18d_29_) + xb08.z = elevation + ballPos.z; + + if (xae4.magnitude() < 2.f) + { + if (xb08.z < 2.f + ballPos.z) + xb08.z = 2.f + ballPos.z; + x214_ballCameraSpring.Reset(); + } + + xb08 = ClampElevationToWater(xb08, mgr); + if (xae4.magnitude() < 2.f && x3dc_tooCloseActorId != kInvalidUniqueId && x3e0_tooCloseActorDist < 5.f) + if (TCastToConstPtr door = mgr.GetObjectById(x3dc_tooCloseActorId)) + if (!door->x2a8_26_) + xb08 = GetTranslation(); + + float backupZ = xb08.z; + xb08 = MoveCollisionActor(xb08, dt, mgr); + + if (x18c_31_ && x478_ > 0) + { + xb08.z = backupZ; + xb08 = MoveCollisionActor(xb08, dt, mgr); + } + + zeus::CVector3f xb14 = x1d8_ - xb08; + if (x18d_26_) + xb14 = ballPos - xb08; + if (xb14.canBeNormalized()) + { + xb14.normalize(); + UpdateTransform(xb14, xb08, dt, mgr); + } + + if (x470_ > 0.f) + x470_ -= dt; + } } void CBallCamera::UpdateUsingSpindleCameras(float dt, CStateManager& mgr) @@ -1046,9 +1505,9 @@ void CBallCamera::ActivateFailsafe(float dt, CStateManager& mgr) } -void CBallCamera::ConstrainElevationAndDistance(float& elevation, float& distance, float f1, CStateManager& mgr) +bool CBallCamera::ConstrainElevationAndDistance(float& elevation, float& distance, float dt, CStateManager& mgr) { - + return false; } zeus::CVector3f CBallCamera::FindDesiredPosition(float distance, float elevation, diff --git a/Runtime/Camera/CBallCamera.hpp b/Runtime/Camera/CBallCamera.hpp index ca86cd320..a42c14e3c 100644 --- a/Runtime/Camera/CBallCamera.hpp +++ b/Runtime/Camera/CBallCamera.hpp @@ -124,12 +124,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 +193,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 +205,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& colliderList, int w1) const; zeus::CVector3f ApplyColliders(); void UpdateColliders(const zeus::CTransform& xf, std::vector& colliderList, int& r6, int r7, - float f1, const rstl::reserved_vector& nearList, float f2, + float f1, const rstl::reserved_vector& nearList, float dt, CStateManager& mgr); - void AvoidGeometry(const zeus::CTransform& xf, const rstl::reserved_vector& nearList, - float dt, CStateManager& mgr); - void AvoidGeometryFull(const zeus::CTransform& xf, const rstl::reserved_vector& nearList, - float dt, CStateManager& mgr); + zeus::CVector3f AvoidGeometry(const zeus::CTransform& xf, const rstl::reserved_vector& nearList, + float dt, CStateManager& mgr); + zeus::CVector3f AvoidGeometryFull(const zeus::CTransform& xf, const rstl::reserved_vector& nearList, + float dt, CStateManager& mgr); zeus::CAABox CalculateCollidersBoundingBox(const std::vector& colliderList, CStateManager& mgr) const; int CountObscuredColliders(const std::vector& colliderList) const; @@ -228,7 +228,7 @@ private: 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); + bool ConstrainElevationAndDistance(float& elevation, float& distance, float dt, CStateManager& mgr); zeus::CVector3f FindDesiredPosition(float distance, float elevation, const zeus::CVector3f& dir, CStateManager& mgr); static bool DetectCollision(const zeus::CVector3f& from, const zeus::CVector3f& to, float margin, float& d, CStateManager& mgr); diff --git a/Runtime/Camera/CCameraSpline.cpp b/Runtime/Camera/CCameraSpline.cpp index 8d5d91886..010f2a13e 100644 --- a/Runtime/Camera/CCameraSpline.cpp +++ b/Runtime/Camera/CCameraSpline.cpp @@ -20,7 +20,33 @@ void CCameraSpline::CalculateKnots(TUniqueId cameraId, const std::vector 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)); + } + } } } diff --git a/Runtime/Camera/CCameraSpline.hpp b/Runtime/Camera/CCameraSpline.hpp index dc1afa575..3c59974ec 100644 --- a/Runtime/Camera/CCameraSpline.hpp +++ b/Runtime/Camera/CCameraSpline.hpp @@ -10,7 +10,7 @@ class CCameraSpline { friend class CBallCamera; std::vector x4_positions; - std::vector x14_; + std::vector x14_wpTracker; std::vector x24_t; std::vector x34_directions; float x44_length = 0.f; diff --git a/Runtime/MkCastTo.py b/Runtime/MkCastTo.py index 3f187e983..099538311 100644 --- a/Runtime/MkCastTo.py +++ b/Runtime/MkCastTo.py @@ -117,6 +117,8 @@ public: TCastToPtr() = default; TCastToPtr(CEntity* p); TCastToPtr(CEntity& p); + TCastToPtr& operator=(CEntity& p); + TCastToPtr& operator=(CEntity* p); ''') @@ -139,6 +141,8 @@ public: TCastToConstPtr() = default; TCastToConstPtr(const CEntity* p) : TCastToPtr(const_cast(p)) {} TCastToConstPtr(const CEntity& p) : TCastToPtr(const_cast(p)) {} + TCastToConstPtr& operator=(const CEntity& p) { TCastToPtr::operator=(const_cast(p)); return *this; } + TCastToConstPtr& operator=(const CEntity* p) { TCastToPtr::operator=(const_cast(p)); return *this; } const T* GetPtr() const { return TCastToPtr::ptr; } operator const T*() const { return GetPtr(); } const T& operator*() const { return *GetPtr(); } @@ -169,6 +173,12 @@ TCastToPtr::TCastToPtr(CEntity* p) { p->Accept(*this); } template TCastToPtr::TCastToPtr(CEntity& p) { p.Accept(*this); } +template +TCastToPtr& TCastToPtr::operator=(CEntity* p) { p->Accept(*this); return *this; } + +template +TCastToPtr& TCastToPtr::operator=(CEntity& p) { p.Accept(*this); return *this; } + ''') for tp in CENTITY_TYPES: diff --git a/Runtime/World/CPlayer.hpp b/Runtime/World/CPlayer.hpp index 5af53dbb0..736e76858 100644 --- a/Runtime/World/CPlayer.hpp +++ b/Runtime/World/CPlayer.hpp @@ -678,6 +678,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; } }; } diff --git a/Runtime/World/CScriptCameraWaypoint.cpp b/Runtime/World/CScriptCameraWaypoint.cpp index 4934ce334..512839ce7 100644 --- a/Runtime/World/CScriptCameraWaypoint.cpp +++ b/Runtime/World/CScriptCameraWaypoint.cpp @@ -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 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))]; +} + } diff --git a/Runtime/World/CScriptCameraWaypoint.hpp b/Runtime/World/CScriptCameraWaypoint.hpp index c196adc6e..6e69fbcd7 100644 --- a/Runtime/World/CScriptCameraWaypoint.hpp +++ b/Runtime/World/CScriptCameraWaypoint.hpp @@ -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; }; } From 2aee5910d65c1451bbb6562b461c1c104240d22b Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Sat, 14 Oct 2017 19:38:10 -1000 Subject: [PATCH 3/3] Work on CBallCamera --- Runtime/Camera/CBallCamera.cpp | 420 +++++++++++++++++++++++++- Runtime/Camera/CBallCamera.hpp | 17 +- Runtime/Camera/CCameraManager.cpp | 2 +- Runtime/Camera/CCameraSpline.cpp | 4 +- Runtime/Camera/CCameraSpline.hpp | 4 +- Runtime/Camera/CFirstPersonCamera.cpp | 5 +- Runtime/MP1/CSamusHud.cpp | 9 +- Runtime/World/CPlayer.cpp | 4 +- Runtime/World/CPlayer.hpp | 6 + specter | 2 +- 10 files changed, 432 insertions(+), 41 deletions(-) diff --git a/Runtime/Camera/CBallCamera.cpp b/Runtime/Camera/CBallCamera.cpp index 066f99918..4d649d5fc 100644 --- a/Runtime/Camera/CBallCamera.cpp +++ b/Runtime/Camera/CBallCamera.cpp @@ -11,6 +11,7 @@ #include "World/CScriptCameraHint.hpp" #include "World/CScriptDoor.hpp" #include "World/CScriptWater.hpp" +#include "World/CScriptDock.hpp" #include "Collision/CGameCollision.hpp" namespace urde @@ -219,11 +220,11 @@ void CBallCamera::Reset(const zeus::CTransform& xf, CStateManager& mgr) x41c_ballCameraChaseSpring.Reset(); x448_ballCameraBoostSpring.Reset(); - zeus::CVector3f desiredPos = FindDesiredPosition(x190_curMinDistance, x1a0_elevation, xf.basis[1], mgr); + zeus::CVector3f desiredPos = FindDesiredPosition(x190_curMinDistance, x1a0_elevation, xf.basis[1], mgr, false); if (TCastToConstPtr player = mgr.GetObjectById(xe8_watchedObject)) { - ResetPosition(); + ResetPosition(mgr); x310_ = x1b4_lookAtOffset; x31c_ = x1d8_; if ((x1d8_ - desiredPos).canBeNormalized()) @@ -331,7 +332,7 @@ void CBallCamera::ResetSpline(CStateManager& mgr) tmpPoint2Ball.normalize(); else tmpPoint2Ball = mgr.GetPlayer().GetMoveDir(); - zeus::CVector3f desiredPosition = FindDesiredPosition(distance, elevation, tmpPoint2Ball, mgr); + zeus::CVector3f desiredPosition = FindDesiredPosition(distance, elevation, tmpPoint2Ball, mgr, false); x37c_camSpline.AddKnot(desiredPosition, zeus::CVector3f::skForward); x37c_camSpline.UpdateSplineLength(); x3d0_24_ = false; @@ -380,7 +381,7 @@ void CBallCamera::BuildSpline(CStateManager& mgr) else x994 = f30f31 + x978; x37c_camSpline.AddKnot(x994, zeus::CVector3f::skForward); - FindDesiredPosition(distance, elevation, mgr.GetPlayer().GetMoveDir(), mgr); + FindDesiredPosition(distance, elevation, mgr.GetPlayer().GetMoveDir(), mgr, false); x978 = rot.transform(x978); zeus::CVector3f x9ac = f30f31 + x978; result = @@ -852,7 +853,7 @@ void CBallCamera::UpdateUsingFreeLook(float dt, CStateManager& mgr) else knotToBall = mgr.GetPlayer().GetMoveDir(); zeus::CVector3f knot3 = x37c_camSpline.GetKnotPosition(3); - zeus::CVector3f desiredPos = FindDesiredPosition(distance, elevation, knotToBall, mgr); + zeus::CVector3f desiredPos = FindDesiredPosition(distance, elevation, knotToBall, mgr, false); if (x370_24_) x37c_camSpline.SetKnotPosition(3, desiredPos); @@ -1474,44 +1475,341 @@ zeus::CVector3f CBallCamera::ClampElevationToWater(zeus::CVector3f& pos, CStateM return ret; } +void CBallCamera::UpdateTransitionFromBallCamera(CStateManager& mgr) +{ + float f28 = mgr.GetPlayer().GetMorphFactor(); + zeus::CVector3f eyePos = mgr.GetPlayer().GetEyePosition(); + zeus::CVector3f delta = mgr.GetPlayer().GetTranslation() - x47c_failsafeState->x84_; + x47c_failsafeState->x90_bezPoints[1] += delta; + x47c_failsafeState->x90_bezPoints[2] += delta; + x47c_failsafeState->x90_bezPoints[3] += delta; + zeus::CVector3f x9c = GetFailsafeBezierPoint(x47c_failsafeState->x90_bezPoints, f28); + f28 = (x9c.z - eyePos.z) * zeus::clamp(0.f, 1.f - 1.5f * f28, 1.f); + x9c.z = f28 + eyePos.z; + zeus::CVector3f xa8 = eyePos - x9c; + xa8.z = 0.f; + if (xa8.magnitude() > 0.001f) + { + SetTransform(zeus::lookAt(x9c, eyePos)); + } + else + { + SetTransform(mgr.GetCameraManager()->GetFirstPersonCamera()->GetTransform()); + SetTranslation(x9c); + } + mgr.GetCameraManager()->GetFirstPersonCamera()->Reset(x34_transform, mgr); + x47c_failsafeState->x84_ = mgr.GetPlayer().GetTranslation(); +} + void CBallCamera::UpdateUsingTransitions(float dt, CStateManager& mgr) { + if (x400_state == EBallCameraState::Five) + { + UpdateTransitionFromBallCamera(mgr); + return; + } + x18d_26_ = false; + zeus::CVector3f ballPos = mgr.GetPlayer().GetBallPosition(); + zeus::CVector3f eyePos = mgr.GetPlayer().GetEyePosition(); + ballPos.z += x1b4_lookAtOffset.z; + + zeus::CVector3f lookDir = x34_transform.basis[1]; + zeus::CTransform xe8 = x34_transform; + + switch (x400_state) + { + case EBallCameraState::Four: + { + float elevation = x1a0_elevation; + float distance = x194_targetMinDistance; + ConstrainElevationAndDistance(elevation, distance, dt, mgr); + distance = x194_targetMinDistance; + bool r28 = IsBallNearDoor(GetTranslation(), mgr) || x478_ > 2; + zeus::CVector3f toDesired = + FindDesiredPosition(distance, elevation, mgr.GetPlayer().GetMoveDir(), mgr, r28) - eyePos; + zeus::CVector3f x214 = toDesired * mgr.GetPlayer().GetMorphFactor() + eyePos; + if (TCastToPtr act = mgr.ObjectById(x46c_collisionActorId)) + { + act->SetTranslation(GetTranslation()); + x214 = ClampElevationToWater(x214, mgr); + x214 = MoveCollisionActor(x214, dt, mgr); + zeus::CVector3f x220 = x1d8_ - x214; + if (x220.canBeNormalized()) + { + x220.normalize(); + float f22 = std::fabs(zeus::clamp(-1.f, lookDir.dot(x220), 1.f)); + float x380 = zeus::clamp(-1.f, mgr.GetPlayer().GetMorphFactor() * 0.5f, 1.f) * std::acos(f22); + if (f22 < 1.f) + SetTransform(zeus::CQuaternion::lookAt(xe8.basis[1], x220, x380).toTransform() * xe8.getRotation()); + else + SetTransform(zeus::lookAt(zeus::CVector3f::skZero, x220)); + } + } + SetTransform(ValidateCameraTransform(x34_transform, xe8)); + SetTranslation(x214); + TeleportCamera(x214, mgr); + break; + } + case EBallCameraState::Five: + { + if (std::fabs(mgr.GetPlayer().GetMorphFactor() - 1.f) < 0.00001f) + { + SetTransform(mgr.GetPlayer().GetTransform()); + SetTranslation(mgr.GetPlayer().GetEyePosition()); + } + else + { + float f28 = zeus::clamp(-1.f, mgr.GetPlayer().GetMorphFactor() / 0.9f, 1.f); + zeus::CVector3f x23c = GetTranslation(); + zeus::CVector3f x248 = GetTranslation() - eyePos; + if (x248.canBeNormalized()) + { + float f29 = x248.magnitude(); + f29 = std::min(f29, (1.f - mgr.GetPlayer().GetMorphFactor()) * x190_curMinDistance); + float f30 = M_PIF; + zeus::CVector3f x254 = GetTranslation() - mgr.GetPlayer().GetTranslation(); + zeus::CVector3f x260 = mgr.GetPlayer().GetMoveDir(); + if (x254.canBeNormalized()) + x254.normalize(); + else + x254 = -x260; + if (x260.canBeNormalized()) + { + x260.normalize(); + f30 = std::fabs(std::acos(zeus::clamp(-1.f, x254.dot(-x260), 1.f))) * f28 / dt; + } + zeus::CVector3f x26c = ConstrainYawAngle(mgr.GetPlayer(), f30, zeus::degToRad(10.f), dt, mgr); + x26c.z = 0.f; + x26c.normalize(); + zeus::CVector3f x360 = x26c * f29 + eyePos; + x360.z = (GetTranslation().z - eyePos.z) * f28 + eyePos.z; + x23c = ClampElevationToWater(x360, mgr); + x23c = MoveCollisionActor(x23c, dt, mgr); + zeus::CVector3f x284 = ballPos - x23c; + x284.z = 0.f; + zeus::CVector3f x278 = ballPos; + x278.z = f28 * (eyePos.z - ballPos.z) + ballPos.z; + if (x284.canBeNormalized()) + SetTransform(zeus::lookAt(x23c, x278)); + else + SetTransform(mgr.GetCameraManager()->GetFirstPersonCamera()->GetTransform()); + } + else + { + SetTransform(mgr.GetCameraManager()->GetFirstPersonCamera()->GetTransform()); + } + SetTranslation(x23c); + } + break; + } + default: + break; + } + + mgr.GetCameraManager()->GetFirstPersonCamera()->Reset(x34_transform, mgr); } zeus::CTransform CBallCamera::UpdateCameraPositions(float dt, const zeus::CTransform& oldXf, const zeus::CTransform& newXf) { - return {}; + zeus::CTransform useXf = newXf; + if (std::fabs(oldXf.basis[1].z) > 0.9f && std::fabs(newXf.basis[1].z) > 0.9f && + oldXf.basis[0].dot(newXf.basis[0]) <= 0.999f) + { + zeus::CVector3f x150 = zeus::CQuaternion::clampedRotateTo(oldXf.basis[0], newXf.basis[0], + zeus::degToRad(2.f * dt)).toTransform() * + oldXf.basis[0]; + if ((x150).dot(newXf.basis[1]) <= 0.999f) + { + zeus::CVector3f xe0 = newXf.basis[1].cross(x150).normalized(); + zeus::CVector3f x180 = newXf.basis[1].normalized(); + useXf = {xe0.cross(x180), newXf.basis[1], xe0, newXf.origin}; + } + } + return useXf; +} + +zeus::CVector3f CBallCamera::GetFailsafeBezierPoint(const std::vector& points, float t) +{ + t *= (points.size() - 3); + int baseIdx = 0; + while (t > 1.f) + { + t -= 1.f; + baseIdx += 1; + } + return zeus::getBezierPoint(points[baseIdx], points[baseIdx+1], points[baseIdx+2], points[baseIdx+3], t); } bool CBallCamera::CheckFailsafeFromMorphBallState(CStateManager& mgr) const { - return false; + TUniqueId xbb8 = kInvalidUniqueId; + float curT = 0.f; + rstl::reserved_vector nearList; + rstl::reserved_vector resultsA; + rstl::reserved_vector resultsB; + while (curT < 6.f) + { + zeus::CVector3f pointA = GetFailsafeBezierPoint(x47c_failsafeState->x90_bezPoints, curT / 6.f); + zeus::CVector3f pointB = GetFailsafeBezierPoint(x47c_failsafeState->x90_bezPoints, (1.f + curT) / 6.f); + zeus::CVector3f pointDelta = pointB - pointA; + if (pointDelta.magnitude() > 0.1f) + { + resultsA.push_back( + mgr.RayWorldIntersection(xbb8, pointA, pointDelta.normalized(), pointDelta.magnitude(), + BallCameraFilter, nearList)); + resultsB.push_back( + mgr.RayWorldIntersection(xbb8, pointB, -pointDelta.normalized(), pointDelta.magnitude(), + BallCameraFilter, nearList)); + } + else + { + resultsA.push_back({}); + resultsB.push_back({}); + } + curT += 1.f; + } + for (int i=0 ; ix90_bezPoints, + (1.f + i) / 6.f) - resA.GetPoint(); + if (separation.magnitude() > 0.3f) + return false; + } + } + return true; } bool CBallCamera::SplineIntersectTest(CMaterialList& intersectMat, CStateManager& mgr) const { - return false; + rstl::reserved_vector nearList; + TUniqueId xe38 = kInvalidUniqueId; + rstl::reserved_vector xacc; + rstl::reserved_vector xd10; + CMaterialFilter filter = CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid, + EMaterialTypes::Floor, + EMaterialTypes::Wall}, + {EMaterialTypes::ProjectilePassthrough, + EMaterialTypes::Player, + EMaterialTypes::Character, + EMaterialTypes::CameraPassthrough}); + float f29 = 0.f; + while (f29 < 12.f) + { + zeus::CVector3f xdb0 = x37c_camSpline.GetInterpolatedSplinePointByTime(f29, 12.f); + zeus::CVector3f xdbc = x37c_camSpline.GetInterpolatedSplinePointByTime(f29, 12.f); + zeus::CVector3f xdc8 = xdbc - xdb0; + if (xdc8.magnitude() > 0.1f) + { + xacc.push_back( + mgr.RayWorldIntersection(xe38, xdb0, xdc8.normalized(), xdc8.magnitude(), filter, nearList)); + xd10.push_back( + mgr.RayWorldIntersection(xe38, xdbc, -xdc8.normalized(), xdc8.magnitude(), filter, nearList)); + } + else + { + xacc.push_back({}); + xd10.push_back({}); + } + f29 += 1.f; + } + for (int i=0 ; i 0.3f) + return false; + } + } + return true; } bool CBallCamera::IsBallNearDoor(const zeus::CVector3f& pos, CStateManager& mgr) { + TCastToConstPtr door = + mgr.GetObjectById(mgr.GetCameraManager()->GetBallCamera()->x3dc_tooCloseActorId); + if (!door || door->x2a8_26_) + return false; + + auto x2c = door->GetTouchBounds(); + zeus::CAABox testAABB(pos - 0.3f, pos + 0.3f); + if (!x2c || !x2c->intersects(testAABB)) + return false; + + if (TCastToConstPtr dock = mgr.GetObjectById(door->x282_dockId)) + if (std::fabs(dock->GetPlane(mgr).pointToPlaneDist(pos)) < 1.15f) + return true; + return false; } void CBallCamera::ActivateFailsafe(float dt, CStateManager& mgr) { - + float elevation = x1a0_elevation; + float distance = x194_targetMinDistance; + ConstrainElevationAndDistance(elevation, distance, dt, mgr); + zeus::CVector3f desiredPos = FindDesiredPosition(distance, elevation, mgr.GetPlayer().GetMoveDir(), mgr, true); + SetTranslation(desiredPos); + ResetPosition(mgr); + TeleportCamera(zeus::lookAt(desiredPos, x1d8_), mgr); + mgr.GetCameraManager()->SetPlayerCamera(mgr, GetUniqueId()); + x3e4_ = false; + x34c_ = 0.f; } bool CBallCamera::ConstrainElevationAndDistance(float& elevation, float& distance, float dt, CStateManager& mgr) { - return false; + zeus::CVector3f x68 = GetTranslation() - mgr.GetPlayer().GetBallPosition(); + float f31 = 0.f; + if (x68.canBeNormalized()) + f31 = x68.toVec2f().magnitude(); + else + x68 = -mgr.GetPlayer().GetMoveDir(); + + bool r31 = false; + float f30 = 1.f; + float f1 = distance; + float f28 = elevation; + float f0 = 1.f; + if (TCastToConstPtr door = mgr.GetObjectById(x3dc_tooCloseActorId)) + { + if (!door->x2a8_29_ballDoor) + { + f30 = zeus::clamp(-1.f, std::fabs(x3e0_tooCloseActorDist / (3.f * distance)), 1.f); + if (x3e0_tooCloseActorDist < 3.f * distance) + r31 = true; + if (door->x2a8_26_) + f1 = f30 * (distance - x468_) + x468_; + else + f1 = f30 * (distance - 5.f) + 5.f; + if (x18d_28_) + f1 *= 1.f + x308_; + f28 = door->x2a8_26_ ? 0.75f : 1.5f; + f0 = 4.f; + } + } + + x214_ballCameraSpring.ApplyDistanceSpring(f1, f31, dt * f0); + distance = f1; + elevation = (elevation - f28) * f30 + f28; + + return r31; } zeus::CVector3f CBallCamera::FindDesiredPosition(float distance, float elevation, - const zeus::CVector3f& dir, CStateManager& mgr) + const zeus::CVector3f& dir, CStateManager& mgr, bool b) { return {}; } @@ -1595,9 +1893,70 @@ void CBallCamera::Think(float dt, CStateManager& mgr) } } +bool CBallCamera::CheckTransitionLineOfSight(const zeus::CVector3f& eyePos, const zeus::CVector3f& behindPos, + float& eyeToOccDist, float colRadius, CStateManager& mgr) +{ + zeus::CVector3f eyeToBehind = behindPos - eyePos; + float eyeToBehindMag = eyeToBehind.magnitude(); + zeus::CVector3f eyeToBehindNorm = eyeToBehind * (1.f / eyeToBehindMag); + bool clear = true; + if (eyeToBehindMag > 0.000001f) + { + float margin = 2.f * colRadius; + zeus::CAABox aabb; + aabb.accumulateBounds(eyePos); + aabb.accumulateBounds(behindPos); + aabb = zeus::CAABox(aabb.min - margin, aabb.max + margin); + rstl::reserved_vector nearList; + mgr.BuildColliderList(nearList, mgr.GetPlayer(), aabb); + CAreaCollisionCache cache(aabb); + CGameCollision::BuildAreaCollisionCache(mgr, cache); + if (cache.HasCacheOverflowed()) + clear = false; + if (clear) + { + CCollisionInfo cinfo; + double d = eyeToBehindMag; + TUniqueId intersectId = kInvalidUniqueId; + CCollidableSphere cSphere({zeus::CVector3f::skZero, colRadius}, {EMaterialTypes::Solid}); + if (CGameCollision::DetectCollision_Cached_Moving(mgr, cache, cSphere, zeus::CTransform::Translate(eyePos), + CMaterialFilter::MakeIncludeExclude( + {EMaterialTypes::Solid}, + {EMaterialTypes::ProjectilePassthrough, + EMaterialTypes::Player, + EMaterialTypes::Character, + EMaterialTypes::CameraPassthrough}), + nearList, eyeToBehindNorm, intersectId, cinfo, d)) + { + eyeToOccDist = float(d); + clear = false; + } + } + } + return !clear; +} + bool CBallCamera::TransitionFromMorphBallState(CStateManager& mgr) { - return false; + x47c_failsafeState->x0_ = mgr.GetPlayer().GetTransform(); + x47c_failsafeState->x30_ = GetTransform(); + x47c_failsafeState->x60_ = x1d8_; + x47c_failsafeState->x84_ = x47c_failsafeState->x0_.origin; + zeus::CVector3f eyePos = mgr.GetPlayer().GetEyePosition(); + float f28 = (x47c_failsafeState->x60_ - x47c_failsafeState->x30_.origin).magnitude(); + zeus::CVector3f behindPos = x47c_failsafeState->x0_.basis[1] * (0.6f * -f28) + eyePos; + float eyeToOccDist; + if (CheckTransitionLineOfSight(eyePos, behindPos, eyeToOccDist, 0.6f, mgr)) + x47c_failsafeState->x6c_ = x47c_failsafeState->x0_.basis[1] * -eyeToOccDist + eyePos; + else + x47c_failsafeState->x6c_ = behindPos; + x47c_failsafeState->x90_bezPoints.clear(); + x47c_failsafeState->x90_bezPoints.reserve(4); + x47c_failsafeState->x90_bezPoints.push_back(x47c_failsafeState->x30_.origin); + x47c_failsafeState->x90_bezPoints.push_back(x47c_failsafeState->x6c_); + x47c_failsafeState->x90_bezPoints.push_back(x47c_failsafeState->x6c_); + x47c_failsafeState->x90_bezPoints.push_back(eyePos); + return CheckFailsafeFromMorphBallState(mgr); } void CBallCamera::TeleportColliders(std::vector& colliderList, const zeus::CVector3f& pos) @@ -1628,7 +1987,35 @@ void CBallCamera::TeleportCamera(const zeus::CTransform& xf, CStateManager& mgr) void CBallCamera::ResetToTweaks(CStateManager& mgr) { - + x188_behaviour = EBallCameraBehaviour::Zero; + x18c_25_ = true; + x18c_26_ = true; + x18c_27_ = true; + x18c_28_ = true; + x18c_29_ = false; + x18c_30_ = false; + x194_targetMinDistance = g_tweakBall->GetBallCameraMinSpeedDistance(); + x198_maxDistance = g_tweakBall->GetBallCameraMaxSpeedDistance(); + x19c_backwardsDistance = g_tweakBall->GetBallCameraBackwardsDistance(); + x214_ballCameraSpring = CCameraSpring(g_tweakBall->GetBallCameraSpringConstant(), + g_tweakBall->GetBallCameraSpringMax(), + g_tweakBall->GetBallCameraSpringTardis()); + x250_ballCameraCentroidDistanceSpring = CCameraSpring(g_tweakBall->GetBallCameraCentroidDistanceSpringConstant(), + g_tweakBall->GetBallCameraCentroidDistanceSpringMax(), + g_tweakBall->GetBallCameraCentroidDistanceSpringTardis()); + x1b4_lookAtOffset = g_tweakBall->GetBallCameraOffset(); + x410_chaseLookAtOffset = g_tweakBall->GetBallCameraChaseLookAtOffset(); + x1a0_elevation = g_tweakBall->GetBallCameraElevation(); + x1ac_ = M_PIF / 2.f; + x1b0_ = M_PIF / 2.f; + SetFovInterpolation(x15c_currentFov, CCameraManager::ThirdPersonFOV(), 1.f, 0.f); + x1a8_targetAnglePerSecond = g_tweakBall->GetBallCameraAnglePerSecond(); + x18d_29_ = false; + x18d_30_ = false; + x18d_31_ = false; + x18e_24_ = false; + x18e_25_ = false; + x18e_26_ = false; } void CBallCamera::UpdateLookAtPosition(float dt, CStateManager& mgr) @@ -1646,9 +2033,12 @@ void CBallCamera::ApplyCameraHint(CStateManager& mgr) } -void CBallCamera::ResetPosition() +void CBallCamera::ResetPosition(CStateManager& mgr) { - + x1d8_ = mgr.GetPlayer().GetBallPosition(); + x1d8_.z += x1b4_lookAtOffset.z; + x1c0_ = x1d8_; + x1cc_ = x1d8_; } void CBallCamera::DoorClosed(TUniqueId doorId) diff --git a/Runtime/Camera/CBallCamera.hpp b/Runtime/Camera/CBallCamera.hpp index a42c14e3c..9343b6bed 100644 --- a/Runtime/Camera/CBallCamera.hpp +++ b/Runtime/Camera/CBallCamera.hpp @@ -72,7 +72,7 @@ private: zeus::CVector3f x6c_; zeus::CVector3f x78_; zeus::CVector3f x84_; - std::vector x90_; + std::vector 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_; @@ -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& 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); bool ConstrainElevationAndDistance(float& elevation, float& distance, float dt, CStateManager& mgr); - zeus::CVector3f FindDesiredPosition(float distance, float elevation, const zeus::CVector3f& dir, 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& 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); }; diff --git a/Runtime/Camera/CCameraManager.cpp b/Runtime/Camera/CCameraManager.cpp index fb70a61ca..5f0f4f836 100644 --- a/Runtime/Camera/CCameraManager.cpp +++ b/Runtime/Camera/CCameraManager.cpp @@ -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()) { diff --git a/Runtime/Camera/CCameraSpline.cpp b/Runtime/Camera/CCameraSpline.cpp index 010f2a13e..e6a7505fb 100644 --- a/Runtime/Camera/CCameraSpline.cpp +++ b/Runtime/Camera/CCameraSpline.cpp @@ -197,7 +197,7 @@ bool CCameraSpline::GetSurroundingPoints(int idx, rstl::reserved_vectorGetMorphballTransitionState() != 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; } } diff --git a/Runtime/MP1/CSamusHud.cpp b/Runtime/MP1/CSamusHud.cpp index ca2f7842c..ced0d158a 100644 --- a/Runtime/MP1/CSamusHud.cpp +++ b/Runtime/MP1/CSamusHud.cpp @@ -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; } diff --git a/Runtime/World/CPlayer.cpp b/Runtime/World/CPlayer.cpp index 5ec8a79a4..b873e6800 100644 --- a/Runtime/World/CPlayer.cpp +++ b/Runtime/World/CPlayer.cpp @@ -281,7 +281,7 @@ void CPlayer::TransitionFromMorphBallState(CStateManager& mgr) CBallCamera* ballCam = mgr.GetCameraManager()->GetBallCamera(); if (TCastToConstPtr 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; diff --git a/Runtime/World/CPlayer.hpp b/Runtime/World/CPlayer.hpp index 736e76858..4ca86393a 100644 --- a/Runtime/World/CPlayer.hpp +++ b/Runtime/World/CPlayer.hpp @@ -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(); } diff --git a/specter b/specter index 1d44b0463..126de2c01 160000 --- a/specter +++ b/specter @@ -1 +1 @@ -Subproject commit 1d44b04638cf1ce3947477254ac3255868b650d2 +Subproject commit 126de2c01b9acf3ff7917d63b04ba52b2fca3e91