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 tree collider.
21 * \file OPC_TreeCollider.h
22 * \author Pierre Terdiman
23 * \date March, 20, 2001
25 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
27 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
29 #ifndef __OPC_TREECOLLIDER_H__
30 #define __OPC_TREECOLLIDER_H__
32 //! This structure holds cached information used by the algorithm.
33 //! Two model pointers and two colliding primitives are cached. Model pointers are assigned
34 //! to their respective meshes, and the pair of colliding primitives is used for temporal
35 //! coherence. That is, in case temporal coherence is enabled, those two primitives are
36 //! tested for overlap before everything else. If they still collide, we're done before
37 //! even entering the recursive collision code.
38 struct OPCODE_API BVTCache : Pair
53 #ifdef __MESHMERIZER_H__ // Collision hulls only supported within ICE !
57 SepVector.SV = Point(1.0f, 0.0f, 0.0f);
58 #endif // __MESHMERIZER_H__
61 inline_ void ResetCountDown()
63 #ifdef __MESHMERIZER_H__ // Collision hulls only supported within ICE !
65 #endif // __MESHMERIZER_H__
68 const Model* Model0; //!< Model for first object
69 const Model* Model1; //!< Model for second object
71 #ifdef __MESHMERIZER_H__ // Collision hulls only supported within ICE !
75 #endif // __MESHMERIZER_H__
78 class OPCODE_API AABBTreeCollider : public Collider
81 // Constructor / Destructor
83 virtual ~AABBTreeCollider();
84 // Generic collision query
86 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
88 * Generic collision query for generic OPCODE models. After the call, access the results with:
89 * - GetContactStatus()
93 * \param cache [in] collision cache for model pointers and a colliding pair of primitives
94 * \param world0 [in] world matrix for first object, or null
95 * \param world1 [in] world matrix for second object, or null
96 * \return true if success
97 * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
99 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
100 bool Collide(BVTCache& cache, const Matrix4x4* world0=null, const Matrix4x4* world1=null);
103 bool Collide(const AABBCollisionTree* tree0, const AABBCollisionTree* tree1, const Matrix4x4* world0=null, const Matrix4x4* world1=null, Pair* cache=null);
104 bool Collide(const AABBNoLeafTree* tree0, const AABBNoLeafTree* tree1, const Matrix4x4* world0=null, const Matrix4x4* world1=null, Pair* cache=null);
105 bool Collide(const AABBQuantizedTree* tree0, const AABBQuantizedTree* tree1, const Matrix4x4* world0=null, const Matrix4x4* world1=null, Pair* cache=null);
106 bool Collide(const AABBQuantizedNoLeafTree* tree0, const AABBQuantizedNoLeafTree* tree1, const Matrix4x4* world0=null, const Matrix4x4* world1=null, Pair* cache=null);
109 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
111 * Settings: selects between full box-box tests or "SAT-lite" tests (where Class III axes are discarded)
112 * \param flag [in] true for full tests, false for coarse tests
113 * \see SetFullPrimBoxTest(bool flag)
115 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
116 inline_ void SetFullBoxBoxTest(bool flag) { mFullBoxBoxTest = flag; }
118 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
120 * Settings: selects between full triangle-box tests or "SAT-lite" tests (where Class III axes are discarded)
121 * \param flag [in] true for full tests, false for coarse tests
122 * \see SetFullBoxBoxTest(bool flag)
124 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
125 inline_ void SetFullPrimBoxTest(bool flag) { mFullPrimBoxTest = flag; }
129 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
131 * Stats: gets the number of BV-BV overlap tests after a collision query.
132 * \see GetNbPrimPrimTests()
133 * \see GetNbBVPrimTests()
134 * \return the number of BV-BV tests performed during last query
136 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
137 inline_ udword GetNbBVBVTests() const { return mNbBVBVTests; }
139 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
141 * Stats: gets the number of Triangle-Triangle overlap tests after a collision query.
142 * \see GetNbBVBVTests()
143 * \see GetNbBVPrimTests()
144 * \return the number of Triangle-Triangle tests performed during last query
146 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
147 inline_ udword GetNbPrimPrimTests() const { return mNbPrimPrimTests; }
149 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
151 * Stats: gets the number of BV-Triangle overlap tests after a collision query.
152 * \see GetNbBVBVTests()
153 * \see GetNbPrimPrimTests()
154 * \return the number of BV-Triangle tests performed during last query
156 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
157 inline_ udword GetNbBVPrimTests() const { return mNbBVPrimTests; }
161 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
163 * Gets the number of contacts after a collision query.
164 * \see GetContactStatus()
166 * \return the number of contacts / colliding pairs.
168 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
169 inline_ udword GetNbPairs() const { return mPairs.GetNbEntries()>>1; }
171 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
173 * Gets the pairs of colliding triangles after a collision query.
174 * \see GetContactStatus()
176 * \return the list of colliding pairs (triangle indices)
178 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
179 inline_ const Pair* GetPairs() const { return (const Pair*)mPairs.GetEntries(); }
181 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
183 * Validates current settings. You should call this method after all the settings and callbacks have been defined for a collider.
184 * \return null if everything is ok, else a string describing the problem
186 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
187 override(Collider) const char* ValidateSettings();
191 Container mPairs; //!< Pairs of colliding primitives
192 // User mesh interfaces
193 const MeshInterface* mIMesh0; //!< User-defined mesh interface for object0
194 const MeshInterface* mIMesh1; //!< User-defined mesh interface for object1
196 udword mNbBVBVTests; //!< Number of BV-BV tests
197 udword mNbPrimPrimTests; //!< Number of Primitive-Primitive tests
198 udword mNbBVPrimTests; //!< Number of BV-Primitive tests
200 Matrix3x3 mAR; //!< Absolute rotation matrix
201 Matrix3x3 mR0to1; //!< Rotation from object0 to object1
202 Matrix3x3 mR1to0; //!< Rotation from object1 to object0
203 Point mT0to1; //!< Translation from object0 to object1
204 Point mT1to0; //!< Translation from object1 to object0
205 // Dequantization coeffs
207 Point mExtentsCoeff0;
209 Point mExtentsCoeff1;
211 Point mLeafVerts[3]; //!< Triangle vertices
212 udword mLeafIndex; //!< Triangle index
214 bool mFullBoxBoxTest; //!< Perform full BV-BV tests (true) or SAT-lite tests (false)
215 bool mFullPrimBoxTest; //!< Perform full Primitive-BV tests (true) or SAT-lite tests (false)
218 // Standard AABB trees
219 void _Collide(const AABBCollisionNode* b0, const AABBCollisionNode* b1);
220 // Quantized AABB trees
221 void _Collide(const AABBQuantizedNode* b0, const AABBQuantizedNode* b1, const Point& a, const Point& Pa, const Point& b, const Point& Pb);
222 // No-leaf AABB trees
223 void _CollideTriBox(const AABBNoLeafNode* b);
224 void _CollideBoxTri(const AABBNoLeafNode* b);
225 void _Collide(const AABBNoLeafNode* a, const AABBNoLeafNode* b);
226 // Quantized no-leaf AABB trees
227 void _CollideTriBox(const AABBQuantizedNoLeafNode* b);
228 void _CollideBoxTri(const AABBQuantizedNoLeafNode* b);
229 void _Collide(const AABBQuantizedNoLeafNode* a, const AABBQuantizedNoLeafNode* b);
231 void PrimTest(udword id0, udword id1);
232 inline_ void PrimTestTriIndex(udword id1);
233 inline_ void PrimTestIndexTri(udword id0);
235 inline_ BOOL BoxBoxOverlap(const Point& ea, const Point& ca, const Point& eb, const Point& cb);
236 inline_ BOOL TriBoxOverlap(const Point& center, const Point& extents);
237 inline_ BOOL TriTriOverlap(const Point& V0, const Point& V1, const Point& V2, const Point& U0, const Point& U1, const Point& U2);
239 void InitQuery(const Matrix4x4* world0=null, const Matrix4x4* world1=null);
240 bool CheckTemporalCoherence(Pair* cache);
242 inline_ BOOL Setup(const MeshInterface* mi0, const MeshInterface* mi1)
247 if(!mIMesh0 || !mIMesh1) return FALSE;
253 #endif // __OPC_TREECOLLIDER_H__