octbox.h 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  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. /***********************************************************************************************
  19. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : WWPhys *
  23. * *
  24. * $Archive:: /Commando/Code/wwphys/octbox.h $*
  25. * *
  26. * Original Author:: Greg Hjelstrom *
  27. * *
  28. * $Author:: Greg_h $*
  29. * *
  30. * $Modtime:: 11/21/01 2:48p $*
  31. * *
  32. * $Revision:: 14 $*
  33. * *
  34. *---------------------------------------------------------------------------------------------*
  35. * Functions: *
  36. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  37. #if defined(_MSC_VER)
  38. #pragma once
  39. #endif
  40. #ifndef OCTBOX_H
  41. #define OCTBOX_H
  42. #include "always.h"
  43. #include "obbox.h"
  44. #include "rbody.h"
  45. /**
  46. ** OctBoxClass
  47. ** This class encapsulates the collision detection algorithms used by Renegade's "rigid-body"
  48. ** physics. It basically acts like rigid box with a contact zone around it. Contacts are detected
  49. ** when geometry is within "thickness" distance of the rigid box.
  50. */
  51. class OctBoxClass
  52. {
  53. public:
  54. OctBoxClass(RigidBodyClass & parent,const OBBoxClass & box);
  55. ~OctBoxClass(void);
  56. void Set_Stiffness(float stiffness) { Stiffness = stiffness; }
  57. float Get_Stiffness(void) const { return Stiffness; }
  58. void Set_Damping(float damping) { Damping = damping; }
  59. float Get_Damping(void) const { return Damping; }
  60. void Set_Thickness(float thickness);
  61. float Get_Thickness(void) { return Thickness; }
  62. void Update_Contact_Parameters(void);
  63. enum CollisionResult
  64. {
  65. RESULT_NO_COLLISION = 0, // this object isn't touching anything
  66. RESULT_INTERSECTION, // this object has penetrated another, have to back up
  67. RESULT_CONTACT, // no penetration but there is contact.
  68. };
  69. void Set_Transform(const Matrix3D & tm);
  70. void Set_Transform(const Quaternion & q,const Vector3 & p);
  71. bool Is_Intersecting(NonRefPhysListClass * result_list = NULL,bool check_static_objs = true,bool check_dyn_objs = true);
  72. bool Is_In_Contact_Zone(void);
  73. CollisionResult Compute_Contacts(bool lock_to_centroids = false);
  74. int Get_Contact_Count(void);
  75. const CastResultStruct &Get_Contact(int index);
  76. PhysClass * Peek_Contacted_Object(int index);
  77. void Get_Outer_Bounds(AABoxClass * set_bounds);
  78. void Get_Outer_Box(OBBoxClass * set_box) { *set_box = Get_World_Inner_Box(); }
  79. void Get_Inner_Box(OBBoxClass * set_box) { *set_box = Get_World_Inner_Box(); set_box->Extent += Vector3(Thickness,Thickness,Thickness); }
  80. void Get_Inner_Box(OBBoxClass * set_box, const Quaternion & q, const Vector3 & p);
  81. float Get_Extent_Length2() { return InnerBox.Extent.Length2(); }
  82. public: //protected:
  83. CollisionResult Internal_Compute_Contacts(bool lock_to_centroids);
  84. void Compute_Octant_Contact(int oi,bool lock_to_centroids);
  85. void Transform_To_World_Space(const Matrix3D & tm);
  86. void Transform_To_World_Space(const Quaternion & q,const Vector3 & p);
  87. void Reset_Contacts(void);
  88. void Add_Contact(const CastResultStruct & res,PhysClass * other_obj);
  89. const OBBoxClass & Get_World_Inner_Box(void) { return WrldInnerBox; }
  90. /*
  91. ** Properties
  92. */
  93. RigidBodyClass & Parent; // parent object this OctBox is working for
  94. OBBoxClass InnerBox; // OBBox for the parent when parent's TM is I
  95. float Thickness; // thickness of the "squishy zone"
  96. float Stiffness; // spring stiffness to use
  97. float Damping; // damping coefficient to use
  98. Vector3 OctantCenter; // offest to center of octant0 in InnerBox's coord system
  99. Vector3 OctantExtent; // extent of the octant boxes
  100. /*
  101. ** Current State
  102. */
  103. OBBoxClass WrldInnerBox;
  104. /*
  105. ** Contact Accumulation
  106. */
  107. enum { MAX_CONTACTS = 16 };
  108. int ContactCount;
  109. CastResultStruct Contacts[MAX_CONTACTS];
  110. PhysClass * ContactedObject[MAX_CONTACTS];
  111. };
  112. inline void OctBoxClass::Set_Transform(const Matrix3D & tm)
  113. {
  114. Transform_To_World_Space(tm);
  115. }
  116. inline void OctBoxClass::Set_Transform(const Quaternion & q,const Vector3 & p)
  117. {
  118. Transform_To_World_Space(q,p);
  119. }
  120. inline int OctBoxClass::Get_Contact_Count(void)
  121. {
  122. return ContactCount;
  123. }
  124. inline const CastResultStruct & OctBoxClass::Get_Contact(int index)
  125. {
  126. static CastResultStruct _no_result;
  127. if ((index >= 0) && (index < ContactCount)) {
  128. return Contacts[index];
  129. } else {
  130. return _no_result;
  131. }
  132. }
  133. inline PhysClass * OctBoxClass::Peek_Contacted_Object(int index)
  134. {
  135. if ((index >= 0) && (index < ContactCount)) {
  136. return ContactedObject[index];
  137. } else {
  138. return NULL;
  139. }
  140. }
  141. inline void OctBoxClass::Transform_To_World_Space(const Matrix3D & tm)
  142. {
  143. OBBoxClass::Transform(tm,InnerBox,&WrldInnerBox);
  144. }
  145. inline void OctBoxClass::Transform_To_World_Space(const Quaternion & q,const Vector3 & p)
  146. {
  147. Matrix3D tm(q,p);
  148. OBBoxClass::Transform(tm,InnerBox,&WrldInnerBox);
  149. }
  150. inline void OctBoxClass::Reset_Contacts(void)
  151. {
  152. ContactCount = 0;
  153. }
  154. inline void OctBoxClass::Add_Contact(const CastResultStruct & res,PhysClass * other_obj)
  155. {
  156. WWASSERT(ContactCount < MAX_CONTACTS);
  157. Contacts[ContactCount] = res;
  158. ContactedObject[ContactCount] = other_obj;
  159. ContactCount++;
  160. }
  161. inline void OctBoxClass::Get_Inner_Box(OBBoxClass * set_box, const Quaternion & q, const Vector3 & p)
  162. {
  163. Matrix3D tm(q,p);
  164. OBBoxClass::Transform(tm,InnerBox,set_box);
  165. }
  166. #endif