2
0

btSequentialImpulseConstraintSolverMt.cpp 67 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621
  1. /*
  2. Bullet Continuous Collision Detection and Physics Library
  3. Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
  4. This software is provided 'as-is', without any express or implied warranty.
  5. In no event will the authors be held liable for any damages arising from the use of this software.
  6. Permission is granted to anyone to use this software for any purpose,
  7. including commercial applications, and to alter it and redistribute it freely,
  8. subject to the following restrictions:
  9. 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.
  10. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
  11. 3. This notice may not be removed or altered from any source distribution.
  12. */
  13. #include "btSequentialImpulseConstraintSolverMt.h"
  14. #include "LinearMath/btQuickprof.h"
  15. #include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
  16. #include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
  17. #include "BulletDynamics/Dynamics/btRigidBody.h"
  18. bool btSequentialImpulseConstraintSolverMt::s_allowNestedParallelForLoops = false; // some task schedulers don't like nested loops
  19. int btSequentialImpulseConstraintSolverMt::s_minimumContactManifoldsForBatching = 250;
  20. int btSequentialImpulseConstraintSolverMt::s_minBatchSize = 50;
  21. int btSequentialImpulseConstraintSolverMt::s_maxBatchSize = 100;
  22. btBatchedConstraints::BatchingMethod btSequentialImpulseConstraintSolverMt::s_contactBatchingMethod = btBatchedConstraints::BATCHING_METHOD_SPATIAL_GRID_2D;
  23. btBatchedConstraints::BatchingMethod btSequentialImpulseConstraintSolverMt::s_jointBatchingMethod = btBatchedConstraints::BATCHING_METHOD_SPATIAL_GRID_2D;
  24. btSequentialImpulseConstraintSolverMt::btSequentialImpulseConstraintSolverMt()
  25. {
  26. m_numFrictionDirections = 1;
  27. m_useBatching = false;
  28. m_useObsoleteJointConstraints = false;
  29. }
  30. btSequentialImpulseConstraintSolverMt::~btSequentialImpulseConstraintSolverMt()
  31. {
  32. }
  33. void btSequentialImpulseConstraintSolverMt::setupBatchedContactConstraints()
  34. {
  35. BT_PROFILE("setupBatchedContactConstraints");
  36. m_batchedContactConstraints.setup( &m_tmpSolverContactConstraintPool,
  37. m_tmpSolverBodyPool,
  38. s_contactBatchingMethod,
  39. s_minBatchSize,
  40. s_maxBatchSize,
  41. &m_scratchMemory
  42. );
  43. }
  44. void btSequentialImpulseConstraintSolverMt::setupBatchedJointConstraints()
  45. {
  46. BT_PROFILE("setupBatchedJointConstraints");
  47. m_batchedJointConstraints.setup( &m_tmpSolverNonContactConstraintPool,
  48. m_tmpSolverBodyPool,
  49. s_jointBatchingMethod,
  50. s_minBatchSize,
  51. s_maxBatchSize,
  52. &m_scratchMemory
  53. );
  54. }
  55. void btSequentialImpulseConstraintSolverMt::internalSetupContactConstraints(int iContactConstraint, const btContactSolverInfo& infoGlobal)
  56. {
  57. btSolverConstraint& contactConstraint = m_tmpSolverContactConstraintPool[iContactConstraint];
  58. btVector3 rel_pos1;
  59. btVector3 rel_pos2;
  60. btScalar relaxation;
  61. int solverBodyIdA = contactConstraint.m_solverBodyIdA;
  62. int solverBodyIdB = contactConstraint.m_solverBodyIdB;
  63. btSolverBody* solverBodyA = &m_tmpSolverBodyPool[ solverBodyIdA ];
  64. btSolverBody* solverBodyB = &m_tmpSolverBodyPool[ solverBodyIdB ];
  65. btRigidBody* colObj0 = solverBodyA->m_originalBody;
  66. btRigidBody* colObj1 = solverBodyB->m_originalBody;
  67. btManifoldPoint& cp = *static_cast<btManifoldPoint*>( contactConstraint.m_originalContactPoint );
  68. const btVector3& pos1 = cp.getPositionWorldOnA();
  69. const btVector3& pos2 = cp.getPositionWorldOnB();
  70. rel_pos1 = pos1 - solverBodyA->getWorldTransform().getOrigin();
  71. rel_pos2 = pos2 - solverBodyB->getWorldTransform().getOrigin();
  72. btVector3 vel1;
  73. btVector3 vel2;
  74. solverBodyA->getVelocityInLocalPointNoDelta( rel_pos1, vel1 );
  75. solverBodyB->getVelocityInLocalPointNoDelta( rel_pos2, vel2 );
  76. btVector3 vel = vel1 - vel2;
  77. btScalar rel_vel = cp.m_normalWorldOnB.dot( vel );
  78. setupContactConstraint( contactConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal, relaxation, rel_pos1, rel_pos2 );
  79. // setup rolling friction constraints
  80. int rollingFrictionIndex = m_rollingFrictionIndexTable[iContactConstraint];
  81. if (rollingFrictionIndex >= 0)
  82. {
  83. btSolverConstraint& spinningFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[ rollingFrictionIndex ];
  84. btAssert( spinningFrictionConstraint.m_frictionIndex == iContactConstraint );
  85. setupTorsionalFrictionConstraint( spinningFrictionConstraint,
  86. cp.m_normalWorldOnB,
  87. solverBodyIdA,
  88. solverBodyIdB,
  89. cp,
  90. cp.m_combinedSpinningFriction,
  91. rel_pos1,
  92. rel_pos2,
  93. colObj0,
  94. colObj1,
  95. relaxation,
  96. 0.0f,
  97. 0.0f
  98. );
  99. btVector3 axis[2];
  100. btPlaneSpace1( cp.m_normalWorldOnB, axis[0], axis[1] );
  101. axis[0].normalize();
  102. axis[1].normalize();
  103. applyAnisotropicFriction( colObj0, axis[0], btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION );
  104. applyAnisotropicFriction( colObj1, axis[0], btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION );
  105. applyAnisotropicFriction( colObj0, axis[1], btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION );
  106. applyAnisotropicFriction( colObj1, axis[1], btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION );
  107. // put the largest axis first
  108. if (axis[1].length2() > axis[0].length2())
  109. {
  110. btSwap(axis[0], axis[1]);
  111. }
  112. const btScalar kRollingFrictionThreshold = 0.001f;
  113. for (int i = 0; i < 2; ++i)
  114. {
  115. int iRollingFric = rollingFrictionIndex + 1 + i;
  116. btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[ iRollingFric ];
  117. btAssert(rollingFrictionConstraint.m_frictionIndex == iContactConstraint);
  118. btVector3 dir = axis[i];
  119. if ( dir.length() > kRollingFrictionThreshold )
  120. {
  121. setupTorsionalFrictionConstraint( rollingFrictionConstraint,
  122. dir,
  123. solverBodyIdA,
  124. solverBodyIdB,
  125. cp,
  126. cp.m_combinedRollingFriction,
  127. rel_pos1,
  128. rel_pos2,
  129. colObj0,
  130. colObj1,
  131. relaxation,
  132. 0.0f,
  133. 0.0f
  134. );
  135. }
  136. else
  137. {
  138. rollingFrictionConstraint.m_frictionIndex = -1; // disable constraint
  139. }
  140. }
  141. }
  142. // setup friction constraints
  143. // setupFrictionConstraint(solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, desiredVelocity, cfmSlip);
  144. {
  145. ///Bullet has several options to set the friction directions
  146. ///By default, each contact has only a single friction direction that is recomputed automatically very frame
  147. ///based on the relative linear velocity.
  148. ///If the relative velocity it zero, it will automatically compute a friction direction.
  149. ///You can also enable two friction directions, using the SOLVER_USE_2_FRICTION_DIRECTIONS.
  150. ///In that case, the second friction direction will be orthogonal to both contact normal and first friction direction.
  151. ///
  152. ///If you choose SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION, then the friction will be independent from the relative projected velocity.
  153. ///
  154. ///The user can manually override the friction directions for certain contacts using a contact callback,
  155. ///and set the cp.m_lateralFrictionInitialized to true
  156. ///In that case, you can set the target relative motion in each friction direction (cp.m_contactMotion1 and cp.m_contactMotion2)
  157. ///this will give a conveyor belt effect
  158. ///
  159. btSolverConstraint* frictionConstraint1 = &m_tmpSolverContactFrictionConstraintPool[contactConstraint.m_frictionIndex];
  160. btAssert(frictionConstraint1->m_frictionIndex == iContactConstraint);
  161. btSolverConstraint* frictionConstraint2 = NULL;
  162. if ( infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS )
  163. {
  164. frictionConstraint2 = &m_tmpSolverContactFrictionConstraintPool[contactConstraint.m_frictionIndex + 1];
  165. btAssert( frictionConstraint2->m_frictionIndex == iContactConstraint );
  166. }
  167. if ( !( infoGlobal.m_solverMode & SOLVER_ENABLE_FRICTION_DIRECTION_CACHING ) || !( cp.m_contactPointFlags&BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED ) )
  168. {
  169. cp.m_lateralFrictionDir1 = vel - cp.m_normalWorldOnB * rel_vel;
  170. btScalar lat_rel_vel = cp.m_lateralFrictionDir1.length2();
  171. if ( !( infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION ) && lat_rel_vel > SIMD_EPSILON )
  172. {
  173. cp.m_lateralFrictionDir1 *= 1.f / btSqrt( lat_rel_vel );
  174. applyAnisotropicFriction( colObj0, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION );
  175. applyAnisotropicFriction( colObj1, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION );
  176. setupFrictionConstraint( *frictionConstraint1, cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal );
  177. if ( frictionConstraint2 )
  178. {
  179. cp.m_lateralFrictionDir2 = cp.m_lateralFrictionDir1.cross( cp.m_normalWorldOnB );
  180. cp.m_lateralFrictionDir2.normalize();//??
  181. applyAnisotropicFriction( colObj0, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION );
  182. applyAnisotropicFriction( colObj1, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION );
  183. setupFrictionConstraint( *frictionConstraint2, cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal );
  184. }
  185. }
  186. else
  187. {
  188. btPlaneSpace1( cp.m_normalWorldOnB, cp.m_lateralFrictionDir1, cp.m_lateralFrictionDir2 );
  189. applyAnisotropicFriction( colObj0, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION );
  190. applyAnisotropicFriction( colObj1, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION );
  191. setupFrictionConstraint( *frictionConstraint1, cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal );
  192. if ( frictionConstraint2 )
  193. {
  194. applyAnisotropicFriction( colObj0, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION );
  195. applyAnisotropicFriction( colObj1, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION );
  196. setupFrictionConstraint( *frictionConstraint2, cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal );
  197. }
  198. if ( ( infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS ) && ( infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION ) )
  199. {
  200. cp.m_contactPointFlags |= BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED;
  201. }
  202. }
  203. }
  204. else
  205. {
  206. setupFrictionConstraint( *frictionConstraint1, cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion1, cp.m_frictionCFM );
  207. if ( frictionConstraint2 )
  208. {
  209. setupFrictionConstraint( *frictionConstraint2, cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion2, cp.m_frictionCFM );
  210. }
  211. }
  212. }
  213. setFrictionConstraintImpulse( contactConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal );
  214. }
  215. struct SetupContactConstraintsLoop : public btIParallelForBody
  216. {
  217. btSequentialImpulseConstraintSolverMt* m_solver;
  218. const btBatchedConstraints* m_bc;
  219. const btContactSolverInfo* m_infoGlobal;
  220. SetupContactConstraintsLoop( btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc, const btContactSolverInfo& infoGlobal )
  221. {
  222. m_solver = solver;
  223. m_bc = bc;
  224. m_infoGlobal = &infoGlobal;
  225. }
  226. void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE
  227. {
  228. BT_PROFILE( "SetupContactConstraintsLoop" );
  229. for ( int iBatch = iBegin; iBatch < iEnd; ++iBatch )
  230. {
  231. const btBatchedConstraints::Range& batch = m_bc->m_batches[ iBatch ];
  232. for (int i = batch.begin; i < batch.end; ++i)
  233. {
  234. int iContact = m_bc->m_constraintIndices[i];
  235. m_solver->internalSetupContactConstraints( iContact, *m_infoGlobal );
  236. }
  237. }
  238. }
  239. };
  240. void btSequentialImpulseConstraintSolverMt::setupAllContactConstraints(const btContactSolverInfo& infoGlobal)
  241. {
  242. BT_PROFILE( "setupAllContactConstraints" );
  243. if ( m_useBatching )
  244. {
  245. const btBatchedConstraints& batchedCons = m_batchedContactConstraints;
  246. SetupContactConstraintsLoop loop( this, &batchedCons, infoGlobal );
  247. for ( int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase )
  248. {
  249. int iPhase = batchedCons.m_phaseOrder[ iiPhase ];
  250. const btBatchedConstraints::Range& phase = batchedCons.m_phases[ iPhase ];
  251. int grainSize = 1;
  252. btParallelFor( phase.begin, phase.end, grainSize, loop );
  253. }
  254. }
  255. else
  256. {
  257. for ( int i = 0; i < m_tmpSolverContactConstraintPool.size(); ++i )
  258. {
  259. internalSetupContactConstraints( i, infoGlobal );
  260. }
  261. }
  262. }
  263. int btSequentialImpulseConstraintSolverMt::getOrInitSolverBodyThreadsafe(btCollisionObject& body,btScalar timeStep)
  264. {
  265. //
  266. // getOrInitSolverBody is threadsafe only for a single thread per solver (with potentially multiple solvers)
  267. //
  268. // getOrInitSolverBodyThreadsafe -- attempts to be fully threadsafe (however may affect determinism)
  269. //
  270. int solverBodyId = -1;
  271. bool isRigidBodyType = btRigidBody::upcast( &body ) != NULL;
  272. if ( isRigidBodyType && !body.isStaticOrKinematicObject() )
  273. {
  274. // dynamic body
  275. // Dynamic bodies can only be in one island, so it's safe to write to the companionId
  276. solverBodyId = body.getCompanionId();
  277. if ( solverBodyId < 0 )
  278. {
  279. m_bodySolverArrayMutex.lock();
  280. // now that we have the lock, check again
  281. solverBodyId = body.getCompanionId();
  282. if ( solverBodyId < 0 )
  283. {
  284. solverBodyId = m_tmpSolverBodyPool.size();
  285. btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
  286. initSolverBody( &solverBody, &body, timeStep );
  287. body.setCompanionId( solverBodyId );
  288. }
  289. m_bodySolverArrayMutex.unlock();
  290. }
  291. }
  292. else if (isRigidBodyType && body.isKinematicObject())
  293. {
  294. //
  295. // NOTE: must test for kinematic before static because some kinematic objects also
  296. // identify as "static"
  297. //
  298. // Kinematic bodies can be in multiple islands at once, so it is a
  299. // race condition to write to them, so we use an alternate method
  300. // to record the solverBodyId
  301. int uniqueId = body.getWorldArrayIndex();
  302. const int INVALID_SOLVER_BODY_ID = -1;
  303. if (m_kinematicBodyUniqueIdToSolverBodyTable.size() <= uniqueId )
  304. {
  305. m_kinematicBodyUniqueIdToSolverBodyTableMutex.lock();
  306. // now that we have the lock, check again
  307. if ( m_kinematicBodyUniqueIdToSolverBodyTable.size() <= uniqueId )
  308. {
  309. m_kinematicBodyUniqueIdToSolverBodyTable.resize( uniqueId + 1, INVALID_SOLVER_BODY_ID );
  310. }
  311. m_kinematicBodyUniqueIdToSolverBodyTableMutex.unlock();
  312. }
  313. solverBodyId = m_kinematicBodyUniqueIdToSolverBodyTable[ uniqueId ];
  314. // if no table entry yet,
  315. if ( INVALID_SOLVER_BODY_ID == solverBodyId )
  316. {
  317. // need to acquire both locks
  318. m_kinematicBodyUniqueIdToSolverBodyTableMutex.lock();
  319. m_bodySolverArrayMutex.lock();
  320. // now that we have the lock, check again
  321. solverBodyId = m_kinematicBodyUniqueIdToSolverBodyTable[ uniqueId ];
  322. if ( INVALID_SOLVER_BODY_ID == solverBodyId )
  323. {
  324. // create a table entry for this body
  325. solverBodyId = m_tmpSolverBodyPool.size();
  326. btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
  327. initSolverBody( &solverBody, &body, timeStep );
  328. m_kinematicBodyUniqueIdToSolverBodyTable[ uniqueId ] = solverBodyId;
  329. }
  330. m_bodySolverArrayMutex.unlock();
  331. m_kinematicBodyUniqueIdToSolverBodyTableMutex.unlock();
  332. }
  333. }
  334. else
  335. {
  336. // all fixed bodies (inf mass) get mapped to a single solver id
  337. if ( m_fixedBodyId < 0 )
  338. {
  339. m_bodySolverArrayMutex.lock();
  340. // now that we have the lock, check again
  341. if ( m_fixedBodyId < 0 )
  342. {
  343. m_fixedBodyId = m_tmpSolverBodyPool.size();
  344. btSolverBody& fixedBody = m_tmpSolverBodyPool.expand();
  345. initSolverBody( &fixedBody, 0, timeStep );
  346. }
  347. m_bodySolverArrayMutex.unlock();
  348. }
  349. solverBodyId = m_fixedBodyId;
  350. }
  351. btAssert( solverBodyId >= 0 && solverBodyId < m_tmpSolverBodyPool.size() );
  352. return solverBodyId;
  353. }
  354. void btSequentialImpulseConstraintSolverMt::internalCollectContactManifoldCachedInfo(btContactManifoldCachedInfo* cachedInfoArray, btPersistentManifold** manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal)
  355. {
  356. BT_PROFILE("internalCollectContactManifoldCachedInfo");
  357. for (int i = 0; i < numManifolds; ++i)
  358. {
  359. btContactManifoldCachedInfo* cachedInfo = &cachedInfoArray[i];
  360. btPersistentManifold* manifold = manifoldPtr[i];
  361. btCollisionObject* colObj0 = (btCollisionObject*) manifold->getBody0();
  362. btCollisionObject* colObj1 = (btCollisionObject*) manifold->getBody1();
  363. int solverBodyIdA = getOrInitSolverBodyThreadsafe( *colObj0, infoGlobal.m_timeStep );
  364. int solverBodyIdB = getOrInitSolverBodyThreadsafe( *colObj1, infoGlobal.m_timeStep );
  365. cachedInfo->solverBodyIds[ 0 ] = solverBodyIdA;
  366. cachedInfo->solverBodyIds[ 1 ] = solverBodyIdB;
  367. cachedInfo->numTouchingContacts = 0;
  368. btSolverBody* solverBodyA = &m_tmpSolverBodyPool[ solverBodyIdA ];
  369. btSolverBody* solverBodyB = &m_tmpSolverBodyPool[ solverBodyIdB ];
  370. // A contact manifold between 2 static object should not exist!
  371. // check the collision flags of your objects if this assert fires.
  372. // Incorrectly set collision object flags can degrade performance in various ways.
  373. btAssert( !m_tmpSolverBodyPool[ solverBodyIdA ].m_invMass.isZero() || !m_tmpSolverBodyPool[ solverBodyIdB ].m_invMass.isZero() );
  374. int iContact = 0;
  375. for ( int j = 0; j < manifold->getNumContacts(); j++ )
  376. {
  377. btManifoldPoint& cp = manifold->getContactPoint( j );
  378. if ( cp.getDistance() <= manifold->getContactProcessingThreshold() )
  379. {
  380. cachedInfo->contactPoints[ iContact ] = &cp;
  381. cachedInfo->contactHasRollingFriction[ iContact ] = ( cp.m_combinedRollingFriction > 0.f );
  382. iContact++;
  383. }
  384. }
  385. cachedInfo->numTouchingContacts = iContact;
  386. }
  387. }
  388. struct CollectContactManifoldCachedInfoLoop : public btIParallelForBody
  389. {
  390. btSequentialImpulseConstraintSolverMt* m_solver;
  391. btSequentialImpulseConstraintSolverMt::btContactManifoldCachedInfo* m_cachedInfoArray;
  392. btPersistentManifold** m_manifoldPtr;
  393. const btContactSolverInfo* m_infoGlobal;
  394. CollectContactManifoldCachedInfoLoop( btSequentialImpulseConstraintSolverMt* solver, btSequentialImpulseConstraintSolverMt::btContactManifoldCachedInfo* cachedInfoArray, btPersistentManifold** manifoldPtr, const btContactSolverInfo& infoGlobal )
  395. {
  396. m_solver = solver;
  397. m_cachedInfoArray = cachedInfoArray;
  398. m_manifoldPtr = manifoldPtr;
  399. m_infoGlobal = &infoGlobal;
  400. }
  401. void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE
  402. {
  403. m_solver->internalCollectContactManifoldCachedInfo( m_cachedInfoArray + iBegin, m_manifoldPtr + iBegin, iEnd - iBegin, *m_infoGlobal );
  404. }
  405. };
  406. void btSequentialImpulseConstraintSolverMt::internalAllocContactConstraints(const btContactManifoldCachedInfo* cachedInfoArray, int numManifolds)
  407. {
  408. BT_PROFILE("internalAllocContactConstraints");
  409. // possibly parallel part
  410. for ( int iManifold = 0; iManifold < numManifolds; ++iManifold )
  411. {
  412. const btContactManifoldCachedInfo& cachedInfo = cachedInfoArray[ iManifold ];
  413. int contactIndex = cachedInfo.contactIndex;
  414. int frictionIndex = contactIndex * m_numFrictionDirections;
  415. int rollingFrictionIndex = cachedInfo.rollingFrictionIndex;
  416. for ( int i = 0; i < cachedInfo.numTouchingContacts; i++ )
  417. {
  418. btSolverConstraint& contactConstraint = m_tmpSolverContactConstraintPool[contactIndex];
  419. contactConstraint.m_solverBodyIdA = cachedInfo.solverBodyIds[ 0 ];
  420. contactConstraint.m_solverBodyIdB = cachedInfo.solverBodyIds[ 1 ];
  421. contactConstraint.m_originalContactPoint = cachedInfo.contactPoints[ i ];
  422. // allocate the friction constraints
  423. contactConstraint.m_frictionIndex = frictionIndex;
  424. for ( int iDir = 0; iDir < m_numFrictionDirections; ++iDir )
  425. {
  426. btSolverConstraint& frictionConstraint = m_tmpSolverContactFrictionConstraintPool[frictionIndex];
  427. frictionConstraint.m_frictionIndex = contactIndex;
  428. frictionIndex++;
  429. }
  430. // allocate rolling friction constraints
  431. if ( cachedInfo.contactHasRollingFriction[ i ] )
  432. {
  433. m_rollingFrictionIndexTable[ contactIndex ] = rollingFrictionIndex;
  434. // allocate 3 (although we may use only 2 sometimes)
  435. for ( int i = 0; i < 3; i++ )
  436. {
  437. m_tmpSolverContactRollingFrictionConstraintPool[ rollingFrictionIndex ].m_frictionIndex = contactIndex;
  438. rollingFrictionIndex++;
  439. }
  440. }
  441. else
  442. {
  443. // indicate there is no rolling friction for this contact point
  444. m_rollingFrictionIndexTable[ contactIndex ] = -1;
  445. }
  446. contactIndex++;
  447. }
  448. }
  449. }
  450. struct AllocContactConstraintsLoop : public btIParallelForBody
  451. {
  452. btSequentialImpulseConstraintSolverMt* m_solver;
  453. const btSequentialImpulseConstraintSolverMt::btContactManifoldCachedInfo* m_cachedInfoArray;
  454. AllocContactConstraintsLoop( btSequentialImpulseConstraintSolverMt* solver, btSequentialImpulseConstraintSolverMt::btContactManifoldCachedInfo* cachedInfoArray )
  455. {
  456. m_solver = solver;
  457. m_cachedInfoArray = cachedInfoArray;
  458. }
  459. void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE
  460. {
  461. m_solver->internalAllocContactConstraints( m_cachedInfoArray + iBegin, iEnd - iBegin );
  462. }
  463. };
  464. void btSequentialImpulseConstraintSolverMt::allocAllContactConstraints(btPersistentManifold** manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal)
  465. {
  466. BT_PROFILE( "allocAllContactConstraints" );
  467. btAlignedObjectArray<btContactManifoldCachedInfo> cachedInfoArray; // = m_manifoldCachedInfoArray;
  468. cachedInfoArray.resizeNoInitialize( numManifolds );
  469. if (/* DISABLES CODE */ (false))
  470. {
  471. // sequential
  472. internalCollectContactManifoldCachedInfo(&cachedInfoArray[ 0 ], manifoldPtr, numManifolds, infoGlobal);
  473. }
  474. else
  475. {
  476. // may alter ordering of bodies which affects determinism
  477. CollectContactManifoldCachedInfoLoop loop( this, &cachedInfoArray[ 0 ], manifoldPtr, infoGlobal );
  478. int grainSize = 200;
  479. btParallelFor( 0, numManifolds, grainSize, loop );
  480. }
  481. {
  482. // serial part
  483. int numContacts = 0;
  484. int numRollingFrictionConstraints = 0;
  485. for ( int iManifold = 0; iManifold < numManifolds; ++iManifold )
  486. {
  487. btContactManifoldCachedInfo& cachedInfo = cachedInfoArray[ iManifold ];
  488. cachedInfo.contactIndex = numContacts;
  489. cachedInfo.rollingFrictionIndex = numRollingFrictionConstraints;
  490. numContacts += cachedInfo.numTouchingContacts;
  491. for (int i = 0; i < cachedInfo.numTouchingContacts; ++i)
  492. {
  493. if (cachedInfo.contactHasRollingFriction[i])
  494. {
  495. numRollingFrictionConstraints += 3;
  496. }
  497. }
  498. }
  499. {
  500. BT_PROFILE( "allocPools" );
  501. if ( m_tmpSolverContactConstraintPool.capacity() < numContacts )
  502. {
  503. // if we need to reallocate, reserve some extra so we don't have to reallocate again next frame
  504. int extraReserve = numContacts / 16;
  505. m_tmpSolverContactConstraintPool.reserve( numContacts + extraReserve );
  506. m_rollingFrictionIndexTable.reserve( numContacts + extraReserve );
  507. m_tmpSolverContactFrictionConstraintPool.reserve( ( numContacts + extraReserve )*m_numFrictionDirections );
  508. m_tmpSolverContactRollingFrictionConstraintPool.reserve( numRollingFrictionConstraints + extraReserve );
  509. }
  510. m_tmpSolverContactConstraintPool.resizeNoInitialize( numContacts );
  511. m_rollingFrictionIndexTable.resizeNoInitialize( numContacts );
  512. m_tmpSolverContactFrictionConstraintPool.resizeNoInitialize( numContacts*m_numFrictionDirections );
  513. m_tmpSolverContactRollingFrictionConstraintPool.resizeNoInitialize( numRollingFrictionConstraints );
  514. }
  515. }
  516. {
  517. AllocContactConstraintsLoop loop(this, &cachedInfoArray[0]);
  518. int grainSize = 200;
  519. btParallelFor( 0, numManifolds, grainSize, loop );
  520. }
  521. }
  522. void btSequentialImpulseConstraintSolverMt::convertContacts(btPersistentManifold** manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal)
  523. {
  524. if (!m_useBatching)
  525. {
  526. btSequentialImpulseConstraintSolver::convertContacts(manifoldPtr, numManifolds, infoGlobal);
  527. return;
  528. }
  529. BT_PROFILE( "convertContacts" );
  530. if (numManifolds > 0)
  531. {
  532. if ( m_fixedBodyId < 0 )
  533. {
  534. m_fixedBodyId = m_tmpSolverBodyPool.size();
  535. btSolverBody& fixedBody = m_tmpSolverBodyPool.expand();
  536. initSolverBody( &fixedBody, 0, infoGlobal.m_timeStep );
  537. }
  538. allocAllContactConstraints( manifoldPtr, numManifolds, infoGlobal );
  539. if ( m_useBatching )
  540. {
  541. setupBatchedContactConstraints();
  542. }
  543. setupAllContactConstraints( infoGlobal );
  544. }
  545. }
  546. void btSequentialImpulseConstraintSolverMt::internalInitMultipleJoints( btTypedConstraint** constraints, int iBegin, int iEnd )
  547. {
  548. BT_PROFILE("internalInitMultipleJoints");
  549. for ( int i = iBegin; i < iEnd; i++ )
  550. {
  551. btTypedConstraint* constraint = constraints[i];
  552. btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
  553. if (constraint->isEnabled())
  554. {
  555. constraint->buildJacobian();
  556. constraint->internalSetAppliedImpulse( 0.0f );
  557. btJointFeedback* fb = constraint->getJointFeedback();
  558. if ( fb )
  559. {
  560. fb->m_appliedForceBodyA.setZero();
  561. fb->m_appliedTorqueBodyA.setZero();
  562. fb->m_appliedForceBodyB.setZero();
  563. fb->m_appliedTorqueBodyB.setZero();
  564. }
  565. constraint->getInfo1( &info1 );
  566. }
  567. else
  568. {
  569. info1.m_numConstraintRows = 0;
  570. info1.nub = 0;
  571. }
  572. }
  573. }
  574. struct InitJointsLoop : public btIParallelForBody
  575. {
  576. btSequentialImpulseConstraintSolverMt* m_solver;
  577. btTypedConstraint** m_constraints;
  578. InitJointsLoop( btSequentialImpulseConstraintSolverMt* solver, btTypedConstraint** constraints )
  579. {
  580. m_solver = solver;
  581. m_constraints = constraints;
  582. }
  583. void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE
  584. {
  585. m_solver->internalInitMultipleJoints( m_constraints, iBegin, iEnd );
  586. }
  587. };
  588. void btSequentialImpulseConstraintSolverMt::internalConvertMultipleJoints( const btAlignedObjectArray<JointParams>& jointParamsArray, btTypedConstraint** constraints, int iBegin, int iEnd, const btContactSolverInfo& infoGlobal )
  589. {
  590. BT_PROFILE("internalConvertMultipleJoints");
  591. for ( int i = iBegin; i < iEnd; ++i )
  592. {
  593. const JointParams& jointParams = jointParamsArray[ i ];
  594. int currentRow = jointParams.m_solverConstraint;
  595. if ( currentRow != -1 )
  596. {
  597. const btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[ i ];
  598. btAssert( currentRow < m_tmpSolverNonContactConstraintPool.size() );
  599. btAssert( info1.m_numConstraintRows > 0 );
  600. btSolverConstraint* currentConstraintRow = &m_tmpSolverNonContactConstraintPool[ currentRow ];
  601. btTypedConstraint* constraint = constraints[ i ];
  602. convertJoint( currentConstraintRow, constraint, info1, jointParams.m_solverBodyA, jointParams.m_solverBodyB, infoGlobal );
  603. }
  604. }
  605. }
  606. struct ConvertJointsLoop : public btIParallelForBody
  607. {
  608. btSequentialImpulseConstraintSolverMt* m_solver;
  609. const btAlignedObjectArray<btSequentialImpulseConstraintSolverMt::JointParams>& m_jointParamsArray;
  610. btTypedConstraint** m_srcConstraints;
  611. const btContactSolverInfo& m_infoGlobal;
  612. ConvertJointsLoop( btSequentialImpulseConstraintSolverMt* solver,
  613. const btAlignedObjectArray<btSequentialImpulseConstraintSolverMt::JointParams>& jointParamsArray,
  614. btTypedConstraint** srcConstraints,
  615. const btContactSolverInfo& infoGlobal
  616. ) :
  617. m_jointParamsArray(jointParamsArray),
  618. m_infoGlobal(infoGlobal)
  619. {
  620. m_solver = solver;
  621. m_srcConstraints = srcConstraints;
  622. }
  623. void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE
  624. {
  625. m_solver->internalConvertMultipleJoints( m_jointParamsArray, m_srcConstraints, iBegin, iEnd, m_infoGlobal );
  626. }
  627. };
  628. void btSequentialImpulseConstraintSolverMt::convertJoints(btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal)
  629. {
  630. if ( !m_useBatching )
  631. {
  632. btSequentialImpulseConstraintSolver::convertJoints(constraints, numConstraints, infoGlobal);
  633. return;
  634. }
  635. BT_PROFILE("convertJoints");
  636. bool parallelJointSetup = true;
  637. m_tmpConstraintSizesPool.resizeNoInitialize(numConstraints);
  638. if (parallelJointSetup)
  639. {
  640. InitJointsLoop loop(this, constraints);
  641. int grainSize = 40;
  642. btParallelFor(0, numConstraints, grainSize, loop);
  643. }
  644. else
  645. {
  646. internalInitMultipleJoints( constraints, 0, numConstraints );
  647. }
  648. int totalNumRows = 0;
  649. btAlignedObjectArray<JointParams> jointParamsArray;
  650. jointParamsArray.resizeNoInitialize(numConstraints);
  651. //calculate the total number of contraint rows
  652. for (int i=0;i<numConstraints;i++)
  653. {
  654. btTypedConstraint* constraint = constraints[ i ];
  655. JointParams& params = jointParamsArray[ i ];
  656. const btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
  657. if (info1.m_numConstraintRows)
  658. {
  659. params.m_solverConstraint = totalNumRows;
  660. params.m_solverBodyA = getOrInitSolverBody( constraint->getRigidBodyA(), infoGlobal.m_timeStep );
  661. params.m_solverBodyB = getOrInitSolverBody( constraint->getRigidBodyB(), infoGlobal.m_timeStep );
  662. }
  663. else
  664. {
  665. params.m_solverConstraint = -1;
  666. }
  667. totalNumRows += info1.m_numConstraintRows;
  668. }
  669. m_tmpSolverNonContactConstraintPool.resizeNoInitialize(totalNumRows);
  670. ///setup the btSolverConstraints
  671. if ( parallelJointSetup )
  672. {
  673. ConvertJointsLoop loop(this, jointParamsArray, constraints, infoGlobal);
  674. int grainSize = 20;
  675. btParallelFor(0, numConstraints, grainSize, loop);
  676. }
  677. else
  678. {
  679. internalConvertMultipleJoints( jointParamsArray, constraints, 0, numConstraints, infoGlobal );
  680. }
  681. setupBatchedJointConstraints();
  682. }
  683. void btSequentialImpulseConstraintSolverMt::internalConvertBodies(btCollisionObject** bodies, int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
  684. {
  685. BT_PROFILE("internalConvertBodies");
  686. for (int i=iBegin; i < iEnd; i++)
  687. {
  688. btCollisionObject* obj = bodies[i];
  689. obj->setCompanionId(i);
  690. btSolverBody& solverBody = m_tmpSolverBodyPool[i];
  691. initSolverBody(&solverBody, obj, infoGlobal.m_timeStep);
  692. btRigidBody* body = btRigidBody::upcast(obj);
  693. if (body && body->getInvMass())
  694. {
  695. btVector3 gyroForce (0,0,0);
  696. if (body->getFlags()&BT_ENABLE_GYROSCOPIC_FORCE_EXPLICIT)
  697. {
  698. gyroForce = body->computeGyroscopicForceExplicit(infoGlobal.m_maxGyroscopicForce);
  699. solverBody.m_externalTorqueImpulse -= gyroForce*body->getInvInertiaTensorWorld()*infoGlobal.m_timeStep;
  700. }
  701. if (body->getFlags()&BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_WORLD)
  702. {
  703. gyroForce = body->computeGyroscopicImpulseImplicit_World(infoGlobal.m_timeStep);
  704. solverBody.m_externalTorqueImpulse += gyroForce;
  705. }
  706. if (body->getFlags()&BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_BODY)
  707. {
  708. gyroForce = body->computeGyroscopicImpulseImplicit_Body(infoGlobal.m_timeStep);
  709. solverBody.m_externalTorqueImpulse += gyroForce;
  710. }
  711. }
  712. }
  713. }
  714. struct ConvertBodiesLoop : public btIParallelForBody
  715. {
  716. btSequentialImpulseConstraintSolverMt* m_solver;
  717. btCollisionObject** m_bodies;
  718. int m_numBodies;
  719. const btContactSolverInfo& m_infoGlobal;
  720. ConvertBodiesLoop( btSequentialImpulseConstraintSolverMt* solver,
  721. btCollisionObject** bodies,
  722. int numBodies,
  723. const btContactSolverInfo& infoGlobal
  724. ) :
  725. m_infoGlobal(infoGlobal)
  726. {
  727. m_solver = solver;
  728. m_bodies = bodies;
  729. m_numBodies = numBodies;
  730. }
  731. void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE
  732. {
  733. m_solver->internalConvertBodies( m_bodies, iBegin, iEnd, m_infoGlobal );
  734. }
  735. };
  736. void btSequentialImpulseConstraintSolverMt::convertBodies(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal)
  737. {
  738. BT_PROFILE("convertBodies");
  739. m_kinematicBodyUniqueIdToSolverBodyTable.resize( 0 );
  740. m_tmpSolverBodyPool.resizeNoInitialize(numBodies+1);
  741. m_fixedBodyId = numBodies;
  742. {
  743. btSolverBody& fixedBody = m_tmpSolverBodyPool[ m_fixedBodyId ];
  744. initSolverBody( &fixedBody, NULL, infoGlobal.m_timeStep );
  745. }
  746. bool parallelBodySetup = true;
  747. if (parallelBodySetup)
  748. {
  749. ConvertBodiesLoop loop(this, bodies, numBodies, infoGlobal);
  750. int grainSize = 40;
  751. btParallelFor(0, numBodies, grainSize, loop);
  752. }
  753. else
  754. {
  755. internalConvertBodies( bodies, 0, numBodies, infoGlobal );
  756. }
  757. }
  758. btScalar btSequentialImpulseConstraintSolverMt::solveGroupCacheFriendlySetup(
  759. btCollisionObject** bodies,
  760. int numBodies,
  761. btPersistentManifold** manifoldPtr,
  762. int numManifolds,
  763. btTypedConstraint** constraints,
  764. int numConstraints,
  765. const btContactSolverInfo& infoGlobal,
  766. btIDebugDraw* debugDrawer
  767. )
  768. {
  769. m_numFrictionDirections = (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) ? 2 : 1;
  770. m_useBatching = false;
  771. if ( numManifolds >= s_minimumContactManifoldsForBatching &&
  772. (s_allowNestedParallelForLoops || !btThreadsAreRunning())
  773. )
  774. {
  775. m_useBatching = true;
  776. m_batchedContactConstraints.m_debugDrawer = debugDrawer;
  777. m_batchedJointConstraints.m_debugDrawer = debugDrawer;
  778. }
  779. btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup( bodies,
  780. numBodies,
  781. manifoldPtr,
  782. numManifolds,
  783. constraints,
  784. numConstraints,
  785. infoGlobal,
  786. debugDrawer
  787. );
  788. return 0.0f;
  789. }
  790. btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactSplitPenetrationImpulseConstraints( const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd )
  791. {
  792. btScalar leastSquaresResidual = 0.f;
  793. for ( int iiCons = batchBegin; iiCons < batchEnd; ++iiCons )
  794. {
  795. int iCons = consIndices[ iiCons ];
  796. const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[ iCons ];
  797. btSolverBody& bodyA = m_tmpSolverBodyPool[ solveManifold.m_solverBodyIdA ];
  798. btSolverBody& bodyB = m_tmpSolverBodyPool[ solveManifold.m_solverBodyIdB ];
  799. btScalar residual = resolveSplitPenetrationImpulse( bodyA, bodyB, solveManifold );
  800. leastSquaresResidual += residual*residual;
  801. }
  802. return leastSquaresResidual;
  803. }
  804. struct ContactSplitPenetrationImpulseSolverLoop : public btIParallelSumBody
  805. {
  806. btSequentialImpulseConstraintSolverMt* m_solver;
  807. const btBatchedConstraints* m_bc;
  808. ContactSplitPenetrationImpulseSolverLoop( btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc )
  809. {
  810. m_solver = solver;
  811. m_bc = bc;
  812. }
  813. btScalar sumLoop( int iBegin, int iEnd ) const BT_OVERRIDE
  814. {
  815. BT_PROFILE( "ContactSplitPenetrationImpulseSolverLoop" );
  816. btScalar sum = 0;
  817. for ( int iBatch = iBegin; iBatch < iEnd; ++iBatch )
  818. {
  819. const btBatchedConstraints::Range& batch = m_bc->m_batches[ iBatch ];
  820. sum += m_solver->resolveMultipleContactSplitPenetrationImpulseConstraints( m_bc->m_constraintIndices, batch.begin, batch.end );
  821. }
  822. return sum;
  823. }
  824. };
  825. void btSequentialImpulseConstraintSolverMt::solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer)
  826. {
  827. BT_PROFILE("solveGroupCacheFriendlySplitImpulseIterations");
  828. if (infoGlobal.m_splitImpulse)
  829. {
  830. for ( int iteration = 0; iteration < infoGlobal.m_numIterations; iteration++ )
  831. {
  832. btScalar leastSquaresResidual = 0.f;
  833. if (m_useBatching)
  834. {
  835. const btBatchedConstraints& batchedCons = m_batchedContactConstraints;
  836. ContactSplitPenetrationImpulseSolverLoop loop( this, &batchedCons );
  837. btScalar leastSquaresResidual = 0.f;
  838. for ( int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase )
  839. {
  840. int iPhase = batchedCons.m_phaseOrder[ iiPhase ];
  841. const btBatchedConstraints::Range& phase = batchedCons.m_phases[ iPhase ];
  842. int grainSize = batchedCons.m_phaseGrainSize[iPhase];
  843. leastSquaresResidual += btParallelSum( phase.begin, phase.end, grainSize, loop );
  844. }
  845. }
  846. else
  847. {
  848. // non-batched
  849. leastSquaresResidual = resolveMultipleContactSplitPenetrationImpulseConstraints(m_orderTmpConstraintPool, 0, m_tmpSolverContactConstraintPool.size());
  850. }
  851. if ( leastSquaresResidual <= infoGlobal.m_leastSquaresResidualThreshold || iteration >= ( infoGlobal.m_numIterations - 1 ) )
  852. {
  853. #ifdef VERBOSE_RESIDUAL_PRINTF
  854. printf( "residual = %f at iteration #%d\n", leastSquaresResidual, iteration );
  855. #endif
  856. break;
  857. }
  858. }
  859. }
  860. }
  861. btScalar btSequentialImpulseConstraintSolverMt::solveSingleIteration(int iteration, btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer)
  862. {
  863. if ( !m_useBatching )
  864. {
  865. return btSequentialImpulseConstraintSolver::solveSingleIteration( iteration, bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer );
  866. }
  867. BT_PROFILE( "solveSingleIterationMt" );
  868. btScalar leastSquaresResidual = 0.f;
  869. if (infoGlobal.m_solverMode & SOLVER_RANDMIZE_ORDER)
  870. {
  871. if (1) // uncomment this for a bit less random ((iteration & 7) == 0)
  872. {
  873. randomizeConstraintOrdering(iteration, infoGlobal.m_numIterations);
  874. }
  875. }
  876. {
  877. ///solve all joint constraints
  878. leastSquaresResidual += resolveAllJointConstraints(iteration);
  879. if (iteration< infoGlobal.m_numIterations)
  880. {
  881. // this loop is only used for cone-twist constraints,
  882. // it would be nice to skip this loop if none of the constraints need it
  883. if ( m_useObsoleteJointConstraints )
  884. {
  885. for ( int j = 0; j<numConstraints; j++ )
  886. {
  887. if ( constraints[ j ]->isEnabled() )
  888. {
  889. int bodyAid = getOrInitSolverBody( constraints[ j ]->getRigidBodyA(), infoGlobal.m_timeStep );
  890. int bodyBid = getOrInitSolverBody( constraints[ j ]->getRigidBodyB(), infoGlobal.m_timeStep );
  891. btSolverBody& bodyA = m_tmpSolverBodyPool[ bodyAid ];
  892. btSolverBody& bodyB = m_tmpSolverBodyPool[ bodyBid ];
  893. constraints[ j ]->solveConstraintObsolete( bodyA, bodyB, infoGlobal.m_timeStep );
  894. }
  895. }
  896. }
  897. if (infoGlobal.m_solverMode & SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS)
  898. {
  899. // solve all contact, contact-friction, and rolling friction constraints interleaved
  900. leastSquaresResidual += resolveAllContactConstraintsInterleaved();
  901. }
  902. else//SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS
  903. {
  904. // don't interleave them
  905. // solve all contact constraints
  906. leastSquaresResidual += resolveAllContactConstraints();
  907. // solve all contact friction constraints
  908. leastSquaresResidual += resolveAllContactFrictionConstraints();
  909. // solve all rolling friction constraints
  910. leastSquaresResidual += resolveAllRollingFrictionConstraints();
  911. }
  912. }
  913. }
  914. return leastSquaresResidual;
  915. }
  916. btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleJointConstraints( const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd, int iteration )
  917. {
  918. btScalar leastSquaresResidual = 0.f;
  919. for ( int iiCons = batchBegin; iiCons < batchEnd; ++iiCons )
  920. {
  921. int iCons = consIndices[ iiCons ];
  922. const btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[ iCons ];
  923. if ( iteration < constraint.m_overrideNumSolverIterations )
  924. {
  925. btSolverBody& bodyA = m_tmpSolverBodyPool[ constraint.m_solverBodyIdA ];
  926. btSolverBody& bodyB = m_tmpSolverBodyPool[ constraint.m_solverBodyIdB ];
  927. btScalar residual = resolveSingleConstraintRowGeneric( bodyA, bodyB, constraint );
  928. leastSquaresResidual += residual*residual;
  929. }
  930. }
  931. return leastSquaresResidual;
  932. }
  933. btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactConstraints( const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd )
  934. {
  935. btScalar leastSquaresResidual = 0.f;
  936. for ( int iiCons = batchBegin; iiCons < batchEnd; ++iiCons )
  937. {
  938. int iCons = consIndices[ iiCons ];
  939. const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[ iCons ];
  940. btSolverBody& bodyA = m_tmpSolverBodyPool[ solveManifold.m_solverBodyIdA ];
  941. btSolverBody& bodyB = m_tmpSolverBodyPool[ solveManifold.m_solverBodyIdB ];
  942. btScalar residual = resolveSingleConstraintRowLowerLimit( bodyA, bodyB, solveManifold );
  943. leastSquaresResidual += residual*residual;
  944. }
  945. return leastSquaresResidual;
  946. }
  947. btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactFrictionConstraints( const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd )
  948. {
  949. btScalar leastSquaresResidual = 0.f;
  950. for ( int iiCons = batchBegin; iiCons < batchEnd; ++iiCons )
  951. {
  952. int iContact = consIndices[ iiCons ];
  953. btScalar totalImpulse = m_tmpSolverContactConstraintPool[ iContact ].m_appliedImpulse;
  954. // apply sliding friction
  955. if ( totalImpulse > 0.0f )
  956. {
  957. int iBegin = iContact * m_numFrictionDirections;
  958. int iEnd = iBegin + m_numFrictionDirections;
  959. for ( int iFriction = iBegin; iFriction < iEnd; ++iFriction )
  960. {
  961. btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[ iFriction++ ];
  962. btAssert( solveManifold.m_frictionIndex == iContact );
  963. solveManifold.m_lowerLimit = -( solveManifold.m_friction*totalImpulse );
  964. solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse;
  965. btSolverBody& bodyA = m_tmpSolverBodyPool[ solveManifold.m_solverBodyIdA ];
  966. btSolverBody& bodyB = m_tmpSolverBodyPool[ solveManifold.m_solverBodyIdB ];
  967. btScalar residual = resolveSingleConstraintRowGeneric( bodyA, bodyB, solveManifold );
  968. leastSquaresResidual += residual*residual;
  969. }
  970. }
  971. }
  972. return leastSquaresResidual;
  973. }
  974. btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactRollingFrictionConstraints( const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd )
  975. {
  976. btScalar leastSquaresResidual = 0.f;
  977. for ( int iiCons = batchBegin; iiCons < batchEnd; ++iiCons )
  978. {
  979. int iContact = consIndices[ iiCons ];
  980. int iFirstRollingFriction = m_rollingFrictionIndexTable[ iContact ];
  981. if ( iFirstRollingFriction >= 0 )
  982. {
  983. btScalar totalImpulse = m_tmpSolverContactConstraintPool[ iContact ].m_appliedImpulse;
  984. // apply rolling friction
  985. if ( totalImpulse > 0.0f )
  986. {
  987. int iBegin = iFirstRollingFriction;
  988. int iEnd = iBegin + 3;
  989. for ( int iRollingFric = iBegin; iRollingFric < iEnd; ++iRollingFric )
  990. {
  991. btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[ iRollingFric ];
  992. if ( rollingFrictionConstraint.m_frictionIndex != iContact )
  993. {
  994. break;
  995. }
  996. btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction*totalImpulse;
  997. if ( rollingFrictionMagnitude > rollingFrictionConstraint.m_friction )
  998. {
  999. rollingFrictionMagnitude = rollingFrictionConstraint.m_friction;
  1000. }
  1001. rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
  1002. rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
  1003. btScalar residual = resolveSingleConstraintRowGeneric( m_tmpSolverBodyPool[ rollingFrictionConstraint.m_solverBodyIdA ], m_tmpSolverBodyPool[ rollingFrictionConstraint.m_solverBodyIdB ], rollingFrictionConstraint );
  1004. leastSquaresResidual += residual*residual;
  1005. }
  1006. }
  1007. }
  1008. }
  1009. return leastSquaresResidual;
  1010. }
  1011. btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactConstraintsInterleaved( const btAlignedObjectArray<int>& contactIndices,
  1012. int batchBegin,
  1013. int batchEnd
  1014. )
  1015. {
  1016. btScalar leastSquaresResidual = 0.f;
  1017. int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
  1018. for ( int iiCons = batchBegin; iiCons < batchEnd; iiCons++ )
  1019. {
  1020. btScalar totalImpulse = 0;
  1021. int iContact = contactIndices[ iiCons ];
  1022. // apply penetration constraint
  1023. {
  1024. const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[ iContact ];
  1025. btScalar residual = resolveSingleConstraintRowLowerLimit( m_tmpSolverBodyPool[ solveManifold.m_solverBodyIdA ], m_tmpSolverBodyPool[ solveManifold.m_solverBodyIdB ], solveManifold );
  1026. leastSquaresResidual += residual*residual;
  1027. totalImpulse = solveManifold.m_appliedImpulse;
  1028. }
  1029. // apply sliding friction
  1030. if ( totalImpulse > 0.0f )
  1031. {
  1032. int iBegin = iContact * m_numFrictionDirections;
  1033. int iEnd = iBegin + m_numFrictionDirections;
  1034. for ( int iFriction = iBegin; iFriction < iEnd; ++iFriction )
  1035. {
  1036. btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[ iFriction ];
  1037. btAssert( solveManifold.m_frictionIndex == iContact );
  1038. solveManifold.m_lowerLimit = -( solveManifold.m_friction*totalImpulse );
  1039. solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse;
  1040. btSolverBody& bodyA = m_tmpSolverBodyPool[ solveManifold.m_solverBodyIdA ];
  1041. btSolverBody& bodyB = m_tmpSolverBodyPool[ solveManifold.m_solverBodyIdB ];
  1042. btScalar residual = resolveSingleConstraintRowGeneric( bodyA, bodyB, solveManifold );
  1043. leastSquaresResidual += residual*residual;
  1044. }
  1045. }
  1046. // apply rolling friction
  1047. int iFirstRollingFriction = m_rollingFrictionIndexTable[ iContact ];
  1048. if ( totalImpulse > 0.0f && iFirstRollingFriction >= 0)
  1049. {
  1050. int iBegin = iFirstRollingFriction;
  1051. int iEnd = iBegin + 3;
  1052. for ( int iRollingFric = iBegin; iRollingFric < iEnd; ++iRollingFric )
  1053. {
  1054. btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[ iRollingFric ];
  1055. if ( rollingFrictionConstraint.m_frictionIndex != iContact )
  1056. {
  1057. break;
  1058. }
  1059. btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction*totalImpulse;
  1060. if ( rollingFrictionMagnitude > rollingFrictionConstraint.m_friction )
  1061. {
  1062. rollingFrictionMagnitude = rollingFrictionConstraint.m_friction;
  1063. }
  1064. rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
  1065. rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
  1066. btScalar residual = resolveSingleConstraintRowGeneric( m_tmpSolverBodyPool[ rollingFrictionConstraint.m_solverBodyIdA ], m_tmpSolverBodyPool[ rollingFrictionConstraint.m_solverBodyIdB ], rollingFrictionConstraint );
  1067. leastSquaresResidual += residual*residual;
  1068. }
  1069. }
  1070. }
  1071. return leastSquaresResidual;
  1072. }
  1073. void btSequentialImpulseConstraintSolverMt::randomizeBatchedConstraintOrdering( btBatchedConstraints* batchedConstraints )
  1074. {
  1075. btBatchedConstraints& bc = *batchedConstraints;
  1076. // randomize ordering of phases
  1077. for ( int ii = 1; ii < bc.m_phaseOrder.size(); ++ii )
  1078. {
  1079. int iSwap = btRandInt2( ii + 1 );
  1080. bc.m_phaseOrder.swap( ii, iSwap );
  1081. }
  1082. // for each batch,
  1083. for ( int iBatch = 0; iBatch < bc.m_batches.size(); ++iBatch )
  1084. {
  1085. // randomize ordering of constraints within the batch
  1086. const btBatchedConstraints::Range& batch = bc.m_batches[ iBatch ];
  1087. for ( int iiCons = batch.begin; iiCons < batch.end; ++iiCons )
  1088. {
  1089. int iSwap = batch.begin + btRandInt2( iiCons - batch.begin + 1 );
  1090. btAssert(iSwap >= batch.begin && iSwap < batch.end);
  1091. bc.m_constraintIndices.swap( iiCons, iSwap );
  1092. }
  1093. }
  1094. }
  1095. void btSequentialImpulseConstraintSolverMt::randomizeConstraintOrdering(int iteration, int numIterations)
  1096. {
  1097. // randomize ordering of joint constraints
  1098. randomizeBatchedConstraintOrdering( &m_batchedJointConstraints );
  1099. //contact/friction constraints are not solved more than numIterations
  1100. if ( iteration < numIterations )
  1101. {
  1102. randomizeBatchedConstraintOrdering( &m_batchedContactConstraints );
  1103. }
  1104. }
  1105. struct JointSolverLoop : public btIParallelSumBody
  1106. {
  1107. btSequentialImpulseConstraintSolverMt* m_solver;
  1108. const btBatchedConstraints* m_bc;
  1109. int m_iteration;
  1110. JointSolverLoop( btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc, int iteration )
  1111. {
  1112. m_solver = solver;
  1113. m_bc = bc;
  1114. m_iteration = iteration;
  1115. }
  1116. btScalar sumLoop( int iBegin, int iEnd ) const BT_OVERRIDE
  1117. {
  1118. BT_PROFILE( "JointSolverLoop" );
  1119. btScalar sum = 0;
  1120. for ( int iBatch = iBegin; iBatch < iEnd; ++iBatch )
  1121. {
  1122. const btBatchedConstraints::Range& batch = m_bc->m_batches[ iBatch ];
  1123. sum += m_solver->resolveMultipleJointConstraints( m_bc->m_constraintIndices, batch.begin, batch.end, m_iteration );
  1124. }
  1125. return sum;
  1126. }
  1127. };
  1128. btScalar btSequentialImpulseConstraintSolverMt::resolveAllJointConstraints(int iteration)
  1129. {
  1130. BT_PROFILE( "resolveAllJointConstraints" );
  1131. const btBatchedConstraints& batchedCons = m_batchedJointConstraints;
  1132. JointSolverLoop loop( this, &batchedCons, iteration );
  1133. btScalar leastSquaresResidual = 0.f;
  1134. for ( int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase )
  1135. {
  1136. int iPhase = batchedCons.m_phaseOrder[ iiPhase ];
  1137. const btBatchedConstraints::Range& phase = batchedCons.m_phases[ iPhase ];
  1138. int grainSize = 1;
  1139. leastSquaresResidual += btParallelSum( phase.begin, phase.end, grainSize, loop );
  1140. }
  1141. return leastSquaresResidual;
  1142. }
  1143. struct ContactSolverLoop : public btIParallelSumBody
  1144. {
  1145. btSequentialImpulseConstraintSolverMt* m_solver;
  1146. const btBatchedConstraints* m_bc;
  1147. ContactSolverLoop( btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc )
  1148. {
  1149. m_solver = solver;
  1150. m_bc = bc;
  1151. }
  1152. btScalar sumLoop( int iBegin, int iEnd ) const BT_OVERRIDE
  1153. {
  1154. BT_PROFILE( "ContactSolverLoop" );
  1155. btScalar sum = 0;
  1156. for ( int iBatch = iBegin; iBatch < iEnd; ++iBatch )
  1157. {
  1158. const btBatchedConstraints::Range& batch = m_bc->m_batches[ iBatch ];
  1159. sum += m_solver->resolveMultipleContactConstraints( m_bc->m_constraintIndices, batch.begin, batch.end );
  1160. }
  1161. return sum;
  1162. }
  1163. };
  1164. btScalar btSequentialImpulseConstraintSolverMt::resolveAllContactConstraints()
  1165. {
  1166. BT_PROFILE( "resolveAllContactConstraints" );
  1167. const btBatchedConstraints& batchedCons = m_batchedContactConstraints;
  1168. ContactSolverLoop loop( this, &batchedCons );
  1169. btScalar leastSquaresResidual = 0.f;
  1170. for ( int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase )
  1171. {
  1172. int iPhase = batchedCons.m_phaseOrder[ iiPhase ];
  1173. const btBatchedConstraints::Range& phase = batchedCons.m_phases[ iPhase ];
  1174. int grainSize = batchedCons.m_phaseGrainSize[iPhase];
  1175. leastSquaresResidual += btParallelSum( phase.begin, phase.end, grainSize, loop );
  1176. }
  1177. return leastSquaresResidual;
  1178. }
  1179. struct ContactFrictionSolverLoop : public btIParallelSumBody
  1180. {
  1181. btSequentialImpulseConstraintSolverMt* m_solver;
  1182. const btBatchedConstraints* m_bc;
  1183. ContactFrictionSolverLoop( btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc )
  1184. {
  1185. m_solver = solver;
  1186. m_bc = bc;
  1187. }
  1188. btScalar sumLoop( int iBegin, int iEnd ) const BT_OVERRIDE
  1189. {
  1190. BT_PROFILE( "ContactFrictionSolverLoop" );
  1191. btScalar sum = 0;
  1192. for ( int iBatch = iBegin; iBatch < iEnd; ++iBatch )
  1193. {
  1194. const btBatchedConstraints::Range& batch = m_bc->m_batches[ iBatch ];
  1195. sum += m_solver->resolveMultipleContactFrictionConstraints( m_bc->m_constraintIndices, batch.begin, batch.end );
  1196. }
  1197. return sum;
  1198. }
  1199. };
  1200. btScalar btSequentialImpulseConstraintSolverMt::resolveAllContactFrictionConstraints()
  1201. {
  1202. BT_PROFILE( "resolveAllContactFrictionConstraints" );
  1203. const btBatchedConstraints& batchedCons = m_batchedContactConstraints;
  1204. ContactFrictionSolverLoop loop( this, &batchedCons );
  1205. btScalar leastSquaresResidual = 0.f;
  1206. for ( int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase )
  1207. {
  1208. int iPhase = batchedCons.m_phaseOrder[ iiPhase ];
  1209. const btBatchedConstraints::Range& phase = batchedCons.m_phases[ iPhase ];
  1210. int grainSize = batchedCons.m_phaseGrainSize[iPhase];
  1211. leastSquaresResidual += btParallelSum( phase.begin, phase.end, grainSize, loop );
  1212. }
  1213. return leastSquaresResidual;
  1214. }
  1215. struct InterleavedContactSolverLoop : public btIParallelSumBody
  1216. {
  1217. btSequentialImpulseConstraintSolverMt* m_solver;
  1218. const btBatchedConstraints* m_bc;
  1219. InterleavedContactSolverLoop( btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc )
  1220. {
  1221. m_solver = solver;
  1222. m_bc = bc;
  1223. }
  1224. btScalar sumLoop( int iBegin, int iEnd ) const BT_OVERRIDE
  1225. {
  1226. BT_PROFILE( "InterleavedContactSolverLoop" );
  1227. btScalar sum = 0;
  1228. for ( int iBatch = iBegin; iBatch < iEnd; ++iBatch )
  1229. {
  1230. const btBatchedConstraints::Range& batch = m_bc->m_batches[ iBatch ];
  1231. sum += m_solver->resolveMultipleContactConstraintsInterleaved( m_bc->m_constraintIndices, batch.begin, batch.end );
  1232. }
  1233. return sum;
  1234. }
  1235. };
  1236. btScalar btSequentialImpulseConstraintSolverMt::resolveAllContactConstraintsInterleaved()
  1237. {
  1238. BT_PROFILE( "resolveAllContactConstraintsInterleaved" );
  1239. const btBatchedConstraints& batchedCons = m_batchedContactConstraints;
  1240. InterleavedContactSolverLoop loop( this, &batchedCons );
  1241. btScalar leastSquaresResidual = 0.f;
  1242. for ( int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase )
  1243. {
  1244. int iPhase = batchedCons.m_phaseOrder[ iiPhase ];
  1245. const btBatchedConstraints::Range& phase = batchedCons.m_phases[ iPhase ];
  1246. int grainSize = 1;
  1247. leastSquaresResidual += btParallelSum( phase.begin, phase.end, grainSize, loop );
  1248. }
  1249. return leastSquaresResidual;
  1250. }
  1251. struct ContactRollingFrictionSolverLoop : public btIParallelSumBody
  1252. {
  1253. btSequentialImpulseConstraintSolverMt* m_solver;
  1254. const btBatchedConstraints* m_bc;
  1255. ContactRollingFrictionSolverLoop( btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc )
  1256. {
  1257. m_solver = solver;
  1258. m_bc = bc;
  1259. }
  1260. btScalar sumLoop( int iBegin, int iEnd ) const BT_OVERRIDE
  1261. {
  1262. BT_PROFILE( "ContactFrictionSolverLoop" );
  1263. btScalar sum = 0;
  1264. for ( int iBatch = iBegin; iBatch < iEnd; ++iBatch )
  1265. {
  1266. const btBatchedConstraints::Range& batch = m_bc->m_batches[ iBatch ];
  1267. sum += m_solver->resolveMultipleContactRollingFrictionConstraints( m_bc->m_constraintIndices, batch.begin, batch.end );
  1268. }
  1269. return sum;
  1270. }
  1271. };
  1272. btScalar btSequentialImpulseConstraintSolverMt::resolveAllRollingFrictionConstraints()
  1273. {
  1274. BT_PROFILE( "resolveAllRollingFrictionConstraints" );
  1275. btScalar leastSquaresResidual = 0.f;
  1276. //
  1277. // We do not generate batches for rolling friction constraints. We assume that
  1278. // one of two cases is true:
  1279. //
  1280. // 1. either most bodies in the simulation have rolling friction, in which case we can use the
  1281. // batches for contacts and use a lookup table to translate contact indices to rolling friction
  1282. // (ignoring any contact indices that don't map to a rolling friction constraint). As long as
  1283. // most contacts have a corresponding rolling friction constraint, this should parallelize well.
  1284. //
  1285. // -OR-
  1286. //
  1287. // 2. few bodies in the simulation have rolling friction, so it is not worth trying to use the
  1288. // batches from contacts as most of the contacts won't have corresponding rolling friction
  1289. // constraints and most threads would end up doing very little work. Most of the time would
  1290. // go to threading overhead, so we don't bother with threading.
  1291. //
  1292. int numRollingFrictionPoolConstraints = m_tmpSolverContactRollingFrictionConstraintPool.size();
  1293. if (numRollingFrictionPoolConstraints >= m_tmpSolverContactConstraintPool.size())
  1294. {
  1295. // use batching if there are many rolling friction constraints
  1296. const btBatchedConstraints& batchedCons = m_batchedContactConstraints;
  1297. ContactRollingFrictionSolverLoop loop( this, &batchedCons );
  1298. btScalar leastSquaresResidual = 0.f;
  1299. for ( int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase )
  1300. {
  1301. int iPhase = batchedCons.m_phaseOrder[ iiPhase ];
  1302. const btBatchedConstraints::Range& phase = batchedCons.m_phases[ iPhase ];
  1303. int grainSize = 1;
  1304. leastSquaresResidual += btParallelSum( phase.begin, phase.end, grainSize, loop );
  1305. }
  1306. }
  1307. else
  1308. {
  1309. // no batching, also ignores SOLVER_RANDMIZE_ORDER
  1310. for ( int j = 0; j < numRollingFrictionPoolConstraints; j++ )
  1311. {
  1312. btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[ j ];
  1313. if ( rollingFrictionConstraint.m_frictionIndex >= 0 )
  1314. {
  1315. btScalar totalImpulse = m_tmpSolverContactConstraintPool[ rollingFrictionConstraint.m_frictionIndex ].m_appliedImpulse;
  1316. if ( totalImpulse > 0.0f )
  1317. {
  1318. btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction*totalImpulse;
  1319. if ( rollingFrictionMagnitude > rollingFrictionConstraint.m_friction )
  1320. rollingFrictionMagnitude = rollingFrictionConstraint.m_friction;
  1321. rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
  1322. rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
  1323. btScalar residual = resolveSingleConstraintRowGeneric( m_tmpSolverBodyPool[ rollingFrictionConstraint.m_solverBodyIdA ], m_tmpSolverBodyPool[ rollingFrictionConstraint.m_solverBodyIdB ], rollingFrictionConstraint );
  1324. leastSquaresResidual += residual*residual;
  1325. }
  1326. }
  1327. }
  1328. }
  1329. return leastSquaresResidual;
  1330. }
  1331. void btSequentialImpulseConstraintSolverMt::internalWriteBackContacts( int iBegin, int iEnd, const btContactSolverInfo& infoGlobal )
  1332. {
  1333. BT_PROFILE("internalWriteBackContacts");
  1334. writeBackContacts(iBegin, iEnd, infoGlobal);
  1335. //for ( int iContact = iBegin; iContact < iEnd; ++iContact)
  1336. //{
  1337. // const btSolverConstraint& contactConstraint = m_tmpSolverContactConstraintPool[ iContact ];
  1338. // btManifoldPoint* pt = (btManifoldPoint*) contactConstraint.m_originalContactPoint;
  1339. // btAssert( pt );
  1340. // pt->m_appliedImpulse = contactConstraint.m_appliedImpulse;
  1341. // pt->m_appliedImpulseLateral1 = m_tmpSolverContactFrictionConstraintPool[ contactConstraint.m_frictionIndex ].m_appliedImpulse;
  1342. // if ( m_numFrictionDirections == 2 )
  1343. // {
  1344. // pt->m_appliedImpulseLateral2 = m_tmpSolverContactFrictionConstraintPool[ contactConstraint.m_frictionIndex + 1 ].m_appliedImpulse;
  1345. // }
  1346. //}
  1347. }
  1348. void btSequentialImpulseConstraintSolverMt::internalWriteBackJoints( int iBegin, int iEnd, const btContactSolverInfo& infoGlobal )
  1349. {
  1350. BT_PROFILE("internalWriteBackJoints");
  1351. writeBackJoints(iBegin, iEnd, infoGlobal);
  1352. }
  1353. void btSequentialImpulseConstraintSolverMt::internalWriteBackBodies( int iBegin, int iEnd, const btContactSolverInfo& infoGlobal )
  1354. {
  1355. BT_PROFILE("internalWriteBackBodies");
  1356. writeBackBodies( iBegin, iEnd, infoGlobal );
  1357. }
  1358. struct WriteContactPointsLoop : public btIParallelForBody
  1359. {
  1360. btSequentialImpulseConstraintSolverMt* m_solver;
  1361. const btContactSolverInfo* m_infoGlobal;
  1362. WriteContactPointsLoop( btSequentialImpulseConstraintSolverMt* solver, const btContactSolverInfo& infoGlobal )
  1363. {
  1364. m_solver = solver;
  1365. m_infoGlobal = &infoGlobal;
  1366. }
  1367. void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE
  1368. {
  1369. m_solver->internalWriteBackContacts( iBegin, iEnd, *m_infoGlobal );
  1370. }
  1371. };
  1372. struct WriteJointsLoop : public btIParallelForBody
  1373. {
  1374. btSequentialImpulseConstraintSolverMt* m_solver;
  1375. const btContactSolverInfo* m_infoGlobal;
  1376. WriteJointsLoop( btSequentialImpulseConstraintSolverMt* solver, const btContactSolverInfo& infoGlobal )
  1377. {
  1378. m_solver = solver;
  1379. m_infoGlobal = &infoGlobal;
  1380. }
  1381. void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE
  1382. {
  1383. m_solver->internalWriteBackJoints( iBegin, iEnd, *m_infoGlobal );
  1384. }
  1385. };
  1386. struct WriteBodiesLoop : public btIParallelForBody
  1387. {
  1388. btSequentialImpulseConstraintSolverMt* m_solver;
  1389. const btContactSolverInfo* m_infoGlobal;
  1390. WriteBodiesLoop( btSequentialImpulseConstraintSolverMt* solver, const btContactSolverInfo& infoGlobal )
  1391. {
  1392. m_solver = solver;
  1393. m_infoGlobal = &infoGlobal;
  1394. }
  1395. void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE
  1396. {
  1397. m_solver->internalWriteBackBodies( iBegin, iEnd, *m_infoGlobal );
  1398. }
  1399. };
  1400. btScalar btSequentialImpulseConstraintSolverMt::solveGroupCacheFriendlyFinish(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal)
  1401. {
  1402. BT_PROFILE("solveGroupCacheFriendlyFinish");
  1403. if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
  1404. {
  1405. WriteContactPointsLoop loop( this, infoGlobal );
  1406. int grainSize = 500;
  1407. btParallelFor( 0, m_tmpSolverContactConstraintPool.size(), grainSize, loop );
  1408. }
  1409. {
  1410. WriteJointsLoop loop( this, infoGlobal );
  1411. int grainSize = 400;
  1412. btParallelFor( 0, m_tmpSolverNonContactConstraintPool.size(), grainSize, loop );
  1413. }
  1414. {
  1415. WriteBodiesLoop loop( this, infoGlobal );
  1416. int grainSize = 100;
  1417. btParallelFor( 0, m_tmpSolverBodyPool.size(), grainSize, loop );
  1418. }
  1419. m_tmpSolverContactConstraintPool.resizeNoInitialize(0);
  1420. m_tmpSolverNonContactConstraintPool.resizeNoInitialize(0);
  1421. m_tmpSolverContactFrictionConstraintPool.resizeNoInitialize(0);
  1422. m_tmpSolverContactRollingFrictionConstraintPool.resizeNoInitialize(0);
  1423. m_tmpSolverBodyPool.resizeNoInitialize(0);
  1424. return 0.f;
  1425. }