btHingeConstraint.cpp 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083
  1. /*
  2. Bullet Continuous Collision Detection and Physics Library
  3. Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
  4. This software is provided 'as-is', without any express or implied warranty.
  5. In no event will the authors be held liable for any damages arising from the use of this software.
  6. Permission is granted to anyone to use this software for any purpose,
  7. including commercial applications, and to alter it and redistribute it freely,
  8. subject to the following restrictions:
  9. 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
  10. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
  11. 3. This notice may not be removed or altered from any source distribution.
  12. */
  13. #include "btHingeConstraint.h"
  14. #include "BulletDynamics/Dynamics/btRigidBody.h"
  15. #include "LinearMath/btTransformUtil.h"
  16. #include "LinearMath/btMinMax.h"
  17. #include <new>
  18. #include "btSolverBody.h"
  19. //#define HINGE_USE_OBSOLETE_SOLVER false
  20. #define HINGE_USE_OBSOLETE_SOLVER false
  21. #define HINGE_USE_FRAME_OFFSET true
  22. #ifndef __SPU__
  23. btHingeConstraint::btHingeConstraint(btRigidBody& rbA, btRigidBody& rbB, const btVector3& pivotInA, const btVector3& pivotInB,
  24. const btVector3& axisInA, const btVector3& axisInB, bool useReferenceFrameA)
  25. : btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA, rbB),
  26. #ifdef _BT_USE_CENTER_LIMIT_
  27. m_limit(),
  28. #endif
  29. m_angularOnly(false),
  30. m_enableAngularMotor(false),
  31. m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER),
  32. m_useOffsetForConstraintFrame(HINGE_USE_FRAME_OFFSET),
  33. m_useReferenceFrameA(useReferenceFrameA),
  34. m_flags(0),
  35. m_normalCFM(0),
  36. m_normalERP(0),
  37. m_stopCFM(0),
  38. m_stopERP(0)
  39. {
  40. m_rbAFrame.getOrigin() = pivotInA;
  41. // since no frame is given, assume this to be zero angle and just pick rb transform axis
  42. btVector3 rbAxisA1 = rbA.getCenterOfMassTransform().getBasis().getColumn(0);
  43. btVector3 rbAxisA2;
  44. btScalar projection = axisInA.dot(rbAxisA1);
  45. if (projection >= 1.0f - SIMD_EPSILON)
  46. {
  47. rbAxisA1 = -rbA.getCenterOfMassTransform().getBasis().getColumn(2);
  48. rbAxisA2 = rbA.getCenterOfMassTransform().getBasis().getColumn(1);
  49. }
  50. else if (projection <= -1.0f + SIMD_EPSILON)
  51. {
  52. rbAxisA1 = rbA.getCenterOfMassTransform().getBasis().getColumn(2);
  53. rbAxisA2 = rbA.getCenterOfMassTransform().getBasis().getColumn(1);
  54. }
  55. else
  56. {
  57. rbAxisA2 = axisInA.cross(rbAxisA1);
  58. rbAxisA1 = rbAxisA2.cross(axisInA);
  59. }
  60. m_rbAFrame.getBasis().setValue(rbAxisA1.getX(), rbAxisA2.getX(), axisInA.getX(),
  61. rbAxisA1.getY(), rbAxisA2.getY(), axisInA.getY(),
  62. rbAxisA1.getZ(), rbAxisA2.getZ(), axisInA.getZ());
  63. btQuaternion rotationArc = shortestArcQuat(axisInA, axisInB);
  64. btVector3 rbAxisB1 = quatRotate(rotationArc, rbAxisA1);
  65. btVector3 rbAxisB2 = axisInB.cross(rbAxisB1);
  66. m_rbBFrame.getOrigin() = pivotInB;
  67. m_rbBFrame.getBasis().setValue(rbAxisB1.getX(), rbAxisB2.getX(), axisInB.getX(),
  68. rbAxisB1.getY(), rbAxisB2.getY(), axisInB.getY(),
  69. rbAxisB1.getZ(), rbAxisB2.getZ(), axisInB.getZ());
  70. #ifndef _BT_USE_CENTER_LIMIT_
  71. //start with free
  72. m_lowerLimit = btScalar(1.0f);
  73. m_upperLimit = btScalar(-1.0f);
  74. m_biasFactor = 0.3f;
  75. m_relaxationFactor = 1.0f;
  76. m_limitSoftness = 0.9f;
  77. m_solveLimit = false;
  78. #endif
  79. m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f);
  80. }
  81. btHingeConstraint::btHingeConstraint(btRigidBody& rbA, const btVector3& pivotInA, const btVector3& axisInA, bool useReferenceFrameA)
  82. : btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA),
  83. #ifdef _BT_USE_CENTER_LIMIT_
  84. m_limit(),
  85. #endif
  86. m_angularOnly(false),
  87. m_enableAngularMotor(false),
  88. m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER),
  89. m_useOffsetForConstraintFrame(HINGE_USE_FRAME_OFFSET),
  90. m_useReferenceFrameA(useReferenceFrameA),
  91. m_flags(0),
  92. m_normalCFM(0),
  93. m_normalERP(0),
  94. m_stopCFM(0),
  95. m_stopERP(0)
  96. {
  97. // since no frame is given, assume this to be zero angle and just pick rb transform axis
  98. // fixed axis in worldspace
  99. btVector3 rbAxisA1, rbAxisA2;
  100. btPlaneSpace1(axisInA, rbAxisA1, rbAxisA2);
  101. m_rbAFrame.getOrigin() = pivotInA;
  102. m_rbAFrame.getBasis().setValue(rbAxisA1.getX(), rbAxisA2.getX(), axisInA.getX(),
  103. rbAxisA1.getY(), rbAxisA2.getY(), axisInA.getY(),
  104. rbAxisA1.getZ(), rbAxisA2.getZ(), axisInA.getZ());
  105. btVector3 axisInB = rbA.getCenterOfMassTransform().getBasis() * axisInA;
  106. btQuaternion rotationArc = shortestArcQuat(axisInA, axisInB);
  107. btVector3 rbAxisB1 = quatRotate(rotationArc, rbAxisA1);
  108. btVector3 rbAxisB2 = axisInB.cross(rbAxisB1);
  109. m_rbBFrame.getOrigin() = rbA.getCenterOfMassTransform()(pivotInA);
  110. m_rbBFrame.getBasis().setValue(rbAxisB1.getX(), rbAxisB2.getX(), axisInB.getX(),
  111. rbAxisB1.getY(), rbAxisB2.getY(), axisInB.getY(),
  112. rbAxisB1.getZ(), rbAxisB2.getZ(), axisInB.getZ());
  113. #ifndef _BT_USE_CENTER_LIMIT_
  114. //start with free
  115. m_lowerLimit = btScalar(1.0f);
  116. m_upperLimit = btScalar(-1.0f);
  117. m_biasFactor = 0.3f;
  118. m_relaxationFactor = 1.0f;
  119. m_limitSoftness = 0.9f;
  120. m_solveLimit = false;
  121. #endif
  122. m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f);
  123. }
  124. btHingeConstraint::btHingeConstraint(btRigidBody& rbA, btRigidBody& rbB,
  125. const btTransform& rbAFrame, const btTransform& rbBFrame, bool useReferenceFrameA)
  126. : btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA, rbB), m_rbAFrame(rbAFrame), m_rbBFrame(rbBFrame),
  127. #ifdef _BT_USE_CENTER_LIMIT_
  128. m_limit(),
  129. #endif
  130. m_angularOnly(false),
  131. m_enableAngularMotor(false),
  132. m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER),
  133. m_useOffsetForConstraintFrame(HINGE_USE_FRAME_OFFSET),
  134. m_useReferenceFrameA(useReferenceFrameA),
  135. m_flags(0),
  136. m_normalCFM(0),
  137. m_normalERP(0),
  138. m_stopCFM(0),
  139. m_stopERP(0)
  140. {
  141. #ifndef _BT_USE_CENTER_LIMIT_
  142. //start with free
  143. m_lowerLimit = btScalar(1.0f);
  144. m_upperLimit = btScalar(-1.0f);
  145. m_biasFactor = 0.3f;
  146. m_relaxationFactor = 1.0f;
  147. m_limitSoftness = 0.9f;
  148. m_solveLimit = false;
  149. #endif
  150. m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f);
  151. }
  152. btHingeConstraint::btHingeConstraint(btRigidBody& rbA, const btTransform& rbAFrame, bool useReferenceFrameA)
  153. : btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA), m_rbAFrame(rbAFrame), m_rbBFrame(rbAFrame),
  154. #ifdef _BT_USE_CENTER_LIMIT_
  155. m_limit(),
  156. #endif
  157. m_angularOnly(false),
  158. m_enableAngularMotor(false),
  159. m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER),
  160. m_useOffsetForConstraintFrame(HINGE_USE_FRAME_OFFSET),
  161. m_useReferenceFrameA(useReferenceFrameA),
  162. m_flags(0),
  163. m_normalCFM(0),
  164. m_normalERP(0),
  165. m_stopCFM(0),
  166. m_stopERP(0)
  167. {
  168. ///not providing rigidbody B means implicitly using worldspace for body B
  169. m_rbBFrame.getOrigin() = m_rbA.getCenterOfMassTransform()(m_rbAFrame.getOrigin());
  170. #ifndef _BT_USE_CENTER_LIMIT_
  171. //start with free
  172. m_lowerLimit = btScalar(1.0f);
  173. m_upperLimit = btScalar(-1.0f);
  174. m_biasFactor = 0.3f;
  175. m_relaxationFactor = 1.0f;
  176. m_limitSoftness = 0.9f;
  177. m_solveLimit = false;
  178. #endif
  179. m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f);
  180. }
  181. void btHingeConstraint::buildJacobian()
  182. {
  183. if (m_useSolveConstraintObsolete)
  184. {
  185. m_appliedImpulse = btScalar(0.);
  186. m_accMotorImpulse = btScalar(0.);
  187. if (!m_angularOnly)
  188. {
  189. btVector3 pivotAInW = m_rbA.getCenterOfMassTransform() * m_rbAFrame.getOrigin();
  190. btVector3 pivotBInW = m_rbB.getCenterOfMassTransform() * m_rbBFrame.getOrigin();
  191. btVector3 relPos = pivotBInW - pivotAInW;
  192. btVector3 normal[3];
  193. if (relPos.length2() > SIMD_EPSILON)
  194. {
  195. normal[0] = relPos.normalized();
  196. }
  197. else
  198. {
  199. normal[0].setValue(btScalar(1.0), 0, 0);
  200. }
  201. btPlaneSpace1(normal[0], normal[1], normal[2]);
  202. for (int i = 0; i < 3; i++)
  203. {
  204. new (&m_jac[i]) btJacobianEntry(
  205. m_rbA.getCenterOfMassTransform().getBasis().transpose(),
  206. m_rbB.getCenterOfMassTransform().getBasis().transpose(),
  207. pivotAInW - m_rbA.getCenterOfMassPosition(),
  208. pivotBInW - m_rbB.getCenterOfMassPosition(),
  209. normal[i],
  210. m_rbA.getInvInertiaDiagLocal(),
  211. m_rbA.getInvMass(),
  212. m_rbB.getInvInertiaDiagLocal(),
  213. m_rbB.getInvMass());
  214. }
  215. }
  216. //calculate two perpendicular jointAxis, orthogonal to hingeAxis
  217. //these two jointAxis require equal angular velocities for both bodies
  218. //this is unused for now, it's a todo
  219. btVector3 jointAxis0local;
  220. btVector3 jointAxis1local;
  221. btPlaneSpace1(m_rbAFrame.getBasis().getColumn(2), jointAxis0local, jointAxis1local);
  222. btVector3 jointAxis0 = getRigidBodyA().getCenterOfMassTransform().getBasis() * jointAxis0local;
  223. btVector3 jointAxis1 = getRigidBodyA().getCenterOfMassTransform().getBasis() * jointAxis1local;
  224. btVector3 hingeAxisWorld = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2);
  225. new (&m_jacAng[0]) btJacobianEntry(jointAxis0,
  226. m_rbA.getCenterOfMassTransform().getBasis().transpose(),
  227. m_rbB.getCenterOfMassTransform().getBasis().transpose(),
  228. m_rbA.getInvInertiaDiagLocal(),
  229. m_rbB.getInvInertiaDiagLocal());
  230. new (&m_jacAng[1]) btJacobianEntry(jointAxis1,
  231. m_rbA.getCenterOfMassTransform().getBasis().transpose(),
  232. m_rbB.getCenterOfMassTransform().getBasis().transpose(),
  233. m_rbA.getInvInertiaDiagLocal(),
  234. m_rbB.getInvInertiaDiagLocal());
  235. new (&m_jacAng[2]) btJacobianEntry(hingeAxisWorld,
  236. m_rbA.getCenterOfMassTransform().getBasis().transpose(),
  237. m_rbB.getCenterOfMassTransform().getBasis().transpose(),
  238. m_rbA.getInvInertiaDiagLocal(),
  239. m_rbB.getInvInertiaDiagLocal());
  240. // clear accumulator
  241. m_accLimitImpulse = btScalar(0.);
  242. // test angular limit
  243. testLimit(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform());
  244. //Compute K = J*W*J' for hinge axis
  245. btVector3 axisA = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2);
  246. m_kHinge = 1.0f / (getRigidBodyA().computeAngularImpulseDenominator(axisA) +
  247. getRigidBodyB().computeAngularImpulseDenominator(axisA));
  248. }
  249. }
  250. #endif //__SPU__
  251. static inline btScalar btNormalizeAnglePositive(btScalar angle)
  252. {
  253. return btFmod(btFmod(angle, btScalar(2.0 * SIMD_PI)) + btScalar(2.0 * SIMD_PI), btScalar(2.0 * SIMD_PI));
  254. }
  255. static btScalar btShortestAngularDistance(btScalar accAngle, btScalar curAngle)
  256. {
  257. btScalar result = btNormalizeAngle(btNormalizeAnglePositive(btNormalizeAnglePositive(curAngle) -
  258. btNormalizeAnglePositive(accAngle)));
  259. return result;
  260. }
  261. static btScalar btShortestAngleUpdate(btScalar accAngle, btScalar curAngle)
  262. {
  263. btScalar tol(0.3);
  264. btScalar result = btShortestAngularDistance(accAngle, curAngle);
  265. if (btFabs(result) > tol)
  266. return curAngle;
  267. else
  268. return accAngle + result;
  269. return curAngle;
  270. }
  271. btScalar btHingeAccumulatedAngleConstraint::getAccumulatedHingeAngle()
  272. {
  273. btScalar hingeAngle = getHingeAngle();
  274. m_accumulatedAngle = btShortestAngleUpdate(m_accumulatedAngle, hingeAngle);
  275. return m_accumulatedAngle;
  276. }
  277. void btHingeAccumulatedAngleConstraint::setAccumulatedHingeAngle(btScalar accAngle)
  278. {
  279. m_accumulatedAngle = accAngle;
  280. }
  281. void btHingeAccumulatedAngleConstraint::getInfo1(btConstraintInfo1* info)
  282. {
  283. //update m_accumulatedAngle
  284. btScalar curHingeAngle = getHingeAngle();
  285. m_accumulatedAngle = btShortestAngleUpdate(m_accumulatedAngle, curHingeAngle);
  286. btHingeConstraint::getInfo1(info);
  287. }
  288. void btHingeConstraint::getInfo1(btConstraintInfo1* info)
  289. {
  290. if (m_useSolveConstraintObsolete)
  291. {
  292. info->m_numConstraintRows = 0;
  293. info->nub = 0;
  294. }
  295. else
  296. {
  297. info->m_numConstraintRows = 5; // Fixed 3 linear + 2 angular
  298. info->nub = 1;
  299. //always add the row, to avoid computation (data is not available yet)
  300. //prepare constraint
  301. testLimit(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform());
  302. if (getSolveLimit() || getEnableAngularMotor())
  303. {
  304. info->m_numConstraintRows++; // limit 3rd anguar as well
  305. info->nub--;
  306. }
  307. }
  308. }
  309. void btHingeConstraint::getInfo1NonVirtual(btConstraintInfo1* info)
  310. {
  311. if (m_useSolveConstraintObsolete)
  312. {
  313. info->m_numConstraintRows = 0;
  314. info->nub = 0;
  315. }
  316. else
  317. {
  318. //always add the 'limit' row, to avoid computation (data is not available yet)
  319. info->m_numConstraintRows = 6; // Fixed 3 linear + 2 angular
  320. info->nub = 0;
  321. }
  322. }
  323. void btHingeConstraint::getInfo2(btConstraintInfo2* info)
  324. {
  325. if (m_useOffsetForConstraintFrame)
  326. {
  327. getInfo2InternalUsingFrameOffset(info, m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform(), m_rbA.getAngularVelocity(), m_rbB.getAngularVelocity());
  328. }
  329. else
  330. {
  331. getInfo2Internal(info, m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform(), m_rbA.getAngularVelocity(), m_rbB.getAngularVelocity());
  332. }
  333. }
  334. void btHingeConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTransform& transA, const btTransform& transB, const btVector3& angVelA, const btVector3& angVelB)
  335. {
  336. ///the regular (virtual) implementation getInfo2 already performs 'testLimit' during getInfo1, so we need to do it now
  337. testLimit(transA, transB);
  338. getInfo2Internal(info, transA, transB, angVelA, angVelB);
  339. }
  340. void btHingeConstraint::getInfo2Internal(btConstraintInfo2* info, const btTransform& transA, const btTransform& transB, const btVector3& angVelA, const btVector3& angVelB)
  341. {
  342. btAssert(!m_useSolveConstraintObsolete);
  343. int i, skip = info->rowskip;
  344. // transforms in world space
  345. btTransform trA = transA * m_rbAFrame;
  346. btTransform trB = transB * m_rbBFrame;
  347. // pivot point
  348. btVector3 pivotAInW = trA.getOrigin();
  349. btVector3 pivotBInW = trB.getOrigin();
  350. #if 0
  351. if (0)
  352. {
  353. for (i=0;i<6;i++)
  354. {
  355. info->m_J1linearAxis[i*skip]=0;
  356. info->m_J1linearAxis[i*skip+1]=0;
  357. info->m_J1linearAxis[i*skip+2]=0;
  358. info->m_J1angularAxis[i*skip]=0;
  359. info->m_J1angularAxis[i*skip+1]=0;
  360. info->m_J1angularAxis[i*skip+2]=0;
  361. info->m_J2linearAxis[i*skip]=0;
  362. info->m_J2linearAxis[i*skip+1]=0;
  363. info->m_J2linearAxis[i*skip+2]=0;
  364. info->m_J2angularAxis[i*skip]=0;
  365. info->m_J2angularAxis[i*skip+1]=0;
  366. info->m_J2angularAxis[i*skip+2]=0;
  367. info->m_constraintError[i*skip]=0.f;
  368. }
  369. }
  370. #endif //#if 0
  371. // linear (all fixed)
  372. if (!m_angularOnly)
  373. {
  374. info->m_J1linearAxis[0] = 1;
  375. info->m_J1linearAxis[skip + 1] = 1;
  376. info->m_J1linearAxis[2 * skip + 2] = 1;
  377. info->m_J2linearAxis[0] = -1;
  378. info->m_J2linearAxis[skip + 1] = -1;
  379. info->m_J2linearAxis[2 * skip + 2] = -1;
  380. }
  381. btVector3 a1 = pivotAInW - transA.getOrigin();
  382. {
  383. btVector3* angular0 = (btVector3*)(info->m_J1angularAxis);
  384. btVector3* angular1 = (btVector3*)(info->m_J1angularAxis + skip);
  385. btVector3* angular2 = (btVector3*)(info->m_J1angularAxis + 2 * skip);
  386. btVector3 a1neg = -a1;
  387. a1neg.getSkewSymmetricMatrix(angular0, angular1, angular2);
  388. }
  389. btVector3 a2 = pivotBInW - transB.getOrigin();
  390. {
  391. btVector3* angular0 = (btVector3*)(info->m_J2angularAxis);
  392. btVector3* angular1 = (btVector3*)(info->m_J2angularAxis + skip);
  393. btVector3* angular2 = (btVector3*)(info->m_J2angularAxis + 2 * skip);
  394. a2.getSkewSymmetricMatrix(angular0, angular1, angular2);
  395. }
  396. // linear RHS
  397. btScalar normalErp = (m_flags & BT_HINGE_FLAGS_ERP_NORM) ? m_normalERP : info->erp;
  398. btScalar k = info->fps * normalErp;
  399. if (!m_angularOnly)
  400. {
  401. for (i = 0; i < 3; i++)
  402. {
  403. info->m_constraintError[i * skip] = k * (pivotBInW[i] - pivotAInW[i]);
  404. }
  405. }
  406. // make rotations around X and Y equal
  407. // the hinge axis should be the only unconstrained
  408. // rotational axis, the angular velocity of the two bodies perpendicular to
  409. // the hinge axis should be equal. thus the constraint equations are
  410. // p*w1 - p*w2 = 0
  411. // q*w1 - q*w2 = 0
  412. // where p and q are unit vectors normal to the hinge axis, and w1 and w2
  413. // are the angular velocity vectors of the two bodies.
  414. // get hinge axis (Z)
  415. btVector3 ax1 = trA.getBasis().getColumn(2);
  416. // get 2 orthos to hinge axis (X, Y)
  417. btVector3 p = trA.getBasis().getColumn(0);
  418. btVector3 q = trA.getBasis().getColumn(1);
  419. // set the two hinge angular rows
  420. int s3 = 3 * info->rowskip;
  421. int s4 = 4 * info->rowskip;
  422. info->m_J1angularAxis[s3 + 0] = p[0];
  423. info->m_J1angularAxis[s3 + 1] = p[1];
  424. info->m_J1angularAxis[s3 + 2] = p[2];
  425. info->m_J1angularAxis[s4 + 0] = q[0];
  426. info->m_J1angularAxis[s4 + 1] = q[1];
  427. info->m_J1angularAxis[s4 + 2] = q[2];
  428. info->m_J2angularAxis[s3 + 0] = -p[0];
  429. info->m_J2angularAxis[s3 + 1] = -p[1];
  430. info->m_J2angularAxis[s3 + 2] = -p[2];
  431. info->m_J2angularAxis[s4 + 0] = -q[0];
  432. info->m_J2angularAxis[s4 + 1] = -q[1];
  433. info->m_J2angularAxis[s4 + 2] = -q[2];
  434. // compute the right hand side of the constraint equation. set relative
  435. // body velocities along p and q to bring the hinge back into alignment.
  436. // if ax1,ax2 are the unit length hinge axes as computed from body1 and
  437. // body2, we need to rotate both bodies along the axis u = (ax1 x ax2).
  438. // if `theta' is the angle between ax1 and ax2, we need an angular velocity
  439. // along u to cover angle erp*theta in one step :
  440. // |angular_velocity| = angle/time = erp*theta / stepsize
  441. // = (erp*fps) * theta
  442. // angular_velocity = |angular_velocity| * (ax1 x ax2) / |ax1 x ax2|
  443. // = (erp*fps) * theta * (ax1 x ax2) / sin(theta)
  444. // ...as ax1 and ax2 are unit length. if theta is smallish,
  445. // theta ~= sin(theta), so
  446. // angular_velocity = (erp*fps) * (ax1 x ax2)
  447. // ax1 x ax2 is in the plane space of ax1, so we project the angular
  448. // velocity to p and q to find the right hand side.
  449. btVector3 ax2 = trB.getBasis().getColumn(2);
  450. btVector3 u = ax1.cross(ax2);
  451. info->m_constraintError[s3] = k * u.dot(p);
  452. info->m_constraintError[s4] = k * u.dot(q);
  453. // check angular limits
  454. int nrow = 4; // last filled row
  455. int srow;
  456. btScalar limit_err = btScalar(0.0);
  457. int limit = 0;
  458. if (getSolveLimit())
  459. {
  460. #ifdef _BT_USE_CENTER_LIMIT_
  461. limit_err = m_limit.getCorrection() * m_referenceSign;
  462. #else
  463. limit_err = m_correction * m_referenceSign;
  464. #endif
  465. limit = (limit_err > btScalar(0.0)) ? 1 : 2;
  466. }
  467. // if the hinge has joint limits or motor, add in the extra row
  468. bool powered = getEnableAngularMotor();
  469. if (limit || powered)
  470. {
  471. nrow++;
  472. srow = nrow * info->rowskip;
  473. info->m_J1angularAxis[srow + 0] = ax1[0];
  474. info->m_J1angularAxis[srow + 1] = ax1[1];
  475. info->m_J1angularAxis[srow + 2] = ax1[2];
  476. info->m_J2angularAxis[srow + 0] = -ax1[0];
  477. info->m_J2angularAxis[srow + 1] = -ax1[1];
  478. info->m_J2angularAxis[srow + 2] = -ax1[2];
  479. btScalar lostop = getLowerLimit();
  480. btScalar histop = getUpperLimit();
  481. if (limit && (lostop == histop))
  482. { // the joint motor is ineffective
  483. powered = false;
  484. }
  485. info->m_constraintError[srow] = btScalar(0.0f);
  486. btScalar currERP = (m_flags & BT_HINGE_FLAGS_ERP_STOP) ? m_stopERP : normalErp;
  487. if (powered)
  488. {
  489. if (m_flags & BT_HINGE_FLAGS_CFM_NORM)
  490. {
  491. info->cfm[srow] = m_normalCFM;
  492. }
  493. btScalar mot_fact = getMotorFactor(m_hingeAngle, lostop, histop, m_motorTargetVelocity, info->fps * currERP);
  494. info->m_constraintError[srow] += mot_fact * m_motorTargetVelocity * m_referenceSign;
  495. info->m_lowerLimit[srow] = -m_maxMotorImpulse;
  496. info->m_upperLimit[srow] = m_maxMotorImpulse;
  497. }
  498. if (limit)
  499. {
  500. k = info->fps * currERP;
  501. info->m_constraintError[srow] += k * limit_err;
  502. if (m_flags & BT_HINGE_FLAGS_CFM_STOP)
  503. {
  504. info->cfm[srow] = m_stopCFM;
  505. }
  506. if (lostop == histop)
  507. {
  508. // limited low and high simultaneously
  509. info->m_lowerLimit[srow] = -SIMD_INFINITY;
  510. info->m_upperLimit[srow] = SIMD_INFINITY;
  511. }
  512. else if (limit == 1)
  513. { // low limit
  514. info->m_lowerLimit[srow] = 0;
  515. info->m_upperLimit[srow] = SIMD_INFINITY;
  516. }
  517. else
  518. { // high limit
  519. info->m_lowerLimit[srow] = -SIMD_INFINITY;
  520. info->m_upperLimit[srow] = 0;
  521. }
  522. // bounce (we'll use slider parameter abs(1.0 - m_dampingLimAng) for that)
  523. #ifdef _BT_USE_CENTER_LIMIT_
  524. btScalar bounce = m_limit.getRelaxationFactor();
  525. #else
  526. btScalar bounce = m_relaxationFactor;
  527. #endif
  528. if (bounce > btScalar(0.0))
  529. {
  530. btScalar vel = angVelA.dot(ax1);
  531. vel -= angVelB.dot(ax1);
  532. // only apply bounce if the velocity is incoming, and if the
  533. // resulting c[] exceeds what we already have.
  534. if (limit == 1)
  535. { // low limit
  536. if (vel < 0)
  537. {
  538. btScalar newc = -bounce * vel;
  539. if (newc > info->m_constraintError[srow])
  540. {
  541. info->m_constraintError[srow] = newc;
  542. }
  543. }
  544. }
  545. else
  546. { // high limit - all those computations are reversed
  547. if (vel > 0)
  548. {
  549. btScalar newc = -bounce * vel;
  550. if (newc < info->m_constraintError[srow])
  551. {
  552. info->m_constraintError[srow] = newc;
  553. }
  554. }
  555. }
  556. }
  557. #ifdef _BT_USE_CENTER_LIMIT_
  558. info->m_constraintError[srow] *= m_limit.getBiasFactor();
  559. #else
  560. info->m_constraintError[srow] *= m_biasFactor;
  561. #endif
  562. } // if(limit)
  563. } // if angular limit or powered
  564. }
  565. void btHingeConstraint::setFrames(const btTransform& frameA, const btTransform& frameB)
  566. {
  567. m_rbAFrame = frameA;
  568. m_rbBFrame = frameB;
  569. buildJacobian();
  570. }
  571. void btHingeConstraint::updateRHS(btScalar timeStep)
  572. {
  573. (void)timeStep;
  574. }
  575. btScalar btHingeConstraint::getHingeAngle()
  576. {
  577. return getHingeAngle(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform());
  578. }
  579. btScalar btHingeConstraint::getHingeAngle(const btTransform& transA, const btTransform& transB)
  580. {
  581. const btVector3 refAxis0 = transA.getBasis() * m_rbAFrame.getBasis().getColumn(0);
  582. const btVector3 refAxis1 = transA.getBasis() * m_rbAFrame.getBasis().getColumn(1);
  583. const btVector3 swingAxis = transB.getBasis() * m_rbBFrame.getBasis().getColumn(1);
  584. // btScalar angle = btAtan2Fast(swingAxis.dot(refAxis0), swingAxis.dot(refAxis1));
  585. btScalar angle = btAtan2(swingAxis.dot(refAxis0), swingAxis.dot(refAxis1));
  586. return m_referenceSign * angle;
  587. }
  588. void btHingeConstraint::testLimit(const btTransform& transA, const btTransform& transB)
  589. {
  590. // Compute limit information
  591. m_hingeAngle = getHingeAngle(transA, transB);
  592. #ifdef _BT_USE_CENTER_LIMIT_
  593. m_limit.test(m_hingeAngle);
  594. #else
  595. m_correction = btScalar(0.);
  596. m_limitSign = btScalar(0.);
  597. m_solveLimit = false;
  598. if (m_lowerLimit <= m_upperLimit)
  599. {
  600. m_hingeAngle = btAdjustAngleToLimits(m_hingeAngle, m_lowerLimit, m_upperLimit);
  601. if (m_hingeAngle <= m_lowerLimit)
  602. {
  603. m_correction = (m_lowerLimit - m_hingeAngle);
  604. m_limitSign = 1.0f;
  605. m_solveLimit = true;
  606. }
  607. else if (m_hingeAngle >= m_upperLimit)
  608. {
  609. m_correction = m_upperLimit - m_hingeAngle;
  610. m_limitSign = -1.0f;
  611. m_solveLimit = true;
  612. }
  613. }
  614. #endif
  615. return;
  616. }
  617. static btVector3 vHinge(0, 0, btScalar(1));
  618. void btHingeConstraint::setMotorTarget(const btQuaternion& qAinB, btScalar dt)
  619. {
  620. // convert target from body to constraint space
  621. btQuaternion qConstraint = m_rbBFrame.getRotation().inverse() * qAinB * m_rbAFrame.getRotation();
  622. qConstraint.normalize();
  623. // extract "pure" hinge component
  624. btVector3 vNoHinge = quatRotate(qConstraint, vHinge);
  625. vNoHinge.normalize();
  626. btQuaternion qNoHinge = shortestArcQuat(vHinge, vNoHinge);
  627. btQuaternion qHinge = qNoHinge.inverse() * qConstraint;
  628. qHinge.normalize();
  629. // compute angular target, clamped to limits
  630. btScalar targetAngle = qHinge.getAngle();
  631. if (targetAngle > SIMD_PI) // long way around. flip quat and recalculate.
  632. {
  633. qHinge = -(qHinge);
  634. targetAngle = qHinge.getAngle();
  635. }
  636. if (qHinge.getZ() < 0)
  637. targetAngle = -targetAngle;
  638. setMotorTarget(targetAngle, dt);
  639. }
  640. void btHingeConstraint::setMotorTarget(btScalar targetAngle, btScalar dt)
  641. {
  642. #ifdef _BT_USE_CENTER_LIMIT_
  643. m_limit.fit(targetAngle);
  644. #else
  645. if (m_lowerLimit < m_upperLimit)
  646. {
  647. if (targetAngle < m_lowerLimit)
  648. targetAngle = m_lowerLimit;
  649. else if (targetAngle > m_upperLimit)
  650. targetAngle = m_upperLimit;
  651. }
  652. #endif
  653. // compute angular velocity
  654. btScalar curAngle = getHingeAngle(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform());
  655. btScalar dAngle = targetAngle - curAngle;
  656. m_motorTargetVelocity = dAngle / dt;
  657. }
  658. void btHingeConstraint::getInfo2InternalUsingFrameOffset(btConstraintInfo2* info, const btTransform& transA, const btTransform& transB, const btVector3& angVelA, const btVector3& angVelB)
  659. {
  660. btAssert(!m_useSolveConstraintObsolete);
  661. int i, s = info->rowskip;
  662. // transforms in world space
  663. btTransform trA = transA * m_rbAFrame;
  664. btTransform trB = transB * m_rbBFrame;
  665. // pivot point
  666. // btVector3 pivotAInW = trA.getOrigin();
  667. // btVector3 pivotBInW = trB.getOrigin();
  668. #if 1
  669. // difference between frames in WCS
  670. btVector3 ofs = trB.getOrigin() - trA.getOrigin();
  671. // now get weight factors depending on masses
  672. btScalar miA = getRigidBodyA().getInvMass();
  673. btScalar miB = getRigidBodyB().getInvMass();
  674. bool hasStaticBody = (miA < SIMD_EPSILON) || (miB < SIMD_EPSILON);
  675. btScalar miS = miA + miB;
  676. btScalar factA, factB;
  677. if (miS > btScalar(0.f))
  678. {
  679. factA = miB / miS;
  680. }
  681. else
  682. {
  683. factA = btScalar(0.5f);
  684. }
  685. factB = btScalar(1.0f) - factA;
  686. // get the desired direction of hinge axis
  687. // as weighted sum of Z-orthos of frameA and frameB in WCS
  688. btVector3 ax1A = trA.getBasis().getColumn(2);
  689. btVector3 ax1B = trB.getBasis().getColumn(2);
  690. btVector3 ax1 = ax1A * factA + ax1B * factB;
  691. if (ax1.length2()<SIMD_EPSILON)
  692. {
  693. factA=0.f;
  694. factB=1.f;
  695. ax1 = ax1A * factA + ax1B * factB;
  696. }
  697. ax1.normalize();
  698. // fill first 3 rows
  699. // we want: velA + wA x relA == velB + wB x relB
  700. btTransform bodyA_trans = transA;
  701. btTransform bodyB_trans = transB;
  702. int s0 = 0;
  703. int s1 = s;
  704. int s2 = s * 2;
  705. int nrow = 2; // last filled row
  706. btVector3 tmpA, tmpB, relA, relB, p, q;
  707. // get vector from bodyB to frameB in WCS
  708. relB = trB.getOrigin() - bodyB_trans.getOrigin();
  709. // get its projection to hinge axis
  710. btVector3 projB = ax1 * relB.dot(ax1);
  711. // get vector directed from bodyB to hinge axis (and orthogonal to it)
  712. btVector3 orthoB = relB - projB;
  713. // same for bodyA
  714. relA = trA.getOrigin() - bodyA_trans.getOrigin();
  715. btVector3 projA = ax1 * relA.dot(ax1);
  716. btVector3 orthoA = relA - projA;
  717. btVector3 totalDist = projA - projB;
  718. // get offset vectors relA and relB
  719. relA = orthoA + totalDist * factA;
  720. relB = orthoB - totalDist * factB;
  721. // now choose average ortho to hinge axis
  722. p = orthoB * factA + orthoA * factB;
  723. btScalar len2 = p.length2();
  724. if (len2 > SIMD_EPSILON)
  725. {
  726. p /= btSqrt(len2);
  727. }
  728. else
  729. {
  730. p = trA.getBasis().getColumn(1);
  731. }
  732. // make one more ortho
  733. q = ax1.cross(p);
  734. // fill three rows
  735. tmpA = relA.cross(p);
  736. tmpB = relB.cross(p);
  737. for (i = 0; i < 3; i++) info->m_J1angularAxis[s0 + i] = tmpA[i];
  738. for (i = 0; i < 3; i++) info->m_J2angularAxis[s0 + i] = -tmpB[i];
  739. tmpA = relA.cross(q);
  740. tmpB = relB.cross(q);
  741. if (hasStaticBody && getSolveLimit())
  742. { // to make constraint between static and dynamic objects more rigid
  743. // remove wA (or wB) from equation if angular limit is hit
  744. tmpB *= factB;
  745. tmpA *= factA;
  746. }
  747. for (i = 0; i < 3; i++) info->m_J1angularAxis[s1 + i] = tmpA[i];
  748. for (i = 0; i < 3; i++) info->m_J2angularAxis[s1 + i] = -tmpB[i];
  749. tmpA = relA.cross(ax1);
  750. tmpB = relB.cross(ax1);
  751. if (hasStaticBody)
  752. { // to make constraint between static and dynamic objects more rigid
  753. // remove wA (or wB) from equation
  754. tmpB *= factB;
  755. tmpA *= factA;
  756. }
  757. for (i = 0; i < 3; i++) info->m_J1angularAxis[s2 + i] = tmpA[i];
  758. for (i = 0; i < 3; i++) info->m_J2angularAxis[s2 + i] = -tmpB[i];
  759. btScalar normalErp = (m_flags & BT_HINGE_FLAGS_ERP_NORM) ? m_normalERP : info->erp;
  760. btScalar k = info->fps * normalErp;
  761. if (!m_angularOnly)
  762. {
  763. for (i = 0; i < 3; i++) info->m_J1linearAxis[s0 + i] = p[i];
  764. for (i = 0; i < 3; i++) info->m_J1linearAxis[s1 + i] = q[i];
  765. for (i = 0; i < 3; i++) info->m_J1linearAxis[s2 + i] = ax1[i];
  766. for (i = 0; i < 3; i++) info->m_J2linearAxis[s0 + i] = -p[i];
  767. for (i = 0; i < 3; i++) info->m_J2linearAxis[s1 + i] = -q[i];
  768. for (i = 0; i < 3; i++) info->m_J2linearAxis[s2 + i] = -ax1[i];
  769. // compute three elements of right hand side
  770. btScalar rhs = k * p.dot(ofs);
  771. info->m_constraintError[s0] = rhs;
  772. rhs = k * q.dot(ofs);
  773. info->m_constraintError[s1] = rhs;
  774. rhs = k * ax1.dot(ofs);
  775. info->m_constraintError[s2] = rhs;
  776. }
  777. // the hinge axis should be the only unconstrained
  778. // rotational axis, the angular velocity of the two bodies perpendicular to
  779. // the hinge axis should be equal. thus the constraint equations are
  780. // p*w1 - p*w2 = 0
  781. // q*w1 - q*w2 = 0
  782. // where p and q are unit vectors normal to the hinge axis, and w1 and w2
  783. // are the angular velocity vectors of the two bodies.
  784. int s3 = 3 * s;
  785. int s4 = 4 * s;
  786. info->m_J1angularAxis[s3 + 0] = p[0];
  787. info->m_J1angularAxis[s3 + 1] = p[1];
  788. info->m_J1angularAxis[s3 + 2] = p[2];
  789. info->m_J1angularAxis[s4 + 0] = q[0];
  790. info->m_J1angularAxis[s4 + 1] = q[1];
  791. info->m_J1angularAxis[s4 + 2] = q[2];
  792. info->m_J2angularAxis[s3 + 0] = -p[0];
  793. info->m_J2angularAxis[s3 + 1] = -p[1];
  794. info->m_J2angularAxis[s3 + 2] = -p[2];
  795. info->m_J2angularAxis[s4 + 0] = -q[0];
  796. info->m_J2angularAxis[s4 + 1] = -q[1];
  797. info->m_J2angularAxis[s4 + 2] = -q[2];
  798. // compute the right hand side of the constraint equation. set relative
  799. // body velocities along p and q to bring the hinge back into alignment.
  800. // if ax1A,ax1B are the unit length hinge axes as computed from bodyA and
  801. // bodyB, we need to rotate both bodies along the axis u = (ax1 x ax2).
  802. // if "theta" is the angle between ax1 and ax2, we need an angular velocity
  803. // along u to cover angle erp*theta in one step :
  804. // |angular_velocity| = angle/time = erp*theta / stepsize
  805. // = (erp*fps) * theta
  806. // angular_velocity = |angular_velocity| * (ax1 x ax2) / |ax1 x ax2|
  807. // = (erp*fps) * theta * (ax1 x ax2) / sin(theta)
  808. // ...as ax1 and ax2 are unit length. if theta is smallish,
  809. // theta ~= sin(theta), so
  810. // angular_velocity = (erp*fps) * (ax1 x ax2)
  811. // ax1 x ax2 is in the plane space of ax1, so we project the angular
  812. // velocity to p and q to find the right hand side.
  813. k = info->fps * normalErp; //??
  814. btVector3 u = ax1A.cross(ax1B);
  815. info->m_constraintError[s3] = k * u.dot(p);
  816. info->m_constraintError[s4] = k * u.dot(q);
  817. #endif
  818. // check angular limits
  819. nrow = 4; // last filled row
  820. int srow;
  821. btScalar limit_err = btScalar(0.0);
  822. int limit = 0;
  823. if (getSolveLimit())
  824. {
  825. #ifdef _BT_USE_CENTER_LIMIT_
  826. limit_err = m_limit.getCorrection() * m_referenceSign;
  827. #else
  828. limit_err = m_correction * m_referenceSign;
  829. #endif
  830. limit = (limit_err > btScalar(0.0)) ? 1 : 2;
  831. }
  832. // if the hinge has joint limits or motor, add in the extra row
  833. bool powered = getEnableAngularMotor();
  834. if (limit || powered)
  835. {
  836. nrow++;
  837. srow = nrow * info->rowskip;
  838. info->m_J1angularAxis[srow + 0] = ax1[0];
  839. info->m_J1angularAxis[srow + 1] = ax1[1];
  840. info->m_J1angularAxis[srow + 2] = ax1[2];
  841. info->m_J2angularAxis[srow + 0] = -ax1[0];
  842. info->m_J2angularAxis[srow + 1] = -ax1[1];
  843. info->m_J2angularAxis[srow + 2] = -ax1[2];
  844. btScalar lostop = getLowerLimit();
  845. btScalar histop = getUpperLimit();
  846. if (limit && (lostop == histop))
  847. { // the joint motor is ineffective
  848. powered = false;
  849. }
  850. info->m_constraintError[srow] = btScalar(0.0f);
  851. btScalar currERP = (m_flags & BT_HINGE_FLAGS_ERP_STOP) ? m_stopERP : normalErp;
  852. if (powered)
  853. {
  854. if (m_flags & BT_HINGE_FLAGS_CFM_NORM)
  855. {
  856. info->cfm[srow] = m_normalCFM;
  857. }
  858. btScalar mot_fact = getMotorFactor(m_hingeAngle, lostop, histop, m_motorTargetVelocity, info->fps * currERP);
  859. info->m_constraintError[srow] += mot_fact * m_motorTargetVelocity * m_referenceSign;
  860. info->m_lowerLimit[srow] = -m_maxMotorImpulse;
  861. info->m_upperLimit[srow] = m_maxMotorImpulse;
  862. }
  863. if (limit)
  864. {
  865. k = info->fps * currERP;
  866. info->m_constraintError[srow] += k * limit_err;
  867. if (m_flags & BT_HINGE_FLAGS_CFM_STOP)
  868. {
  869. info->cfm[srow] = m_stopCFM;
  870. }
  871. if (lostop == histop)
  872. {
  873. // limited low and high simultaneously
  874. info->m_lowerLimit[srow] = -SIMD_INFINITY;
  875. info->m_upperLimit[srow] = SIMD_INFINITY;
  876. }
  877. else if (limit == 1)
  878. { // low limit
  879. info->m_lowerLimit[srow] = 0;
  880. info->m_upperLimit[srow] = SIMD_INFINITY;
  881. }
  882. else
  883. { // high limit
  884. info->m_lowerLimit[srow] = -SIMD_INFINITY;
  885. info->m_upperLimit[srow] = 0;
  886. }
  887. // bounce (we'll use slider parameter abs(1.0 - m_dampingLimAng) for that)
  888. #ifdef _BT_USE_CENTER_LIMIT_
  889. btScalar bounce = m_limit.getRelaxationFactor();
  890. #else
  891. btScalar bounce = m_relaxationFactor;
  892. #endif
  893. if (bounce > btScalar(0.0))
  894. {
  895. btScalar vel = angVelA.dot(ax1);
  896. vel -= angVelB.dot(ax1);
  897. // only apply bounce if the velocity is incoming, and if the
  898. // resulting c[] exceeds what we already have.
  899. if (limit == 1)
  900. { // low limit
  901. if (vel < 0)
  902. {
  903. btScalar newc = -bounce * vel;
  904. if (newc > info->m_constraintError[srow])
  905. {
  906. info->m_constraintError[srow] = newc;
  907. }
  908. }
  909. }
  910. else
  911. { // high limit - all those computations are reversed
  912. if (vel > 0)
  913. {
  914. btScalar newc = -bounce * vel;
  915. if (newc < info->m_constraintError[srow])
  916. {
  917. info->m_constraintError[srow] = newc;
  918. }
  919. }
  920. }
  921. }
  922. #ifdef _BT_USE_CENTER_LIMIT_
  923. info->m_constraintError[srow] *= m_limit.getBiasFactor();
  924. #else
  925. info->m_constraintError[srow] *= m_biasFactor;
  926. #endif
  927. } // if(limit)
  928. } // if angular limit or powered
  929. }
  930. ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
  931. ///If no axis is provided, it uses the default axis for this constraint.
  932. void btHingeConstraint::setParam(int num, btScalar value, int axis)
  933. {
  934. if ((axis == -1) || (axis == 5))
  935. {
  936. switch (num)
  937. {
  938. case BT_CONSTRAINT_STOP_ERP:
  939. m_stopERP = value;
  940. m_flags |= BT_HINGE_FLAGS_ERP_STOP;
  941. break;
  942. case BT_CONSTRAINT_STOP_CFM:
  943. m_stopCFM = value;
  944. m_flags |= BT_HINGE_FLAGS_CFM_STOP;
  945. break;
  946. case BT_CONSTRAINT_CFM:
  947. m_normalCFM = value;
  948. m_flags |= BT_HINGE_FLAGS_CFM_NORM;
  949. break;
  950. case BT_CONSTRAINT_ERP:
  951. m_normalERP = value;
  952. m_flags |= BT_HINGE_FLAGS_ERP_NORM;
  953. break;
  954. default:
  955. btAssertConstrParams(0);
  956. }
  957. }
  958. else
  959. {
  960. btAssertConstrParams(0);
  961. }
  962. }
  963. ///return the local value of parameter
  964. btScalar btHingeConstraint::getParam(int num, int axis) const
  965. {
  966. btScalar retVal = 0;
  967. if ((axis == -1) || (axis == 5))
  968. {
  969. switch (num)
  970. {
  971. case BT_CONSTRAINT_STOP_ERP:
  972. btAssertConstrParams(m_flags & BT_HINGE_FLAGS_ERP_STOP);
  973. retVal = m_stopERP;
  974. break;
  975. case BT_CONSTRAINT_STOP_CFM:
  976. btAssertConstrParams(m_flags & BT_HINGE_FLAGS_CFM_STOP);
  977. retVal = m_stopCFM;
  978. break;
  979. case BT_CONSTRAINT_CFM:
  980. btAssertConstrParams(m_flags & BT_HINGE_FLAGS_CFM_NORM);
  981. retVal = m_normalCFM;
  982. break;
  983. case BT_CONSTRAINT_ERP:
  984. btAssertConstrParams(m_flags & BT_HINGE_FLAGS_ERP_NORM);
  985. retVal = m_normalERP;
  986. break;
  987. default:
  988. btAssertConstrParams(0);
  989. }
  990. }
  991. else
  992. {
  993. btAssertConstrParams(0);
  994. }
  995. return retVal;
  996. }