| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361 |
- /*
- ** Command & Conquer Renegade(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- #ifndef RBODY_H
- #define RBODY_H
- #include "always.h"
- #include "movephys.h"
- #include "ode.h"
- #include "aabox.h"
- #include "quat.h"
- #include "physcon.h"
- #include "wwdebug.h"
- class RigidBodyDefClass;
- class OBBoxRenderObjClass;
- class PaddedBoxClass;
- class OctBoxClass;
- class RBodyHistoryClass;
- struct CastResultStruct;
- const int MAX_CONTACT_POINTS = 10;
- const float RBODY_SLEEP_DELAY = 0.5f; // if still for this many seconds, shut off simulation
- /**
- ** RigidBodyStateStruct
- ** This is the state vector for a RigidBodyClass.
- */
- struct RigidBodyStateStruct
- {
- RigidBodyStateStruct(void) {}
- RigidBodyStateStruct(const RigidBodyStateStruct & that);
- RigidBodyStateStruct & operator = (const RigidBodyStateStruct & that);
-
- void Reset(void);
- void To_Vector(StateVectorClass & vec);
- int From_Vector(const StateVectorClass & vec,int index);
- static void Lerp(const RigidBodyStateStruct & s0,const RigidBodyStateStruct & s1,float fraction,RigidBodyStateStruct * res);
- bool Is_Valid(void) { return (Position.Is_Valid() && Orientation.Is_Valid() && LMomentum.Is_Valid() && AMomentum.Is_Valid()); }
- Vector3 Position;
- Quaternion Orientation;
- Vector3 LMomentum;
- Vector3 AMomentum;
- };
- /**
- ** RigidBodyClass
- ** Simulation of a rigid body. The shape is limited to be an oriented box.
- */
- class RigidBodyClass : public MoveablePhysClass , public ODESystemClass
- {
- public:
- RigidBodyClass(void);
- virtual ~RigidBodyClass(void);
- virtual RigidBodyClass * As_RigidBodyClass(void) { return this; }
- RigidBodyDefClass * Get_RigidBodyDef(void) { return (RigidBodyDefClass *)Definition; }
- void Init(const RigidBodyDefClass & definition);
- virtual const AABoxClass & Get_Bounding_Box(void) const;
- virtual const Matrix3D & Get_Transform(void) const;
- virtual void Set_Transform(const Matrix3D & m);
- virtual bool Cast_Ray(PhysRayCollisionTestClass & raytest);
- virtual bool Cast_AABox(PhysAABoxCollisionTestClass & boxtest);
- virtual bool Cast_OBBox(PhysOBBoxCollisionTestClass & boxtest);
- virtual bool Intersection_Test(PhysAABoxIntersectionTestClass & test);
- virtual bool Intersection_Test(PhysOBBoxIntersectionTestClass & test);
- virtual bool Intersection_Test(PhysMeshIntersectionTestClass & test);
- /*
- ** Teleport support
- */
- virtual bool Can_Teleport(const Matrix3D &new_tm, bool check_dyn_only = false,NonRefPhysListClass * result_list = NULL);
- virtual bool Can_Teleport_And_Stand(const Matrix3D &new_tm, Matrix3D *out);
- /*
- ** State
- */
- void Get_Orientation(Quaternion * set_q) const { *set_q = State.Orientation; }
- virtual void Get_Velocity(Vector3 * set_vel) const;
- virtual void Get_Angular_Velocity(Vector3 * set_avel) const;
- virtual void Set_Velocity(const Vector3 & newvel);
- virtual void Set_Angular_Velocity(const Vector3 & newavel);
- virtual void Apply_Impulse(const Vector3 & imp);
- virtual void Apply_Impulse(const Vector3 & imp, const Vector3 & wpos);
- virtual void Timestep(float dt);
- void Compute_Point_Velocity(const Vector3 & p,Vector3 * pdot);
- float Get_Last_Timestep(void) { return LastTimestep; }
- /*
- ** Networking code.
- ** Network_Interpolate_State_Update - interpolate towards the given state
- ** Network_Latency_State_Update - client player update, interpolate, considering latency.
- */
- void Network_Interpolate_State_Update( const Vector3 & new_pos,
- const Quaternion & new_orientation,
- const Vector3 & new_vel,
- const Vector3 & new_avel,
- float blend_fraction);
- void Network_Latency_State_Update( const Vector3 & new_pos,
- const Quaternion & new_orientation,
- const Vector3 & new_vel,
- const Vector3 & new_avel);
-
- static void Set_Correction_Time(float time) { _CorrectionTime = time; }
- static float Get_Correction_Time(void) { return _CorrectionTime; }
- /*
- ** Properties
- */
- virtual void Set_Model(RenderObjClass * model);
- virtual void Set_Mass(float mass);
- virtual void Get_Inertia_Inv(Matrix3 * set_I_inv);
- void Set_Inertia(const Matrix3 & I);
- void Get_Inertia(Matrix3 * I);
- void Set_Contact_Parameters(float length);
- void Get_Contact_Parameters(float * stiffness,float * damping,float * length);
- float Get_Weight(void) { return GravScale * Mass * (-PhysicsConstants::GravityAcceleration.Z); }
- /*
- ** Shadow support
- */
- virtual void Get_Shadow_Blob_Box(AABoxClass * set_obj_space_box);
- /*
- ** MoveablePhysClass Push interface. RigidBody's try to move when they are pushed.
- */
- virtual bool Push(const Vector3 & move);
- /*
- ** Save-Load System
- */
- virtual const PersistFactoryClass & Get_Factory (void) const;
- virtual bool Save (ChunkSaveClass &csave);
- virtual bool Load (ChunkLoadClass &cload);
- virtual void On_Post_Load(void);
- protected:
- /*
- ** Integration system
- */
- virtual void Get_State(StateVectorClass & set_state);
- virtual int Set_State(const StateVectorClass & new_state,int start_index);
- void Set_State(const RigidBodyStateStruct & new_state);
- virtual int Compute_Derivatives(float t,StateVectorClass * test_state,StateVectorClass * set_derivs,int start_index);
- void Integrate(float time);
- /*
- ** Internal functions
- */
- void Update_Cached_Model_Parameters(void);
- virtual void Compute_Inertia(void);
- void Update_Auxiliary_State(void);
- virtual void Compute_Force_And_Torque(Vector3 * force,Vector3 * torque);
- void Compute_Impact(const CastResultStruct & result,Vector3 * impulse);
- void Compute_Impact(const Vector3 & point,const Vector3 & normal,Vector3 * impulse);
- bool Is_Colliding(const Vector3 & point, const Vector3 & normal);
- void Set_Moving_Collision_Region(float dt);
- void Set_Stationary_Collision_Region(void);
- virtual bool Can_Go_To_Sleep(float dt);
- bool Find_State_In_Contact_Zone(const RigidBodyStateStruct & oldstate);
- bool Push_Phys3_Object_Away(Phys3Class * p3obj,const CastResultStruct & contact);
- void Network_Latency_Error_Correction(float dt);
- void Assert_State_Valid(void) const;
- void Assert_Not_Intersecting(void);
- void Dump_State(void) const;
-
- /*
- ** Physical Description:
- */
- OBBoxRenderObjClass * Box; // World-Space Box
- Matrix3 IBody; // Body space inertia tensor
- Matrix3 IBodyInv; // Inverse of the body space inertia tensor
- OctBoxClass * ContactBox; // datastructure for finding contact points
- float ContactThickness; // Dimension of the contact region
- /*
- ** State vector
- */
- RigidBodyStateStruct State; // current state vector
-
- /*
- ** Quantities derived from (dependent on) the current state
- */
- Matrix3 Rotation;
- Matrix3 IInv;
- Vector3 Velocity;
- Vector3 AngularVelocity;
- /*
- ** Other Member variables
- */
- bool IsInContact;
- int ContactCount;
- Vector3 ContactPoint[MAX_CONTACT_POINTS];
- Vector3 ContactNormal;
- int StickCount;
- float LastTimestep;
- float GoToSleepTimer;
- /*
- ** Network history for latency handling
- */
- RBodyHistoryClass * History;
- RigidBodyStateStruct LatencyError;
- RigidBodyStateStruct LastKnownState;
- static float _CorrectionTime;
- private:
- // not implemented
- RigidBodyClass(const RigidBodyClass &);
- RigidBodyClass & operator = (const RigidBodyClass &);
- };
- inline RigidBodyStateStruct::RigidBodyStateStruct(const RigidBodyStateStruct & that)
- {
- *this = that;
- }
- inline RigidBodyStateStruct & RigidBodyStateStruct::operator = (const RigidBodyStateStruct & that)
- {
- Position = that.Position;
- Orientation = that.Orientation;
- LMomentum = that.LMomentum;
- AMomentum = that.AMomentum;
- return *this;
- }
- inline void RigidBodyStateStruct::Reset(void)
- {
- Position.Set(0,0,0);
- Orientation.Make_Identity();
- LMomentum.Set(0,0,0);
- AMomentum.Set(0,0,0);
- }
- inline void RigidBodyStateStruct::To_Vector(StateVectorClass & vec)
- {
- vec.Add(Position[0]);
- vec.Add(Position[1]);
- vec.Add(Position[2]);
-
- vec.Add(Orientation[0]);
- vec.Add(Orientation[1]);
- vec.Add(Orientation[2]);
- vec.Add(Orientation[3]);
- vec.Add(LMomentum[0]);
- vec.Add(LMomentum[1]);
- vec.Add(LMomentum[2]);
- vec.Add(AMomentum[0]);
- vec.Add(AMomentum[1]);
- vec.Add(AMomentum[2]);
- }
- inline int RigidBodyStateStruct::From_Vector(const StateVectorClass & vec,int index)
- {
- Position[0] = vec[index++];
- Position[1] = vec[index++];
- Position[2] = vec[index++];
- Orientation[0] = vec[index++];
- Orientation[1] = vec[index++];
- Orientation[2] = vec[index++];
- Orientation[3] = vec[index++];
- LMomentum[0] = vec[index++];
- LMomentum[1] = vec[index++];
- LMomentum[2] = vec[index++];
-
- AMomentum[0] = vec[index++];
- AMomentum[1] = vec[index++];
- AMomentum[2] = vec[index++];
- return index;
- }
- inline void RigidBodyStateStruct::Lerp
- (
- const RigidBodyStateStruct & s0,
- const RigidBodyStateStruct & s1,
- float fraction,
- RigidBodyStateStruct * res
- )
- {
- Vector3::Lerp(s0.Position,s1.Position,fraction,&(res->Position));
- Vector3::Lerp(s0.LMomentum,s1.LMomentum,fraction,&(res->LMomentum));
- Vector3::Lerp(s0.AMomentum,s1.AMomentum,fraction,&(res->AMomentum));
- ::Fast_Slerp(res->Orientation,s0.Orientation,s1.Orientation,fraction);
- }
- /**
- ** RigidBodyDefClass
- ** Initialization data structure for RigidBodyClass
- */
- class RigidBodyDefClass : public MoveablePhysDefClass
- {
- public:
- RigidBodyDefClass(void);
-
- // From DefinitionClass
- virtual uint32 Get_Class_ID (void) const;
- virtual PersistClass * Create(void) const;
- // From PhysDefClass
- virtual const char * Get_Type_Name(void) { return "RigidBodyDef"; }
- virtual bool Is_Type(const char *);
- // From PersistClass
- virtual const PersistFactoryClass & Get_Factory (void) const;
- virtual bool Save(ChunkSaveClass &csave);
- virtual bool Load(ChunkLoadClass &cload);
- // In-Game Editing (DEBUGGING/TESTING ONLY)
- float Get_Aerodynamic_Drag(void) { return AerodynamicDragCoefficient; }
- void Set_Aerodynamic_Drag(float new_drag) { AerodynamicDragCoefficient = new_drag; }
- // Editable interface requirements
- DECLARE_EDITABLE(RigidBodyDefClass,MoveablePhysDefClass);
- protected:
- // Variables
- float AerodynamicDragCoefficient;
- bool CollisionDisabled;
- friend class RigidBodyClass;
- };
- #endif
|