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/GuOverlapTests.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/GuOverlapTests.cpp')
| -rw-r--r-- | PhysX_3.4/Source/GeomUtils/src/GuOverlapTests.cpp | 695 |
1 files changed, 695 insertions, 0 deletions
diff --git a/PhysX_3.4/Source/GeomUtils/src/GuOverlapTests.cpp b/PhysX_3.4/Source/GeomUtils/src/GuOverlapTests.cpp new file mode 100644 index 00000000..ebeca456 --- /dev/null +++ b/PhysX_3.4/Source/GeomUtils/src/GuOverlapTests.cpp @@ -0,0 +1,695 @@ +// 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 "GuOverlapTests.h" +#include "GuIntersectionBoxBox.h" +#include "GuIntersectionSphereBox.h" +#include "GuDistancePointSegment.h" +#include "GuDistanceSegmentBox.h" +#include "GuDistanceSegmentSegment.h" +#include "GuSphere.h" +#include "GuBoxConversion.h" +#include "GuInternal.h" +#include "GuVecCapsule.h" +#include "GuVecConvexHull.h" +#include "GuVecBox.h" +#include "GuConvexMesh.h" +#include "GuHillClimbing.h" +#include "GuGJK.h" + +using namespace physx; +using namespace Cm; +using namespace Gu; + +// PT: TODO: why don't we use ShapeData for overlaps? + +//returns the maximal vertex in shape space +// PT: this function should be removed. We already have 2 different project hull functions in PxcShapeConvex & GuGJKObjectSupport, this one looks like a weird mix of both! +static PxVec3 projectHull_( const ConvexHullData& hull, + float& minimum, float& maximum, + const PxVec3& localDir, // expected to be normalized + const PxMat33& vert2ShapeSkew) +{ + PX_ASSERT(localDir.isNormalized()); + + //use property that x|My == Mx|y for symmetric M to avoid having to transform vertices. + const PxVec3 vertexSpaceDir = vert2ShapeSkew * localDir; + + const PxVec3* Verts = hull.getHullVertices(); + const PxVec3* bestVert = NULL; + + if(!hull.mBigConvexRawData) // Brute-force, local space. Experiments show break-even point is around 32 verts. + { + PxU32 NbVerts = hull.mNbHullVertices; + float min_ = PX_MAX_F32; + float max_ = -PX_MAX_F32; + while(NbVerts--) + { + const float dp = (*Verts).dot(vertexSpaceDir); + min_ = physx::intrinsics::selectMin(min_, dp); + if(dp > max_) { max_ = dp; bestVert = Verts; } + + Verts++; + } + minimum = min_; + maximum = max_; + + PX_ASSERT(bestVert != NULL); + + return vert2ShapeSkew * *bestVert; + } + else //*/if(1) // This version is better for objects with a lot of vertices + { + const PxU32 Offset = ComputeCubemapNearestOffset(vertexSpaceDir, hull.mBigConvexRawData->mSubdiv); + PxU32 MinID = hull.mBigConvexRawData->mSamples[Offset]; + PxU32 MaxID = hull.mBigConvexRawData->getSamples2()[Offset]; + + localSearch(MinID, -vertexSpaceDir, Verts, hull.mBigConvexRawData); + localSearch(MaxID, vertexSpaceDir, Verts, hull.mBigConvexRawData); + + minimum = (Verts[MinID].dot(vertexSpaceDir)); + maximum = (Verts[MaxID].dot(vertexSpaceDir)); + + PX_ASSERT(maximum >= minimum); + + return vert2ShapeSkew * Verts[MaxID]; + } +} + +static bool intersectSphereConvex(const PxTransform& sphereTransform, float radius, const ConvexMesh& mesh, const PxMeshScale& meshScale, const PxTransform& convexGlobalPose, + PxVec3*) +{ + using namespace Ps::aos; + const Vec3V zeroV = V3Zero(); + const ConvexHullData* hullData = &mesh.getHull(); + const FloatV sphereRadius = FLoad(radius); + const Vec3V vScale = V3LoadU_SafeReadW(meshScale.scale); // PT: safe because 'rotation' follows 'scale' in PxMeshScale + const QuatV vQuat = QuatVLoadU(&meshScale.rotation.x); + + const PsMatTransformV aToB(convexGlobalPose.transformInv(sphereTransform)); + ConvexHullV convexHull(hullData, zeroV, vScale, vQuat, meshScale.isIdentity()); + CapsuleV capsule(aToB.p, sphereRadius); + + Vec3V contactA, contactB, normal; + FloatV dist; + LocalConvex<CapsuleV> convexA(capsule); + LocalConvex<ConvexHullV> convexB(convexHull); + const Vec3V initialSearchDir = V3Sub(capsule.getCenter(), convexHull.getCenter()); + + GjkStatus status = gjk(convexA, convexB, initialSearchDir, FZero(), contactA, contactB, normal, dist); + + return status == GJK_CONTACT; +} + +static bool intersectCapsuleConvex( const PxCapsuleGeometry& capsGeom, const PxTransform& capsGlobalPose, + const ConvexMesh& mesh, const PxMeshScale& meshScale, const PxTransform& convexGlobalPose, + PxVec3*) +{ + using namespace Ps::aos; + + const Vec3V zeroV = V3Zero(); + const ConvexHullData* hull = &mesh.getHull(); + + const FloatV capsuleHalfHeight = FLoad(capsGeom.halfHeight); + const FloatV capsuleRadius = FLoad(capsGeom.radius); + + const Vec3V vScale = V3LoadU_SafeReadW(meshScale.scale); // PT: safe because 'rotation' follows 'scale' in PxMeshScale + const QuatV vQuat = QuatVLoadU(&meshScale.rotation.x); + + const PsMatTransformV aToB(convexGlobalPose.transformInv(capsGlobalPose)); + + ConvexHullV convexHull(hull, zeroV, vScale, vQuat, meshScale.isIdentity()); + CapsuleV capsule(aToB.p, aToB.rotate(V3Scale(V3UnitX(), capsuleHalfHeight)), capsuleRadius); + + Vec3V contactA, contactB, normal; + FloatV dist; + LocalConvex<CapsuleV> convexA(capsule); + LocalConvex<ConvexHullV> convexB(convexHull); + const Vec3V initialSearchDir = V3Sub(capsule.getCenter(), convexHull.getCenter()); + + GjkStatus status = gjk(convexA, convexB, initialSearchDir, FZero(), contactA, contactB, normal, dist); + + return status == GJK_CONTACT; +} + +static bool intersectBoxConvex(const PxBoxGeometry& boxGeom, const PxTransform& boxGlobalPose, + const ConvexMesh& mesh, const PxMeshScale& meshScale, const PxTransform& convexGlobalPose, + PxVec3*) +{ + // AP: see archived non-GJK version in //sw/physx/dev/pterdiman/graveyard/contactConvexBox.cpp + using namespace Ps::aos; + const Vec3V zeroV = V3Zero(); + const ConvexHullData* hull = &mesh.getHull(); + + const Vec3V vScale = V3LoadU_SafeReadW(meshScale.scale); // PT: safe because 'rotation' follows 'scale' in PxMeshScale + const QuatV vQuat = QuatVLoadU(&meshScale.rotation.x); + const Vec3V boxExtents = V3LoadU(boxGeom.halfExtents); + const PsMatTransformV aToB(convexGlobalPose.transformInv(boxGlobalPose)); + + ConvexHullV convexHull(hull, zeroV, vScale, vQuat, meshScale.isIdentity()); + BoxV box(zeroV, boxExtents); + + Vec3V contactA, contactB, normal; + FloatV dist; + RelativeConvex<BoxV> convexA(box, aToB); + LocalConvex<ConvexHullV> convexB(convexHull); + + GjkStatus status = gjk(convexA, convexB, aToB.p, FZero(), contactA, contactB, normal, dist); + + //PX_PRINTF("BOX status = %i, overlap = %i, PxVec3(%f, %f, %f)\n", status, overlap, boxGlobalPose.p.x, boxGlobalPose.p.y, boxGlobalPose.p.z); + + return status == GJK_CONTACT; +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +static PX_FORCE_INLINE PxVec3* getCachedAxis(TriggerCache* cache) +{ + if(cache && cache->state==TRIGGER_OVERLAP) + return &cache->dir; + else + return NULL; +} + +static PX_FORCE_INLINE bool updateTriggerCache(bool overlap, TriggerCache* cache) +{ + if(cache) + { + if(overlap) + cache->state = TRIGGER_OVERLAP; + else + cache->state = TRIGGER_DISJOINT; + } + return overlap; +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +// Sphere-vs-shape + +static bool GeomOverlapCallback_SphereSphere(GU_OVERLAP_FUNC_PARAMS) +{ + PX_ASSERT(geom0.getType()==PxGeometryType::eSPHERE); + PX_ASSERT(geom1.getType()==PxGeometryType::eSPHERE); + PX_UNUSED(cache); + + const PxSphereGeometry& sphereGeom0 = static_cast<const PxSphereGeometry&>(geom0); + const PxSphereGeometry& sphereGeom1 = static_cast<const PxSphereGeometry&>(geom1); + + const PxVec3 delta = pose1.p - pose0.p; + const PxReal r = sphereGeom0.radius + sphereGeom1.radius; + return delta.magnitudeSquared() <= r*r; // PT: objects are defined as closed, so we return 'true' in case of equality +} + +static bool GeomOverlapCallback_SpherePlane(GU_OVERLAP_FUNC_PARAMS) +{ + PX_ASSERT(geom0.getType()==PxGeometryType::eSPHERE); + PX_ASSERT(geom1.getType()==PxGeometryType::ePLANE); + PX_UNUSED(cache); + PX_UNUSED(geom1); + + const PxSphereGeometry& sphereGeom = static_cast<const PxSphereGeometry&>(geom0); + + return getPlane(pose1).distance(pose0.p) <= sphereGeom.radius; // PT: objects are defined as closed, so we return 'true' in case of equality +} + +static bool GeomOverlapCallback_SphereCapsule(GU_OVERLAP_FUNC_PARAMS) +{ + PX_ASSERT(geom0.getType()==PxGeometryType::eSPHERE); + PX_ASSERT(geom1.getType()==PxGeometryType::eCAPSULE); + PX_UNUSED(cache); + + const PxSphereGeometry& sphereGeom = static_cast<const PxSphereGeometry&>(geom0); + const PxCapsuleGeometry& capsuleGeom = static_cast<const PxCapsuleGeometry&>(geom1); + + // PT: TODO: remove this useless conversion + const PxVec3 capsuleHalfHeightVector = getCapsuleHalfHeightVector(pose1, capsuleGeom); + const PxReal r = sphereGeom.radius + capsuleGeom.radius; + + return distancePointSegmentSquared(capsuleHalfHeightVector, -capsuleHalfHeightVector, pose0.p - pose1.p) <= r*r; // PT: objects are defined as closed, so we return 'true' in case of equality +} + +static bool GeomOverlapCallback_SphereBox(GU_OVERLAP_FUNC_PARAMS) +{ + PX_ASSERT(geom0.getType()==PxGeometryType::eSPHERE); + PX_ASSERT(geom1.getType()==PxGeometryType::eBOX); + PX_UNUSED(cache); + + const PxSphereGeometry& sphereGeom = static_cast<const PxSphereGeometry&>(geom0); + const PxBoxGeometry& boxGeom = static_cast<const PxBoxGeometry&>(geom1); + + // PT: TODO: remove this useless conversion + Box obb; + buildFrom(obb, pose1.p, boxGeom.halfExtents, pose1.q); + + return intersectSphereBox(Sphere(pose0.p, sphereGeom.radius), obb); +} + +static bool GeomOverlapCallback_SphereConvex(GU_OVERLAP_FUNC_PARAMS) +{ + PX_ASSERT(geom0.getType()==PxGeometryType::eSPHERE); + PX_ASSERT(geom1.getType()==PxGeometryType::eCONVEXMESH); + + const PxSphereGeometry& sphereGeom = static_cast<const PxSphereGeometry&>(geom0); + const PxConvexMeshGeometry& convexGeom = static_cast<const PxConvexMeshGeometry&>(geom1); + + ConvexMesh* cm = static_cast<ConvexMesh*>(convexGeom.convexMesh); + + PxVec3 cachedSepAxis; + PxVec3* tmp = getCachedAxis(cache); + if(tmp) + cachedSepAxis = *tmp; + else + cachedSepAxis = PxVec3(0,0,1.f); + + const bool overlap = intersectSphereConvex(pose0, sphereGeom.radius, + *cm, + convexGeom.scale, pose1, + &cachedSepAxis); + + if(cache && overlap) + cache->dir = cachedSepAxis; + + return updateTriggerCache(overlap, cache); +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +// Plane-vs-shape + +static bool GeomOverlapCallback_PlaneCapsule(GU_OVERLAP_FUNC_PARAMS) +{ + PX_ASSERT(geom0.getType()==PxGeometryType::ePLANE); + PX_ASSERT(geom1.getType()==PxGeometryType::eCAPSULE); + PX_UNUSED(cache); + PX_UNUSED(geom0); + +// const PxPlaneGeometry& planeGeom = static_cast<const PxPlaneGeometry&>(geom0); + const PxCapsuleGeometry& capsuleGeom = static_cast<const PxCapsuleGeometry&>(geom1); + + // PT: TODO: remove this useless conversion + Capsule capsule; + getCapsule(capsule, capsuleGeom, pose1); + + const PxPlane plane = getPlane(pose0); + + // We handle the capsule-plane collision with 2 sphere-plane collisions. + // Seems ok so far, since plane is infinite. + + if(plane.distance(capsule.p0) <= capsule.radius) // PT: objects are defined as closed, so we return 'true' in case of equality + return true; + + if(plane.distance(capsule.p1) <= capsule.radius) // PT: objects are defined as closed, so we return 'true' in case of equality + return true; + + return false; +} + +/*static bool intersectPlaneBox(const PxPlane& plane, const Box& box) +{ + PxVec3 pts[8]; + box.computeBoxPoints(pts); + + for(PxU32 i=0;i<8;i++) + { + if(plane.distance(pts[i]) <= 0.0f) // PT: objects are defined as closed, so we return 'true' in case of equality + return true; + } + return false; +}*/ + +static bool GeomOverlapCallback_PlaneBox(GU_OVERLAP_FUNC_PARAMS) +{ + PX_ASSERT(geom0.getType()==PxGeometryType::ePLANE); + PX_ASSERT(geom1.getType()==PxGeometryType::eBOX); + PX_UNUSED(cache); + PX_UNUSED(geom0); + +// const PxPlaneGeometry& planeGeom = static_cast<const PxPlaneGeometry&>(geom0); + const PxBoxGeometry& boxGeom = static_cast<const PxBoxGeometry&>(geom1); + + // I currently use the same code as for contact generation but maybe we could do something faster (in theory testing + // only 2 pts is enough). + + const Matrix34 absPose(pose1); + const PxPlane worldPlane = getPlane(pose0); + + for(int vx=-1; vx<=1; vx+=2) + for(int vy=-1; vy<=1; vy+=2) + for(int vz=-1; vz<=1; vz+=2) + { + const PxVec3 v = absPose.transform(PxVec3(PxReal(vx),PxReal(vy),PxReal(vz)).multiply(boxGeom.halfExtents)); + + if(worldPlane.distance(v) <= 0.0f) // PT: objects are defined as closed, so we return 'true' in case of equality + return true; + } + return false; +} + +static bool GeomOverlapCallback_PlaneConvex(GU_OVERLAP_FUNC_PARAMS) +{ + PX_ASSERT(geom0.getType()==PxGeometryType::ePLANE); + PX_ASSERT(geom1.getType()==PxGeometryType::eCONVEXMESH); + PX_UNUSED(cache); + PX_UNUSED(geom0); + +// const PxPlaneGeometry& planeGeom = static_cast<const PxPlaneGeometry&>(geom0); + const PxConvexMeshGeometry& convexGeom = static_cast<const PxConvexMeshGeometry&>(geom1); + + ConvexMesh* cm = static_cast<ConvexMesh*>(convexGeom.convexMesh); + + //find plane normal in shape space of convex: + const PxTransform plane2convex = pose1.getInverse().transform(pose0); + + const PxPlane shapeSpacePlane = getPlane(plane2convex); + + PxReal minimum, maximum; + projectHull_(cm->getHull(), minimum, maximum, shapeSpacePlane.n, convexGeom.scale.toMat33()); + + return (minimum <= -shapeSpacePlane.d); +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +// Capsule-vs-shape + +static bool GeomOverlapCallback_CapsuleCapsule(GU_OVERLAP_FUNC_PARAMS) +{ + PX_ASSERT(geom0.getType()==PxGeometryType::eCAPSULE); + PX_ASSERT(geom1.getType()==PxGeometryType::eCAPSULE); + PX_UNUSED(cache); + + const PxCapsuleGeometry& capsuleGeom0 = static_cast<const PxCapsuleGeometry&>(geom0); + const PxCapsuleGeometry& capsuleGeom1 = static_cast<const PxCapsuleGeometry&>(geom1); + + // PT: move computation to local space for improved accuracy + const PxVec3 delta = pose1.p - pose0.p; + + // PT: TODO: remove this useless conversion + const PxVec3 capsuleHalfHeightVector0 = getCapsuleHalfHeightVector(pose0, capsuleGeom0); + const PxVec3 capsuleHalfHeightVector1 = getCapsuleHalfHeightVector(pose1, capsuleGeom1); + + const PxReal squareDist = distanceSegmentSegmentSquared(-capsuleHalfHeightVector0, capsuleHalfHeightVector0*2.0f, + delta-capsuleHalfHeightVector1, capsuleHalfHeightVector1*2.0f); + const PxReal r = capsuleGeom0.radius + capsuleGeom1.radius; + return squareDist <= r*r; // PT: objects are defined as closed, so we return 'true' in case of equality +} + +static bool GeomOverlapCallback_CapsuleBox(GU_OVERLAP_FUNC_PARAMS) +{ + PX_ASSERT(geom0.getType()==PxGeometryType::eCAPSULE); + PX_ASSERT(geom1.getType()==PxGeometryType::eBOX); + PX_UNUSED(cache); + + const PxCapsuleGeometry& capsuleGeom = static_cast<const PxCapsuleGeometry&>(geom0); + const PxBoxGeometry& boxGeom = static_cast<const PxBoxGeometry&>(geom1); + + // PT: move computation to local space for improved accuracy + const PxVec3 delta = pose1.p - pose0.p; + + // PT: TODO: remove this useless conversion + const PxVec3 capsuleHalfHeightVector = getCapsuleHalfHeightVector(pose0, capsuleGeom); + + // PT: TODO: remove this useless conversion + const PxMat33 obbRot(pose1.q); + + // PT: objects are defined as closed, so we return 'true' in case of equality + return distanceSegmentBoxSquared(capsuleHalfHeightVector, -capsuleHalfHeightVector, delta, boxGeom.halfExtents, obbRot) <= capsuleGeom.radius*capsuleGeom.radius; +} + +static bool GeomOverlapCallback_CapsuleConvex(GU_OVERLAP_FUNC_PARAMS) +{ + PX_ASSERT(geom0.getType()==PxGeometryType::eCAPSULE); + PX_ASSERT(geom1.getType()==PxGeometryType::eCONVEXMESH); + + const PxCapsuleGeometry& capsuleGeom = static_cast<const PxCapsuleGeometry&>(geom0); + const PxConvexMeshGeometry& convexGeom = static_cast<const PxConvexMeshGeometry&>(geom1); + + ConvexMesh* cm = static_cast<ConvexMesh*>(convexGeom.convexMesh); + + + PxVec3 cachedSepAxis; + PxVec3* tmp = getCachedAxis(cache); + if(tmp) + cachedSepAxis = *tmp; + else + cachedSepAxis = PxVec3(0,0,1.0f); + + const bool overlap = intersectCapsuleConvex(capsuleGeom, pose0, *cm, convexGeom.scale, pose1, &cachedSepAxis); + + if(cache && overlap) + cache->dir = cachedSepAxis; + + return updateTriggerCache(overlap, cache); +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +// Box-vs-shape + +static bool GeomOverlapCallback_BoxBox(GU_OVERLAP_FUNC_PARAMS) +{ + PX_ASSERT(geom0.getType()==PxGeometryType::eBOX); + PX_ASSERT(geom1.getType()==PxGeometryType::eBOX); + PX_UNUSED(cache); + + const PxBoxGeometry& boxGeom0 = static_cast<const PxBoxGeometry&>(geom0); + const PxBoxGeometry& boxGeom1 = static_cast<const PxBoxGeometry&>(geom1); + + // PT: TODO: remove this useless conversion + return intersectOBBOBB( boxGeom0.halfExtents, pose0.p, PxMat33Padded(pose0.q), + boxGeom1.halfExtents, pose1.p, PxMat33Padded(pose1.q), true); +} + +static bool GeomOverlapCallback_BoxConvex(GU_OVERLAP_FUNC_PARAMS) +{ + PX_ASSERT(geom0.getType()==PxGeometryType::eBOX); + PX_ASSERT(geom1.getType()==PxGeometryType::eCONVEXMESH); + + const PxBoxGeometry& boxGeom = static_cast<const PxBoxGeometry&>(geom0); + const PxConvexMeshGeometry& convexGeom = static_cast<const PxConvexMeshGeometry&>(geom1); + + ConvexMesh* cm = static_cast<ConvexMesh*>(convexGeom.convexMesh); + + PxVec3 cachedSepAxis; + PxVec3* tmp = getCachedAxis(cache); + if(tmp) + cachedSepAxis = *tmp; + else + cachedSepAxis = PxVec3(0.0f, 0.0f, 1.0f); + + const bool overlap = intersectBoxConvex(boxGeom, pose0, *cm, convexGeom.scale, pose1, &cachedSepAxis); + + if(cache && overlap) + cache->dir = cachedSepAxis; + + return updateTriggerCache(overlap, cache); +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +// Convex-vs-shape +static bool GeomOverlapCallback_ConvexConvex(GU_OVERLAP_FUNC_PARAMS) +{ + using namespace Ps::aos; + PX_ASSERT(geom0.getType()==PxGeometryType::eCONVEXMESH); + PX_ASSERT(geom1.getType()==PxGeometryType::eCONVEXMESH); + + const Vec3V zeroV = V3Zero(); + const PxConvexMeshGeometry& convexGeom0 = static_cast<const PxConvexMeshGeometry&>(geom0); + const PxConvexMeshGeometry& convexGeom1 = static_cast<const PxConvexMeshGeometry&>(geom1); + const ConvexMesh* cm0 = static_cast<ConvexMesh*>(convexGeom0.convexMesh); + const ConvexMesh* cm1 = static_cast<ConvexMesh*>(convexGeom1.convexMesh); + + bool overlap; + { + const ConvexHullData* hullData0 = &cm0->getHull(); + const ConvexHullData* hullData1 = &cm1->getHull(); + + const Vec3V vScale0 = V3LoadU_SafeReadW(convexGeom0.scale.scale); // PT: safe because 'rotation' follows 'scale' in PxMeshScale + const QuatV vQuat0 = QuatVLoadU(&convexGeom0.scale.rotation.x); + const Vec3V vScale1 = V3LoadU_SafeReadW(convexGeom1.scale.scale); // PT: safe because 'rotation' follows 'scale' in PxMeshScale + const QuatV vQuat1 = QuatVLoadU(&convexGeom1.scale.rotation.x); + + const QuatV q0 = QuatVLoadU(&pose0.q.x); + const Vec3V p0 = V3LoadU(&pose0.p.x); + + const QuatV q1 = QuatVLoadU(&pose1.q.x); + const Vec3V p1 = V3LoadU(&pose1.p.x); + + const PsTransformV transf0(p0, q0); + const PsTransformV transf1(p1, q1); + + const PsMatTransformV aToB(transf1.transformInv(transf0)); + + ConvexHullV convexHull0(hullData0, zeroV, vScale0, vQuat0, convexGeom0.scale.isIdentity()); + ConvexHullV convexHull1(hullData1, zeroV, vScale1, vQuat1, convexGeom1.scale.isIdentity()); + + Vec3V contactA, contactB, normal; + FloatV dist; + RelativeConvex<ConvexHullV> convexA(convexHull0, aToB); + LocalConvex<ConvexHullV> convexB(convexHull1); + + GjkStatus status = gjk(convexA, convexB, aToB.p, FZero(), contactA, contactB, normal, dist); + overlap = (status == GJK_CONTACT); + } + + return updateTriggerCache(overlap, cache); +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +static bool GeomOverlapCallback_NotSupported(GU_OVERLAP_FUNC_PARAMS) +{ + PX_ALWAYS_ASSERT_MESSAGE("NOT SUPPORTED"); + PX_UNUSED(cache); + PX_UNUSED(pose0); + PX_UNUSED(pose1); + PX_UNUSED(geom0); + PX_UNUSED(geom1); + return false; +} + +static bool GeomOverlapCallback_HeightfieldUnregistered(GU_OVERLAP_FUNC_PARAMS) +{ + PX_UNUSED(cache); + PX_UNUSED(geom0); + PX_UNUSED(geom1); + PX_UNUSED(pose0); + PX_UNUSED(pose1); + Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Height Field Overlap test called with height fields unregistered "); + return false; +} + +bool GeomOverlapCallback_SphereMesh (GU_OVERLAP_FUNC_PARAMS); +bool GeomOverlapCallback_CapsuleMesh (GU_OVERLAP_FUNC_PARAMS); +bool GeomOverlapCallback_BoxMesh (GU_OVERLAP_FUNC_PARAMS); +bool GeomOverlapCallback_ConvexMesh (GU_OVERLAP_FUNC_PARAMS); +bool GeomOverlapCallback_SphereHeightfield (GU_OVERLAP_FUNC_PARAMS); +bool GeomOverlapCallback_CapsuleHeightfield (GU_OVERLAP_FUNC_PARAMS); +bool GeomOverlapCallback_BoxHeightfield (GU_OVERLAP_FUNC_PARAMS); +bool GeomOverlapCallback_ConvexHeightfield (GU_OVERLAP_FUNC_PARAMS); + +GeomOverlapTable gGeomOverlapMethodTable[] = +{ + //PxGeometryType::eSPHERE + { + GeomOverlapCallback_SphereSphere, //PxGeometryType::eSPHERE + GeomOverlapCallback_SpherePlane, //PxGeometryType::ePLANE + GeomOverlapCallback_SphereCapsule, //PxGeometryType::eCAPSULE + GeomOverlapCallback_SphereBox, //PxGeometryType::eBOX + GeomOverlapCallback_SphereConvex, //PxGeometryType::eCONVEXMESH + GeomOverlapCallback_SphereMesh, //PxGeometryType::eTRIANGLEMESH + GeomOverlapCallback_HeightfieldUnregistered, //PxGeometryType::eHEIGHTFIELD + }, + + //PxGeometryType::ePLANE + { + 0, //PxGeometryType::eSPHERE + GeomOverlapCallback_NotSupported, //PxGeometryType::ePLANE + GeomOverlapCallback_PlaneCapsule, //PxGeometryType::eCAPSULE + GeomOverlapCallback_PlaneBox, //PxGeometryType::eBOX + GeomOverlapCallback_PlaneConvex, //PxGeometryType::eCONVEXMESH + GeomOverlapCallback_NotSupported, //PxGeometryType::eTRIANGLEMESH + GeomOverlapCallback_NotSupported, //PxGeometryType::eHEIGHTFIELD + }, + + //PxGeometryType::eCAPSULE + { + 0, //PxGeometryType::eSPHERE + 0, //PxGeometryType::ePLANE + GeomOverlapCallback_CapsuleCapsule, //PxGeometryType::eCAPSULE + GeomOverlapCallback_CapsuleBox, //PxGeometryType::eBOX + GeomOverlapCallback_CapsuleConvex, //PxGeometryType::eCONVEXMESH + GeomOverlapCallback_CapsuleMesh, //PxGeometryType::eTRIANGLEMESH + GeomOverlapCallback_HeightfieldUnregistered, //PxGeometryType::eHEIGHTFIELD + }, + + //PxGeometryType::eBOX + { + 0, //PxGeometryType::eSPHERE + 0, //PxGeometryType::ePLANE + 0, //PxGeometryType::eCAPSULE + GeomOverlapCallback_BoxBox, //PxGeometryType::eBOX + GeomOverlapCallback_BoxConvex, //PxGeometryType::eCONVEXMESH + GeomOverlapCallback_BoxMesh, //PxGeometryType::eTRIANGLEMESH + GeomOverlapCallback_HeightfieldUnregistered, //PxGeometryType::eHEIGHTFIELD + }, + + //PxGeometryType::eCONVEXMESH + { + 0, //PxGeometryType::eSPHERE + 0, //PxGeometryType::ePLANE + 0, //PxGeometryType::eCAPSULE + 0, //PxGeometryType::eBOX + GeomOverlapCallback_ConvexConvex, //PxGeometryType::eCONVEXMESH + GeomOverlapCallback_ConvexMesh, //PxGeometryType::eTRIANGLEMESH //not used: mesh always uses swept method for midphase. + GeomOverlapCallback_HeightfieldUnregistered, //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this + }, + + //PxGeometryType::eTRIANGLEMESH + { + 0, //PxGeometryType::eSPHERE + 0, //PxGeometryType::ePLANE + 0, //PxGeometryType::eCAPSULE + 0, //PxGeometryType::eBOX + 0, //PxGeometryType::eCONVEXMESH + GeomOverlapCallback_NotSupported, //PxGeometryType::eTRIANGLEMESH + GeomOverlapCallback_NotSupported, //PxGeometryType::eHEIGHTFIELD + }, + + //PxGeometryType::eHEIGHTFIELD + { + 0, //PxGeometryType::eSPHERE + 0, //PxGeometryType::ePLANE + 0, //PxGeometryType::eCAPSULE + 0, //PxGeometryType::eBOX + 0, //PxGeometryType::eCONVEXMESH + 0, //PxGeometryType::eTRIANGLEMESH + GeomOverlapCallback_NotSupported, //PxGeometryType::eHEIGHTFIELD + }, +}; + +const GeomOverlapTable* Gu::getOverlapFuncTable() +{ + return gGeomOverlapMethodTable; +} + +void registerHeightFields_Raycasts(); +void registerHeightFields_Sweeps(); +void Gu::registerHeightFields() +{ + registerHeightFields_Raycasts(); + registerHeightFields_Sweeps(); + + gGeomOverlapMethodTable[PxGeometryType::eSPHERE][PxGeometryType::eHEIGHTFIELD] = GeomOverlapCallback_SphereHeightfield; + gGeomOverlapMethodTable[PxGeometryType::eCAPSULE][PxGeometryType::eHEIGHTFIELD] = GeomOverlapCallback_CapsuleHeightfield; + gGeomOverlapMethodTable[PxGeometryType::eBOX][PxGeometryType::eHEIGHTFIELD] = GeomOverlapCallback_BoxHeightfield; + gGeomOverlapMethodTable[PxGeometryType::eCONVEXMESH][PxGeometryType::eHEIGHTFIELD] = GeomOverlapCallback_ConvexHeightfield; +} |