mirror of https://github.com/AxioDL/metaforce.git
More CBallCamera and CCameraSpline work
This commit is contained in:
parent
651d0a27c2
commit
16f6307642
|
@ -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<CPhysicsActor> 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<CPhysicsActor> 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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
@ -27,12 +27,12 @@ void CCameraSpline::CalculateKnots(TUniqueId cameraId, const std::vector<SConnec
|
|||
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 +50,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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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 {};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,10 +11,12 @@ class CCameraSpline
|
|||
friend class CBallCamera;
|
||||
std::vector<zeus::CVector3f> x4_positions;
|
||||
std::vector<TUniqueId> x14_;
|
||||
std::vector<float> x24_;
|
||||
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);
|
||||
zeus::CVector3f GetInterpolatedSplinePointByTime(float time, float range);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue