aboutsummaryrefslogtreecommitdiff
path: root/PhysX_3.4/Source/GeomUtils/src/pcm/GuPCMContactCapsuleBox.cpp
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/pcm/GuPCMContactCapsuleBox.cpp
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/pcm/GuPCMContactCapsuleBox.cpp')
-rw-r--r--PhysX_3.4/Source/GeomUtils/src/pcm/GuPCMContactCapsuleBox.cpp230
1 files changed, 230 insertions, 0 deletions
diff --git a/PhysX_3.4/Source/GeomUtils/src/pcm/GuPCMContactCapsuleBox.cpp b/PhysX_3.4/Source/GeomUtils/src/pcm/GuPCMContactCapsuleBox.cpp
new file mode 100644
index 00000000..c0c4c968
--- /dev/null
+++ b/PhysX_3.4/Source/GeomUtils/src/pcm/GuPCMContactCapsuleBox.cpp
@@ -0,0 +1,230 @@
+// 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 "GuVecBox.h"
+#include "GuVecCapsule.h"
+#include "GuGeometryUnion.h"
+
+#include "GuContactMethodImpl.h"
+#include "GuContactBuffer.h"
+#include "GuPCMContactGen.h"
+#include "GuPCMShapeConvex.h"
+#include "GuGJKPenetration.h"
+#include "GuEPA.h"
+
+
+namespace physx
+{
+ using namespace Ps::aos;
+
+namespace Gu
+{
+
+static bool fullContactsGenerationCapsuleBox(const CapsuleV& capsule, const BoxV& box, const PxVec3 halfExtents, const PsMatTransformV& aToB, const PsTransformV& transf0, const PsTransformV& transf1,
+ PersistentContact* manifoldContacts, PxU32& numContacts, ContactBuffer& contactBuffer, PersistentContactManifold& manifold, Vec3V& normal, const Vec3VArg closest,
+ const FloatVArg boxMargin, const FloatVArg contactDist, const bool doOverlapTest, const FloatVArg toleranceScale)
+{
+
+ PolygonalData polyData;
+ PCMPolygonalBox polyBox(halfExtents);
+ polyBox.getPolygonalData(&polyData);
+
+ Mat33V identity = M33Identity();
+ SupportLocalImpl<BoxV> map(box, transf1, identity, identity);
+
+ PxU32 origContacts = numContacts;
+ if (generateCapsuleBoxFullContactManifold(capsule, polyData, &map, aToB, manifoldContacts, numContacts, contactDist, normal, closest, boxMargin, doOverlapTest, toleranceScale))
+ {
+ //EPA has contacts and we have new contacts, we discard the EPA contacts
+ if(origContacts != 0 && numContacts != origContacts)
+ {
+ numContacts--;
+ manifoldContacts++;
+ }
+
+ manifold.addBatchManifoldContacts2(manifoldContacts, numContacts);
+
+ normal = transf1.rotate(normal);
+
+ manifold.addManifoldContactsToContactBuffer(contactBuffer, normal, transf0, capsule.radius, contactDist);
+
+ return true;
+
+ }
+
+ return false;
+
+}
+
+
+bool pcmContactCapsuleBox(GU_CONTACT_METHOD_ARGS)
+{
+
+ PX_UNUSED(renderOutput);
+
+ PersistentContactManifold& manifold = cache.getManifold();
+ Ps::prefetchLine(&manifold, 256);
+ const PxCapsuleGeometry& shapeCapsule = shape0.get<const PxCapsuleGeometry>();
+ const PxBoxGeometry& shapeBox = shape1.get<const PxBoxGeometry>();
+
+ PX_ASSERT(transform1.q.isSane());
+ PX_ASSERT(transform0.q.isSane());
+
+ const Vec3V zeroV = V3Zero();
+ const Vec3V boxExtents = V3LoadU(shapeBox.halfExtents);
+
+ const FloatV contactDist = FLoad(params.mContactDistance);
+
+ const PsTransformV transf0 = loadTransformA(transform0);
+ const PsTransformV transf1 = loadTransformA(transform1);
+
+ const PsTransformV curRTrans = transf1.transformInv(transf0);
+ const PsMatTransformV aToB_(curRTrans);
+
+ const FloatV capsuleRadius = FLoad(shapeCapsule.radius);
+ const FloatV capsuleHalfHeight = FLoad(shapeCapsule.halfHeight);
+
+ const PxU32 initialContacts = manifold.mNumContacts;
+
+ const FloatV boxMargin = Gu::CalculatePCMBoxMargin(boxExtents);
+
+ const FloatV minMargin = FMin(boxMargin, capsuleRadius);
+
+ const FloatV projectBreakingThreshold = FMul(minMargin, FLoad(0.8f));
+
+ const FloatV refreshDist = FAdd(contactDist, capsuleRadius);
+ //refreshContactPoints remove invalid contacts from the manifold and update the number correspondingly
+ manifold.refreshContactPoints(aToB_, projectBreakingThreshold, refreshDist);
+
+ const bool bLostContacts = (manifold.mNumContacts != initialContacts);
+
+ PX_UNUSED(bLostContacts);
+ if(bLostContacts || manifold.invalidate_SphereCapsule(curRTrans, minMargin))
+ {
+
+ GjkStatus status = manifold.mNumContacts > 0 ? GJK_UNDEFINED : GJK_NON_INTERSECT;
+
+ Vec3V closestA(zeroV), closestB(zeroV);
+ Vec3V normal(zeroV); // from a to b
+ const FloatV zero = FZero();
+ FloatV penDep = zero;
+
+ manifold.setRelativeTransform(curRTrans);
+ const PsMatTransformV aToB(curRTrans);
+
+ BoxV box(transf1.p, boxExtents);
+ box.setMargin(zero);
+
+ //transform capsule into the local space of box
+ CapsuleV capsule(aToB.p, aToB.rotate(V3Scale(V3UnitX(), capsuleHalfHeight)), capsuleRadius);
+ LocalConvex<CapsuleV> convexA(capsule);
+ LocalConvex<BoxV> convexB(box);
+ const Vec3V initialSearchDir = V3Sub(capsule.getCenter(), box.getCenter());
+ status = gjkPenetration<LocalConvex<CapsuleV>, LocalConvex<BoxV> >(convexA, convexB, initialSearchDir, contactDist, closestA, closestB, normal, penDep,
+ manifold.mAIndice, manifold.mBIndice, manifold.mNumWarmStartPoints, true);
+
+ PersistentContact* manifoldContacts = PX_CP_TO_PCP(contactBuffer.contacts);
+ PxU32 numContacts = 0;
+ bool doOverlapTest = false;
+ if(status == GJK_NON_INTERSECT)
+ {
+ return false;
+ }
+ else if(status == GJK_DEGENERATE)
+ {
+ return fullContactsGenerationCapsuleBox(capsule, box, shapeBox.halfExtents, aToB, transf0, transf1, manifoldContacts, numContacts, contactBuffer,
+ manifold, normal, closestB, box.getMargin(), contactDist, true, FLoad(params.mToleranceLength));
+ }
+ else
+ {
+ if(status == GJK_CONTACT)
+ {
+ const Vec3V localPointA = aToB.transformInv(closestA);//curRTrans.transformInv(closestA);
+ const Vec4V localNormalPen = V4SetW(Vec4V_From_Vec3V(normal), penDep);
+ //Add contact to contact stream
+ manifoldContacts[numContacts].mLocalPointA = localPointA;
+ manifoldContacts[numContacts].mLocalPointB = closestB;
+ manifoldContacts[numContacts++].mLocalNormalPen = localNormalPen;
+ }
+ else
+ {
+ PX_ASSERT(status == EPA_CONTACT);
+
+ status= epaPenetration(convexA, convexB, manifold.mAIndice, manifold.mBIndice, manifold.mNumWarmStartPoints,
+ closestA, closestB, normal, penDep, true);
+ if(status == EPA_CONTACT)
+ {
+ const Vec3V localPointA = aToB.transformInv(closestA);//curRTrans.transformInv(closestA);
+ const Vec4V localNormalPen = V4SetW(Vec4V_From_Vec3V(normal), penDep);
+ //Add contact to contact stream
+ manifoldContacts[numContacts].mLocalPointA = localPointA;
+ manifoldContacts[numContacts].mLocalPointB = closestB;
+ manifoldContacts[numContacts++].mLocalNormalPen = localNormalPen;
+
+ }
+ else
+ {
+ doOverlapTest = true;
+ }
+
+ }
+
+
+ if(initialContacts == 0 || bLostContacts || doOverlapTest)
+ {
+ return fullContactsGenerationCapsuleBox(capsule, box, shapeBox.halfExtents, aToB, transf0, transf1, manifoldContacts, numContacts, contactBuffer, manifold, normal,
+ closestB, box.getMargin(), contactDist, doOverlapTest, FLoad(params.mToleranceLength));
+ }
+ else
+ {
+
+ //The contacts is either come from GJK or EPA
+ const FloatV replaceBreakingThreshold = FMul(minMargin, FLoad(0.1f));
+ const Vec4V localNormalPen = V4SetW(Vec4V_From_Vec3V(normal), penDep);
+ manifold.addManifoldPoint2(curRTrans.transformInv(closestA), closestB, localNormalPen, replaceBreakingThreshold);
+
+ normal = transf1.rotate(normal);
+ manifold.addManifoldContactsToContactBuffer(contactBuffer, normal, transf0, capsuleRadius, contactDist);
+
+ return true;
+ }
+ }
+ }
+ else if(manifold.getNumContacts() > 0)
+ {
+ const Vec3V worldNormal = manifold.getWorldNormal(transf1);
+ manifold.addManifoldContactsToContactBuffer(contactBuffer, worldNormal, transf0, capsuleRadius, contactDist);
+ return true;
+ }
+
+ return false;
+
+}
+}
+}