29#ifndef GU_BV4_CAPSULE_SWEEP_INTERNAL_H
30#define GU_BV4_CAPSULE_SWEEP_INTERNAL_H
38static PX_FORCE_INLINE bool sweepSphereVSTriangle(
const PxVec3& center,
const float radius,
39 const PxVec3*
PX_RESTRICT triVerts,
const PxVec3& triUnitNormal,
40 const PxVec3& unitDir,
41 float& curT,
bool& directHit)
43 float currentDistance;
44 if(!
sweepSphereVSTri(triVerts, triUnitNormal, center, radius, unitDir, currentDistance, directHit,
true))
48 if(currentDistance > curT + GU_EPSILON_SAME_DISTANCE *
PxMax(1.0f, curT))
50 curT = currentDistance;
54static PX_FORCE_INLINE bool sweepSphereVSQuad(
const PxVec3& center,
const float radius,
55 const PxVec3*
PX_RESTRICT quadVerts,
const PxVec3& quadUnitNormal,
56 const PxVec3& unitDir,
59 float currentDistance;
60 if(!sweepSphereVSQuad(quadVerts, quadUnitNormal, center, radius, unitDir, currentDistance))
64 if(currentDistance > curT + GU_EPSILON_SAME_DISTANCE *
PxMax(1.0f, curT))
66 curT = currentDistance;
73static bool testTri(
const CapsuleSweepParams*
PX_RESTRICT params,
const PxVec3& p0,
const PxVec3& p1,
const PxVec3& p2,
const PxVec3& N,
74 const PxVec3& unitDir,
const float capsuleRadius,
const float dpc0,
float& curT,
bool& status)
84 if(rejectTriangle(params->mCapsuleCenter, unitDir, curT, capsuleRadius, currentTri, dpc0))
87 float magnitude = N.magnitude();
91 PxVec3 triNormal = N / magnitude;
94 if(sweepSphereVSTriangle(params->mCapsuleCenter, capsuleRadius, currentTri, triNormal, unitDir, curT, DirectHit))
102static void testQuad(
const CapsuleSweepParams*
PX_RESTRICT params,
const PxVec3& p0,
const PxVec3& p1,
const PxVec3& p2,
const PxVec3& p3,
const PxVec3& N,
103 const PxVec3& unitDir,
const float capsuleRadius,
const float dpc0,
float& curT,
bool& status)
106 PxVec3 currentQuad[4];
113 if(rejectQuad(params->mCapsuleCenter, unitDir, curT, capsuleRadius, currentQuad, dpc0))
116 float magnitude = N.magnitude();
120 PxVec3 triNormal = N / magnitude;
122 if(sweepSphereVSQuad(params->mCapsuleCenter, capsuleRadius, currentQuad, triNormal, unitDir, curT))
128static PX_FORCE_INLINE float Set2(
const PxVec3& p0,
const PxVec3& n,
const PxVec3& p)
130 return (p-p0).dot(n);
133static PX_FORCE_INLINE bool sweepCapsuleVsTriangle(
const CapsuleSweepParams*
PX_RESTRICT params,
const PxTriangle& triangle,
float& t,
bool isDoubleSided, PxVec3& normal)
135 const PxVec3& unitDir = params->mLocalDir_Padded;
138 PxVec3 denormalizedNormal = (triangle.verts[0] - triangle.verts[1]).
cross(triangle.verts[0] - triangle.verts[2]);
140 normal = denormalizedNormal;
143 const bool culled = denormalizedNormal.dot(unitDir) > 0.0f;
149 denormalizedNormal = -denormalizedNormal;
152 const float capsuleRadius = params->mLocalCapsule.radius;
153 float curT = params->mStabbedFace.mDistance;
154 const float dpc0 = params->mCapsuleCenter.dot(unitDir);
159 const PxVec3 p0 = triangle.verts[0] - params->mExtrusionDir;
160 const PxVec3 p1 = triangle.verts[1+culled] - params->mExtrusionDir;
161 const PxVec3 p2 = triangle.verts[2-culled] - params->mExtrusionDir;
163 const PxVec3 p0b = triangle.verts[0] + params->mExtrusionDir;
164 const PxVec3 p1b = triangle.verts[1+culled] + params->mExtrusionDir;
165 const PxVec3 p2b = triangle.verts[2-culled] + params->mExtrusionDir;
167 const float extrusionSign = denormalizedNormal.
dot(params->mExtrusionDir);
169 const PxVec3 p2b_p1b = p2b - p1b;
170 const PxVec3 p0b_p1b = p0b - p1b;
171 const PxVec3 p2b_p2 = 2.0f * params->mExtrusionDir;
172 const PxVec3 p1_p1b = -p2b_p2;
174 const PxVec3 N1 = p2b_p1b.
cross(p0b_p1b);
175 const float dp0 = Set2(p0b, N1, params->mCapsuleCenter);
177 const PxVec3 N2 = (p2 - p1).
cross(p0 - p1);
178 const float dp1 = -Set2(p0, N2, params->mCapsuleCenter);
181 if(extrusionSign >= 0.0f)
182 directHit = testTri(params, p0b, p1b, p2b, N1, unitDir, capsuleRadius, dpc0, curT, status);
184 directHit = testTri(params, p0, p1, p2, N2, unitDir, capsuleRadius, dpc0, curT, status);
186 const PxVec3 N3 = p2b_p1b.
cross(p1_p1b);
187 const float dp2 = -Set2(p1, N3, params->mCapsuleCenter);
190 const float dp = N3.dot(unitDir);
191 if(dp*extrusionSign>=0.0f)
192 testQuad(params, p1, p1b, p2, p2b, N3, unitDir, capsuleRadius, dpc0, curT, status);
195 const PxVec3 N5 = p2b_p2.
cross(p0 - p2);
196 const float dp3 = -Set2(p0, N5, params->mCapsuleCenter);
199 const float dp = N5.dot(unitDir);
200 if(dp*extrusionSign>=0.0f)
201 testQuad(params, p2, p2b, p0, p0b, N5, unitDir, capsuleRadius, dpc0, curT, status);
204 const PxVec3 N7 = p1_p1b.
cross(p0b_p1b);
205 const float dp4 = -Set2(p0b, N7, params->mCapsuleCenter);
208 const float dp = N7.dot(unitDir);
209 if(dp*extrusionSign>=0.0f)
210 testQuad(params, p0, p0b, p1, p1b, N7, unitDir, capsuleRadius, dpc0, curT, status);
215 bool originInside =
true;
216 if(extrusionSign<0.0f)
218 if(dp0<0.0f || dp1<0.0f || dp2<0.0f || dp3<0.0f || dp4<0.0f)
219 originInside =
false;
223 if(dp0>0.0f || dp1>0.0f || dp2>0.0f || dp3>0.0f || dp4>0.0f)
224 originInside =
false;
242static bool triCapsuleSweep(CapsuleSweepParams*
PX_RESTRICT params, PxU32 primIndex,
bool nodeSorting=
true)
244 PxU32 VRef0, VRef1, VRef2;
245 getVertexReferences(VRef0, VRef1, VRef2, primIndex, params->mTris32, params->mTris16);
247 const PxVec3& p0 = params->mVerts[VRef0];
248 const PxVec3& p1 = params->mVerts[VRef1];
249 const PxVec3& p2 = params->mVerts[VRef2];
251 const PxTriangle Tri(p0, p1, p2);
253 const bool isDoubleSided = params->mBackfaceCulling==0;
256 PxVec3 denormalizedNormal;
257 if(sweepCapsuleVsTriangle(params, Tri, dist, isDoubleSided, denormalizedNormal))
262 if(
keepTriangle(dist, alignmentValue, params->mBestDistance, params->mBestAlignmentValue, params->mMaxDist))
264 params->mStabbedFace.mDistance = dist;
265 params->mStabbedFace.mTriangleID = primIndex;
271 params->mBestDistance =
PxMin(params->mBestDistance, dist);
272 params->mBestAlignmentValue = alignmentValue;
273 params->mBestTriNormal = denormalizedNormal;
277#ifdef SWEEP_AABB_IMPL
278 #ifndef GU_BV4_USE_SLABS
280 setupRayData(params, params->mBestDistance, params->mOrigin_Padded, params->mLocalDir_PaddedAligned);
284 params->ShrinkOBB(params->mBestDistance);
290 else if(keepTriangleBasic(dist, params->mBestDistance, params->mMaxDist))
292 params->mStabbedFace.mDistance = dist;
293 params->mBestDistance =
PxMin(params->mBestDistance, dist);
300#include "GuDistanceSegmentTriangleSIMD.h"
304class LeafFunction_CapsuleSweepClosest
309 PxU32 nbToGo = getNbPrimitives(primIndex);
312 triCapsuleSweep(params, primIndex);
318class LeafFunction_CapsuleSweepAny
324 PxU32 nbToGo = getNbPrimitives(primIndex);
327 if(triCapsuleSweep(params, primIndex))
336class ImpactFunctionCapsule
339 static PX_FORCE_INLINE void computeImpact(PxVec3& impactPos, PxVec3& impactNormal,
const Capsule& capsule,
const PxVec3& dir,
const PxReal t,
const PxTrianglePadded& triangle)
341 const PxVec3 delta = dir * t;
342 const PxVec3p P0 = capsule.p0 + delta;
343 const PxVec3p P1 = capsule.p1 + delta;
344 Vec3V pointOnSeg, pointOnTri;
345 distanceSegmentTriangleSquared(
347 V3LoadU_SafeReadW(P0), V3LoadU_SafeReadW(P1),
349 V3LoadU_SafeReadW(triangle.verts[0]), V3LoadU_SafeReadW(triangle.verts[1]), V3LoadU_SafeReadW(triangle.verts[2]),
350 pointOnSeg, pointOnTri);
352 PxVec3 localImpactPos, tmp;
353 V3StoreU(pointOnTri, localImpactPos);
354 V3StoreU(pointOnSeg, tmp);
357 PxVec3 localImpactNormal = tmp - localImpactPos;
358 const float M = localImpactNormal.
magnitude();
361 localImpactNormal = (triangle.verts[0] - triangle.verts[1]).
cross(triangle.verts[0] - triangle.verts[2]);
362 localImpactNormal.normalize();
365 localImpactNormal /= M;
367 impactPos = localImpactPos;
368 impactNormal = localImpactNormal;
376 box.center = capsule.computeCenter();
378 extrusionDir = (capsule.p0 - capsule.p1)*0.5f;
379 const PxF32 d = extrusionDir.magnitude();
382 box.extents.x = capsule.radius + d;
383 box.extents.y = capsule.radius;
384 box.extents.z = capsule.radius;
389 box.rot = PxMat33(PxIdentity);
393 PxVec3 dir, right, up;
395 box.setAxes(dir, right, up);
399template<
class ParamsT>
402 params->mStabbedFace.mTriangleID = PX_INVALID_U32;
403 params->mBestAlignmentValue = 2.0f;
404 params->mBestDistance = maxDist + GU_EPSILON_SAME_DISTANCE;
405 params->mMaxDist = maxDist;
407 setupParamsFlags(params, flags);
409 setupMeshPointersAndQuantizedCoeffs(params, mesh, tree);
411 params->mLocalCapsule = capsule;
416 params->mCapsuleCenter = localBox.center;
418 const PxVec3& localDir = dir;
420#ifdef SWEEP_AABB_IMPL
421 const PxVec3& localP0 = params->mLocalCapsule.p0;
422 const PxVec3& localP1 = params->mLocalCapsule.p1;
423 const PxVec3 sweepOrigin = (localP0+localP1)*0.5f;
424 const PxVec3 sweepExtents = PxVec3(params->mLocalCapsule.radius) + (localP0-localP1).abs()*0.5f;
426 #ifndef GU_BV4_USE_SLABS
427 params->mLocalDir_PaddedAligned = localDir;
429 params->mOrigin_Padded = sweepOrigin;
431 const Box aabb(sweepOrigin, sweepExtents, PxMat33(PxIdentity));
432 prepareSweepData(aabb, localDir, maxDist, params);
434 #ifndef GU_BV4_USE_SLABS
435 setupRayData(params, maxDist, sweepOrigin, localDir);
438 prepareSweepData(localBox, localDir, maxDist, params);
PX_CUDA_CALLABLE PX_FORCE_INLINE Type magnitude() const
returns the magnitude
Definition PxVec3.h:181
PX_CUDA_CALLABLE PX_FORCE_INLINE Type dot(const PxVec3T &v) const
returns the scalar product of this and other.
Definition PxVec3.h:274
PX_CUDA_CALLABLE PX_FORCE_INLINE Type normalize()
normalizes the vector in place
Definition PxVec3.h:297
PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3T cross(const PxVec3T &v) const
cross product
Definition PxVec3.h:282
GLM_FUNC_QUALIFIER vec< 3, T, Q > cross(vec< 3, T, Q > const &x, vec< 3, T, Q > const &y)
Definition func_geometric.inl:175
#define PX_RESTRICT
Definition PxPreprocessor.h:355
#define PX_FORCE_INLINE
Definition PxPreprocessor.h:335
PX_FORCE_INLINE bool keepTriangle(float triImpactDistance, float triAlignmentValue, float bestImpactDistance, float bestAlignmentValue, float maxDistance)
Definition GuInternal.h:110
PX_FORCE_INLINE PxReal computeAlignmentValue(const PxVec3 &triNormal, const PxVec3 &unitDir)
Definition GuInternal.h:88
bool sweepSphereVSTri(const PxVec3 *PX_RESTRICT triVerts, const PxVec3 &triUnitNormal, const PxVec3 &sphereCenter, PxReal sphereRadius, const PxVec3 &unitDir, PxReal &impactDistance, bool &directHit, bool testInitialOverlap)
Definition GuSweepSphereTriangle.cpp:203
void computeBoxAroundCapsule(const Capsule &capsule, Box &box)
Definition GuCapsule.cpp:40
PX_INLINE void PxComputeBasisVectors(const PxVec3 &dir, PxVec3 &right, PxVec3 &up)
Compute two normalized vectors (right and up) that are perpendicular to an input normalized vector (d...
Definition PxMathUtils.h:271
PX_CUDA_CALLABLE PX_FORCE_INLINE T PxMax(T a, T b)
The return value is the greater of the two specified values.
Definition PxMath.h:72
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