From 3dfe2108cfab31ba3ee5527e217d0d8e99a51162 Mon Sep 17 00:00:00 2001 From: git perforce import user Date: Tue, 25 Oct 2016 12:29:14 -0600 Subject: Initial commit: PhysX 3.4.0 Update @ 21294896 APEX 1.4.0 Update @ 21275617 [CL 21300167] --- .../LowLevelDynamics/src/DySolverPFConstraints.cpp | 868 +++++++++++++++++++++ 1 file changed, 868 insertions(+) create mode 100644 PhysX_3.4/Source/LowLevelDynamics/src/DySolverPFConstraints.cpp (limited to 'PhysX_3.4/Source/LowLevelDynamics/src/DySolverPFConstraints.cpp') diff --git a/PhysX_3.4/Source/LowLevelDynamics/src/DySolverPFConstraints.cpp b/PhysX_3.4/Source/LowLevelDynamics/src/DySolverPFConstraints.cpp new file mode 100644 index 00000000..e5eb3328 --- /dev/null +++ b/PhysX_3.4/Source/LowLevelDynamics/src/DySolverPFConstraints.cpp @@ -0,0 +1,868 @@ +// 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" + +#ifdef PX_SUPPORT_SIMD + +#include "CmPhysXCommon.h" +#include "DySolverBody.h" +#include "DySolverContact.h" +#include "DySolverContactPF.h" +#include "DySolverConstraint1D.h" +#include "DySolverConstraintDesc.h" +#include "DyThresholdTable.h" +#include "DySolverContext.h" +#include "PsUtilities.h" +#include "DyConstraint.h" +#include "PsAtomic.h" +#include "DyThresholdTable.h" +#include "DySolverConstraintsShared.h" + +namespace physx +{ + +namespace Dy +{ + +void solveContactCoulomb(const PxSolverConstraintDesc& desc, SolverContext& /*cache*/) +{ + PxSolverBody& b0 = *desc.bodyA; + PxSolverBody& b1 = *desc.bodyB; + + Vec3V linVel0 = V3LoadA(b0.linearVelocity); + Vec3V linVel1 = V3LoadA(b1.linearVelocity); + Vec3V angState0 = V3LoadA(b0.angularState); + Vec3V angState1 = V3LoadA(b1.angularState); + + SolverContactCoulombHeader* PX_RESTRICT firstHeader = reinterpret_cast(desc.constraint); + const PxU8* PX_RESTRICT last = desc.constraint + firstHeader->frictionOffset;//getConstraintLength(desc); + + //hopefully pointer aliasing doesn't bite. + PxU8* PX_RESTRICT currPtr = desc.constraint; + + + //const FloatV zero = FZero(); + + while(currPtr < last) + { + SolverContactCoulombHeader* PX_RESTRICT hdr = reinterpret_cast(currPtr); + currPtr += sizeof(SolverContactCoulombHeader); + + const PxU32 numNormalConstr = hdr->numNormalConstr; + + const Vec3V normal = hdr->getNormal(); + const FloatV invMassDom0 = FLoad(hdr->dominance0); + const FloatV invMassDom1 = FLoad(hdr->dominance1); + const FloatV angD0 = FLoad(hdr->angDom0); + const FloatV angD1 = FLoad(hdr->angDom1); + + + + SolverContactPoint* PX_RESTRICT contacts = reinterpret_cast(currPtr); + currPtr += numNormalConstr * sizeof(SolverContactPoint); + + PxF32* appliedImpulse = reinterpret_cast ((reinterpret_cast(hdr)) + hdr->frictionOffset + sizeof(SolverFrictionHeader)); + Ps::prefetchLine(appliedImpulse); + + solveDynamicContacts(contacts, numNormalConstr, normal, invMassDom0, invMassDom1, + angD0, angD1, linVel0, angState0, linVel1, angState1, appliedImpulse); + } + + // Write back + V3StoreA(linVel0, b0.linearVelocity); + V3StoreA(linVel1, b1.linearVelocity); + V3StoreA(angState0, b0.angularState); + V3StoreA(angState1, b1.angularState); + + PX_ASSERT(currPtr == last); +} + +void solveFriction(const PxSolverConstraintDesc& desc, SolverContext& /*cache*/) +{ + PxSolverBody& b0 = *desc.bodyA; + PxSolverBody& b1 = *desc.bodyB; + + Vec3V linVel0 = V3LoadA(b0.linearVelocity); + Vec3V linVel1 = V3LoadA(b1.linearVelocity); + Vec3V angState0 = V3LoadA(b0.angularState); + Vec3V angState1 = V3LoadA(b1.angularState); + + PxU8* PX_RESTRICT ptr = desc.constraint; + PxU8* PX_RESTRICT currPtr = ptr; + + const PxU8* PX_RESTRICT last = ptr + getConstraintLength(desc); + + + while(currPtr < last) + { + const SolverFrictionHeader* PX_RESTRICT frictionHeader = reinterpret_cast(currPtr); + currPtr += sizeof(SolverFrictionHeader); + PxF32* appliedImpulse = reinterpret_cast(currPtr); + currPtr += frictionHeader->getAppliedForcePaddingSize(); + + SolverContactFriction* PX_RESTRICT frictions = reinterpret_cast(currPtr); + const PxU32 numFrictionConstr = frictionHeader->numFrictionConstr; + const PxU32 numNormalConstr = frictionHeader->numNormalConstr; + + const PxU32 numFrictionPerPoint = numFrictionConstr/numNormalConstr; + + currPtr += numFrictionConstr * sizeof(SolverContactFriction); + const FloatV staticFriction = frictionHeader->getStaticFriction(); + + const FloatV invMass0D0 = FLoad(frictionHeader->invMass0D0); + const FloatV invMass1D1 = FLoad(frictionHeader->invMass1D1); + + + const FloatV angD0 = FLoad(frictionHeader->angDom0); + const FloatV angD1 = FLoad(frictionHeader->angDom1); + + for(PxU32 i=0, j = 0;i(desc.constraint); + const PxU8* PX_RESTRICT last = desc.constraint + firstHeader->frictionOffset;//getConstraintLength(desc); + + //hopefully pointer aliasing doesn't bite. + PxU8* PX_RESTRICT currPtr = desc.constraint; + + //const FloatV zero = FZero(); + + while(currPtr < last) + { + SolverContactCoulombHeader* PX_RESTRICT hdr = reinterpret_cast(currPtr); + currPtr += sizeof(SolverContactCoulombHeader); + + const PxU32 numNormalConstr = hdr->numNormalConstr; + + SolverContactPoint* PX_RESTRICT contacts = reinterpret_cast(currPtr); + Ps::prefetchLine(contacts); + currPtr += numNormalConstr * sizeof(SolverContactPoint); + + PxF32* appliedImpulse = reinterpret_cast ((reinterpret_cast(hdr)) + hdr->frictionOffset + sizeof(SolverFrictionHeader)); + Ps::prefetchLine(appliedImpulse); + + const Vec3V normal = hdr->getNormal(); + + const FloatV invMassDom0 = FLoad(hdr->dominance0); + + const FloatV angD0 = FLoad(hdr->angDom0); + + solveStaticContacts(contacts, numNormalConstr, normal, invMassDom0, + angD0, linVel0, angState0, appliedImpulse); + } + + // Write back + V3StoreA(linVel0, b0.linearVelocity); + V3StoreA(angState0, b0.angularState); + + PX_ASSERT(currPtr == last); +} + +void solveFriction_BStatic(const PxSolverConstraintDesc& desc, SolverContext& /*cache*/) +{ + PxSolverBody& b0 = *desc.bodyA; + + Vec3V linVel0 = V3LoadA(b0.linearVelocity); + Vec3V angState0 = V3LoadA(b0.angularState); + + PxU8* PX_RESTRICT currPtr = desc.constraint; + + const PxU8* PX_RESTRICT last = currPtr + getConstraintLength(desc); + + while(currPtr < last) + { + + const SolverFrictionHeader* PX_RESTRICT frictionHeader = reinterpret_cast(currPtr); + const PxU32 numFrictionConstr = frictionHeader->numFrictionConstr; + const PxU32 numNormalConstr = frictionHeader->numNormalConstr; + const PxU32 numFrictionPerPoint = numFrictionConstr/numNormalConstr; + currPtr +=sizeof(SolverFrictionHeader); + PxF32* appliedImpulse = reinterpret_cast(currPtr); + currPtr +=frictionHeader->getAppliedForcePaddingSize(); + + SolverContactFriction* PX_RESTRICT frictions = reinterpret_cast(currPtr); + currPtr += numFrictionConstr * sizeof(SolverContactFriction); + + const FloatV invMass0 = FLoad(frictionHeader->invMass0D0); + const FloatV angD0 = FLoad(frictionHeader->angDom0); + //const FloatV angD1 = FLoad(frictionHeader->angDom1); + + + const FloatV staticFriction = frictionHeader->getStaticFriction(); + + for(PxU32 i=0, j = 0;i(cPtr); + PxU8* PX_RESTRICT last = desc.constraint + firstHeader->frictionOffset;//getConstraintLength(desc); + while(cPtr < last) + { + const SolverContactCoulombHeader* PX_RESTRICT hdr = reinterpret_cast(cPtr); + cPtr += sizeof(SolverContactCoulombHeader); + + const PxU32 numNormalConstr = hdr->numNormalConstr; + + //if(cPtr < last) + //Ps::prefetchLine(cPtr, 512); + Ps::prefetchLine(cPtr,128); + Ps::prefetchLine(cPtr,256); + Ps::prefetchLine(cPtr,384); + + const PxU32 pointStride = hdr->type == DY_SC_TYPE_EXT_CONTACT ? sizeof(SolverContactPointExt) + : sizeof(SolverContactPoint); + for(PxU32 i=0;i(cPtr); + cPtr += pointStride; + //c->scaledBias = PxMin(c->scaledBias, 0.f); + c->biasedErr = c->unbiasedErr; + } + } + PX_ASSERT(cPtr == last); +} + +void writeBackContactCoulomb(const PxSolverConstraintDesc& desc, SolverContext& cache, + PxSolverBodyData& bd0, PxSolverBodyData& bd1) +{ + + PxReal normalForce = 0.f; + + PxU8* PX_RESTRICT cPtr = desc.constraint; + PxReal* PX_RESTRICT vForceWriteback = reinterpret_cast(desc.writeBack); + const SolverContactCoulombHeader* PX_RESTRICT firstHeader = reinterpret_cast(cPtr); + PxU8* PX_RESTRICT last = desc.constraint + firstHeader->frictionOffset; + + const PxU32 pointStride = firstHeader->type == DY_SC_TYPE_EXT_CONTACT ? sizeof(SolverContactPointExt) + : sizeof(SolverContactPoint); + + bool hasForceThresholds = false; + while(cPtr < last) + { + const SolverContactCoulombHeader* PX_RESTRICT hdr = reinterpret_cast(cPtr); + cPtr += sizeof(SolverContactCoulombHeader); + + PxF32* appliedImpulse = reinterpret_cast (const_cast((reinterpret_cast(hdr)) + hdr->frictionOffset + sizeof(SolverFrictionHeader))); + + hasForceThresholds = hdr->flags & SolverContactHeader::eHAS_FORCE_THRESHOLDS; + + const PxU32 numNormalConstr = hdr->numNormalConstr; + + Ps::prefetchLine(cPtr, 256); + Ps::prefetchLine(cPtr, 384); + + if(vForceWriteback!=NULL) + { + for(PxU32 i=0; i(bd0.reportThreshold, bd1.reportThreshold); + elt.nodeIndexA = bd0.nodeIndex; + elt.nodeIndexB = bd1.nodeIndex; + elt.shapeInteraction = (reinterpret_cast(desc.constraint))->shapeInteraction; + Ps::order(elt.nodeIndexA, elt.nodeIndexB); + PX_ASSERT(elt.nodeIndexA < elt.nodeIndexB); + + PX_ASSERT(cache.mThresholdStreamIndex (cache.mThresholdStreamLength - 4)) + { + //Write back to global buffer + PxI32 threshIndex = physx::shdfnd::atomicAdd(cache.mSharedOutThresholdPairs, PxI32(cache.mThresholdStreamIndex)) - PxI32(cache.mThresholdStreamIndex); + for(PxU32 a = 0; a < cache.mThresholdStreamIndex; ++a) + { + cache.mSharedThresholdStream[a + threshIndex] = cache.mThresholdStream[a]; + } + cache.mThresholdStreamIndex = 0; + } +} + +void solveContactCoulomb_BStaticBlock(const PxSolverConstraintDesc* PX_RESTRICT desc, const PxU32 constraintCount, SolverContext& cache) +{ + for(PxU32 a = 0; a < constraintCount; ++a) + { + solveContactCoulomb_BStatic(desc[a], cache); + } +} + +void solveContactCoulomb_BStaticConcludeBlock(const PxSolverConstraintDesc* PX_RESTRICT desc, const PxU32 constraintCount, SolverContext& cache) +{ + for(PxU32 a = 0; a < constraintCount; ++a) + { + solveContactCoulomb_BStatic(desc[a], cache); + concludeContactCoulomb(desc[a], cache); + } +} + +void solveContactCoulomb_BStaticBlockWriteBack(const PxSolverConstraintDesc* PX_RESTRICT desc, const PxU32 constraintCount, SolverContext& cache) +{ + for(PxU32 a = 0; a < constraintCount; ++a) + { + PxSolverBodyData& bd0 = cache.solverBodyArray[desc[a].bodyADataIndex]; + PxSolverBodyData& bd1 = cache.solverBodyArray[desc[a].bodyBDataIndex]; + solveContactCoulomb_BStatic(desc[a], cache); + writeBackContactCoulomb(desc[a], cache, bd0, bd1); + } + + if(cache.mThresholdStreamIndex > (cache.mThresholdStreamLength - 4)) + { + //Not enough space to write 4 more thresholds back! + //Write back to global buffer + PxI32 threshIndex = physx::shdfnd::atomicAdd(cache.mSharedOutThresholdPairs, PxI32(cache.mThresholdStreamIndex)) - PxI32(cache.mThresholdStreamIndex); + for(PxU32 a = 0; a < cache.mThresholdStreamIndex; ++a) + { + cache.mSharedThresholdStream[a + threshIndex] = cache.mThresholdStream[a]; + } + cache.mThresholdStreamIndex = 0; + } +} + +void solveExtContactCoulomb(const PxSolverConstraintDesc& desc, SolverContext& /*cache*/) +{ + //We'll need this. +// const FloatV zero = FZero(); +// const FloatV one = FOne(); + + Vec3V linVel0, angVel0, linVel1, angVel1; + + if(desc.linkIndexA == PxSolverConstraintDesc::NO_LINK) + { + linVel0 = V3LoadA(desc.bodyA->linearVelocity); + angVel0 = V3LoadA(desc.bodyA->angularState); + } + else + { + Cm::SpatialVectorV v = PxcFsGetVelocity(*desc.articulationA, desc.linkIndexA); + linVel0 = v.linear; + angVel0 = v.angular; + } + + if(desc.linkIndexB == PxSolverConstraintDesc::NO_LINK) + { + linVel1 = V3LoadA(desc.bodyB->linearVelocity); + angVel1 = V3LoadA(desc.bodyB->angularState); + } + else + { + Cm::SpatialVectorV v = PxcFsGetVelocity(*desc.articulationB, desc.linkIndexB); + linVel1 = v.linear; + angVel1 = v.angular; + } + + //const PxU8* PX_RESTRICT last = desc.constraint + desc.constraintLengthOver16*16; + + PxU8* PX_RESTRICT currPtr = desc.constraint; + + const SolverContactCoulombHeader* PX_RESTRICT firstHeader = reinterpret_cast(currPtr); + + const PxU8* PX_RESTRICT last = desc.constraint + firstHeader->frictionOffset; + + //hopefully pointer aliasing doesn't bite. + + Vec3V linImpulse0 = V3Zero(), linImpulse1 = V3Zero(), angImpulse0 = V3Zero(), angImpulse1 = V3Zero(); + + while(currPtr < last) + { + const SolverContactCoulombHeader* PX_RESTRICT hdr = reinterpret_cast(currPtr); + currPtr += sizeof(SolverContactCoulombHeader); + + const PxU32 numNormalConstr = hdr->numNormalConstr; + + PxF32* appliedImpulse = reinterpret_cast(const_cast(((reinterpret_cast(hdr)) + hdr->frictionOffset + sizeof(SolverFrictionHeader)))); + Ps::prefetchLine(appliedImpulse); + + SolverContactPointExt* PX_RESTRICT contacts = reinterpret_cast(currPtr); + Ps::prefetchLine(contacts); + currPtr += numNormalConstr * sizeof(SolverContactPointExt); + + Vec3V li0 = V3Zero(), li1 = V3Zero(), ai0 = V3Zero(), ai1 = V3Zero(); + + const Vec3V normal = hdr->getNormal(); + + solveExtContacts(contacts, numNormalConstr, normal, linVel0, angVel0, linVel1, angVel1, li0, ai0, li1, ai1, appliedImpulse); + + linImpulse0 = V3ScaleAdd(li0, FLoad(hdr->dominance0), linImpulse0); + angImpulse0 = V3ScaleAdd(ai0, FLoad(hdr->angDom0), angImpulse0); + linImpulse1 = V3NegScaleSub(li1, FLoad(hdr->dominance1), linImpulse1); + angImpulse1 = V3NegScaleSub(ai1, FLoad(hdr->angDom1), angImpulse1); + } + + if(desc.linkIndexA == PxSolverConstraintDesc::NO_LINK) + { + V3StoreA(linVel0, desc.bodyA->linearVelocity); + V3StoreA(angVel0, desc.bodyA->angularState); + } + else + PxcFsApplyImpulse(*desc.articulationA, desc.linkIndexA, linImpulse0, angImpulse0); + + if(desc.linkIndexB == PxSolverConstraintDesc::NO_LINK) + { + V3StoreA(linVel1, desc.bodyB->linearVelocity); + V3StoreA(angVel1, desc.bodyB->angularState); + } + else + PxcFsApplyImpulse(*desc.articulationB, desc.linkIndexB, linImpulse1, angImpulse1); + + PX_ASSERT(currPtr == last); +} + +void solveExtFriction(const PxSolverConstraintDesc& desc, SolverContext& /*cache*/) +{ + Vec3V linVel0, angVel0, linVel1, angVel1; + + if(desc.linkIndexA == PxSolverConstraintDesc::NO_LINK) + { + linVel0 = V3LoadA(desc.bodyA->linearVelocity); + angVel0 = V3LoadA(desc.bodyA->angularState); + } + else + { + Cm::SpatialVectorV v = PxcFsGetVelocity(*desc.articulationA, desc.linkIndexA); + linVel0 = v.linear; + angVel0 = v.angular; + } + + if(desc.linkIndexB == PxSolverConstraintDesc::NO_LINK) + { + linVel1 = V3LoadA(desc.bodyB->linearVelocity); + angVel1 = V3LoadA(desc.bodyB->angularState); + } + else + { + Cm::SpatialVectorV v = PxcFsGetVelocity(*desc.articulationB, desc.linkIndexB); + linVel1 = v.linear; + angVel1 = v.angular; + } + + + //hopefully pointer aliasing doesn't bite. + PxU8* PX_RESTRICT currPtr = desc.constraint; + + const PxU8* PX_RESTRICT last = currPtr + desc.constraintLengthOver16*16; + + Vec3V linImpulse0 = V3Zero(), linImpulse1 = V3Zero(), angImpulse0 = V3Zero(), angImpulse1 = V3Zero(); + + while(currPtr < last) + { + + const SolverFrictionHeader* PX_RESTRICT frictionHeader = reinterpret_cast(currPtr); + currPtr += sizeof(SolverFrictionHeader); + PxF32* appliedImpulse = reinterpret_cast(currPtr); + currPtr += frictionHeader->getAppliedForcePaddingSize(); + + SolverContactFrictionExt* PX_RESTRICT frictions = reinterpret_cast(currPtr); + const PxU32 numFrictionConstr = frictionHeader->numFrictionConstr; + + currPtr += numFrictionConstr * sizeof(SolverContactFrictionExt); + const FloatV staticFriction = frictionHeader->getStaticFriction(); + + + Vec3V li0 = V3Zero(), li1 = V3Zero(), ai0 = V3Zero(), ai1 = V3Zero(); + + PxU32 numNormalConstr = frictionHeader->numNormalConstr; + PxU32 nbFrictionsPerPoint = numFrictionConstr/numNormalConstr; + + + + + for(PxU32 i = 0, j = 0; i < numFrictionConstr; j++) + { + for(PxU32 p=0;pinvMass0D0), linImpulse0); + angImpulse0 = V3ScaleAdd(ai0, FLoad(frictionHeader->angDom0), angImpulse0); + linImpulse1 = V3NegScaleSub(li1, FLoad(frictionHeader->invMass1D1), linImpulse1); + angImpulse1 = V3NegScaleSub(ai1, FLoad(frictionHeader->angDom1), angImpulse1); + } + + if(desc.linkIndexA == PxSolverConstraintDesc::NO_LINK) + { + V3StoreA(linVel0, desc.bodyA->linearVelocity); + V3StoreA(angVel0, desc.bodyA->angularState); + } + else + PxcFsApplyImpulse(*desc.articulationA, desc.linkIndexA, linImpulse0, angImpulse0); + + if(desc.linkIndexB == PxSolverConstraintDesc::NO_LINK) + { + V3StoreA(linVel1, desc.bodyB->linearVelocity); + V3StoreA(angVel1, desc.bodyB->angularState); + } + else + PxcFsApplyImpulse(*desc.articulationB, desc.linkIndexB, linImpulse1, angImpulse1); + + PX_ASSERT(currPtr == last); + +} + +void solveExtFrictionBlock(const PxSolverConstraintDesc* PX_RESTRICT desc, const PxU32 constraintCount, SolverContext& cache) +{ + for(PxU32 a = 0; a < constraintCount; ++a) + { + solveExtFriction(desc[a], cache); + } +} + +void solveExtFrictionConcludeBlock(const PxSolverConstraintDesc* PX_RESTRICT desc, const PxU32 constraintCount, SolverContext& cache) +{ + for(PxU32 a = 0; a < constraintCount; ++a) + { + solveExtFriction(desc[a], cache); + } +} + +void solveExtFrictionBlockWriteBack(const PxSolverConstraintDesc* PX_RESTRICT desc, const PxU32 constraintCount, SolverContext& cache) +{ + for(PxU32 a = 0; a < constraintCount; ++a) + { + solveExtFriction(desc[a], cache); + } +} + + +void solveConcludeExtContactCoulomb (const PxSolverConstraintDesc& desc, SolverContext& cache) +{ + solveExtContactCoulomb(desc, cache); + concludeContactCoulomb(desc, cache); +} + +void solveExtContactCoulombBlock(const PxSolverConstraintDesc* PX_RESTRICT desc, const PxU32 constraintCount, SolverContext& cache) +{ + for(PxU32 a = 0; a < constraintCount; ++a) + { + solveExtContactCoulomb(desc[a], cache); + } +} + +void solveExtContactCoulombConcludeBlock(const PxSolverConstraintDesc* PX_RESTRICT desc, const PxU32 constraintCount, SolverContext& cache) +{ + for(PxU32 a = 0; a < constraintCount; ++a) + { + solveExtContactCoulomb(desc[a], cache); + concludeContactCoulomb(desc[a], cache); + } +} + +void solveExtContactCoulombBlockWriteBack(const PxSolverConstraintDesc* PX_RESTRICT desc, const PxU32 constraintCount, SolverContext& cache) +{ + for(PxU32 a = 0; a < constraintCount; ++a) + { + PxSolverBodyData& bd0 = cache.solverBodyArray[desc[a].linkIndexA != PxSolverConstraintDesc::NO_LINK ? 0 : desc[a].bodyADataIndex]; + PxSolverBodyData& bd1 = cache.solverBodyArray[desc[a].linkIndexB != PxSolverConstraintDesc::NO_LINK ? 0 : desc[a].bodyBDataIndex]; + + solveExtContactCoulomb(desc[a], cache); + writeBackContactCoulomb(desc[a], cache, bd0, bd1); + } + if(cache.mThresholdStreamIndex > 0) + { + //Not enough space to write 4 more thresholds back! + //Write back to global buffer + PxI32 threshIndex = physx::shdfnd::atomicAdd(cache.mSharedOutThresholdPairs, PxI32(cache.mThresholdStreamIndex)) - PxI32(cache.mThresholdStreamIndex); + for(PxU32 a = 0; a < cache.mThresholdStreamIndex; ++a) + { + cache.mSharedThresholdStream[a + threshIndex] = cache.mThresholdStream[a]; + } + cache.mThresholdStreamIndex = 0; + } +} + + +void solveConcludeContactCoulomb (const PxSolverConstraintDesc& desc, SolverContext& cache) +{ + solveContactCoulomb(desc, cache); + concludeContactCoulomb(desc, cache); +} + + +void solveConcludeContactCoulomb_BStatic (const PxSolverConstraintDesc& desc, SolverContext& cache) +{ + solveContactCoulomb_BStatic(desc, cache); + concludeContactCoulomb(desc, cache); +} + + + +} + +} + +#endif //PX_SUPPORT_SIMD -- cgit v1.2.3