2 * OPCODE - Optimized Collision Detection
3 * http://www.codercorner.com/Opcode.htm
5 * Copyright (c) 2001-2008 Pierre Terdiman, pierre@codercorner.com
7 This software is provided 'as-is', without any express or implied warranty.
8 In no event will the authors be held liable for any damages arising from the use of this software.
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it freely,
11 subject to the following restrictions:
13 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
14 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
15 3. This notice may not be removed or altered from any source distribution.
18 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
20 * Contains code for a ray collider.
21 * \file OPC_RayCollider.h
22 * \author Pierre Terdiman
25 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
27 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
29 #ifndef __OPC_RAYCOLLIDER_H__
30 #define __OPC_RAYCOLLIDER_H__
32 class OPCODE_API CollisionFace
36 inline_ CollisionFace() {}
38 inline_ ~CollisionFace() {}
40 udword mFaceID; //!< Index of touched face
41 float mDistance; //!< Distance from collider to hitpoint
42 float mU, mV; //!< Impact barycentric coordinates
45 class OPCODE_API CollisionFaces : private Container
53 inline_ udword GetNbFaces() const { return GetNbEntries()>>2; }
54 inline_ const CollisionFace* GetFaces() const { return (const CollisionFace*)GetEntries(); }
56 inline_ void Reset() { Container::Reset(); }
58 inline_ void AddFace(const CollisionFace& face) { Add(face.mFaceID).Add(face.mDistance).Add(face.mU).Add(face.mV); }
61 #ifdef OPC_RAYHIT_CALLBACK
62 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
64 * User-callback, called by OPCODE to record a hit.
65 * \param hit [in] current hit
66 * \param user_data [in] user-defined data from SetCallback()
68 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
69 typedef void (*HitCallback) (const CollisionFace& hit, void* user_data);
72 class OPCODE_API RayCollider : public Collider
75 // Constructor / Destructor
77 virtual ~RayCollider();
79 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
81 * Generic stabbing query for generic OPCODE models. After the call, access the results:
82 * - with GetContactStatus()
83 * - in the user-provided destination array
85 * \param world_ray [in] stabbing ray in world space
86 * \param model [in] Opcode model to collide with
87 * \param world [in] model's world matrix, or null
88 * \param cache [in] a possibly cached face index, or null
89 * \return true if success
90 * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
92 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
93 bool Collide(const Ray& world_ray, const Model& model, const Matrix4x4* world=null, udword* cache=null);
95 bool Collide(const Ray& world_ray, const AABBTree* tree, Container& box_indices);
98 #ifndef OPC_RAYHIT_CALLBACK
99 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
101 * Settings: enable or disable "closest hit" mode.
102 * \param flag [in] true to report closest hit only
103 * \see SetCulling(bool flag)
104 * \see SetMaxDist(float max_dist)
105 * \see SetDestination(StabbedFaces* sf)
107 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
108 inline_ void SetClosestHit(bool flag) { mClosestHit = flag; }
110 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
112 * Settings: enable or disable backface culling.
113 * \param flag [in] true to enable backface culling
114 * \see SetClosestHit(bool flag)
115 * \see SetMaxDist(float max_dist)
116 * \see SetDestination(StabbedFaces* sf)
118 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
119 inline_ void SetCulling(bool flag) { mCulling = flag; }
121 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
123 * Settings: sets the higher distance bound.
124 * \param max_dist [in] higher distance bound. Default = maximal value, for ray queries (else segment)
125 * \see SetClosestHit(bool flag)
126 * \see SetCulling(bool flag)
127 * \see SetDestination(StabbedFaces* sf)
129 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
130 inline_ void SetMaxDist(float max_dist=MAX_FLOAT) { mMaxDist = max_dist; }
132 #ifdef OPC_RAYHIT_CALLBACK
133 inline_ void SetHitCallback(HitCallback cb) { mHitCallback = cb; }
134 inline_ void SetUserData(void* user_data) { mUserData = user_data; }
136 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
138 * Settings: sets the destination array for stabbed faces.
139 * \param cf [in] destination array, filled during queries
140 * \see SetClosestHit(bool flag)
141 * \see SetCulling(bool flag)
142 * \see SetMaxDist(float max_dist)
144 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
145 inline_ void SetDestination(CollisionFaces* cf) { mStabbedFaces = cf; }
148 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
150 * Stats: gets the number of Ray-BV overlap tests after a collision query.
151 * \see GetNbRayPrimTests()
152 * \see GetNbIntersections()
153 * \return the number of Ray-BV tests performed during last query
155 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
156 inline_ udword GetNbRayBVTests() const { return mNbRayBVTests; }
158 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
160 * Stats: gets the number of Ray-Triangle overlap tests after a collision query.
161 * \see GetNbRayBVTests()
162 * \see GetNbIntersections()
163 * \return the number of Ray-Triangle tests performed during last query
165 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
166 inline_ udword GetNbRayPrimTests() const { return mNbRayPrimTests; }
169 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
171 * Stats: gets the number of intersection found after a collision query. Can be used for in/out tests.
172 * \see GetNbRayBVTests()
173 * \see GetNbRayPrimTests()
174 * \return the number of valid intersections during last query
176 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
177 inline_ udword GetNbIntersections() const { return mNbIntersections; }
179 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
181 * Validates current settings. You should call this method after all the settings and callbacks have been defined for a collider.
182 * \return null if everything is ok, else a string describing the problem
184 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
185 override(Collider) const char* ValidateSettings();
188 // Ray in local space
189 Point mOrigin; //!< Ray origin
190 Point mDir; //!< Ray direction (normalized)
191 Point mFDir; //!< fabsf(mDir)
194 CollisionFace mStabbedFace; //!< Current stabbed face
195 #ifdef OPC_RAYHIT_CALLBACK
196 HitCallback mHitCallback; //!< Callback used to record a hit
197 void* mUserData; //!< User-defined data
199 CollisionFaces* mStabbedFaces; //!< List of stabbed faces
202 udword mNbRayBVTests; //!< Number of Ray-BV tests
203 udword mNbRayPrimTests; //!< Number of Ray-Primitive tests
205 udword mNbIntersections; //!< Number of valid intersections
206 // Dequantization coeffs
210 float mMaxDist; //!< Valid segment on the ray
211 #ifndef OPC_RAYHIT_CALLBACK
212 bool mClosestHit; //!< Report closest hit only
214 bool mCulling; //!< Stab culled faces or not
216 void _SegmentStab(const AABBCollisionNode* node);
217 void _SegmentStab(const AABBNoLeafNode* node);
218 void _SegmentStab(const AABBQuantizedNode* node);
219 void _SegmentStab(const AABBQuantizedNoLeafNode* node);
220 void _SegmentStab(const AABBTreeNode* node, Container& box_indices);
221 void _RayStab(const AABBCollisionNode* node);
222 void _RayStab(const AABBNoLeafNode* node);
223 void _RayStab(const AABBQuantizedNode* node);
224 void _RayStab(const AABBQuantizedNoLeafNode* node);
225 void _RayStab(const AABBTreeNode* node, Container& box_indices);
227 inline_ BOOL RayAABBOverlap(const Point& center, const Point& extents);
228 inline_ BOOL SegmentAABBOverlap(const Point& center, const Point& extents);
229 inline_ BOOL RayTriOverlap(const Point& vert0, const Point& vert1, const Point& vert2);
231 BOOL InitQuery(const Ray& world_ray, const Matrix4x4* world=null, udword* face_id=null);
234 #endif // __OPC_RAYCOLLIDER_H__