RavEngine
Loading...
Searching...
No Matches
GuBV4_BoxSweep_Internal.h
1// Redistribution and use in source and binary forms, with or without
2// modification, are permitted provided that the following conditions
3// are met:
4// * Redistributions of source code must retain the above copyright
5// notice, this list of conditions and the following disclaimer.
6// * Redistributions in binary form must reproduce the above copyright
7// notice, this list of conditions and the following disclaimer in the
8// documentation and/or other materials provided with the distribution.
9// * Neither the name of NVIDIA CORPORATION nor the names of its
10// contributors may be used to endorse or promote products derived
11// from this software without specific prior written permission.
12//
13// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
14// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
17// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24//
25// Copyright (c) 2008-2022 NVIDIA Corporation. All rights reserved.
26// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
27// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
28
29#include "GuSweepTriangleUtils.h"
30#include "GuSweepBoxTriangle_FeatureBased.h"
31#include "GuSweepBoxTriangle_SAT.h"
32#include "GuBV4_BoxOverlap_Internal.h"
33
34// PT: for box-sweeps please refer to %SDKRoot%\InternalDocumentation\GU\Sweep strategies.ppt.
35// We use:
36// - method 3 if the box is an AABB (SWEEP_AABB_IMPL is defined)
37// - method 2 if the box is an OBB (SWEEP_AABB_IMPL is undefined)
38
39#ifdef SWEEP_AABB_IMPL
40 // PT: TODO: refactor structure (TA34704)
41 struct RayParams
42 {
43 BV4_ALIGN16(PxVec3p mCenterOrMinCoeff_PaddedAligned);
44 BV4_ALIGN16(PxVec3p mExtentsOrMaxCoeff_PaddedAligned);
45 #ifndef GU_BV4_USE_SLABS
46 BV4_ALIGN16(PxVec3p mData2_PaddedAligned);
47 BV4_ALIGN16(PxVec3p mFDir_PaddedAligned);
48 BV4_ALIGN16(PxVec3p mData_PaddedAligned);
49 BV4_ALIGN16(PxVec3p mLocalDir_PaddedAligned);
50 #endif
51 BV4_ALIGN16(PxVec3p mOrigin_Padded); // PT: TODO: this one could be switched to PaddedAligned & V4LoadA (TA34704)
52 };
53
54 #include "GuBV4_AABBAABBSweepTest.h"
55#else
56 #include "GuBV4_BoxBoxOverlapTest.h"
57#endif
58
59#include "GuBV4_BoxSweep_Params.h"
60
61static PX_FORCE_INLINE Vec4V multiply3x3V(const Vec4V p, const PxMat33& mat_Padded)
62{
63 const FloatV xxxV = V4GetX(p);
64 const FloatV yyyV = V4GetY(p);
65 const FloatV zzzV = V4GetZ(p);
66
67 Vec4V ResV = V4Scale(V4LoadU_Safe(&mat_Padded.column0.x), xxxV);
68 ResV = V4Add(ResV, V4Scale(V4LoadU_Safe(&mat_Padded.column1.x), yyyV));
69 ResV = V4Add(ResV, V4Scale(V4LoadU_Safe(&mat_Padded.column2.x), zzzV));
70
71 return ResV;
72}
73
74// PT: TODO: __fastcall removed to make it compile everywhere. Revisit.
75static bool /*__fastcall*/ triBoxSweep(BoxSweepParams* PX_RESTRICT params, PxU32 primIndex, bool nodeSorting=true)
76{
77 PxU32 VRef0, VRef1, VRef2;
78 getVertexReferences(VRef0, VRef1, VRef2, primIndex, params->mTris32, params->mTris16);
79
80 const PxVec3& p0 = params->mVerts[VRef0];
81 const PxVec3& p1 = params->mVerts[VRef1];
82 const PxVec3& p2 = params->mVerts[VRef2];
83
84 // Don't bother doing the actual sweep test if the triangle is too far away
85 if(1)
86 {
87 const float dp0 = p0.dot(params->mLocalDir_Padded);
88 const float dp1 = p1.dot(params->mLocalDir_Padded);
89 const float dp2 = p2.dot(params->mLocalDir_Padded);
90
91 float TriMin = PxMin(dp0, dp1);
92 TriMin = PxMin(TriMin, dp2);
93
94 if(TriMin >= params->mOffset + params->mStabbedFace.mDistance)
95 return false;
96 }
97
98 PxTrianglePadded triBoxSpace;
99 const Vec4V transModelToBoxV = V4LoadU_Safe(&params->mTModelToBox_Padded.x);
100 const Vec4V v0V = V4Add(multiply3x3V(V4LoadU_Safe(&p0.x), params->mRModelToBox_Padded), transModelToBoxV);
101 V4StoreU_Safe(v0V, &triBoxSpace.verts[0].x);
102 const Vec4V v1V = V4Add(multiply3x3V(V4LoadU_Safe(&p1.x), params->mRModelToBox_Padded), transModelToBoxV);
103 V4StoreU_Safe(v1V, &triBoxSpace.verts[1].x);
104 const Vec4V v2V = V4Add(multiply3x3V(V4LoadU_Safe(&p2.x), params->mRModelToBox_Padded), transModelToBoxV);
105 V4StoreU_Safe(v2V, &triBoxSpace.verts[2].x);
106
107 float Dist;
108 if(triBoxSweepTestBoxSpace_inlined(triBoxSpace, params->mOriginalExtents_Padded, params->mOriginalDir_Padded*params->mStabbedFace.mDistance, params->mOneOverDir_Padded, 1.0f, Dist, params->mBackfaceCulling))
109 {
110 // PT: TODO: these muls & divs may not be needed at all - we just pass the unit dir/inverse dir to the sweep code. Revisit. (TA34704)
111 Dist *= params->mStabbedFace.mDistance;
112 params->mOneOverDir_Padded = params->mOneOverOriginalDir / Dist;
113 params->mStabbedFace.mDistance = Dist;
114 params->mStabbedFace.mTriangleID = primIndex;
115 // PT: TODO: revisit this (TA34704)
116 params->mP0 = triBoxSpace.verts[0];
117 params->mP1 = triBoxSpace.verts[1];
118 params->mP2 = triBoxSpace.verts[2];
119// V4StoreU_Safe(v0V, &params->mP0.x);
120// V4StoreU_Safe(v1V, &params->mP1.x);
121// V4StoreU_Safe(v2V, &params->mP2.x);
122
123 if(nodeSorting)
124 {
125#ifdef SWEEP_AABB_IMPL
126 #ifndef GU_BV4_USE_SLABS
127 setupRayData(params, Dist, params->mOrigin_Padded, params->mLocalDir_PaddedAligned);
128 #endif
129#else
130 params->ShrinkOBB(Dist);
131#endif
132 }
133 return true;
134 }
135 return false;
136}
137
138namespace
139{
140class LeafFunction_BoxSweepClosest
141{
142public:
143 static PX_FORCE_INLINE void doLeafTest(BoxSweepParams* PX_RESTRICT params, PxU32 primIndex)
144 {
145 PxU32 nbToGo = getNbPrimitives(primIndex);
146 do
147 {
148 triBoxSweep(params, primIndex);
149 primIndex++;
150 }while(nbToGo--);
151 }
152};
153
154class LeafFunction_BoxSweepAny
155{
156public:
157 static PX_FORCE_INLINE PxIntBool doLeafTest(BoxSweepParams* PX_RESTRICT params, PxU32 primIndex)
158 {
159 PxU32 nbToGo = getNbPrimitives(primIndex);
160 do
161 {
162 if(triBoxSweep(params, primIndex))
163 return 1;
164 primIndex++;
165 }while(nbToGo--);
166
167 return 0;
168 }
169};
170}
171
172// PT: TODO: refactor with sphere/capsule versions (TA34704)
173static PX_FORCE_INLINE bool computeImpactData(const Box& box, const PxVec3& dir, SweepHit* PX_RESTRICT hit, const BoxSweepParams* PX_RESTRICT params, bool isDoubleSided, bool meshBothSides)
174{
175 if(params->mStabbedFace.mTriangleID==PX_INVALID_U32)
176 return false; // We didn't touch any triangle
177
178 if(hit)
179 {
180 const float t = params->mStabbedFace.mDistance;
181 hit->mTriangleID = params->mStabbedFace.mTriangleID;
182 hit->mDistance = t;
183
184 if(t==0.0f)
185 {
186 hit->mPos = PxVec3(0.0f);
187 hit->mNormal = -dir;
188 }
189 else
190 {
191 // PT: TODO: revisit/optimize/use this (TA34704)
192 const PxTriangle triInBoxSpace(params->mP0, params->mP1, params->mP2);
193 PxHitFlags outFlags = PxHitFlag::Enum(0);
194 computeBoxLocalImpact(hit->mPos, hit->mNormal, outFlags, box, params->mOriginalDir_Padded, triInBoxSpace, PxHitFlag::ePOSITION|PxHitFlag::eNORMAL, isDoubleSided, meshBothSides, t);
195 }
196 }
197 return true;
198}
199
200template<class ParamsT>
201static PX_FORCE_INLINE void setupBoxSweepParams(ParamsT* PX_RESTRICT params, const Box& localBox, const PxVec3& localDir, float maxDist, const BV4Tree* PX_RESTRICT tree, const SourceMesh* PX_RESTRICT mesh, PxU32 flags)
202{
203 params->mStabbedFace.mTriangleID = PX_INVALID_U32;
204 setupParamsFlags(params, flags);
205
206 setupMeshPointersAndQuantizedCoeffs(params, mesh, tree);
207
208 prepareSweepData(localBox, localDir, maxDist, params);
209
210#ifdef SWEEP_AABB_IMPL
211 params->mOrigin_Padded = localBox.center;
212 #ifndef GU_BV4_USE_SLABS
213 params->mLocalDir_PaddedAligned = localDir;
214 setupRayData(params, maxDist, localBox.center, localDir);
215 #endif
216#endif
217}
218
219#ifdef GU_BV4_USE_SLABS
220 #include "GuBV4_Slabs.h"
221#endif
222#ifdef SWEEP_AABB_IMPL
223 #include "GuBV4_ProcessStreamOrdered_SegmentAABB_Inflated.h"
224 #include "GuBV4_ProcessStreamNoOrder_SegmentAABB_Inflated.h"
225 #ifdef GU_BV4_USE_SLABS
226 #include "GuBV4_Slabs_KajiyaNoOrder.h"
227 #include "GuBV4_Slabs_KajiyaOrdered.h"
228 #endif
229#else
230 #include "GuBV4_ProcessStreamOrdered_OBBOBB.h"
231 #include "GuBV4_ProcessStreamNoOrder_OBBOBB.h"
232 #ifdef GU_BV4_USE_SLABS
233 #include "GuBV4_Slabs_SwizzledNoOrder.h"
234 #include "GuBV4_Slabs_SwizzledOrdered.h"
235 #endif
236#endif
237
238#ifdef SWEEP_AABB_IMPL
239 #define GU_BV4_PROCESS_STREAM_RAY_NO_ORDER
240 #define GU_BV4_PROCESS_STREAM_RAY_ORDERED
241#else
242 #define GU_BV4_PROCESS_STREAM_NO_ORDER
243 #define GU_BV4_PROCESS_STREAM_ORDERED
244#endif
245#include "GuBV4_Internal.h"
246
247#ifdef SWEEP_AABB_IMPL
248PxIntBool Sweep_AABB_BV4(const Box& localBox, const PxVec3& localDir, float maxDist, const BV4Tree& tree, SweepHit* PX_RESTRICT hit, PxU32 flags)
249#else
250PxIntBool Sweep_OBB_BV4(const Box& localBox, const PxVec3& localDir, float maxDist, const BV4Tree& tree, SweepHit* PX_RESTRICT hit, PxU32 flags)
251#endif
252{
253 const SourceMesh* PX_RESTRICT mesh = static_cast<const SourceMesh*>(tree.mMeshInterface);
254
255 BoxSweepParams Params;
256 setupBoxSweepParams(&Params, localBox, localDir, maxDist, &tree, mesh, flags);
257
258 if(tree.mNodes)
259 {
260#ifdef SWEEP_AABB_IMPL
261 if(Params.mEarlyExit)
262 processStreamRayNoOrder<1, LeafFunction_BoxSweepAny>(tree, &Params);
263 else
264 processStreamRayOrdered<1, LeafFunction_BoxSweepClosest>(tree, &Params);
265#else
266 if(Params.mEarlyExit)
267 processStreamNoOrder<LeafFunction_BoxSweepAny>(tree, &Params);
268 else
269 processStreamOrdered<LeafFunction_BoxSweepClosest>(tree, &Params);
270#endif
271 }
272 else
273 doBruteForceTests<LeafFunction_BoxSweepAny, LeafFunction_BoxSweepClosest>(mesh->getNbTriangles(), &Params);
274
275 return computeImpactData(localBox, localDir, hit, &Params, (flags & QUERY_MODIFIER_DOUBLE_SIDED)!=0, (flags & QUERY_MODIFIER_MESH_BOTH_SIDES)!=0);
276}
277
278
279
280// PT: box sweep callback version - currently not used
281
282namespace
283{
284 struct BoxSweepParamsCB : BoxSweepParams
285 {
286 // PT: these new members are only here to call computeImpactData during traversal :(
287 // PT: TODO: most of them may not be needed
288 Box mBoxCB; // Box in original space (maybe not local/mesh space)
289 PxVec3 mDirCB; // Dir in original space (maybe not local/mesh space)
290 const PxMat44* mWorldm_Aligned;
291 PxU32 mFlags;
292
293 SweepUnlimitedCallback mCallback;
294 void* mUserData;
295 float mMaxDist;
296 bool mNodeSorting;
297 };
298
299class LeafFunction_BoxSweepCB
300{
301public:
302 static PX_FORCE_INLINE PxIntBool doLeafTest(BoxSweepParamsCB* PX_RESTRICT params, PxU32 primIndex)
303 {
304 PxU32 nbToGo = getNbPrimitives(primIndex);
305 do
306 {
307 if(triBoxSweep(params, primIndex, params->mNodeSorting))
308 {
309 // PT: TODO: in this version we must compute the impact data immediately,
310 // which is a terrible idea in general, but I'm not sure what else I can do.
311 SweepHit hit;
312 const bool b = computeImpactData(params->mBoxCB, params->mDirCB, &hit, params, (params->mFlags & QUERY_MODIFIER_DOUBLE_SIDED)!=0, (params->mFlags & QUERY_MODIFIER_MESH_BOTH_SIDES)!=0);
313 PX_ASSERT(b);
314
315 // PT: then replicate part from BV4_BoxSweepSingle:
316 if(b && params->mWorldm_Aligned)
317 {
318 // Move to world space
319 // PT: TODO: optimize (TA34704)
320 hit.mPos = params->mWorldm_Aligned->transform(hit.mPos);
321 hit.mNormal = params->mWorldm_Aligned->rotate(hit.mNormal);
322 }
323
324 reportUnlimitedCallbackHit(params, hit);
325 }
326
327 primIndex++;
328 }while(nbToGo--);
329
330 return 0;
331 }
332};
333
334}
335
336// PT: for design decisions in this function, refer to the comments of BV4_GenericSweepCB().
337// PT: 'worldm_Aligned' is only here to move back results to world space, but input is already in local space.
338#ifdef SWEEP_AABB_IMPL
339void Sweep_AABB_BV4_CB(const Box& localBox, const PxVec3& localDir, float maxDist, const BV4Tree& tree, const PxMat44* PX_RESTRICT worldm_Aligned, SweepUnlimitedCallback callback, void* userData, PxU32 flags, bool nodeSorting)
340#else
341void Sweep_OBB_BV4_CB(const Box& localBox, const PxVec3& localDir, float maxDist, const BV4Tree& tree, const PxMat44* PX_RESTRICT worldm_Aligned, SweepUnlimitedCallback callback, void* userData, PxU32 flags, bool nodeSorting)
342#endif
343{
344 const SourceMesh* PX_RESTRICT mesh = static_cast<const SourceMesh*>(tree.mMeshInterface);
345
346 BoxSweepParamsCB Params;
347 Params.mBoxCB = localBox;
348 Params.mDirCB = localDir;
349 Params.mWorldm_Aligned = worldm_Aligned;
350 Params.mFlags = flags;
351
352 Params.mCallback = callback;
353 Params.mUserData = userData;
354 Params.mMaxDist = maxDist;
355 Params.mNodeSorting = nodeSorting;
356 setupBoxSweepParams(&Params, localBox, localDir, maxDist, &tree, mesh, flags);
357
358 PX_ASSERT(!Params.mEarlyExit);
359
360 if(tree.mNodes)
361 {
362 if(nodeSorting)
363 {
364#ifdef SWEEP_AABB_IMPL
365 processStreamRayOrdered<1, LeafFunction_BoxSweepCB>(tree, &Params);
366#else
367 processStreamOrdered<LeafFunction_BoxSweepCB>(tree, &Params);
368#endif
369 }
370 else
371 {
372#ifdef SWEEP_AABB_IMPL
373 processStreamRayNoOrder<1, LeafFunction_BoxSweepCB>(tree, &Params);
374#else
375 processStreamNoOrder<LeafFunction_BoxSweepCB>(tree, &Params);
376#endif
377 }
378 }
379 else
380 doBruteForceTests<LeafFunction_BoxSweepCB, LeafFunction_BoxSweepCB>(mesh->getNbTriangles(), &Params);
381}
382
383
384
385
386// New callback-based box sweeps. Reuses code above, allow early exits. Some init code may be done in vain
387// since the leaf tests are not performed (we don't do box-sweeps-vs-tri since the box is only a BV around
388// the actual shape, say a convex)
389
390namespace
391{
392struct GenericSweepParamsCB : BoxSweepParams
393{
394 MeshSweepCallback mCallback;
395 void* mUserData;
396};
397
398class LeafFunction_BoxSweepClosestCB
399{
400public:
401 static PX_FORCE_INLINE void doLeafTest(GenericSweepParamsCB* PX_RESTRICT params, PxU32 prim_index)
402 {
403 PxU32 nbToGo = getNbPrimitives(prim_index);
404 do
405 {
406 // PT: in the regular version we'd do a box-vs-triangle sweep test here
407 // Instead we just grab the triangle and send it to the callback
408 //
409 // This can be used for regular "closest hit" sweeps, when the scale is not identity or
410 // when the box is just around a more complex shape (e.g. convex). In this case we want
411 // the calling code to compute a convex-triangle distance, and then we want to shrink
412 // the ray/box while doing an ordered traversal.
413 //
414 // For "sweep all" or "sweep any" purposes we want to either report all hits or early exit
415 // as soon as we find one. There is no need for shrinking or ordered traversals here.
416
417 PxU32 VRef0, VRef1, VRef2;
418 getVertexReferences(VRef0, VRef1, VRef2, prim_index, params->mTris32, params->mTris16);
419
420 const PxVec3& p0 = params->mVerts[VRef0];
421 const PxVec3& p1 = params->mVerts[VRef1];
422 const PxVec3& p2 = params->mVerts[VRef2];
423
424 // Don't bother doing the actual sweep test if the triangle is too far away
425 const float dp0 = p0.dot(params->mLocalDir_Padded);
426 const float dp1 = p1.dot(params->mLocalDir_Padded);
427 const float dp2 = p2.dot(params->mLocalDir_Padded);
428
429 float TriMin = PxMin(dp0, dp1);
430 TriMin = PxMin(TriMin, dp2);
431
432 if(TriMin < params->mOffset + params->mStabbedFace.mDistance)
433 {
434// const PxU32 vrefs[3] = { VRef0, VRef1, VRef2 };
435 float Dist = params->mStabbedFace.mDistance;
436 if((params->mCallback)(params->mUserData, p0, p1, p2, prim_index, /*vrefs,*/ Dist))
437 return; // PT: TODO: we return here but the ordered path doesn't really support early exits (TA34704)
438
439 if(Dist<params->mStabbedFace.mDistance)
440 {
441 params->mStabbedFace.mDistance = Dist;
442 params->mStabbedFace.mTriangleID = prim_index;
443#ifdef SWEEP_AABB_IMPL
444 #ifndef GU_BV4_USE_SLABS
445 setupRayData(params, Dist, params->mOrigin_Padded, params->mLocalDir_PaddedAligned);
446 #endif
447#else
448 params->ShrinkOBB(Dist);
449#endif
450 }
451 }
452
453 prim_index++;
454 }while(nbToGo--);
455 }
456};
457
458class LeafFunction_BoxSweepAnyCB
459{
460public:
461 static PX_FORCE_INLINE PxIntBool doLeafTest(GenericSweepParamsCB* PX_RESTRICT params, PxU32 prim_index)
462 {
463 PxU32 nbToGo = getNbPrimitives(prim_index);
464 do
465 {
466 PxU32 VRef0, VRef1, VRef2;
467 getVertexReferences(VRef0, VRef1, VRef2, prim_index, params->mTris32, params->mTris16);
468
469 const PxVec3& p0 = params->mVerts[VRef0];
470 const PxVec3& p1 = params->mVerts[VRef1];
471 const PxVec3& p2 = params->mVerts[VRef2];
472
473 {
474// const PxU32 vrefs[3] = { VRef0, VRef1, VRef2 };
475 float Dist = params->mStabbedFace.mDistance;
476 if((params->mCallback)(params->mUserData, p0, p1, p2, prim_index, /*vrefs,*/ Dist))
477 return 1;
478 }
479
480 prim_index++;
481 }while(nbToGo--);
482
483 return 0;
484 }
485};
486}
487
488#ifdef SWEEP_AABB_IMPL
489void GenericSweep_AABB_CB(const Box& localBox, const PxVec3& localDir, float maxDist, const BV4Tree& tree, MeshSweepCallback callback, void* userData, PxU32 flags)
490#else
491void GenericSweep_OBB_CB(const Box& localBox, const PxVec3& localDir, float maxDist, const BV4Tree& tree, MeshSweepCallback callback, void* userData, PxU32 flags)
492#endif
493{
494 const SourceMesh* PX_RESTRICT mesh = static_cast<const SourceMesh*>(tree.mMeshInterface);
495
496 GenericSweepParamsCB Params;
497 Params.mCallback = callback;
498 Params.mUserData = userData;
499 setupBoxSweepParams(&Params, localBox, localDir, maxDist, &tree, mesh, flags);
500
501 if(tree.mNodes)
502 {
503#ifdef SWEEP_AABB_IMPL
504 if(Params.mEarlyExit)
505 processStreamRayNoOrder<1, LeafFunction_BoxSweepAnyCB>(tree, &Params);
506 else
507 processStreamRayOrdered<1, LeafFunction_BoxSweepClosestCB>(tree, &Params);
508#else
509 if(Params.mEarlyExit)
510 processStreamNoOrder<LeafFunction_BoxSweepAnyCB>(tree, &Params);
511 else
512 processStreamOrdered<LeafFunction_BoxSweepClosestCB>(tree, &Params);
513#endif
514 }
515 else
516 doBruteForceTests<LeafFunction_BoxSweepAnyCB, LeafFunction_BoxSweepClosestCB>(mesh->getNbTriangles(), &Params);
517}
A padded version of PxVec3, to safely load its data using SIMD.
Definition PxVec3.h:392
PX_CUDA_CALLABLE PX_FORCE_INLINE Type dot(const PxVec3T &v) const
returns the scalar product of this and other.
Definition PxVec3.h:274
#define PX_RESTRICT
Definition PxPreprocessor.h:355
#define PX_FORCE_INLINE
Definition PxPreprocessor.h:335
PX_FORCE_INLINE int triBoxSweepTestBoxSpace_inlined(const PxTriangle &tri, const PxVec3 &extents, const PxVec3 &dir, const PxVec3 &oneOverDir, float tmax, float &toi, PxU32 doBackfaceCulling)
Inlined version of triBoxSweepTestBoxSpace. See that other function for comments.
Definition GuSweepBoxTriangle_SAT.h:201
PX_CUDA_CALLABLE PX_FORCE_INLINE T PxMin(T a, T b)
The return value is the lesser of the two specified values.
Definition PxMath.h:88
Definition GuBV4_BoxSweep_Internal.h:42