Merge pull request #2240 from GarageGames/Release_3_10_1
[Torque-3d.git] / Engine / lib / opcode / OPC_RayCollider.h
blobe3931b03a2343ed3df0bc2316e413d5982029332
1 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2 /*
3 * OPCODE - Optimized Collision Detection
4 * Copyright (C) 2001 Pierre Terdiman
5 * Homepage: http://www.codercorner.com/Opcode.htm
6 */
7 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10 /**
11 * Contains code for a ray collider.
12 * \file OPC_RayCollider.h
13 * \author Pierre Terdiman
14 * \date June, 2, 2001
16 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
18 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
19 // Include Guard
20 #ifndef __OPC_RAYCOLLIDER_H__
21 #define __OPC_RAYCOLLIDER_H__
23 class OPCODE_API CollisionFace
25 public:
26 //! Constructor
27 inline_ CollisionFace() {}
28 //! Destructor
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
38 public:
39 //! Constructor
40 CollisionFaces() {}
41 //! Destructor
42 ~CollisionFaces() {}
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 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
54 /**
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);
61 #endif
63 class OPCODE_API RayCollider : public Collider
65 public:
66 // Constructor / Destructor
67 RayCollider();
68 virtual ~RayCollider();
70 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
71 /**
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);
87 // Settings
89 #ifndef OPC_RAYHIT_CALLBACK
90 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
91 /**
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; }
100 #endif
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; }
126 #else
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; }
137 #endif
138 // Stats
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; }
159 // In-out test
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();
178 protected:
179 // Ray in local space
180 Point mOrigin; //!< Ray origin
181 Point mDir; //!< Ray direction (normalized)
182 Point mFDir; //!< fabsf(mDir)
183 Point mData, mData2;
184 // Stabbed faces
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
189 #else
190 CollisionFaces* mStabbedFaces; //!< List of stabbed faces
191 #endif
192 // Stats
193 udword mNbRayBVTests; //!< Number of Ray-BV tests
194 udword mNbRayPrimTests; //!< Number of Ray-Primitive tests
195 // In-out test
196 udword mNbIntersections; //!< Number of valid intersections
197 // Dequantization coeffs
198 Point mCenterCoeff;
199 Point mExtentsCoeff;
200 // Settings
201 float mMaxDist; //!< Valid segment on the ray
202 #ifndef OPC_RAYHIT_CALLBACK
203 bool mClosestHit; //!< Report closest hit only
204 #endif
205 bool mCulling; //!< Stab culled faces or not
206 // Internal methods
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);
217 // Overlap tests
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);
221 // Init methods
222 BOOL InitQuery(const Ray& world_ray, const Matrix4x4* world=null, udword* face_id=null);
225 #endif // __OPC_RAYCOLLIDER_H__