OPC_RayCollider.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  2. /*
  3. * OPCODE - Optimized Collision Detection
  4. * Copyright (C) 2001 Pierre Terdiman
  5. * Homepage: http://www.codercorner.com/Opcode.htm
  6. */
  7. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  8. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  9. /**
  10. * Contains code for a ray collider.
  11. * \file OPC_RayCollider.h
  12. * \author Pierre Terdiman
  13. * \date June, 2, 2001
  14. */
  15. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  16. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  17. // Include Guard
  18. #ifndef __OPC_RAYCOLLIDER_H__
  19. #define __OPC_RAYCOLLIDER_H__
  20. class OPCODE_API CollisionFace
  21. {
  22. public:
  23. //! Constructor
  24. inline_ CollisionFace() {}
  25. //! Destructor
  26. inline_ ~CollisionFace() {}
  27. udword mFaceID; //!< Index of touched face
  28. float mDistance; //!< Distance from collider to hitpoint
  29. float mU, mV; //!< Impact barycentric coordinates
  30. };
  31. class OPCODE_API CollisionFaces : private OPC_Container
  32. {
  33. public:
  34. //! Constructor
  35. CollisionFaces() {}
  36. //! Destructor
  37. ~CollisionFaces() {}
  38. inline_ udword GetNbFaces() const { return GetNbEntries()>>2; }
  39. inline_ const CollisionFace* GetFaces() const { return (const CollisionFace*)GetEntries(); }
  40. inline_ void Reset() { OPC_Container::Reset(); }
  41. inline_ void AddFace(const CollisionFace& face) { Add(face.mFaceID).Add(face.mDistance).Add(face.mU).Add(face.mV); }
  42. };
  43. #ifdef OPC_RAYHIT_CALLBACK
  44. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  45. /**
  46. * User-callback, called by OPCODE to record a hit.
  47. * \param hit [in] current hit
  48. * \param user_data [in] user-defined data from SetCallback()
  49. */
  50. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  51. typedef void (*HitCallback) (const CollisionFace& hit, void* user_data);
  52. #endif
  53. class OPCODE_API RayCollider : public Collider
  54. {
  55. public:
  56. // Constructor / Destructor
  57. RayCollider();
  58. virtual ~RayCollider();
  59. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  60. /**
  61. * Generic stabbing query for generic OPCODE models. After the call, access the results:
  62. * - with GetContactStatus()
  63. * - in the user-provided destination array
  64. *
  65. * \param world_ray [in] stabbing ray in world space
  66. * \param model [in] Opcode model to collide with
  67. * \param world [in] model's world matrix, or null
  68. * \param cache [in] a possibly cached face index, or null
  69. * \return true if success
  70. * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
  71. */
  72. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  73. bool Collide(const Ray& world_ray, const Model& model, const Matrix4x4* world=null, udword* cache=null);
  74. //
  75. bool Collide(const Ray& world_ray, const AABBTree* tree, OPC_Container& box_indices);
  76. // Settings
  77. #ifndef OPC_RAYHIT_CALLBACK
  78. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  79. /**
  80. * Settings: enable or disable "closest hit" mode.
  81. * \param flag [in] true to report closest hit only
  82. * \see SetCulling(bool flag)
  83. * \see SetMaxDist(float max_dist)
  84. * \see SetDestination(StabbedFaces* sf)
  85. */
  86. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  87. inline_ void SetClosestHit(bool flag) { mClosestHit = flag; }
  88. #endif
  89. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  90. /**
  91. * Settings: enable or disable backface culling.
  92. * \param flag [in] true to enable backface culling
  93. * \see SetClosestHit(bool flag)
  94. * \see SetMaxDist(float max_dist)
  95. * \see SetDestination(StabbedFaces* sf)
  96. */
  97. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  98. inline_ void SetCulling(bool flag) { mCulling = flag; }
  99. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  100. /**
  101. * Settings: sets the higher distance bound.
  102. * \param max_dist [in] higher distance bound. Default = maximal value, for ray queries (else segment)
  103. * \see SetClosestHit(bool flag)
  104. * \see SetCulling(bool flag)
  105. * \see SetDestination(StabbedFaces* sf)
  106. */
  107. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  108. inline_ void SetMaxDist(float max_dist=MAX_FLOAT) { mMaxDist = max_dist; }
  109. #ifdef OPC_RAYHIT_CALLBACK
  110. inline_ void SetHitCallback(HitCallback cb) { mHitCallback = cb; }
  111. inline_ void SetUserData(void* user_data) { mUserData = user_data; }
  112. #else
  113. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  114. /**
  115. * Settings: sets the destination array for stabbed faces.
  116. * \param cf [in] destination array, filled during queries
  117. * \see SetClosestHit(bool flag)
  118. * \see SetCulling(bool flag)
  119. * \see SetMaxDist(float max_dist)
  120. */
  121. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  122. inline_ void SetDestination(CollisionFaces* cf) { mStabbedFaces = cf; }
  123. #endif
  124. // Stats
  125. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  126. /**
  127. * Stats: gets the number of Ray-BV overlap tests after a collision query.
  128. * \see GetNbRayPrimTests()
  129. * \see GetNbIntersections()
  130. * \return the number of Ray-BV tests performed during last query
  131. */
  132. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  133. inline_ udword GetNbRayBVTests() const { return mNbRayBVTests; }
  134. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  135. /**
  136. * Stats: gets the number of Ray-Triangle overlap tests after a collision query.
  137. * \see GetNbRayBVTests()
  138. * \see GetNbIntersections()
  139. * \return the number of Ray-Triangle tests performed during last query
  140. */
  141. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  142. inline_ udword GetNbRayPrimTests() const { return mNbRayPrimTests; }
  143. // In-out test
  144. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  145. /**
  146. * Stats: gets the number of intersection found after a collision query. Can be used for in/out tests.
  147. * \see GetNbRayBVTests()
  148. * \see GetNbRayPrimTests()
  149. * \return the number of valid intersections during last query
  150. */
  151. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  152. inline_ udword GetNbIntersections() const { return mNbIntersections; }
  153. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  154. /**
  155. * Validates current settings. You should call this method after all the settings and callbacks have been defined for a collider.
  156. * \return null if everything is ok, else a string describing the problem
  157. */
  158. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  159. override(Collider) const char* ValidateSettings();
  160. protected:
  161. // Ray in local space
  162. Point mOrigin; //!< Ray origin
  163. Point mDir; //!< Ray direction (normalized)
  164. Point mFDir; //!< fabsf(mDir)
  165. Point mData, mData2;
  166. // Stabbed faces
  167. CollisionFace mStabbedFace; //!< Current stabbed face
  168. #ifdef OPC_RAYHIT_CALLBACK
  169. HitCallback mHitCallback; //!< Callback used to record a hit
  170. void* mUserData; //!< User-defined data
  171. #else
  172. CollisionFaces* mStabbedFaces; //!< List of stabbed faces
  173. #endif
  174. // Stats
  175. udword mNbRayBVTests; //!< Number of Ray-BV tests
  176. udword mNbRayPrimTests; //!< Number of Ray-Primitive tests
  177. // In-out test
  178. udword mNbIntersections; //!< Number of valid intersections
  179. // Dequantization coeffs
  180. Point mCenterCoeff;
  181. Point mExtentsCoeff;
  182. // Settings
  183. float mMaxDist; //!< Valid segment on the ray
  184. #ifndef OPC_RAYHIT_CALLBACK
  185. bool mClosestHit; //!< Report closest hit only
  186. #endif
  187. bool mCulling; //!< Stab culled faces or not
  188. // Internal methods
  189. void _SegmentStab(const AABBCollisionNode* node);
  190. void _SegmentStab(const AABBNoLeafNode* node);
  191. void _SegmentStab(const AABBQuantizedNode* node);
  192. void _SegmentStab(const AABBQuantizedNoLeafNode* node);
  193. void _SegmentStab(const AABBTreeNode* node, OPC_Container& box_indices);
  194. void _RayStab(const AABBCollisionNode* node);
  195. void _RayStab(const AABBNoLeafNode* node);
  196. void _RayStab(const AABBQuantizedNode* node);
  197. void _RayStab(const AABBQuantizedNoLeafNode* node);
  198. void _RayStab(const AABBTreeNode* node, OPC_Container& box_indices);
  199. // Overlap tests
  200. inline_ BOOL RayAABBOverlap(const Point& center, const Point& extents);
  201. inline_ BOOL SegmentAABBOverlap(const Point& center, const Point& extents);
  202. inline_ BOOL RayTriOverlap(const Point& vert0, const Point& vert1, const Point& vert2);
  203. // Init methods
  204. BOOL InitQuery(const Ray& world_ray, const Matrix4x4* world=null, udword* face_id=null);
  205. };
  206. #endif // __OPC_RAYCOLLIDER_H__