btSliderConstraint.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855
  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. /*
  14. Added by Roman Ponomarev ([email protected])
  15. April 04, 2008
  16. */
  17. #include "btSliderConstraint.h"
  18. #include "BulletDynamics/Dynamics/btRigidBody.h"
  19. #include "LinearMath/btTransformUtil.h"
  20. #include <new>
  21. #define USE_OFFSET_FOR_CONSTANT_FRAME true
  22. void btSliderConstraint::initParams()
  23. {
  24. m_lowerLinLimit = btScalar(1.0);
  25. m_upperLinLimit = btScalar(-1.0);
  26. m_lowerAngLimit = btScalar(0.);
  27. m_upperAngLimit = btScalar(0.);
  28. m_softnessDirLin = SLIDER_CONSTRAINT_DEF_SOFTNESS;
  29. m_restitutionDirLin = SLIDER_CONSTRAINT_DEF_RESTITUTION;
  30. m_dampingDirLin = btScalar(0.);
  31. m_cfmDirLin = SLIDER_CONSTRAINT_DEF_CFM;
  32. m_softnessDirAng = SLIDER_CONSTRAINT_DEF_SOFTNESS;
  33. m_restitutionDirAng = SLIDER_CONSTRAINT_DEF_RESTITUTION;
  34. m_dampingDirAng = btScalar(0.);
  35. m_cfmDirAng = SLIDER_CONSTRAINT_DEF_CFM;
  36. m_softnessOrthoLin = SLIDER_CONSTRAINT_DEF_SOFTNESS;
  37. m_restitutionOrthoLin = SLIDER_CONSTRAINT_DEF_RESTITUTION;
  38. m_dampingOrthoLin = SLIDER_CONSTRAINT_DEF_DAMPING;
  39. m_cfmOrthoLin = SLIDER_CONSTRAINT_DEF_CFM;
  40. m_softnessOrthoAng = SLIDER_CONSTRAINT_DEF_SOFTNESS;
  41. m_restitutionOrthoAng = SLIDER_CONSTRAINT_DEF_RESTITUTION;
  42. m_dampingOrthoAng = SLIDER_CONSTRAINT_DEF_DAMPING;
  43. m_cfmOrthoAng = SLIDER_CONSTRAINT_DEF_CFM;
  44. m_softnessLimLin = SLIDER_CONSTRAINT_DEF_SOFTNESS;
  45. m_restitutionLimLin = SLIDER_CONSTRAINT_DEF_RESTITUTION;
  46. m_dampingLimLin = SLIDER_CONSTRAINT_DEF_DAMPING;
  47. m_cfmLimLin = SLIDER_CONSTRAINT_DEF_CFM;
  48. m_softnessLimAng = SLIDER_CONSTRAINT_DEF_SOFTNESS;
  49. m_restitutionLimAng = SLIDER_CONSTRAINT_DEF_RESTITUTION;
  50. m_dampingLimAng = SLIDER_CONSTRAINT_DEF_DAMPING;
  51. m_cfmLimAng = SLIDER_CONSTRAINT_DEF_CFM;
  52. m_poweredLinMotor = false;
  53. m_targetLinMotorVelocity = btScalar(0.);
  54. m_maxLinMotorForce = btScalar(0.);
  55. m_accumulatedLinMotorImpulse = btScalar(0.0);
  56. m_poweredAngMotor = false;
  57. m_targetAngMotorVelocity = btScalar(0.);
  58. m_maxAngMotorForce = btScalar(0.);
  59. m_accumulatedAngMotorImpulse = btScalar(0.0);
  60. m_flags = 0;
  61. m_flags = 0;
  62. m_useOffsetForConstraintFrame = USE_OFFSET_FOR_CONSTANT_FRAME;
  63. calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
  64. }
  65. btSliderConstraint::btSliderConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA)
  66. : btTypedConstraint(SLIDER_CONSTRAINT_TYPE, rbA, rbB),
  67. m_useSolveConstraintObsolete(false),
  68. m_frameInA(frameInA),
  69. m_frameInB(frameInB),
  70. m_useLinearReferenceFrameA(useLinearReferenceFrameA)
  71. {
  72. initParams();
  73. }
  74. btSliderConstraint::btSliderConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameA)
  75. : btTypedConstraint(SLIDER_CONSTRAINT_TYPE, getFixedBody(), rbB),
  76. m_useSolveConstraintObsolete(false),
  77. m_frameInB(frameInB),
  78. m_useLinearReferenceFrameA(useLinearReferenceFrameA)
  79. {
  80. ///not providing rigidbody A means implicitly using worldspace for body A
  81. m_frameInA = rbB.getCenterOfMassTransform() * m_frameInB;
  82. // m_frameInA.getOrigin() = m_rbA.getCenterOfMassTransform()(m_frameInA.getOrigin());
  83. initParams();
  84. }
  85. void btSliderConstraint::getInfo1(btConstraintInfo1* info)
  86. {
  87. if (m_useSolveConstraintObsolete)
  88. {
  89. info->m_numConstraintRows = 0;
  90. info->nub = 0;
  91. }
  92. else
  93. {
  94. info->m_numConstraintRows = 4; // Fixed 2 linear + 2 angular
  95. info->nub = 2;
  96. //prepare constraint
  97. calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
  98. testAngLimits();
  99. testLinLimits();
  100. if(getSolveLinLimit() || getPoweredLinMotor())
  101. {
  102. info->m_numConstraintRows++; // limit 3rd linear as well
  103. info->nub--;
  104. }
  105. if(getSolveAngLimit() || getPoweredAngMotor())
  106. {
  107. info->m_numConstraintRows++; // limit 3rd angular as well
  108. info->nub--;
  109. }
  110. }
  111. }
  112. void btSliderConstraint::getInfo1NonVirtual(btConstraintInfo1* info)
  113. {
  114. info->m_numConstraintRows = 6; // Fixed 2 linear + 2 angular + 1 limit (even if not used)
  115. info->nub = 0;
  116. }
  117. void btSliderConstraint::getInfo2(btConstraintInfo2* info)
  118. {
  119. getInfo2NonVirtual(info,m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform(), m_rbA.getLinearVelocity(),m_rbB.getLinearVelocity(), m_rbA.getInvMass(),m_rbB.getInvMass());
  120. }
  121. void btSliderConstraint::calculateTransforms(const btTransform& transA,const btTransform& transB)
  122. {
  123. if(m_useLinearReferenceFrameA || (!m_useSolveConstraintObsolete))
  124. {
  125. m_calculatedTransformA = transA * m_frameInA;
  126. m_calculatedTransformB = transB * m_frameInB;
  127. }
  128. else
  129. {
  130. m_calculatedTransformA = transB * m_frameInB;
  131. m_calculatedTransformB = transA * m_frameInA;
  132. }
  133. m_realPivotAInW = m_calculatedTransformA.getOrigin();
  134. m_realPivotBInW = m_calculatedTransformB.getOrigin();
  135. m_sliderAxis = m_calculatedTransformA.getBasis().getColumn(0); // along X
  136. if(m_useLinearReferenceFrameA || m_useSolveConstraintObsolete)
  137. {
  138. m_delta = m_realPivotBInW - m_realPivotAInW;
  139. }
  140. else
  141. {
  142. m_delta = m_realPivotAInW - m_realPivotBInW;
  143. }
  144. m_projPivotInW = m_realPivotAInW + m_sliderAxis.dot(m_delta) * m_sliderAxis;
  145. btVector3 normalWorld;
  146. int i;
  147. //linear part
  148. for(i = 0; i < 3; i++)
  149. {
  150. normalWorld = m_calculatedTransformA.getBasis().getColumn(i);
  151. m_depth[i] = m_delta.dot(normalWorld);
  152. }
  153. }
  154. void btSliderConstraint::testLinLimits(void)
  155. {
  156. m_solveLinLim = false;
  157. m_linPos = m_depth[0];
  158. if(m_lowerLinLimit <= m_upperLinLimit)
  159. {
  160. if(m_depth[0] > m_upperLinLimit)
  161. {
  162. m_depth[0] -= m_upperLinLimit;
  163. m_solveLinLim = true;
  164. }
  165. else if(m_depth[0] < m_lowerLinLimit)
  166. {
  167. m_depth[0] -= m_lowerLinLimit;
  168. m_solveLinLim = true;
  169. }
  170. else
  171. {
  172. m_depth[0] = btScalar(0.);
  173. }
  174. }
  175. else
  176. {
  177. m_depth[0] = btScalar(0.);
  178. }
  179. }
  180. void btSliderConstraint::testAngLimits(void)
  181. {
  182. m_angDepth = btScalar(0.);
  183. m_solveAngLim = false;
  184. if(m_lowerAngLimit <= m_upperAngLimit)
  185. {
  186. const btVector3 axisA0 = m_calculatedTransformA.getBasis().getColumn(1);
  187. const btVector3 axisA1 = m_calculatedTransformA.getBasis().getColumn(2);
  188. const btVector3 axisB0 = m_calculatedTransformB.getBasis().getColumn(1);
  189. // btScalar rot = btAtan2Fast(axisB0.dot(axisA1), axisB0.dot(axisA0));
  190. btScalar rot = btAtan2(axisB0.dot(axisA1), axisB0.dot(axisA0));
  191. rot = btAdjustAngleToLimits(rot, m_lowerAngLimit, m_upperAngLimit);
  192. m_angPos = rot;
  193. if(rot < m_lowerAngLimit)
  194. {
  195. m_angDepth = rot - m_lowerAngLimit;
  196. m_solveAngLim = true;
  197. }
  198. else if(rot > m_upperAngLimit)
  199. {
  200. m_angDepth = rot - m_upperAngLimit;
  201. m_solveAngLim = true;
  202. }
  203. }
  204. }
  205. btVector3 btSliderConstraint::getAncorInA(void)
  206. {
  207. btVector3 ancorInA;
  208. ancorInA = m_realPivotAInW + (m_lowerLinLimit + m_upperLinLimit) * btScalar(0.5) * m_sliderAxis;
  209. ancorInA = m_rbA.getCenterOfMassTransform().inverse() * ancorInA;
  210. return ancorInA;
  211. }
  212. btVector3 btSliderConstraint::getAncorInB(void)
  213. {
  214. btVector3 ancorInB;
  215. ancorInB = m_frameInB.getOrigin();
  216. return ancorInB;
  217. }
  218. void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTransform& transA,const btTransform& transB, const btVector3& linVelA,const btVector3& linVelB, btScalar rbAinvMass,btScalar rbBinvMass )
  219. {
  220. const btTransform& trA = getCalculatedTransformA();
  221. const btTransform& trB = getCalculatedTransformB();
  222. btAssert(!m_useSolveConstraintObsolete);
  223. int i, s = info->rowskip;
  224. btScalar signFact = m_useLinearReferenceFrameA ? btScalar(1.0f) : btScalar(-1.0f);
  225. // difference between frames in WCS
  226. btVector3 ofs = trB.getOrigin() - trA.getOrigin();
  227. // now get weight factors depending on masses
  228. btScalar miA = rbAinvMass;
  229. btScalar miB = rbBinvMass;
  230. bool hasStaticBody = (miA < SIMD_EPSILON) || (miB < SIMD_EPSILON);
  231. btScalar miS = miA + miB;
  232. btScalar factA, factB;
  233. if(miS > btScalar(0.f))
  234. {
  235. factA = miB / miS;
  236. }
  237. else
  238. {
  239. factA = btScalar(0.5f);
  240. }
  241. factB = btScalar(1.0f) - factA;
  242. btVector3 ax1, p, q;
  243. btVector3 ax1A = trA.getBasis().getColumn(0);
  244. btVector3 ax1B = trB.getBasis().getColumn(0);
  245. if(m_useOffsetForConstraintFrame)
  246. {
  247. // get the desired direction of slider axis
  248. // as weighted sum of X-orthos of frameA and frameB in WCS
  249. ax1 = ax1A * factA + ax1B * factB;
  250. ax1.normalize();
  251. // construct two orthos to slider axis
  252. btPlaneSpace1 (ax1, p, q);
  253. }
  254. else
  255. { // old way - use frameA
  256. ax1 = trA.getBasis().getColumn(0);
  257. // get 2 orthos to slider axis (Y, Z)
  258. p = trA.getBasis().getColumn(1);
  259. q = trA.getBasis().getColumn(2);
  260. }
  261. // make rotations around these orthos equal
  262. // the slider axis should be the only unconstrained
  263. // rotational axis, the angular velocity of the two bodies perpendicular to
  264. // the slider axis should be equal. thus the constraint equations are
  265. // p*w1 - p*w2 = 0
  266. // q*w1 - q*w2 = 0
  267. // where p and q are unit vectors normal to the slider axis, and w1 and w2
  268. // are the angular velocity vectors of the two bodies.
  269. info->m_J1angularAxis[0] = p[0];
  270. info->m_J1angularAxis[1] = p[1];
  271. info->m_J1angularAxis[2] = p[2];
  272. info->m_J1angularAxis[s+0] = q[0];
  273. info->m_J1angularAxis[s+1] = q[1];
  274. info->m_J1angularAxis[s+2] = q[2];
  275. info->m_J2angularAxis[0] = -p[0];
  276. info->m_J2angularAxis[1] = -p[1];
  277. info->m_J2angularAxis[2] = -p[2];
  278. info->m_J2angularAxis[s+0] = -q[0];
  279. info->m_J2angularAxis[s+1] = -q[1];
  280. info->m_J2angularAxis[s+2] = -q[2];
  281. // compute the right hand side of the constraint equation. set relative
  282. // body velocities along p and q to bring the slider back into alignment.
  283. // if ax1A,ax1B are the unit length slider axes as computed from bodyA and
  284. // bodyB, we need to rotate both bodies along the axis u = (ax1 x ax2).
  285. // if "theta" is the angle between ax1 and ax2, we need an angular velocity
  286. // along u to cover angle erp*theta in one step :
  287. // |angular_velocity| = angle/time = erp*theta / stepsize
  288. // = (erp*fps) * theta
  289. // angular_velocity = |angular_velocity| * (ax1 x ax2) / |ax1 x ax2|
  290. // = (erp*fps) * theta * (ax1 x ax2) / sin(theta)
  291. // ...as ax1 and ax2 are unit length. if theta is smallish,
  292. // theta ~= sin(theta), so
  293. // angular_velocity = (erp*fps) * (ax1 x ax2)
  294. // ax1 x ax2 is in the plane space of ax1, so we project the angular
  295. // velocity to p and q to find the right hand side.
  296. // btScalar k = info->fps * info->erp * getSoftnessOrthoAng();
  297. btScalar currERP = (m_flags & BT_SLIDER_FLAGS_ERP_ORTANG) ? m_softnessOrthoAng : m_softnessOrthoAng * info->erp;
  298. btScalar k = info->fps * currERP;
  299. btVector3 u = ax1A.cross(ax1B);
  300. info->m_constraintError[0] = k * u.dot(p);
  301. info->m_constraintError[s] = k * u.dot(q);
  302. if(m_flags & BT_SLIDER_FLAGS_CFM_ORTANG)
  303. {
  304. info->cfm[0] = m_cfmOrthoAng;
  305. info->cfm[s] = m_cfmOrthoAng;
  306. }
  307. int nrow = 1; // last filled row
  308. int srow;
  309. btScalar limit_err;
  310. int limit;
  311. // next two rows.
  312. // we want: velA + wA x relA == velB + wB x relB ... but this would
  313. // result in three equations, so we project along two orthos to the slider axis
  314. btTransform bodyA_trans = transA;
  315. btTransform bodyB_trans = transB;
  316. nrow++;
  317. int s2 = nrow * s;
  318. nrow++;
  319. int s3 = nrow * s;
  320. btVector3 tmpA(0,0,0), tmpB(0,0,0), relA(0,0,0), relB(0,0,0), c(0,0,0);
  321. if(m_useOffsetForConstraintFrame)
  322. {
  323. // get vector from bodyB to frameB in WCS
  324. relB = trB.getOrigin() - bodyB_trans.getOrigin();
  325. // get its projection to slider axis
  326. btVector3 projB = ax1 * relB.dot(ax1);
  327. // get vector directed from bodyB to slider axis (and orthogonal to it)
  328. btVector3 orthoB = relB - projB;
  329. // same for bodyA
  330. relA = trA.getOrigin() - bodyA_trans.getOrigin();
  331. btVector3 projA = ax1 * relA.dot(ax1);
  332. btVector3 orthoA = relA - projA;
  333. // get desired offset between frames A and B along slider axis
  334. btScalar sliderOffs = m_linPos - m_depth[0];
  335. // desired vector from projection of center of bodyA to projection of center of bodyB to slider axis
  336. btVector3 totalDist = projA + ax1 * sliderOffs - projB;
  337. // get offset vectors relA and relB
  338. relA = orthoA + totalDist * factA;
  339. relB = orthoB - totalDist * factB;
  340. // now choose average ortho to slider axis
  341. p = orthoB * factA + orthoA * factB;
  342. btScalar len2 = p.length2();
  343. if(len2 > SIMD_EPSILON)
  344. {
  345. p /= btSqrt(len2);
  346. }
  347. else
  348. {
  349. p = trA.getBasis().getColumn(1);
  350. }
  351. // make one more ortho
  352. q = ax1.cross(p);
  353. // fill two rows
  354. tmpA = relA.cross(p);
  355. tmpB = relB.cross(p);
  356. for (i=0; i<3; i++) info->m_J1angularAxis[s2+i] = tmpA[i];
  357. for (i=0; i<3; i++) info->m_J2angularAxis[s2+i] = -tmpB[i];
  358. tmpA = relA.cross(q);
  359. tmpB = relB.cross(q);
  360. if(hasStaticBody && getSolveAngLimit())
  361. { // to make constraint between static and dynamic objects more rigid
  362. // remove wA (or wB) from equation if angular limit is hit
  363. tmpB *= factB;
  364. tmpA *= factA;
  365. }
  366. for (i=0; i<3; i++) info->m_J1angularAxis[s3+i] = tmpA[i];
  367. for (i=0; i<3; i++) info->m_J2angularAxis[s3+i] = -tmpB[i];
  368. for (i=0; i<3; i++) info->m_J1linearAxis[s2+i] = p[i];
  369. for (i=0; i<3; i++) info->m_J1linearAxis[s3+i] = q[i];
  370. for (i=0; i<3; i++) info->m_J2linearAxis[s2+i] = -p[i];
  371. for (i=0; i<3; i++) info->m_J2linearAxis[s3+i] = -q[i];
  372. }
  373. else
  374. { // old way - maybe incorrect if bodies are not on the slider axis
  375. // see discussion "Bug in slider constraint" http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?f=9&t=4024&start=0
  376. c = bodyB_trans.getOrigin() - bodyA_trans.getOrigin();
  377. btVector3 tmp = c.cross(p);
  378. for (i=0; i<3; i++) info->m_J1angularAxis[s2+i] = factA*tmp[i];
  379. for (i=0; i<3; i++) info->m_J2angularAxis[s2+i] = factB*tmp[i];
  380. tmp = c.cross(q);
  381. for (i=0; i<3; i++) info->m_J1angularAxis[s3+i] = factA*tmp[i];
  382. for (i=0; i<3; i++) info->m_J2angularAxis[s3+i] = factB*tmp[i];
  383. for (i=0; i<3; i++) info->m_J1linearAxis[s2+i] = p[i];
  384. for (i=0; i<3; i++) info->m_J1linearAxis[s3+i] = q[i];
  385. for (i=0; i<3; i++) info->m_J2linearAxis[s2+i] = -p[i];
  386. for (i=0; i<3; i++) info->m_J2linearAxis[s3+i] = -q[i];
  387. }
  388. // compute two elements of right hand side
  389. // k = info->fps * info->erp * getSoftnessOrthoLin();
  390. currERP = (m_flags & BT_SLIDER_FLAGS_ERP_ORTLIN) ? m_softnessOrthoLin : m_softnessOrthoLin * info->erp;
  391. k = info->fps * currERP;
  392. btScalar rhs = k * p.dot(ofs);
  393. info->m_constraintError[s2] = rhs;
  394. rhs = k * q.dot(ofs);
  395. info->m_constraintError[s3] = rhs;
  396. if(m_flags & BT_SLIDER_FLAGS_CFM_ORTLIN)
  397. {
  398. info->cfm[s2] = m_cfmOrthoLin;
  399. info->cfm[s3] = m_cfmOrthoLin;
  400. }
  401. // check linear limits
  402. limit_err = btScalar(0.0);
  403. limit = 0;
  404. if(getSolveLinLimit())
  405. {
  406. limit_err = getLinDepth() * signFact;
  407. limit = (limit_err > btScalar(0.0)) ? 2 : 1;
  408. }
  409. bool powered = getPoweredLinMotor();
  410. // if the slider has joint limits or motor, add in the extra row
  411. if (limit || powered)
  412. {
  413. nrow++;
  414. srow = nrow * info->rowskip;
  415. info->m_J1linearAxis[srow+0] = ax1[0];
  416. info->m_J1linearAxis[srow+1] = ax1[1];
  417. info->m_J1linearAxis[srow+2] = ax1[2];
  418. info->m_J2linearAxis[srow+0] = -ax1[0];
  419. info->m_J2linearAxis[srow+1] = -ax1[1];
  420. info->m_J2linearAxis[srow+2] = -ax1[2];
  421. // linear torque decoupling step:
  422. //
  423. // we have to be careful that the linear constraint forces (+/- ax1) applied to the two bodies
  424. // do not create a torque couple. in other words, the points that the
  425. // constraint force is applied at must lie along the same ax1 axis.
  426. // a torque couple will result in limited slider-jointed free
  427. // bodies from gaining angular momentum.
  428. if(m_useOffsetForConstraintFrame)
  429. {
  430. // this is needed only when bodyA and bodyB are both dynamic.
  431. if(!hasStaticBody)
  432. {
  433. tmpA = relA.cross(ax1);
  434. tmpB = relB.cross(ax1);
  435. info->m_J1angularAxis[srow+0] = tmpA[0];
  436. info->m_J1angularAxis[srow+1] = tmpA[1];
  437. info->m_J1angularAxis[srow+2] = tmpA[2];
  438. info->m_J2angularAxis[srow+0] = -tmpB[0];
  439. info->m_J2angularAxis[srow+1] = -tmpB[1];
  440. info->m_J2angularAxis[srow+2] = -tmpB[2];
  441. }
  442. }
  443. else
  444. { // The old way. May be incorrect if bodies are not on the slider axis
  445. btVector3 ltd; // Linear Torque Decoupling vector (a torque)
  446. ltd = c.cross(ax1);
  447. info->m_J1angularAxis[srow+0] = factA*ltd[0];
  448. info->m_J1angularAxis[srow+1] = factA*ltd[1];
  449. info->m_J1angularAxis[srow+2] = factA*ltd[2];
  450. info->m_J2angularAxis[srow+0] = factB*ltd[0];
  451. info->m_J2angularAxis[srow+1] = factB*ltd[1];
  452. info->m_J2angularAxis[srow+2] = factB*ltd[2];
  453. }
  454. // right-hand part
  455. btScalar lostop = getLowerLinLimit();
  456. btScalar histop = getUpperLinLimit();
  457. if(limit && (lostop == histop))
  458. { // the joint motor is ineffective
  459. powered = false;
  460. }
  461. info->m_constraintError[srow] = 0.;
  462. info->m_lowerLimit[srow] = 0.;
  463. info->m_upperLimit[srow] = 0.;
  464. currERP = (m_flags & BT_SLIDER_FLAGS_ERP_LIMLIN) ? m_softnessLimLin : info->erp;
  465. if(powered)
  466. {
  467. if(m_flags & BT_SLIDER_FLAGS_CFM_DIRLIN)
  468. {
  469. info->cfm[srow] = m_cfmDirLin;
  470. }
  471. btScalar tag_vel = getTargetLinMotorVelocity();
  472. btScalar mot_fact = getMotorFactor(m_linPos, m_lowerLinLimit, m_upperLinLimit, tag_vel, info->fps * currERP);
  473. info->m_constraintError[srow] -= signFact * mot_fact * getTargetLinMotorVelocity();
  474. info->m_lowerLimit[srow] += -getMaxLinMotorForce() / info->fps;
  475. info->m_upperLimit[srow] += getMaxLinMotorForce() / info->fps;
  476. }
  477. if(limit)
  478. {
  479. k = info->fps * currERP;
  480. info->m_constraintError[srow] += k * limit_err;
  481. if(m_flags & BT_SLIDER_FLAGS_CFM_LIMLIN)
  482. {
  483. info->cfm[srow] = m_cfmLimLin;
  484. }
  485. if(lostop == histop)
  486. { // limited low and high simultaneously
  487. info->m_lowerLimit[srow] = -SIMD_INFINITY;
  488. info->m_upperLimit[srow] = SIMD_INFINITY;
  489. }
  490. else if(limit == 1)
  491. { // low limit
  492. info->m_lowerLimit[srow] = -SIMD_INFINITY;
  493. info->m_upperLimit[srow] = 0;
  494. }
  495. else
  496. { // high limit
  497. info->m_lowerLimit[srow] = 0;
  498. info->m_upperLimit[srow] = SIMD_INFINITY;
  499. }
  500. // bounce (we'll use slider parameter abs(1.0 - m_dampingLimLin) for that)
  501. btScalar bounce = btFabs(btScalar(1.0) - getDampingLimLin());
  502. if(bounce > btScalar(0.0))
  503. {
  504. btScalar vel = linVelA.dot(ax1);
  505. vel -= linVelB.dot(ax1);
  506. vel *= signFact;
  507. // only apply bounce if the velocity is incoming, and if the
  508. // resulting c[] exceeds what we already have.
  509. if(limit == 1)
  510. { // low limit
  511. if(vel < 0)
  512. {
  513. btScalar newc = -bounce * vel;
  514. if (newc > info->m_constraintError[srow])
  515. {
  516. info->m_constraintError[srow] = newc;
  517. }
  518. }
  519. }
  520. else
  521. { // high limit - all those computations are reversed
  522. if(vel > 0)
  523. {
  524. btScalar newc = -bounce * vel;
  525. if(newc < info->m_constraintError[srow])
  526. {
  527. info->m_constraintError[srow] = newc;
  528. }
  529. }
  530. }
  531. }
  532. info->m_constraintError[srow] *= getSoftnessLimLin();
  533. } // if(limit)
  534. } // if linear limit
  535. // check angular limits
  536. limit_err = btScalar(0.0);
  537. limit = 0;
  538. if(getSolveAngLimit())
  539. {
  540. limit_err = getAngDepth();
  541. limit = (limit_err > btScalar(0.0)) ? 1 : 2;
  542. }
  543. // if the slider has joint limits, add in the extra row
  544. powered = getPoweredAngMotor();
  545. if(limit || powered)
  546. {
  547. nrow++;
  548. srow = nrow * info->rowskip;
  549. info->m_J1angularAxis[srow+0] = ax1[0];
  550. info->m_J1angularAxis[srow+1] = ax1[1];
  551. info->m_J1angularAxis[srow+2] = ax1[2];
  552. info->m_J2angularAxis[srow+0] = -ax1[0];
  553. info->m_J2angularAxis[srow+1] = -ax1[1];
  554. info->m_J2angularAxis[srow+2] = -ax1[2];
  555. btScalar lostop = getLowerAngLimit();
  556. btScalar histop = getUpperAngLimit();
  557. if(limit && (lostop == histop))
  558. { // the joint motor is ineffective
  559. powered = false;
  560. }
  561. currERP = (m_flags & BT_SLIDER_FLAGS_ERP_LIMANG) ? m_softnessLimAng : info->erp;
  562. if(powered)
  563. {
  564. if(m_flags & BT_SLIDER_FLAGS_CFM_DIRANG)
  565. {
  566. info->cfm[srow] = m_cfmDirAng;
  567. }
  568. btScalar mot_fact = getMotorFactor(m_angPos, m_lowerAngLimit, m_upperAngLimit, getTargetAngMotorVelocity(), info->fps * currERP);
  569. info->m_constraintError[srow] = mot_fact * getTargetAngMotorVelocity();
  570. info->m_lowerLimit[srow] = -getMaxAngMotorForce() / info->fps;
  571. info->m_upperLimit[srow] = getMaxAngMotorForce() / info->fps;
  572. }
  573. if(limit)
  574. {
  575. k = info->fps * currERP;
  576. info->m_constraintError[srow] += k * limit_err;
  577. if(m_flags & BT_SLIDER_FLAGS_CFM_LIMANG)
  578. {
  579. info->cfm[srow] = m_cfmLimAng;
  580. }
  581. if(lostop == histop)
  582. {
  583. // limited low and high simultaneously
  584. info->m_lowerLimit[srow] = -SIMD_INFINITY;
  585. info->m_upperLimit[srow] = SIMD_INFINITY;
  586. }
  587. else if(limit == 1)
  588. { // low limit
  589. info->m_lowerLimit[srow] = 0;
  590. info->m_upperLimit[srow] = SIMD_INFINITY;
  591. }
  592. else
  593. { // high limit
  594. info->m_lowerLimit[srow] = -SIMD_INFINITY;
  595. info->m_upperLimit[srow] = 0;
  596. }
  597. // bounce (we'll use slider parameter abs(1.0 - m_dampingLimAng) for that)
  598. btScalar bounce = btFabs(btScalar(1.0) - getDampingLimAng());
  599. if(bounce > btScalar(0.0))
  600. {
  601. btScalar vel = m_rbA.getAngularVelocity().dot(ax1);
  602. vel -= m_rbB.getAngularVelocity().dot(ax1);
  603. // only apply bounce if the velocity is incoming, and if the
  604. // resulting c[] exceeds what we already have.
  605. if(limit == 1)
  606. { // low limit
  607. if(vel < 0)
  608. {
  609. btScalar newc = -bounce * vel;
  610. if(newc > info->m_constraintError[srow])
  611. {
  612. info->m_constraintError[srow] = newc;
  613. }
  614. }
  615. }
  616. else
  617. { // high limit - all those computations are reversed
  618. if(vel > 0)
  619. {
  620. btScalar newc = -bounce * vel;
  621. if(newc < info->m_constraintError[srow])
  622. {
  623. info->m_constraintError[srow] = newc;
  624. }
  625. }
  626. }
  627. }
  628. info->m_constraintError[srow] *= getSoftnessLimAng();
  629. } // if(limit)
  630. } // if angular limit or powered
  631. }
  632. ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
  633. ///If no axis is provided, it uses the default axis for this constraint.
  634. void btSliderConstraint::setParam(int num, btScalar value, int axis)
  635. {
  636. switch(num)
  637. {
  638. case BT_CONSTRAINT_STOP_ERP :
  639. if(axis < 1)
  640. {
  641. m_softnessLimLin = value;
  642. m_flags |= BT_SLIDER_FLAGS_ERP_LIMLIN;
  643. }
  644. else if(axis < 3)
  645. {
  646. m_softnessOrthoLin = value;
  647. m_flags |= BT_SLIDER_FLAGS_ERP_ORTLIN;
  648. }
  649. else if(axis == 3)
  650. {
  651. m_softnessLimAng = value;
  652. m_flags |= BT_SLIDER_FLAGS_ERP_LIMANG;
  653. }
  654. else if(axis < 6)
  655. {
  656. m_softnessOrthoAng = value;
  657. m_flags |= BT_SLIDER_FLAGS_ERP_ORTANG;
  658. }
  659. else
  660. {
  661. btAssertConstrParams(0);
  662. }
  663. break;
  664. case BT_CONSTRAINT_CFM :
  665. if(axis < 1)
  666. {
  667. m_cfmDirLin = value;
  668. m_flags |= BT_SLIDER_FLAGS_CFM_DIRLIN;
  669. }
  670. else if(axis == 3)
  671. {
  672. m_cfmDirAng = value;
  673. m_flags |= BT_SLIDER_FLAGS_CFM_DIRANG;
  674. }
  675. else
  676. {
  677. btAssertConstrParams(0);
  678. }
  679. break;
  680. case BT_CONSTRAINT_STOP_CFM :
  681. if(axis < 1)
  682. {
  683. m_cfmLimLin = value;
  684. m_flags |= BT_SLIDER_FLAGS_CFM_LIMLIN;
  685. }
  686. else if(axis < 3)
  687. {
  688. m_cfmOrthoLin = value;
  689. m_flags |= BT_SLIDER_FLAGS_CFM_ORTLIN;
  690. }
  691. else if(axis == 3)
  692. {
  693. m_cfmLimAng = value;
  694. m_flags |= BT_SLIDER_FLAGS_CFM_LIMANG;
  695. }
  696. else if(axis < 6)
  697. {
  698. m_cfmOrthoAng = value;
  699. m_flags |= BT_SLIDER_FLAGS_CFM_ORTANG;
  700. }
  701. else
  702. {
  703. btAssertConstrParams(0);
  704. }
  705. break;
  706. }
  707. }
  708. ///return the local value of parameter
  709. btScalar btSliderConstraint::getParam(int num, int axis) const
  710. {
  711. btScalar retVal(SIMD_INFINITY);
  712. switch(num)
  713. {
  714. case BT_CONSTRAINT_STOP_ERP :
  715. if(axis < 1)
  716. {
  717. btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_LIMLIN);
  718. retVal = m_softnessLimLin;
  719. }
  720. else if(axis < 3)
  721. {
  722. btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_ORTLIN);
  723. retVal = m_softnessOrthoLin;
  724. }
  725. else if(axis == 3)
  726. {
  727. btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_LIMANG);
  728. retVal = m_softnessLimAng;
  729. }
  730. else if(axis < 6)
  731. {
  732. btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_ORTANG);
  733. retVal = m_softnessOrthoAng;
  734. }
  735. else
  736. {
  737. btAssertConstrParams(0);
  738. }
  739. break;
  740. case BT_CONSTRAINT_CFM :
  741. if(axis < 1)
  742. {
  743. btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_DIRLIN);
  744. retVal = m_cfmDirLin;
  745. }
  746. else if(axis == 3)
  747. {
  748. btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_DIRANG);
  749. retVal = m_cfmDirAng;
  750. }
  751. else
  752. {
  753. btAssertConstrParams(0);
  754. }
  755. break;
  756. case BT_CONSTRAINT_STOP_CFM :
  757. if(axis < 1)
  758. {
  759. btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_LIMLIN);
  760. retVal = m_cfmLimLin;
  761. }
  762. else if(axis < 3)
  763. {
  764. btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_ORTLIN);
  765. retVal = m_cfmOrthoLin;
  766. }
  767. else if(axis == 3)
  768. {
  769. btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_LIMANG);
  770. retVal = m_cfmLimAng;
  771. }
  772. else if(axis < 6)
  773. {
  774. btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_ORTANG);
  775. retVal = m_cfmOrthoAng;
  776. }
  777. else
  778. {
  779. btAssertConstrParams(0);
  780. }
  781. break;
  782. }
  783. return retVal;
  784. }