rbody.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #ifndef RBODY_H
  19. #define RBODY_H
  20. #include "always.h"
  21. #include "movephys.h"
  22. #include "ode.h"
  23. #include "aabox.h"
  24. #include "quat.h"
  25. #include "physcon.h"
  26. #include "wwdebug.h"
  27. class RigidBodyDefClass;
  28. class OBBoxRenderObjClass;
  29. class PaddedBoxClass;
  30. class OctBoxClass;
  31. class RBodyHistoryClass;
  32. struct CastResultStruct;
  33. const int MAX_CONTACT_POINTS = 10;
  34. const float RBODY_SLEEP_DELAY = 0.5f; // if still for this many seconds, shut off simulation
  35. /**
  36. ** RigidBodyStateStruct
  37. ** This is the state vector for a RigidBodyClass.
  38. */
  39. struct RigidBodyStateStruct
  40. {
  41. RigidBodyStateStruct(void) {}
  42. RigidBodyStateStruct(const RigidBodyStateStruct & that);
  43. RigidBodyStateStruct & operator = (const RigidBodyStateStruct & that);
  44. void Reset(void);
  45. void To_Vector(StateVectorClass & vec);
  46. int From_Vector(const StateVectorClass & vec,int index);
  47. static void Lerp(const RigidBodyStateStruct & s0,const RigidBodyStateStruct & s1,float fraction,RigidBodyStateStruct * res);
  48. bool Is_Valid(void) { return (Position.Is_Valid() && Orientation.Is_Valid() && LMomentum.Is_Valid() && AMomentum.Is_Valid()); }
  49. Vector3 Position;
  50. Quaternion Orientation;
  51. Vector3 LMomentum;
  52. Vector3 AMomentum;
  53. };
  54. /**
  55. ** RigidBodyClass
  56. ** Simulation of a rigid body. The shape is limited to be an oriented box.
  57. */
  58. class RigidBodyClass : public MoveablePhysClass , public ODESystemClass
  59. {
  60. public:
  61. RigidBodyClass(void);
  62. virtual ~RigidBodyClass(void);
  63. virtual RigidBodyClass * As_RigidBodyClass(void) { return this; }
  64. RigidBodyDefClass * Get_RigidBodyDef(void) { return (RigidBodyDefClass *)Definition; }
  65. void Init(const RigidBodyDefClass & definition);
  66. virtual const AABoxClass & Get_Bounding_Box(void) const;
  67. virtual const Matrix3D & Get_Transform(void) const;
  68. virtual void Set_Transform(const Matrix3D & m);
  69. virtual bool Cast_Ray(PhysRayCollisionTestClass & raytest);
  70. virtual bool Cast_AABox(PhysAABoxCollisionTestClass & boxtest);
  71. virtual bool Cast_OBBox(PhysOBBoxCollisionTestClass & boxtest);
  72. virtual bool Intersection_Test(PhysAABoxIntersectionTestClass & test);
  73. virtual bool Intersection_Test(PhysOBBoxIntersectionTestClass & test);
  74. virtual bool Intersection_Test(PhysMeshIntersectionTestClass & test);
  75. /*
  76. ** Teleport support
  77. */
  78. virtual bool Can_Teleport(const Matrix3D &new_tm, bool check_dyn_only = false,NonRefPhysListClass * result_list = NULL);
  79. virtual bool Can_Teleport_And_Stand(const Matrix3D &new_tm, Matrix3D *out);
  80. /*
  81. ** State
  82. */
  83. void Get_Orientation(Quaternion * set_q) const { *set_q = State.Orientation; }
  84. virtual void Get_Velocity(Vector3 * set_vel) const;
  85. virtual void Get_Angular_Velocity(Vector3 * set_avel) const;
  86. virtual void Set_Velocity(const Vector3 & newvel);
  87. virtual void Set_Angular_Velocity(const Vector3 & newavel);
  88. virtual void Apply_Impulse(const Vector3 & imp);
  89. virtual void Apply_Impulse(const Vector3 & imp, const Vector3 & wpos);
  90. virtual void Timestep(float dt);
  91. void Compute_Point_Velocity(const Vector3 & p,Vector3 * pdot);
  92. float Get_Last_Timestep(void) { return LastTimestep; }
  93. /*
  94. ** Networking code.
  95. ** Network_Interpolate_State_Update - interpolate towards the given state
  96. ** Network_Latency_State_Update - client player update, interpolate, considering latency.
  97. */
  98. void Network_Interpolate_State_Update( const Vector3 & new_pos,
  99. const Quaternion & new_orientation,
  100. const Vector3 & new_vel,
  101. const Vector3 & new_avel,
  102. float blend_fraction);
  103. void Network_Latency_State_Update( const Vector3 & new_pos,
  104. const Quaternion & new_orientation,
  105. const Vector3 & new_vel,
  106. const Vector3 & new_avel);
  107. static void Set_Correction_Time(float time) { _CorrectionTime = time; }
  108. static float Get_Correction_Time(void) { return _CorrectionTime; }
  109. /*
  110. ** Properties
  111. */
  112. virtual void Set_Model(RenderObjClass * model);
  113. virtual void Set_Mass(float mass);
  114. virtual void Get_Inertia_Inv(Matrix3 * set_I_inv);
  115. void Set_Inertia(const Matrix3 & I);
  116. void Get_Inertia(Matrix3 * I);
  117. void Set_Contact_Parameters(float length);
  118. void Get_Contact_Parameters(float * stiffness,float * damping,float * length);
  119. float Get_Weight(void) { return GravScale * Mass * (-PhysicsConstants::GravityAcceleration.Z); }
  120. /*
  121. ** Shadow support
  122. */
  123. virtual void Get_Shadow_Blob_Box(AABoxClass * set_obj_space_box);
  124. /*
  125. ** MoveablePhysClass Push interface. RigidBody's try to move when they are pushed.
  126. */
  127. virtual bool Push(const Vector3 & move);
  128. /*
  129. ** Save-Load System
  130. */
  131. virtual const PersistFactoryClass & Get_Factory (void) const;
  132. virtual bool Save (ChunkSaveClass &csave);
  133. virtual bool Load (ChunkLoadClass &cload);
  134. virtual void On_Post_Load(void);
  135. protected:
  136. /*
  137. ** Integration system
  138. */
  139. virtual void Get_State(StateVectorClass & set_state);
  140. virtual int Set_State(const StateVectorClass & new_state,int start_index);
  141. void Set_State(const RigidBodyStateStruct & new_state);
  142. virtual int Compute_Derivatives(float t,StateVectorClass * test_state,StateVectorClass * set_derivs,int start_index);
  143. void Integrate(float time);
  144. /*
  145. ** Internal functions
  146. */
  147. void Update_Cached_Model_Parameters(void);
  148. virtual void Compute_Inertia(void);
  149. void Update_Auxiliary_State(void);
  150. virtual void Compute_Force_And_Torque(Vector3 * force,Vector3 * torque);
  151. void Compute_Impact(const CastResultStruct & result,Vector3 * impulse);
  152. void Compute_Impact(const Vector3 & point,const Vector3 & normal,Vector3 * impulse);
  153. bool Is_Colliding(const Vector3 & point, const Vector3 & normal);
  154. void Set_Moving_Collision_Region(float dt);
  155. void Set_Stationary_Collision_Region(void);
  156. virtual bool Can_Go_To_Sleep(float dt);
  157. bool Find_State_In_Contact_Zone(const RigidBodyStateStruct & oldstate);
  158. bool Push_Phys3_Object_Away(Phys3Class * p3obj,const CastResultStruct & contact);
  159. void Network_Latency_Error_Correction(float dt);
  160. void Assert_State_Valid(void) const;
  161. void Assert_Not_Intersecting(void);
  162. void Dump_State(void) const;
  163. /*
  164. ** Physical Description:
  165. */
  166. OBBoxRenderObjClass * Box; // World-Space Box
  167. Matrix3 IBody; // Body space inertia tensor
  168. Matrix3 IBodyInv; // Inverse of the body space inertia tensor
  169. OctBoxClass * ContactBox; // datastructure for finding contact points
  170. float ContactThickness; // Dimension of the contact region
  171. /*
  172. ** State vector
  173. */
  174. RigidBodyStateStruct State; // current state vector
  175. /*
  176. ** Quantities derived from (dependent on) the current state
  177. */
  178. Matrix3 Rotation;
  179. Matrix3 IInv;
  180. Vector3 Velocity;
  181. Vector3 AngularVelocity;
  182. /*
  183. ** Other Member variables
  184. */
  185. bool IsInContact;
  186. int ContactCount;
  187. Vector3 ContactPoint[MAX_CONTACT_POINTS];
  188. Vector3 ContactNormal;
  189. int StickCount;
  190. float LastTimestep;
  191. float GoToSleepTimer;
  192. /*
  193. ** Network history for latency handling
  194. */
  195. RBodyHistoryClass * History;
  196. RigidBodyStateStruct LatencyError;
  197. RigidBodyStateStruct LastKnownState;
  198. static float _CorrectionTime;
  199. private:
  200. // not implemented
  201. RigidBodyClass(const RigidBodyClass &);
  202. RigidBodyClass & operator = (const RigidBodyClass &);
  203. };
  204. inline RigidBodyStateStruct::RigidBodyStateStruct(const RigidBodyStateStruct & that)
  205. {
  206. *this = that;
  207. }
  208. inline RigidBodyStateStruct & RigidBodyStateStruct::operator = (const RigidBodyStateStruct & that)
  209. {
  210. Position = that.Position;
  211. Orientation = that.Orientation;
  212. LMomentum = that.LMomentum;
  213. AMomentum = that.AMomentum;
  214. return *this;
  215. }
  216. inline void RigidBodyStateStruct::Reset(void)
  217. {
  218. Position.Set(0,0,0);
  219. Orientation.Make_Identity();
  220. LMomentum.Set(0,0,0);
  221. AMomentum.Set(0,0,0);
  222. }
  223. inline void RigidBodyStateStruct::To_Vector(StateVectorClass & vec)
  224. {
  225. vec.Add(Position[0]);
  226. vec.Add(Position[1]);
  227. vec.Add(Position[2]);
  228. vec.Add(Orientation[0]);
  229. vec.Add(Orientation[1]);
  230. vec.Add(Orientation[2]);
  231. vec.Add(Orientation[3]);
  232. vec.Add(LMomentum[0]);
  233. vec.Add(LMomentum[1]);
  234. vec.Add(LMomentum[2]);
  235. vec.Add(AMomentum[0]);
  236. vec.Add(AMomentum[1]);
  237. vec.Add(AMomentum[2]);
  238. }
  239. inline int RigidBodyStateStruct::From_Vector(const StateVectorClass & vec,int index)
  240. {
  241. Position[0] = vec[index++];
  242. Position[1] = vec[index++];
  243. Position[2] = vec[index++];
  244. Orientation[0] = vec[index++];
  245. Orientation[1] = vec[index++];
  246. Orientation[2] = vec[index++];
  247. Orientation[3] = vec[index++];
  248. LMomentum[0] = vec[index++];
  249. LMomentum[1] = vec[index++];
  250. LMomentum[2] = vec[index++];
  251. AMomentum[0] = vec[index++];
  252. AMomentum[1] = vec[index++];
  253. AMomentum[2] = vec[index++];
  254. return index;
  255. }
  256. inline void RigidBodyStateStruct::Lerp
  257. (
  258. const RigidBodyStateStruct & s0,
  259. const RigidBodyStateStruct & s1,
  260. float fraction,
  261. RigidBodyStateStruct * res
  262. )
  263. {
  264. Vector3::Lerp(s0.Position,s1.Position,fraction,&(res->Position));
  265. Vector3::Lerp(s0.LMomentum,s1.LMomentum,fraction,&(res->LMomentum));
  266. Vector3::Lerp(s0.AMomentum,s1.AMomentum,fraction,&(res->AMomentum));
  267. ::Fast_Slerp(res->Orientation,s0.Orientation,s1.Orientation,fraction);
  268. }
  269. /**
  270. ** RigidBodyDefClass
  271. ** Initialization data structure for RigidBodyClass
  272. */
  273. class RigidBodyDefClass : public MoveablePhysDefClass
  274. {
  275. public:
  276. RigidBodyDefClass(void);
  277. // From DefinitionClass
  278. virtual uint32 Get_Class_ID (void) const;
  279. virtual PersistClass * Create(void) const;
  280. // From PhysDefClass
  281. virtual const char * Get_Type_Name(void) { return "RigidBodyDef"; }
  282. virtual bool Is_Type(const char *);
  283. // From PersistClass
  284. virtual const PersistFactoryClass & Get_Factory (void) const;
  285. virtual bool Save(ChunkSaveClass &csave);
  286. virtual bool Load(ChunkLoadClass &cload);
  287. // In-Game Editing (DEBUGGING/TESTING ONLY)
  288. float Get_Aerodynamic_Drag(void) { return AerodynamicDragCoefficient; }
  289. void Set_Aerodynamic_Drag(float new_drag) { AerodynamicDragCoefficient = new_drag; }
  290. // Editable interface requirements
  291. DECLARE_EDITABLE(RigidBodyDefClass,MoveablePhysDefClass);
  292. protected:
  293. // Variables
  294. float AerodynamicDragCoefficient;
  295. bool CollisionDisabled;
  296. friend class RigidBodyClass;
  297. };
  298. #endif