aboutsummaryrefslogtreecommitdiff
path: root/PhysX_3.4/Source/LowLevelDynamics/src/DyContactPrepPF.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/LowLevelDynamics/src/DyContactPrepPF.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/LowLevelDynamics/src/DyContactPrepPF.cpp')
-rw-r--r--PhysX_3.4/Source/LowLevelDynamics/src/DyContactPrepPF.cpp650
1 files changed, 650 insertions, 0 deletions
diff --git a/PhysX_3.4/Source/LowLevelDynamics/src/DyContactPrepPF.cpp b/PhysX_3.4/Source/LowLevelDynamics/src/DyContactPrepPF.cpp
new file mode 100644
index 00000000..4651605b
--- /dev/null
+++ b/PhysX_3.4/Source/LowLevelDynamics/src/DyContactPrepPF.cpp
@@ -0,0 +1,650 @@
+// 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 "foundation/PxPreprocessor.h"
+#include "PsVecMath.h"
+#include "PsMathUtils.h"
+#include "DySolverContact.h"
+#include "DySolverContactPF.h"
+#include "DySolverConstraintTypes.h"
+#include "PxcNpWorkUnit.h"
+#include "DyThreadContext.h"
+#include "DyContactPrep.h"
+#include "PxcNpContactPrepShared.h"
+//#include "PxvGeometry.h"
+#include "PxvDynamics.h"
+#include "DyCorrelationBuffer.h"
+#include "DySolverConstraintDesc.h"
+#include "DySolverBody.h"
+#include "DySolverContact4.h"
+#include "DySolverContactPF4.h"
+
+
+#include "PsVecMath.h"
+#include "PxContactModifyCallback.h"
+#include "PxsMaterialManager.h"
+#include "PxsMaterialCombiner.h"
+#include "DySolverExt.h"
+#include "DyArticulationContactPrep.h"
+#include "DyContactPrepShared.h"
+
+#include "PsFoundation.h"
+
+using namespace physx::Gu;
+using namespace physx::shdfnd::aos;
+
+namespace physx
+{
+namespace Dy
+{
+
+bool createFinalizeSolverContactsCoulomb(PxSolverContactDesc& contactDesc,
+ PxsContactManagerOutput& output,
+ ThreadContext& threadContext,
+ const PxReal invDtF32,
+ PxReal bounceThresholdF32,
+ PxReal frictionOffsetThreshold,
+ PxReal correlationDistance,
+ PxConstraintAllocator& constraintAllocator,
+ PxFrictionType::Enum frictionType);
+
+static bool setupFinalizeSolverConstraintsCoulomb(
+ Sc::ShapeInteraction* shapeInteraction,
+ const ContactBuffer& buffer,
+ const CorrelationBuffer& c,
+ const PxTransform& bodyFrame0,
+ const PxTransform& bodyFrame1,
+ PxU8* workspace,
+ const PxSolverBodyData& data0,
+ const PxSolverBodyData& data1,
+ const PxReal invDtF32,
+ PxReal bounceThresholdF32,
+ PxU32 frictionPerPointCount,
+ const bool hasForceThresholds,
+ const bool staticBody,
+ PxReal invMassScale0, PxReal invInertiaScale0,
+ PxReal invMassScale1, PxReal invInertiaScale1,
+ PxReal restDist,
+ const PxReal maxCCDSeparation)
+{
+ const FloatV ccdMaxSeparation = FLoad(maxCCDSeparation);
+ PxU8* PX_RESTRICT ptr = workspace;
+ const FloatV zero=FZero();
+
+ PxU8 flags = PxU8(hasForceThresholds ? SolverContactHeader::eHAS_FORCE_THRESHOLDS : 0);
+
+ const FloatV restDistance = FLoad(restDist);
+
+ const Vec3V bodyFrame0p = V3LoadU(bodyFrame0.p);
+ const Vec3V bodyFrame1p = V3LoadU(bodyFrame1.p);
+
+ Ps::prefetchLine(c.contactID);
+ Ps::prefetchLine(c.contactID, 128);
+
+ const PxU32 frictionPatchCount = c.frictionPatchCount;
+
+ const PxU32 pointStride = sizeof(SolverContactPoint);
+ const PxU32 frictionStride = sizeof(SolverContactFriction);
+ const PxU8 pointHeaderType = Ps::to8(staticBody ? DY_SC_TYPE_STATIC_CONTACT : DY_SC_TYPE_RB_CONTACT);
+ const PxU8 frictionHeaderType = Ps::to8(staticBody ? DY_SC_TYPE_STATIC_FRICTION : DY_SC_TYPE_FRICTION);
+
+
+ const Vec3V linVel0 = V3LoadU(data0.linearVelocity);
+ const Vec3V linVel1 = V3LoadU(data1.linearVelocity);
+ const Vec3V angVel0 = V3LoadU(data0.angularVelocity);
+ const Vec3V angVel1 = V3LoadU(data1.angularVelocity);
+
+
+ const FloatV invMass0 = FLoad(data0.invMass);
+ const FloatV invMass1 = FLoad(data1.invMass);
+
+ const FloatV maxPenBias = FMax(FLoad(data0.penBiasClamp), FLoad(data1.penBiasClamp));
+
+ // PT: the matrix is symmetric so we can read it as a PxMat33! Gets rid of 25000+ LHS.
+ const PxMat33& invIn0 = reinterpret_cast<const PxMat33&>(data0.sqrtInvInertia);
+ PX_ALIGN(16, const Mat33V invSqrtInertia0)
+ (
+ V3LoadU(invIn0.column0),
+ V3LoadU(invIn0.column1),
+ V3LoadU(invIn0.column2)
+ );
+ const PxMat33& invIn1 = reinterpret_cast<const PxMat33&>(data1.sqrtInvInertia);
+ PX_ALIGN(16, const Mat33V invSqrtInertia1)
+ (
+ V3LoadU(invIn1.column0),
+ V3LoadU(invIn1.column1),
+ V3LoadU(invIn1.column2)
+ );
+
+ const FloatV invDt = FLoad(invDtF32);
+ const FloatV p8 = FLoad(0.8f);
+ const FloatV bounceThreshold = FLoad(bounceThresholdF32);
+ const FloatV orthoThreshold = FLoad(0.70710678f);
+ const FloatV eps = FLoad(0.00001f);
+
+ const FloatV invDtp8 = FMul(invDt, p8);
+
+ const FloatV d0 = FLoad(invMassScale0);
+ const FloatV d1 = FLoad(invMassScale1);
+ const FloatV nDom1fV = FNeg(d1);
+ const FloatV angD0 = FLoad(invInertiaScale0);
+ const FloatV angD1 = FLoad(invInertiaScale1);
+
+ const FloatV invMass0_dom0fV = FMul(d0, invMass0);
+ const FloatV invMass1_dom1fV = FMul(nDom1fV, invMass1);
+
+
+ for(PxU32 i=0;i< frictionPatchCount;i++)
+ {
+ const PxU32 contactCount = c.frictionPatchContactCounts[i];
+ if(contactCount == 0)
+ continue;
+
+ const Gu::ContactPoint* contactBase0 = buffer.contacts + c.contactPatches[c.correlationListHeads[i]].start;
+
+ const Vec3V normal = Ps::aos::V3LoadA(contactBase0->normal);
+
+ const FloatV normalLenSq = V3LengthSq(normal);
+ const VecCrossV norCross = V3PrepareCross(normal);
+
+ const FloatV restitution = FLoad(contactBase0->restitution);
+
+ const FloatV norVel = V3SumElems(V3NegMulSub(normal, linVel1, V3Mul(normal, linVel0)));
+ /*const FloatV norVel0 = V3Dot(normal, linVel0);
+ const FloatV norVel1 = V3Dot(normal, linVel1);
+ const FloatV norVel = FSub(norVel0, norVel1);*/
+
+ const FloatV invMassNorLenSq0 = FMul(invMass0_dom0fV, normalLenSq);
+ const FloatV invMassNorLenSq1 = FMul(invMass1_dom1fV, normalLenSq);
+
+
+ SolverContactCoulombHeader* PX_RESTRICT header = reinterpret_cast<SolverContactCoulombHeader*>(ptr);
+ ptr += sizeof(SolverContactCoulombHeader);
+
+ Ps::prefetchLine(ptr, 128);
+ Ps::prefetchLine(ptr, 256);
+ Ps::prefetchLine(ptr, 384);
+
+
+ header->numNormalConstr = PxU8(contactCount);
+ header->type = pointHeaderType;
+ //header->setRestitution(n.restitution);
+ //header->setRestitution(contactBase0->restitution);
+
+ header->setDominance0(invMass0_dom0fV);
+ header->setDominance1(FNeg(invMass1_dom1fV));
+ FStore(angD0, &header->angDom0);
+ FStore(angD1, &header->angDom1);
+ header->setNormal(normal);
+ header->flags = flags;
+ header->shapeInteraction = shapeInteraction;
+
+
+ for(PxU32 patch=c.correlationListHeads[i];
+ patch!=CorrelationBuffer::LIST_END;
+ patch = c.contactPatches[patch].next)
+ {
+ const PxU32 count = c.contactPatches[patch].count;
+ const Gu::ContactPoint* contactBase = buffer.contacts + c.contactPatches[patch].start;
+
+
+ PxU8* p = ptr;
+ for(PxU32 j=0;j<count;j++)
+ {
+ const Gu::ContactPoint& contact = contactBase[j];
+
+ SolverContactPoint* PX_RESTRICT solverContact = reinterpret_cast<SolverContactPoint*>(p);
+ p += pointStride;
+
+ constructContactConstraint(invSqrtInertia0, invSqrtInertia1, invMassNorLenSq0,
+ invMassNorLenSq1, angD0, angD1, bodyFrame0p, bodyFrame1p,
+ normal, norVel, norCross, angVel0, angVel1,
+ invDt, invDtp8, restDistance, maxPenBias, restitution,
+ bounceThreshold, contact, *solverContact, ccdMaxSeparation);
+ }
+ ptr = p;
+ }
+ }
+
+ //construct all the frictions
+
+ PxU8* PX_RESTRICT ptr2 = workspace;
+
+ bool hasFriction = false;
+ for(PxU32 i=0;i< frictionPatchCount;i++)
+ {
+ const PxU32 contactCount = c.frictionPatchContactCounts[i];
+ if(contactCount == 0)
+ continue;
+
+ const Gu::ContactPoint* contactBase0 = buffer.contacts + c.contactPatches[c.correlationListHeads[i]].start;
+
+ SolverContactCoulombHeader* header = reinterpret_cast<SolverContactCoulombHeader*>(ptr2);
+ header->frictionOffset = PxU16(ptr - ptr2);// + sizeof(SolverFrictionHeader);
+ ptr2 += sizeof(SolverContactCoulombHeader) + header->numNormalConstr * pointStride;
+
+ const PxReal staticFriction = contactBase0->staticFriction;
+ const bool disableStrongFriction = !!(contactBase0->materialFlags & PxMaterialFlag::eDISABLE_FRICTION);
+ const bool haveFriction = (disableStrongFriction == 0);
+
+ SolverFrictionHeader* frictionHeader = reinterpret_cast<SolverFrictionHeader*>(ptr);
+ frictionHeader->numNormalConstr = Ps::to8(c.frictionPatchContactCounts[i]);
+ frictionHeader->numFrictionConstr = Ps::to8(haveFriction ? c.frictionPatchContactCounts[i] * frictionPerPointCount : 0);
+ ptr += sizeof(SolverFrictionHeader);
+ PxF32* appliedForceBuffer = reinterpret_cast<PxF32*>(ptr);
+ ptr += frictionHeader->getAppliedForcePaddingSize(c.frictionPatchContactCounts[i]);
+ PxMemZero(appliedForceBuffer, sizeof(PxF32)*contactCount*frictionPerPointCount);
+ Ps::prefetchLine(ptr, 128);
+ Ps::prefetchLine(ptr, 256);
+ Ps::prefetchLine(ptr, 384);
+
+ const Vec3V normal = V3LoadU(buffer.contacts[c.contactPatches[c.correlationListHeads[i]].start].normal);
+
+ const FloatV normalX = V3GetX(normal);
+ const FloatV normalY = V3GetY(normal);
+ const FloatV normalZ = V3GetZ(normal);
+
+ const Vec3V t0Fallback1 = V3Merge(zero, FNeg(normalZ), normalY);
+ const Vec3V t0Fallback2 = V3Merge(FNeg(normalY), normalX, zero) ;
+
+ const BoolV con = FIsGrtr(orthoThreshold, FAbs(normalX));
+ const Vec3V tFallback1 = V3Sel(con, t0Fallback1, t0Fallback2);
+
+ const Vec3V linVrel = V3Sub(linVel0, linVel1);
+ const Vec3V t0_ = V3Sub(linVrel, V3Scale(normal, V3Dot(normal, linVrel)));
+ const FloatV sqDist = V3Dot(t0_,t0_);
+ const BoolV con1 = FIsGrtr(sqDist, eps);
+ const Vec3V tDir0 =V3Normalize(V3Sel(con1, t0_, tFallback1));
+ const Vec3V tDir1 = V3Cross(tDir0, normal);
+
+ Vec3V tFallback = tDir0;
+ Vec3V tFallbackAlt = tDir1;
+
+ if(haveFriction)
+ {
+ //frictionHeader->setStaticFriction(n.staticFriction);
+ frictionHeader->setStaticFriction(staticFriction);
+ FStore(invMass0_dom0fV, &frictionHeader->invMass0D0);
+ FStore(FNeg(invMass1_dom1fV), &frictionHeader->invMass1D1);
+ FStore(angD0, &frictionHeader->angDom0);
+ FStore(angD1, &frictionHeader->angDom1);
+ frictionHeader->type = frictionHeaderType;
+
+ PxU32 totalPatchContactCount = 0;
+
+ for(PxU32 patch=c.correlationListHeads[i];
+ patch!=CorrelationBuffer::LIST_END;
+ patch = c.contactPatches[patch].next)
+ {
+ const PxU32 count = c.contactPatches[patch].count;
+ const PxU32 start = c.contactPatches[patch].start;
+ const Gu::ContactPoint* contactBase = buffer.contacts + start;
+
+ PxU8* p = ptr;
+ for(PxU32 j =0; j < count; j++)
+ {
+ hasFriction = true;
+ const Gu::ContactPoint& contact = contactBase[j];
+ const Vec3V point = V3LoadU(contact.point);
+ const Vec3V ra = V3Sub(point, bodyFrame0p);
+ const Vec3V rb = V3Sub(point, bodyFrame1p);
+ const Vec3V targetVel = V3LoadU(contact.targetVel);
+
+ for(PxU32 k = 0; k < frictionPerPointCount; ++k)
+ {
+ const Vec3V t0 = tFallback;
+ tFallback = tFallbackAlt;
+ tFallbackAlt = t0;
+
+ SolverContactFriction* PX_RESTRICT f0 = reinterpret_cast<SolverContactFriction*>(p);
+ p += frictionStride;
+ //f0->brokenOrContactIndex = contactId;
+
+ const Vec3V raXn = V3Cross(ra, t0);
+ const Vec3V rbXn = V3Cross(rb, t0);
+
+ const Vec3V delAngVel0 = M33MulV3(invSqrtInertia0, raXn);
+ const Vec3V delAngVel1 = M33MulV3(invSqrtInertia1, rbXn);
+
+ const FloatV resp0 = FAdd(invMass0_dom0fV, FMul(angD0, V3Dot(delAngVel0, delAngVel0)));
+ const FloatV resp1 = FSub(FMul(angD1, V3Dot(delAngVel1, delAngVel1)), invMass1_dom1fV);
+ const FloatV resp = FAdd(resp0, resp1);
+
+ const FloatV velMultiplier = FNeg(FSel(FIsGrtr(resp, zero), FRecip(resp), zero));
+
+ const FloatV vrel1 = FAdd(V3Dot(t0, linVel0), V3Dot(raXn, angVel0));
+ const FloatV vrel2 = FAdd(V3Dot(t0, linVel1), V3Dot(rbXn, angVel1));
+ const FloatV vrel = FSub(vrel1, vrel2);
+
+
+ f0->normalXYZ_appliedForceW = V4SetW(Vec4V_From_Vec3V(t0), zero);
+ f0->raXnXYZ_velMultiplierW = V4SetW(Vec4V_From_Vec3V(delAngVel0), velMultiplier);
+ //f0->rbXnXYZ_targetVelocityW = V4SetW(Vec4V_From_Vec3V(delAngVel1), FSub(V3Dot(targetVel, t0), vrel));
+ f0->rbXnXYZ_biasW = Vec4V_From_Vec3V(delAngVel1);
+ FStore(FSub(V3Dot(targetVel, t0), vrel), &f0->targetVel);
+ }
+ }
+
+ totalPatchContactCount += c.contactPatches[patch].count;
+
+ ptr = p;
+ }
+ }
+ }
+ *ptr = 0;
+ return hasFriction;
+}
+
+
+
+static void computeBlockStreamByteSizesCoulomb(const CorrelationBuffer& c,
+ const PxU32 frictionCountPerPoint, PxU32& _solverConstraintByteSize,
+ PxU32& _axisConstraintCount,
+ bool useExtContacts)
+{
+ PX_ASSERT(0 == _solverConstraintByteSize);
+ PX_ASSERT(0 == _axisConstraintCount);
+
+ // PT: use local vars to remove LHS
+ PxU32 solverConstraintByteSize = 0;
+ PxU32 numFrictionPatches = 0;
+ PxU32 axisConstraintCount = 0;
+
+ for(PxU32 i = 0; i < c.frictionPatchCount; i++)
+ {
+ //Friction patches.
+ if(c.correlationListHeads[i] != CorrelationBuffer::LIST_END)
+ numFrictionPatches++;
+
+
+ const FrictionPatch& frictionPatch = c.frictionPatches[i];
+ const bool haveFriction = (frictionPatch.materialFlags & PxMaterialFlag::eDISABLE_FRICTION) == 0;
+
+ //Solver constraint data.
+ if(c.frictionPatchContactCounts[i]!=0)
+ {
+ solverConstraintByteSize += sizeof(SolverContactCoulombHeader);
+
+ solverConstraintByteSize += useExtContacts ? c.frictionPatchContactCounts[i] * sizeof(SolverContactPointExt)
+ : c.frictionPatchContactCounts[i] * sizeof(SolverContactPoint);
+
+ axisConstraintCount += c.frictionPatchContactCounts[i];
+
+ //We always need the friction headers to write the accumulated
+ if(haveFriction)
+ {
+ //4 bytes
+ solverConstraintByteSize += sizeof(SolverFrictionHeader);
+ //buffer to store applied forces in
+ solverConstraintByteSize += SolverFrictionHeader::getAppliedForcePaddingSize(c.frictionPatchContactCounts[i]);
+
+ const PxU32 nbFrictionConstraints = c.frictionPatchContactCounts[i] * frictionCountPerPoint;
+
+ solverConstraintByteSize += useExtContacts ? nbFrictionConstraints * sizeof(SolverContactFrictionExt)
+ : nbFrictionConstraints * sizeof(SolverContactFriction);
+ axisConstraintCount += c.frictionPatchContactCounts[i];
+ }
+ else
+ {
+ //reserve buffers for storing accumulated impulses
+ solverConstraintByteSize += sizeof(SolverFrictionHeader);
+ solverConstraintByteSize += SolverFrictionHeader::getAppliedForcePaddingSize(c.frictionPatchContactCounts[i]);
+ }
+ }
+ }
+ _axisConstraintCount = axisConstraintCount;
+
+ //16-byte alignment.
+ _solverConstraintByteSize = ((solverConstraintByteSize + 0x0f) & ~0x0f);
+ PX_ASSERT(0 == (_solverConstraintByteSize & 0x0f));
+}
+
+static bool reserveBlockStreamsCoulomb(const CorrelationBuffer& c,
+ PxU8*& solverConstraint, PxU32 frictionCountPerPoint,
+ PxU32& solverConstraintByteSize,
+ PxU32& axisConstraintCount, PxConstraintAllocator& constraintAllocator,
+ bool useExtContacts)
+{
+ PX_ASSERT(NULL == solverConstraint);
+ PX_ASSERT(0 == solverConstraintByteSize);
+ PX_ASSERT(0 == axisConstraintCount);
+
+
+ //From constraintBlockStream we need to reserve contact points, contact forces, and a char buffer for the solver constraint data (already have a variable for this).
+ //From frictionPatchStream we just need to reserve a single buffer.
+
+ //Compute the sizes of all the buffers.
+ computeBlockStreamByteSizesCoulomb(
+ c,
+ frictionCountPerPoint, solverConstraintByteSize,
+ axisConstraintCount, useExtContacts);
+
+ //Reserve the buffers.
+
+ //First reserve the accumulated buffer size for the constraint block.
+ PxU8* constraintBlock = NULL;
+ const PxU32 constraintBlockByteSize = solverConstraintByteSize;
+ if(constraintBlockByteSize > 0)
+ {
+ constraintBlock = constraintAllocator.reserveConstraintData(constraintBlockByteSize + 16u);
+
+ if(0==constraintBlock || (reinterpret_cast<PxU8*>(-1))==constraintBlock)
+ {
+ if(0==constraintBlock)
+ {
+ PX_WARN_ONCE(
+ "Reached limit set by PxSceneDesc::maxNbContactDataBlocks - ran out of buffer space for constraint prep. "
+ "Either accept dropped contacts or increase buffer size allocated for narrow phase by increasing PxSceneDesc::maxNbContactDataBlocks.");
+ }
+ else
+ {
+ PX_WARN_ONCE(
+ "Attempting to allocate more than 16K of contact data for a single contact pair in constraint prep. "
+ "Either accept dropped contacts or simplify collision geometry.");
+ constraintBlock=NULL;
+ }
+ }
+ }
+
+ //Patch up the individual ptrs to the buffer returned by the constraint block reservation (assuming the reservation didn't fail).
+ if(0==constraintBlockByteSize || constraintBlock)
+ {
+ if(solverConstraintByteSize)
+ {
+ solverConstraint = constraintBlock;
+ PX_ASSERT(0==(uintptr_t(solverConstraint) & 0x0f));
+ }
+ }
+
+ //Return true if neither of the two block reservations failed.
+ return ((0==constraintBlockByteSize || constraintBlock));
+}
+
+bool createFinalizeSolverContactsCoulomb1D(PxSolverContactDesc& contactDesc,
+ PxsContactManagerOutput& output,
+ ThreadContext& threadContext,
+ const PxReal invDtF32,
+ PxReal bounceThresholdF32,
+ PxReal frictionOffsetThreshold,
+ PxReal correlationDistance,
+ PxConstraintAllocator& constraintAllocator)
+{
+ return createFinalizeSolverContactsCoulomb(contactDesc, output, threadContext, invDtF32, bounceThresholdF32, frictionOffsetThreshold, correlationDistance, constraintAllocator, PxFrictionType::eONE_DIRECTIONAL);
+}
+
+bool createFinalizeSolverContactsCoulomb2D(PxSolverContactDesc& contactDesc,
+ PxsContactManagerOutput& output,
+ ThreadContext& threadContext,
+ const PxReal invDtF32,
+ PxReal bounceThresholdF32,
+ PxReal frictionOffsetThreshold,
+ PxReal correlationDistance,
+ PxConstraintAllocator& constraintAllocator)
+
+{
+ return createFinalizeSolverContactsCoulomb(contactDesc, output, threadContext, invDtF32, bounceThresholdF32, frictionOffsetThreshold, correlationDistance, constraintAllocator, PxFrictionType::eTWO_DIRECTIONAL);
+}
+
+bool createFinalizeSolverContactsCoulomb(PxSolverContactDesc& contactDesc,
+ PxsContactManagerOutput& output,
+ ThreadContext& threadContext,
+ const PxReal invDtF32,
+ PxReal bounceThresholdF32,
+ PxReal frictionOffsetThreshold,
+ PxReal correlationDistance,
+ PxConstraintAllocator& constraintAllocator,
+ PxFrictionType::Enum frictionType)
+{
+ PX_UNUSED(frictionOffsetThreshold);
+ PX_UNUSED(correlationDistance);
+
+ PxSolverConstraintDesc& desc = *contactDesc.desc;
+
+ desc.constraintLengthOver16 = 0;
+
+ ContactBuffer& buffer = threadContext.mContactBuffer;
+
+ buffer.count = 0;
+
+ // We pull the friction patches out of the cache to remove the dependency on how
+ // the cache is organized. Remember original addrs so we can write them back
+ // efficiently.
+
+ Ps::prefetchLine(contactDesc.frictionPtr);
+
+ PxReal invMassScale0 = 1.f;
+ PxReal invMassScale1 = 1.f;
+ PxReal invInertiaScale0 = 1.f;
+ PxReal invInertiaScale1 = 1.f;
+
+ bool hasMaxImpulse = false, hasTargetVelocity = false;
+
+ PxU32 numContacts = extractContacts(buffer, output, hasMaxImpulse, hasTargetVelocity, invMassScale0, invMassScale1,
+ invInertiaScale0, invInertiaScale1, PxMin(contactDesc.data0->maxContactImpulse, contactDesc.data1->maxContactImpulse));
+
+ if(numContacts == 0)
+ {
+ contactDesc.frictionPtr = NULL;
+ contactDesc.frictionCount = 0;
+ return true;
+ }
+
+ Ps::prefetchLine(contactDesc.body0);
+ Ps::prefetchLine(contactDesc.body1);
+ Ps::prefetchLine(contactDesc.data0);
+ Ps::prefetchLine(contactDesc.data1);
+
+ CorrelationBuffer& c = threadContext.mCorrelationBuffer;
+ c.frictionPatchCount = 0;
+ c.contactPatchCount = 0;
+
+ createContactPatches(c, buffer.contacts, buffer.count, PXC_SAME_NORMAL);
+
+ PxU32 numFrictionPerPatch = PxU32(frictionType == PxFrictionType::eONE_DIRECTIONAL ? 1 : 2);
+
+ bool overflow = correlatePatches(c, buffer.contacts, contactDesc.bodyFrame0, contactDesc.bodyFrame1, PXC_SAME_NORMAL, 0, 0);
+ PX_UNUSED(overflow);
+#if PX_CHECKED
+ if(overflow)
+ {
+ Ps::getFoundation().error(physx::PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__,
+ "Dropping contacts in solver because we exceeded limit of 32 friction patches.");
+ }
+#endif
+
+
+ //PX_ASSERT(patchCount == c.frictionPatchCount);
+
+ PxU8* solverConstraint = NULL;
+ PxU32 solverConstraintByteSize = 0;
+ PxU32 axisConstraintCount = 0;
+
+ bool useExtContacts = !!((contactDesc.bodyState0 | contactDesc.bodyState1) & PxSolverContactDesc::eARTICULATION);
+
+ const bool successfulReserve = reserveBlockStreamsCoulomb(
+ c,
+ solverConstraint, numFrictionPerPatch,
+ solverConstraintByteSize,
+ axisConstraintCount,
+ constraintAllocator,
+ useExtContacts);
+
+ // initialise the work unit's ptrs to the various buffers.
+
+ contactDesc.frictionPtr = NULL;
+ desc.constraint = NULL;
+ desc.constraintLengthOver16 = 0;
+ contactDesc.frictionCount = 0;
+
+ // patch up the work unit with the reserved buffers and set the reserved buffer data as appropriate.
+
+ if(successfulReserve)
+ {
+ desc.constraint = solverConstraint;
+ output.nbContacts = Ps::to8(numContacts);
+ desc.constraintLengthOver16 = Ps::to16(solverConstraintByteSize/16);
+
+ //Initialise solverConstraint buffer.
+ if(solverConstraint)
+ {
+ bool hasFriction = false;
+ if(useExtContacts)
+ {
+ const PxSolverBodyData& data0 = *contactDesc.data0;
+ const PxSolverBodyData& data1 = *contactDesc.data1;
+
+ const SolverExtBody b0(reinterpret_cast<const void*>(contactDesc.body0), reinterpret_cast<const void*>(&data0), desc.linkIndexA);
+ const SolverExtBody b1(reinterpret_cast<const void*>(contactDesc.body1), reinterpret_cast<const void*>(&data1), desc.linkIndexB);
+
+ hasFriction = setupFinalizeExtSolverContactsCoulomb(buffer, c, contactDesc.bodyFrame0, contactDesc.bodyFrame1, solverConstraint,
+ invDtF32, bounceThresholdF32, b0, b1, numFrictionPerPatch,
+ invMassScale0, invInertiaScale0, invMassScale1, invInertiaScale1, contactDesc.restDistance, contactDesc.maxCCDSeparation);
+ }
+ else
+ {
+ const PxSolverBodyData& data0 = *contactDesc.data0;
+ const PxSolverBodyData& data1 = *contactDesc.data1;
+
+ hasFriction = setupFinalizeSolverConstraintsCoulomb(contactDesc.shapeInteraction, buffer, c, contactDesc.bodyFrame0, contactDesc.bodyFrame1, solverConstraint,
+ data0, data1, invDtF32, bounceThresholdF32, numFrictionPerPatch, contactDesc.hasForceThresholds, contactDesc.bodyState1 == PxSolverContactDesc::eSTATIC_BODY,
+ invMassScale0, invInertiaScale0, invMassScale1, invInertiaScale1, contactDesc.restDistance, contactDesc.maxCCDSeparation);
+ }
+ *(reinterpret_cast<PxU32*>(solverConstraint + solverConstraintByteSize)) = 0;
+ *(reinterpret_cast<PxU32*>(solverConstraint + solverConstraintByteSize + 4)) = hasFriction ? 0xFFFFFFFF : 0;
+ }
+ }
+
+ return successfulReserve;
+}
+
+}
+}
+
+