btMultiBodyConstraintSolver.cpp 70 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752
  1. /*
  2. Bullet Continuous Collision Detection and Physics Library
  3. Copyright (c) 2013 Erwin Coumans http://bulletphysics.org
  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 "btMultiBodyConstraintSolver.h"
  14. #include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
  15. #include "btMultiBodyLinkCollider.h"
  16. #include "BulletDynamics/ConstraintSolver/btSolverBody.h"
  17. #include "btMultiBodyConstraint.h"
  18. #include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
  19. #include "LinearMath/btQuickprof.h"
  20. #include "BulletDynamics/Featherstone/btMultiBodySolverConstraint.h"
  21. #include "LinearMath/btScalar.h"
  22. btScalar btMultiBodyConstraintSolver::solveSingleIteration(int iteration, btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
  23. {
  24. btScalar leastSquaredResidual = btSequentialImpulseConstraintSolver::solveSingleIteration(iteration, bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
  25. //solve featherstone non-contact constraints
  26. btScalar nonContactResidual = 0;
  27. //printf("m_multiBodyNonContactConstraints = %d\n",m_multiBodyNonContactConstraints.size());
  28. for (int i = 0; i < infoGlobal.m_numNonContactInnerIterations; ++i)
  29. {
  30. // reset the nonContactResdual to 0 at start of each inner iteration
  31. nonContactResidual = 0;
  32. for (int j = 0; j < m_multiBodyNonContactConstraints.size(); j++)
  33. {
  34. int index = iteration & 1 ? j : m_multiBodyNonContactConstraints.size() - 1 - j;
  35. btMultiBodySolverConstraint& constraint = m_multiBodyNonContactConstraints[index];
  36. btScalar residual = resolveSingleConstraintRowGeneric(constraint);
  37. nonContactResidual = btMax(nonContactResidual, residual * residual);
  38. if (constraint.m_multiBodyA)
  39. constraint.m_multiBodyA->setPosUpdated(false);
  40. if (constraint.m_multiBodyB)
  41. constraint.m_multiBodyB->setPosUpdated(false);
  42. }
  43. }
  44. leastSquaredResidual = btMax(leastSquaredResidual, nonContactResidual);
  45. //solve featherstone normal contact
  46. for (int j0 = 0; j0 < m_multiBodyNormalContactConstraints.size(); j0++)
  47. {
  48. int index = j0; //iteration&1? j0 : m_multiBodyNormalContactConstraints.size()-1-j0;
  49. btMultiBodySolverConstraint& constraint = m_multiBodyNormalContactConstraints[index];
  50. btScalar residual = 0.f;
  51. if (iteration < infoGlobal.m_numIterations)
  52. {
  53. residual = resolveSingleConstraintRowGeneric(constraint);
  54. }
  55. leastSquaredResidual = btMax(leastSquaredResidual, residual * residual);
  56. if (constraint.m_multiBodyA)
  57. constraint.m_multiBodyA->setPosUpdated(false);
  58. if (constraint.m_multiBodyB)
  59. constraint.m_multiBodyB->setPosUpdated(false);
  60. }
  61. //solve featherstone frictional contact
  62. if (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS && ((infoGlobal.m_solverMode & SOLVER_DISABLE_IMPLICIT_CONE_FRICTION) == 0))
  63. {
  64. for (int j1 = 0; j1 < this->m_multiBodySpinningFrictionContactConstraints.size(); j1++)
  65. {
  66. if (iteration < infoGlobal.m_numIterations)
  67. {
  68. int index = j1;
  69. btMultiBodySolverConstraint& frictionConstraint = m_multiBodySpinningFrictionContactConstraints[index];
  70. btScalar totalImpulse = m_multiBodyNormalContactConstraints[frictionConstraint.m_frictionIndex].m_appliedImpulse;
  71. //adjust friction limits here
  72. if (totalImpulse > btScalar(0))
  73. {
  74. frictionConstraint.m_lowerLimit = -(frictionConstraint.m_friction * totalImpulse);
  75. frictionConstraint.m_upperLimit = frictionConstraint.m_friction * totalImpulse;
  76. btScalar residual = resolveSingleConstraintRowGeneric(frictionConstraint);
  77. leastSquaredResidual = btMax(leastSquaredResidual, residual * residual);
  78. if (frictionConstraint.m_multiBodyA)
  79. frictionConstraint.m_multiBodyA->setPosUpdated(false);
  80. if (frictionConstraint.m_multiBodyB)
  81. frictionConstraint.m_multiBodyB->setPosUpdated(false);
  82. }
  83. }
  84. }
  85. for (int j1 = 0; j1 < this->m_multiBodyTorsionalFrictionContactConstraints.size(); j1++)
  86. {
  87. if (iteration < infoGlobal.m_numIterations)
  88. {
  89. int index = j1; //iteration&1? j1 : m_multiBodyTorsionalFrictionContactConstraints.size()-1-j1;
  90. btMultiBodySolverConstraint& frictionConstraint = m_multiBodyTorsionalFrictionContactConstraints[index];
  91. btScalar totalImpulse = m_multiBodyNormalContactConstraints[frictionConstraint.m_frictionIndex].m_appliedImpulse;
  92. j1++;
  93. int index2 = j1;
  94. btMultiBodySolverConstraint& frictionConstraintB = m_multiBodyTorsionalFrictionContactConstraints[index2];
  95. //adjust friction limits here
  96. if (totalImpulse > btScalar(0) && frictionConstraint.m_frictionIndex == frictionConstraintB.m_frictionIndex)
  97. {
  98. frictionConstraint.m_lowerLimit = -(frictionConstraint.m_friction * totalImpulse);
  99. frictionConstraint.m_upperLimit = frictionConstraint.m_friction * totalImpulse;
  100. frictionConstraintB.m_lowerLimit = -(frictionConstraintB.m_friction * totalImpulse);
  101. frictionConstraintB.m_upperLimit = frictionConstraintB.m_friction * totalImpulse;
  102. btScalar residual = resolveConeFrictionConstraintRows(frictionConstraint, frictionConstraintB);
  103. leastSquaredResidual = btMax(leastSquaredResidual, residual * residual);
  104. if (frictionConstraint.m_multiBodyA)
  105. frictionConstraint.m_multiBodyA->setPosUpdated(false);
  106. if (frictionConstraint.m_multiBodyB)
  107. frictionConstraint.m_multiBodyB->setPosUpdated(false);
  108. if (frictionConstraintB.m_multiBodyA)
  109. frictionConstraintB.m_multiBodyA->setPosUpdated(false);
  110. if (frictionConstraintB.m_multiBodyB)
  111. frictionConstraintB.m_multiBodyB->setPosUpdated(false);
  112. }
  113. }
  114. }
  115. for (int j1 = 0; j1 < this->m_multiBodyFrictionContactConstraints.size(); j1++)
  116. {
  117. if (iteration < infoGlobal.m_numIterations)
  118. {
  119. int index = j1; //iteration&1? j1 : m_multiBodyFrictionContactConstraints.size()-1-j1;
  120. btMultiBodySolverConstraint& frictionConstraint = m_multiBodyFrictionContactConstraints[index];
  121. btScalar totalImpulse = m_multiBodyNormalContactConstraints[frictionConstraint.m_frictionIndex].m_appliedImpulse;
  122. j1++;
  123. int index2 = j1; //iteration&1? j1 : m_multiBodyFrictionContactConstraints.size()-1-j1;
  124. btMultiBodySolverConstraint& frictionConstraintB = m_multiBodyFrictionContactConstraints[index2];
  125. btAssert(frictionConstraint.m_frictionIndex == frictionConstraintB.m_frictionIndex);
  126. if (frictionConstraint.m_frictionIndex == frictionConstraintB.m_frictionIndex)
  127. {
  128. frictionConstraint.m_lowerLimit = -(frictionConstraint.m_friction * totalImpulse);
  129. frictionConstraint.m_upperLimit = frictionConstraint.m_friction * totalImpulse;
  130. frictionConstraintB.m_lowerLimit = -(frictionConstraintB.m_friction * totalImpulse);
  131. frictionConstraintB.m_upperLimit = frictionConstraintB.m_friction * totalImpulse;
  132. btScalar residual = resolveConeFrictionConstraintRows(frictionConstraint, frictionConstraintB);
  133. leastSquaredResidual = btMax(leastSquaredResidual, residual * residual);
  134. if (frictionConstraintB.m_multiBodyA)
  135. frictionConstraintB.m_multiBodyA->setPosUpdated(false);
  136. if (frictionConstraintB.m_multiBodyB)
  137. frictionConstraintB.m_multiBodyB->setPosUpdated(false);
  138. if (frictionConstraint.m_multiBodyA)
  139. frictionConstraint.m_multiBodyA->setPosUpdated(false);
  140. if (frictionConstraint.m_multiBodyB)
  141. frictionConstraint.m_multiBodyB->setPosUpdated(false);
  142. }
  143. }
  144. }
  145. }
  146. else
  147. {
  148. for (int j1 = 0; j1 < this->m_multiBodyFrictionContactConstraints.size(); j1++)
  149. {
  150. if (iteration < infoGlobal.m_numIterations)
  151. {
  152. int index = j1; //iteration&1? j1 : m_multiBodyFrictionContactConstraints.size()-1-j1;
  153. btMultiBodySolverConstraint& frictionConstraint = m_multiBodyFrictionContactConstraints[index];
  154. btScalar totalImpulse = m_multiBodyNormalContactConstraints[frictionConstraint.m_frictionIndex].m_appliedImpulse;
  155. //adjust friction limits here
  156. if (totalImpulse > btScalar(0))
  157. {
  158. frictionConstraint.m_lowerLimit = -(frictionConstraint.m_friction * totalImpulse);
  159. frictionConstraint.m_upperLimit = frictionConstraint.m_friction * totalImpulse;
  160. btScalar residual = resolveSingleConstraintRowGeneric(frictionConstraint);
  161. leastSquaredResidual = btMax(leastSquaredResidual, residual * residual);
  162. if (frictionConstraint.m_multiBodyA)
  163. frictionConstraint.m_multiBodyA->setPosUpdated(false);
  164. if (frictionConstraint.m_multiBodyB)
  165. frictionConstraint.m_multiBodyB->setPosUpdated(false);
  166. }
  167. }
  168. }
  169. }
  170. return leastSquaredResidual;
  171. }
  172. btScalar btMultiBodyConstraintSolver::solveGroupCacheFriendlySetup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
  173. {
  174. m_multiBodyNonContactConstraints.resize(0);
  175. m_multiBodyNormalContactConstraints.resize(0);
  176. m_multiBodyFrictionContactConstraints.resize(0);
  177. m_multiBodyTorsionalFrictionContactConstraints.resize(0);
  178. m_multiBodySpinningFrictionContactConstraints.resize(0);
  179. m_data.m_jacobians.resize(0);
  180. m_data.m_deltaVelocitiesUnitImpulse.resize(0);
  181. m_data.m_deltaVelocities.resize(0);
  182. for (int i = 0; i < numBodies; i++)
  183. {
  184. const btMultiBodyLinkCollider* fcA = btMultiBodyLinkCollider::upcast(bodies[i]);
  185. if (fcA)
  186. {
  187. fcA->m_multiBody->setCompanionId(-1);
  188. }
  189. }
  190. btScalar val = btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
  191. return val;
  192. }
  193. void btMultiBodyConstraintSolver::applyDeltaVee(btScalar* delta_vee, btScalar impulse, int velocityIndex, int ndof)
  194. {
  195. for (int i = 0; i < ndof; ++i)
  196. m_data.m_deltaVelocities[velocityIndex + i] += delta_vee[i] * impulse;
  197. }
  198. btScalar btMultiBodyConstraintSolver::resolveSingleConstraintRowGeneric(const btMultiBodySolverConstraint& c)
  199. {
  200. btScalar deltaImpulse = c.m_rhs - btScalar(c.m_appliedImpulse) * c.m_cfm;
  201. btScalar deltaVelADotn = 0;
  202. btScalar deltaVelBDotn = 0;
  203. btSolverBody* bodyA = 0;
  204. btSolverBody* bodyB = 0;
  205. int ndofA = 0;
  206. int ndofB = 0;
  207. if (c.m_multiBodyA)
  208. {
  209. ndofA = c.m_multiBodyA->getNumDofs() + 6;
  210. for (int i = 0; i < ndofA; ++i)
  211. deltaVelADotn += m_data.m_jacobians[c.m_jacAindex + i] * m_data.m_deltaVelocities[c.m_deltaVelAindex + i];
  212. }
  213. else if (c.m_solverBodyIdA >= 0)
  214. {
  215. bodyA = &m_tmpSolverBodyPool[c.m_solverBodyIdA];
  216. deltaVelADotn += c.m_contactNormal1.dot(bodyA->internalGetDeltaLinearVelocity()) + c.m_relpos1CrossNormal.dot(bodyA->internalGetDeltaAngularVelocity());
  217. }
  218. if (c.m_multiBodyB)
  219. {
  220. ndofB = c.m_multiBodyB->getNumDofs() + 6;
  221. for (int i = 0; i < ndofB; ++i)
  222. deltaVelBDotn += m_data.m_jacobians[c.m_jacBindex + i] * m_data.m_deltaVelocities[c.m_deltaVelBindex + i];
  223. }
  224. else if (c.m_solverBodyIdB >= 0)
  225. {
  226. bodyB = &m_tmpSolverBodyPool[c.m_solverBodyIdB];
  227. deltaVelBDotn += c.m_contactNormal2.dot(bodyB->internalGetDeltaLinearVelocity()) + c.m_relpos2CrossNormal.dot(bodyB->internalGetDeltaAngularVelocity());
  228. }
  229. deltaImpulse -= deltaVelADotn * c.m_jacDiagABInv; //m_jacDiagABInv = 1./denom
  230. deltaImpulse -= deltaVelBDotn * c.m_jacDiagABInv;
  231. const btScalar sum = btScalar(c.m_appliedImpulse) + deltaImpulse;
  232. if (sum < c.m_lowerLimit)
  233. {
  234. deltaImpulse = c.m_lowerLimit - c.m_appliedImpulse;
  235. c.m_appliedImpulse = c.m_lowerLimit;
  236. }
  237. else if (sum > c.m_upperLimit)
  238. {
  239. deltaImpulse = c.m_upperLimit - c.m_appliedImpulse;
  240. c.m_appliedImpulse = c.m_upperLimit;
  241. }
  242. else
  243. {
  244. c.m_appliedImpulse = sum;
  245. }
  246. if (c.m_multiBodyA)
  247. {
  248. applyDeltaVee(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacAindex], deltaImpulse, c.m_deltaVelAindex, ndofA);
  249. #ifdef DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
  250. //note: update of the actual velocities (below) in the multibody does not have to happen now since m_deltaVelocities can be applied after all iterations
  251. //it would make the multibody solver more like the regular one with m_deltaVelocities being equivalent to btSolverBody::m_deltaLinearVelocity/m_deltaAngularVelocity
  252. c.m_multiBodyA->applyDeltaVeeMultiDof2(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacAindex], deltaImpulse);
  253. #endif //DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
  254. }
  255. else if (c.m_solverBodyIdA >= 0)
  256. {
  257. bodyA->internalApplyImpulse(c.m_contactNormal1 * bodyA->internalGetInvMass(), c.m_angularComponentA, deltaImpulse);
  258. }
  259. if (c.m_multiBodyB)
  260. {
  261. applyDeltaVee(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacBindex], deltaImpulse, c.m_deltaVelBindex, ndofB);
  262. #ifdef DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
  263. //note: update of the actual velocities (below) in the multibody does not have to happen now since m_deltaVelocities can be applied after all iterations
  264. //it would make the multibody solver more like the regular one with m_deltaVelocities being equivalent to btSolverBody::m_deltaLinearVelocity/m_deltaAngularVelocity
  265. c.m_multiBodyB->applyDeltaVeeMultiDof2(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacBindex], deltaImpulse);
  266. #endif //DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
  267. }
  268. else if (c.m_solverBodyIdB >= 0)
  269. {
  270. bodyB->internalApplyImpulse(c.m_contactNormal2 * bodyB->internalGetInvMass(), c.m_angularComponentB, deltaImpulse);
  271. }
  272. btScalar deltaVel = deltaImpulse / c.m_jacDiagABInv;
  273. return deltaVel;
  274. }
  275. btScalar btMultiBodyConstraintSolver::resolveConeFrictionConstraintRows(const btMultiBodySolverConstraint& cA1, const btMultiBodySolverConstraint& cB)
  276. {
  277. int ndofA = 0;
  278. int ndofB = 0;
  279. btSolverBody* bodyA = 0;
  280. btSolverBody* bodyB = 0;
  281. btScalar deltaImpulseB = 0.f;
  282. btScalar sumB = 0.f;
  283. {
  284. deltaImpulseB = cB.m_rhs - btScalar(cB.m_appliedImpulse) * cB.m_cfm;
  285. btScalar deltaVelADotn = 0;
  286. btScalar deltaVelBDotn = 0;
  287. if (cB.m_multiBodyA)
  288. {
  289. ndofA = cB.m_multiBodyA->getNumDofs() + 6;
  290. for (int i = 0; i < ndofA; ++i)
  291. deltaVelADotn += m_data.m_jacobians[cB.m_jacAindex + i] * m_data.m_deltaVelocities[cB.m_deltaVelAindex + i];
  292. }
  293. else if (cB.m_solverBodyIdA >= 0)
  294. {
  295. bodyA = &m_tmpSolverBodyPool[cB.m_solverBodyIdA];
  296. deltaVelADotn += cB.m_contactNormal1.dot(bodyA->internalGetDeltaLinearVelocity()) + cB.m_relpos1CrossNormal.dot(bodyA->internalGetDeltaAngularVelocity());
  297. }
  298. if (cB.m_multiBodyB)
  299. {
  300. ndofB = cB.m_multiBodyB->getNumDofs() + 6;
  301. for (int i = 0; i < ndofB; ++i)
  302. deltaVelBDotn += m_data.m_jacobians[cB.m_jacBindex + i] * m_data.m_deltaVelocities[cB.m_deltaVelBindex + i];
  303. }
  304. else if (cB.m_solverBodyIdB >= 0)
  305. {
  306. bodyB = &m_tmpSolverBodyPool[cB.m_solverBodyIdB];
  307. deltaVelBDotn += cB.m_contactNormal2.dot(bodyB->internalGetDeltaLinearVelocity()) + cB.m_relpos2CrossNormal.dot(bodyB->internalGetDeltaAngularVelocity());
  308. }
  309. deltaImpulseB -= deltaVelADotn * cB.m_jacDiagABInv; //m_jacDiagABInv = 1./denom
  310. deltaImpulseB -= deltaVelBDotn * cB.m_jacDiagABInv;
  311. sumB = btScalar(cB.m_appliedImpulse) + deltaImpulseB;
  312. }
  313. btScalar deltaImpulseA = 0.f;
  314. btScalar sumA = 0.f;
  315. const btMultiBodySolverConstraint& cA = cA1;
  316. {
  317. {
  318. deltaImpulseA = cA.m_rhs - btScalar(cA.m_appliedImpulse) * cA.m_cfm;
  319. btScalar deltaVelADotn = 0;
  320. btScalar deltaVelBDotn = 0;
  321. if (cA.m_multiBodyA)
  322. {
  323. ndofA = cA.m_multiBodyA->getNumDofs() + 6;
  324. for (int i = 0; i < ndofA; ++i)
  325. deltaVelADotn += m_data.m_jacobians[cA.m_jacAindex + i] * m_data.m_deltaVelocities[cA.m_deltaVelAindex + i];
  326. }
  327. else if (cA.m_solverBodyIdA >= 0)
  328. {
  329. bodyA = &m_tmpSolverBodyPool[cA.m_solverBodyIdA];
  330. deltaVelADotn += cA.m_contactNormal1.dot(bodyA->internalGetDeltaLinearVelocity()) + cA.m_relpos1CrossNormal.dot(bodyA->internalGetDeltaAngularVelocity());
  331. }
  332. if (cA.m_multiBodyB)
  333. {
  334. ndofB = cA.m_multiBodyB->getNumDofs() + 6;
  335. for (int i = 0; i < ndofB; ++i)
  336. deltaVelBDotn += m_data.m_jacobians[cA.m_jacBindex + i] * m_data.m_deltaVelocities[cA.m_deltaVelBindex + i];
  337. }
  338. else if (cA.m_solverBodyIdB >= 0)
  339. {
  340. bodyB = &m_tmpSolverBodyPool[cA.m_solverBodyIdB];
  341. deltaVelBDotn += cA.m_contactNormal2.dot(bodyB->internalGetDeltaLinearVelocity()) + cA.m_relpos2CrossNormal.dot(bodyB->internalGetDeltaAngularVelocity());
  342. }
  343. deltaImpulseA -= deltaVelADotn * cA.m_jacDiagABInv; //m_jacDiagABInv = 1./denom
  344. deltaImpulseA -= deltaVelBDotn * cA.m_jacDiagABInv;
  345. sumA = btScalar(cA.m_appliedImpulse) + deltaImpulseA;
  346. }
  347. }
  348. if (sumA * sumA + sumB * sumB >= cA.m_lowerLimit * cB.m_lowerLimit)
  349. {
  350. btScalar angle = btAtan2(sumA, sumB);
  351. btScalar sumAclipped = btFabs(cA.m_lowerLimit * btSin(angle));
  352. btScalar sumBclipped = btFabs(cB.m_lowerLimit * btCos(angle));
  353. if (sumA < -sumAclipped)
  354. {
  355. deltaImpulseA = -sumAclipped - cA.m_appliedImpulse;
  356. cA.m_appliedImpulse = -sumAclipped;
  357. }
  358. else if (sumA > sumAclipped)
  359. {
  360. deltaImpulseA = sumAclipped - cA.m_appliedImpulse;
  361. cA.m_appliedImpulse = sumAclipped;
  362. }
  363. else
  364. {
  365. cA.m_appliedImpulse = sumA;
  366. }
  367. if (sumB < -sumBclipped)
  368. {
  369. deltaImpulseB = -sumBclipped - cB.m_appliedImpulse;
  370. cB.m_appliedImpulse = -sumBclipped;
  371. }
  372. else if (sumB > sumBclipped)
  373. {
  374. deltaImpulseB = sumBclipped - cB.m_appliedImpulse;
  375. cB.m_appliedImpulse = sumBclipped;
  376. }
  377. else
  378. {
  379. cB.m_appliedImpulse = sumB;
  380. }
  381. //deltaImpulseA = sumAclipped-cA.m_appliedImpulse;
  382. //cA.m_appliedImpulse = sumAclipped;
  383. //deltaImpulseB = sumBclipped-cB.m_appliedImpulse;
  384. //cB.m_appliedImpulse = sumBclipped;
  385. }
  386. else
  387. {
  388. cA.m_appliedImpulse = sumA;
  389. cB.m_appliedImpulse = sumB;
  390. }
  391. if (cA.m_multiBodyA)
  392. {
  393. applyDeltaVee(&m_data.m_deltaVelocitiesUnitImpulse[cA.m_jacAindex], deltaImpulseA, cA.m_deltaVelAindex, ndofA);
  394. #ifdef DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
  395. //note: update of the actual velocities (below) in the multibody does not have to happen now since m_deltaVelocities can be applied after all iterations
  396. //it would make the multibody solver more like the regular one with m_deltaVelocities being equivalent to btSolverBody::m_deltaLinearVelocity/m_deltaAngularVelocity
  397. cA.m_multiBodyA->applyDeltaVeeMultiDof2(&m_data.m_deltaVelocitiesUnitImpulse[cA.m_jacAindex], deltaImpulseA);
  398. #endif //DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
  399. }
  400. else if (cA.m_solverBodyIdA >= 0)
  401. {
  402. bodyA->internalApplyImpulse(cA.m_contactNormal1 * bodyA->internalGetInvMass(), cA.m_angularComponentA, deltaImpulseA);
  403. }
  404. if (cA.m_multiBodyB)
  405. {
  406. applyDeltaVee(&m_data.m_deltaVelocitiesUnitImpulse[cA.m_jacBindex], deltaImpulseA, cA.m_deltaVelBindex, ndofB);
  407. #ifdef DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
  408. //note: update of the actual velocities (below) in the multibody does not have to happen now since m_deltaVelocities can be applied after all iterations
  409. //it would make the multibody solver more like the regular one with m_deltaVelocities being equivalent to btSolverBody::m_deltaLinearVelocity/m_deltaAngularVelocity
  410. cA.m_multiBodyB->applyDeltaVeeMultiDof2(&m_data.m_deltaVelocitiesUnitImpulse[cA.m_jacBindex], deltaImpulseA);
  411. #endif //DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
  412. }
  413. else if (cA.m_solverBodyIdB >= 0)
  414. {
  415. bodyB->internalApplyImpulse(cA.m_contactNormal2 * bodyB->internalGetInvMass(), cA.m_angularComponentB, deltaImpulseA);
  416. }
  417. if (cB.m_multiBodyA)
  418. {
  419. applyDeltaVee(&m_data.m_deltaVelocitiesUnitImpulse[cB.m_jacAindex], deltaImpulseB, cB.m_deltaVelAindex, ndofA);
  420. #ifdef DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
  421. //note: update of the actual velocities (below) in the multibody does not have to happen now since m_deltaVelocities can be applied after all iterations
  422. //it would make the multibody solver more like the regular one with m_deltaVelocities being equivalent to btSolverBody::m_deltaLinearVelocity/m_deltaAngularVelocity
  423. cB.m_multiBodyA->applyDeltaVeeMultiDof2(&m_data.m_deltaVelocitiesUnitImpulse[cB.m_jacAindex], deltaImpulseB);
  424. #endif //DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
  425. }
  426. else if (cB.m_solverBodyIdA >= 0)
  427. {
  428. bodyA->internalApplyImpulse(cB.m_contactNormal1 * bodyA->internalGetInvMass(), cB.m_angularComponentA, deltaImpulseB);
  429. }
  430. if (cB.m_multiBodyB)
  431. {
  432. applyDeltaVee(&m_data.m_deltaVelocitiesUnitImpulse[cB.m_jacBindex], deltaImpulseB, cB.m_deltaVelBindex, ndofB);
  433. #ifdef DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
  434. //note: update of the actual velocities (below) in the multibody does not have to happen now since m_deltaVelocities can be applied after all iterations
  435. //it would make the multibody solver more like the regular one with m_deltaVelocities being equivalent to btSolverBody::m_deltaLinearVelocity/m_deltaAngularVelocity
  436. cB.m_multiBodyB->applyDeltaVeeMultiDof2(&m_data.m_deltaVelocitiesUnitImpulse[cB.m_jacBindex], deltaImpulseB);
  437. #endif //DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
  438. }
  439. else if (cB.m_solverBodyIdB >= 0)
  440. {
  441. bodyB->internalApplyImpulse(cB.m_contactNormal2 * bodyB->internalGetInvMass(), cB.m_angularComponentB, deltaImpulseB);
  442. }
  443. btScalar deltaVel = deltaImpulseA / cA.m_jacDiagABInv + deltaImpulseB / cB.m_jacDiagABInv;
  444. return deltaVel;
  445. }
  446. void btMultiBodyConstraintSolver::setupMultiBodyContactConstraint(btMultiBodySolverConstraint& solverConstraint, const btVector3& contactNormal, const btScalar& appliedImpulse, btManifoldPoint& cp, const btContactSolverInfo& infoGlobal, btScalar& relaxation, bool isFriction, btScalar desiredVelocity, btScalar cfmSlip)
  447. {
  448. BT_PROFILE("setupMultiBodyContactConstraint");
  449. btVector3 rel_pos1;
  450. btVector3 rel_pos2;
  451. btMultiBody* multiBodyA = solverConstraint.m_multiBodyA;
  452. btMultiBody* multiBodyB = solverConstraint.m_multiBodyB;
  453. const btVector3& pos1 = cp.getPositionWorldOnA();
  454. const btVector3& pos2 = cp.getPositionWorldOnB();
  455. btSolverBody* bodyA = multiBodyA ? 0 : &m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdA];
  456. btSolverBody* bodyB = multiBodyB ? 0 : &m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdB];
  457. btRigidBody* rb0 = multiBodyA ? 0 : bodyA->m_originalBody;
  458. btRigidBody* rb1 = multiBodyB ? 0 : bodyB->m_originalBody;
  459. if (bodyA)
  460. rel_pos1 = pos1 - bodyA->getWorldTransform().getOrigin();
  461. if (bodyB)
  462. rel_pos2 = pos2 - bodyB->getWorldTransform().getOrigin();
  463. relaxation = infoGlobal.m_sor;
  464. btScalar invTimeStep = btScalar(1) / infoGlobal.m_timeStep;
  465. //cfm = 1 / ( dt * kp + kd )
  466. //erp = dt * kp / ( dt * kp + kd )
  467. btScalar cfm;
  468. btScalar erp;
  469. if (isFriction)
  470. {
  471. cfm = infoGlobal.m_frictionCFM;
  472. erp = infoGlobal.m_frictionERP;
  473. }
  474. else
  475. {
  476. cfm = infoGlobal.m_globalCfm;
  477. erp = infoGlobal.m_erp2;
  478. if ((cp.m_contactPointFlags & BT_CONTACT_FLAG_HAS_CONTACT_CFM) || (cp.m_contactPointFlags & BT_CONTACT_FLAG_HAS_CONTACT_ERP))
  479. {
  480. if (cp.m_contactPointFlags & BT_CONTACT_FLAG_HAS_CONTACT_CFM)
  481. cfm = cp.m_contactCFM;
  482. if (cp.m_contactPointFlags & BT_CONTACT_FLAG_HAS_CONTACT_ERP)
  483. erp = cp.m_contactERP;
  484. }
  485. else
  486. {
  487. if (cp.m_contactPointFlags & BT_CONTACT_FLAG_CONTACT_STIFFNESS_DAMPING)
  488. {
  489. btScalar denom = (infoGlobal.m_timeStep * cp.m_combinedContactStiffness1 + cp.m_combinedContactDamping1);
  490. if (denom < SIMD_EPSILON)
  491. {
  492. denom = SIMD_EPSILON;
  493. }
  494. cfm = btScalar(1) / denom;
  495. erp = (infoGlobal.m_timeStep * cp.m_combinedContactStiffness1) / denom;
  496. }
  497. }
  498. }
  499. cfm *= invTimeStep;
  500. if (multiBodyA)
  501. {
  502. if (solverConstraint.m_linkA < 0)
  503. {
  504. rel_pos1 = pos1 - multiBodyA->getBasePos();
  505. }
  506. else
  507. {
  508. rel_pos1 = pos1 - multiBodyA->getLink(solverConstraint.m_linkA).m_cachedWorldTransform.getOrigin();
  509. }
  510. const int ndofA = multiBodyA->getNumDofs() + 6;
  511. solverConstraint.m_deltaVelAindex = multiBodyA->getCompanionId();
  512. if (solverConstraint.m_deltaVelAindex < 0)
  513. {
  514. solverConstraint.m_deltaVelAindex = m_data.m_deltaVelocities.size();
  515. multiBodyA->setCompanionId(solverConstraint.m_deltaVelAindex);
  516. m_data.m_deltaVelocities.resize(m_data.m_deltaVelocities.size() + ndofA);
  517. }
  518. else
  519. {
  520. btAssert(m_data.m_deltaVelocities.size() >= solverConstraint.m_deltaVelAindex + ndofA);
  521. }
  522. solverConstraint.m_jacAindex = m_data.m_jacobians.size();
  523. m_data.m_jacobians.resize(m_data.m_jacobians.size() + ndofA);
  524. m_data.m_deltaVelocitiesUnitImpulse.resize(m_data.m_deltaVelocitiesUnitImpulse.size() + ndofA);
  525. btAssert(m_data.m_jacobians.size() == m_data.m_deltaVelocitiesUnitImpulse.size());
  526. btScalar* jac1 = &m_data.m_jacobians[solverConstraint.m_jacAindex];
  527. multiBodyA->fillContactJacobianMultiDof(solverConstraint.m_linkA, cp.getPositionWorldOnA(), contactNormal, jac1, m_data.scratch_r, m_data.scratch_v, m_data.scratch_m);
  528. btScalar* delta = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
  529. multiBodyA->calcAccelerationDeltasMultiDof(&m_data.m_jacobians[solverConstraint.m_jacAindex], delta, m_data.scratch_r, m_data.scratch_v);
  530. btVector3 torqueAxis0 = rel_pos1.cross(contactNormal);
  531. solverConstraint.m_relpos1CrossNormal = torqueAxis0;
  532. solverConstraint.m_contactNormal1 = contactNormal;
  533. }
  534. else
  535. {
  536. btVector3 torqueAxis0 = rel_pos1.cross(contactNormal);
  537. solverConstraint.m_relpos1CrossNormal = torqueAxis0;
  538. solverConstraint.m_contactNormal1 = contactNormal;
  539. solverConstraint.m_angularComponentA = rb0 ? rb0->getInvInertiaTensorWorld() * torqueAxis0 * rb0->getAngularFactor() : btVector3(0, 0, 0);
  540. }
  541. if (multiBodyB)
  542. {
  543. if (solverConstraint.m_linkB < 0)
  544. {
  545. rel_pos2 = pos2 - multiBodyB->getBasePos();
  546. }
  547. else
  548. {
  549. rel_pos2 = pos2 - multiBodyB->getLink(solverConstraint.m_linkB).m_cachedWorldTransform.getOrigin();
  550. }
  551. const int ndofB = multiBodyB->getNumDofs() + 6;
  552. solverConstraint.m_deltaVelBindex = multiBodyB->getCompanionId();
  553. if (solverConstraint.m_deltaVelBindex < 0)
  554. {
  555. solverConstraint.m_deltaVelBindex = m_data.m_deltaVelocities.size();
  556. multiBodyB->setCompanionId(solverConstraint.m_deltaVelBindex);
  557. m_data.m_deltaVelocities.resize(m_data.m_deltaVelocities.size() + ndofB);
  558. }
  559. solverConstraint.m_jacBindex = m_data.m_jacobians.size();
  560. m_data.m_jacobians.resize(m_data.m_jacobians.size() + ndofB);
  561. m_data.m_deltaVelocitiesUnitImpulse.resize(m_data.m_deltaVelocitiesUnitImpulse.size() + ndofB);
  562. btAssert(m_data.m_jacobians.size() == m_data.m_deltaVelocitiesUnitImpulse.size());
  563. multiBodyB->fillContactJacobianMultiDof(solverConstraint.m_linkB, cp.getPositionWorldOnB(), -contactNormal, &m_data.m_jacobians[solverConstraint.m_jacBindex], m_data.scratch_r, m_data.scratch_v, m_data.scratch_m);
  564. multiBodyB->calcAccelerationDeltasMultiDof(&m_data.m_jacobians[solverConstraint.m_jacBindex], &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex], m_data.scratch_r, m_data.scratch_v);
  565. btVector3 torqueAxis1 = rel_pos2.cross(contactNormal);
  566. solverConstraint.m_relpos2CrossNormal = -torqueAxis1;
  567. solverConstraint.m_contactNormal2 = -contactNormal;
  568. }
  569. else
  570. {
  571. btVector3 torqueAxis1 = rel_pos2.cross(contactNormal);
  572. solverConstraint.m_relpos2CrossNormal = -torqueAxis1;
  573. solverConstraint.m_contactNormal2 = -contactNormal;
  574. solverConstraint.m_angularComponentB = rb1 ? rb1->getInvInertiaTensorWorld() * -torqueAxis1 * rb1->getAngularFactor() : btVector3(0, 0, 0);
  575. }
  576. {
  577. btVector3 vec;
  578. btScalar denom0 = 0.f;
  579. btScalar denom1 = 0.f;
  580. btScalar* jacB = 0;
  581. btScalar* jacA = 0;
  582. btScalar* lambdaA = 0;
  583. btScalar* lambdaB = 0;
  584. int ndofA = 0;
  585. if (multiBodyA)
  586. {
  587. ndofA = multiBodyA->getNumDofs() + 6;
  588. jacA = &m_data.m_jacobians[solverConstraint.m_jacAindex];
  589. lambdaA = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
  590. for (int i = 0; i < ndofA; ++i)
  591. {
  592. btScalar j = jacA[i];
  593. btScalar l = lambdaA[i];
  594. denom0 += j * l;
  595. }
  596. }
  597. else
  598. {
  599. if (rb0)
  600. {
  601. vec = (solverConstraint.m_angularComponentA).cross(rel_pos1);
  602. denom0 = rb0->getInvMass() + contactNormal.dot(vec);
  603. }
  604. }
  605. if (multiBodyB)
  606. {
  607. const int ndofB = multiBodyB->getNumDofs() + 6;
  608. jacB = &m_data.m_jacobians[solverConstraint.m_jacBindex];
  609. lambdaB = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex];
  610. for (int i = 0; i < ndofB; ++i)
  611. {
  612. btScalar j = jacB[i];
  613. btScalar l = lambdaB[i];
  614. denom1 += j * l;
  615. }
  616. }
  617. else
  618. {
  619. if (rb1)
  620. {
  621. vec = (-solverConstraint.m_angularComponentB).cross(rel_pos2);
  622. denom1 = rb1->getInvMass() + contactNormal.dot(vec);
  623. }
  624. }
  625. btScalar d = denom0 + denom1 + cfm;
  626. if (d > SIMD_EPSILON)
  627. {
  628. solverConstraint.m_jacDiagABInv = relaxation / (d);
  629. }
  630. else
  631. {
  632. //disable the constraint row to handle singularity/redundant constraint
  633. solverConstraint.m_jacDiagABInv = 0.f;
  634. }
  635. }
  636. //compute rhs and remaining solverConstraint fields
  637. btScalar restitution = 0.f;
  638. btScalar distance = 0;
  639. if (!isFriction)
  640. {
  641. distance = cp.getDistance() + infoGlobal.m_linearSlop;
  642. }
  643. else
  644. {
  645. if (cp.m_contactPointFlags & BT_CONTACT_FLAG_FRICTION_ANCHOR)
  646. {
  647. distance = (cp.getPositionWorldOnA() - cp.getPositionWorldOnB()).dot(contactNormal);
  648. }
  649. }
  650. btScalar rel_vel = 0.f;
  651. int ndofA = 0;
  652. int ndofB = 0;
  653. {
  654. btVector3 vel1, vel2;
  655. if (multiBodyA)
  656. {
  657. ndofA = multiBodyA->getNumDofs() + 6;
  658. btScalar* jacA = &m_data.m_jacobians[solverConstraint.m_jacAindex];
  659. for (int i = 0; i < ndofA; ++i)
  660. rel_vel += multiBodyA->getVelocityVector()[i] * jacA[i];
  661. }
  662. else
  663. {
  664. if (rb0)
  665. {
  666. rel_vel += (rb0->getVelocityInLocalPoint(rel_pos1) +
  667. (rb0->getTotalTorque() * rb0->getInvInertiaTensorWorld() * infoGlobal.m_timeStep).cross(rel_pos1) +
  668. rb0->getTotalForce() * rb0->getInvMass() * infoGlobal.m_timeStep)
  669. .dot(solverConstraint.m_contactNormal1);
  670. }
  671. }
  672. if (multiBodyB)
  673. {
  674. ndofB = multiBodyB->getNumDofs() + 6;
  675. btScalar* jacB = &m_data.m_jacobians[solverConstraint.m_jacBindex];
  676. for (int i = 0; i < ndofB; ++i)
  677. rel_vel += multiBodyB->getVelocityVector()[i] * jacB[i];
  678. }
  679. else
  680. {
  681. if (rb1)
  682. {
  683. rel_vel += (rb1->getVelocityInLocalPoint(rel_pos2) +
  684. (rb1->getTotalTorque() * rb1->getInvInertiaTensorWorld() * infoGlobal.m_timeStep).cross(rel_pos2) +
  685. rb1->getTotalForce() * rb1->getInvMass() * infoGlobal.m_timeStep)
  686. .dot(solverConstraint.m_contactNormal2);
  687. }
  688. }
  689. solverConstraint.m_friction = cp.m_combinedFriction;
  690. if (!isFriction)
  691. {
  692. restitution = restitutionCurve(rel_vel, cp.m_combinedRestitution, infoGlobal.m_restitutionVelocityThreshold);
  693. if (restitution <= btScalar(0.))
  694. {
  695. restitution = 0.f;
  696. }
  697. }
  698. }
  699. {
  700. btScalar positionalError = 0.f;
  701. btScalar velocityError = restitution - rel_vel; // * damping; //note for friction restitution is always set to 0 (check above) so it is acutally velocityError = -rel_vel for friction
  702. if (isFriction)
  703. {
  704. positionalError = -distance * erp / infoGlobal.m_timeStep;
  705. }
  706. else
  707. {
  708. if (distance > 0)
  709. {
  710. positionalError = 0;
  711. velocityError -= distance / infoGlobal.m_timeStep;
  712. }
  713. else
  714. {
  715. positionalError = -distance * erp / infoGlobal.m_timeStep;
  716. }
  717. }
  718. btScalar penetrationImpulse = positionalError * solverConstraint.m_jacDiagABInv;
  719. btScalar velocityImpulse = velocityError * solverConstraint.m_jacDiagABInv;
  720. if (!isFriction)
  721. {
  722. // if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold))
  723. {
  724. //combine position and velocity into rhs
  725. solverConstraint.m_rhs = penetrationImpulse + velocityImpulse;
  726. solverConstraint.m_rhsPenetration = 0.f;
  727. }
  728. /*else
  729. {
  730. //split position and velocity into rhs and m_rhsPenetration
  731. solverConstraint.m_rhs = velocityImpulse;
  732. solverConstraint.m_rhsPenetration = penetrationImpulse;
  733. }
  734. */
  735. solverConstraint.m_lowerLimit = 0;
  736. solverConstraint.m_upperLimit = 1e10f;
  737. }
  738. else
  739. {
  740. solverConstraint.m_rhs = penetrationImpulse + velocityImpulse;
  741. solverConstraint.m_rhsPenetration = 0.f;
  742. solverConstraint.m_lowerLimit = -solverConstraint.m_friction;
  743. solverConstraint.m_upperLimit = solverConstraint.m_friction;
  744. }
  745. solverConstraint.m_cfm = cfm * solverConstraint.m_jacDiagABInv;
  746. }
  747. if (infoGlobal.m_solverMode & SOLVER_USE_ARTICULATED_WARMSTARTING)
  748. {
  749. if (btFabs(cp.m_prevRHS) > 1e-5 && cp.m_prevRHS < 2* solverConstraint.m_rhs && solverConstraint.m_rhs < 2*cp.m_prevRHS)
  750. {
  751. solverConstraint.m_appliedImpulse = isFriction ? 0 : cp.m_appliedImpulse / cp.m_prevRHS * solverConstraint.m_rhs * infoGlobal.m_articulatedWarmstartingFactor;
  752. if (solverConstraint.m_appliedImpulse < 0)
  753. solverConstraint.m_appliedImpulse = 0;
  754. }
  755. else
  756. {
  757. solverConstraint.m_appliedImpulse = 0.f;
  758. }
  759. if (solverConstraint.m_appliedImpulse)
  760. {
  761. if (multiBodyA)
  762. {
  763. btScalar impulse = solverConstraint.m_appliedImpulse;
  764. btScalar* deltaV = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
  765. multiBodyA->applyDeltaVeeMultiDof2(deltaV, impulse);
  766. applyDeltaVee(deltaV, impulse, solverConstraint.m_deltaVelAindex, ndofA);
  767. }
  768. else
  769. {
  770. if (rb0)
  771. bodyA->internalApplyImpulse(solverConstraint.m_contactNormal1 * bodyA->internalGetInvMass() * rb0->getLinearFactor(), solverConstraint.m_angularComponentA, solverConstraint.m_appliedImpulse);
  772. }
  773. if (multiBodyB)
  774. {
  775. btScalar impulse = solverConstraint.m_appliedImpulse;
  776. btScalar* deltaV = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex];
  777. multiBodyB->applyDeltaVeeMultiDof2(deltaV, impulse);
  778. applyDeltaVee(deltaV, impulse, solverConstraint.m_deltaVelBindex, ndofB);
  779. }
  780. else
  781. {
  782. if (rb1)
  783. bodyB->internalApplyImpulse(-solverConstraint.m_contactNormal2 * bodyB->internalGetInvMass() * rb1->getLinearFactor(), -solverConstraint.m_angularComponentB, -(btScalar)solverConstraint.m_appliedImpulse);
  784. }
  785. }
  786. }
  787. else
  788. {
  789. solverConstraint.m_appliedImpulse = 0.f;
  790. solverConstraint.m_appliedPushImpulse = 0.f;
  791. }
  792. }
  793. void btMultiBodyConstraintSolver::setupMultiBodyTorsionalFrictionConstraint(btMultiBodySolverConstraint& solverConstraint,
  794. const btVector3& constraintNormal,
  795. btManifoldPoint& cp,
  796. btScalar combinedTorsionalFriction,
  797. const btContactSolverInfo& infoGlobal,
  798. btScalar& relaxation,
  799. bool isFriction, btScalar desiredVelocity, btScalar cfmSlip)
  800. {
  801. BT_PROFILE("setupMultiBodyRollingFrictionConstraint");
  802. btVector3 rel_pos1;
  803. btVector3 rel_pos2;
  804. btMultiBody* multiBodyA = solverConstraint.m_multiBodyA;
  805. btMultiBody* multiBodyB = solverConstraint.m_multiBodyB;
  806. const btVector3& pos1 = cp.getPositionWorldOnA();
  807. const btVector3& pos2 = cp.getPositionWorldOnB();
  808. btSolverBody* bodyA = multiBodyA ? 0 : &m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdA];
  809. btSolverBody* bodyB = multiBodyB ? 0 : &m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdB];
  810. btRigidBody* rb0 = multiBodyA ? 0 : bodyA->m_originalBody;
  811. btRigidBody* rb1 = multiBodyB ? 0 : bodyB->m_originalBody;
  812. if (bodyA)
  813. rel_pos1 = pos1 - bodyA->getWorldTransform().getOrigin();
  814. if (bodyB)
  815. rel_pos2 = pos2 - bodyB->getWorldTransform().getOrigin();
  816. relaxation = infoGlobal.m_sor;
  817. // btScalar invTimeStep = btScalar(1)/infoGlobal.m_timeStep;
  818. if (multiBodyA)
  819. {
  820. if (solverConstraint.m_linkA < 0)
  821. {
  822. rel_pos1 = pos1 - multiBodyA->getBasePos();
  823. }
  824. else
  825. {
  826. rel_pos1 = pos1 - multiBodyA->getLink(solverConstraint.m_linkA).m_cachedWorldTransform.getOrigin();
  827. }
  828. const int ndofA = multiBodyA->getNumDofs() + 6;
  829. solverConstraint.m_deltaVelAindex = multiBodyA->getCompanionId();
  830. if (solverConstraint.m_deltaVelAindex < 0)
  831. {
  832. solverConstraint.m_deltaVelAindex = m_data.m_deltaVelocities.size();
  833. multiBodyA->setCompanionId(solverConstraint.m_deltaVelAindex);
  834. m_data.m_deltaVelocities.resize(m_data.m_deltaVelocities.size() + ndofA);
  835. }
  836. else
  837. {
  838. btAssert(m_data.m_deltaVelocities.size() >= solverConstraint.m_deltaVelAindex + ndofA);
  839. }
  840. solverConstraint.m_jacAindex = m_data.m_jacobians.size();
  841. m_data.m_jacobians.resize(m_data.m_jacobians.size() + ndofA);
  842. m_data.m_deltaVelocitiesUnitImpulse.resize(m_data.m_deltaVelocitiesUnitImpulse.size() + ndofA);
  843. btAssert(m_data.m_jacobians.size() == m_data.m_deltaVelocitiesUnitImpulse.size());
  844. btScalar* jac1 = &m_data.m_jacobians[solverConstraint.m_jacAindex];
  845. multiBodyA->fillConstraintJacobianMultiDof(solverConstraint.m_linkA, cp.getPositionWorldOnA(), constraintNormal, btVector3(0, 0, 0), jac1, m_data.scratch_r, m_data.scratch_v, m_data.scratch_m);
  846. btScalar* delta = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
  847. multiBodyA->calcAccelerationDeltasMultiDof(&m_data.m_jacobians[solverConstraint.m_jacAindex], delta, m_data.scratch_r, m_data.scratch_v);
  848. btVector3 torqueAxis0 = constraintNormal;
  849. solverConstraint.m_relpos1CrossNormal = torqueAxis0;
  850. solverConstraint.m_contactNormal1 = btVector3(0, 0, 0);
  851. }
  852. else
  853. {
  854. btVector3 torqueAxis0 = constraintNormal;
  855. solverConstraint.m_relpos1CrossNormal = torqueAxis0;
  856. solverConstraint.m_contactNormal1 = btVector3(0, 0, 0);
  857. solverConstraint.m_angularComponentA = rb0 ? rb0->getInvInertiaTensorWorld() * torqueAxis0 * rb0->getAngularFactor() : btVector3(0, 0, 0);
  858. }
  859. if (multiBodyB)
  860. {
  861. if (solverConstraint.m_linkB < 0)
  862. {
  863. rel_pos2 = pos2 - multiBodyB->getBasePos();
  864. }
  865. else
  866. {
  867. rel_pos2 = pos2 - multiBodyB->getLink(solverConstraint.m_linkB).m_cachedWorldTransform.getOrigin();
  868. }
  869. const int ndofB = multiBodyB->getNumDofs() + 6;
  870. solverConstraint.m_deltaVelBindex = multiBodyB->getCompanionId();
  871. if (solverConstraint.m_deltaVelBindex < 0)
  872. {
  873. solverConstraint.m_deltaVelBindex = m_data.m_deltaVelocities.size();
  874. multiBodyB->setCompanionId(solverConstraint.m_deltaVelBindex);
  875. m_data.m_deltaVelocities.resize(m_data.m_deltaVelocities.size() + ndofB);
  876. }
  877. solverConstraint.m_jacBindex = m_data.m_jacobians.size();
  878. m_data.m_jacobians.resize(m_data.m_jacobians.size() + ndofB);
  879. m_data.m_deltaVelocitiesUnitImpulse.resize(m_data.m_deltaVelocitiesUnitImpulse.size() + ndofB);
  880. btAssert(m_data.m_jacobians.size() == m_data.m_deltaVelocitiesUnitImpulse.size());
  881. multiBodyB->fillConstraintJacobianMultiDof(solverConstraint.m_linkB, cp.getPositionWorldOnB(), -constraintNormal, btVector3(0, 0, 0), &m_data.m_jacobians[solverConstraint.m_jacBindex], m_data.scratch_r, m_data.scratch_v, m_data.scratch_m);
  882. multiBodyB->calcAccelerationDeltasMultiDof(&m_data.m_jacobians[solverConstraint.m_jacBindex], &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex], m_data.scratch_r, m_data.scratch_v);
  883. btVector3 torqueAxis1 = -constraintNormal;
  884. solverConstraint.m_relpos2CrossNormal = torqueAxis1;
  885. solverConstraint.m_contactNormal2 = -btVector3(0, 0, 0);
  886. }
  887. else
  888. {
  889. btVector3 torqueAxis1 = -constraintNormal;
  890. solverConstraint.m_relpos2CrossNormal = torqueAxis1;
  891. solverConstraint.m_contactNormal2 = -btVector3(0, 0, 0);
  892. solverConstraint.m_angularComponentB = rb1 ? rb1->getInvInertiaTensorWorld() * torqueAxis1 * rb1->getAngularFactor() : btVector3(0, 0, 0);
  893. }
  894. {
  895. btScalar denom0 = 0.f;
  896. btScalar denom1 = 0.f;
  897. btScalar* jacB = 0;
  898. btScalar* jacA = 0;
  899. btScalar* lambdaA = 0;
  900. btScalar* lambdaB = 0;
  901. int ndofA = 0;
  902. if (multiBodyA)
  903. {
  904. ndofA = multiBodyA->getNumDofs() + 6;
  905. jacA = &m_data.m_jacobians[solverConstraint.m_jacAindex];
  906. lambdaA = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
  907. for (int i = 0; i < ndofA; ++i)
  908. {
  909. btScalar j = jacA[i];
  910. btScalar l = lambdaA[i];
  911. denom0 += j * l;
  912. }
  913. }
  914. else
  915. {
  916. if (rb0)
  917. {
  918. btVector3 iMJaA = rb0 ? rb0->getInvInertiaTensorWorld() * solverConstraint.m_relpos1CrossNormal : btVector3(0, 0, 0);
  919. denom0 = iMJaA.dot(solverConstraint.m_relpos1CrossNormal);
  920. }
  921. }
  922. if (multiBodyB)
  923. {
  924. const int ndofB = multiBodyB->getNumDofs() + 6;
  925. jacB = &m_data.m_jacobians[solverConstraint.m_jacBindex];
  926. lambdaB = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex];
  927. for (int i = 0; i < ndofB; ++i)
  928. {
  929. btScalar j = jacB[i];
  930. btScalar l = lambdaB[i];
  931. denom1 += j * l;
  932. }
  933. }
  934. else
  935. {
  936. if (rb1)
  937. {
  938. btVector3 iMJaB = rb1 ? rb1->getInvInertiaTensorWorld() * solverConstraint.m_relpos2CrossNormal : btVector3(0, 0, 0);
  939. denom1 = iMJaB.dot(solverConstraint.m_relpos2CrossNormal);
  940. }
  941. }
  942. btScalar d = denom0 + denom1 + infoGlobal.m_globalCfm;
  943. if (d > SIMD_EPSILON)
  944. {
  945. solverConstraint.m_jacDiagABInv = relaxation / (d);
  946. }
  947. else
  948. {
  949. //disable the constraint row to handle singularity/redundant constraint
  950. solverConstraint.m_jacDiagABInv = 0.f;
  951. }
  952. }
  953. //compute rhs and remaining solverConstraint fields
  954. btScalar restitution = 0.f;
  955. btScalar penetration = isFriction ? 0 : cp.getDistance();
  956. btScalar rel_vel = 0.f;
  957. int ndofA = 0;
  958. int ndofB = 0;
  959. {
  960. btVector3 vel1, vel2;
  961. if (multiBodyA)
  962. {
  963. ndofA = multiBodyA->getNumDofs() + 6;
  964. btScalar* jacA = &m_data.m_jacobians[solverConstraint.m_jacAindex];
  965. for (int i = 0; i < ndofA; ++i)
  966. rel_vel += multiBodyA->getVelocityVector()[i] * jacA[i];
  967. }
  968. else
  969. {
  970. if (rb0)
  971. {
  972. btSolverBody* solverBodyA = &m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdA];
  973. rel_vel += solverConstraint.m_contactNormal1.dot(rb0 ? solverBodyA->m_linearVelocity + solverBodyA->m_externalForceImpulse : btVector3(0, 0, 0)) + solverConstraint.m_relpos1CrossNormal.dot(rb0 ? solverBodyA->m_angularVelocity : btVector3(0, 0, 0));
  974. }
  975. }
  976. if (multiBodyB)
  977. {
  978. ndofB = multiBodyB->getNumDofs() + 6;
  979. btScalar* jacB = &m_data.m_jacobians[solverConstraint.m_jacBindex];
  980. for (int i = 0; i < ndofB; ++i)
  981. rel_vel += multiBodyB->getVelocityVector()[i] * jacB[i];
  982. }
  983. else
  984. {
  985. if (rb1)
  986. {
  987. btSolverBody* solverBodyB = &m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdB];
  988. rel_vel += solverConstraint.m_contactNormal2.dot(rb1 ? solverBodyB->m_linearVelocity + solverBodyB->m_externalForceImpulse : btVector3(0, 0, 0)) + solverConstraint.m_relpos2CrossNormal.dot(rb1 ? solverBodyB->m_angularVelocity : btVector3(0, 0, 0));
  989. }
  990. }
  991. solverConstraint.m_friction = combinedTorsionalFriction;
  992. if (!isFriction)
  993. {
  994. restitution = restitutionCurve(rel_vel, cp.m_combinedRestitution, infoGlobal.m_restitutionVelocityThreshold);
  995. if (restitution <= btScalar(0.))
  996. {
  997. restitution = 0.f;
  998. }
  999. }
  1000. }
  1001. solverConstraint.m_appliedImpulse = 0.f;
  1002. solverConstraint.m_appliedPushImpulse = 0.f;
  1003. {
  1004. btScalar velocityError = 0 - rel_vel; // * damping; //note for friction restitution is always set to 0 (check above) so it is acutally velocityError = -rel_vel for friction
  1005. btScalar velocityImpulse = velocityError * solverConstraint.m_jacDiagABInv;
  1006. solverConstraint.m_rhs = velocityImpulse;
  1007. solverConstraint.m_rhsPenetration = 0.f;
  1008. solverConstraint.m_lowerLimit = -solverConstraint.m_friction;
  1009. solverConstraint.m_upperLimit = solverConstraint.m_friction;
  1010. solverConstraint.m_cfm = infoGlobal.m_globalCfm * solverConstraint.m_jacDiagABInv;
  1011. }
  1012. }
  1013. btMultiBodySolverConstraint& btMultiBodyConstraintSolver::addMultiBodyFrictionConstraint(const btVector3& normalAxis, const btScalar& appliedImpulse, btPersistentManifold* manifold, int frictionIndex, btManifoldPoint& cp, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip)
  1014. {
  1015. BT_PROFILE("addMultiBodyFrictionConstraint");
  1016. btMultiBodySolverConstraint& solverConstraint = m_multiBodyFrictionContactConstraints.expandNonInitializing();
  1017. solverConstraint.m_orgConstraint = 0;
  1018. solverConstraint.m_orgDofIndex = -1;
  1019. solverConstraint.m_frictionIndex = frictionIndex;
  1020. bool isFriction = true;
  1021. const btMultiBodyLinkCollider* fcA = btMultiBodyLinkCollider::upcast(manifold->getBody0());
  1022. const btMultiBodyLinkCollider* fcB = btMultiBodyLinkCollider::upcast(manifold->getBody1());
  1023. btMultiBody* mbA = fcA ? fcA->m_multiBody : 0;
  1024. btMultiBody* mbB = fcB ? fcB->m_multiBody : 0;
  1025. int solverBodyIdA = mbA ? -1 : getOrInitSolverBody(*colObj0, infoGlobal.m_timeStep);
  1026. int solverBodyIdB = mbB ? -1 : getOrInitSolverBody(*colObj1, infoGlobal.m_timeStep);
  1027. solverConstraint.m_solverBodyIdA = solverBodyIdA;
  1028. solverConstraint.m_solverBodyIdB = solverBodyIdB;
  1029. solverConstraint.m_multiBodyA = mbA;
  1030. if (mbA)
  1031. solverConstraint.m_linkA = fcA->m_link;
  1032. solverConstraint.m_multiBodyB = mbB;
  1033. if (mbB)
  1034. solverConstraint.m_linkB = fcB->m_link;
  1035. solverConstraint.m_originalContactPoint = &cp;
  1036. setupMultiBodyContactConstraint(solverConstraint, normalAxis, 0, cp, infoGlobal, relaxation, isFriction, desiredVelocity, cfmSlip);
  1037. return solverConstraint;
  1038. }
  1039. btMultiBodySolverConstraint& btMultiBodyConstraintSolver::addMultiBodyTorsionalFrictionConstraint(const btVector3& normalAxis, btPersistentManifold* manifold, int frictionIndex, btManifoldPoint& cp,
  1040. btScalar combinedTorsionalFriction,
  1041. btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip)
  1042. {
  1043. BT_PROFILE("addMultiBodyRollingFrictionConstraint");
  1044. bool useTorsionalAndConeFriction = (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS && ((infoGlobal.m_solverMode & SOLVER_DISABLE_IMPLICIT_CONE_FRICTION) == 0));
  1045. btMultiBodySolverConstraint& solverConstraint = useTorsionalAndConeFriction ? m_multiBodyTorsionalFrictionContactConstraints.expandNonInitializing() : m_multiBodyFrictionContactConstraints.expandNonInitializing();
  1046. solverConstraint.m_orgConstraint = 0;
  1047. solverConstraint.m_orgDofIndex = -1;
  1048. solverConstraint.m_frictionIndex = frictionIndex;
  1049. bool isFriction = true;
  1050. const btMultiBodyLinkCollider* fcA = btMultiBodyLinkCollider::upcast(manifold->getBody0());
  1051. const btMultiBodyLinkCollider* fcB = btMultiBodyLinkCollider::upcast(manifold->getBody1());
  1052. btMultiBody* mbA = fcA ? fcA->m_multiBody : 0;
  1053. btMultiBody* mbB = fcB ? fcB->m_multiBody : 0;
  1054. int solverBodyIdA = mbA ? -1 : getOrInitSolverBody(*colObj0, infoGlobal.m_timeStep);
  1055. int solverBodyIdB = mbB ? -1 : getOrInitSolverBody(*colObj1, infoGlobal.m_timeStep);
  1056. solverConstraint.m_solverBodyIdA = solverBodyIdA;
  1057. solverConstraint.m_solverBodyIdB = solverBodyIdB;
  1058. solverConstraint.m_multiBodyA = mbA;
  1059. if (mbA)
  1060. solverConstraint.m_linkA = fcA->m_link;
  1061. solverConstraint.m_multiBodyB = mbB;
  1062. if (mbB)
  1063. solverConstraint.m_linkB = fcB->m_link;
  1064. solverConstraint.m_originalContactPoint = &cp;
  1065. setupMultiBodyTorsionalFrictionConstraint(solverConstraint, normalAxis, cp, combinedTorsionalFriction, infoGlobal, relaxation, isFriction, desiredVelocity, cfmSlip);
  1066. return solverConstraint;
  1067. }
  1068. btMultiBodySolverConstraint& btMultiBodyConstraintSolver::addMultiBodySpinningFrictionConstraint(const btVector3& normalAxis, btPersistentManifold* manifold, int frictionIndex, btManifoldPoint& cp,
  1069. btScalar combinedTorsionalFriction,
  1070. btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip)
  1071. {
  1072. BT_PROFILE("addMultiBodyRollingFrictionConstraint");
  1073. btMultiBodySolverConstraint& solverConstraint = m_multiBodySpinningFrictionContactConstraints.expandNonInitializing();
  1074. solverConstraint.m_orgConstraint = 0;
  1075. solverConstraint.m_orgDofIndex = -1;
  1076. solverConstraint.m_frictionIndex = frictionIndex;
  1077. bool isFriction = true;
  1078. const btMultiBodyLinkCollider* fcA = btMultiBodyLinkCollider::upcast(manifold->getBody0());
  1079. const btMultiBodyLinkCollider* fcB = btMultiBodyLinkCollider::upcast(manifold->getBody1());
  1080. btMultiBody* mbA = fcA ? fcA->m_multiBody : 0;
  1081. btMultiBody* mbB = fcB ? fcB->m_multiBody : 0;
  1082. int solverBodyIdA = mbA ? -1 : getOrInitSolverBody(*colObj0, infoGlobal.m_timeStep);
  1083. int solverBodyIdB = mbB ? -1 : getOrInitSolverBody(*colObj1, infoGlobal.m_timeStep);
  1084. solverConstraint.m_solverBodyIdA = solverBodyIdA;
  1085. solverConstraint.m_solverBodyIdB = solverBodyIdB;
  1086. solverConstraint.m_multiBodyA = mbA;
  1087. if (mbA)
  1088. solverConstraint.m_linkA = fcA->m_link;
  1089. solverConstraint.m_multiBodyB = mbB;
  1090. if (mbB)
  1091. solverConstraint.m_linkB = fcB->m_link;
  1092. solverConstraint.m_originalContactPoint = &cp;
  1093. setupMultiBodyTorsionalFrictionConstraint(solverConstraint, normalAxis, cp, combinedTorsionalFriction, infoGlobal, relaxation, isFriction, desiredVelocity, cfmSlip);
  1094. return solverConstraint;
  1095. }
  1096. void btMultiBodyConstraintSolver::convertMultiBodyContact(btPersistentManifold* manifold, const btContactSolverInfo& infoGlobal)
  1097. {
  1098. const btMultiBodyLinkCollider* fcA = btMultiBodyLinkCollider::upcast(manifold->getBody0());
  1099. const btMultiBodyLinkCollider* fcB = btMultiBodyLinkCollider::upcast(manifold->getBody1());
  1100. btMultiBody* mbA = fcA ? fcA->m_multiBody : 0;
  1101. btMultiBody* mbB = fcB ? fcB->m_multiBody : 0;
  1102. btCollisionObject *colObj0 = 0, *colObj1 = 0;
  1103. colObj0 = (btCollisionObject*)manifold->getBody0();
  1104. colObj1 = (btCollisionObject*)manifold->getBody1();
  1105. int solverBodyIdA = mbA ? -1 : getOrInitSolverBody(*colObj0, infoGlobal.m_timeStep);
  1106. int solverBodyIdB = mbB ? -1 : getOrInitSolverBody(*colObj1, infoGlobal.m_timeStep);
  1107. // btSolverBody* solverBodyA = mbA ? 0 : &m_tmpSolverBodyPool[solverBodyIdA];
  1108. // btSolverBody* solverBodyB = mbB ? 0 : &m_tmpSolverBodyPool[solverBodyIdB];
  1109. ///avoid collision response between two static objects
  1110. // if (!solverBodyA || (solverBodyA->m_invMass.isZero() && (!solverBodyB || solverBodyB->m_invMass.isZero())))
  1111. // return;
  1112. //only a single rollingFriction per manifold
  1113. int rollingFriction = 4;
  1114. for (int j = 0; j < manifold->getNumContacts(); j++)
  1115. {
  1116. btManifoldPoint& cp = manifold->getContactPoint(j);
  1117. if (cp.getDistance() <= manifold->getContactProcessingThreshold())
  1118. {
  1119. btScalar relaxation;
  1120. int frictionIndex = m_multiBodyNormalContactConstraints.size();
  1121. btMultiBodySolverConstraint& solverConstraint = m_multiBodyNormalContactConstraints.expandNonInitializing();
  1122. // btRigidBody* rb0 = btRigidBody::upcast(colObj0);
  1123. // btRigidBody* rb1 = btRigidBody::upcast(colObj1);
  1124. solverConstraint.m_orgConstraint = 0;
  1125. solverConstraint.m_orgDofIndex = -1;
  1126. solverConstraint.m_solverBodyIdA = solverBodyIdA;
  1127. solverConstraint.m_solverBodyIdB = solverBodyIdB;
  1128. solverConstraint.m_multiBodyA = mbA;
  1129. if (mbA)
  1130. solverConstraint.m_linkA = fcA->m_link;
  1131. solverConstraint.m_multiBodyB = mbB;
  1132. if (mbB)
  1133. solverConstraint.m_linkB = fcB->m_link;
  1134. solverConstraint.m_originalContactPoint = &cp;
  1135. bool isFriction = false;
  1136. setupMultiBodyContactConstraint(solverConstraint, cp.m_normalWorldOnB, cp.m_appliedImpulse, cp, infoGlobal, relaxation, isFriction);
  1137. // const btVector3& pos1 = cp.getPositionWorldOnA();
  1138. // const btVector3& pos2 = cp.getPositionWorldOnB();
  1139. /////setup the friction constraints
  1140. #define ENABLE_FRICTION
  1141. #ifdef ENABLE_FRICTION
  1142. solverConstraint.m_frictionIndex = m_multiBodyFrictionContactConstraints.size();
  1143. ///Bullet has several options to set the friction directions
  1144. ///By default, each contact has only a single friction direction that is recomputed automatically every frame
  1145. ///based on the relative linear velocity.
  1146. ///If the relative velocity is zero, it will automatically compute a friction direction.
  1147. ///You can also enable two friction directions, using the SOLVER_USE_2_FRICTION_DIRECTIONS.
  1148. ///In that case, the second friction direction will be orthogonal to both contact normal and first friction direction.
  1149. ///
  1150. ///If you choose SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION, then the friction will be independent from the relative projected velocity.
  1151. ///
  1152. ///The user can manually override the friction directions for certain contacts using a contact callback,
  1153. ///and set the cp.m_lateralFrictionInitialized to true
  1154. ///In that case, you can set the target relative motion in each friction direction (cp.m_contactMotion1 and cp.m_contactMotion2)
  1155. ///this will give a conveyor belt effect
  1156. ///
  1157. btPlaneSpace1(cp.m_normalWorldOnB, cp.m_lateralFrictionDir1, cp.m_lateralFrictionDir2);
  1158. cp.m_lateralFrictionDir1.normalize();
  1159. cp.m_lateralFrictionDir2.normalize();
  1160. if (rollingFriction > 0)
  1161. {
  1162. if (cp.m_combinedSpinningFriction > 0)
  1163. {
  1164. addMultiBodySpinningFrictionConstraint(cp.m_normalWorldOnB, manifold, frictionIndex, cp, cp.m_combinedSpinningFriction, colObj0, colObj1, relaxation, infoGlobal);
  1165. }
  1166. if (cp.m_combinedRollingFriction > 0)
  1167. {
  1168. applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
  1169. applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
  1170. applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
  1171. applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
  1172. addMultiBodyTorsionalFrictionConstraint(cp.m_lateralFrictionDir1, manifold, frictionIndex, cp, cp.m_combinedRollingFriction, colObj0, colObj1, relaxation, infoGlobal);
  1173. addMultiBodyTorsionalFrictionConstraint(cp.m_lateralFrictionDir2, manifold, frictionIndex, cp, cp.m_combinedRollingFriction, colObj0, colObj1, relaxation, infoGlobal);
  1174. }
  1175. rollingFriction--;
  1176. }
  1177. if (!(infoGlobal.m_solverMode & SOLVER_ENABLE_FRICTION_DIRECTION_CACHING) || !(cp.m_contactPointFlags & BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED))
  1178. { /*
  1179. cp.m_lateralFrictionDir1 = vel - cp.m_normalWorldOnB * rel_vel;
  1180. btScalar lat_rel_vel = cp.m_lateralFrictionDir1.length2();
  1181. if (!(infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION) && lat_rel_vel > SIMD_EPSILON)
  1182. {
  1183. cp.m_lateralFrictionDir1 *= 1.f/btSqrt(lat_rel_vel);
  1184. if((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
  1185. {
  1186. cp.m_lateralFrictionDir2 = cp.m_lateralFrictionDir1.cross(cp.m_normalWorldOnB);
  1187. cp.m_lateralFrictionDir2.normalize();//??
  1188. applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir2,btCollisionObject::CF_ANISOTROPIC_FRICTION);
  1189. applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir2,btCollisionObject::CF_ANISOTROPIC_FRICTION);
  1190. addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
  1191. }
  1192. applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir1,btCollisionObject::CF_ANISOTROPIC_FRICTION);
  1193. applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir1,btCollisionObject::CF_ANISOTROPIC_FRICTION);
  1194. addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
  1195. } else
  1196. */
  1197. {
  1198. applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
  1199. applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
  1200. addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir1, cp.m_appliedImpulseLateral1, manifold, frictionIndex, cp, colObj0, colObj1, relaxation, infoGlobal);
  1201. if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
  1202. {
  1203. applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
  1204. applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
  1205. addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir2, cp.m_appliedImpulseLateral2, manifold, frictionIndex, cp, colObj0, colObj1, relaxation, infoGlobal);
  1206. }
  1207. if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) && (infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION))
  1208. {
  1209. cp.m_contactPointFlags |= BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED;
  1210. }
  1211. }
  1212. }
  1213. else
  1214. {
  1215. addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir1, cp.m_appliedImpulseLateral1, manifold, frictionIndex, cp, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion1, cp.m_frictionCFM);
  1216. if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
  1217. addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir2, cp.m_appliedImpulseLateral2, manifold, frictionIndex, cp, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion2, cp.m_frictionCFM);
  1218. solverConstraint.m_appliedImpulse = 0.f;
  1219. solverConstraint.m_appliedPushImpulse = 0.f;
  1220. }
  1221. #endif //ENABLE_FRICTION
  1222. }
  1223. else
  1224. {
  1225. // Reset quantities related to warmstart as 0.
  1226. cp.m_appliedImpulse = 0;
  1227. cp.m_prevRHS = 0;
  1228. }
  1229. }
  1230. }
  1231. void btMultiBodyConstraintSolver::convertContacts(btPersistentManifold** manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal)
  1232. {
  1233. for (int i = 0; i < numManifolds; i++)
  1234. {
  1235. btPersistentManifold* manifold = manifoldPtr[i];
  1236. const btMultiBodyLinkCollider* fcA = btMultiBodyLinkCollider::upcast(manifold->getBody0());
  1237. const btMultiBodyLinkCollider* fcB = btMultiBodyLinkCollider::upcast(manifold->getBody1());
  1238. if (!fcA && !fcB)
  1239. {
  1240. //the contact doesn't involve any Featherstone btMultiBody, so deal with the regular btRigidBody/btCollisionObject case
  1241. convertContact(manifold, infoGlobal);
  1242. }
  1243. else
  1244. {
  1245. convertMultiBodyContact(manifold, infoGlobal);
  1246. }
  1247. }
  1248. //also convert the multibody constraints, if any
  1249. for (int i = 0; i < m_tmpNumMultiBodyConstraints; i++)
  1250. {
  1251. btMultiBodyConstraint* c = m_tmpMultiBodyConstraints[i];
  1252. m_data.m_solverBodyPool = &m_tmpSolverBodyPool;
  1253. m_data.m_fixedBodyId = m_fixedBodyId;
  1254. c->createConstraintRows(m_multiBodyNonContactConstraints, m_data, infoGlobal);
  1255. }
  1256. // Warmstart for noncontact constraints
  1257. if (infoGlobal.m_solverMode & SOLVER_USE_ARTICULATED_WARMSTARTING)
  1258. {
  1259. for (int i = 0; i < m_multiBodyNonContactConstraints.size(); i++)
  1260. {
  1261. btMultiBodySolverConstraint& solverConstraint =
  1262. m_multiBodyNonContactConstraints[i];
  1263. solverConstraint.m_appliedImpulse =
  1264. solverConstraint.m_orgConstraint->getAppliedImpulse(solverConstraint.m_orgDofIndex) *
  1265. infoGlobal.m_articulatedWarmstartingFactor;
  1266. btMultiBody* multiBodyA = solverConstraint.m_multiBodyA;
  1267. btMultiBody* multiBodyB = solverConstraint.m_multiBodyB;
  1268. if (solverConstraint.m_appliedImpulse)
  1269. {
  1270. if (multiBodyA)
  1271. {
  1272. int ndofA = multiBodyA->getNumDofs() + 6;
  1273. btScalar* deltaV =
  1274. &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
  1275. btScalar impulse = solverConstraint.m_appliedImpulse;
  1276. multiBodyA->applyDeltaVeeMultiDof2(deltaV, impulse);
  1277. applyDeltaVee(deltaV, impulse, solverConstraint.m_deltaVelAindex, ndofA);
  1278. }
  1279. if (multiBodyB)
  1280. {
  1281. int ndofB = multiBodyB->getNumDofs() + 6;
  1282. btScalar* deltaV =
  1283. &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex];
  1284. btScalar impulse = solverConstraint.m_appliedImpulse;
  1285. multiBodyB->applyDeltaVeeMultiDof2(deltaV, impulse);
  1286. applyDeltaVee(deltaV, impulse, solverConstraint.m_deltaVelBindex, ndofB);
  1287. }
  1288. }
  1289. }
  1290. }
  1291. else
  1292. {
  1293. for (int i = 0; i < m_multiBodyNonContactConstraints.size(); i++)
  1294. {
  1295. btMultiBodySolverConstraint& solverConstraint = m_multiBodyNonContactConstraints[i];
  1296. solverConstraint.m_appliedImpulse = 0;
  1297. }
  1298. }
  1299. }
  1300. btScalar btMultiBodyConstraintSolver::solveGroup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifold, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& info, btIDebugDraw* debugDrawer, btDispatcher* dispatcher)
  1301. {
  1302. //printf("btMultiBodyConstraintSolver::solveGroup: numBodies=%d, numConstraints=%d\n", numBodies, numConstraints);
  1303. return btSequentialImpulseConstraintSolver::solveGroup(bodies, numBodies, manifold, numManifolds, constraints, numConstraints, info, debugDrawer, dispatcher);
  1304. }
  1305. #if 0
  1306. static void applyJointFeedback(btMultiBodyJacobianData& data, const btMultiBodySolverConstraint& solverConstraint, int jacIndex, btMultiBody* mb, btScalar appliedImpulse)
  1307. {
  1308. if (appliedImpulse!=0 && mb->internalNeedsJointFeedback())
  1309. {
  1310. //todo: get rid of those temporary memory allocations for the joint feedback
  1311. btAlignedObjectArray<btScalar> forceVector;
  1312. int numDofsPlusBase = 6+mb->getNumDofs();
  1313. forceVector.resize(numDofsPlusBase);
  1314. for (int i=0;i<numDofsPlusBase;i++)
  1315. {
  1316. forceVector[i] = data.m_jacobians[jacIndex+i]*appliedImpulse;
  1317. }
  1318. btAlignedObjectArray<btScalar> output;
  1319. output.resize(numDofsPlusBase);
  1320. bool applyJointFeedback = true;
  1321. mb->calcAccelerationDeltasMultiDof(&forceVector[0],&output[0],data.scratch_r,data.scratch_v,applyJointFeedback);
  1322. }
  1323. }
  1324. #endif
  1325. void btMultiBodyConstraintSolver::writeBackSolverBodyToMultiBody(btMultiBodySolverConstraint& c, btScalar deltaTime)
  1326. {
  1327. #if 1
  1328. //bod->addBaseForce(m_gravity * bod->getBaseMass());
  1329. //bod->addLinkForce(j, m_gravity * bod->getLinkMass(j));
  1330. if (c.m_orgConstraint)
  1331. {
  1332. c.m_orgConstraint->internalSetAppliedImpulse(c.m_orgDofIndex, c.m_appliedImpulse);
  1333. }
  1334. if (c.m_multiBodyA)
  1335. {
  1336. c.m_multiBodyA->setCompanionId(-1);
  1337. btVector3 force = c.m_contactNormal1 * (c.m_appliedImpulse / deltaTime);
  1338. btVector3 torque = c.m_relpos1CrossNormal * (c.m_appliedImpulse / deltaTime);
  1339. if (c.m_linkA < 0)
  1340. {
  1341. c.m_multiBodyA->addBaseConstraintForce(force);
  1342. c.m_multiBodyA->addBaseConstraintTorque(torque);
  1343. }
  1344. else
  1345. {
  1346. c.m_multiBodyA->addLinkConstraintForce(c.m_linkA, force);
  1347. //b3Printf("force = %f,%f,%f\n",force[0],force[1],force[2]);//[0],torque[1],torque[2]);
  1348. c.m_multiBodyA->addLinkConstraintTorque(c.m_linkA, torque);
  1349. }
  1350. }
  1351. if (c.m_multiBodyB)
  1352. {
  1353. {
  1354. c.m_multiBodyB->setCompanionId(-1);
  1355. btVector3 force = c.m_contactNormal2 * (c.m_appliedImpulse / deltaTime);
  1356. btVector3 torque = c.m_relpos2CrossNormal * (c.m_appliedImpulse / deltaTime);
  1357. if (c.m_linkB < 0)
  1358. {
  1359. c.m_multiBodyB->addBaseConstraintForce(force);
  1360. c.m_multiBodyB->addBaseConstraintTorque(torque);
  1361. }
  1362. else
  1363. {
  1364. {
  1365. c.m_multiBodyB->addLinkConstraintForce(c.m_linkB, force);
  1366. //b3Printf("t = %f,%f,%f\n",force[0],force[1],force[2]);//[0],torque[1],torque[2]);
  1367. c.m_multiBodyB->addLinkConstraintTorque(c.m_linkB, torque);
  1368. }
  1369. }
  1370. }
  1371. }
  1372. #endif
  1373. #ifndef DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
  1374. if (c.m_multiBodyA)
  1375. {
  1376. c.m_multiBodyA->applyDeltaVeeMultiDof(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacAindex], c.m_appliedImpulse);
  1377. }
  1378. if (c.m_multiBodyB)
  1379. {
  1380. c.m_multiBodyB->applyDeltaVeeMultiDof(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacBindex], c.m_appliedImpulse);
  1381. }
  1382. #endif
  1383. }
  1384. btScalar btMultiBodyConstraintSolver::solveGroupCacheFriendlyFinish(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal)
  1385. {
  1386. BT_PROFILE("btMultiBodyConstraintSolver::solveGroupCacheFriendlyFinish");
  1387. int numPoolConstraints = m_multiBodyNormalContactConstraints.size();
  1388. //write back the delta v to the multi bodies, either as applied impulse (direct velocity change)
  1389. //or as applied force, so we can measure the joint reaction forces easier
  1390. for (int i = 0; i < numPoolConstraints; i++)
  1391. {
  1392. btMultiBodySolverConstraint& solverConstraint = m_multiBodyNormalContactConstraints[i];
  1393. writeBackSolverBodyToMultiBody(solverConstraint, infoGlobal.m_timeStep);
  1394. writeBackSolverBodyToMultiBody(m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex], infoGlobal.m_timeStep);
  1395. if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
  1396. {
  1397. writeBackSolverBodyToMultiBody(m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex + 1], infoGlobal.m_timeStep);
  1398. }
  1399. }
  1400. for (int i = 0; i < m_multiBodyNonContactConstraints.size(); i++)
  1401. {
  1402. btMultiBodySolverConstraint& solverConstraint = m_multiBodyNonContactConstraints[i];
  1403. writeBackSolverBodyToMultiBody(solverConstraint, infoGlobal.m_timeStep);
  1404. }
  1405. {
  1406. BT_PROFILE("warm starting write back");
  1407. for (int j = 0; j < numPoolConstraints; j++)
  1408. {
  1409. const btMultiBodySolverConstraint& solverConstraint = m_multiBodyNormalContactConstraints[j];
  1410. btManifoldPoint* pt = (btManifoldPoint*)solverConstraint.m_originalContactPoint;
  1411. btAssert(pt);
  1412. pt->m_appliedImpulse = solverConstraint.m_appliedImpulse;
  1413. pt->m_prevRHS = solverConstraint.m_rhs;
  1414. pt->m_appliedImpulseLateral1 = m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_appliedImpulse;
  1415. //printf("pt->m_appliedImpulseLateral1 = %f\n", pt->m_appliedImpulseLateral1);
  1416. if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
  1417. {
  1418. pt->m_appliedImpulseLateral2 = m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex + 1].m_appliedImpulse;
  1419. } else
  1420. {
  1421. pt->m_appliedImpulseLateral2 = 0;
  1422. }
  1423. }
  1424. }
  1425. #if 0
  1426. //multibody joint feedback
  1427. {
  1428. BT_PROFILE("multi body joint feedback");
  1429. for (int j=0;j<numPoolConstraints;j++)
  1430. {
  1431. const btMultiBodySolverConstraint& solverConstraint = m_multiBodyNormalContactConstraints[j];
  1432. //apply the joint feedback into all links of the btMultiBody
  1433. //todo: double-check the signs of the applied impulse
  1434. if(solverConstraint.m_multiBodyA && solverConstraint.m_multiBodyA->isMultiDof())
  1435. {
  1436. applyJointFeedback(m_data,solverConstraint, solverConstraint.m_jacAindex,solverConstraint.m_multiBodyA, solverConstraint.m_appliedImpulse*btSimdScalar(1./infoGlobal.m_timeStep));
  1437. }
  1438. if(solverConstraint.m_multiBodyB && solverConstraint.m_multiBodyB->isMultiDof())
  1439. {
  1440. applyJointFeedback(m_data,solverConstraint, solverConstraint.m_jacBindex,solverConstraint.m_multiBodyB,solverConstraint.m_appliedImpulse*btSimdScalar(-1./infoGlobal.m_timeStep));
  1441. }
  1442. #if 0
  1443. if (m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_multiBodyA && m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_multiBodyA->isMultiDof())
  1444. {
  1445. applyJointFeedback(m_data,m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex],
  1446. m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_jacAindex,
  1447. m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_multiBodyA,
  1448. m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_appliedImpulse*btSimdScalar(1./infoGlobal.m_timeStep));
  1449. }
  1450. if (m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_multiBodyB && m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_multiBodyB->isMultiDof())
  1451. {
  1452. applyJointFeedback(m_data,m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex],
  1453. m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_jacBindex,
  1454. m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_multiBodyB,
  1455. m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_appliedImpulse*btSimdScalar(-1./infoGlobal.m_timeStep));
  1456. }
  1457. if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
  1458. {
  1459. if (m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_multiBodyA && m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_multiBodyA->isMultiDof())
  1460. {
  1461. applyJointFeedback(m_data,m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1],
  1462. m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_jacAindex,
  1463. m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_multiBodyA,
  1464. m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_appliedImpulse*btSimdScalar(1./infoGlobal.m_timeStep));
  1465. }
  1466. if (m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_multiBodyB && m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_multiBodyB->isMultiDof())
  1467. {
  1468. applyJointFeedback(m_data,m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1],
  1469. m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_jacBindex,
  1470. m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_multiBodyB,
  1471. m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_appliedImpulse*btSimdScalar(-1./infoGlobal.m_timeStep));
  1472. }
  1473. }
  1474. #endif
  1475. }
  1476. for (int i=0;i<m_multiBodyNonContactConstraints.size();i++)
  1477. {
  1478. const btMultiBodySolverConstraint& solverConstraint = m_multiBodyNonContactConstraints[i];
  1479. if(solverConstraint.m_multiBodyA && solverConstraint.m_multiBodyA->isMultiDof())
  1480. {
  1481. applyJointFeedback(m_data,solverConstraint, solverConstraint.m_jacAindex,solverConstraint.m_multiBodyA, solverConstraint.m_appliedImpulse*btSimdScalar(1./infoGlobal.m_timeStep));
  1482. }
  1483. if(solverConstraint.m_multiBodyB && solverConstraint.m_multiBodyB->isMultiDof())
  1484. {
  1485. applyJointFeedback(m_data,solverConstraint, solverConstraint.m_jacBindex,solverConstraint.m_multiBodyB,solverConstraint.m_appliedImpulse*btSimdScalar(1./infoGlobal.m_timeStep));
  1486. }
  1487. }
  1488. }
  1489. numPoolConstraints = m_multiBodyNonContactConstraints.size();
  1490. #if 0
  1491. //@todo: m_originalContactPoint is not initialized for btMultiBodySolverConstraint
  1492. for (int i=0;i<numPoolConstraints;i++)
  1493. {
  1494. const btMultiBodySolverConstraint& c = m_multiBodyNonContactConstraints[i];
  1495. btTypedConstraint* constr = (btTypedConstraint*)c.m_originalContactPoint;
  1496. btJointFeedback* fb = constr->getJointFeedback();
  1497. if (fb)
  1498. {
  1499. fb->m_appliedForceBodyA += c.m_contactNormal1*c.m_appliedImpulse*constr->getRigidBodyA().getLinearFactor()/infoGlobal.m_timeStep;
  1500. fb->m_appliedForceBodyB += c.m_contactNormal2*c.m_appliedImpulse*constr->getRigidBodyB().getLinearFactor()/infoGlobal.m_timeStep;
  1501. fb->m_appliedTorqueBodyA += c.m_relpos1CrossNormal* constr->getRigidBodyA().getAngularFactor()*c.m_appliedImpulse/infoGlobal.m_timeStep;
  1502. fb->m_appliedTorqueBodyB += c.m_relpos2CrossNormal* constr->getRigidBodyB().getAngularFactor()*c.m_appliedImpulse/infoGlobal.m_timeStep; /*RGM ???? */
  1503. }
  1504. constr->internalSetAppliedImpulse(c.m_appliedImpulse);
  1505. if (btFabs(c.m_appliedImpulse)>=constr->getBreakingImpulseThreshold())
  1506. {
  1507. constr->setEnabled(false);
  1508. }
  1509. }
  1510. #endif
  1511. #endif
  1512. return btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyFinish(bodies, numBodies, infoGlobal);
  1513. }
  1514. void btMultiBodyConstraintSolver::solveMultiBodyGroup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifold, int numManifolds, btTypedConstraint** constraints, int numConstraints, btMultiBodyConstraint** multiBodyConstraints, int numMultiBodyConstraints, const btContactSolverInfo& info, btIDebugDraw* debugDrawer, btDispatcher* dispatcher)
  1515. {
  1516. //printf("solveMultiBodyGroup: numBodies=%d, numConstraints=%d, numManifolds=%d, numMultiBodyConstraints=%d\n", numBodies, numConstraints, numManifolds, numMultiBodyConstraints);
  1517. //printf("solveMultiBodyGroup start\n");
  1518. m_tmpMultiBodyConstraints = multiBodyConstraints;
  1519. m_tmpNumMultiBodyConstraints = numMultiBodyConstraints;
  1520. btSequentialImpulseConstraintSolver::solveGroup(bodies, numBodies, manifold, numManifolds, constraints, numConstraints, info, debugDrawer, dispatcher);
  1521. m_tmpMultiBodyConstraints = 0;
  1522. m_tmpNumMultiBodyConstraints = 0;
  1523. }