diff options
| author | git perforce import user <a@b> | 2016-10-25 12:29:14 -0600 |
|---|---|---|
| committer | Sheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees> | 2016-10-25 18:56:37 -0500 |
| commit | 3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch) | |
| tree | fa6485c169e50d7415a651bf838f5bcd0fd3bfbd /PhysX_3.4/Source/GeomUtils/src/GuSweepSharedTests.cpp | |
| download | physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.tar.xz physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.zip | |
Initial commit:
PhysX 3.4.0 Update @ 21294896
APEX 1.4.0 Update @ 21275617
[CL 21300167]
Diffstat (limited to 'PhysX_3.4/Source/GeomUtils/src/GuSweepSharedTests.cpp')
| -rw-r--r-- | PhysX_3.4/Source/GeomUtils/src/GuSweepSharedTests.cpp | 726 |
1 files changed, 726 insertions, 0 deletions
diff --git a/PhysX_3.4/Source/GeomUtils/src/GuSweepSharedTests.cpp b/PhysX_3.4/Source/GeomUtils/src/GuSweepSharedTests.cpp new file mode 100644 index 00000000..162de3f5 --- /dev/null +++ b/PhysX_3.4/Source/GeomUtils/src/GuSweepSharedTests.cpp @@ -0,0 +1,726 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#include "GuSweepTests.h" +#include "GuHeightFieldUtil.h" +#include "CmScaling.h" +#include "GuConvexMesh.h" +#include "GuIntersectionRayPlane.h" +#include "GuVecBox.h" +#include "GuVecShrunkBox.h" +#include "GuVecCapsule.h" +#include "GuVecConvexHull.h" +#include "GuSweepMTD.h" +#include "PxConvexMeshGeometry.h" +#include "PxSphereGeometry.h" +#include "GuSweepSphereCapsule.h" +#include "GuSweepCapsuleCapsule.h" +#include "GuSweepTriangleUtils.h" +#include "GuSweepCapsuleTriangle.h" +#include "GuInternal.h" +#include "GuGJKRaycast.h" + +using namespace physx; +using namespace Gu; +using namespace Cm; +using namespace physx::shdfnd::aos; + +static const PxReal gEpsilon = .01f; + +static PxU32 computeSweepConvexPlane( + const PxConvexMeshGeometry& convexGeom, ConvexHullData* hullData, const PxU32& nbPolys, const PxTransform& pose, + const PxVec3& impact_, const PxVec3& unitDir) +{ + PX_ASSERT(nbPolys); + + const PxVec3 impact = impact_ - unitDir * gEpsilon; + + const PxVec3 localPoint = pose.transformInv(impact); + const PxVec3 localDir = pose.rotateInv(unitDir); + + const FastVertex2ShapeScaling scaling(convexGeom.scale); + + PxU32 minIndex = 0; + PxReal minD = PX_MAX_REAL; + for(PxU32 j=0; j<nbPolys; j++) + { + const PxPlane& pl = hullData->mPolygons[j].mPlane; + + PxPlane plane; + scaling.transformPlaneToShapeSpace(pl.n, pl.d, plane.n, plane.d); + + PxReal d = plane.distance(localPoint); + if(d<0.0f) + continue; + + const PxReal tweak = plane.n.dot(localDir) * gEpsilon; + d += tweak; + + if(d<minD) + { + minIndex = j; + minD = d; + } + } + return minIndex; +} + +static PX_FORCE_INLINE bool computeFaceIndex(PxSweepHit& sweepHit, const PxHitFlags hitFlags, const PxConvexMeshGeometry& convexGeom, ConvexHullData* hullData, const PxTransform& pose, const PxVec3& unitDir) +{ + if(hitFlags & PxHitFlag::eFACE_INDEX) + { + // PT: compute closest polygon using the same tweak as in swept-capsule-vs-mesh + sweepHit.faceIndex = computeSweepConvexPlane(convexGeom, hullData, hullData->mNbPolygons, pose, sweepHit.position, unitDir); + sweepHit.flags |= PxHitFlag::eFACE_INDEX; + } + return true; +} + +static PX_FORCE_INLINE bool hasInitialOverlap(PxSweepHit& sweepHit, const PxVec3& unitDir, + const FloatVArg toi, + const Vec3VArg normal, const Vec3VArg closestA, + const PsTransformV& convexPose, + const bool isMtd, const bool impactPointOnTheOtherShape) +{ + sweepHit.flags = PxHitFlag::eDISTANCE | PxHitFlag::eNORMAL; + + const FloatV zero = FZero(); + if(FAllGrtrOrEq(zero, toi)) + { + //ML: initial overlap + if(isMtd) + { + sweepHit.flags |= PxHitFlag::ePOSITION; + const FloatV length = toi; + const Vec3V worldPointA = convexPose.transform(closestA); + const Vec3V worldNormal = V3Normalize(convexPose.rotate(normal)); + if(impactPointOnTheOtherShape) + { + const Vec3V destWorldPointA = V3NegScaleSub(worldNormal, length, worldPointA); + V3StoreU(worldNormal, sweepHit.normal); + V3StoreU(destWorldPointA, sweepHit.position); + } + else + { + const Vec3V destNormal = V3Neg(worldNormal); + V3StoreU(destNormal, sweepHit.normal); + V3StoreU(worldPointA, sweepHit.position); + } + FStore(length, &sweepHit.distance); + } + else + { + sweepHit.distance = 0.0f; + sweepHit.normal = -unitDir; + } + sweepHit.faceIndex = 0xffffffff; + return true; + } + return false; +} + +///////////////////////////////////////////////// sweepCapsule/Sphere ////////////////////////////////////////////////////// +bool sweepCapsule_SphereGeom(GU_CAPSULE_SWEEP_FUNC_PARAMS) +{ + PX_UNUSED(capsuleGeom_); + PX_UNUSED(capsulePose_); + + PX_ASSERT(geom.getType() == PxGeometryType::eSPHERE); + const PxSphereGeometry& sphereGeom = static_cast<const PxSphereGeometry&>(geom); + + const Sphere sphere(pose.p, sphereGeom.radius+inflation); + + if(!sweepSphereCapsule(sphere, lss, -unitDir, distance, sweepHit.distance, sweepHit.position, sweepHit.normal, hitFlags)) + return false; + + const bool isMtd = hitFlags & PxHitFlag::eMTD; + + if(isMtd) + { + sweepHit.flags = PxHitFlag::eDISTANCE | PxHitFlag::ePOSITION | PxHitFlag::eNORMAL; + + if(sweepHit.distance == 0.f) + { + //intialOverlap + if(lss.p0 == lss.p1) + { + //sphere + return computeSphere_SphereMTD(sphere, Sphere(lss.p0, lss.radius), sweepHit); + } + else + { + //capsule + return computeSphere_CapsuleMTD(sphere, lss, sweepHit); + } + } + } + else + { + if(sweepHit.distance!=0.0f) + sweepHit.flags = PxHitFlag::eDISTANCE | PxHitFlag::ePOSITION | PxHitFlag::eNORMAL; + else + sweepHit.flags = PxHitFlag::eDISTANCE | PxHitFlag::eNORMAL; + } + return true; +} + +bool sweepCapsule_PlaneGeom(GU_CAPSULE_SWEEP_FUNC_PARAMS) +{ + PX_UNUSED(capsuleGeom_); + PX_UNUSED(capsulePose_); + + PX_ASSERT(geom.getType() == PxGeometryType::ePLANE); + PX_UNUSED(geom); +// const PxPlaneGeometry& planeGeom = static_cast<const PxPlaneGeometry&>(geom); + + const PxPlane& worldPlane = getPlane(pose); + + const PxF32 capsuleRadius = lss.radius + inflation; + + PxU32 index = 0; + PxVec3 pts[2]; + + PxReal minDp = PX_MAX_REAL; + + sweepHit.faceIndex = 0xFFFFffff; // spec says face index is undefined for planes + + // Find extreme point on the capsule + // AP: removed if (lss.p0 == lss.p1 clause because it wasn't properly computing minDp) + pts[0] = lss.p0; + pts[1] = lss.p1; + for(PxU32 i=0; i<2; i++) + { + const PxReal dp = pts[i].dot(worldPlane.n); + if(dp<minDp) + { + minDp = dp; + index = i; + } + } + + const bool isMtd = hitFlags & PxHitFlag::eMTD; + + if(isMtd) + { + //initial overlap with the plane + if(minDp <= capsuleRadius - worldPlane.d) + { + sweepHit.flags = PxHitFlag::eDISTANCE|PxHitFlag::eNORMAL| PxHitFlag::ePOSITION; + return computePlane_CapsuleMTD(worldPlane, lss, sweepHit); + } + } + else + { + if(!(hitFlags & PxHitFlag::eASSUME_NO_INITIAL_OVERLAP)) + { + // test if the capsule initially overlaps with plane + if(minDp <= capsuleRadius - worldPlane.d) + { + sweepHit.flags = PxHitFlag::eDISTANCE|PxHitFlag::eNORMAL; + sweepHit.distance = 0.0f; + sweepHit.normal = -unitDir; + return true; + } + } + } + + const PxVec3 ptOnCapsule = pts[index] - worldPlane.n*capsuleRadius; + + // Raycast extreme vertex against plane + bool hitPlane = intersectRayPlane(ptOnCapsule, unitDir, worldPlane, sweepHit.distance, &sweepHit.position); + if(hitPlane && sweepHit.distance > 0 && sweepHit.distance <= distance) + { + sweepHit.normal = worldPlane.n; + sweepHit.flags = PxHitFlag::eDISTANCE | PxHitFlag::ePOSITION | PxHitFlag::eNORMAL; + return true; + } + return false; +} + +bool sweepCapsule_CapsuleGeom(GU_CAPSULE_SWEEP_FUNC_PARAMS) +{ + PX_UNUSED(capsuleGeom_); + PX_UNUSED(capsulePose_); + + PX_ASSERT(geom.getType() == PxGeometryType::eCAPSULE); + const PxCapsuleGeometry& capsuleGeom = static_cast<const PxCapsuleGeometry&>(geom); + + Capsule staticCapsule; + getCapsule(staticCapsule, capsuleGeom, pose); + staticCapsule.radius +=inflation; + + const bool isMtd = hitFlags & PxHitFlag::eMTD; + + PxU16 outFlags; + if(!sweepCapsuleCapsule(lss, staticCapsule, -unitDir, distance, sweepHit.distance, sweepHit.position, sweepHit.normal, hitFlags, outFlags)) + return false; + + sweepHit.flags = PxHitFlags(outFlags); + if(sweepHit.distance == 0.0f) + { + //initial overlap + if(isMtd) + { + sweepHit.flags |= PxHitFlag::ePOSITION; + return computeCapsule_CapsuleMTD(lss, staticCapsule, sweepHit); + } + } + return true; +} + +bool sweepCapsule_ConvexGeom(GU_CAPSULE_SWEEP_FUNC_PARAMS) +{ + PX_ASSERT(geom.getType() == PxGeometryType::eCONVEXMESH); + + using namespace Ps::aos; + + PX_ASSERT(geom.getType() == PxGeometryType::eCONVEXMESH); + const PxConvexMeshGeometry& convexGeom = static_cast<const PxConvexMeshGeometry&>(geom); + + ConvexMesh* convexMesh = static_cast<ConvexMesh*>(convexGeom.convexMesh); + ConvexHullData* hullData = &convexMesh->getHull(); + + const Vec3V zeroV = V3Zero(); + const FloatV zero = FZero(); + const FloatV dist = FLoad(distance); + const Vec3V worldDir = V3LoadU(unitDir); + + const PsTransformV capPose = loadTransformU(capsulePose_); + const PsTransformV convexPose = loadTransformU(pose); + + const PsMatTransformV aToB(convexPose.transformInv(capPose)); + + const FloatV capsuleHalfHeight = FLoad(capsuleGeom_.halfHeight); + const FloatV capsuleRadius = FLoad(lss.radius); + + const Vec3V vScale = V3LoadU_SafeReadW(convexGeom.scale.scale); // PT: safe because 'rotation' follows 'scale' in PxMeshScale + const QuatV vQuat = QuatVLoadU(&convexGeom.scale.rotation.x); + + CapsuleV capsule(aToB.p, aToB.rotate( V3Scale(V3UnitX(), capsuleHalfHeight)), capsuleRadius); + ConvexHullV convexHull(hullData, zeroV, vScale, vQuat, convexGeom.scale.isIdentity()); + + const Vec3V dir = convexPose.rotateInv(V3Neg(V3Scale(worldDir, dist))); + + bool isMtd = hitFlags & PxHitFlag::eMTD; + + FloatV toi; + Vec3V closestA, normal;//closestA and normal is in the local space of convex hull + LocalConvex<CapsuleV> convexA(capsule); + LocalConvex<ConvexHullV> convexB(convexHull); + const Vec3V initialSearchDir = V3Sub(capsule.getCenter(), convexHull.getCenter()); + if(!gjkRaycastPenetration< LocalConvex<CapsuleV>, LocalConvex<ConvexHullV> >(convexA, convexB, initialSearchDir, zero, zeroV, dir, toi, normal, closestA, lss.radius + inflation, isMtd)) + return false; + + if(hasInitialOverlap(sweepHit, unitDir, toi, normal, closestA, convexPose, isMtd, true)) + return true; + + sweepHit.flags |= PxHitFlag::ePOSITION; + const Vec3V worldPointA = convexPose.transform(closestA); + const FloatV length = FMul(dist, toi); + const Vec3V destNormal = V3Normalize(convexPose.rotate(normal)); + const Vec3V destWorldPointA = V3ScaleAdd(worldDir, length, worldPointA); + V3StoreU(destNormal, sweepHit.normal); + V3StoreU(destWorldPointA, sweepHit.position); + FStore(length, &sweepHit.distance); + + return computeFaceIndex(sweepHit, hitFlags, convexGeom, hullData, pose, unitDir); +} + +///////////////////////////////////////////////// sweepBox ////////////////////////////////////////////////////// + +bool sweepBox_PlaneGeom(GU_BOX_SWEEP_FUNC_PARAMS) +{ + PX_ASSERT(geom.getType() == PxGeometryType::ePLANE); + PX_UNUSED(geom); + PX_UNUSED(boxPose_); + PX_UNUSED(boxGeom_); + +// const PxPlaneGeometry& planeGeom = static_cast<const PxPlaneGeometry&>(geom); + + sweepHit.faceIndex = 0xFFFFffff; // spec says face index is undefined for planes + + PxPlane worldPlane = getPlane(pose); + worldPlane.d -=inflation; + + // Find extreme point on the box + PxVec3 boxPts[8]; + box.computeBoxPoints(boxPts); + PxU32 index = 0; + PxReal minDp = PX_MAX_REAL; + for(PxU32 i=0;i<8;i++) + { + const PxReal dp = boxPts[i].dot(worldPlane.n); + + if(dp<minDp) + { + minDp = dp; + index = i; + } + } + + bool isMtd = hitFlags & PxHitFlag::eMTD; + + if(isMtd) + { + // test if box initially overlap with plane + if(minDp <= -worldPlane.d) + { + sweepHit.flags = PxHitFlag::eDISTANCE | PxHitFlag::ePOSITION | PxHitFlag::eNORMAL; + //compute Mtd; + return computePlane_BoxMTD(worldPlane, box, sweepHit); + } + } + else + { + if(!(hitFlags & PxHitFlag::eASSUME_NO_INITIAL_OVERLAP)) + { + // test if box initially overlap with plane + if(minDp <= -worldPlane.d) + { + sweepHit.flags = PxHitFlag::eDISTANCE|PxHitFlag::eNORMAL; + sweepHit.distance = 0.0f; + sweepHit.normal = -unitDir; + return true; + } + } + } + + // Raycast extreme vertex against plane + bool hitPlane = intersectRayPlane(boxPts[index], unitDir, worldPlane, sweepHit.distance, &sweepHit.position); + if(hitPlane && sweepHit.distance > 0 && sweepHit.distance <= distance) + { + sweepHit.normal = worldPlane.n; + sweepHit.flags = PxHitFlag::eDISTANCE | PxHitFlag::ePOSITION | PxHitFlag::eNORMAL; + return true; + } + return false; +} + +bool sweepBox_ConvexGeom(GU_BOX_SWEEP_FUNC_PARAMS) +{ + PX_UNUSED(boxGeom_); + + using namespace Ps::aos; + PX_ASSERT(geom.getType() == PxGeometryType::eCONVEXMESH); + const PxConvexMeshGeometry& convexGeom = static_cast<const PxConvexMeshGeometry&>(geom); + + ConvexMesh* convexMesh = static_cast<ConvexMesh*>(convexGeom.convexMesh); + ConvexHullData* hullData = &convexMesh->getHull(); + + const Vec3V zeroV = V3Zero(); + const FloatV zero = FZero(); + + const PsTransformV boxPose = loadTransformU(boxPose_); + const PsTransformV convexPose = loadTransformU(pose); + + const PsMatTransformV aToB(convexPose.transformInv(boxPose)); + + const Vec3V boxExtents = V3LoadU(box.extents); + + const Vec3V vScale = V3LoadU_SafeReadW(convexGeom.scale.scale); // PT: safe because 'rotation' follows 'scale' in PxMeshScale + const QuatV vQuat = QuatVLoadU(&convexGeom.scale.rotation.x); + + ShrunkBoxV boxV(zeroV, boxExtents); + ConvexHullV convexHull(hullData, zeroV, vScale, vQuat, convexGeom.scale.isIdentity()); + + const Vec3V worldDir = V3LoadU(unitDir); + const FloatV dist = FLoad(distance); + const Vec3V dir = convexPose.rotateInv(V3Neg(V3Scale(worldDir, dist))); + + bool isMtd = hitFlags & PxHitFlag::eMTD; + + FloatV toi; + Vec3V closestA, normal; + RelativeConvex<BoxV> convexA(boxV, aToB); + LocalConvex<ConvexHullV> convexB(convexHull); + if(!gjkRaycastPenetration< RelativeConvex<BoxV>,LocalConvex<ConvexHullV> >(convexA, convexB, aToB.p, zero, zeroV, dir, toi, normal, closestA, inflation, isMtd)) + return false; + + if(hasInitialOverlap(sweepHit, unitDir, toi, normal, closestA, convexPose, isMtd, true)) + return true; + + sweepHit.flags |= PxHitFlag::ePOSITION; + const Vec3V destNormal = V3Normalize(convexPose.rotate(normal)); + const FloatV length = FMul(dist, toi); + const Vec3V worldPointA = convexPose.transform(closestA); + const Vec3V destWorldPointA = V3ScaleAdd(worldDir, length, worldPointA); + V3StoreU(destNormal, sweepHit.normal); + V3StoreU(destWorldPointA, sweepHit.position); + FStore(length, &sweepHit.distance); + + return computeFaceIndex(sweepHit, hitFlags, convexGeom, hullData, pose, unitDir); +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////////// + +bool Gu::sweepCapsuleTriangles(GU_SWEEP_TRIANGLES_FUNC_PARAMS(PxCapsuleGeometry)) +{ + Capsule capsule; + getCapsule(capsule, geom, pose); + capsule.radius +=inflation; + + // Compute swept box + Box capsuleBox; + computeBoxAroundCapsule(capsule, capsuleBox); + + BoxPadded sweptBounds; + computeSweptBox(sweptBounds, capsuleBox.extents, capsuleBox.center, capsuleBox.rot, unitDir, distance); + + PxVec3 triNormal; + return sweepCapsuleTriangles_Precise(nbTris, triangles, capsule, unitDir, distance, cachedIndex, hit, triNormal, hitFlags, doubleSided, &sweptBounds); +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////////// + +bool sweepConvex_SphereGeom(GU_CONVEX_SWEEP_FUNC_PARAMS) +{ + PX_ASSERT(geom.getType() == PxGeometryType::eSPHERE); + const PxSphereGeometry& sphereGeom = static_cast<const PxSphereGeometry&>(geom); + + ConvexMesh* convexMesh = static_cast<ConvexMesh*>(convexGeom.convexMesh); + ConvexHullData* hullData = &convexMesh->getHull(); + + const Vec3V zeroV = V3Zero(); + const FloatV zero= FZero(); + + const Vec3V vScale = V3LoadU_SafeReadW(convexGeom.scale.scale); // PT: safe because 'rotation' follows 'scale' in PxMeshScale + const QuatV vQuat = QuatVLoadU(&convexGeom.scale.rotation.x); + + const FloatV sphereRadius = FLoad(sphereGeom.radius); + + const PsTransformV sphereTransf = loadTransformU(pose); + const PsTransformV convexTransf = loadTransformU(convexPose); + + const PsMatTransformV aToB(convexTransf.transformInv(sphereTransf)); + + const Vec3V worldDir = V3LoadU(unitDir); + const FloatV dist = FLoad(distance); + const Vec3V dir = convexTransf.rotateInv(V3Scale(worldDir, dist)); + + ConvexHullV convexHull(hullData, zeroV, vScale, vQuat, convexGeom.scale.isIdentity()); + //CapsuleV capsule(zeroV, sphereRadius); + CapsuleV capsule(aToB.p, sphereRadius); + + const bool isMtd = hitFlags & PxHitFlag::eMTD; + + FloatV toi; + Vec3V closestA, normal; + LocalConvex<CapsuleV> convexA(capsule); + LocalConvex<ConvexHullV> convexB(convexHull); + const Vec3V initialSearchDir = V3Sub(capsule.getCenter(), convexHull.getCenter()); + if(!gjkRaycastPenetration< LocalConvex<CapsuleV>, LocalConvex<ConvexHullV> >(convexA, convexB, initialSearchDir, zero, zeroV, dir, toi, normal, closestA, sphereGeom.radius+inflation, isMtd)) + return false; + + if(hasInitialOverlap(sweepHit, unitDir, toi, normal, closestA, convexPose, isMtd, false)) + return true; + + sweepHit.flags |= PxHitFlag::ePOSITION; + const Vec3V destNormal = V3Neg(V3Normalize(convexTransf.rotate(normal))); + const FloatV length = FMul(dist, toi); + const Vec3V destWorldPointA = convexTransf.transform(closestA); + V3StoreU(destNormal, sweepHit.normal); + V3StoreU(destWorldPointA, sweepHit.position); + FStore(length, &sweepHit.distance); + sweepHit.faceIndex = 0xffffffff; + return true; +} + +bool sweepConvex_PlaneGeom(GU_CONVEX_SWEEP_FUNC_PARAMS) +{ + PX_ASSERT(geom.getType() == PxGeometryType::ePLANE); + PX_UNUSED(hitFlags); + PX_UNUSED(geom); + + ConvexMesh* convexMesh = static_cast<ConvexMesh*>(convexGeom.convexMesh); + ConvexHullData* hullData = &convexMesh->getHull(); + + sweepHit.faceIndex = 0xFFFFffff; // spec says face index is undefined for planes + + const PxVec3* PX_RESTRICT hullVertices = hullData->getHullVertices(); + PxU32 numHullVertices = hullData->mNbHullVertices; + + const bool isMtd = hitFlags & PxHitFlag::eMTD; + + const FastVertex2ShapeScaling convexScaling(convexGeom.scale); + + PxPlane plane = getPlane(pose); + plane.d -=inflation; + + sweepHit.distance = distance; + bool status = false; + bool initialOverlap = false; + while(numHullVertices--) + { + const PxVec3& vertex = *hullVertices++; + const PxVec3 worldPt = convexPose.transform(convexScaling * vertex); + float t; + PxVec3 pointOnPlane; + if(intersectRayPlane(worldPt, unitDir, plane, t, &pointOnPlane)) + { + if(plane.distance(worldPt) <= 0.0f) + { + initialOverlap = true; + break; + //// Convex touches plane + //sweepHit.distance = 0.0f; + //sweepHit.flags = PxHitFlag::eDISTANCE | PxHitFlag::eNORMAL; + //sweepHit.normal = -unitDir; + //return true; + } + + if(t > 0.0f && t <= sweepHit.distance) + { + sweepHit.distance = t; + sweepHit.flags = PxHitFlag::eDISTANCE | PxHitFlag::ePOSITION | PxHitFlag::eNORMAL; + sweepHit.position = pointOnPlane; + sweepHit.normal = plane.n; + status = true; + } + } + } + + if(initialOverlap) + { + if(isMtd) + { + sweepHit.flags = PxHitFlag::eDISTANCE | PxHitFlag::ePOSITION | PxHitFlag::eNORMAL; + return computePlane_ConvexMTD(plane, convexGeom, convexPose, sweepHit); + } + else + { + sweepHit.distance = 0.0f; + sweepHit.flags = PxHitFlag::eDISTANCE | PxHitFlag::eNORMAL; + sweepHit.normal = -unitDir; + return true; + } + } + return status; +} + +bool sweepConvex_CapsuleGeom(GU_CONVEX_SWEEP_FUNC_PARAMS) +{ + PX_ASSERT(geom.getType() == PxGeometryType::eCAPSULE); + const PxCapsuleGeometry& capsuleGeom = static_cast<const PxCapsuleGeometry&>(geom); + + Capsule capsule; + getCapsule(capsule, capsuleGeom, pose); + + // remove PxHitFlag::eFACE_INDEX, not neeeded to compute. + PxHitFlags tempHitFlags = hitFlags; + tempHitFlags &= ~PxHitFlag::eFACE_INDEX; + + if(!sweepCapsule_ConvexGeom(convexGeom, convexPose, capsuleGeom, pose, capsule, -unitDir, distance, sweepHit, tempHitFlags, inflation)) + return false; + + if(sweepHit.flags & PxHitFlag::ePOSITION) + sweepHit.position += unitDir * sweepHit.distance; + + sweepHit.normal = -sweepHit.normal; + sweepHit.faceIndex = 0xffffffff; + return true; +} + +bool sweepConvex_BoxGeom(GU_CONVEX_SWEEP_FUNC_PARAMS) +{ + PX_ASSERT(geom.getType() == PxGeometryType::eBOX); + const PxBoxGeometry& boxGeom = static_cast<const PxBoxGeometry&>(geom); + + Box box; + buildFrom(box, pose.p, boxGeom.halfExtents, pose.q); + + // remove PxHitFlag::eFACE_INDEX, not neeeded to compute. + PxHitFlags tempHitFlags = hitFlags; + tempHitFlags &= ~PxHitFlag::eFACE_INDEX; + + if(!sweepBox_ConvexGeom(convexGeom, convexPose, boxGeom, pose, box, -unitDir, distance, sweepHit, tempHitFlags, inflation)) + return false; + + if(sweepHit.flags & PxHitFlag::ePOSITION) + sweepHit.position += unitDir * sweepHit.distance; + + sweepHit.normal = -sweepHit.normal; + sweepHit.faceIndex = 0xffffffff; + return true; +} + +bool sweepConvex_ConvexGeom(GU_CONVEX_SWEEP_FUNC_PARAMS) +{ + using namespace Ps::aos; + PX_ASSERT(geom.getType() == PxGeometryType::eCONVEXMESH); + const PxConvexMeshGeometry& otherConvexGeom = static_cast<const PxConvexMeshGeometry&>(geom); + ConvexMesh& otherConvexMesh = *static_cast<ConvexMesh*>(otherConvexGeom.convexMesh); + + ConvexMesh* convexMesh = static_cast<ConvexMesh*>(convexGeom.convexMesh); + ConvexHullData* hullData = &convexMesh->getHull(); + + ConvexHullData* otherHullData = &otherConvexMesh.getHull(); + + const Vec3V zeroV = V3Zero(); + const FloatV zero = FZero(); + + const Vec3V otherVScale = V3LoadU_SafeReadW(otherConvexGeom.scale.scale); // PT: safe because 'rotation' follows 'scale' in PxMeshScale + const QuatV otherVQuat = QuatVLoadU(&otherConvexGeom.scale.rotation.x); + + const Vec3V vScale = V3LoadU_SafeReadW(convexGeom.scale.scale); // PT: safe because 'rotation' follows 'scale' in PxMeshScale + const QuatV vQuat = QuatVLoadU(&convexGeom.scale.rotation.x); + + const PsTransformV otherTransf = loadTransformU(pose); + const PsTransformV convexTransf = loadTransformU(convexPose); + + const Vec3V worldDir = V3LoadU(unitDir); + const FloatV dist = FLoad(distance); + const Vec3V dir = convexTransf.rotateInv(V3Scale(worldDir, dist)); + + const PsMatTransformV aToB(convexTransf.transformInv(otherTransf)); + + ConvexHullV otherConvexHull(otherHullData, zeroV, otherVScale, otherVQuat, otherConvexGeom.scale.isIdentity()); + ConvexHullV convexHull(hullData, zeroV, vScale, vQuat, convexGeom.scale.isIdentity()); + + const bool isMtd = hitFlags & PxHitFlag::eMTD; + + FloatV toi; + Vec3V closestA, normal; + RelativeConvex<ConvexHullV> convexA(otherConvexHull, aToB); + LocalConvex<ConvexHullV> convexB(convexHull); + if(!gjkRaycastPenetration< RelativeConvex<ConvexHullV>, LocalConvex<ConvexHullV> >(convexA, convexB, aToB.p, zero, zeroV, dir, toi, normal, closestA, inflation, isMtd)) + return false; + + if(hasInitialOverlap(sweepHit, unitDir, toi, normal, closestA, convexPose, isMtd, false)) + return true; + + sweepHit.flags |= PxHitFlag::ePOSITION; + const Vec3V worldPointA = convexTransf.transform(closestA); + const Vec3V destNormal = V3Neg(V3Normalize(convexTransf.rotate(normal))); + const FloatV length = FMul(dist, toi); + V3StoreU(destNormal, sweepHit.normal); + V3StoreU(worldPointA, sweepHit.position); + FStore(length, &sweepHit.distance); + + return computeFaceIndex(sweepHit, hitFlags, otherConvexGeom, otherHullData, pose, unitDir); +} |