2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2006 Erwin Coumans https://bulletphysics.org
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising from the use of this software.
7 Permission is granted to anyone to use this software for any purpose,
8 including commercial applications, and to alter it and redistribute it freely,
9 subject to the following restrictions:
11 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.
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13 3. This notice may not be removed or altered from any source distribution.
16 #include "btSequentialImpulseConstraintSolverMt.h"
18 #include "LinearMath/btQuickprof.h"
20 #include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
22 #include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
23 #include "BulletDynamics/Dynamics/btRigidBody.h"
25 bool btSequentialImpulseConstraintSolverMt::s_allowNestedParallelForLoops = false; // some task schedulers don't like nested loops
26 int btSequentialImpulseConstraintSolverMt::s_minimumContactManifoldsForBatching = 250;
27 int btSequentialImpulseConstraintSolverMt::s_minBatchSize = 50;
28 int btSequentialImpulseConstraintSolverMt::s_maxBatchSize = 100;
29 btBatchedConstraints::BatchingMethod btSequentialImpulseConstraintSolverMt::s_contactBatchingMethod = btBatchedConstraints::BATCHING_METHOD_SPATIAL_GRID_2D;
30 btBatchedConstraints::BatchingMethod btSequentialImpulseConstraintSolverMt::s_jointBatchingMethod = btBatchedConstraints::BATCHING_METHOD_SPATIAL_GRID_2D;
32 btSequentialImpulseConstraintSolverMt::btSequentialImpulseConstraintSolverMt()
34 m_numFrictionDirections = 1;
35 m_useBatching = false;
36 m_useObsoleteJointConstraints = false;
39 btSequentialImpulseConstraintSolverMt::~btSequentialImpulseConstraintSolverMt()
43 void btSequentialImpulseConstraintSolverMt::setupBatchedContactConstraints()
45 BT_PROFILE("setupBatchedContactConstraints");
46 m_batchedContactConstraints.setup(&m_tmpSolverContactConstraintPool,
48 s_contactBatchingMethod,
54 void btSequentialImpulseConstraintSolverMt::setupBatchedJointConstraints()
56 BT_PROFILE("setupBatchedJointConstraints");
57 m_batchedJointConstraints.setup(&m_tmpSolverNonContactConstraintPool,
59 s_jointBatchingMethod,
65 void btSequentialImpulseConstraintSolverMt::internalSetupContactConstraints(int iContactConstraint, const btContactSolverInfo& infoGlobal)
67 btSolverConstraint& contactConstraint = m_tmpSolverContactConstraintPool[iContactConstraint];
73 int solverBodyIdA = contactConstraint.m_solverBodyIdA;
74 int solverBodyIdB = contactConstraint.m_solverBodyIdB;
76 btSolverBody* solverBodyA = &m_tmpSolverBodyPool[solverBodyIdA];
77 btSolverBody* solverBodyB = &m_tmpSolverBodyPool[solverBodyIdB];
79 btRigidBody* colObj0 = solverBodyA->m_originalBody;
80 btRigidBody* colObj1 = solverBodyB->m_originalBody;
82 btManifoldPoint& cp = *static_cast<btManifoldPoint*>(contactConstraint.m_originalContactPoint);
84 const btVector3& pos1 = cp.getPositionWorldOnA();
85 const btVector3& pos2 = cp.getPositionWorldOnB();
87 rel_pos1 = pos1 - solverBodyA->getWorldTransform().getOrigin();
88 rel_pos2 = pos2 - solverBodyB->getWorldTransform().getOrigin();
93 solverBodyA->getVelocityInLocalPointNoDelta(rel_pos1, vel1);
94 solverBodyB->getVelocityInLocalPointNoDelta(rel_pos2, vel2);
96 btVector3 vel = vel1 - vel2;
97 btScalar rel_vel = cp.m_normalWorldOnB.dot(vel);
99 setupContactConstraint(contactConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal, relaxation, rel_pos1, rel_pos2);
101 // setup rolling friction constraints
102 int rollingFrictionIndex = m_rollingFrictionIndexTable[iContactConstraint];
103 if (rollingFrictionIndex >= 0)
105 btSolverConstraint& spinningFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[rollingFrictionIndex];
106 btAssert(spinningFrictionConstraint.m_frictionIndex == iContactConstraint);
107 setupTorsionalFrictionConstraint(spinningFrictionConstraint,
112 cp.m_combinedSpinningFriction,
121 btPlaneSpace1(cp.m_normalWorldOnB, axis[0], axis[1]);
125 applyAnisotropicFriction(colObj0, axis[0], btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
126 applyAnisotropicFriction(colObj1, axis[0], btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
127 applyAnisotropicFriction(colObj0, axis[1], btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
128 applyAnisotropicFriction(colObj1, axis[1], btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
129 // put the largest axis first
130 if (axis[1].length2() > axis[0].length2())
132 btSwap(axis[0], axis[1]);
134 const btScalar kRollingFrictionThreshold = 0.001f;
135 for (int i = 0; i < 2; ++i)
137 int iRollingFric = rollingFrictionIndex + 1 + i;
138 btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[iRollingFric];
139 btAssert(rollingFrictionConstraint.m_frictionIndex == iContactConstraint);
140 btVector3 dir = axis[i];
141 if (dir.length() > kRollingFrictionThreshold)
143 setupTorsionalFrictionConstraint(rollingFrictionConstraint,
148 cp.m_combinedRollingFriction,
159 rollingFrictionConstraint.m_frictionIndex = -1; // disable constraint
164 // setup friction constraints
165 // setupFrictionConstraint(solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, desiredVelocity, cfmSlip);
167 ///Bullet has several options to set the friction directions
168 ///By default, each contact has only a single friction direction that is recomputed automatically very frame
169 ///based on the relative linear velocity.
170 ///If the relative velocity it zero, it will automatically compute a friction direction.
172 ///You can also enable two friction directions, using the SOLVER_USE_2_FRICTION_DIRECTIONS.
173 ///In that case, the second friction direction will be orthogonal to both contact normal and first friction direction.
175 ///If you choose SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION, then the friction will be independent from the relative projected velocity.
177 ///The user can manually override the friction directions for certain contacts using a contact callback,
178 ///and set the cp.m_lateralFrictionInitialized to true
179 ///In that case, you can set the target relative motion in each friction direction (cp.m_contactMotion1 and cp.m_contactMotion2)
180 ///this will give a conveyor belt effect
182 btSolverConstraint* frictionConstraint1 = &m_tmpSolverContactFrictionConstraintPool[contactConstraint.m_frictionIndex];
183 btAssert(frictionConstraint1->m_frictionIndex == iContactConstraint);
185 btSolverConstraint* frictionConstraint2 = NULL;
186 if (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)
188 frictionConstraint2 = &m_tmpSolverContactFrictionConstraintPool[contactConstraint.m_frictionIndex + 1];
189 btAssert(frictionConstraint2->m_frictionIndex == iContactConstraint);
192 if (!(infoGlobal.m_solverMode & SOLVER_ENABLE_FRICTION_DIRECTION_CACHING) || !(cp.m_contactPointFlags & BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED))
194 cp.m_lateralFrictionDir1 = vel - cp.m_normalWorldOnB * rel_vel;
195 btScalar lat_rel_vel = cp.m_lateralFrictionDir1.length2();
196 if (!(infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION) && lat_rel_vel > SIMD_EPSILON)
198 cp.m_lateralFrictionDir1 *= 1.f / btSqrt(lat_rel_vel);
199 applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
200 applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
201 setupFrictionConstraint(*frictionConstraint1, cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
203 if (frictionConstraint2)
205 cp.m_lateralFrictionDir2 = cp.m_lateralFrictionDir1.cross(cp.m_normalWorldOnB);
206 cp.m_lateralFrictionDir2.normalize(); //??
207 applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
208 applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
209 setupFrictionConstraint(*frictionConstraint2, cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
214 btPlaneSpace1(cp.m_normalWorldOnB, cp.m_lateralFrictionDir1, cp.m_lateralFrictionDir2);
216 applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
217 applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
218 setupFrictionConstraint(*frictionConstraint1, cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
220 if (frictionConstraint2)
222 applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
223 applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
224 setupFrictionConstraint(*frictionConstraint2, cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
227 if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) && (infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION))
229 cp.m_contactPointFlags |= BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED;
235 setupFrictionConstraint(*frictionConstraint1, cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion1, cp.m_frictionCFM);
236 if (frictionConstraint2)
238 setupFrictionConstraint(*frictionConstraint2, cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion2, cp.m_frictionCFM);
243 setFrictionConstraintImpulse(contactConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal);
246 struct SetupContactConstraintsLoop : public btIParallelForBody
248 btSequentialImpulseConstraintSolverMt* m_solver;
249 const btBatchedConstraints* m_bc;
250 const btContactSolverInfo* m_infoGlobal;
252 SetupContactConstraintsLoop(btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc, const btContactSolverInfo& infoGlobal)
256 m_infoGlobal = &infoGlobal;
258 void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
260 BT_PROFILE("SetupContactConstraintsLoop");
261 for (int iBatch = iBegin; iBatch < iEnd; ++iBatch)
263 const btBatchedConstraints::Range& batch = m_bc->m_batches[iBatch];
264 for (int i = batch.begin; i < batch.end; ++i)
266 int iContact = m_bc->m_constraintIndices[i];
267 m_solver->internalSetupContactConstraints(iContact, *m_infoGlobal);
273 void btSequentialImpulseConstraintSolverMt::setupAllContactConstraints(const btContactSolverInfo& infoGlobal)
275 BT_PROFILE("setupAllContactConstraints");
278 const btBatchedConstraints& batchedCons = m_batchedContactConstraints;
279 SetupContactConstraintsLoop loop(this, &batchedCons, infoGlobal);
280 for (int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase)
282 int iPhase = batchedCons.m_phaseOrder[iiPhase];
283 const btBatchedConstraints::Range& phase = batchedCons.m_phases[iPhase];
285 btParallelFor(phase.begin, phase.end, grainSize, loop);
290 for (int i = 0; i < m_tmpSolverContactConstraintPool.size(); ++i)
292 internalSetupContactConstraints(i, infoGlobal);
297 int btSequentialImpulseConstraintSolverMt::getOrInitSolverBodyThreadsafe(btCollisionObject& body, btScalar timeStep)
300 // getOrInitSolverBody is threadsafe only for a single thread per solver (with potentially multiple solvers)
302 // getOrInitSolverBodyThreadsafe -- attempts to be fully threadsafe (however may affect determinism)
304 int solverBodyId = -1;
305 bool isRigidBodyType = btRigidBody::upcast(&body) != NULL;
306 if (isRigidBodyType && !body.isStaticOrKinematicObject())
309 // Dynamic bodies can only be in one island, so it's safe to write to the companionId
310 solverBodyId = body.getCompanionId();
311 if (solverBodyId < 0)
313 m_bodySolverArrayMutex.lock();
314 // now that we have the lock, check again
315 solverBodyId = body.getCompanionId();
316 if (solverBodyId < 0)
318 solverBodyId = m_tmpSolverBodyPool.size();
319 btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
320 initSolverBody(&solverBody, &body, timeStep);
321 body.setCompanionId(solverBodyId);
323 m_bodySolverArrayMutex.unlock();
326 else if (isRigidBodyType && body.isKinematicObject())
329 // NOTE: must test for kinematic before static because some kinematic objects also
330 // identify as "static"
332 // Kinematic bodies can be in multiple islands at once, so it is a
333 // race condition to write to them, so we use an alternate method
334 // to record the solverBodyId
335 int uniqueId = body.getWorldArrayIndex();
336 const int INVALID_SOLVER_BODY_ID = -1;
337 if (m_kinematicBodyUniqueIdToSolverBodyTable.size() <= uniqueId)
339 m_kinematicBodyUniqueIdToSolverBodyTableMutex.lock();
340 // now that we have the lock, check again
341 if (m_kinematicBodyUniqueIdToSolverBodyTable.size() <= uniqueId)
343 m_kinematicBodyUniqueIdToSolverBodyTable.resize(uniqueId + 1, INVALID_SOLVER_BODY_ID);
345 m_kinematicBodyUniqueIdToSolverBodyTableMutex.unlock();
347 solverBodyId = m_kinematicBodyUniqueIdToSolverBodyTable[uniqueId];
348 // if no table entry yet,
349 if (INVALID_SOLVER_BODY_ID == solverBodyId)
351 // need to acquire both locks
352 m_kinematicBodyUniqueIdToSolverBodyTableMutex.lock();
353 m_bodySolverArrayMutex.lock();
354 // now that we have the lock, check again
355 solverBodyId = m_kinematicBodyUniqueIdToSolverBodyTable[uniqueId];
356 if (INVALID_SOLVER_BODY_ID == solverBodyId)
358 // create a table entry for this body
359 solverBodyId = m_tmpSolverBodyPool.size();
360 btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
361 initSolverBody(&solverBody, &body, timeStep);
362 m_kinematicBodyUniqueIdToSolverBodyTable[uniqueId] = solverBodyId;
364 m_bodySolverArrayMutex.unlock();
365 m_kinematicBodyUniqueIdToSolverBodyTableMutex.unlock();
370 // all fixed bodies (inf mass) get mapped to a single solver id
371 if (m_fixedBodyId < 0)
373 m_bodySolverArrayMutex.lock();
374 // now that we have the lock, check again
375 if (m_fixedBodyId < 0)
377 m_fixedBodyId = m_tmpSolverBodyPool.size();
378 btSolverBody& fixedBody = m_tmpSolverBodyPool.expand();
379 initSolverBody(&fixedBody, 0, timeStep);
381 m_bodySolverArrayMutex.unlock();
383 solverBodyId = m_fixedBodyId;
385 btAssert(solverBodyId >= 0 && solverBodyId < m_tmpSolverBodyPool.size());
389 void btSequentialImpulseConstraintSolverMt::internalCollectContactManifoldCachedInfo(btContactManifoldCachedInfo* cachedInfoArray, btPersistentManifold** manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal)
391 BT_PROFILE("internalCollectContactManifoldCachedInfo");
392 for (int i = 0; i < numManifolds; ++i)
394 btContactManifoldCachedInfo* cachedInfo = &cachedInfoArray[i];
395 btPersistentManifold* manifold = manifoldPtr[i];
396 btCollisionObject* colObj0 = (btCollisionObject*)manifold->getBody0();
397 btCollisionObject* colObj1 = (btCollisionObject*)manifold->getBody1();
399 int solverBodyIdA = getOrInitSolverBodyThreadsafe(*colObj0, infoGlobal.m_timeStep);
400 int solverBodyIdB = getOrInitSolverBodyThreadsafe(*colObj1, infoGlobal.m_timeStep);
402 cachedInfo->solverBodyIds[0] = solverBodyIdA;
403 cachedInfo->solverBodyIds[1] = solverBodyIdB;
404 cachedInfo->numTouchingContacts = 0;
406 btSolverBody* solverBodyA = &m_tmpSolverBodyPool[solverBodyIdA];
407 btSolverBody* solverBodyB = &m_tmpSolverBodyPool[solverBodyIdB];
409 // A contact manifold between 2 static object should not exist!
410 // check the collision flags of your objects if this assert fires.
411 // Incorrectly set collision object flags can degrade performance in various ways.
412 btAssert(!m_tmpSolverBodyPool[solverBodyIdA].m_invMass.isZero() || !m_tmpSolverBodyPool[solverBodyIdB].m_invMass.isZero());
415 for (int j = 0; j < manifold->getNumContacts(); j++)
417 btManifoldPoint& cp = manifold->getContactPoint(j);
419 if (cp.getDistance() <= manifold->getContactProcessingThreshold())
421 cachedInfo->contactPoints[iContact] = &cp;
422 cachedInfo->contactHasRollingFriction[iContact] = (cp.m_combinedRollingFriction > 0.f);
426 cachedInfo->numTouchingContacts = iContact;
430 struct CollectContactManifoldCachedInfoLoop : public btIParallelForBody
432 btSequentialImpulseConstraintSolverMt* m_solver;
433 btSequentialImpulseConstraintSolverMt::btContactManifoldCachedInfo* m_cachedInfoArray;
434 btPersistentManifold** m_manifoldPtr;
435 const btContactSolverInfo* m_infoGlobal;
437 CollectContactManifoldCachedInfoLoop(btSequentialImpulseConstraintSolverMt* solver, btSequentialImpulseConstraintSolverMt::btContactManifoldCachedInfo* cachedInfoArray, btPersistentManifold** manifoldPtr, const btContactSolverInfo& infoGlobal)
440 m_cachedInfoArray = cachedInfoArray;
441 m_manifoldPtr = manifoldPtr;
442 m_infoGlobal = &infoGlobal;
444 void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
446 m_solver->internalCollectContactManifoldCachedInfo(m_cachedInfoArray + iBegin, m_manifoldPtr + iBegin, iEnd - iBegin, *m_infoGlobal);
450 void btSequentialImpulseConstraintSolverMt::internalAllocContactConstraints(const btContactManifoldCachedInfo* cachedInfoArray, int numManifolds)
452 BT_PROFILE("internalAllocContactConstraints");
453 // possibly parallel part
454 for (int iManifold = 0; iManifold < numManifolds; ++iManifold)
456 const btContactManifoldCachedInfo& cachedInfo = cachedInfoArray[iManifold];
457 int contactIndex = cachedInfo.contactIndex;
458 int frictionIndex = contactIndex * m_numFrictionDirections;
459 int rollingFrictionIndex = cachedInfo.rollingFrictionIndex;
460 for (int i = 0; i < cachedInfo.numTouchingContacts; i++)
462 btSolverConstraint& contactConstraint = m_tmpSolverContactConstraintPool[contactIndex];
463 contactConstraint.m_solverBodyIdA = cachedInfo.solverBodyIds[0];
464 contactConstraint.m_solverBodyIdB = cachedInfo.solverBodyIds[1];
465 contactConstraint.m_originalContactPoint = cachedInfo.contactPoints[i];
467 // allocate the friction constraints
468 contactConstraint.m_frictionIndex = frictionIndex;
469 for (int iDir = 0; iDir < m_numFrictionDirections; ++iDir)
471 btSolverConstraint& frictionConstraint = m_tmpSolverContactFrictionConstraintPool[frictionIndex];
472 frictionConstraint.m_frictionIndex = contactIndex;
476 // allocate rolling friction constraints
477 if (cachedInfo.contactHasRollingFriction[i])
479 m_rollingFrictionIndexTable[contactIndex] = rollingFrictionIndex;
480 // allocate 3 (although we may use only 2 sometimes)
481 for (int i = 0; i < 3; i++)
483 m_tmpSolverContactRollingFrictionConstraintPool[rollingFrictionIndex].m_frictionIndex = contactIndex;
484 rollingFrictionIndex++;
489 // indicate there is no rolling friction for this contact point
490 m_rollingFrictionIndexTable[contactIndex] = -1;
497 struct AllocContactConstraintsLoop : public btIParallelForBody
499 btSequentialImpulseConstraintSolverMt* m_solver;
500 const btSequentialImpulseConstraintSolverMt::btContactManifoldCachedInfo* m_cachedInfoArray;
502 AllocContactConstraintsLoop(btSequentialImpulseConstraintSolverMt* solver, btSequentialImpulseConstraintSolverMt::btContactManifoldCachedInfo* cachedInfoArray)
505 m_cachedInfoArray = cachedInfoArray;
507 void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
509 m_solver->internalAllocContactConstraints(m_cachedInfoArray + iBegin, iEnd - iBegin);
513 void btSequentialImpulseConstraintSolverMt::allocAllContactConstraints(btPersistentManifold** manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal)
515 BT_PROFILE("allocAllContactConstraints");
516 btAlignedObjectArray<btContactManifoldCachedInfo> cachedInfoArray; // = m_manifoldCachedInfoArray;
517 cachedInfoArray.resizeNoInitialize(numManifolds);
518 if (/* DISABLES CODE */ (false))
521 internalCollectContactManifoldCachedInfo(&cachedInfoArray[0], manifoldPtr, numManifolds, infoGlobal);
525 // may alter ordering of bodies which affects determinism
526 CollectContactManifoldCachedInfoLoop loop(this, &cachedInfoArray[0], manifoldPtr, infoGlobal);
528 btParallelFor(0, numManifolds, grainSize, loop);
534 int numRollingFrictionConstraints = 0;
535 for (int iManifold = 0; iManifold < numManifolds; ++iManifold)
537 btContactManifoldCachedInfo& cachedInfo = cachedInfoArray[iManifold];
538 cachedInfo.contactIndex = numContacts;
539 cachedInfo.rollingFrictionIndex = numRollingFrictionConstraints;
540 numContacts += cachedInfo.numTouchingContacts;
541 for (int i = 0; i < cachedInfo.numTouchingContacts; ++i)
543 if (cachedInfo.contactHasRollingFriction[i])
545 numRollingFrictionConstraints += 3;
550 BT_PROFILE("allocPools");
551 if (m_tmpSolverContactConstraintPool.capacity() < numContacts)
553 // if we need to reallocate, reserve some extra so we don't have to reallocate again next frame
554 int extraReserve = numContacts / 16;
555 m_tmpSolverContactConstraintPool.reserve(numContacts + extraReserve);
556 m_rollingFrictionIndexTable.reserve(numContacts + extraReserve);
557 m_tmpSolverContactFrictionConstraintPool.reserve((numContacts + extraReserve) * m_numFrictionDirections);
558 m_tmpSolverContactRollingFrictionConstraintPool.reserve(numRollingFrictionConstraints + extraReserve);
560 m_tmpSolverContactConstraintPool.resizeNoInitialize(numContacts);
561 m_rollingFrictionIndexTable.resizeNoInitialize(numContacts);
562 m_tmpSolverContactFrictionConstraintPool.resizeNoInitialize(numContacts * m_numFrictionDirections);
563 m_tmpSolverContactRollingFrictionConstraintPool.resizeNoInitialize(numRollingFrictionConstraints);
567 AllocContactConstraintsLoop loop(this, &cachedInfoArray[0]);
569 btParallelFor(0, numManifolds, grainSize, loop);
573 void btSequentialImpulseConstraintSolverMt::convertContacts(btPersistentManifold** manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal)
577 btSequentialImpulseConstraintSolver::convertContacts(manifoldPtr, numManifolds, infoGlobal);
580 BT_PROFILE("convertContacts");
581 if (numManifolds > 0)
583 if (m_fixedBodyId < 0)
585 m_fixedBodyId = m_tmpSolverBodyPool.size();
586 btSolverBody& fixedBody = m_tmpSolverBodyPool.expand();
587 initSolverBody(&fixedBody, 0, infoGlobal.m_timeStep);
589 allocAllContactConstraints(manifoldPtr, numManifolds, infoGlobal);
592 setupBatchedContactConstraints();
594 setupAllContactConstraints(infoGlobal);
598 void btSequentialImpulseConstraintSolverMt::internalInitMultipleJoints(btTypedConstraint** constraints, int iBegin, int iEnd)
600 BT_PROFILE("internalInitMultipleJoints");
601 for (int i = iBegin; i < iEnd; i++)
603 btTypedConstraint* constraint = constraints[i];
604 btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
605 if (constraint->isEnabled())
607 constraint->buildJacobian();
608 constraint->internalSetAppliedImpulse(0.0f);
609 btJointFeedback* fb = constraint->getJointFeedback();
612 fb->m_appliedForceBodyA.setZero();
613 fb->m_appliedTorqueBodyA.setZero();
614 fb->m_appliedForceBodyB.setZero();
615 fb->m_appliedTorqueBodyB.setZero();
617 constraint->getInfo1(&info1);
621 info1.m_numConstraintRows = 0;
627 struct InitJointsLoop : public btIParallelForBody
629 btSequentialImpulseConstraintSolverMt* m_solver;
630 btTypedConstraint** m_constraints;
632 InitJointsLoop(btSequentialImpulseConstraintSolverMt* solver, btTypedConstraint** constraints)
635 m_constraints = constraints;
637 void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
639 m_solver->internalInitMultipleJoints(m_constraints, iBegin, iEnd);
643 void btSequentialImpulseConstraintSolverMt::internalConvertMultipleJoints(const btAlignedObjectArray<JointParams>& jointParamsArray, btTypedConstraint** constraints, int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
645 BT_PROFILE("internalConvertMultipleJoints");
646 for (int i = iBegin; i < iEnd; ++i)
648 const JointParams& jointParams = jointParamsArray[i];
649 int currentRow = jointParams.m_solverConstraint;
650 if (currentRow != -1)
652 const btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
653 btAssert(currentRow < m_tmpSolverNonContactConstraintPool.size());
654 btAssert(info1.m_numConstraintRows > 0);
656 btSolverConstraint* currentConstraintRow = &m_tmpSolverNonContactConstraintPool[currentRow];
657 btTypedConstraint* constraint = constraints[i];
659 convertJoint(currentConstraintRow, constraint, info1, jointParams.m_solverBodyA, jointParams.m_solverBodyB, infoGlobal);
664 struct ConvertJointsLoop : public btIParallelForBody
666 btSequentialImpulseConstraintSolverMt* m_solver;
667 const btAlignedObjectArray<btSequentialImpulseConstraintSolverMt::JointParams>& m_jointParamsArray;
668 btTypedConstraint** m_srcConstraints;
669 const btContactSolverInfo& m_infoGlobal;
671 ConvertJointsLoop(btSequentialImpulseConstraintSolverMt* solver,
672 const btAlignedObjectArray<btSequentialImpulseConstraintSolverMt::JointParams>& jointParamsArray,
673 btTypedConstraint** srcConstraints,
674 const btContactSolverInfo& infoGlobal) : m_jointParamsArray(jointParamsArray),
675 m_infoGlobal(infoGlobal)
678 m_srcConstraints = srcConstraints;
680 void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
682 m_solver->internalConvertMultipleJoints(m_jointParamsArray, m_srcConstraints, iBegin, iEnd, m_infoGlobal);
686 void btSequentialImpulseConstraintSolverMt::convertJoints(btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal)
690 btSequentialImpulseConstraintSolver::convertJoints(constraints, numConstraints, infoGlobal);
693 BT_PROFILE("convertJoints");
694 bool parallelJointSetup = true;
695 m_tmpConstraintSizesPool.resizeNoInitialize(numConstraints);
696 if (parallelJointSetup)
698 InitJointsLoop loop(this, constraints);
700 btParallelFor(0, numConstraints, grainSize, loop);
704 internalInitMultipleJoints(constraints, 0, numConstraints);
707 int totalNumRows = 0;
708 btAlignedObjectArray<JointParams> jointParamsArray;
709 jointParamsArray.resizeNoInitialize(numConstraints);
711 //calculate the total number of contraint rows
712 for (int i = 0; i < numConstraints; i++)
714 btTypedConstraint* constraint = constraints[i];
716 JointParams& params = jointParamsArray[i];
717 const btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
719 if (info1.m_numConstraintRows)
721 params.m_solverConstraint = totalNumRows;
722 params.m_solverBodyA = getOrInitSolverBody(constraint->getRigidBodyA(), infoGlobal.m_timeStep);
723 params.m_solverBodyB = getOrInitSolverBody(constraint->getRigidBodyB(), infoGlobal.m_timeStep);
727 params.m_solverConstraint = -1;
729 totalNumRows += info1.m_numConstraintRows;
731 m_tmpSolverNonContactConstraintPool.resizeNoInitialize(totalNumRows);
733 ///setup the btSolverConstraints
734 if (parallelJointSetup)
736 ConvertJointsLoop loop(this, jointParamsArray, constraints, infoGlobal);
738 btParallelFor(0, numConstraints, grainSize, loop);
742 internalConvertMultipleJoints(jointParamsArray, constraints, 0, numConstraints, infoGlobal);
744 setupBatchedJointConstraints();
747 void btSequentialImpulseConstraintSolverMt::internalConvertBodies(btCollisionObject** bodies, int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
749 BT_PROFILE("internalConvertBodies");
750 for (int i = iBegin; i < iEnd; i++)
752 btCollisionObject* obj = bodies[i];
753 obj->setCompanionId(i);
754 btSolverBody& solverBody = m_tmpSolverBodyPool[i];
755 initSolverBody(&solverBody, obj, infoGlobal.m_timeStep);
757 btRigidBody* body = btRigidBody::upcast(obj);
758 if (body && body->getInvMass())
760 btVector3 gyroForce(0, 0, 0);
761 if (body->getFlags() & BT_ENABLE_GYROSCOPIC_FORCE_EXPLICIT)
763 gyroForce = body->computeGyroscopicForceExplicit(infoGlobal.m_maxGyroscopicForce);
764 solverBody.m_externalTorqueImpulse -= gyroForce * body->getInvInertiaTensorWorld() * infoGlobal.m_timeStep;
766 if (body->getFlags() & BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_WORLD)
768 gyroForce = body->computeGyroscopicImpulseImplicit_World(infoGlobal.m_timeStep);
769 solverBody.m_externalTorqueImpulse += gyroForce;
771 if (body->getFlags() & BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_BODY)
773 gyroForce = body->computeGyroscopicImpulseImplicit_Body(infoGlobal.m_timeStep);
774 solverBody.m_externalTorqueImpulse += gyroForce;
780 struct ConvertBodiesLoop : public btIParallelForBody
782 btSequentialImpulseConstraintSolverMt* m_solver;
783 btCollisionObject** m_bodies;
785 const btContactSolverInfo& m_infoGlobal;
787 ConvertBodiesLoop(btSequentialImpulseConstraintSolverMt* solver,
788 btCollisionObject** bodies,
790 const btContactSolverInfo& infoGlobal) : m_infoGlobal(infoGlobal)
794 m_numBodies = numBodies;
796 void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
798 m_solver->internalConvertBodies(m_bodies, iBegin, iEnd, m_infoGlobal);
802 void btSequentialImpulseConstraintSolverMt::convertBodies(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal)
804 BT_PROFILE("convertBodies");
805 m_kinematicBodyUniqueIdToSolverBodyTable.resize(0);
807 m_tmpSolverBodyPool.resizeNoInitialize(numBodies + 1);
809 m_fixedBodyId = numBodies;
811 btSolverBody& fixedBody = m_tmpSolverBodyPool[m_fixedBodyId];
812 initSolverBody(&fixedBody, NULL, infoGlobal.m_timeStep);
815 bool parallelBodySetup = true;
816 if (parallelBodySetup)
818 ConvertBodiesLoop loop(this, bodies, numBodies, infoGlobal);
820 btParallelFor(0, numBodies, grainSize, loop);
824 internalConvertBodies(bodies, 0, numBodies, infoGlobal);
828 btScalar btSequentialImpulseConstraintSolverMt::solveGroupCacheFriendlySetup(
829 btCollisionObject** bodies,
831 btPersistentManifold** manifoldPtr,
833 btTypedConstraint** constraints,
835 const btContactSolverInfo& infoGlobal,
836 btIDebugDraw* debugDrawer)
838 m_numFrictionDirections = (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) ? 2 : 1;
839 m_useBatching = false;
840 if (numManifolds >= s_minimumContactManifoldsForBatching &&
841 (s_allowNestedParallelForLoops || !btThreadsAreRunning()))
843 m_useBatching = true;
844 m_batchedContactConstraints.m_debugDrawer = debugDrawer;
845 m_batchedJointConstraints.m_debugDrawer = debugDrawer;
847 btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(bodies,
858 btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactSplitPenetrationImpulseConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd)
860 btScalar leastSquaresResidual = 0.f;
861 for (int iiCons = batchBegin; iiCons < batchEnd; ++iiCons)
863 int iCons = consIndices[iiCons];
864 const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[iCons];
865 btSolverBody& bodyA = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA];
866 btSolverBody& bodyB = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB];
867 btScalar residual = resolveSplitPenetrationImpulse(bodyA, bodyB, solveManifold);
868 leastSquaresResidual += residual * residual;
870 return leastSquaresResidual;
873 struct ContactSplitPenetrationImpulseSolverLoop : public btIParallelSumBody
875 btSequentialImpulseConstraintSolverMt* m_solver;
876 const btBatchedConstraints* m_bc;
878 ContactSplitPenetrationImpulseSolverLoop(btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc)
883 btScalar sumLoop(int iBegin, int iEnd) const BT_OVERRIDE
885 BT_PROFILE("ContactSplitPenetrationImpulseSolverLoop");
887 for (int iBatch = iBegin; iBatch < iEnd; ++iBatch)
889 const btBatchedConstraints::Range& batch = m_bc->m_batches[iBatch];
890 sum += m_solver->resolveMultipleContactSplitPenetrationImpulseConstraints(m_bc->m_constraintIndices, batch.begin, batch.end);
896 void btSequentialImpulseConstraintSolverMt::solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
898 BT_PROFILE("solveGroupCacheFriendlySplitImpulseIterations");
899 if (infoGlobal.m_splitImpulse)
901 for (int iteration = 0; iteration < infoGlobal.m_numIterations; iteration++)
903 btScalar leastSquaresResidual = 0.f;
906 const btBatchedConstraints& batchedCons = m_batchedContactConstraints;
907 ContactSplitPenetrationImpulseSolverLoop loop(this, &batchedCons);
908 btScalar leastSquaresResidual = 0.f;
909 for (int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase)
911 int iPhase = batchedCons.m_phaseOrder[iiPhase];
912 const btBatchedConstraints::Range& phase = batchedCons.m_phases[iPhase];
913 int grainSize = batchedCons.m_phaseGrainSize[iPhase];
914 leastSquaresResidual += btParallelSum(phase.begin, phase.end, grainSize, loop);
920 leastSquaresResidual = resolveMultipleContactSplitPenetrationImpulseConstraints(m_orderTmpConstraintPool, 0, m_tmpSolverContactConstraintPool.size());
922 if (leastSquaresResidual <= infoGlobal.m_leastSquaresResidualThreshold || iteration >= (infoGlobal.m_numIterations - 1))
924 #ifdef VERBOSE_RESIDUAL_PRINTF
925 printf("residual = %f at iteration #%d\n", leastSquaresResidual, iteration);
933 btScalar btSequentialImpulseConstraintSolverMt::solveSingleIteration(int iteration, btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
937 return btSequentialImpulseConstraintSolver::solveSingleIteration(iteration, bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
939 BT_PROFILE("solveSingleIterationMt");
940 btScalar leastSquaresResidual = 0.f;
942 if (infoGlobal.m_solverMode & SOLVER_RANDMIZE_ORDER)
944 if (1) // uncomment this for a bit less random ((iteration & 7) == 0)
946 randomizeConstraintOrdering(iteration, infoGlobal.m_numIterations);
951 ///solve all joint constraints
952 leastSquaresResidual += resolveAllJointConstraints(iteration);
954 if (iteration < infoGlobal.m_numIterations)
956 // this loop is only used for cone-twist constraints,
957 // it would be nice to skip this loop if none of the constraints need it
958 if (m_useObsoleteJointConstraints)
960 for (int j = 0; j < numConstraints; j++)
962 if (constraints[j]->isEnabled())
964 int bodyAid = getOrInitSolverBody(constraints[j]->getRigidBodyA(), infoGlobal.m_timeStep);
965 int bodyBid = getOrInitSolverBody(constraints[j]->getRigidBodyB(), infoGlobal.m_timeStep);
966 btSolverBody& bodyA = m_tmpSolverBodyPool[bodyAid];
967 btSolverBody& bodyB = m_tmpSolverBodyPool[bodyBid];
968 constraints[j]->solveConstraintObsolete(bodyA, bodyB, infoGlobal.m_timeStep);
973 if (infoGlobal.m_solverMode & SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS)
975 // solve all contact, contact-friction, and rolling friction constraints interleaved
976 leastSquaresResidual += resolveAllContactConstraintsInterleaved();
978 else //SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS
980 // don't interleave them
981 // solve all contact constraints
982 leastSquaresResidual += resolveAllContactConstraints();
984 // solve all contact friction constraints
985 leastSquaresResidual += resolveAllContactFrictionConstraints();
987 // solve all rolling friction constraints
988 leastSquaresResidual += resolveAllRollingFrictionConstraints();
992 return leastSquaresResidual;
995 btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleJointConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd, int iteration)
997 btScalar leastSquaresResidual = 0.f;
998 for (int iiCons = batchBegin; iiCons < batchEnd; ++iiCons)
1000 int iCons = consIndices[iiCons];
1001 const btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[iCons];
1002 if (iteration < constraint.m_overrideNumSolverIterations)
1004 btSolverBody& bodyA = m_tmpSolverBodyPool[constraint.m_solverBodyIdA];
1005 btSolverBody& bodyB = m_tmpSolverBodyPool[constraint.m_solverBodyIdB];
1006 btScalar residual = resolveSingleConstraintRowGeneric(bodyA, bodyB, constraint);
1007 leastSquaresResidual += residual * residual;
1010 return leastSquaresResidual;
1013 btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd)
1015 btScalar leastSquaresResidual = 0.f;
1016 for (int iiCons = batchBegin; iiCons < batchEnd; ++iiCons)
1018 int iCons = consIndices[iiCons];
1019 const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[iCons];
1020 btSolverBody& bodyA = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA];
1021 btSolverBody& bodyB = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB];
1022 btScalar residual = resolveSingleConstraintRowLowerLimit(bodyA, bodyB, solveManifold);
1023 leastSquaresResidual += residual * residual;
1025 return leastSquaresResidual;
1028 btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactFrictionConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd)
1030 btScalar leastSquaresResidual = 0.f;
1031 for (int iiCons = batchBegin; iiCons < batchEnd; ++iiCons)
1033 int iContact = consIndices[iiCons];
1034 btScalar totalImpulse = m_tmpSolverContactConstraintPool[iContact].m_appliedImpulse;
1036 // apply sliding friction
1037 if (totalImpulse > 0.0f)
1039 int iBegin = iContact * m_numFrictionDirections;
1040 int iEnd = iBegin + m_numFrictionDirections;
1041 for (int iFriction = iBegin; iFriction < iEnd; ++iFriction)
1043 btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[iFriction++];
1044 btAssert(solveManifold.m_frictionIndex == iContact);
1046 solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
1047 solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
1049 btSolverBody& bodyA = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA];
1050 btSolverBody& bodyB = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB];
1051 btScalar residual = resolveSingleConstraintRowGeneric(bodyA, bodyB, solveManifold);
1052 leastSquaresResidual += residual * residual;
1056 return leastSquaresResidual;
1059 btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactRollingFrictionConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd)
1061 btScalar leastSquaresResidual = 0.f;
1062 for (int iiCons = batchBegin; iiCons < batchEnd; ++iiCons)
1064 int iContact = consIndices[iiCons];
1065 int iFirstRollingFriction = m_rollingFrictionIndexTable[iContact];
1066 if (iFirstRollingFriction >= 0)
1068 btScalar totalImpulse = m_tmpSolverContactConstraintPool[iContact].m_appliedImpulse;
1069 // apply rolling friction
1070 if (totalImpulse > 0.0f)
1072 int iBegin = iFirstRollingFriction;
1073 int iEnd = iBegin + 3;
1074 for (int iRollingFric = iBegin; iRollingFric < iEnd; ++iRollingFric)
1076 btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[iRollingFric];
1077 if (rollingFrictionConstraint.m_frictionIndex != iContact)
1081 btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction * totalImpulse;
1082 if (rollingFrictionMagnitude > rollingFrictionConstraint.m_friction)
1084 rollingFrictionMagnitude = rollingFrictionConstraint.m_friction;
1087 rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
1088 rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
1090 btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA], m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB], rollingFrictionConstraint);
1091 leastSquaresResidual += residual * residual;
1096 return leastSquaresResidual;
1099 btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactConstraintsInterleaved(const btAlignedObjectArray<int>& contactIndices,
1103 btScalar leastSquaresResidual = 0.f;
1104 int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
1106 for (int iiCons = batchBegin; iiCons < batchEnd; iiCons++)
1108 btScalar totalImpulse = 0;
1109 int iContact = contactIndices[iiCons];
1110 // apply penetration constraint
1112 const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[iContact];
1113 btScalar residual = resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
1114 leastSquaresResidual += residual * residual;
1115 totalImpulse = solveManifold.m_appliedImpulse;
1118 // apply sliding friction
1119 if (totalImpulse > 0.0f)
1121 int iBegin = iContact * m_numFrictionDirections;
1122 int iEnd = iBegin + m_numFrictionDirections;
1123 for (int iFriction = iBegin; iFriction < iEnd; ++iFriction)
1125 btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[iFriction];
1126 btAssert(solveManifold.m_frictionIndex == iContact);
1128 solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
1129 solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
1131 btSolverBody& bodyA = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA];
1132 btSolverBody& bodyB = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB];
1133 btScalar residual = resolveSingleConstraintRowGeneric(bodyA, bodyB, solveManifold);
1134 leastSquaresResidual += residual * residual;
1138 // apply rolling friction
1139 int iFirstRollingFriction = m_rollingFrictionIndexTable[iContact];
1140 if (totalImpulse > 0.0f && iFirstRollingFriction >= 0)
1142 int iBegin = iFirstRollingFriction;
1143 int iEnd = iBegin + 3;
1144 for (int iRollingFric = iBegin; iRollingFric < iEnd; ++iRollingFric)
1146 btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[iRollingFric];
1147 if (rollingFrictionConstraint.m_frictionIndex != iContact)
1151 btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction * totalImpulse;
1152 if (rollingFrictionMagnitude > rollingFrictionConstraint.m_friction)
1154 rollingFrictionMagnitude = rollingFrictionConstraint.m_friction;
1157 rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
1158 rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
1160 btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA], m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB], rollingFrictionConstraint);
1161 leastSquaresResidual += residual * residual;
1165 return leastSquaresResidual;
1168 void btSequentialImpulseConstraintSolverMt::randomizeBatchedConstraintOrdering(btBatchedConstraints* batchedConstraints)
1170 btBatchedConstraints& bc = *batchedConstraints;
1171 // randomize ordering of phases
1172 for (int ii = 1; ii < bc.m_phaseOrder.size(); ++ii)
1174 int iSwap = btRandInt2(ii + 1);
1175 bc.m_phaseOrder.swap(ii, iSwap);
1179 for (int iBatch = 0; iBatch < bc.m_batches.size(); ++iBatch)
1181 // randomize ordering of constraints within the batch
1182 const btBatchedConstraints::Range& batch = bc.m_batches[iBatch];
1183 for (int iiCons = batch.begin; iiCons < batch.end; ++iiCons)
1185 int iSwap = batch.begin + btRandInt2(iiCons - batch.begin + 1);
1186 btAssert(iSwap >= batch.begin && iSwap < batch.end);
1187 bc.m_constraintIndices.swap(iiCons, iSwap);
1192 void btSequentialImpulseConstraintSolverMt::randomizeConstraintOrdering(int iteration, int numIterations)
1194 // randomize ordering of joint constraints
1195 randomizeBatchedConstraintOrdering(&m_batchedJointConstraints);
1197 //contact/friction constraints are not solved more than numIterations
1198 if (iteration < numIterations)
1200 randomizeBatchedConstraintOrdering(&m_batchedContactConstraints);
1204 struct JointSolverLoop : public btIParallelSumBody
1206 btSequentialImpulseConstraintSolverMt* m_solver;
1207 const btBatchedConstraints* m_bc;
1210 JointSolverLoop(btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc, int iteration)
1214 m_iteration = iteration;
1216 btScalar sumLoop(int iBegin, int iEnd) const BT_OVERRIDE
1218 BT_PROFILE("JointSolverLoop");
1220 for (int iBatch = iBegin; iBatch < iEnd; ++iBatch)
1222 const btBatchedConstraints::Range& batch = m_bc->m_batches[iBatch];
1223 sum += m_solver->resolveMultipleJointConstraints(m_bc->m_constraintIndices, batch.begin, batch.end, m_iteration);
1229 btScalar btSequentialImpulseConstraintSolverMt::resolveAllJointConstraints(int iteration)
1231 BT_PROFILE("resolveAllJointConstraints");
1232 const btBatchedConstraints& batchedCons = m_batchedJointConstraints;
1233 JointSolverLoop loop(this, &batchedCons, iteration);
1234 btScalar leastSquaresResidual = 0.f;
1235 for (int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase)
1237 int iPhase = batchedCons.m_phaseOrder[iiPhase];
1238 const btBatchedConstraints::Range& phase = batchedCons.m_phases[iPhase];
1240 leastSquaresResidual += btParallelSum(phase.begin, phase.end, grainSize, loop);
1242 return leastSquaresResidual;
1245 struct ContactSolverLoop : public btIParallelSumBody
1247 btSequentialImpulseConstraintSolverMt* m_solver;
1248 const btBatchedConstraints* m_bc;
1250 ContactSolverLoop(btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc)
1255 btScalar sumLoop(int iBegin, int iEnd) const BT_OVERRIDE
1257 BT_PROFILE("ContactSolverLoop");
1259 for (int iBatch = iBegin; iBatch < iEnd; ++iBatch)
1261 const btBatchedConstraints::Range& batch = m_bc->m_batches[iBatch];
1262 sum += m_solver->resolveMultipleContactConstraints(m_bc->m_constraintIndices, batch.begin, batch.end);
1268 btScalar btSequentialImpulseConstraintSolverMt::resolveAllContactConstraints()
1270 BT_PROFILE("resolveAllContactConstraints");
1271 const btBatchedConstraints& batchedCons = m_batchedContactConstraints;
1272 ContactSolverLoop loop(this, &batchedCons);
1273 btScalar leastSquaresResidual = 0.f;
1274 for (int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase)
1276 int iPhase = batchedCons.m_phaseOrder[iiPhase];
1277 const btBatchedConstraints::Range& phase = batchedCons.m_phases[iPhase];
1278 int grainSize = batchedCons.m_phaseGrainSize[iPhase];
1279 leastSquaresResidual += btParallelSum(phase.begin, phase.end, grainSize, loop);
1281 return leastSquaresResidual;
1284 struct ContactFrictionSolverLoop : public btIParallelSumBody
1286 btSequentialImpulseConstraintSolverMt* m_solver;
1287 const btBatchedConstraints* m_bc;
1289 ContactFrictionSolverLoop(btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc)
1294 btScalar sumLoop(int iBegin, int iEnd) const BT_OVERRIDE
1296 BT_PROFILE("ContactFrictionSolverLoop");
1298 for (int iBatch = iBegin; iBatch < iEnd; ++iBatch)
1300 const btBatchedConstraints::Range& batch = m_bc->m_batches[iBatch];
1301 sum += m_solver->resolveMultipleContactFrictionConstraints(m_bc->m_constraintIndices, batch.begin, batch.end);
1307 btScalar btSequentialImpulseConstraintSolverMt::resolveAllContactFrictionConstraints()
1309 BT_PROFILE("resolveAllContactFrictionConstraints");
1310 const btBatchedConstraints& batchedCons = m_batchedContactConstraints;
1311 ContactFrictionSolverLoop loop(this, &batchedCons);
1312 btScalar leastSquaresResidual = 0.f;
1313 for (int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase)
1315 int iPhase = batchedCons.m_phaseOrder[iiPhase];
1316 const btBatchedConstraints::Range& phase = batchedCons.m_phases[iPhase];
1317 int grainSize = batchedCons.m_phaseGrainSize[iPhase];
1318 leastSquaresResidual += btParallelSum(phase.begin, phase.end, grainSize, loop);
1320 return leastSquaresResidual;
1323 struct InterleavedContactSolverLoop : public btIParallelSumBody
1325 btSequentialImpulseConstraintSolverMt* m_solver;
1326 const btBatchedConstraints* m_bc;
1328 InterleavedContactSolverLoop(btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc)
1333 btScalar sumLoop(int iBegin, int iEnd) const BT_OVERRIDE
1335 BT_PROFILE("InterleavedContactSolverLoop");
1337 for (int iBatch = iBegin; iBatch < iEnd; ++iBatch)
1339 const btBatchedConstraints::Range& batch = m_bc->m_batches[iBatch];
1340 sum += m_solver->resolveMultipleContactConstraintsInterleaved(m_bc->m_constraintIndices, batch.begin, batch.end);
1346 btScalar btSequentialImpulseConstraintSolverMt::resolveAllContactConstraintsInterleaved()
1348 BT_PROFILE("resolveAllContactConstraintsInterleaved");
1349 const btBatchedConstraints& batchedCons = m_batchedContactConstraints;
1350 InterleavedContactSolverLoop loop(this, &batchedCons);
1351 btScalar leastSquaresResidual = 0.f;
1352 for (int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase)
1354 int iPhase = batchedCons.m_phaseOrder[iiPhase];
1355 const btBatchedConstraints::Range& phase = batchedCons.m_phases[iPhase];
1357 leastSquaresResidual += btParallelSum(phase.begin, phase.end, grainSize, loop);
1359 return leastSquaresResidual;
1362 struct ContactRollingFrictionSolverLoop : public btIParallelSumBody
1364 btSequentialImpulseConstraintSolverMt* m_solver;
1365 const btBatchedConstraints* m_bc;
1367 ContactRollingFrictionSolverLoop(btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc)
1372 btScalar sumLoop(int iBegin, int iEnd) const BT_OVERRIDE
1374 BT_PROFILE("ContactFrictionSolverLoop");
1376 for (int iBatch = iBegin; iBatch < iEnd; ++iBatch)
1378 const btBatchedConstraints::Range& batch = m_bc->m_batches[iBatch];
1379 sum += m_solver->resolveMultipleContactRollingFrictionConstraints(m_bc->m_constraintIndices, batch.begin, batch.end);
1385 btScalar btSequentialImpulseConstraintSolverMt::resolveAllRollingFrictionConstraints()
1387 BT_PROFILE("resolveAllRollingFrictionConstraints");
1388 btScalar leastSquaresResidual = 0.f;
1390 // We do not generate batches for rolling friction constraints. We assume that
1391 // one of two cases is true:
1393 // 1. either most bodies in the simulation have rolling friction, in which case we can use the
1394 // batches for contacts and use a lookup table to translate contact indices to rolling friction
1395 // (ignoring any contact indices that don't map to a rolling friction constraint). As long as
1396 // most contacts have a corresponding rolling friction constraint, this should parallelize well.
1400 // 2. few bodies in the simulation have rolling friction, so it is not worth trying to use the
1401 // batches from contacts as most of the contacts won't have corresponding rolling friction
1402 // constraints and most threads would end up doing very little work. Most of the time would
1403 // go to threading overhead, so we don't bother with threading.
1405 int numRollingFrictionPoolConstraints = m_tmpSolverContactRollingFrictionConstraintPool.size();
1406 if (numRollingFrictionPoolConstraints >= m_tmpSolverContactConstraintPool.size())
1408 // use batching if there are many rolling friction constraints
1409 const btBatchedConstraints& batchedCons = m_batchedContactConstraints;
1410 ContactRollingFrictionSolverLoop loop(this, &batchedCons);
1411 btScalar leastSquaresResidual = 0.f;
1412 for (int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase)
1414 int iPhase = batchedCons.m_phaseOrder[iiPhase];
1415 const btBatchedConstraints::Range& phase = batchedCons.m_phases[iPhase];
1417 leastSquaresResidual += btParallelSum(phase.begin, phase.end, grainSize, loop);
1422 // no batching, also ignores SOLVER_RANDMIZE_ORDER
1423 for (int j = 0; j < numRollingFrictionPoolConstraints; j++)
1425 btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[j];
1426 if (rollingFrictionConstraint.m_frictionIndex >= 0)
1428 btScalar totalImpulse = m_tmpSolverContactConstraintPool[rollingFrictionConstraint.m_frictionIndex].m_appliedImpulse;
1429 if (totalImpulse > 0.0f)
1431 btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction * totalImpulse;
1432 if (rollingFrictionMagnitude > rollingFrictionConstraint.m_friction)
1433 rollingFrictionMagnitude = rollingFrictionConstraint.m_friction;
1435 rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
1436 rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
1438 btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA], m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB], rollingFrictionConstraint);
1439 leastSquaresResidual += residual * residual;
1444 return leastSquaresResidual;
1447 void btSequentialImpulseConstraintSolverMt::internalWriteBackContacts(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
1449 BT_PROFILE("internalWriteBackContacts");
1450 writeBackContacts(iBegin, iEnd, infoGlobal);
1451 //for ( int iContact = iBegin; iContact < iEnd; ++iContact)
1453 // const btSolverConstraint& contactConstraint = m_tmpSolverContactConstraintPool[ iContact ];
1454 // btManifoldPoint* pt = (btManifoldPoint*) contactConstraint.m_originalContactPoint;
1456 // pt->m_appliedImpulse = contactConstraint.m_appliedImpulse;
1457 // pt->m_appliedImpulseLateral1 = m_tmpSolverContactFrictionConstraintPool[ contactConstraint.m_frictionIndex ].m_appliedImpulse;
1458 // if ( m_numFrictionDirections == 2 )
1460 // pt->m_appliedImpulseLateral2 = m_tmpSolverContactFrictionConstraintPool[ contactConstraint.m_frictionIndex + 1 ].m_appliedImpulse;
1465 void btSequentialImpulseConstraintSolverMt::internalWriteBackJoints(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
1467 BT_PROFILE("internalWriteBackJoints");
1468 writeBackJoints(iBegin, iEnd, infoGlobal);
1471 void btSequentialImpulseConstraintSolverMt::internalWriteBackBodies(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
1473 BT_PROFILE("internalWriteBackBodies");
1474 writeBackBodies(iBegin, iEnd, infoGlobal);
1477 struct WriteContactPointsLoop : public btIParallelForBody
1479 btSequentialImpulseConstraintSolverMt* m_solver;
1480 const btContactSolverInfo* m_infoGlobal;
1482 WriteContactPointsLoop(btSequentialImpulseConstraintSolverMt* solver, const btContactSolverInfo& infoGlobal)
1485 m_infoGlobal = &infoGlobal;
1487 void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
1489 m_solver->internalWriteBackContacts(iBegin, iEnd, *m_infoGlobal);
1493 struct WriteJointsLoop : public btIParallelForBody
1495 btSequentialImpulseConstraintSolverMt* m_solver;
1496 const btContactSolverInfo* m_infoGlobal;
1498 WriteJointsLoop(btSequentialImpulseConstraintSolverMt* solver, const btContactSolverInfo& infoGlobal)
1501 m_infoGlobal = &infoGlobal;
1503 void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
1505 m_solver->internalWriteBackJoints(iBegin, iEnd, *m_infoGlobal);
1509 struct WriteBodiesLoop : public btIParallelForBody
1511 btSequentialImpulseConstraintSolverMt* m_solver;
1512 const btContactSolverInfo* m_infoGlobal;
1514 WriteBodiesLoop(btSequentialImpulseConstraintSolverMt* solver, const btContactSolverInfo& infoGlobal)
1517 m_infoGlobal = &infoGlobal;
1519 void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
1521 m_solver->internalWriteBackBodies(iBegin, iEnd, *m_infoGlobal);
1525 btScalar btSequentialImpulseConstraintSolverMt::solveGroupCacheFriendlyFinish(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal)
1527 BT_PROFILE("solveGroupCacheFriendlyFinish");
1529 if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
1531 WriteContactPointsLoop loop(this, infoGlobal);
1532 int grainSize = 500;
1533 btParallelFor(0, m_tmpSolverContactConstraintPool.size(), grainSize, loop);
1537 WriteJointsLoop loop(this, infoGlobal);
1538 int grainSize = 400;
1539 btParallelFor(0, m_tmpSolverNonContactConstraintPool.size(), grainSize, loop);
1542 WriteBodiesLoop loop(this, infoGlobal);
1543 int grainSize = 100;
1544 btParallelFor(0, m_tmpSolverBodyPool.size(), grainSize, loop);
1547 m_tmpSolverContactConstraintPool.resizeNoInitialize(0);
1548 m_tmpSolverNonContactConstraintPool.resizeNoInitialize(0);
1549 m_tmpSolverContactFrictionConstraintPool.resizeNoInitialize(0);
1550 m_tmpSolverContactRollingFrictionConstraintPool.resizeNoInitialize(0);
1552 m_tmpSolverBodyPool.resizeNoInitialize(0);