aboutsummaryrefslogtreecommitdiff
path: root/PhysX_3.4/Source/GeomUtils/src/ccd
diff options
context:
space:
mode:
authorgit perforce import user <a@b>2016-10-25 12:29:14 -0600
committerSheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees>2016-10-25 18:56:37 -0500
commit3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch)
treefa6485c169e50d7415a651bf838f5bcd0fd3bfbd /PhysX_3.4/Source/GeomUtils/src/ccd
downloadphysx-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/ccd')
-rw-r--r--PhysX_3.4/Source/GeomUtils/src/ccd/GuCCDSweepConvexMesh.cpp733
-rw-r--r--PhysX_3.4/Source/GeomUtils/src/ccd/GuCCDSweepConvexMesh.h178
-rw-r--r--PhysX_3.4/Source/GeomUtils/src/ccd/GuCCDSweepPrimitives.cpp290
3 files changed, 1201 insertions, 0 deletions
diff --git a/PhysX_3.4/Source/GeomUtils/src/ccd/GuCCDSweepConvexMesh.cpp b/PhysX_3.4/Source/GeomUtils/src/ccd/GuCCDSweepConvexMesh.cpp
new file mode 100644
index 00000000..3d3d9e36
--- /dev/null
+++ b/PhysX_3.4/Source/GeomUtils/src/ccd/GuCCDSweepConvexMesh.cpp
@@ -0,0 +1,733 @@
+// 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 "Ps.h"
+#include "GuVecCapsule.h"
+#include "GuVecBox.h"
+#include "GuVecConvexHull.h"
+#include "GuVecTriangle.h"
+#include "GuVecShrunkConvexHull.h"
+#include "GuVecShrunkBox.h"
+#include "GuGJKRaycast.h"
+#include "GuCCDSweepConvexMesh.h"
+#include "GuHeightFieldUtil.h"
+#include "PsInlineArray.h"
+#include "GuEntityReport.h"
+#include "PxContact.h"
+#include "GuDistancePointTriangle.h"
+#include "GuBox.h"
+#include "GuInternal.h"
+#include "GuBoxConversion.h"
+#include "GuConvexUtilsInternal.h"
+#include "GuMidphaseInterface.h"
+#include "GuTriangleVertexPointers.h"
+
+
+
+namespace physx
+{
+namespace Gu
+{
+
+PxReal SweepShapeTriangle(GU_TRIANGLE_SWEEP_METHOD_ARGS);
+
+using namespace Ps::aos;
+
+namespace
+{
+struct AccumCallback: public MeshHitCallback<PxRaycastHit>
+{
+ PX_NOCOPY(AccumCallback)
+ public:
+
+ Ps::InlineArray<PxU32, 64>& mResult;
+ AccumCallback(Ps::InlineArray<PxU32, 64>& result)
+ : MeshHitCallback<PxRaycastHit>(CallbackMode::eMULTIPLE),
+ mResult(result)
+ {
+ }
+
+ virtual PxAgain processHit( // all reported coords are in mesh local space including hit.position
+ const PxRaycastHit& hit, const PxVec3&, const PxVec3&, const PxVec3&, PxReal&, const PxU32*)
+ {
+ mResult.pushBack(hit.faceIndex);
+ return true;
+ }
+};
+
+// PT: TODO: refactor with MidPhaseQueryLocalReport
+struct EntityReportContainerCallback : public EntityReport<PxU32>
+{
+ Ps::InlineArray<PxU32, 64>& container;
+ EntityReportContainerCallback(Ps::InlineArray<PxU32,64>& container_) : container(container_)
+ {
+ container.forceSize_Unsafe(0);
+ }
+ virtual ~EntityReportContainerCallback() {}
+
+ virtual bool onEvent(PxU32 nb, PxU32* indices)
+ {
+ for(PxU32 i=0; i<nb; i++)
+ container.pushBack(indices[i]);
+ return true;
+ }
+private:
+ EntityReportContainerCallback& operator=(const EntityReportContainerCallback&);
+};
+
+class ConvexTriangles
+{
+public:
+ ConvexTriangles(const PxTriangleMeshGeometryLL& shapeMesh,
+ const Cm::FastVertex2ShapeScaling& skew, // object is not copied, beware!
+ const PxU32* trigsInGroup,
+ PxU32 numTrigsInGroup,
+ PxU32* trigIndexDestBuffer);//trigIndexDestBuffer should be at least numTrigsInGroup long.
+
+ void getBounds(PxBounds3& bounds, const physx::PxTransform& transform) const;
+
+ //non-virtuals:
+ PX_FORCE_INLINE const TriangleMesh* getMeshData() const { return shapeMesh.meshData; }
+
+ PxVec3 getPolygonNormal(PxU32 index) const;
+
+
+private:
+ ConvexTriangles& operator=(const ConvexTriangles&);
+ void calcCenterAndBounds(const physx::PxTransform& transform) const;
+
+ const PxTriangleMeshGeometryLL& shapeMesh;
+ const Cm::FastVertex2ShapeScaling& mVertex2ShapeSkew;
+ const PxU32* trigsInGroup;
+ PxU32 numTrigsInGroup;
+ PxU32* trigIndexDestBuffer;
+ mutable HullPolygonData selectedPolygon;
+
+ mutable PxBounds3 bounds;
+ mutable PxVec3 mCenter; //average of vertices rather than center of bounds!
+ mutable bool haveCenterAndBounds;
+};
+
+ConvexTriangles::ConvexTriangles(const PxTriangleMeshGeometryLL& md,
+ const Cm::FastVertex2ShapeScaling& skew,
+ const PxU32* tg, PxU32 ntg, PxU32 * tb)
+: shapeMesh(md), mVertex2ShapeSkew(skew), trigsInGroup(tg), numTrigsInGroup(ntg), trigIndexDestBuffer(tb), bounds(PxBounds3::empty()), mCenter(0.0f), haveCenterAndBounds(false)
+{
+}
+
+
+void ConvexTriangles::getBounds(PxBounds3& b, const physx::PxTransform& transform) const
+{
+ calcCenterAndBounds(transform);
+ b = bounds;
+}
+
+void ConvexTriangles::calcCenterAndBounds(const physx::PxTransform& transform) const //computes bounds in shape space
+{
+ //NOTE: we have code that does this in a loop inside PxcContactHullMeshPenetrationFallback -- a relatively expensive weighted average of the faces.
+ //see if we really need to be that expensive!
+
+ //shound be done in ctor:
+ PX_ASSERT(bounds.isEmpty());
+ PX_ASSERT(mCenter.isZero());
+
+ for (PxU32 i = 0; i < numTrigsInGroup; i++)
+ {
+ const PxU32 triangleIndex = trigsInGroup[i];
+ PxVec3 v0l, v1l, v2l;
+ TriangleVertexPointers::getTriangleVerts(getMeshData(), triangleIndex, v0l, v1l, v2l);
+
+ //TODO: this does a lot of redundant work because shared vertices get tested multiple times.
+ //Still, its not a lot of work so any overhead of optimized data access may not be worth it.
+
+ //gotta take bounds in shape space because building it in vertex space and transforming it out would skew it.
+
+ //unrolled loop of 3
+ const PxVec3 v0 = transform.transform(mVertex2ShapeSkew * v0l);
+ mCenter += v0;
+ bounds.include(v0);
+
+ const PxVec3 v1 = transform.transform(mVertex2ShapeSkew * v1l);
+ mCenter += v1;
+ bounds.include(v1);
+
+ const PxVec3 v2 = transform.transform(mVertex2ShapeSkew * v2l);
+ mCenter += v2;
+ bounds.include(v2);
+ }
+
+ mCenter *= 1.0f / (numTrigsInGroup * 3);
+ haveCenterAndBounds = true;
+}
+
+PxVec3 ConvexTriangles::getPolygonNormal(PxU32 index) const
+{
+ PX_ASSERT(index < numTrigsInGroup);
+ const PxU32 triangleIndex = trigsInGroup[index];
+ PxVec3 v0l, v1l, v2l;
+ TriangleVertexPointers::getTriangleVerts(getMeshData(), triangleIndex, v0l, v1l, v2l);
+ const bool flipNormal = mVertex2ShapeSkew.flipsNormal();
+ const PxVec3 t0 = mVertex2ShapeSkew * v0l;
+ const PxVec3 t1 = mVertex2ShapeSkew * (flipNormal ? v2l : v1l);
+ const PxVec3 t2 = mVertex2ShapeSkew * (flipNormal ? v1l : v2l);
+ const PxVec3 v0 = t0 - t1;
+ const PxVec3 v1 = t0 - t2;
+ const PxVec3 nor = v0.cross(v1);
+ return nor.getNormalized();
+}
+
+}
+
+
+
+PxReal SweepAnyShapeHeightfield(GU_SWEEP_METHOD_ARGS)
+{
+ PX_UNUSED(toiEstimate);
+ HeightFieldUtil hfUtil(shape1.mGeometry->get<const physx::PxHeightFieldGeometryLL>());
+
+ Ps::InlineArray<PxU32,64> tempContainer;
+
+ EntityReportContainerCallback callback(tempContainer);
+
+ PxVec3 trA = transform0.p - lastTm0.p;
+ PxVec3 trB = transform1.p - lastTm1.p;
+
+ PxVec3 relTr = trA - trB;
+ PxVec3 halfRelTr = relTr * 0.5f;
+
+ const PxVec3 ext = shape0.mExtents + halfRelTr.abs() + PxVec3(restDistance);
+ const PxVec3 cent = shape0.mCenter + halfRelTr;
+
+ PxBounds3 bounds0(cent - ext, cent + ext);
+
+ hfUtil.overlapAABBTriangles(transform1, bounds0, GuHfQueryFlags::eWORLD_SPACE, &callback);
+
+ Ps::Array<PxU32> orderedContainer(tempContainer.size());
+
+ Ps::Array<PxU32> distanceEntries(tempContainer.size());
+
+ PxU32* orderedList = orderedContainer.begin();
+ PxF32* distances = reinterpret_cast<PxF32*>(distanceEntries.begin());
+
+ PxVec3 origin = shape0.mCenter;
+ PxVec3 extent = shape0.mExtents + PxVec3(restDistance);
+
+ PxReal minTOI = PX_MAX_REAL;
+
+ PxU32 numTrigs = tempContainer.size();
+ PxU32* trianglesIndices = tempContainer.begin();
+
+ PxU32 count = 0;
+ for(PxU32 a = 0; a < numTrigs; ++a)
+ {
+ PxTriangle tri;
+ hfUtil.getTriangle(shape1.mPrevTransform, tri, 0, 0, trianglesIndices[a], true, true);
+
+ PxVec3 resultNormal = -(tri.verts[1]-tri.verts[0]).cross(tri.verts[2]-tri.verts[0]);
+ resultNormal.normalize();
+
+ if(relTr.dot(resultNormal) >= fastMovingThreshold)
+ {
+
+ PxBounds3 bounds;
+ bounds.setEmpty();
+ bounds.include(tri.verts[0]);
+ bounds.include(tri.verts[1]);
+ bounds.include(tri.verts[2]);
+
+ PxF32 toi = sweepAABBAABB(origin, extent * 1.1f, bounds.getCenter(), (bounds.getExtents() + PxVec3(0.01f, 0.01f, 0.01f)) * 1.1f, trA, trB);
+
+ PxU32 index = 0;
+ if(toi <= 1.f)
+ {
+ for(PxU32 b = count; b > 0; --b)
+ {
+ if(distances[b-1] <= toi)
+ {
+ //shuffle down and swap
+ index = b;
+ break;
+ }
+ PX_ASSERT(b > 0);
+ PX_ASSERT(b < numTrigs);
+ distances[b] = distances[b-1];
+ orderedList[b] = orderedList[b-1];
+ }
+ PX_ASSERT(index < numTrigs);
+ orderedList[index] = trianglesIndices[a];
+ distances[index] = toi;
+ count++;
+ }
+ }
+ }
+
+
+
+ worldNormal = PxVec3(PxReal(0));
+ worldPoint = PxVec3(PxReal(0));
+ Cm::FastVertex2ShapeScaling idScale;
+ PxU32 ccdFaceIndex = PXC_CONTACT_NO_FACE_INDEX;
+
+ PxVec3 sphereCenter(shape0.mPrevTransform.p);
+ PxF32 inSphereRadius = shape0.mFastMovingThreshold;
+ PxF32 inRadSq = inSphereRadius * inSphereRadius;
+
+
+ PxVec3 sphereCenterInTr1 = transform1.transformInv(sphereCenter);
+ PxVec3 sphereCenterInTr1T0 = transform1.transformInv(lastTm0.p);
+
+ PxVec3 tempWorldNormal(0.f), tempWorldPoint(0.f);
+
+ for (PxU32 ti = 0; ti < count; ti++)
+ {
+ PxTriangle tri;
+ hfUtil.getTriangle(lastTm1, tri, 0, 0, orderedList[ti], false, false);
+
+ PxVec3 resultNormal, resultPoint;
+
+ TriangleV triangle(V3LoadU(tri.verts[0]), V3LoadU(tri.verts[1]), V3LoadU(tri.verts[2]));
+
+ //do sweep
+
+ PxReal res = SweepShapeTriangle(
+ *shape0.mGeometry, *shape1.mGeometry, transform0, transform1, lastTm0, lastTm1, restDistance,
+ resultNormal, resultPoint, Cm::FastVertex2ShapeScaling(), triangle,
+ 0.f);
+
+ if(res <= 0.f)
+ {
+ res = 0.f;
+
+ const PxVec3 v0 = tri.verts[1] - tri.verts[0] ;
+ const PxVec3 v1 = tri.verts[2] - tri.verts[0];
+
+ //Now we have a 0 TOI, lets see if the in-sphere hit it!
+
+ PxF32 distanceSq = distancePointTriangleSquared( sphereCenterInTr1, tri.verts[0], v0, v1);
+
+ if(distanceSq < inRadSq)
+ {
+ const PxVec3 nor = v0.cross(v1);
+ const PxF32 distance = PxSqrt(distanceSq);
+ res = distance - inSphereRadius;
+ const PxF32 d = nor.dot(tri.verts[0]);
+ const PxF32 dd = nor.dot(sphereCenterInTr1T0);
+ if((dd - d) > 0.f)
+ {
+ //back side, penetration
+ res = -(2.f * inSphereRadius - distance);
+ }
+ }
+ }
+
+ if (res < minTOI)
+ {
+ const PxVec3 v0 = tri.verts[1] - tri.verts[0] ;
+ const PxVec3 v1 = tri.verts[2] - tri.verts[0];
+
+ PxVec3 resultNormal1 = v0.cross(v1);
+ resultNormal1.normalize();
+ //if(norDotRel > 1e-6f)
+ {
+ tempWorldNormal = resultNormal1;
+ tempWorldPoint = resultPoint;
+ minTOI = res;
+ ccdFaceIndex = orderedList[ti];
+ }
+ }
+
+ }
+
+ worldNormal = transform1.rotate(tempWorldNormal);
+ worldPoint = tempWorldPoint;
+
+ outCCDFaceIndex = ccdFaceIndex;
+
+ return minTOI;
+}
+
+
+PxReal SweepEstimateAnyShapeHeightfield(GU_SWEEP_ESTIMATE_ARGS)
+{
+ HeightFieldUtil hfUtil(shape1.mGeometry->get<const physx::PxHeightFieldGeometryLL>());
+
+ Ps::InlineArray<PxU32,64> tempContainer;
+
+ EntityReportContainerCallback callback(tempContainer);
+
+ PxVec3 trA = transform0.p - lastTr0.p;
+ PxVec3 trB = transform1.p - lastTr1.p;
+
+ PxVec3 relTr = trA - trB;
+ PxVec3 halfRelTr = relTr * 0.5f;
+
+ const PxVec3 extents = shape0.mExtents + halfRelTr.abs() + PxVec3(restDistance);
+ const PxVec3 center = shape0.mCenter + halfRelTr;
+
+
+ PxBounds3 bounds0(center - extents, center + extents);
+
+
+ hfUtil.overlapAABBTriangles(transform1, bounds0, GuHfQueryFlags::eWORLD_SPACE, &callback);
+
+ PxVec3 origin = shape0.mCenter;
+ PxVec3 extent = shape0.mExtents;
+
+ PxReal minTOI = PX_MAX_REAL;
+
+ PxU32 numTrigs = tempContainer.size();
+ PxU32* trianglesIndices = tempContainer.begin();
+
+ for(PxU32 a = 0; a < numTrigs; ++a)
+ {
+
+ PxTriangle tri;
+ hfUtil.getTriangle(shape1.mPrevTransform, tri, 0, 0, trianglesIndices[a], true, true);
+
+
+
+ PxVec3 resultNormal = -(tri.verts[1]-tri.verts[0]).cross(tri.verts[2]-tri.verts[0]);
+ resultNormal.normalize();
+
+ if(relTr.dot(resultNormal) >= fastMovingThreshold)
+ {
+
+ PxBounds3 bounds;
+ bounds.setEmpty();
+ bounds.include(tri.verts[0]);
+ bounds.include(tri.verts[1]);
+ bounds.include(tri.verts[2]);
+
+ PxF32 toi = sweepAABBAABB(origin, extent * 1.1f, bounds.getCenter(), (bounds.getExtents() + PxVec3(0.01f, 0.01f, 0.01f)) * 1.1f, trA, trB);
+
+ minTOI = PxMin(minTOI, toi);
+ }
+ }
+
+ return minTOI;
+}
+
+
+
+PxReal SweepAnyShapeMesh(GU_SWEEP_METHOD_ARGS)
+{
+ PX_UNUSED(toiEstimate);
+ // this is the trimesh midphase for convex vs mesh sweep. shape0 is the convex shape.
+
+ // Get actual shape data
+ const PxTriangleMeshGeometryLL& shapeMesh = shape1.mGeometry->get<const PxTriangleMeshGeometryLL>();
+
+ const Cm::FastVertex2ShapeScaling meshScaling(shapeMesh.scale);
+
+ /*---------------------------------------------------*\
+ |
+ | STEP1: OPCODE Geometry collection
+ |
+ \*---------------------------------------------------*/
+
+ PxVec3 trA = transform0.p - lastTm0.p;
+ PxVec3 trB = transform1.p - lastTm1.p;
+
+ PxVec3 relTr = trA - trB;
+ PxVec3 unitDir = relTr;
+ PxReal length = unitDir.normalize();
+
+ PxMat33 matRot(lastTm0.q);
+
+
+ //1) Compute the swept bounds
+ Box sweptBox;
+ computeSweptBox(sweptBox, shape0.mExtents, shape0.mCenter, matRot, unitDir, length);
+
+ Box vertexSpaceBox;
+ if (shapeMesh.scale.isIdentity())
+ vertexSpaceBox = transformBoxOrthonormal(sweptBox, transform1.getInverse());
+ else
+ computeVertexSpaceOBB(vertexSpaceBox, sweptBox, transform1, shapeMesh.scale);
+
+
+ vertexSpaceBox.extents += PxVec3(restDistance);
+
+ Ps::InlineArray<PxU32, 64> tempContainer;
+
+ AccumCallback callback(tempContainer);
+
+ // AP scaffold: early out opportunities, should probably use fat raycast
+ Midphase::intersectOBB(shapeMesh.meshData, vertexSpaceBox, callback, true);
+
+ if (tempContainer.size() == 0)
+ return PX_MAX_REAL;
+
+ // Intersection found, fetch triangles
+ PxU32 numTrigs = tempContainer.size();
+ const PxU32* triangleIndices = tempContainer.begin();
+
+ PxVec3 origin = shape0.mCenter;
+ PxVec3 extent = shape0.mExtents + PxVec3(restDistance);
+
+ Ps::InlineArray<PxU32, 64> orderedContainer;
+ orderedContainer.resize(tempContainer.size());
+
+ Ps::InlineArray<PxU32, 64> distanceEntries;
+ distanceEntries.resize(tempContainer.size());
+
+ PxU32* orderedList = orderedContainer.begin();
+ PxF32* distances = reinterpret_cast<PxF32*>(distanceEntries.begin());
+
+ PxReal minTOI = PX_MAX_REAL;
+
+
+ PxU32 count = 0;
+ for(PxU32 a = 0; a < numTrigs; ++a)
+ {
+ PxU32 unused;
+ ConvexTriangles convexPartOfMesh1(shapeMesh, meshScaling, &triangleIndices[a], 1, &unused);
+
+ PxVec3 resultNormal = -transform1.rotate(convexPartOfMesh1.getPolygonNormal(0));
+
+ if(relTr.dot(resultNormal) >= fastMovingThreshold)
+ {
+ PxBounds3 bounds;
+ convexPartOfMesh1.getBounds(bounds, lastTm1);
+ //OK, we have all 3 vertices, now calculate bounds...
+
+ PxF32 toi = sweepAABBAABB(origin, extent, bounds.getCenter(), bounds.getExtents() + PxVec3(0.02f, 0.02f, 0.02f), trA, trB);
+
+ PxU32 index = 0;
+ if(toi <= 1.f)
+ {
+ for(PxU32 b = count; b > 0; --b)
+ {
+ if(distances[b-1] <= toi)
+ {
+ //shuffle down and swap
+ index = b;
+ break;
+ }
+ PX_ASSERT(b > 0);
+ PX_ASSERT(b < numTrigs);
+ distances[b] = distances[b-1];
+ orderedList[b] = orderedList[b-1];
+ }
+ PX_ASSERT(index < numTrigs);
+ orderedList[index] = triangleIndices[a];
+ distances[index] = toi;
+ count++;
+ }
+ }
+ }
+
+
+
+ PxVec3 tempWorldNormal(0.f), tempWorldPoint(0.f);
+
+ Cm::FastVertex2ShapeScaling idScale;
+ PxU32 ccdFaceIndex = PXC_CONTACT_NO_FACE_INDEX;
+
+ PxVec3 sphereCenter(lastTm1.p);
+ PxF32 inSphereRadius = shape0.mFastMovingThreshold;
+ //PxF32 inRadSq = inSphereRadius * inSphereRadius;
+
+ PxVec3 sphereCenterInTransform1 = transform1.transformInv(sphereCenter);
+
+ PxVec3 sphereCenterInTransform0p = transform1.transformInv(lastTm0.p);
+
+
+ for (PxU32 ti = 0; ti < count /*&& PxMax(minTOI, 0.f) >= distances[ti]*/; ti++)
+ {
+ PxU32 unused;
+ ConvexTriangles convexPartOfMesh1(shapeMesh, meshScaling, &orderedList[ti], 1, &unused);
+
+ PxVec3 resultNormal, resultPoint, v0l, v1l, v2l;
+ TriangleVertexPointers::getTriangleVerts(shapeMesh.meshData, orderedList[ti], v0l, v1l, v2l);
+ const bool flipNormal = meshScaling.flipsNormal();
+
+ const PxVec3 v0 = meshScaling * v0l;
+ const PxVec3 v1 = meshScaling * (flipNormal ? v2l : v1l);
+ const PxVec3 v2 = meshScaling * (flipNormal ? v1l : v2l);
+
+ TriangleV triangle(V3LoadU(v0), V3LoadU(v1), V3LoadU(v2));
+
+ //do sweep
+ PxReal res = SweepShapeTriangle(
+ *shape0.mGeometry, *shape1.mGeometry, transform0, transform1, lastTm0, lastTm1, restDistance,
+ resultNormal, resultPoint, Cm::FastVertex2ShapeScaling(), triangle,
+ 0.f);
+
+ resultNormal = -resultNormal;
+
+ if(res <= 0.f)
+ {
+ res = 0.f;
+
+ PxF32 inRad = inSphereRadius + restDistance;
+ PxF32 inRadSq = inRad*inRad;
+
+ const PxVec3 vv0 = v1 - v0 ;
+ const PxVec3 vv1 = v2 - v0;
+ const PxVec3 nor = vv0.cross(vv1);
+
+ //Now we have a 0 TOI, lets see if the in-sphere hit it!
+
+ PxF32 distanceSq = distancePointTriangleSquared( sphereCenterInTransform1, v0, vv0, vv1);
+
+ if(distanceSq < inRadSq)
+ {
+ const PxF32 distance = PxSqrt(distanceSq);
+ res = distance - inRad;
+ const PxF32 d = nor.dot(v0);
+ const PxF32 dd = nor.dot(sphereCenterInTransform0p);
+ if((dd - d) < 0.f)
+ {
+ //back side, penetration
+ res = -(2.f * inRad - distance);
+ }
+ }
+ PX_ASSERT(PxIsFinite(res));
+ resultNormal = convexPartOfMesh1.getPolygonNormal(0);
+ }
+
+ if (res < minTOI)
+ {
+ tempWorldNormal = resultNormal;//convexPartOfMesh1.getPolygonNormal(0);//transform1.rotate(convexPartOfMesh1.getPolygonNormal(0));
+ tempWorldPoint = resultPoint;
+ minTOI = res;
+ ccdFaceIndex = orderedList[ti];
+ }
+
+ }
+
+ worldNormal = transform1.rotate(tempWorldNormal);
+ worldPoint = tempWorldPoint;
+ outCCDFaceIndex = ccdFaceIndex;
+ return minTOI;
+}
+
+
+/**
+\brief This code performs a conservative estimate of the TOI of a shape v mesh.
+*/
+PxReal SweepEstimateAnyShapeMesh(GU_SWEEP_ESTIMATE_ARGS)
+{
+ // this is the trimesh midphase for convex vs mesh sweep. shape0 is the convex shape.
+ // Get actual shape data
+ const PxTriangleMeshGeometryLL& shapeMesh = shape1.mGeometry->get<const PxTriangleMeshGeometryLL>();
+
+ const Cm::FastVertex2ShapeScaling meshScaling(shapeMesh.scale);
+
+
+ /*---------------------------------------------------*\
+ |
+ | STEP1: OPCODE Geometry collection
+ |
+ \*---------------------------------------------------*/
+
+ PxVec3 trA = transform0.p - lastTr0.p;
+ PxVec3 trB = transform1.p - lastTr1.p;
+
+ PxVec3 relTr = trA - trB;
+ PxVec3 unitDir = relTr;
+ PxReal length = unitDir.normalize();
+
+ PxMat33 matRot(lastTr0.q);
+
+ //1) Compute the swept bounds
+ Box sweptBox;
+ computeSweptBox(sweptBox, shape0.mExtents, shape0.mCenter, matRot, unitDir, length);
+
+ Box vertexSpaceBox;
+ computeVertexSpaceOBB(vertexSpaceBox, sweptBox, transform1, shapeMesh.scale);
+
+ vertexSpaceBox.extents += PxVec3(restDistance);
+
+ // TODO: implement a cached mode that fetches the trigs from a cache rather than per opcode if there is little motion.
+
+ struct CB : MeshHitCallback<PxRaycastHit>
+ {
+ PxReal minTOI;
+ PxReal sumFastMovingThresh;
+ const PxTriangleMeshGeometryLL& shapeMesh;
+ const Cm::FastVertex2ShapeScaling& meshScaling;
+ const PxVec3& relTr;
+ const PxVec3& trA;
+ const PxVec3& trB;
+ const PxTransform& transform1;
+ const PxVec3& origin;
+ const PxVec3& extent;
+
+ CB(PxReal aSumFast, const PxTriangleMeshGeometryLL& aShapeMesh, const Cm::FastVertex2ShapeScaling& aMeshScaling,
+ const PxVec3& aRelTr, const PxVec3& atrA, const PxVec3& atrB, const PxTransform& aTransform1, const PxVec3& aOrigin, const PxVec3& aExtent)
+ : MeshHitCallback<PxRaycastHit>(CallbackMode::eMULTIPLE),
+ sumFastMovingThresh(aSumFast), shapeMesh(aShapeMesh), meshScaling(aMeshScaling), relTr(aRelTr), trA(atrA), trB(atrB),
+ transform1(aTransform1), origin(aOrigin), extent(aExtent)
+ {
+ minTOI = PX_MAX_REAL;
+ }
+
+ virtual PxAgain processHit( // all reported coords are in mesh local space including hit.position
+ const PxRaycastHit& hit, const PxVec3&, const PxVec3&, const PxVec3&, PxReal& shrunkMaxT, const PxU32*)
+ {
+ PxU32 unused;
+ ConvexTriangles convexPartOfMesh1(shapeMesh, meshScaling, &hit.faceIndex, 1, &unused);
+ PxVec3 resultNormal = -transform1.rotate(convexPartOfMesh1.getPolygonNormal(0));
+ if(relTr.dot(resultNormal) >= sumFastMovingThresh)
+ {
+ PxBounds3 bounds;
+ convexPartOfMesh1.getBounds(bounds, transform1);
+ //OK, we have all 3 vertices, now calculate bounds...
+
+ PX_ASSERT(trB.x == 0.f);
+ PX_ASSERT(trB.y == 0.f);
+ PX_ASSERT(trB.z == 0.f);
+ PxF32 toi = sweepAABBAABB(
+ origin, extent * 1.1f, bounds.getCenter(), (bounds.getExtents() + PxVec3(0.01f, 0.01f, 0.01f)) * 1.1f, trA, trB);
+
+ minTOI = PxMin(minTOI, toi);
+ shrunkMaxT = minTOI;
+ }
+
+ return (minTOI > 0.0f); // stop traversal if minTOI == 0.0f
+ }
+
+ void operator=(const CB&) {}
+ };
+
+ PxVec3 origin = shape0.mCenter;
+ PxVec3 extent = shape0.mExtents + PxVec3(restDistance);
+
+ CB callback(fastMovingThreshold, shapeMesh, meshScaling, relTr, trA, trB, transform1, origin, extent);
+ Midphase::intersectOBB(shapeMesh.meshData, vertexSpaceBox, callback, true);
+
+ return callback.minTOI;
+}
+
+
+}
+}
+
diff --git a/PhysX_3.4/Source/GeomUtils/src/ccd/GuCCDSweepConvexMesh.h b/PhysX_3.4/Source/GeomUtils/src/ccd/GuCCDSweepConvexMesh.h
new file mode 100644
index 00000000..8c520610
--- /dev/null
+++ b/PhysX_3.4/Source/GeomUtils/src/ccd/GuCCDSweepConvexMesh.h
@@ -0,0 +1,178 @@
+// 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.
+
+
+#ifndef GU_CCD_SWEEP_H
+#define GU_CCD_SWEEP_H
+
+#include "PxPhysXCommonConfig.h"
+#include "CmPhysXCommon.h"
+#include "PsVecTransform.h"
+#include "GuGeometryUnion.h"
+#include "CmScaling.h"
+
+#define GU_TRIANGLE_SWEEP_METHOD_ARGS \
+ const Gu::GeometryUnion& shape0, \
+ const Gu::GeometryUnion& shape1, \
+ const PxTransform& transform0, \
+ const PxTransform& transform1, \
+ const PxTransform& lastTm0, \
+ const PxTransform& lastTm1, \
+ PxReal restDistance, \
+ PxVec3& worldNormal, \
+ PxVec3& worldPoint, \
+ const Cm::FastVertex2ShapeScaling& meshScaling, \
+ Gu::TriangleV& triangle, \
+ const PxF32 toiEstimate
+
+
+#define GU_SWEEP_METHOD_ARGS \
+ const Gu::CCDShape& shape0, \
+ const Gu::CCDShape& shape1, \
+ const PxTransform& transform0, \
+ const PxTransform& transform1, \
+ const PxTransform& lastTm0, \
+ const PxTransform& lastTm1, \
+ PxReal restDistance, \
+ PxVec3& worldNormal, \
+ PxVec3& worldPoint, \
+ const PxF32 toiEstimate, \
+ PxU32& outCCDFaceIndex, \
+ const PxReal fastMovingThreshold
+
+
+#define GU_SWEEP_ESTIMATE_ARGS \
+ const CCDShape& shape0, \
+ const CCDShape& shape1, \
+ const PxTransform& transform0, \
+ const PxTransform& transform1, \
+ const PxTransform& lastTr0, \
+ const PxTransform& lastTr1, \
+ const PxReal restDistance, \
+ const PxReal fastMovingThreshold
+
+
+#define GU_SWEEP_METHOD_ARGS_UNUSED \
+ const Gu::CCDShape& /*shape0*/, \
+ const Gu::CCDShape& /*shape1*/, \
+ const PxTransform& /*transform0*/, \
+ const PxTransform& /*transform1*/, \
+ const PxTransform& /*lastTm0*/, \
+ const PxTransform& /*lastTm1*/, \
+ PxReal /*restDistance*/, \
+ PxVec3& /*worldNormal*/, \
+ PxVec3& /*worldPoint*/, \
+ const PxF32 /*toiEstimate*/, \
+ PxU32& /*outCCDFaceIndex*/, \
+ const PxReal /*fastMovingThreshold*/
+
+namespace physx
+{
+namespace Gu
+{
+ struct CCDShape
+ {
+ const Gu::GeometryUnion* mGeometry;
+ PxReal mFastMovingThreshold; //The CCD threshold for this shape
+ PxTransform mPrevTransform; //This shape's previous transform
+ PxTransform mCurrentTransform; //This shape's current transform
+ PxVec3 mExtents; //The extents of this shape's AABB
+ PxVec3 mCenter; //The center of this shape's AABB
+ PxU32 mUpdateCount; //How many times this shape has been updated in the CCD. This is correlated with the CCD body's update count.
+ };
+
+ PX_FORCE_INLINE PxF32 sweepAABBAABB(const PxVec3& centerA, const PxVec3& extentsA, const PxVec3& centerB, const PxVec3& extentsB, const PxVec3& trA, const PxVec3& trB)
+ {
+ //Sweep 2 AABBs against each other, return the TOI when they hit else PX_MAX_REAL if they don't hit
+ const PxVec3 cAcB = centerA - centerB;
+ const PxVec3 sumExtents = extentsA + extentsB;
+
+ //Initial hit
+ if(PxAbs(cAcB.x) <= sumExtents.x &&
+ PxAbs(cAcB.y) <= sumExtents.y &&
+ PxAbs(cAcB.z) <= sumExtents.z)
+ return 0.f;
+
+ //No initial hit - perform the sweep
+ const PxVec3 relTr = trB - trA;
+ PxF32 tfirst = 0.f;
+ PxF32 tlast = 1.f;
+
+ const PxVec3 aMax = centerA + extentsA;
+ const PxVec3 aMin = centerA - extentsA;
+ const PxVec3 bMax = centerB + extentsB;
+ const PxVec3 bMin = centerB - extentsB;
+
+ const PxF32 eps = 1e-6f;
+
+ for(PxU32 a = 0; a < 3; ++a)
+ {
+ if(relTr[a] < -eps)
+ {
+ if(bMax[a] < aMin[a])
+ return PX_MAX_REAL;
+ if(aMax[a] < bMin[a])
+ tfirst = PxMax((aMax[a] - bMin[a])/relTr[a], tfirst);
+ if(bMax[a] > aMin[a])
+ tlast = PxMin((aMin[a] - bMax[a])/relTr[a], tlast);
+ }
+ else if(relTr[a] > eps)
+ {
+ if(bMin[a] > aMax[a])
+ return PX_MAX_REAL;
+ if(bMax[a] < aMin[a])
+ tfirst = PxMax((aMin[a] - bMax[a])/relTr[a], tfirst);
+ if(aMax[a] > bMin[a])
+ tlast = PxMin((aMax[a] - bMin[a])/relTr[a], tlast);
+ }
+ else
+ {
+ if(bMax[a] < aMin[a] || bMin[a] > aMax[a])
+ return PX_MAX_REAL;
+ }
+
+ //No hit
+ if(tfirst > tlast)
+ return PX_MAX_REAL;
+ }
+ //There was a hit so return the TOI
+ return tfirst;
+ }
+
+ PX_PHYSX_COMMON_API PxReal SweepShapeShape(GU_SWEEP_METHOD_ARGS);
+
+ PX_PHYSX_COMMON_API PxReal SweepEstimateAnyShapeHeightfield(GU_SWEEP_ESTIMATE_ARGS);
+
+ PX_PHYSX_COMMON_API PxReal SweepEstimateAnyShapeMesh(GU_SWEEP_ESTIMATE_ARGS);
+
+
+}
+}
+#endif
+
diff --git a/PhysX_3.4/Source/GeomUtils/src/ccd/GuCCDSweepPrimitives.cpp b/PhysX_3.4/Source/GeomUtils/src/ccd/GuCCDSweepPrimitives.cpp
new file mode 100644
index 00000000..0a8f55f3
--- /dev/null
+++ b/PhysX_3.4/Source/GeomUtils/src/ccd/GuCCDSweepPrimitives.cpp
@@ -0,0 +1,290 @@
+// 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 "Ps.h"
+#include "GuVecCapsule.h"
+#include "GuVecBox.h"
+#include "GuVecConvexHull.h"
+#include "GuVecTriangle.h"
+#include "GuVecShrunkConvexHull.h"
+#include "GuVecShrunkBox.h"
+#include "GuGJKRaycast.h"
+#include "GuCCDSweepConvexMesh.h"
+#include "GuGJKType.h"
+
+namespace physx
+{
+namespace Gu
+{
+
+using namespace Ps::aos;
+
+template<typename Geom> PX_FORCE_INLINE PxReal getRadius(const PxGeometry&)
+{
+ return 0;
+}
+
+template<> PX_FORCE_INLINE PxReal getRadius<CapsuleV>(const PxGeometry& g)
+{
+ PX_ASSERT(g.getType() == PxGeometryType::eCAPSULE || g.getType() == PxGeometryType::eSPHERE);
+ PX_COMPILE_TIME_ASSERT(PX_OFFSET_OF(PxSphereGeometry, radius) == PX_OFFSET_OF(PxCapsuleGeometry, radius));
+ return static_cast<const PxSphereGeometry&>(g).radius;
+}
+
+
+
+template<class ConvexA, class ConvexB>
+static PxReal CCDSweep(ConvexA& a, ConvexB& b, const PxTransform& transform0, const PxTransform& transform1, const PxTransform& lastTm0, const PxTransform& lastTm1,
+ const Ps::aos::FloatV& toiEstimate, PxVec3& worldPoint, PxVec3& worldNormal, PxReal inflation = 0.f)
+{
+ PX_UNUSED(toiEstimate); //KS - TODO - can we use this again?
+ using namespace Ps::aos;
+
+ const Vec3V zero = V3Zero();
+
+ const QuatV q0 = QuatVLoadA(&transform0.q.x);
+ const Vec3V p0 = V3LoadA(&lastTm0.p.x);
+
+ const QuatV q1 = QuatVLoadA(&transform1.q.x);
+ const Vec3V p1 = V3LoadA(&lastTm1.p.x);
+
+ const PsTransformV tr0(p0, q0);
+ const PsTransformV tr1(p1, q1);
+
+ const PsMatTransformV aToB(tr1.transformInv(tr0));
+
+ const Vec3V trans0p = V3LoadU(transform0.p);
+ const Vec3V trans1p = V3LoadU(transform1.p);
+ const Vec3V trA = V3Sub(trans0p, p0);
+ const Vec3V trB = V3Sub(trans1p, p1);
+ const Vec3V relTr = tr1.rotateInv(V3Sub(trB, trA));
+
+ FloatV lambda;
+ Vec3V closestA, normal;
+ const FloatV initialLambda = FZero();
+ const RelativeConvex<ConvexA> convexA(a, aToB);
+ const LocalConvex<ConvexB> convexB(b);
+ if(gjkRaycastPenetration<RelativeConvex<ConvexA>, LocalConvex<ConvexB> >(convexA, convexB, aToB.p, initialLambda, zero, relTr, lambda, normal, closestA, inflation, true))
+ {
+ //Adjust closestA because it will be on the surface of convex a in its initial position (s). If the TOI > 0, we need to move
+ //the point along the sweep direction to get the world-space hit position.
+ PxF32 res;
+ FStore(lambda, &res);
+ closestA = V3ScaleAdd(trA, FMax(lambda, FZero()), tr1.transform(closestA));
+ normal = tr1.rotate(normal);
+
+ V3StoreU(normal, worldNormal);
+ V3StoreU(closestA, worldPoint);
+ return res;
+ }
+ return PX_MAX_REAL;
+}
+
+
+
+//
+// lookup table for geometry-vs-geometry sweeps
+//
+
+
+PxReal UnimplementedSweep (GU_SWEEP_METHOD_ARGS_UNUSED)
+{
+ return PX_MAX_REAL; //no impact
+}
+
+template<typename Geom0, typename Geom1>
+PxReal SweepGeomGeom(GU_SWEEP_METHOD_ARGS)
+{
+ PX_UNUSED(outCCDFaceIndex);
+ PX_UNUSED(fastMovingThreshold);
+
+ const PxGeometry& g0 = shape0.mGeometry->getGeometry();
+ const PxGeometry& g1 = shape1.mGeometry->getGeometry();
+
+ //Geom0 geom0(g0);
+ //Geom1 geom1(g1);
+ typename Shrink<Geom0>::Type geom0(g0);
+ typename Shrink<Geom1>::Type geom1(g1);
+
+ return CCDSweep(geom0, geom1, transform0, transform1, lastTm0, lastTm1, FLoad(toiEstimate), worldPoint, worldNormal, restDistance+getRadius<Geom0>(g0)+getRadius<Geom1>(g1) );
+}
+
+typedef PxReal (*SweepMethod) (GU_SWEEP_METHOD_ARGS);
+
+PxReal SweepAnyShapeHeightfield(GU_SWEEP_METHOD_ARGS);
+PxReal SweepAnyShapeMesh(GU_SWEEP_METHOD_ARGS);
+
+SweepMethod g_SweepMethodTable[PxGeometryType::eGEOMETRY_COUNT][PxGeometryType::eGEOMETRY_COUNT] =
+{
+ //PxGeometryType::eSPHERE
+ {
+ SweepGeomGeom<CapsuleV, CapsuleV>, //PxGeometryType::eSPHERE
+ UnimplementedSweep, //PxGeometryType::ePLANE
+ SweepGeomGeom<CapsuleV, CapsuleV>, //PxGeometryType::eCAPSULE
+ SweepGeomGeom<CapsuleV, BoxV>, //PxGeometryType::eBOX
+ SweepGeomGeom<CapsuleV, ConvexHullV>, //PxGeometryType::eCONVEXMESH
+ SweepAnyShapeMesh, //PxGeometryType::eTRIANGLEMESH
+ SweepAnyShapeHeightfield, //PxGeometryType::eHEIGHTFIELD //TODO
+ },
+
+ //PxGeometryType::ePLANE
+ {
+ 0, //PxGeometryType::eSPHERE
+ UnimplementedSweep, //PxGeometryType::ePLANE
+ UnimplementedSweep, //PxGeometryType::eCAPSULE
+ UnimplementedSweep, //PxGeometryType::eBOX
+ UnimplementedSweep, //PxGeometryType::eCONVEXMESH
+ UnimplementedSweep, //PxGeometryType::eTRIANGLEMESH
+ UnimplementedSweep, //PxGeometryType::eHEIGHTFIELD
+ },
+
+ //PxGeometryType::eCAPSULE
+ {
+ 0, //PxGeometryType::eSPHERE
+ 0, //PxGeometryType::ePLANE
+ SweepGeomGeom<CapsuleV, CapsuleV>, //PxGeometryType::eCAPSULE
+ SweepGeomGeom<CapsuleV, BoxV>, //PxGeometryType::eBOX
+ SweepGeomGeom<CapsuleV, ConvexHullV>, //PxGeometryType::eCONVEXMESH
+ SweepAnyShapeMesh, //PxGeometryType::eTRIANGLEMESH
+ SweepAnyShapeHeightfield, //PxGeometryType::eHEIGHTFIELD
+ },
+
+ //PxGeometryType::eBOX
+ {
+ 0, //PxGeometryType::eSPHERE
+ 0, //PxGeometryType::ePLANE
+ 0, //PxGeometryType::eCAPSULE
+ SweepGeomGeom<BoxV, BoxV>, //PxGeometryType::eBOX
+ SweepGeomGeom<BoxV, ConvexHullV>, //PxGeometryType::eCONVEXMESH
+ SweepAnyShapeMesh, //PxGeometryType::eTRIANGLEMESH
+ SweepAnyShapeHeightfield, //PxGeometryType::eHEIGHTFIELD
+ },
+
+ //PxGeometryType::eCONVEXMESH
+ {
+ 0, //PxGeometryType::eSPHERE
+ 0, //PxGeometryType::ePLANE
+ 0, //PxGeometryType::eCAPSULE
+ 0, //PxGeometryType::eBOX
+ SweepGeomGeom<ConvexHullV, ConvexHullV>, //PxGeometryType::eCONVEXMESH
+ SweepAnyShapeMesh, //PxGeometryType::eTRIANGLEMESH
+ SweepAnyShapeHeightfield, //PxGeometryType::eHEIGHTFIELD
+ },
+
+ //PxGeometryType::eTRIANGLEMESH
+ {
+ 0, //PxGeometryType::eSPHERE
+ 0, //PxGeometryType::ePLANE
+ 0, //PxGeometryType::eCAPSULE
+ 0, //PxGeometryType::eBOX
+ 0, //PxGeometryType::eCONVEXMESH
+ UnimplementedSweep, //PxGeometryType::eTRIANGLEMESH
+ UnimplementedSweep, //PxGeometryType::eHEIGHTFIELD
+ },
+
+ //PxGeometryType::eHEIGHTFIELD
+ {
+ 0, //PxGeometryType::eSPHERE
+ 0, //PxGeometryType::ePLANE
+ 0, //PxGeometryType::eCAPSULE
+ 0, //PxGeometryType::eBOX
+ 0, //PxGeometryType::eCONVEXMESH
+ 0, //PxGeometryType::eTRIANGLEMESH
+ UnimplementedSweep, //PxGeometryType::eHEIGHTFIELD
+ },
+};
+
+
+PxReal SweepShapeShape(GU_SWEEP_METHOD_ARGS)
+{
+ PxGeometryType::Enum type0 = shape0.mGeometry->getType();
+ PxGeometryType::Enum type1 = shape1.mGeometry->getType();
+
+ return g_SweepMethodTable[type0][type1](shape0, shape1, transform0, transform1, lastTm0, lastTm1,
+ restDistance, worldNormal, worldPoint, toiEstimate, outCCDFaceIndex, fastMovingThreshold);
+
+}
+
+//
+// lookup table for sweeps agains triangles
+//
+
+PxReal UnimplementedTriangleSweep(GU_TRIANGLE_SWEEP_METHOD_ARGS)
+{
+ PX_UNUSED(shape0);
+ PX_UNUSED(shape1);
+ PX_UNUSED(transform0);
+ PX_UNUSED(transform1);
+ PX_UNUSED(lastTm0);
+ PX_UNUSED(lastTm1);
+ PX_UNUSED(restDistance);
+ PX_UNUSED(worldNormal);
+ PX_UNUSED(worldPoint);
+ PX_UNUSED(meshScaling);
+ PX_UNUSED(triangle);
+ PX_UNUSED(toiEstimate);
+
+ return 1e10f; //no impact
+}
+
+template<typename Geom>
+PxReal SweepGeomTriangles(GU_TRIANGLE_SWEEP_METHOD_ARGS)
+{
+ PX_UNUSED(meshScaling);
+ PX_UNUSED(shape1);
+
+ const PxGeometry& g = shape0.getGeometry();
+ //Geom geom(g);
+ typename Shrink<Geom>::Type geom(g);
+
+ return CCDSweep<TriangleV, Geom>(triangle, geom, transform1, transform0, lastTm1, lastTm0, FLoad(toiEstimate), worldPoint, worldNormal, restDistance+getRadius<Geom>(g) );
+}
+
+typedef PxReal (*TriangleSweepMethod) (GU_TRIANGLE_SWEEP_METHOD_ARGS);
+TriangleSweepMethod g_TriangleSweepMethodTable[PxGeometryType::eGEOMETRY_COUNT] =
+{
+ SweepGeomTriangles<CapsuleV>, //PxGeometryType::eSPHERE
+ UnimplementedTriangleSweep, //PxGeometryType::ePLANE
+ SweepGeomTriangles<CapsuleV>, //PxGeometryType::eCAPSULE
+ SweepGeomTriangles<BoxV>, //PxGeometryType::eBOX
+ SweepGeomTriangles<ConvexHullV>, //PxGeometryType::eCONVEXMESH
+ UnimplementedTriangleSweep, //PxGeometryType::eTRIANGLEMESH
+ UnimplementedTriangleSweep, //PxGeometryType::eHEIGHTFIELD
+};
+
+PxReal SweepShapeTriangle(GU_TRIANGLE_SWEEP_METHOD_ARGS)
+{
+ const PxGeometryType::Enum type0 = shape0.getType();
+ TriangleSweepMethod method = g_TriangleSweepMethodTable[type0];
+ return method(shape0, shape1, transform0, transform1, lastTm0, lastTm1, restDistance, worldNormal, worldPoint, meshScaling, triangle, toiEstimate);
+}
+
+}
+}
+