1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555 |
- /*
- Bullet Continuous Collision Detection and Physics Library
- Copyright (c) 2003-2006 Erwin Coumans https://bulletphysics.org
- This software is provided 'as-is', without any express or implied warranty.
- In no event will the authors be held liable for any damages arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it freely,
- subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
- #include "btSequentialImpulseConstraintSolverMt.h"
- #include "LinearMath/btQuickprof.h"
- #include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
- #include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
- #include "BulletDynamics/Dynamics/btRigidBody.h"
- bool btSequentialImpulseConstraintSolverMt::s_allowNestedParallelForLoops = false; // some task schedulers don't like nested loops
- int btSequentialImpulseConstraintSolverMt::s_minimumContactManifoldsForBatching = 250;
- int btSequentialImpulseConstraintSolverMt::s_minBatchSize = 50;
- int btSequentialImpulseConstraintSolverMt::s_maxBatchSize = 100;
- btBatchedConstraints::BatchingMethod btSequentialImpulseConstraintSolverMt::s_contactBatchingMethod = btBatchedConstraints::BATCHING_METHOD_SPATIAL_GRID_2D;
- btBatchedConstraints::BatchingMethod btSequentialImpulseConstraintSolverMt::s_jointBatchingMethod = btBatchedConstraints::BATCHING_METHOD_SPATIAL_GRID_2D;
- btSequentialImpulseConstraintSolverMt::btSequentialImpulseConstraintSolverMt()
- {
- m_numFrictionDirections = 1;
- m_useBatching = false;
- m_useObsoleteJointConstraints = false;
- }
- btSequentialImpulseConstraintSolverMt::~btSequentialImpulseConstraintSolverMt()
- {
- }
- void btSequentialImpulseConstraintSolverMt::setupBatchedContactConstraints()
- {
- BT_PROFILE("setupBatchedContactConstraints");
- m_batchedContactConstraints.setup(&m_tmpSolverContactConstraintPool,
- m_tmpSolverBodyPool,
- s_contactBatchingMethod,
- s_minBatchSize,
- s_maxBatchSize,
- &m_scratchMemory);
- }
- void btSequentialImpulseConstraintSolverMt::setupBatchedJointConstraints()
- {
- BT_PROFILE("setupBatchedJointConstraints");
- m_batchedJointConstraints.setup(&m_tmpSolverNonContactConstraintPool,
- m_tmpSolverBodyPool,
- s_jointBatchingMethod,
- s_minBatchSize,
- s_maxBatchSize,
- &m_scratchMemory);
- }
- void btSequentialImpulseConstraintSolverMt::internalSetupContactConstraints(int iContactConstraint, const btContactSolverInfo& infoGlobal)
- {
- btSolverConstraint& contactConstraint = m_tmpSolverContactConstraintPool[iContactConstraint];
- btVector3 rel_pos1;
- btVector3 rel_pos2;
- btScalar relaxation;
- int solverBodyIdA = contactConstraint.m_solverBodyIdA;
- int solverBodyIdB = contactConstraint.m_solverBodyIdB;
- btSolverBody* solverBodyA = &m_tmpSolverBodyPool[solverBodyIdA];
- btSolverBody* solverBodyB = &m_tmpSolverBodyPool[solverBodyIdB];
- btRigidBody* colObj0 = solverBodyA->m_originalBody;
- btRigidBody* colObj1 = solverBodyB->m_originalBody;
- btManifoldPoint& cp = *static_cast<btManifoldPoint*>(contactConstraint.m_originalContactPoint);
- const btVector3& pos1 = cp.getPositionWorldOnA();
- const btVector3& pos2 = cp.getPositionWorldOnB();
- rel_pos1 = pos1 - solverBodyA->getWorldTransform().getOrigin();
- rel_pos2 = pos2 - solverBodyB->getWorldTransform().getOrigin();
- btVector3 vel1;
- btVector3 vel2;
- solverBodyA->getVelocityInLocalPointNoDelta(rel_pos1, vel1);
- solverBodyB->getVelocityInLocalPointNoDelta(rel_pos2, vel2);
- btVector3 vel = vel1 - vel2;
- btScalar rel_vel = cp.m_normalWorldOnB.dot(vel);
- setupContactConstraint(contactConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal, relaxation, rel_pos1, rel_pos2);
- // setup rolling friction constraints
- int rollingFrictionIndex = m_rollingFrictionIndexTable[iContactConstraint];
- if (rollingFrictionIndex >= 0)
- {
- btSolverConstraint& spinningFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[rollingFrictionIndex];
- btAssert(spinningFrictionConstraint.m_frictionIndex == iContactConstraint);
- setupTorsionalFrictionConstraint(spinningFrictionConstraint,
- cp.m_normalWorldOnB,
- solverBodyIdA,
- solverBodyIdB,
- cp,
- cp.m_combinedSpinningFriction,
- rel_pos1,
- rel_pos2,
- colObj0,
- colObj1,
- relaxation,
- 0.0f,
- 0.0f);
- btVector3 axis[2];
- btPlaneSpace1(cp.m_normalWorldOnB, axis[0], axis[1]);
- axis[0].normalize();
- axis[1].normalize();
- applyAnisotropicFriction(colObj0, axis[0], btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
- applyAnisotropicFriction(colObj1, axis[0], btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
- applyAnisotropicFriction(colObj0, axis[1], btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
- applyAnisotropicFriction(colObj1, axis[1], btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
- // put the largest axis first
- if (axis[1].length2() > axis[0].length2())
- {
- btSwap(axis[0], axis[1]);
- }
- const btScalar kRollingFrictionThreshold = 0.001f;
- for (int i = 0; i < 2; ++i)
- {
- int iRollingFric = rollingFrictionIndex + 1 + i;
- btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[iRollingFric];
- btAssert(rollingFrictionConstraint.m_frictionIndex == iContactConstraint);
- btVector3 dir = axis[i];
- if (dir.length() > kRollingFrictionThreshold)
- {
- setupTorsionalFrictionConstraint(rollingFrictionConstraint,
- dir,
- solverBodyIdA,
- solverBodyIdB,
- cp,
- cp.m_combinedRollingFriction,
- rel_pos1,
- rel_pos2,
- colObj0,
- colObj1,
- relaxation,
- 0.0f,
- 0.0f);
- }
- else
- {
- rollingFrictionConstraint.m_frictionIndex = -1; // disable constraint
- }
- }
- }
- // setup friction constraints
- // setupFrictionConstraint(solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, desiredVelocity, cfmSlip);
- {
- ///Bullet has several options to set the friction directions
- ///By default, each contact has only a single friction direction that is recomputed automatically very frame
- ///based on the relative linear velocity.
- ///If the relative velocity it zero, it will automatically compute a friction direction.
- ///You can also enable two friction directions, using the SOLVER_USE_2_FRICTION_DIRECTIONS.
- ///In that case, the second friction direction will be orthogonal to both contact normal and first friction direction.
- ///
- ///If you choose SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION, then the friction will be independent from the relative projected velocity.
- ///
- ///The user can manually override the friction directions for certain contacts using a contact callback,
- ///and set the cp.m_lateralFrictionInitialized to true
- ///In that case, you can set the target relative motion in each friction direction (cp.m_contactMotion1 and cp.m_contactMotion2)
- ///this will give a conveyor belt effect
- ///
- btSolverConstraint* frictionConstraint1 = &m_tmpSolverContactFrictionConstraintPool[contactConstraint.m_frictionIndex];
- btAssert(frictionConstraint1->m_frictionIndex == iContactConstraint);
- btSolverConstraint* frictionConstraint2 = NULL;
- if (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)
- {
- frictionConstraint2 = &m_tmpSolverContactFrictionConstraintPool[contactConstraint.m_frictionIndex + 1];
- btAssert(frictionConstraint2->m_frictionIndex == iContactConstraint);
- }
- if (!(infoGlobal.m_solverMode & SOLVER_ENABLE_FRICTION_DIRECTION_CACHING) || !(cp.m_contactPointFlags & BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED))
- {
- cp.m_lateralFrictionDir1 = vel - cp.m_normalWorldOnB * rel_vel;
- btScalar lat_rel_vel = cp.m_lateralFrictionDir1.length2();
- if (!(infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION) && lat_rel_vel > SIMD_EPSILON)
- {
- cp.m_lateralFrictionDir1 *= 1.f / btSqrt(lat_rel_vel);
- applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
- applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
- setupFrictionConstraint(*frictionConstraint1, cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
- if (frictionConstraint2)
- {
- cp.m_lateralFrictionDir2 = cp.m_lateralFrictionDir1.cross(cp.m_normalWorldOnB);
- cp.m_lateralFrictionDir2.normalize(); //??
- applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
- applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
- setupFrictionConstraint(*frictionConstraint2, cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
- }
- }
- else
- {
- btPlaneSpace1(cp.m_normalWorldOnB, cp.m_lateralFrictionDir1, cp.m_lateralFrictionDir2);
- applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
- applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
- setupFrictionConstraint(*frictionConstraint1, cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
- if (frictionConstraint2)
- {
- applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
- applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
- setupFrictionConstraint(*frictionConstraint2, cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
- }
- if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) && (infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION))
- {
- cp.m_contactPointFlags |= BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED;
- }
- }
- }
- else
- {
- setupFrictionConstraint(*frictionConstraint1, cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion1, cp.m_frictionCFM);
- if (frictionConstraint2)
- {
- setupFrictionConstraint(*frictionConstraint2, cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion2, cp.m_frictionCFM);
- }
- }
- }
- setFrictionConstraintImpulse(contactConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal);
- }
- struct SetupContactConstraintsLoop : public btIParallelForBody
- {
- btSequentialImpulseConstraintSolverMt* m_solver;
- const btBatchedConstraints* m_bc;
- const btContactSolverInfo* m_infoGlobal;
- SetupContactConstraintsLoop(btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc, const btContactSolverInfo& infoGlobal)
- {
- m_solver = solver;
- m_bc = bc;
- m_infoGlobal = &infoGlobal;
- }
- void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
- {
- BT_PROFILE("SetupContactConstraintsLoop");
- for (int iBatch = iBegin; iBatch < iEnd; ++iBatch)
- {
- const btBatchedConstraints::Range& batch = m_bc->m_batches[iBatch];
- for (int i = batch.begin; i < batch.end; ++i)
- {
- int iContact = m_bc->m_constraintIndices[i];
- m_solver->internalSetupContactConstraints(iContact, *m_infoGlobal);
- }
- }
- }
- };
- void btSequentialImpulseConstraintSolverMt::setupAllContactConstraints(const btContactSolverInfo& infoGlobal)
- {
- BT_PROFILE("setupAllContactConstraints");
- if (m_useBatching)
- {
- const btBatchedConstraints& batchedCons = m_batchedContactConstraints;
- SetupContactConstraintsLoop loop(this, &batchedCons, infoGlobal);
- for (int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase)
- {
- int iPhase = batchedCons.m_phaseOrder[iiPhase];
- const btBatchedConstraints::Range& phase = batchedCons.m_phases[iPhase];
- int grainSize = 1;
- btParallelFor(phase.begin, phase.end, grainSize, loop);
- }
- }
- else
- {
- for (int i = 0; i < m_tmpSolverContactConstraintPool.size(); ++i)
- {
- internalSetupContactConstraints(i, infoGlobal);
- }
- }
- }
- int btSequentialImpulseConstraintSolverMt::getOrInitSolverBodyThreadsafe(btCollisionObject& body, btScalar timeStep)
- {
- //
- // getOrInitSolverBody is threadsafe only for a single thread per solver (with potentially multiple solvers)
- //
- // getOrInitSolverBodyThreadsafe -- attempts to be fully threadsafe (however may affect determinism)
- //
- int solverBodyId = -1;
- bool isRigidBodyType = btRigidBody::upcast(&body) != NULL;
- if (isRigidBodyType && !body.isStaticOrKinematicObject())
- {
- // dynamic body
- // Dynamic bodies can only be in one island, so it's safe to write to the companionId
- solverBodyId = body.getCompanionId();
- if (solverBodyId < 0)
- {
- m_bodySolverArrayMutex.lock();
- // now that we have the lock, check again
- solverBodyId = body.getCompanionId();
- if (solverBodyId < 0)
- {
- solverBodyId = m_tmpSolverBodyPool.size();
- btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
- initSolverBody(&solverBody, &body, timeStep);
- body.setCompanionId(solverBodyId);
- }
- m_bodySolverArrayMutex.unlock();
- }
- }
- else if (isRigidBodyType && body.isKinematicObject())
- {
- //
- // NOTE: must test for kinematic before static because some kinematic objects also
- // identify as "static"
- //
- // Kinematic bodies can be in multiple islands at once, so it is a
- // race condition to write to them, so we use an alternate method
- // to record the solverBodyId
- int uniqueId = body.getWorldArrayIndex();
- const int INVALID_SOLVER_BODY_ID = -1;
- if (m_kinematicBodyUniqueIdToSolverBodyTable.size() <= uniqueId)
- {
- m_kinematicBodyUniqueIdToSolverBodyTableMutex.lock();
- // now that we have the lock, check again
- if (m_kinematicBodyUniqueIdToSolverBodyTable.size() <= uniqueId)
- {
- m_kinematicBodyUniqueIdToSolverBodyTable.resize(uniqueId + 1, INVALID_SOLVER_BODY_ID);
- }
- m_kinematicBodyUniqueIdToSolverBodyTableMutex.unlock();
- }
- solverBodyId = m_kinematicBodyUniqueIdToSolverBodyTable[uniqueId];
- // if no table entry yet,
- if (INVALID_SOLVER_BODY_ID == solverBodyId)
- {
- // need to acquire both locks
- m_kinematicBodyUniqueIdToSolverBodyTableMutex.lock();
- m_bodySolverArrayMutex.lock();
- // now that we have the lock, check again
- solverBodyId = m_kinematicBodyUniqueIdToSolverBodyTable[uniqueId];
- if (INVALID_SOLVER_BODY_ID == solverBodyId)
- {
- // create a table entry for this body
- solverBodyId = m_tmpSolverBodyPool.size();
- btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
- initSolverBody(&solverBody, &body, timeStep);
- m_kinematicBodyUniqueIdToSolverBodyTable[uniqueId] = solverBodyId;
- }
- m_bodySolverArrayMutex.unlock();
- m_kinematicBodyUniqueIdToSolverBodyTableMutex.unlock();
- }
- }
- else
- {
- // all fixed bodies (inf mass) get mapped to a single solver id
- if (m_fixedBodyId < 0)
- {
- m_bodySolverArrayMutex.lock();
- // now that we have the lock, check again
- if (m_fixedBodyId < 0)
- {
- m_fixedBodyId = m_tmpSolverBodyPool.size();
- btSolverBody& fixedBody = m_tmpSolverBodyPool.expand();
- initSolverBody(&fixedBody, 0, timeStep);
- }
- m_bodySolverArrayMutex.unlock();
- }
- solverBodyId = m_fixedBodyId;
- }
- btAssert(solverBodyId >= 0 && solverBodyId < m_tmpSolverBodyPool.size());
- return solverBodyId;
- }
- void btSequentialImpulseConstraintSolverMt::internalCollectContactManifoldCachedInfo(btContactManifoldCachedInfo* cachedInfoArray, btPersistentManifold** manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal)
- {
- BT_PROFILE("internalCollectContactManifoldCachedInfo");
- for (int i = 0; i < numManifolds; ++i)
- {
- btContactManifoldCachedInfo* cachedInfo = &cachedInfoArray[i];
- btPersistentManifold* manifold = manifoldPtr[i];
- btCollisionObject* colObj0 = (btCollisionObject*)manifold->getBody0();
- btCollisionObject* colObj1 = (btCollisionObject*)manifold->getBody1();
- int solverBodyIdA = getOrInitSolverBodyThreadsafe(*colObj0, infoGlobal.m_timeStep);
- int solverBodyIdB = getOrInitSolverBodyThreadsafe(*colObj1, infoGlobal.m_timeStep);
- cachedInfo->solverBodyIds[0] = solverBodyIdA;
- cachedInfo->solverBodyIds[1] = solverBodyIdB;
- cachedInfo->numTouchingContacts = 0;
- btSolverBody* solverBodyA = &m_tmpSolverBodyPool[solverBodyIdA];
- btSolverBody* solverBodyB = &m_tmpSolverBodyPool[solverBodyIdB];
- // A contact manifold between 2 static object should not exist!
- // check the collision flags of your objects if this assert fires.
- // Incorrectly set collision object flags can degrade performance in various ways.
- btAssert(!m_tmpSolverBodyPool[solverBodyIdA].m_invMass.isZero() || !m_tmpSolverBodyPool[solverBodyIdB].m_invMass.isZero());
- int iContact = 0;
- for (int j = 0; j < manifold->getNumContacts(); j++)
- {
- btManifoldPoint& cp = manifold->getContactPoint(j);
- if (cp.getDistance() <= manifold->getContactProcessingThreshold())
- {
- cachedInfo->contactPoints[iContact] = &cp;
- cachedInfo->contactHasRollingFriction[iContact] = (cp.m_combinedRollingFriction > 0.f);
- iContact++;
- }
- }
- cachedInfo->numTouchingContacts = iContact;
- }
- }
- struct CollectContactManifoldCachedInfoLoop : public btIParallelForBody
- {
- btSequentialImpulseConstraintSolverMt* m_solver;
- btSequentialImpulseConstraintSolverMt::btContactManifoldCachedInfo* m_cachedInfoArray;
- btPersistentManifold** m_manifoldPtr;
- const btContactSolverInfo* m_infoGlobal;
- CollectContactManifoldCachedInfoLoop(btSequentialImpulseConstraintSolverMt* solver, btSequentialImpulseConstraintSolverMt::btContactManifoldCachedInfo* cachedInfoArray, btPersistentManifold** manifoldPtr, const btContactSolverInfo& infoGlobal)
- {
- m_solver = solver;
- m_cachedInfoArray = cachedInfoArray;
- m_manifoldPtr = manifoldPtr;
- m_infoGlobal = &infoGlobal;
- }
- void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
- {
- m_solver->internalCollectContactManifoldCachedInfo(m_cachedInfoArray + iBegin, m_manifoldPtr + iBegin, iEnd - iBegin, *m_infoGlobal);
- }
- };
- void btSequentialImpulseConstraintSolverMt::internalAllocContactConstraints(const btContactManifoldCachedInfo* cachedInfoArray, int numManifolds)
- {
- BT_PROFILE("internalAllocContactConstraints");
- // possibly parallel part
- for (int iManifold = 0; iManifold < numManifolds; ++iManifold)
- {
- const btContactManifoldCachedInfo& cachedInfo = cachedInfoArray[iManifold];
- int contactIndex = cachedInfo.contactIndex;
- int frictionIndex = contactIndex * m_numFrictionDirections;
- int rollingFrictionIndex = cachedInfo.rollingFrictionIndex;
- for (int i = 0; i < cachedInfo.numTouchingContacts; i++)
- {
- btSolverConstraint& contactConstraint = m_tmpSolverContactConstraintPool[contactIndex];
- contactConstraint.m_solverBodyIdA = cachedInfo.solverBodyIds[0];
- contactConstraint.m_solverBodyIdB = cachedInfo.solverBodyIds[1];
- contactConstraint.m_originalContactPoint = cachedInfo.contactPoints[i];
- // allocate the friction constraints
- contactConstraint.m_frictionIndex = frictionIndex;
- for (int iDir = 0; iDir < m_numFrictionDirections; ++iDir)
- {
- btSolverConstraint& frictionConstraint = m_tmpSolverContactFrictionConstraintPool[frictionIndex];
- frictionConstraint.m_frictionIndex = contactIndex;
- frictionIndex++;
- }
- // allocate rolling friction constraints
- if (cachedInfo.contactHasRollingFriction[i])
- {
- m_rollingFrictionIndexTable[contactIndex] = rollingFrictionIndex;
- // allocate 3 (although we may use only 2 sometimes)
- for (int i = 0; i < 3; i++)
- {
- m_tmpSolverContactRollingFrictionConstraintPool[rollingFrictionIndex].m_frictionIndex = contactIndex;
- rollingFrictionIndex++;
- }
- }
- else
- {
- // indicate there is no rolling friction for this contact point
- m_rollingFrictionIndexTable[contactIndex] = -1;
- }
- contactIndex++;
- }
- }
- }
- struct AllocContactConstraintsLoop : public btIParallelForBody
- {
- btSequentialImpulseConstraintSolverMt* m_solver;
- const btSequentialImpulseConstraintSolverMt::btContactManifoldCachedInfo* m_cachedInfoArray;
- AllocContactConstraintsLoop(btSequentialImpulseConstraintSolverMt* solver, btSequentialImpulseConstraintSolverMt::btContactManifoldCachedInfo* cachedInfoArray)
- {
- m_solver = solver;
- m_cachedInfoArray = cachedInfoArray;
- }
- void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
- {
- m_solver->internalAllocContactConstraints(m_cachedInfoArray + iBegin, iEnd - iBegin);
- }
- };
- void btSequentialImpulseConstraintSolverMt::allocAllContactConstraints(btPersistentManifold** manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal)
- {
- BT_PROFILE("allocAllContactConstraints");
- btAlignedObjectArray<btContactManifoldCachedInfo> cachedInfoArray; // = m_manifoldCachedInfoArray;
- cachedInfoArray.resizeNoInitialize(numManifolds);
- if (/* DISABLES CODE */ (false))
- {
- // sequential
- internalCollectContactManifoldCachedInfo(&cachedInfoArray[0], manifoldPtr, numManifolds, infoGlobal);
- }
- else
- {
- // may alter ordering of bodies which affects determinism
- CollectContactManifoldCachedInfoLoop loop(this, &cachedInfoArray[0], manifoldPtr, infoGlobal);
- int grainSize = 200;
- btParallelFor(0, numManifolds, grainSize, loop);
- }
- {
- // serial part
- int numContacts = 0;
- int numRollingFrictionConstraints = 0;
- for (int iManifold = 0; iManifold < numManifolds; ++iManifold)
- {
- btContactManifoldCachedInfo& cachedInfo = cachedInfoArray[iManifold];
- cachedInfo.contactIndex = numContacts;
- cachedInfo.rollingFrictionIndex = numRollingFrictionConstraints;
- numContacts += cachedInfo.numTouchingContacts;
- for (int i = 0; i < cachedInfo.numTouchingContacts; ++i)
- {
- if (cachedInfo.contactHasRollingFriction[i])
- {
- numRollingFrictionConstraints += 3;
- }
- }
- }
- {
- BT_PROFILE("allocPools");
- if (m_tmpSolverContactConstraintPool.capacity() < numContacts)
- {
- // if we need to reallocate, reserve some extra so we don't have to reallocate again next frame
- int extraReserve = numContacts / 16;
- m_tmpSolverContactConstraintPool.reserve(numContacts + extraReserve);
- m_rollingFrictionIndexTable.reserve(numContacts + extraReserve);
- m_tmpSolverContactFrictionConstraintPool.reserve((numContacts + extraReserve) * m_numFrictionDirections);
- m_tmpSolverContactRollingFrictionConstraintPool.reserve(numRollingFrictionConstraints + extraReserve);
- }
- m_tmpSolverContactConstraintPool.resizeNoInitialize(numContacts);
- m_rollingFrictionIndexTable.resizeNoInitialize(numContacts);
- m_tmpSolverContactFrictionConstraintPool.resizeNoInitialize(numContacts * m_numFrictionDirections);
- m_tmpSolverContactRollingFrictionConstraintPool.resizeNoInitialize(numRollingFrictionConstraints);
- }
- }
- {
- AllocContactConstraintsLoop loop(this, &cachedInfoArray[0]);
- int grainSize = 200;
- btParallelFor(0, numManifolds, grainSize, loop);
- }
- }
- void btSequentialImpulseConstraintSolverMt::convertContacts(btPersistentManifold** manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal)
- {
- if (!m_useBatching)
- {
- btSequentialImpulseConstraintSolver::convertContacts(manifoldPtr, numManifolds, infoGlobal);
- return;
- }
- BT_PROFILE("convertContacts");
- if (numManifolds > 0)
- {
- if (m_fixedBodyId < 0)
- {
- m_fixedBodyId = m_tmpSolverBodyPool.size();
- btSolverBody& fixedBody = m_tmpSolverBodyPool.expand();
- initSolverBody(&fixedBody, 0, infoGlobal.m_timeStep);
- }
- allocAllContactConstraints(manifoldPtr, numManifolds, infoGlobal);
- if (m_useBatching)
- {
- setupBatchedContactConstraints();
- }
- setupAllContactConstraints(infoGlobal);
- }
- }
- void btSequentialImpulseConstraintSolverMt::internalInitMultipleJoints(btTypedConstraint** constraints, int iBegin, int iEnd)
- {
- BT_PROFILE("internalInitMultipleJoints");
- for (int i = iBegin; i < iEnd; i++)
- {
- btTypedConstraint* constraint = constraints[i];
- btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
- if (constraint->isEnabled())
- {
- constraint->buildJacobian();
- constraint->internalSetAppliedImpulse(0.0f);
- btJointFeedback* fb = constraint->getJointFeedback();
- if (fb)
- {
- fb->m_appliedForceBodyA.setZero();
- fb->m_appliedTorqueBodyA.setZero();
- fb->m_appliedForceBodyB.setZero();
- fb->m_appliedTorqueBodyB.setZero();
- }
- constraint->getInfo1(&info1);
- }
- else
- {
- info1.m_numConstraintRows = 0;
- info1.nub = 0;
- }
- }
- }
- struct InitJointsLoop : public btIParallelForBody
- {
- btSequentialImpulseConstraintSolverMt* m_solver;
- btTypedConstraint** m_constraints;
- InitJointsLoop(btSequentialImpulseConstraintSolverMt* solver, btTypedConstraint** constraints)
- {
- m_solver = solver;
- m_constraints = constraints;
- }
- void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
- {
- m_solver->internalInitMultipleJoints(m_constraints, iBegin, iEnd);
- }
- };
- void btSequentialImpulseConstraintSolverMt::internalConvertMultipleJoints(const btAlignedObjectArray<JointParams>& jointParamsArray, btTypedConstraint** constraints, int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
- {
- BT_PROFILE("internalConvertMultipleJoints");
- for (int i = iBegin; i < iEnd; ++i)
- {
- const JointParams& jointParams = jointParamsArray[i];
- int currentRow = jointParams.m_solverConstraint;
- if (currentRow != -1)
- {
- const btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
- btAssert(currentRow < m_tmpSolverNonContactConstraintPool.size());
- btAssert(info1.m_numConstraintRows > 0);
- btSolverConstraint* currentConstraintRow = &m_tmpSolverNonContactConstraintPool[currentRow];
- btTypedConstraint* constraint = constraints[i];
- convertJoint(currentConstraintRow, constraint, info1, jointParams.m_solverBodyA, jointParams.m_solverBodyB, infoGlobal);
- }
- }
- }
- struct ConvertJointsLoop : public btIParallelForBody
- {
- btSequentialImpulseConstraintSolverMt* m_solver;
- const btAlignedObjectArray<btSequentialImpulseConstraintSolverMt::JointParams>& m_jointParamsArray;
- btTypedConstraint** m_srcConstraints;
- const btContactSolverInfo& m_infoGlobal;
- ConvertJointsLoop(btSequentialImpulseConstraintSolverMt* solver,
- const btAlignedObjectArray<btSequentialImpulseConstraintSolverMt::JointParams>& jointParamsArray,
- btTypedConstraint** srcConstraints,
- const btContactSolverInfo& infoGlobal) : m_jointParamsArray(jointParamsArray),
- m_infoGlobal(infoGlobal)
- {
- m_solver = solver;
- m_srcConstraints = srcConstraints;
- }
- void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
- {
- m_solver->internalConvertMultipleJoints(m_jointParamsArray, m_srcConstraints, iBegin, iEnd, m_infoGlobal);
- }
- };
- void btSequentialImpulseConstraintSolverMt::convertJoints(btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal)
- {
- if (!m_useBatching)
- {
- btSequentialImpulseConstraintSolver::convertJoints(constraints, numConstraints, infoGlobal);
- return;
- }
- BT_PROFILE("convertJoints");
- bool parallelJointSetup = true;
- m_tmpConstraintSizesPool.resizeNoInitialize(numConstraints);
- if (parallelJointSetup)
- {
- InitJointsLoop loop(this, constraints);
- int grainSize = 40;
- btParallelFor(0, numConstraints, grainSize, loop);
- }
- else
- {
- internalInitMultipleJoints(constraints, 0, numConstraints);
- }
- int totalNumRows = 0;
- btAlignedObjectArray<JointParams> jointParamsArray;
- jointParamsArray.resizeNoInitialize(numConstraints);
- //calculate the total number of contraint rows
- for (int i = 0; i < numConstraints; i++)
- {
- btTypedConstraint* constraint = constraints[i];
- JointParams& params = jointParamsArray[i];
- const btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
- if (info1.m_numConstraintRows)
- {
- params.m_solverConstraint = totalNumRows;
- params.m_solverBodyA = getOrInitSolverBody(constraint->getRigidBodyA(), infoGlobal.m_timeStep);
- params.m_solverBodyB = getOrInitSolverBody(constraint->getRigidBodyB(), infoGlobal.m_timeStep);
- }
- else
- {
- params.m_solverConstraint = -1;
- }
- totalNumRows += info1.m_numConstraintRows;
- }
- m_tmpSolverNonContactConstraintPool.resizeNoInitialize(totalNumRows);
- ///setup the btSolverConstraints
- if (parallelJointSetup)
- {
- ConvertJointsLoop loop(this, jointParamsArray, constraints, infoGlobal);
- int grainSize = 20;
- btParallelFor(0, numConstraints, grainSize, loop);
- }
- else
- {
- internalConvertMultipleJoints(jointParamsArray, constraints, 0, numConstraints, infoGlobal);
- }
- setupBatchedJointConstraints();
- }
- void btSequentialImpulseConstraintSolverMt::internalConvertBodies(btCollisionObject** bodies, int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
- {
- BT_PROFILE("internalConvertBodies");
- for (int i = iBegin; i < iEnd; i++)
- {
- btCollisionObject* obj = bodies[i];
- obj->setCompanionId(i);
- btSolverBody& solverBody = m_tmpSolverBodyPool[i];
- initSolverBody(&solverBody, obj, infoGlobal.m_timeStep);
- btRigidBody* body = btRigidBody::upcast(obj);
- if (body && body->getInvMass())
- {
- btVector3 gyroForce(0, 0, 0);
- if (body->getFlags() & BT_ENABLE_GYROSCOPIC_FORCE_EXPLICIT)
- {
- gyroForce = body->computeGyroscopicForceExplicit(infoGlobal.m_maxGyroscopicForce);
- solverBody.m_externalTorqueImpulse -= gyroForce * body->getInvInertiaTensorWorld() * infoGlobal.m_timeStep;
- }
- if (body->getFlags() & BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_WORLD)
- {
- gyroForce = body->computeGyroscopicImpulseImplicit_World(infoGlobal.m_timeStep);
- solverBody.m_externalTorqueImpulse += gyroForce;
- }
- if (body->getFlags() & BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_BODY)
- {
- gyroForce = body->computeGyroscopicImpulseImplicit_Body(infoGlobal.m_timeStep);
- solverBody.m_externalTorqueImpulse += gyroForce;
- }
- }
- }
- }
- struct ConvertBodiesLoop : public btIParallelForBody
- {
- btSequentialImpulseConstraintSolverMt* m_solver;
- btCollisionObject** m_bodies;
- int m_numBodies;
- const btContactSolverInfo& m_infoGlobal;
- ConvertBodiesLoop(btSequentialImpulseConstraintSolverMt* solver,
- btCollisionObject** bodies,
- int numBodies,
- const btContactSolverInfo& infoGlobal) : m_infoGlobal(infoGlobal)
- {
- m_solver = solver;
- m_bodies = bodies;
- m_numBodies = numBodies;
- }
- void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
- {
- m_solver->internalConvertBodies(m_bodies, iBegin, iEnd, m_infoGlobal);
- }
- };
- void btSequentialImpulseConstraintSolverMt::convertBodies(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal)
- {
- BT_PROFILE("convertBodies");
- m_kinematicBodyUniqueIdToSolverBodyTable.resize(0);
- m_tmpSolverBodyPool.resizeNoInitialize(numBodies + 1);
- m_fixedBodyId = numBodies;
- {
- btSolverBody& fixedBody = m_tmpSolverBodyPool[m_fixedBodyId];
- initSolverBody(&fixedBody, NULL, infoGlobal.m_timeStep);
- }
- bool parallelBodySetup = true;
- if (parallelBodySetup)
- {
- ConvertBodiesLoop loop(this, bodies, numBodies, infoGlobal);
- int grainSize = 40;
- btParallelFor(0, numBodies, grainSize, loop);
- }
- else
- {
- internalConvertBodies(bodies, 0, numBodies, infoGlobal);
- }
- }
- btScalar btSequentialImpulseConstraintSolverMt::solveGroupCacheFriendlySetup(
- btCollisionObject** bodies,
- int numBodies,
- btPersistentManifold** manifoldPtr,
- int numManifolds,
- btTypedConstraint** constraints,
- int numConstraints,
- const btContactSolverInfo& infoGlobal,
- btIDebugDraw* debugDrawer)
- {
- m_numFrictionDirections = (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) ? 2 : 1;
- m_useBatching = false;
- if (numManifolds >= s_minimumContactManifoldsForBatching &&
- (s_allowNestedParallelForLoops || !btThreadsAreRunning()))
- {
- m_useBatching = true;
- m_batchedContactConstraints.m_debugDrawer = debugDrawer;
- m_batchedJointConstraints.m_debugDrawer = debugDrawer;
- }
- btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(bodies,
- numBodies,
- manifoldPtr,
- numManifolds,
- constraints,
- numConstraints,
- infoGlobal,
- debugDrawer);
- return 0.0f;
- }
- btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactSplitPenetrationImpulseConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd)
- {
- btScalar leastSquaresResidual = 0.f;
- for (int iiCons = batchBegin; iiCons < batchEnd; ++iiCons)
- {
- int iCons = consIndices[iiCons];
- const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[iCons];
- btSolverBody& bodyA = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA];
- btSolverBody& bodyB = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB];
- btScalar residual = resolveSplitPenetrationImpulse(bodyA, bodyB, solveManifold);
- leastSquaresResidual += residual * residual;
- }
- return leastSquaresResidual;
- }
- struct ContactSplitPenetrationImpulseSolverLoop : public btIParallelSumBody
- {
- btSequentialImpulseConstraintSolverMt* m_solver;
- const btBatchedConstraints* m_bc;
- ContactSplitPenetrationImpulseSolverLoop(btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc)
- {
- m_solver = solver;
- m_bc = bc;
- }
- btScalar sumLoop(int iBegin, int iEnd) const BT_OVERRIDE
- {
- BT_PROFILE("ContactSplitPenetrationImpulseSolverLoop");
- btScalar sum = 0;
- for (int iBatch = iBegin; iBatch < iEnd; ++iBatch)
- {
- const btBatchedConstraints::Range& batch = m_bc->m_batches[iBatch];
- sum += m_solver->resolveMultipleContactSplitPenetrationImpulseConstraints(m_bc->m_constraintIndices, batch.begin, batch.end);
- }
- return sum;
- }
- };
- void btSequentialImpulseConstraintSolverMt::solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
- {
- BT_PROFILE("solveGroupCacheFriendlySplitImpulseIterations");
- if (infoGlobal.m_splitImpulse)
- {
- for (int iteration = 0; iteration < infoGlobal.m_numIterations; iteration++)
- {
- btScalar leastSquaresResidual = 0.f;
- if (m_useBatching)
- {
- const btBatchedConstraints& batchedCons = m_batchedContactConstraints;
- ContactSplitPenetrationImpulseSolverLoop loop(this, &batchedCons);
- btScalar leastSquaresResidual = 0.f;
- for (int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase)
- {
- int iPhase = batchedCons.m_phaseOrder[iiPhase];
- const btBatchedConstraints::Range& phase = batchedCons.m_phases[iPhase];
- int grainSize = batchedCons.m_phaseGrainSize[iPhase];
- leastSquaresResidual += btParallelSum(phase.begin, phase.end, grainSize, loop);
- }
- }
- else
- {
- // non-batched
- leastSquaresResidual = resolveMultipleContactSplitPenetrationImpulseConstraints(m_orderTmpConstraintPool, 0, m_tmpSolverContactConstraintPool.size());
- }
- if (leastSquaresResidual <= infoGlobal.m_leastSquaresResidualThreshold || iteration >= (infoGlobal.m_numIterations - 1))
- {
- #ifdef VERBOSE_RESIDUAL_PRINTF
- printf("residual = %f at iteration #%d\n", leastSquaresResidual, iteration);
- #endif
- break;
- }
- }
- }
- }
- btScalar btSequentialImpulseConstraintSolverMt::solveSingleIteration(int iteration, btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
- {
- if (!m_useBatching)
- {
- return btSequentialImpulseConstraintSolver::solveSingleIteration(iteration, bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
- }
- BT_PROFILE("solveSingleIterationMt");
- btScalar leastSquaresResidual = 0.f;
- if (infoGlobal.m_solverMode & SOLVER_RANDMIZE_ORDER)
- {
- if (1) // uncomment this for a bit less random ((iteration & 7) == 0)
- {
- randomizeConstraintOrdering(iteration, infoGlobal.m_numIterations);
- }
- }
- {
- ///solve all joint constraints
- leastSquaresResidual += resolveAllJointConstraints(iteration);
- if (iteration < infoGlobal.m_numIterations)
- {
- // this loop is only used for cone-twist constraints,
- // it would be nice to skip this loop if none of the constraints need it
- if (m_useObsoleteJointConstraints)
- {
- for (int j = 0; j < numConstraints; j++)
- {
- if (constraints[j]->isEnabled())
- {
- int bodyAid = getOrInitSolverBody(constraints[j]->getRigidBodyA(), infoGlobal.m_timeStep);
- int bodyBid = getOrInitSolverBody(constraints[j]->getRigidBodyB(), infoGlobal.m_timeStep);
- btSolverBody& bodyA = m_tmpSolverBodyPool[bodyAid];
- btSolverBody& bodyB = m_tmpSolverBodyPool[bodyBid];
- constraints[j]->solveConstraintObsolete(bodyA, bodyB, infoGlobal.m_timeStep);
- }
- }
- }
- if (infoGlobal.m_solverMode & SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS)
- {
- // solve all contact, contact-friction, and rolling friction constraints interleaved
- leastSquaresResidual += resolveAllContactConstraintsInterleaved();
- }
- else //SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS
- {
- // don't interleave them
- // solve all contact constraints
- leastSquaresResidual += resolveAllContactConstraints();
- // solve all contact friction constraints
- leastSquaresResidual += resolveAllContactFrictionConstraints();
- // solve all rolling friction constraints
- leastSquaresResidual += resolveAllRollingFrictionConstraints();
- }
- }
- }
- return leastSquaresResidual;
- }
- btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleJointConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd, int iteration)
- {
- btScalar leastSquaresResidual = 0.f;
- for (int iiCons = batchBegin; iiCons < batchEnd; ++iiCons)
- {
- int iCons = consIndices[iiCons];
- const btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[iCons];
- if (iteration < constraint.m_overrideNumSolverIterations)
- {
- btSolverBody& bodyA = m_tmpSolverBodyPool[constraint.m_solverBodyIdA];
- btSolverBody& bodyB = m_tmpSolverBodyPool[constraint.m_solverBodyIdB];
- btScalar residual = resolveSingleConstraintRowGeneric(bodyA, bodyB, constraint);
- leastSquaresResidual += residual * residual;
- }
- }
- return leastSquaresResidual;
- }
- btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd)
- {
- btScalar leastSquaresResidual = 0.f;
- for (int iiCons = batchBegin; iiCons < batchEnd; ++iiCons)
- {
- int iCons = consIndices[iiCons];
- const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[iCons];
- btSolverBody& bodyA = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA];
- btSolverBody& bodyB = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB];
- btScalar residual = resolveSingleConstraintRowLowerLimit(bodyA, bodyB, solveManifold);
- leastSquaresResidual += residual * residual;
- }
- return leastSquaresResidual;
- }
- btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactFrictionConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd)
- {
- btScalar leastSquaresResidual = 0.f;
- for (int iiCons = batchBegin; iiCons < batchEnd; ++iiCons)
- {
- int iContact = consIndices[iiCons];
- btScalar totalImpulse = m_tmpSolverContactConstraintPool[iContact].m_appliedImpulse;
- // apply sliding friction
- if (totalImpulse > 0.0f)
- {
- int iBegin = iContact * m_numFrictionDirections;
- int iEnd = iBegin + m_numFrictionDirections;
- for (int iFriction = iBegin; iFriction < iEnd; ++iFriction)
- {
- btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[iFriction++];
- btAssert(solveManifold.m_frictionIndex == iContact);
- solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
- solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
- btSolverBody& bodyA = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA];
- btSolverBody& bodyB = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB];
- btScalar residual = resolveSingleConstraintRowGeneric(bodyA, bodyB, solveManifold);
- leastSquaresResidual += residual * residual;
- }
- }
- }
- return leastSquaresResidual;
- }
- btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactRollingFrictionConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd)
- {
- btScalar leastSquaresResidual = 0.f;
- for (int iiCons = batchBegin; iiCons < batchEnd; ++iiCons)
- {
- int iContact = consIndices[iiCons];
- int iFirstRollingFriction = m_rollingFrictionIndexTable[iContact];
- if (iFirstRollingFriction >= 0)
- {
- btScalar totalImpulse = m_tmpSolverContactConstraintPool[iContact].m_appliedImpulse;
- // apply rolling friction
- if (totalImpulse > 0.0f)
- {
- int iBegin = iFirstRollingFriction;
- int iEnd = iBegin + 3;
- for (int iRollingFric = iBegin; iRollingFric < iEnd; ++iRollingFric)
- {
- btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[iRollingFric];
- if (rollingFrictionConstraint.m_frictionIndex != iContact)
- {
- break;
- }
- btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction * totalImpulse;
- if (rollingFrictionMagnitude > rollingFrictionConstraint.m_friction)
- {
- rollingFrictionMagnitude = rollingFrictionConstraint.m_friction;
- }
- rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
- rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
- btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA], m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB], rollingFrictionConstraint);
- leastSquaresResidual += residual * residual;
- }
- }
- }
- }
- return leastSquaresResidual;
- }
- btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactConstraintsInterleaved(const btAlignedObjectArray<int>& contactIndices,
- int batchBegin,
- int batchEnd)
- {
- btScalar leastSquaresResidual = 0.f;
- int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
- for (int iiCons = batchBegin; iiCons < batchEnd; iiCons++)
- {
- btScalar totalImpulse = 0;
- int iContact = contactIndices[iiCons];
- // apply penetration constraint
- {
- const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[iContact];
- btScalar residual = resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
- leastSquaresResidual += residual * residual;
- totalImpulse = solveManifold.m_appliedImpulse;
- }
- // apply sliding friction
- if (totalImpulse > 0.0f)
- {
- int iBegin = iContact * m_numFrictionDirections;
- int iEnd = iBegin + m_numFrictionDirections;
- for (int iFriction = iBegin; iFriction < iEnd; ++iFriction)
- {
- btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[iFriction];
- btAssert(solveManifold.m_frictionIndex == iContact);
- solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
- solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
- btSolverBody& bodyA = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA];
- btSolverBody& bodyB = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB];
- btScalar residual = resolveSingleConstraintRowGeneric(bodyA, bodyB, solveManifold);
- leastSquaresResidual += residual * residual;
- }
- }
- // apply rolling friction
- int iFirstRollingFriction = m_rollingFrictionIndexTable[iContact];
- if (totalImpulse > 0.0f && iFirstRollingFriction >= 0)
- {
- int iBegin = iFirstRollingFriction;
- int iEnd = iBegin + 3;
- for (int iRollingFric = iBegin; iRollingFric < iEnd; ++iRollingFric)
- {
- btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[iRollingFric];
- if (rollingFrictionConstraint.m_frictionIndex != iContact)
- {
- break;
- }
- btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction * totalImpulse;
- if (rollingFrictionMagnitude > rollingFrictionConstraint.m_friction)
- {
- rollingFrictionMagnitude = rollingFrictionConstraint.m_friction;
- }
- rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
- rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
- btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA], m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB], rollingFrictionConstraint);
- leastSquaresResidual += residual * residual;
- }
- }
- }
- return leastSquaresResidual;
- }
- void btSequentialImpulseConstraintSolverMt::randomizeBatchedConstraintOrdering(btBatchedConstraints* batchedConstraints)
- {
- btBatchedConstraints& bc = *batchedConstraints;
- // randomize ordering of phases
- for (int ii = 1; ii < bc.m_phaseOrder.size(); ++ii)
- {
- int iSwap = btRandInt2(ii + 1);
- bc.m_phaseOrder.swap(ii, iSwap);
- }
- // for each batch,
- for (int iBatch = 0; iBatch < bc.m_batches.size(); ++iBatch)
- {
- // randomize ordering of constraints within the batch
- const btBatchedConstraints::Range& batch = bc.m_batches[iBatch];
- for (int iiCons = batch.begin; iiCons < batch.end; ++iiCons)
- {
- int iSwap = batch.begin + btRandInt2(iiCons - batch.begin + 1);
- btAssert(iSwap >= batch.begin && iSwap < batch.end);
- bc.m_constraintIndices.swap(iiCons, iSwap);
- }
- }
- }
- void btSequentialImpulseConstraintSolverMt::randomizeConstraintOrdering(int iteration, int numIterations)
- {
- // randomize ordering of joint constraints
- randomizeBatchedConstraintOrdering(&m_batchedJointConstraints);
- //contact/friction constraints are not solved more than numIterations
- if (iteration < numIterations)
- {
- randomizeBatchedConstraintOrdering(&m_batchedContactConstraints);
- }
- }
- struct JointSolverLoop : public btIParallelSumBody
- {
- btSequentialImpulseConstraintSolverMt* m_solver;
- const btBatchedConstraints* m_bc;
- int m_iteration;
- JointSolverLoop(btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc, int iteration)
- {
- m_solver = solver;
- m_bc = bc;
- m_iteration = iteration;
- }
- btScalar sumLoop(int iBegin, int iEnd) const BT_OVERRIDE
- {
- BT_PROFILE("JointSolverLoop");
- btScalar sum = 0;
- for (int iBatch = iBegin; iBatch < iEnd; ++iBatch)
- {
- const btBatchedConstraints::Range& batch = m_bc->m_batches[iBatch];
- sum += m_solver->resolveMultipleJointConstraints(m_bc->m_constraintIndices, batch.begin, batch.end, m_iteration);
- }
- return sum;
- }
- };
- btScalar btSequentialImpulseConstraintSolverMt::resolveAllJointConstraints(int iteration)
- {
- BT_PROFILE("resolveAllJointConstraints");
- const btBatchedConstraints& batchedCons = m_batchedJointConstraints;
- JointSolverLoop loop(this, &batchedCons, iteration);
- btScalar leastSquaresResidual = 0.f;
- for (int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase)
- {
- int iPhase = batchedCons.m_phaseOrder[iiPhase];
- const btBatchedConstraints::Range& phase = batchedCons.m_phases[iPhase];
- int grainSize = 1;
- leastSquaresResidual += btParallelSum(phase.begin, phase.end, grainSize, loop);
- }
- return leastSquaresResidual;
- }
- struct ContactSolverLoop : public btIParallelSumBody
- {
- btSequentialImpulseConstraintSolverMt* m_solver;
- const btBatchedConstraints* m_bc;
- ContactSolverLoop(btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc)
- {
- m_solver = solver;
- m_bc = bc;
- }
- btScalar sumLoop(int iBegin, int iEnd) const BT_OVERRIDE
- {
- BT_PROFILE("ContactSolverLoop");
- btScalar sum = 0;
- for (int iBatch = iBegin; iBatch < iEnd; ++iBatch)
- {
- const btBatchedConstraints::Range& batch = m_bc->m_batches[iBatch];
- sum += m_solver->resolveMultipleContactConstraints(m_bc->m_constraintIndices, batch.begin, batch.end);
- }
- return sum;
- }
- };
- btScalar btSequentialImpulseConstraintSolverMt::resolveAllContactConstraints()
- {
- BT_PROFILE("resolveAllContactConstraints");
- const btBatchedConstraints& batchedCons = m_batchedContactConstraints;
- ContactSolverLoop loop(this, &batchedCons);
- btScalar leastSquaresResidual = 0.f;
- for (int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase)
- {
- int iPhase = batchedCons.m_phaseOrder[iiPhase];
- const btBatchedConstraints::Range& phase = batchedCons.m_phases[iPhase];
- int grainSize = batchedCons.m_phaseGrainSize[iPhase];
- leastSquaresResidual += btParallelSum(phase.begin, phase.end, grainSize, loop);
- }
- return leastSquaresResidual;
- }
- struct ContactFrictionSolverLoop : public btIParallelSumBody
- {
- btSequentialImpulseConstraintSolverMt* m_solver;
- const btBatchedConstraints* m_bc;
- ContactFrictionSolverLoop(btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc)
- {
- m_solver = solver;
- m_bc = bc;
- }
- btScalar sumLoop(int iBegin, int iEnd) const BT_OVERRIDE
- {
- BT_PROFILE("ContactFrictionSolverLoop");
- btScalar sum = 0;
- for (int iBatch = iBegin; iBatch < iEnd; ++iBatch)
- {
- const btBatchedConstraints::Range& batch = m_bc->m_batches[iBatch];
- sum += m_solver->resolveMultipleContactFrictionConstraints(m_bc->m_constraintIndices, batch.begin, batch.end);
- }
- return sum;
- }
- };
- btScalar btSequentialImpulseConstraintSolverMt::resolveAllContactFrictionConstraints()
- {
- BT_PROFILE("resolveAllContactFrictionConstraints");
- const btBatchedConstraints& batchedCons = m_batchedContactConstraints;
- ContactFrictionSolverLoop loop(this, &batchedCons);
- btScalar leastSquaresResidual = 0.f;
- for (int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase)
- {
- int iPhase = batchedCons.m_phaseOrder[iiPhase];
- const btBatchedConstraints::Range& phase = batchedCons.m_phases[iPhase];
- int grainSize = batchedCons.m_phaseGrainSize[iPhase];
- leastSquaresResidual += btParallelSum(phase.begin, phase.end, grainSize, loop);
- }
- return leastSquaresResidual;
- }
- struct InterleavedContactSolverLoop : public btIParallelSumBody
- {
- btSequentialImpulseConstraintSolverMt* m_solver;
- const btBatchedConstraints* m_bc;
- InterleavedContactSolverLoop(btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc)
- {
- m_solver = solver;
- m_bc = bc;
- }
- btScalar sumLoop(int iBegin, int iEnd) const BT_OVERRIDE
- {
- BT_PROFILE("InterleavedContactSolverLoop");
- btScalar sum = 0;
- for (int iBatch = iBegin; iBatch < iEnd; ++iBatch)
- {
- const btBatchedConstraints::Range& batch = m_bc->m_batches[iBatch];
- sum += m_solver->resolveMultipleContactConstraintsInterleaved(m_bc->m_constraintIndices, batch.begin, batch.end);
- }
- return sum;
- }
- };
- btScalar btSequentialImpulseConstraintSolverMt::resolveAllContactConstraintsInterleaved()
- {
- BT_PROFILE("resolveAllContactConstraintsInterleaved");
- const btBatchedConstraints& batchedCons = m_batchedContactConstraints;
- InterleavedContactSolverLoop loop(this, &batchedCons);
- btScalar leastSquaresResidual = 0.f;
- for (int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase)
- {
- int iPhase = batchedCons.m_phaseOrder[iiPhase];
- const btBatchedConstraints::Range& phase = batchedCons.m_phases[iPhase];
- int grainSize = 1;
- leastSquaresResidual += btParallelSum(phase.begin, phase.end, grainSize, loop);
- }
- return leastSquaresResidual;
- }
- struct ContactRollingFrictionSolverLoop : public btIParallelSumBody
- {
- btSequentialImpulseConstraintSolverMt* m_solver;
- const btBatchedConstraints* m_bc;
- ContactRollingFrictionSolverLoop(btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc)
- {
- m_solver = solver;
- m_bc = bc;
- }
- btScalar sumLoop(int iBegin, int iEnd) const BT_OVERRIDE
- {
- BT_PROFILE("ContactFrictionSolverLoop");
- btScalar sum = 0;
- for (int iBatch = iBegin; iBatch < iEnd; ++iBatch)
- {
- const btBatchedConstraints::Range& batch = m_bc->m_batches[iBatch];
- sum += m_solver->resolveMultipleContactRollingFrictionConstraints(m_bc->m_constraintIndices, batch.begin, batch.end);
- }
- return sum;
- }
- };
- btScalar btSequentialImpulseConstraintSolverMt::resolveAllRollingFrictionConstraints()
- {
- BT_PROFILE("resolveAllRollingFrictionConstraints");
- btScalar leastSquaresResidual = 0.f;
- //
- // We do not generate batches for rolling friction constraints. We assume that
- // one of two cases is true:
- //
- // 1. either most bodies in the simulation have rolling friction, in which case we can use the
- // batches for contacts and use a lookup table to translate contact indices to rolling friction
- // (ignoring any contact indices that don't map to a rolling friction constraint). As long as
- // most contacts have a corresponding rolling friction constraint, this should parallelize well.
- //
- // -OR-
- //
- // 2. few bodies in the simulation have rolling friction, so it is not worth trying to use the
- // batches from contacts as most of the contacts won't have corresponding rolling friction
- // constraints and most threads would end up doing very little work. Most of the time would
- // go to threading overhead, so we don't bother with threading.
- //
- int numRollingFrictionPoolConstraints = m_tmpSolverContactRollingFrictionConstraintPool.size();
- if (numRollingFrictionPoolConstraints >= m_tmpSolverContactConstraintPool.size())
- {
- // use batching if there are many rolling friction constraints
- const btBatchedConstraints& batchedCons = m_batchedContactConstraints;
- ContactRollingFrictionSolverLoop loop(this, &batchedCons);
- btScalar leastSquaresResidual = 0.f;
- for (int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase)
- {
- int iPhase = batchedCons.m_phaseOrder[iiPhase];
- const btBatchedConstraints::Range& phase = batchedCons.m_phases[iPhase];
- int grainSize = 1;
- leastSquaresResidual += btParallelSum(phase.begin, phase.end, grainSize, loop);
- }
- }
- else
- {
- // no batching, also ignores SOLVER_RANDMIZE_ORDER
- for (int j = 0; j < numRollingFrictionPoolConstraints; j++)
- {
- btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[j];
- if (rollingFrictionConstraint.m_frictionIndex >= 0)
- {
- btScalar totalImpulse = m_tmpSolverContactConstraintPool[rollingFrictionConstraint.m_frictionIndex].m_appliedImpulse;
- if (totalImpulse > 0.0f)
- {
- btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction * totalImpulse;
- if (rollingFrictionMagnitude > rollingFrictionConstraint.m_friction)
- rollingFrictionMagnitude = rollingFrictionConstraint.m_friction;
- rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
- rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
- btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA], m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB], rollingFrictionConstraint);
- leastSquaresResidual += residual * residual;
- }
- }
- }
- }
- return leastSquaresResidual;
- }
- void btSequentialImpulseConstraintSolverMt::internalWriteBackContacts(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
- {
- BT_PROFILE("internalWriteBackContacts");
- writeBackContacts(iBegin, iEnd, infoGlobal);
- //for ( int iContact = iBegin; iContact < iEnd; ++iContact)
- //{
- // const btSolverConstraint& contactConstraint = m_tmpSolverContactConstraintPool[ iContact ];
- // btManifoldPoint* pt = (btManifoldPoint*) contactConstraint.m_originalContactPoint;
- // btAssert( pt );
- // pt->m_appliedImpulse = contactConstraint.m_appliedImpulse;
- // pt->m_appliedImpulseLateral1 = m_tmpSolverContactFrictionConstraintPool[ contactConstraint.m_frictionIndex ].m_appliedImpulse;
- // if ( m_numFrictionDirections == 2 )
- // {
- // pt->m_appliedImpulseLateral2 = m_tmpSolverContactFrictionConstraintPool[ contactConstraint.m_frictionIndex + 1 ].m_appliedImpulse;
- // }
- //}
- }
- void btSequentialImpulseConstraintSolverMt::internalWriteBackJoints(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
- {
- BT_PROFILE("internalWriteBackJoints");
- writeBackJoints(iBegin, iEnd, infoGlobal);
- }
- void btSequentialImpulseConstraintSolverMt::internalWriteBackBodies(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
- {
- BT_PROFILE("internalWriteBackBodies");
- writeBackBodies(iBegin, iEnd, infoGlobal);
- }
- struct WriteContactPointsLoop : public btIParallelForBody
- {
- btSequentialImpulseConstraintSolverMt* m_solver;
- const btContactSolverInfo* m_infoGlobal;
- WriteContactPointsLoop(btSequentialImpulseConstraintSolverMt* solver, const btContactSolverInfo& infoGlobal)
- {
- m_solver = solver;
- m_infoGlobal = &infoGlobal;
- }
- void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
- {
- m_solver->internalWriteBackContacts(iBegin, iEnd, *m_infoGlobal);
- }
- };
- struct WriteJointsLoop : public btIParallelForBody
- {
- btSequentialImpulseConstraintSolverMt* m_solver;
- const btContactSolverInfo* m_infoGlobal;
- WriteJointsLoop(btSequentialImpulseConstraintSolverMt* solver, const btContactSolverInfo& infoGlobal)
- {
- m_solver = solver;
- m_infoGlobal = &infoGlobal;
- }
- void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
- {
- m_solver->internalWriteBackJoints(iBegin, iEnd, *m_infoGlobal);
- }
- };
- struct WriteBodiesLoop : public btIParallelForBody
- {
- btSequentialImpulseConstraintSolverMt* m_solver;
- const btContactSolverInfo* m_infoGlobal;
- WriteBodiesLoop(btSequentialImpulseConstraintSolverMt* solver, const btContactSolverInfo& infoGlobal)
- {
- m_solver = solver;
- m_infoGlobal = &infoGlobal;
- }
- void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
- {
- m_solver->internalWriteBackBodies(iBegin, iEnd, *m_infoGlobal);
- }
- };
- btScalar btSequentialImpulseConstraintSolverMt::solveGroupCacheFriendlyFinish(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal)
- {
- BT_PROFILE("solveGroupCacheFriendlyFinish");
- if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
- {
- WriteContactPointsLoop loop(this, infoGlobal);
- int grainSize = 500;
- btParallelFor(0, m_tmpSolverContactConstraintPool.size(), grainSize, loop);
- }
- {
- WriteJointsLoop loop(this, infoGlobal);
- int grainSize = 400;
- btParallelFor(0, m_tmpSolverNonContactConstraintPool.size(), grainSize, loop);
- }
- {
- WriteBodiesLoop loop(this, infoGlobal);
- int grainSize = 100;
- btParallelFor(0, m_tmpSolverBodyPool.size(), grainSize, loop);
- }
- m_tmpSolverContactConstraintPool.resizeNoInitialize(0);
- m_tmpSolverNonContactConstraintPool.resizeNoInitialize(0);
- m_tmpSolverContactFrictionConstraintPool.resizeNoInitialize(0);
- m_tmpSolverContactRollingFrictionConstraintPool.resizeNoInitialize(0);
- m_tmpSolverBodyPool.resizeNoInitialize(0);
- return 0.f;
- }
|