btSliderConstraint.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864
  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 (rponom@gmail.com)
  15. April 04, 2008
  16. */
  17. #include "btSliderConstraint.h"
  18. #include "bullet/BulletDynamics/Dynamics/btRigidBody.h"
  19. #include "bullet/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. int powered;
  312. // next two rows.
  313. // we want: velA + wA x relA == velB + wB x relB ... but this would
  314. // result in three equations, so we project along two orthos to the slider axis
  315. btTransform bodyA_trans = transA;
  316. btTransform bodyB_trans = transB;
  317. nrow++;
  318. int s2 = nrow * s;
  319. nrow++;
  320. int s3 = nrow * s;
  321. btVector3 tmpA(0,0,0), tmpB(0,0,0), relA(0,0,0), relB(0,0,0), c(0,0,0);
  322. if(m_useOffsetForConstraintFrame)
  323. {
  324. // get vector from bodyB to frameB in WCS
  325. relB = trB.getOrigin() - bodyB_trans.getOrigin();
  326. // get its projection to slider axis
  327. btVector3 projB = ax1 * relB.dot(ax1);
  328. // get vector directed from bodyB to slider axis (and orthogonal to it)
  329. btVector3 orthoB = relB - projB;
  330. // same for bodyA
  331. relA = trA.getOrigin() - bodyA_trans.getOrigin();
  332. btVector3 projA = ax1 * relA.dot(ax1);
  333. btVector3 orthoA = relA - projA;
  334. // get desired offset between frames A and B along slider axis
  335. btScalar sliderOffs = m_linPos - m_depth[0];
  336. // desired vector from projection of center of bodyA to projection of center of bodyB to slider axis
  337. btVector3 totalDist = projA + ax1 * sliderOffs - projB;
  338. // get offset vectors relA and relB
  339. relA = orthoA + totalDist * factA;
  340. relB = orthoB - totalDist * factB;
  341. // now choose average ortho to slider axis
  342. p = orthoB * factA + orthoA * factB;
  343. btScalar len2 = p.length2();
  344. if(len2 > SIMD_EPSILON)
  345. {
  346. p /= btSqrt(len2);
  347. }
  348. else
  349. {
  350. p = trA.getBasis().getColumn(1);
  351. }
  352. // make one more ortho
  353. q = ax1.cross(p);
  354. // fill two rows
  355. tmpA = relA.cross(p);
  356. tmpB = relB.cross(p);
  357. for (i=0; i<3; i++) info->m_J1angularAxis[s2+i] = tmpA[i];
  358. for (i=0; i<3; i++) info->m_J2angularAxis[s2+i] = -tmpB[i];
  359. tmpA = relA.cross(q);
  360. tmpB = relB.cross(q);
  361. if(hasStaticBody && getSolveAngLimit())
  362. { // to make constraint between static and dynamic objects more rigid
  363. // remove wA (or wB) from equation if angular limit is hit
  364. tmpB *= factB;
  365. tmpA *= factA;
  366. }
  367. for (i=0; i<3; i++) info->m_J1angularAxis[s3+i] = tmpA[i];
  368. for (i=0; i<3; i++) info->m_J2angularAxis[s3+i] = -tmpB[i];
  369. for (i=0; i<3; i++) info->m_J1linearAxis[s2+i] = p[i];
  370. for (i=0; i<3; i++) info->m_J1linearAxis[s3+i] = q[i];
  371. for (i=0; i<3; i++) info->m_J2linearAxis[s2+i] = -p[i];
  372. for (i=0; i<3; i++) info->m_J2linearAxis[s3+i] = -q[i];
  373. }
  374. else
  375. { // old way - maybe incorrect if bodies are not on the slider axis
  376. // see discussion "Bug in slider constraint" http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?f=9&t=4024&start=0
  377. c = bodyB_trans.getOrigin() - bodyA_trans.getOrigin();
  378. btVector3 tmp = c.cross(p);
  379. for (i=0; i<3; i++) info->m_J1angularAxis[s2+i] = factA*tmp[i];
  380. for (i=0; i<3; i++) info->m_J2angularAxis[s2+i] = factB*tmp[i];
  381. tmp = c.cross(q);
  382. for (i=0; i<3; i++) info->m_J1angularAxis[s3+i] = factA*tmp[i];
  383. for (i=0; i<3; i++) info->m_J2angularAxis[s3+i] = factB*tmp[i];
  384. for (i=0; i<3; i++) info->m_J1linearAxis[s2+i] = p[i];
  385. for (i=0; i<3; i++) info->m_J1linearAxis[s3+i] = q[i];
  386. for (i=0; i<3; i++) info->m_J2linearAxis[s2+i] = -p[i];
  387. for (i=0; i<3; i++) info->m_J2linearAxis[s3+i] = -q[i];
  388. }
  389. // compute two elements of right hand side
  390. // k = info->fps * info->erp * getSoftnessOrthoLin();
  391. currERP = (m_flags & BT_SLIDER_FLAGS_ERP_ORTLIN) ? m_softnessOrthoLin : m_softnessOrthoLin * info->erp;
  392. k = info->fps * currERP;
  393. btScalar rhs = k * p.dot(ofs);
  394. info->m_constraintError[s2] = rhs;
  395. rhs = k * q.dot(ofs);
  396. info->m_constraintError[s3] = rhs;
  397. if(m_flags & BT_SLIDER_FLAGS_CFM_ORTLIN)
  398. {
  399. info->cfm[s2] = m_cfmOrthoLin;
  400. info->cfm[s3] = m_cfmOrthoLin;
  401. }
  402. // check linear limits
  403. limit_err = btScalar(0.0);
  404. limit = 0;
  405. if(getSolveLinLimit())
  406. {
  407. limit_err = getLinDepth() * signFact;
  408. limit = (limit_err > btScalar(0.0)) ? 2 : 1;
  409. }
  410. powered = 0;
  411. if(getPoweredLinMotor())
  412. {
  413. powered = 1;
  414. }
  415. // if the slider has joint limits or motor, add in the extra row
  416. if (limit || powered)
  417. {
  418. nrow++;
  419. srow = nrow * info->rowskip;
  420. info->m_J1linearAxis[srow+0] = ax1[0];
  421. info->m_J1linearAxis[srow+1] = ax1[1];
  422. info->m_J1linearAxis[srow+2] = ax1[2];
  423. info->m_J2linearAxis[srow+0] = -ax1[0];
  424. info->m_J2linearAxis[srow+1] = -ax1[1];
  425. info->m_J2linearAxis[srow+2] = -ax1[2];
  426. // linear torque decoupling step:
  427. //
  428. // we have to be careful that the linear constraint forces (+/- ax1) applied to the two bodies
  429. // do not create a torque couple. in other words, the points that the
  430. // constraint force is applied at must lie along the same ax1 axis.
  431. // a torque couple will result in limited slider-jointed free
  432. // bodies from gaining angular momentum.
  433. if(m_useOffsetForConstraintFrame)
  434. {
  435. // this is needed only when bodyA and bodyB are both dynamic.
  436. if(!hasStaticBody)
  437. {
  438. tmpA = relA.cross(ax1);
  439. tmpB = relB.cross(ax1);
  440. info->m_J1angularAxis[srow+0] = tmpA[0];
  441. info->m_J1angularAxis[srow+1] = tmpA[1];
  442. info->m_J1angularAxis[srow+2] = tmpA[2];
  443. info->m_J2angularAxis[srow+0] = -tmpB[0];
  444. info->m_J2angularAxis[srow+1] = -tmpB[1];
  445. info->m_J2angularAxis[srow+2] = -tmpB[2];
  446. }
  447. }
  448. else
  449. { // The old way. May be incorrect if bodies are not on the slider axis
  450. btVector3 ltd; // Linear Torque Decoupling vector (a torque)
  451. ltd = c.cross(ax1);
  452. info->m_J1angularAxis[srow+0] = factA*ltd[0];
  453. info->m_J1angularAxis[srow+1] = factA*ltd[1];
  454. info->m_J1angularAxis[srow+2] = factA*ltd[2];
  455. info->m_J2angularAxis[srow+0] = factB*ltd[0];
  456. info->m_J2angularAxis[srow+1] = factB*ltd[1];
  457. info->m_J2angularAxis[srow+2] = factB*ltd[2];
  458. }
  459. // right-hand part
  460. btScalar lostop = getLowerLinLimit();
  461. btScalar histop = getUpperLinLimit();
  462. if(limit && (lostop == histop))
  463. { // the joint motor is ineffective
  464. powered = 0;
  465. }
  466. info->m_constraintError[srow] = 0.;
  467. info->m_lowerLimit[srow] = 0.;
  468. info->m_upperLimit[srow] = 0.;
  469. currERP = (m_flags & BT_SLIDER_FLAGS_ERP_LIMLIN) ? m_softnessLimLin : info->erp;
  470. if(powered)
  471. {
  472. if(m_flags & BT_SLIDER_FLAGS_CFM_DIRLIN)
  473. {
  474. info->cfm[srow] = m_cfmDirLin;
  475. }
  476. btScalar tag_vel = getTargetLinMotorVelocity();
  477. btScalar mot_fact = getMotorFactor(m_linPos, m_lowerLinLimit, m_upperLinLimit, tag_vel, info->fps * currERP);
  478. info->m_constraintError[srow] -= signFact * mot_fact * getTargetLinMotorVelocity();
  479. info->m_lowerLimit[srow] += -getMaxLinMotorForce() * info->fps;
  480. info->m_upperLimit[srow] += getMaxLinMotorForce() * info->fps;
  481. }
  482. if(limit)
  483. {
  484. k = info->fps * currERP;
  485. info->m_constraintError[srow] += k * limit_err;
  486. if(m_flags & BT_SLIDER_FLAGS_CFM_LIMLIN)
  487. {
  488. info->cfm[srow] = m_cfmLimLin;
  489. }
  490. if(lostop == histop)
  491. { // limited low and high simultaneously
  492. info->m_lowerLimit[srow] = -SIMD_INFINITY;
  493. info->m_upperLimit[srow] = SIMD_INFINITY;
  494. }
  495. else if(limit == 1)
  496. { // low limit
  497. info->m_lowerLimit[srow] = -SIMD_INFINITY;
  498. info->m_upperLimit[srow] = 0;
  499. }
  500. else
  501. { // high limit
  502. info->m_lowerLimit[srow] = 0;
  503. info->m_upperLimit[srow] = SIMD_INFINITY;
  504. }
  505. // bounce (we'll use slider parameter abs(1.0 - m_dampingLimLin) for that)
  506. btScalar bounce = btFabs(btScalar(1.0) - getDampingLimLin());
  507. if(bounce > btScalar(0.0))
  508. {
  509. btScalar vel = linVelA.dot(ax1);
  510. vel -= linVelB.dot(ax1);
  511. vel *= signFact;
  512. // only apply bounce if the velocity is incoming, and if the
  513. // resulting c[] exceeds what we already have.
  514. if(limit == 1)
  515. { // low limit
  516. if(vel < 0)
  517. {
  518. btScalar newc = -bounce * vel;
  519. if (newc > info->m_constraintError[srow])
  520. {
  521. info->m_constraintError[srow] = newc;
  522. }
  523. }
  524. }
  525. else
  526. { // high limit - all those computations are reversed
  527. if(vel > 0)
  528. {
  529. btScalar newc = -bounce * vel;
  530. if(newc < info->m_constraintError[srow])
  531. {
  532. info->m_constraintError[srow] = newc;
  533. }
  534. }
  535. }
  536. }
  537. info->m_constraintError[srow] *= getSoftnessLimLin();
  538. } // if(limit)
  539. } // if linear limit
  540. // check angular limits
  541. limit_err = btScalar(0.0);
  542. limit = 0;
  543. if(getSolveAngLimit())
  544. {
  545. limit_err = getAngDepth();
  546. limit = (limit_err > btScalar(0.0)) ? 1 : 2;
  547. }
  548. // if the slider has joint limits, add in the extra row
  549. powered = 0;
  550. if(getPoweredAngMotor())
  551. {
  552. powered = 1;
  553. }
  554. if(limit || powered)
  555. {
  556. nrow++;
  557. srow = nrow * info->rowskip;
  558. info->m_J1angularAxis[srow+0] = ax1[0];
  559. info->m_J1angularAxis[srow+1] = ax1[1];
  560. info->m_J1angularAxis[srow+2] = ax1[2];
  561. info->m_J2angularAxis[srow+0] = -ax1[0];
  562. info->m_J2angularAxis[srow+1] = -ax1[1];
  563. info->m_J2angularAxis[srow+2] = -ax1[2];
  564. btScalar lostop = getLowerAngLimit();
  565. btScalar histop = getUpperAngLimit();
  566. if(limit && (lostop == histop))
  567. { // the joint motor is ineffective
  568. powered = 0;
  569. }
  570. currERP = (m_flags & BT_SLIDER_FLAGS_ERP_LIMANG) ? m_softnessLimAng : info->erp;
  571. if(powered)
  572. {
  573. if(m_flags & BT_SLIDER_FLAGS_CFM_DIRANG)
  574. {
  575. info->cfm[srow] = m_cfmDirAng;
  576. }
  577. btScalar mot_fact = getMotorFactor(m_angPos, m_lowerAngLimit, m_upperAngLimit, getTargetAngMotorVelocity(), info->fps * currERP);
  578. info->m_constraintError[srow] = mot_fact * getTargetAngMotorVelocity();
  579. info->m_lowerLimit[srow] = -getMaxAngMotorForce() * info->fps;
  580. info->m_upperLimit[srow] = getMaxAngMotorForce() * info->fps;
  581. }
  582. if(limit)
  583. {
  584. k = info->fps * currERP;
  585. info->m_constraintError[srow] += k * limit_err;
  586. if(m_flags & BT_SLIDER_FLAGS_CFM_LIMANG)
  587. {
  588. info->cfm[srow] = m_cfmLimAng;
  589. }
  590. if(lostop == histop)
  591. {
  592. // limited low and high simultaneously
  593. info->m_lowerLimit[srow] = -SIMD_INFINITY;
  594. info->m_upperLimit[srow] = SIMD_INFINITY;
  595. }
  596. else if(limit == 1)
  597. { // low limit
  598. info->m_lowerLimit[srow] = 0;
  599. info->m_upperLimit[srow] = SIMD_INFINITY;
  600. }
  601. else
  602. { // high limit
  603. info->m_lowerLimit[srow] = -SIMD_INFINITY;
  604. info->m_upperLimit[srow] = 0;
  605. }
  606. // bounce (we'll use slider parameter abs(1.0 - m_dampingLimAng) for that)
  607. btScalar bounce = btFabs(btScalar(1.0) - getDampingLimAng());
  608. if(bounce > btScalar(0.0))
  609. {
  610. btScalar vel = m_rbA.getAngularVelocity().dot(ax1);
  611. vel -= m_rbB.getAngularVelocity().dot(ax1);
  612. // only apply bounce if the velocity is incoming, and if the
  613. // resulting c[] exceeds what we already have.
  614. if(limit == 1)
  615. { // low limit
  616. if(vel < 0)
  617. {
  618. btScalar newc = -bounce * vel;
  619. if(newc > info->m_constraintError[srow])
  620. {
  621. info->m_constraintError[srow] = newc;
  622. }
  623. }
  624. }
  625. else
  626. { // high limit - all those computations are reversed
  627. if(vel > 0)
  628. {
  629. btScalar newc = -bounce * vel;
  630. if(newc < info->m_constraintError[srow])
  631. {
  632. info->m_constraintError[srow] = newc;
  633. }
  634. }
  635. }
  636. }
  637. info->m_constraintError[srow] *= getSoftnessLimAng();
  638. } // if(limit)
  639. } // if angular limit or powered
  640. }
  641. ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
  642. ///If no axis is provided, it uses the default axis for this constraint.
  643. void btSliderConstraint::setParam(int num, btScalar value, int axis)
  644. {
  645. switch(num)
  646. {
  647. case BT_CONSTRAINT_STOP_ERP :
  648. if(axis < 1)
  649. {
  650. m_softnessLimLin = value;
  651. m_flags |= BT_SLIDER_FLAGS_ERP_LIMLIN;
  652. }
  653. else if(axis < 3)
  654. {
  655. m_softnessOrthoLin = value;
  656. m_flags |= BT_SLIDER_FLAGS_ERP_ORTLIN;
  657. }
  658. else if(axis == 3)
  659. {
  660. m_softnessLimAng = value;
  661. m_flags |= BT_SLIDER_FLAGS_ERP_LIMANG;
  662. }
  663. else if(axis < 6)
  664. {
  665. m_softnessOrthoAng = value;
  666. m_flags |= BT_SLIDER_FLAGS_ERP_ORTANG;
  667. }
  668. else
  669. {
  670. btAssertConstrParams(0);
  671. }
  672. break;
  673. case BT_CONSTRAINT_CFM :
  674. if(axis < 1)
  675. {
  676. m_cfmDirLin = value;
  677. m_flags |= BT_SLIDER_FLAGS_CFM_DIRLIN;
  678. }
  679. else if(axis == 3)
  680. {
  681. m_cfmDirAng = value;
  682. m_flags |= BT_SLIDER_FLAGS_CFM_DIRANG;
  683. }
  684. else
  685. {
  686. btAssertConstrParams(0);
  687. }
  688. break;
  689. case BT_CONSTRAINT_STOP_CFM :
  690. if(axis < 1)
  691. {
  692. m_cfmLimLin = value;
  693. m_flags |= BT_SLIDER_FLAGS_CFM_LIMLIN;
  694. }
  695. else if(axis < 3)
  696. {
  697. m_cfmOrthoLin = value;
  698. m_flags |= BT_SLIDER_FLAGS_CFM_ORTLIN;
  699. }
  700. else if(axis == 3)
  701. {
  702. m_cfmLimAng = value;
  703. m_flags |= BT_SLIDER_FLAGS_CFM_LIMANG;
  704. }
  705. else if(axis < 6)
  706. {
  707. m_cfmOrthoAng = value;
  708. m_flags |= BT_SLIDER_FLAGS_CFM_ORTANG;
  709. }
  710. else
  711. {
  712. btAssertConstrParams(0);
  713. }
  714. break;
  715. }
  716. }
  717. ///return the local value of parameter
  718. btScalar btSliderConstraint::getParam(int num, int axis) const
  719. {
  720. btScalar retVal(SIMD_INFINITY);
  721. switch(num)
  722. {
  723. case BT_CONSTRAINT_STOP_ERP :
  724. if(axis < 1)
  725. {
  726. btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_LIMLIN);
  727. retVal = m_softnessLimLin;
  728. }
  729. else if(axis < 3)
  730. {
  731. btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_ORTLIN);
  732. retVal = m_softnessOrthoLin;
  733. }
  734. else if(axis == 3)
  735. {
  736. btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_LIMANG);
  737. retVal = m_softnessLimAng;
  738. }
  739. else if(axis < 6)
  740. {
  741. btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_ORTANG);
  742. retVal = m_softnessOrthoAng;
  743. }
  744. else
  745. {
  746. btAssertConstrParams(0);
  747. }
  748. break;
  749. case BT_CONSTRAINT_CFM :
  750. if(axis < 1)
  751. {
  752. btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_DIRLIN);
  753. retVal = m_cfmDirLin;
  754. }
  755. else if(axis == 3)
  756. {
  757. btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_DIRANG);
  758. retVal = m_cfmDirAng;
  759. }
  760. else
  761. {
  762. btAssertConstrParams(0);
  763. }
  764. break;
  765. case BT_CONSTRAINT_STOP_CFM :
  766. if(axis < 1)
  767. {
  768. btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_LIMLIN);
  769. retVal = m_cfmLimLin;
  770. }
  771. else if(axis < 3)
  772. {
  773. btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_ORTLIN);
  774. retVal = m_cfmOrthoLin;
  775. }
  776. else if(axis == 3)
  777. {
  778. btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_LIMANG);
  779. retVal = m_cfmLimAng;
  780. }
  781. else if(axis < 6)
  782. {
  783. btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_ORTANG);
  784. retVal = m_cfmOrthoAng;
  785. }
  786. else
  787. {
  788. btAssertConstrParams(0);
  789. }
  790. break;
  791. }
  792. return retVal;
  793. }