btHingeConstraint.cpp 34 KB

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