metaforce/Runtime/Character/CRagDoll.hpp

144 lines
5.2 KiB
C++

#pragma once
#include <vector>
#include "Runtime/RetroTypes.hpp"
#include "Runtime/Character/CSegId.hpp"
#include <zeus/CAABox.hpp>
#include <zeus/CQuaternion.hpp>
#include <zeus/CVector3f.hpp>
namespace urde {
class CCharLayoutInfo;
class CHierarchyPoseBuilder;
class CModelData;
class CStateManager;
class CRagDoll {
protected:
class CRagDollParticle {
friend class CRagDoll;
CSegId x0_id;
zeus::CVector3f x4_curPos;
float x10_radius;
zeus::CVector3f x14_prevPos;
zeus::CVector3f x20_velocity;
zeus::CVector3f x2c_impactResponseDelta;
float x38_impactFrameVel = 0.f;
bool x3c_24_impactPending : 1;
bool x3c_25_ : 1;
public:
CRagDollParticle(CSegId id, const zeus::CVector3f& curPos, float radius, const zeus::CVector3f& prevPos)
: x0_id(id), x4_curPos(curPos), x10_radius(radius), x14_prevPos(prevPos) {
x3c_24_impactPending = false;
x3c_25_ = false;
}
CSegId GetBone() const { return x0_id; }
const zeus::CVector3f& GetPosition() const { return x4_curPos; }
zeus::CVector3f& Position() { return x4_curPos; }
const zeus::CVector3f& GetVelocity() const { return x20_velocity; }
zeus::CVector3f& Velocity() { return x20_velocity; }
float GetRadius() const { return x10_radius; }
};
class CRagDollLengthConstraint {
friend class CRagDoll;
CRagDollParticle* x0_p1;
CRagDollParticle* x4_p2;
float x8_length;
int xc_ineqType;
public:
CRagDollLengthConstraint(CRagDollParticle* p1, CRagDollParticle* p2, float f1, int i1)
: x0_p1(p1), x4_p2(p2), x8_length(f1), xc_ineqType(i1) {}
void Update();
float GetLength() const { return x8_length; }
};
class CRagDollJointConstraint {
friend class CRagDoll;
CRagDollParticle* x0_p1; // Shoulder plane 0
CRagDollParticle* x4_p2; // Shoulder plane 1
CRagDollParticle* x8_p3; // Shoulder plane 2
CRagDollParticle* xc_p4; // Shoulder
CRagDollParticle* x10_p5; // Elbow
CRagDollParticle* x14_p6; // Wrist
public:
CRagDollJointConstraint(CRagDollParticle* p1, CRagDollParticle* p2, CRagDollParticle* p3, CRagDollParticle* p4,
CRagDollParticle* p5, CRagDollParticle* p6)
: x0_p1(p1), x4_p2(p2), x8_p3(p3), xc_p4(p4), x10_p5(p5), x14_p6(p6) {}
void Update();
};
class CRagDollPlaneConstraint {
friend class CRagDoll;
CRagDollParticle* x0_p1;
CRagDollParticle* x4_p2;
CRagDollParticle* x8_p3;
CRagDollParticle* xc_p4;
CRagDollParticle* x10_p5;
public:
CRagDollPlaneConstraint(CRagDollParticle* p1, CRagDollParticle* p2, CRagDollParticle* p3, CRagDollParticle* p4,
CRagDollParticle* p5)
: x0_p1(p1), x4_p2(p2), x8_p3(p3), xc_p4(p4), x10_p5(p5) {}
void Update();
};
std::vector<CRagDollParticle> x4_particles;
std::vector<CRagDollLengthConstraint> x14_lengthConstraints;
std::vector<CRagDollJointConstraint> x24_jointConstraints;
std::vector<CRagDollPlaneConstraint> x34_planeConstraints;
float x44_normalGravity;
float x48_floatingGravity;
u32 x4c_impactCount = 0;
float x50_overTimer;
float x54_impactVel = 0.f;
zeus::CVector3f x58_averageVel;
float x64_angTimer = 0.f;
union {
struct {
bool x68_24_prevMovingSlowly : 1;
bool x68_25_over : 1;
bool x68_26_primed : 1;
bool x68_27_continueSmallMovements : 1;
bool x68_28_noOverTimer : 1;
bool x68_29_noAiCollision : 1;
};
u32 _dummy = 0;
};
void AccumulateForces(float dt, float waterTop);
void SetNumParticles(int num) { x4_particles.reserve(num); }
void AddParticle(CSegId id, const zeus::CVector3f& prevPos, const zeus::CVector3f& curPos, float radius);
void SetNumLengthConstraints(int num) { x14_lengthConstraints.reserve(num); }
void AddLengthConstraint(int i1, int i2);
void AddMaxLengthConstraint(int i1, int i2, float length);
void AddMinLengthConstraint(int i1, int i2, float length);
void SetNumJointConstraints(int num) { x24_jointConstraints.reserve(num); }
void AddJointConstraint(int i1, int i2, int i3, int i4, int i5, int i6);
zeus::CQuaternion BoneAlign(CHierarchyPoseBuilder& pb, const CCharLayoutInfo& charInfo, int i1, int i2,
const zeus::CQuaternion& q);
void CheckStatic(float dt);
void ClearForces();
void SatisfyConstraints(CStateManager& mgr);
bool SatisfyWorldConstraints(CStateManager& mgr, int pass);
void SatisfyWorldConstraintsOnConstruction(CStateManager& mgr);
void Verlet(float dt);
public:
virtual ~CRagDoll() = default;
CRagDoll(float normalGravity, float floatingGravity, float overTime, u32 flags);
virtual void PreRender(const zeus::CVector3f& v, CModelData& mData);
virtual void Update(CStateManager& mgr, float dt, float waterTop);
virtual void Prime(CStateManager& mgr, const zeus::CTransform& xf, CModelData& mData);
zeus::CAABox CalculateRenderBounds() const;
bool IsPrimed() const { return x68_26_primed; }
bool WillContinueSmallMovements() const { return x68_27_continueSmallMovements; }
bool IsOver() const { return x68_25_over; }
void SetNoOverTimer(bool b) { x68_28_noOverTimer = b; }
void SetContinueSmallMovements(bool b) { x68_27_continueSmallMovements = b; }
u32 GetImpactCount() const { return x4c_impactCount; }
};
} // namespace urde