1 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3 * OPCODE - Optimized Collision Detection
4 * Copyright (C) 2001 Pierre Terdiman
5 * Homepage: http://www.codercorner.com/Opcode.htm
7 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
11 * Contains code for a ray collider.
12 * \file OPC_RayCollider.h
13 * \author Pierre Terdiman
16 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
18 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
20 #ifndef __OPC_RAYCOLLIDER_H__
21 #define __OPC_RAYCOLLIDER_H__
23 class OPCODE_API CollisionFace
27 inline_
CollisionFace() {}
29 inline_
~CollisionFace() {}
31 udword mFaceID
; //!< Index of touched face
32 float mDistance
; //!< Distance from collider to hitpoint
33 float mU
, mV
; //!< Impact barycentric coordinates
36 class OPCODE_API CollisionFaces
: private OPC_Container
44 inline_ udword
GetNbFaces() const { return GetNbEntries()>>2; }
45 inline_
const CollisionFace
* GetFaces() const { return (const CollisionFace
*)GetEntries(); }
47 inline_
void Reset() { OPC_Container::Reset(); }
49 inline_
void AddFace(const CollisionFace
& face
) { Add(face
.mFaceID
).Add(face
.mDistance
).Add(face
.mU
).Add(face
.mV
); }
52 #ifdef OPC_RAYHIT_CALLBACK
53 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
55 * User-callback, called by OPCODE to record a hit.
56 * \param hit [in] current hit
57 * \param user_data [in] user-defined data from SetCallback()
59 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
60 typedef void (*HitCallback
) (const CollisionFace
& hit
, void* user_data
);
63 class OPCODE_API RayCollider
: public Collider
66 // Constructor / Destructor
68 virtual ~RayCollider();
70 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
72 * Generic stabbing query for generic OPCODE models. After the call, access the results:
73 * - with GetContactStatus()
74 * - in the user-provided destination array
76 * \param world_ray [in] stabbing ray in world space
77 * \param model [in] Opcode model to collide with
78 * \param world [in] model's world matrix, or null
79 * \param cache [in] a possibly cached face index, or null
80 * \return true if success
81 * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
83 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
84 bool Collide(const Ray
& world_ray
, const Model
& model
, const Matrix4x4
* world
=null
, udword
* cache
=null
);
86 bool Collide(const Ray
& world_ray
, const AABBTree
* tree
, OPC_Container
& box_indices
);
89 #ifndef OPC_RAYHIT_CALLBACK
90 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
92 * Settings: enable or disable "closest hit" mode.
93 * \param flag [in] true to report closest hit only
94 * \see SetCulling(bool flag)
95 * \see SetMaxDist(float max_dist)
96 * \see SetDestination(StabbedFaces* sf)
98 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
99 inline_
void SetClosestHit(bool flag
) { mClosestHit
= flag
; }
101 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
103 * Settings: enable or disable backface culling.
104 * \param flag [in] true to enable backface culling
105 * \see SetClosestHit(bool flag)
106 * \see SetMaxDist(float max_dist)
107 * \see SetDestination(StabbedFaces* sf)
109 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
110 inline_
void SetCulling(bool flag
) { mCulling
= flag
; }
112 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
114 * Settings: sets the higher distance bound.
115 * \param max_dist [in] higher distance bound. Default = maximal value, for ray queries (else segment)
116 * \see SetClosestHit(bool flag)
117 * \see SetCulling(bool flag)
118 * \see SetDestination(StabbedFaces* sf)
120 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
121 inline_
void SetMaxDist(float max_dist
=MAX_FLOAT
) { mMaxDist
= max_dist
; }
123 #ifdef OPC_RAYHIT_CALLBACK
124 inline_
void SetHitCallback(HitCallback cb
) { mHitCallback
= cb
; }
125 inline_
void SetUserData(void* user_data
) { mUserData
= user_data
; }
127 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
129 * Settings: sets the destination array for stabbed faces.
130 * \param cf [in] destination array, filled during queries
131 * \see SetClosestHit(bool flag)
132 * \see SetCulling(bool flag)
133 * \see SetMaxDist(float max_dist)
135 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
136 inline_
void SetDestination(CollisionFaces
* cf
) { mStabbedFaces
= cf
; }
139 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
141 * Stats: gets the number of Ray-BV overlap tests after a collision query.
142 * \see GetNbRayPrimTests()
143 * \see GetNbIntersections()
144 * \return the number of Ray-BV tests performed during last query
146 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
147 inline_ udword
GetNbRayBVTests() const { return mNbRayBVTests
; }
149 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
151 * Stats: gets the number of Ray-Triangle overlap tests after a collision query.
152 * \see GetNbRayBVTests()
153 * \see GetNbIntersections()
154 * \return the number of Ray-Triangle tests performed during last query
156 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
157 inline_ udword
GetNbRayPrimTests() const { return mNbRayPrimTests
; }
160 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
162 * Stats: gets the number of intersection found after a collision query. Can be used for in/out tests.
163 * \see GetNbRayBVTests()
164 * \see GetNbRayPrimTests()
165 * \return the number of valid intersections during last query
167 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
168 inline_ udword
GetNbIntersections() const { return mNbIntersections
; }
170 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
172 * Validates current settings. You should call this method after all the settings and callbacks have been defined for a collider.
173 * \return null if everything is ok, else a string describing the problem
175 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
176 override(Collider
) const char* ValidateSettings();
179 // Ray in local space
180 Point mOrigin
; //!< Ray origin
181 Point mDir
; //!< Ray direction (normalized)
182 Point mFDir
; //!< fabsf(mDir)
185 CollisionFace mStabbedFace
; //!< Current stabbed face
186 #ifdef OPC_RAYHIT_CALLBACK
187 HitCallback mHitCallback
; //!< Callback used to record a hit
188 void* mUserData
; //!< User-defined data
190 CollisionFaces
* mStabbedFaces
; //!< List of stabbed faces
193 udword mNbRayBVTests
; //!< Number of Ray-BV tests
194 udword mNbRayPrimTests
; //!< Number of Ray-Primitive tests
196 udword mNbIntersections
; //!< Number of valid intersections
197 // Dequantization coeffs
201 float mMaxDist
; //!< Valid segment on the ray
202 #ifndef OPC_RAYHIT_CALLBACK
203 bool mClosestHit
; //!< Report closest hit only
205 bool mCulling
; //!< Stab culled faces or not
207 void _SegmentStab(const AABBCollisionNode
* node
);
208 void _SegmentStab(const AABBNoLeafNode
* node
);
209 void _SegmentStab(const AABBQuantizedNode
* node
);
210 void _SegmentStab(const AABBQuantizedNoLeafNode
* node
);
211 void _SegmentStab(const AABBTreeNode
* node
, OPC_Container
& box_indices
);
212 void _RayStab(const AABBCollisionNode
* node
);
213 void _RayStab(const AABBNoLeafNode
* node
);
214 void _RayStab(const AABBQuantizedNode
* node
);
215 void _RayStab(const AABBQuantizedNoLeafNode
* node
);
216 void _RayStab(const AABBTreeNode
* node
, OPC_Container
& box_indices
);
218 inline_ BOOL
RayAABBOverlap(const Point
& center
, const Point
& extents
);
219 inline_ BOOL
SegmentAABBOverlap(const Point
& center
, const Point
& extents
);
220 inline_ BOOL
RayTriOverlap(const Point
& vert0
, const Point
& vert1
, const Point
& vert2
);
222 BOOL
InitQuery(const Ray
& world_ray
, const Matrix4x4
* world
=null
, udword
* face_id
=null
);
225 #endif // __OPC_RAYCOLLIDER_H__