btConeTwistConstraint.cpp 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116
  1. /*
  2. Bullet Continuous Collision Detection and Physics Library
  3. btConeTwistConstraint is Copyright (c) 2007 Starbreeze Studios
  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. Written by: Marcus Hennix
  13. */
  14. #include "btConeTwistConstraint.h"
  15. #include "BulletDynamics/Dynamics/btRigidBody.h"
  16. #include "LinearMath/btTransformUtil.h"
  17. #include "LinearMath/btMinMax.h"
  18. #include <cmath>
  19. #include <new>
  20. //#define CONETWIST_USE_OBSOLETE_SOLVER true
  21. #define CONETWIST_USE_OBSOLETE_SOLVER false
  22. #define CONETWIST_DEF_FIX_THRESH btScalar(.05f)
  23. SIMD_FORCE_INLINE btScalar computeAngularImpulseDenominator(const btVector3& axis, const btMatrix3x3& invInertiaWorld)
  24. {
  25. btVector3 vec = axis * invInertiaWorld;
  26. return axis.dot(vec);
  27. }
  28. btConeTwistConstraint::btConeTwistConstraint(btRigidBody& rbA, btRigidBody& rbB,
  29. const btTransform& rbAFrame, const btTransform& rbBFrame)
  30. : btTypedConstraint(CONETWIST_CONSTRAINT_TYPE, rbA, rbB), m_rbAFrame(rbAFrame), m_rbBFrame(rbBFrame), m_angularOnly(false), m_useSolveConstraintObsolete(CONETWIST_USE_OBSOLETE_SOLVER)
  31. {
  32. init();
  33. }
  34. btConeTwistConstraint::btConeTwistConstraint(btRigidBody& rbA, const btTransform& rbAFrame)
  35. : btTypedConstraint(CONETWIST_CONSTRAINT_TYPE, rbA), m_rbAFrame(rbAFrame), m_angularOnly(false), m_useSolveConstraintObsolete(CONETWIST_USE_OBSOLETE_SOLVER)
  36. {
  37. m_rbBFrame = m_rbAFrame;
  38. m_rbBFrame.setOrigin(btVector3(0., 0., 0.));
  39. init();
  40. }
  41. void btConeTwistConstraint::init()
  42. {
  43. m_angularOnly = false;
  44. m_solveTwistLimit = false;
  45. m_solveSwingLimit = false;
  46. m_bMotorEnabled = false;
  47. m_maxMotorImpulse = btScalar(-1);
  48. setLimit(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
  49. m_damping = btScalar(0.01);
  50. m_fixThresh = CONETWIST_DEF_FIX_THRESH;
  51. m_flags = 0;
  52. m_linCFM = btScalar(0.f);
  53. m_linERP = btScalar(0.7f);
  54. m_angCFM = btScalar(0.f);
  55. }
  56. void btConeTwistConstraint::getInfo1(btConstraintInfo1* info)
  57. {
  58. if (m_useSolveConstraintObsolete)
  59. {
  60. info->m_numConstraintRows = 0;
  61. info->nub = 0;
  62. }
  63. else
  64. {
  65. info->m_numConstraintRows = 3;
  66. info->nub = 3;
  67. calcAngleInfo2(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform(), m_rbA.getInvInertiaTensorWorld(), m_rbB.getInvInertiaTensorWorld());
  68. if (m_solveSwingLimit)
  69. {
  70. info->m_numConstraintRows++;
  71. info->nub--;
  72. if ((m_swingSpan1 < m_fixThresh) && (m_swingSpan2 < m_fixThresh))
  73. {
  74. info->m_numConstraintRows++;
  75. info->nub--;
  76. }
  77. }
  78. if (m_solveTwistLimit)
  79. {
  80. info->m_numConstraintRows++;
  81. info->nub--;
  82. }
  83. }
  84. }
  85. void btConeTwistConstraint::getInfo1NonVirtual(btConstraintInfo1* info)
  86. {
  87. //always reserve 6 rows: object transform is not available on SPU
  88. info->m_numConstraintRows = 6;
  89. info->nub = 0;
  90. }
  91. void btConeTwistConstraint::getInfo2(btConstraintInfo2* info)
  92. {
  93. getInfo2NonVirtual(info, m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform(), m_rbA.getInvInertiaTensorWorld(), m_rbB.getInvInertiaTensorWorld());
  94. }
  95. void btConeTwistConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTransform& transA, const btTransform& transB, const btMatrix3x3& invInertiaWorldA, const btMatrix3x3& invInertiaWorldB)
  96. {
  97. calcAngleInfo2(transA, transB, invInertiaWorldA, invInertiaWorldB);
  98. btAssert(!m_useSolveConstraintObsolete);
  99. // set jacobian
  100. info->m_J1linearAxis[0] = 1;
  101. info->m_J1linearAxis[info->rowskip + 1] = 1;
  102. info->m_J1linearAxis[2 * info->rowskip + 2] = 1;
  103. btVector3 a1 = transA.getBasis() * m_rbAFrame.getOrigin();
  104. {
  105. btVector3* angular0 = (btVector3*)(info->m_J1angularAxis);
  106. btVector3* angular1 = (btVector3*)(info->m_J1angularAxis + info->rowskip);
  107. btVector3* angular2 = (btVector3*)(info->m_J1angularAxis + 2 * info->rowskip);
  108. btVector3 a1neg = -a1;
  109. a1neg.getSkewSymmetricMatrix(angular0, angular1, angular2);
  110. }
  111. info->m_J2linearAxis[0] = -1;
  112. info->m_J2linearAxis[info->rowskip + 1] = -1;
  113. info->m_J2linearAxis[2 * info->rowskip + 2] = -1;
  114. btVector3 a2 = transB.getBasis() * m_rbBFrame.getOrigin();
  115. {
  116. btVector3* angular0 = (btVector3*)(info->m_J2angularAxis);
  117. btVector3* angular1 = (btVector3*)(info->m_J2angularAxis + info->rowskip);
  118. btVector3* angular2 = (btVector3*)(info->m_J2angularAxis + 2 * info->rowskip);
  119. a2.getSkewSymmetricMatrix(angular0, angular1, angular2);
  120. }
  121. // set right hand side
  122. btScalar linERP = (m_flags & BT_CONETWIST_FLAGS_LIN_ERP) ? m_linERP : info->erp;
  123. btScalar k = info->fps * linERP;
  124. int j;
  125. for (j = 0; j < 3; j++)
  126. {
  127. info->m_constraintError[j * info->rowskip] = k * (a2[j] + transB.getOrigin()[j] - a1[j] - transA.getOrigin()[j]);
  128. info->m_lowerLimit[j * info->rowskip] = -SIMD_INFINITY;
  129. info->m_upperLimit[j * info->rowskip] = SIMD_INFINITY;
  130. if (m_flags & BT_CONETWIST_FLAGS_LIN_CFM)
  131. {
  132. info->cfm[j * info->rowskip] = m_linCFM;
  133. }
  134. }
  135. int row = 3;
  136. int srow = row * info->rowskip;
  137. btVector3 ax1;
  138. // angular limits
  139. if (m_solveSwingLimit)
  140. {
  141. btScalar* J1 = info->m_J1angularAxis;
  142. btScalar* J2 = info->m_J2angularAxis;
  143. if ((m_swingSpan1 < m_fixThresh) && (m_swingSpan2 < m_fixThresh))
  144. {
  145. btTransform trA = transA * m_rbAFrame;
  146. btVector3 p = trA.getBasis().getColumn(1);
  147. btVector3 q = trA.getBasis().getColumn(2);
  148. int srow1 = srow + info->rowskip;
  149. J1[srow + 0] = p[0];
  150. J1[srow + 1] = p[1];
  151. J1[srow + 2] = p[2];
  152. J1[srow1 + 0] = q[0];
  153. J1[srow1 + 1] = q[1];
  154. J1[srow1 + 2] = q[2];
  155. J2[srow + 0] = -p[0];
  156. J2[srow + 1] = -p[1];
  157. J2[srow + 2] = -p[2];
  158. J2[srow1 + 0] = -q[0];
  159. J2[srow1 + 1] = -q[1];
  160. J2[srow1 + 2] = -q[2];
  161. btScalar fact = info->fps * m_relaxationFactor;
  162. info->m_constraintError[srow] = fact * m_swingAxis.dot(p);
  163. info->m_constraintError[srow1] = fact * m_swingAxis.dot(q);
  164. info->m_lowerLimit[srow] = -SIMD_INFINITY;
  165. info->m_upperLimit[srow] = SIMD_INFINITY;
  166. info->m_lowerLimit[srow1] = -SIMD_INFINITY;
  167. info->m_upperLimit[srow1] = SIMD_INFINITY;
  168. srow = srow1 + info->rowskip;
  169. }
  170. else
  171. {
  172. ax1 = m_swingAxis * m_relaxationFactor * m_relaxationFactor;
  173. J1[srow + 0] = ax1[0];
  174. J1[srow + 1] = ax1[1];
  175. J1[srow + 2] = ax1[2];
  176. J2[srow + 0] = -ax1[0];
  177. J2[srow + 1] = -ax1[1];
  178. J2[srow + 2] = -ax1[2];
  179. btScalar k = info->fps * m_biasFactor;
  180. info->m_constraintError[srow] = k * m_swingCorrection;
  181. if (m_flags & BT_CONETWIST_FLAGS_ANG_CFM)
  182. {
  183. info->cfm[srow] = m_angCFM;
  184. }
  185. // m_swingCorrection is always positive or 0
  186. info->m_lowerLimit[srow] = 0;
  187. info->m_upperLimit[srow] = (m_bMotorEnabled && m_maxMotorImpulse >= 0.0f) ? m_maxMotorImpulse : SIMD_INFINITY;
  188. srow += info->rowskip;
  189. }
  190. }
  191. if (m_solveTwistLimit)
  192. {
  193. ax1 = m_twistAxis * m_relaxationFactor * m_relaxationFactor;
  194. btScalar* J1 = info->m_J1angularAxis;
  195. btScalar* J2 = info->m_J2angularAxis;
  196. J1[srow + 0] = ax1[0];
  197. J1[srow + 1] = ax1[1];
  198. J1[srow + 2] = ax1[2];
  199. J2[srow + 0] = -ax1[0];
  200. J2[srow + 1] = -ax1[1];
  201. J2[srow + 2] = -ax1[2];
  202. btScalar k = info->fps * m_biasFactor;
  203. info->m_constraintError[srow] = k * m_twistCorrection;
  204. if (m_flags & BT_CONETWIST_FLAGS_ANG_CFM)
  205. {
  206. info->cfm[srow] = m_angCFM;
  207. }
  208. if (m_twistSpan > 0.0f)
  209. {
  210. if (m_twistCorrection > 0.0f)
  211. {
  212. info->m_lowerLimit[srow] = 0;
  213. info->m_upperLimit[srow] = SIMD_INFINITY;
  214. }
  215. else
  216. {
  217. info->m_lowerLimit[srow] = -SIMD_INFINITY;
  218. info->m_upperLimit[srow] = 0;
  219. }
  220. }
  221. else
  222. {
  223. info->m_lowerLimit[srow] = -SIMD_INFINITY;
  224. info->m_upperLimit[srow] = SIMD_INFINITY;
  225. }
  226. srow += info->rowskip;
  227. }
  228. }
  229. void btConeTwistConstraint::buildJacobian()
  230. {
  231. if (m_useSolveConstraintObsolete)
  232. {
  233. m_appliedImpulse = btScalar(0.);
  234. m_accTwistLimitImpulse = btScalar(0.);
  235. m_accSwingLimitImpulse = btScalar(0.);
  236. m_accMotorImpulse = btVector3(0., 0., 0.);
  237. if (!m_angularOnly)
  238. {
  239. btVector3 pivotAInW = m_rbA.getCenterOfMassTransform() * m_rbAFrame.getOrigin();
  240. btVector3 pivotBInW = m_rbB.getCenterOfMassTransform() * m_rbBFrame.getOrigin();
  241. btVector3 relPos = pivotBInW - pivotAInW;
  242. btVector3 normal[3];
  243. if (relPos.length2() > SIMD_EPSILON)
  244. {
  245. normal[0] = relPos.normalized();
  246. }
  247. else
  248. {
  249. normal[0].setValue(btScalar(1.0), 0, 0);
  250. }
  251. btPlaneSpace1(normal[0], normal[1], normal[2]);
  252. for (int i = 0; i < 3; i++)
  253. {
  254. new (&m_jac[i]) btJacobianEntry(
  255. m_rbA.getCenterOfMassTransform().getBasis().transpose(),
  256. m_rbB.getCenterOfMassTransform().getBasis().transpose(),
  257. pivotAInW - m_rbA.getCenterOfMassPosition(),
  258. pivotBInW - m_rbB.getCenterOfMassPosition(),
  259. normal[i],
  260. m_rbA.getInvInertiaDiagLocal(),
  261. m_rbA.getInvMass(),
  262. m_rbB.getInvInertiaDiagLocal(),
  263. m_rbB.getInvMass());
  264. }
  265. }
  266. calcAngleInfo2(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform(), m_rbA.getInvInertiaTensorWorld(), m_rbB.getInvInertiaTensorWorld());
  267. }
  268. }
  269. void btConeTwistConstraint::solveConstraintObsolete(btSolverBody& bodyA, btSolverBody& bodyB, btScalar timeStep)
  270. {
  271. #ifndef __SPU__
  272. if (m_useSolveConstraintObsolete)
  273. {
  274. btVector3 pivotAInW = m_rbA.getCenterOfMassTransform() * m_rbAFrame.getOrigin();
  275. btVector3 pivotBInW = m_rbB.getCenterOfMassTransform() * m_rbBFrame.getOrigin();
  276. btScalar tau = btScalar(0.3);
  277. //linear part
  278. if (!m_angularOnly)
  279. {
  280. btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition();
  281. btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition();
  282. btVector3 vel1;
  283. bodyA.internalGetVelocityInLocalPointObsolete(rel_pos1, vel1);
  284. btVector3 vel2;
  285. bodyB.internalGetVelocityInLocalPointObsolete(rel_pos2, vel2);
  286. btVector3 vel = vel1 - vel2;
  287. for (int i = 0; i < 3; i++)
  288. {
  289. const btVector3& normal = m_jac[i].m_linearJointAxis;
  290. btScalar jacDiagABInv = btScalar(1.) / m_jac[i].getDiagonal();
  291. btScalar rel_vel;
  292. rel_vel = normal.dot(vel);
  293. //positional error (zeroth order error)
  294. btScalar depth = -(pivotAInW - pivotBInW).dot(normal); //this is the error projected on the normal
  295. btScalar impulse = depth * tau / timeStep * jacDiagABInv - rel_vel * jacDiagABInv;
  296. m_appliedImpulse += impulse;
  297. btVector3 ftorqueAxis1 = rel_pos1.cross(normal);
  298. btVector3 ftorqueAxis2 = rel_pos2.cross(normal);
  299. bodyA.internalApplyImpulse(normal * m_rbA.getInvMass(), m_rbA.getInvInertiaTensorWorld() * ftorqueAxis1, impulse);
  300. bodyB.internalApplyImpulse(normal * m_rbB.getInvMass(), m_rbB.getInvInertiaTensorWorld() * ftorqueAxis2, -impulse);
  301. }
  302. }
  303. // apply motor
  304. if (m_bMotorEnabled)
  305. {
  306. // compute current and predicted transforms
  307. btTransform trACur = m_rbA.getCenterOfMassTransform();
  308. btTransform trBCur = m_rbB.getCenterOfMassTransform();
  309. btVector3 omegaA;
  310. bodyA.internalGetAngularVelocity(omegaA);
  311. btVector3 omegaB;
  312. bodyB.internalGetAngularVelocity(omegaB);
  313. btTransform trAPred;
  314. trAPred.setIdentity();
  315. btVector3 zerovec(0, 0, 0);
  316. btTransformUtil::integrateTransform(
  317. trACur, zerovec, omegaA, timeStep, trAPred);
  318. btTransform trBPred;
  319. trBPred.setIdentity();
  320. btTransformUtil::integrateTransform(
  321. trBCur, zerovec, omegaB, timeStep, trBPred);
  322. // compute desired transforms in world
  323. btTransform trPose(m_qTarget);
  324. btTransform trABDes = m_rbBFrame * trPose * m_rbAFrame.inverse();
  325. btTransform trADes = trBPred * trABDes;
  326. btTransform trBDes = trAPred * trABDes.inverse();
  327. // compute desired omegas in world
  328. btVector3 omegaADes, omegaBDes;
  329. btTransformUtil::calculateVelocity(trACur, trADes, timeStep, zerovec, omegaADes);
  330. btTransformUtil::calculateVelocity(trBCur, trBDes, timeStep, zerovec, omegaBDes);
  331. // compute delta omegas
  332. btVector3 dOmegaA = omegaADes - omegaA;
  333. btVector3 dOmegaB = omegaBDes - omegaB;
  334. // compute weighted avg axis of dOmega (weighting based on inertias)
  335. btVector3 axisA, axisB;
  336. btScalar kAxisAInv = 0, kAxisBInv = 0;
  337. if (dOmegaA.length2() > SIMD_EPSILON)
  338. {
  339. axisA = dOmegaA.normalized();
  340. kAxisAInv = getRigidBodyA().computeAngularImpulseDenominator(axisA);
  341. }
  342. if (dOmegaB.length2() > SIMD_EPSILON)
  343. {
  344. axisB = dOmegaB.normalized();
  345. kAxisBInv = getRigidBodyB().computeAngularImpulseDenominator(axisB);
  346. }
  347. btVector3 avgAxis = kAxisAInv * axisA + kAxisBInv * axisB;
  348. static bool bDoTorque = true;
  349. if (bDoTorque && avgAxis.length2() > SIMD_EPSILON)
  350. {
  351. avgAxis.normalize();
  352. kAxisAInv = getRigidBodyA().computeAngularImpulseDenominator(avgAxis);
  353. kAxisBInv = getRigidBodyB().computeAngularImpulseDenominator(avgAxis);
  354. btScalar kInvCombined = kAxisAInv + kAxisBInv;
  355. btVector3 impulse = (kAxisAInv * dOmegaA - kAxisBInv * dOmegaB) /
  356. (kInvCombined * kInvCombined);
  357. if (m_maxMotorImpulse >= 0)
  358. {
  359. btScalar fMaxImpulse = m_maxMotorImpulse;
  360. if (m_bNormalizedMotorStrength)
  361. fMaxImpulse = fMaxImpulse / kAxisAInv;
  362. btVector3 newUnclampedAccImpulse = m_accMotorImpulse + impulse;
  363. btScalar newUnclampedMag = newUnclampedAccImpulse.length();
  364. if (newUnclampedMag > fMaxImpulse)
  365. {
  366. newUnclampedAccImpulse.normalize();
  367. newUnclampedAccImpulse *= fMaxImpulse;
  368. impulse = newUnclampedAccImpulse - m_accMotorImpulse;
  369. }
  370. m_accMotorImpulse += impulse;
  371. }
  372. btScalar impulseMag = impulse.length();
  373. btVector3 impulseAxis = impulse / impulseMag;
  374. bodyA.internalApplyImpulse(btVector3(0, 0, 0), m_rbA.getInvInertiaTensorWorld() * impulseAxis, impulseMag);
  375. bodyB.internalApplyImpulse(btVector3(0, 0, 0), m_rbB.getInvInertiaTensorWorld() * impulseAxis, -impulseMag);
  376. }
  377. }
  378. else if (m_damping > SIMD_EPSILON) // no motor: do a little damping
  379. {
  380. btVector3 angVelA;
  381. bodyA.internalGetAngularVelocity(angVelA);
  382. btVector3 angVelB;
  383. bodyB.internalGetAngularVelocity(angVelB);
  384. btVector3 relVel = angVelB - angVelA;
  385. if (relVel.length2() > SIMD_EPSILON)
  386. {
  387. btVector3 relVelAxis = relVel.normalized();
  388. btScalar m_kDamping = btScalar(1.) /
  389. (getRigidBodyA().computeAngularImpulseDenominator(relVelAxis) +
  390. getRigidBodyB().computeAngularImpulseDenominator(relVelAxis));
  391. btVector3 impulse = m_damping * m_kDamping * relVel;
  392. btScalar impulseMag = impulse.length();
  393. btVector3 impulseAxis = impulse / impulseMag;
  394. bodyA.internalApplyImpulse(btVector3(0, 0, 0), m_rbA.getInvInertiaTensorWorld() * impulseAxis, impulseMag);
  395. bodyB.internalApplyImpulse(btVector3(0, 0, 0), m_rbB.getInvInertiaTensorWorld() * impulseAxis, -impulseMag);
  396. }
  397. }
  398. // joint limits
  399. {
  400. ///solve angular part
  401. btVector3 angVelA;
  402. bodyA.internalGetAngularVelocity(angVelA);
  403. btVector3 angVelB;
  404. bodyB.internalGetAngularVelocity(angVelB);
  405. // solve swing limit
  406. if (m_solveSwingLimit)
  407. {
  408. btScalar amplitude = m_swingLimitRatio * m_swingCorrection * m_biasFactor / timeStep;
  409. btScalar relSwingVel = (angVelB - angVelA).dot(m_swingAxis);
  410. if (relSwingVel > 0)
  411. amplitude += m_swingLimitRatio * relSwingVel * m_relaxationFactor;
  412. btScalar impulseMag = amplitude * m_kSwing;
  413. // Clamp the accumulated impulse
  414. btScalar temp = m_accSwingLimitImpulse;
  415. m_accSwingLimitImpulse = btMax(m_accSwingLimitImpulse + impulseMag, btScalar(0.0));
  416. impulseMag = m_accSwingLimitImpulse - temp;
  417. btVector3 impulse = m_swingAxis * impulseMag;
  418. // don't let cone response affect twist
  419. // (this can happen since body A's twist doesn't match body B's AND we use an elliptical cone limit)
  420. {
  421. btVector3 impulseTwistCouple = impulse.dot(m_twistAxisA) * m_twistAxisA;
  422. btVector3 impulseNoTwistCouple = impulse - impulseTwistCouple;
  423. impulse = impulseNoTwistCouple;
  424. }
  425. impulseMag = impulse.length();
  426. btVector3 noTwistSwingAxis = impulse / impulseMag;
  427. bodyA.internalApplyImpulse(btVector3(0, 0, 0), m_rbA.getInvInertiaTensorWorld() * noTwistSwingAxis, impulseMag);
  428. bodyB.internalApplyImpulse(btVector3(0, 0, 0), m_rbB.getInvInertiaTensorWorld() * noTwistSwingAxis, -impulseMag);
  429. }
  430. // solve twist limit
  431. if (m_solveTwistLimit)
  432. {
  433. btScalar amplitude = m_twistLimitRatio * m_twistCorrection * m_biasFactor / timeStep;
  434. btScalar relTwistVel = (angVelB - angVelA).dot(m_twistAxis);
  435. if (relTwistVel > 0) // only damp when moving towards limit (m_twistAxis flipping is important)
  436. amplitude += m_twistLimitRatio * relTwistVel * m_relaxationFactor;
  437. btScalar impulseMag = amplitude * m_kTwist;
  438. // Clamp the accumulated impulse
  439. btScalar temp = m_accTwistLimitImpulse;
  440. m_accTwistLimitImpulse = btMax(m_accTwistLimitImpulse + impulseMag, btScalar(0.0));
  441. impulseMag = m_accTwistLimitImpulse - temp;
  442. // btVector3 impulse = m_twistAxis * impulseMag;
  443. bodyA.internalApplyImpulse(btVector3(0, 0, 0), m_rbA.getInvInertiaTensorWorld() * m_twistAxis, impulseMag);
  444. bodyB.internalApplyImpulse(btVector3(0, 0, 0), m_rbB.getInvInertiaTensorWorld() * m_twistAxis, -impulseMag);
  445. }
  446. }
  447. }
  448. #else
  449. btAssert(0);
  450. #endif //__SPU__
  451. }
  452. void btConeTwistConstraint::updateRHS(btScalar timeStep)
  453. {
  454. (void)timeStep;
  455. }
  456. #ifndef __SPU__
  457. void btConeTwistConstraint::calcAngleInfo()
  458. {
  459. m_swingCorrection = btScalar(0.);
  460. m_twistLimitSign = btScalar(0.);
  461. m_solveTwistLimit = false;
  462. m_solveSwingLimit = false;
  463. btVector3 b1Axis1(0, 0, 0), b1Axis2(0, 0, 0), b1Axis3(0, 0, 0);
  464. btVector3 b2Axis1(0, 0, 0), b2Axis2(0, 0, 0);
  465. b1Axis1 = getRigidBodyA().getCenterOfMassTransform().getBasis() * this->m_rbAFrame.getBasis().getColumn(0);
  466. b2Axis1 = getRigidBodyB().getCenterOfMassTransform().getBasis() * this->m_rbBFrame.getBasis().getColumn(0);
  467. btScalar swing1 = btScalar(0.), swing2 = btScalar(0.);
  468. btScalar swx = btScalar(0.), swy = btScalar(0.);
  469. btScalar thresh = btScalar(10.);
  470. btScalar fact;
  471. // Get Frame into world space
  472. if (m_swingSpan1 >= btScalar(0.05f))
  473. {
  474. b1Axis2 = getRigidBodyA().getCenterOfMassTransform().getBasis() * this->m_rbAFrame.getBasis().getColumn(1);
  475. swx = b2Axis1.dot(b1Axis1);
  476. swy = b2Axis1.dot(b1Axis2);
  477. swing1 = btAtan2Fast(swy, swx);
  478. fact = (swy * swy + swx * swx) * thresh * thresh;
  479. fact = fact / (fact + btScalar(1.0));
  480. swing1 *= fact;
  481. }
  482. if (m_swingSpan2 >= btScalar(0.05f))
  483. {
  484. b1Axis3 = getRigidBodyA().getCenterOfMassTransform().getBasis() * this->m_rbAFrame.getBasis().getColumn(2);
  485. swx = b2Axis1.dot(b1Axis1);
  486. swy = b2Axis1.dot(b1Axis3);
  487. swing2 = btAtan2Fast(swy, swx);
  488. fact = (swy * swy + swx * swx) * thresh * thresh;
  489. fact = fact / (fact + btScalar(1.0));
  490. swing2 *= fact;
  491. }
  492. btScalar RMaxAngle1Sq = 1.0f / (m_swingSpan1 * m_swingSpan1);
  493. btScalar RMaxAngle2Sq = 1.0f / (m_swingSpan2 * m_swingSpan2);
  494. btScalar EllipseAngle = btFabs(swing1 * swing1) * RMaxAngle1Sq + btFabs(swing2 * swing2) * RMaxAngle2Sq;
  495. if (EllipseAngle > 1.0f)
  496. {
  497. m_swingCorrection = EllipseAngle - 1.0f;
  498. m_solveSwingLimit = true;
  499. // Calculate necessary axis & factors
  500. m_swingAxis = b2Axis1.cross(b1Axis2 * b2Axis1.dot(b1Axis2) + b1Axis3 * b2Axis1.dot(b1Axis3));
  501. m_swingAxis.normalize();
  502. btScalar swingAxisSign = (b2Axis1.dot(b1Axis1) >= 0.0f) ? 1.0f : -1.0f;
  503. m_swingAxis *= swingAxisSign;
  504. }
  505. // Twist limits
  506. if (m_twistSpan >= btScalar(0.))
  507. {
  508. btVector3 b2Axis2 = getRigidBodyB().getCenterOfMassTransform().getBasis() * this->m_rbBFrame.getBasis().getColumn(1);
  509. btQuaternion rotationArc = shortestArcQuat(b2Axis1, b1Axis1);
  510. btVector3 TwistRef = quatRotate(rotationArc, b2Axis2);
  511. btScalar twist = btAtan2Fast(TwistRef.dot(b1Axis3), TwistRef.dot(b1Axis2));
  512. m_twistAngle = twist;
  513. // btScalar lockedFreeFactor = (m_twistSpan > btScalar(0.05f)) ? m_limitSoftness : btScalar(0.);
  514. btScalar lockedFreeFactor = (m_twistSpan > btScalar(0.05f)) ? btScalar(1.0f) : btScalar(0.);
  515. if (twist <= -m_twistSpan * lockedFreeFactor)
  516. {
  517. m_twistCorrection = -(twist + m_twistSpan);
  518. m_solveTwistLimit = true;
  519. m_twistAxis = (b2Axis1 + b1Axis1) * 0.5f;
  520. m_twistAxis.normalize();
  521. m_twistAxis *= -1.0f;
  522. }
  523. else if (twist > m_twistSpan * lockedFreeFactor)
  524. {
  525. m_twistCorrection = (twist - m_twistSpan);
  526. m_solveTwistLimit = true;
  527. m_twistAxis = (b2Axis1 + b1Axis1) * 0.5f;
  528. m_twistAxis.normalize();
  529. }
  530. }
  531. }
  532. #endif //__SPU__
  533. static btVector3 vTwist(1, 0, 0); // twist axis in constraint's space
  534. void btConeTwistConstraint::calcAngleInfo2(const btTransform& transA, const btTransform& transB, const btMatrix3x3& invInertiaWorldA, const btMatrix3x3& invInertiaWorldB)
  535. {
  536. m_swingCorrection = btScalar(0.);
  537. m_twistLimitSign = btScalar(0.);
  538. m_solveTwistLimit = false;
  539. m_solveSwingLimit = false;
  540. // compute rotation of A wrt B (in constraint space)
  541. if (m_bMotorEnabled && (!m_useSolveConstraintObsolete))
  542. { // it is assumed that setMotorTarget() was alredy called
  543. // and motor target m_qTarget is within constraint limits
  544. // TODO : split rotation to pure swing and pure twist
  545. // compute desired transforms in world
  546. btTransform trPose(m_qTarget);
  547. btTransform trA = transA * m_rbAFrame;
  548. btTransform trB = transB * m_rbBFrame;
  549. btTransform trDeltaAB = trB * trPose * trA.inverse();
  550. btQuaternion qDeltaAB = trDeltaAB.getRotation();
  551. btVector3 swingAxis = btVector3(qDeltaAB.x(), qDeltaAB.y(), qDeltaAB.z());
  552. btScalar swingAxisLen2 = swingAxis.length2();
  553. if (btFuzzyZero(swingAxisLen2))
  554. {
  555. return;
  556. }
  557. m_swingAxis = swingAxis;
  558. m_swingAxis.normalize();
  559. m_swingCorrection = qDeltaAB.getAngle();
  560. if (!btFuzzyZero(m_swingCorrection))
  561. {
  562. m_solveSwingLimit = true;
  563. }
  564. return;
  565. }
  566. {
  567. // compute rotation of A wrt B (in constraint space)
  568. btQuaternion qA = transA.getRotation() * m_rbAFrame.getRotation();
  569. btQuaternion qB = transB.getRotation() * m_rbBFrame.getRotation();
  570. btQuaternion qAB = qB.inverse() * qA;
  571. // split rotation into cone and twist
  572. // (all this is done from B's perspective. Maybe I should be averaging axes...)
  573. btVector3 vConeNoTwist = quatRotate(qAB, vTwist);
  574. vConeNoTwist.normalize();
  575. btQuaternion qABCone = shortestArcQuat(vTwist, vConeNoTwist);
  576. qABCone.normalize();
  577. btQuaternion qABTwist = qABCone.inverse() * qAB;
  578. qABTwist.normalize();
  579. if (m_swingSpan1 >= m_fixThresh && m_swingSpan2 >= m_fixThresh)
  580. {
  581. btScalar swingAngle, swingLimit = 0;
  582. btVector3 swingAxis;
  583. computeConeLimitInfo(qABCone, swingAngle, swingAxis, swingLimit);
  584. if (swingAngle > swingLimit * m_limitSoftness)
  585. {
  586. m_solveSwingLimit = true;
  587. // compute limit ratio: 0->1, where
  588. // 0 == beginning of soft limit
  589. // 1 == hard/real limit
  590. m_swingLimitRatio = 1.f;
  591. if (swingAngle < swingLimit && m_limitSoftness < 1.f - SIMD_EPSILON)
  592. {
  593. m_swingLimitRatio = (swingAngle - swingLimit * m_limitSoftness) /
  594. (swingLimit - swingLimit * m_limitSoftness);
  595. }
  596. // swing correction tries to get back to soft limit
  597. m_swingCorrection = swingAngle - (swingLimit * m_limitSoftness);
  598. // adjustment of swing axis (based on ellipse normal)
  599. adjustSwingAxisToUseEllipseNormal(swingAxis);
  600. // Calculate necessary axis & factors
  601. m_swingAxis = quatRotate(qB, -swingAxis);
  602. m_twistAxisA.setValue(0, 0, 0);
  603. m_kSwing = btScalar(1.) /
  604. (computeAngularImpulseDenominator(m_swingAxis, invInertiaWorldA) +
  605. computeAngularImpulseDenominator(m_swingAxis, invInertiaWorldB));
  606. }
  607. }
  608. else
  609. {
  610. // you haven't set any limits;
  611. // or you're trying to set at least one of the swing limits too small. (if so, do you really want a conetwist constraint?)
  612. // anyway, we have either hinge or fixed joint
  613. btVector3 ivA = transA.getBasis() * m_rbAFrame.getBasis().getColumn(0);
  614. btVector3 jvA = transA.getBasis() * m_rbAFrame.getBasis().getColumn(1);
  615. btVector3 kvA = transA.getBasis() * m_rbAFrame.getBasis().getColumn(2);
  616. btVector3 ivB = transB.getBasis() * m_rbBFrame.getBasis().getColumn(0);
  617. btVector3 target;
  618. btScalar x = ivB.dot(ivA);
  619. btScalar y = ivB.dot(jvA);
  620. btScalar z = ivB.dot(kvA);
  621. if ((m_swingSpan1 < m_fixThresh) && (m_swingSpan2 < m_fixThresh))
  622. { // fixed. We'll need to add one more row to constraint
  623. if ((!btFuzzyZero(y)) || (!(btFuzzyZero(z))))
  624. {
  625. m_solveSwingLimit = true;
  626. m_swingAxis = -ivB.cross(ivA);
  627. }
  628. }
  629. else
  630. {
  631. if (m_swingSpan1 < m_fixThresh)
  632. { // hinge around Y axis
  633. // if(!(btFuzzyZero(y)))
  634. if ((!(btFuzzyZero(x))) || (!(btFuzzyZero(z))))
  635. {
  636. m_solveSwingLimit = true;
  637. if (m_swingSpan2 >= m_fixThresh)
  638. {
  639. y = btScalar(0.f);
  640. btScalar span2 = btAtan2(z, x);
  641. if (span2 > m_swingSpan2)
  642. {
  643. x = btCos(m_swingSpan2);
  644. z = btSin(m_swingSpan2);
  645. }
  646. else if (span2 < -m_swingSpan2)
  647. {
  648. x = btCos(m_swingSpan2);
  649. z = -btSin(m_swingSpan2);
  650. }
  651. }
  652. }
  653. }
  654. else
  655. { // hinge around Z axis
  656. // if(!btFuzzyZero(z))
  657. if ((!(btFuzzyZero(x))) || (!(btFuzzyZero(y))))
  658. {
  659. m_solveSwingLimit = true;
  660. if (m_swingSpan1 >= m_fixThresh)
  661. {
  662. z = btScalar(0.f);
  663. btScalar span1 = btAtan2(y, x);
  664. if (span1 > m_swingSpan1)
  665. {
  666. x = btCos(m_swingSpan1);
  667. y = btSin(m_swingSpan1);
  668. }
  669. else if (span1 < -m_swingSpan1)
  670. {
  671. x = btCos(m_swingSpan1);
  672. y = -btSin(m_swingSpan1);
  673. }
  674. }
  675. }
  676. }
  677. target[0] = x * ivA[0] + y * jvA[0] + z * kvA[0];
  678. target[1] = x * ivA[1] + y * jvA[1] + z * kvA[1];
  679. target[2] = x * ivA[2] + y * jvA[2] + z * kvA[2];
  680. target.normalize();
  681. m_swingAxis = -ivB.cross(target);
  682. m_swingCorrection = m_swingAxis.length();
  683. if (!btFuzzyZero(m_swingCorrection))
  684. m_swingAxis.normalize();
  685. }
  686. }
  687. if (m_twistSpan >= btScalar(0.f))
  688. {
  689. btVector3 twistAxis;
  690. computeTwistLimitInfo(qABTwist, m_twistAngle, twistAxis);
  691. if (m_twistAngle > m_twistSpan * m_limitSoftness)
  692. {
  693. m_solveTwistLimit = true;
  694. m_twistLimitRatio = 1.f;
  695. if (m_twistAngle < m_twistSpan && m_limitSoftness < 1.f - SIMD_EPSILON)
  696. {
  697. m_twistLimitRatio = (m_twistAngle - m_twistSpan * m_limitSoftness) /
  698. (m_twistSpan - m_twistSpan * m_limitSoftness);
  699. }
  700. // twist correction tries to get back to soft limit
  701. m_twistCorrection = m_twistAngle - (m_twistSpan * m_limitSoftness);
  702. m_twistAxis = quatRotate(qB, -twistAxis);
  703. m_kTwist = btScalar(1.) /
  704. (computeAngularImpulseDenominator(m_twistAxis, invInertiaWorldA) +
  705. computeAngularImpulseDenominator(m_twistAxis, invInertiaWorldB));
  706. }
  707. if (m_solveSwingLimit)
  708. m_twistAxisA = quatRotate(qA, -twistAxis);
  709. }
  710. else
  711. {
  712. m_twistAngle = btScalar(0.f);
  713. }
  714. }
  715. }
  716. // given a cone rotation in constraint space, (pre: twist must already be removed)
  717. // this method computes its corresponding swing angle and axis.
  718. // more interestingly, it computes the cone/swing limit (angle) for this cone "pose".
  719. void btConeTwistConstraint::computeConeLimitInfo(const btQuaternion& qCone,
  720. btScalar& swingAngle, // out
  721. btVector3& vSwingAxis, // out
  722. btScalar& swingLimit) // out
  723. {
  724. swingAngle = qCone.getAngle();
  725. if (swingAngle > SIMD_EPSILON)
  726. {
  727. vSwingAxis = btVector3(qCone.x(), qCone.y(), qCone.z());
  728. vSwingAxis.normalize();
  729. #if 0
  730. // non-zero twist?! this should never happen.
  731. btAssert(fabs(vSwingAxis.x()) <= SIMD_EPSILON));
  732. #endif
  733. // Compute limit for given swing. tricky:
  734. // Given a swing axis, we're looking for the intersection with the bounding cone ellipse.
  735. // (Since we're dealing with angles, this ellipse is embedded on the surface of a sphere.)
  736. // For starters, compute the direction from center to surface of ellipse.
  737. // This is just the perpendicular (ie. rotate 2D vector by PI/2) of the swing axis.
  738. // (vSwingAxis is the cone rotation (in z,y); change vars and rotate to (x,y) coords.)
  739. btScalar xEllipse = vSwingAxis.y();
  740. btScalar yEllipse = -vSwingAxis.z();
  741. // Now, we use the slope of the vector (using x/yEllipse) and find the length
  742. // of the line that intersects the ellipse:
  743. // x^2 y^2
  744. // --- + --- = 1, where a and b are semi-major axes 2 and 1 respectively (ie. the limits)
  745. // a^2 b^2
  746. // Do the math and it should be clear.
  747. swingLimit = m_swingSpan1; // if xEllipse == 0, we have a pure vSwingAxis.z rotation: just use swingspan1
  748. if (fabs(xEllipse) > SIMD_EPSILON)
  749. {
  750. btScalar surfaceSlope2 = (yEllipse * yEllipse) / (xEllipse * xEllipse);
  751. btScalar norm = 1 / (m_swingSpan2 * m_swingSpan2);
  752. norm += surfaceSlope2 / (m_swingSpan1 * m_swingSpan1);
  753. btScalar swingLimit2 = (1 + surfaceSlope2) / norm;
  754. swingLimit = std::sqrt(swingLimit2);
  755. }
  756. // test!
  757. /*swingLimit = m_swingSpan2;
  758. if (fabs(vSwingAxis.z()) > SIMD_EPSILON)
  759. {
  760. btScalar mag_2 = m_swingSpan1*m_swingSpan1 + m_swingSpan2*m_swingSpan2;
  761. btScalar sinphi = m_swingSpan2 / sqrt(mag_2);
  762. btScalar phi = asin(sinphi);
  763. btScalar theta = atan2(fabs(vSwingAxis.y()),fabs(vSwingAxis.z()));
  764. btScalar alpha = 3.14159f - theta - phi;
  765. btScalar sinalpha = sin(alpha);
  766. swingLimit = m_swingSpan1 * sinphi/sinalpha;
  767. }*/
  768. }
  769. else if (swingAngle < 0)
  770. {
  771. // this should never happen!
  772. #if 0
  773. btAssert(0);
  774. #endif
  775. }
  776. }
  777. btVector3 btConeTwistConstraint::GetPointForAngle(btScalar fAngleInRadians, btScalar fLength) const
  778. {
  779. // compute x/y in ellipse using cone angle (0 -> 2*PI along surface of cone)
  780. btScalar xEllipse = btCos(fAngleInRadians);
  781. btScalar yEllipse = btSin(fAngleInRadians);
  782. // Use the slope of the vector (using x/yEllipse) and find the length
  783. // of the line that intersects the ellipse:
  784. // x^2 y^2
  785. // --- + --- = 1, where a and b are semi-major axes 2 and 1 respectively (ie. the limits)
  786. // a^2 b^2
  787. // Do the math and it should be clear.
  788. btScalar swingLimit = m_swingSpan1; // if xEllipse == 0, just use axis b (1)
  789. if (fabs(xEllipse) > SIMD_EPSILON)
  790. {
  791. btScalar surfaceSlope2 = (yEllipse * yEllipse) / (xEllipse * xEllipse);
  792. btScalar norm = 1 / (m_swingSpan2 * m_swingSpan2);
  793. norm += surfaceSlope2 / (m_swingSpan1 * m_swingSpan1);
  794. btScalar swingLimit2 = (1 + surfaceSlope2) / norm;
  795. swingLimit = std::sqrt(swingLimit2);
  796. }
  797. // convert into point in constraint space:
  798. // note: twist is x-axis, swing 1 and 2 are along the z and y axes respectively
  799. btVector3 vSwingAxis(0, xEllipse, -yEllipse);
  800. btQuaternion qSwing(vSwingAxis, swingLimit);
  801. btVector3 vPointInConstraintSpace(fLength, 0, 0);
  802. return quatRotate(qSwing, vPointInConstraintSpace);
  803. }
  804. // given a twist rotation in constraint space, (pre: cone must already be removed)
  805. // this method computes its corresponding angle and axis.
  806. void btConeTwistConstraint::computeTwistLimitInfo(const btQuaternion& qTwist,
  807. btScalar& twistAngle, // out
  808. btVector3& vTwistAxis) // out
  809. {
  810. btQuaternion qMinTwist = qTwist;
  811. twistAngle = qTwist.getAngle();
  812. if (twistAngle > SIMD_PI) // long way around. flip quat and recalculate.
  813. {
  814. qMinTwist = -(qTwist);
  815. twistAngle = qMinTwist.getAngle();
  816. }
  817. if (twistAngle < 0)
  818. {
  819. // this should never happen
  820. #if 0
  821. btAssert(0);
  822. #endif
  823. }
  824. vTwistAxis = btVector3(qMinTwist.x(), qMinTwist.y(), qMinTwist.z());
  825. if (twistAngle > SIMD_EPSILON)
  826. vTwistAxis.normalize();
  827. }
  828. void btConeTwistConstraint::adjustSwingAxisToUseEllipseNormal(btVector3& vSwingAxis) const
  829. {
  830. // the swing axis is computed as the "twist-free" cone rotation,
  831. // but the cone limit is not circular, but elliptical (if swingspan1 != swingspan2).
  832. // so, if we're outside the limits, the closest way back inside the cone isn't
  833. // along the vector back to the center. better (and more stable) to use the ellipse normal.
  834. // convert swing axis to direction from center to surface of ellipse
  835. // (ie. rotate 2D vector by PI/2)
  836. btScalar y = -vSwingAxis.z();
  837. btScalar z = vSwingAxis.y();
  838. // do the math...
  839. if (fabs(z) > SIMD_EPSILON) // avoid division by 0. and we don't need an update if z == 0.
  840. {
  841. // compute gradient/normal of ellipse surface at current "point"
  842. btScalar grad = y / z;
  843. grad *= m_swingSpan2 / m_swingSpan1;
  844. // adjust y/z to represent normal at point (instead of vector to point)
  845. if (y > 0)
  846. y = fabs(grad * z);
  847. else
  848. y = -fabs(grad * z);
  849. // convert ellipse direction back to swing axis
  850. vSwingAxis.setZ(-y);
  851. vSwingAxis.setY(z);
  852. vSwingAxis.normalize();
  853. }
  854. }
  855. void btConeTwistConstraint::setMotorTarget(const btQuaternion& q)
  856. {
  857. //btTransform trACur = m_rbA.getCenterOfMassTransform();
  858. //btTransform trBCur = m_rbB.getCenterOfMassTransform();
  859. // btTransform trABCur = trBCur.inverse() * trACur;
  860. // btQuaternion qABCur = trABCur.getRotation();
  861. // btTransform trConstraintCur = (trBCur * m_rbBFrame).inverse() * (trACur * m_rbAFrame);
  862. //btQuaternion qConstraintCur = trConstraintCur.getRotation();
  863. btQuaternion qConstraint = m_rbBFrame.getRotation().inverse() * q * m_rbAFrame.getRotation();
  864. setMotorTargetInConstraintSpace(qConstraint);
  865. }
  866. void btConeTwistConstraint::setMotorTargetInConstraintSpace(const btQuaternion& q)
  867. {
  868. m_qTarget = q;
  869. // clamp motor target to within limits
  870. {
  871. btScalar softness = 1.f; //m_limitSoftness;
  872. // split into twist and cone
  873. btVector3 vTwisted = quatRotate(m_qTarget, vTwist);
  874. btQuaternion qTargetCone = shortestArcQuat(vTwist, vTwisted);
  875. qTargetCone.normalize();
  876. btQuaternion qTargetTwist = qTargetCone.inverse() * m_qTarget;
  877. qTargetTwist.normalize();
  878. // clamp cone
  879. if (m_swingSpan1 >= btScalar(0.05f) && m_swingSpan2 >= btScalar(0.05f))
  880. {
  881. btScalar swingAngle, swingLimit;
  882. btVector3 swingAxis;
  883. computeConeLimitInfo(qTargetCone, swingAngle, swingAxis, swingLimit);
  884. if (fabs(swingAngle) > SIMD_EPSILON)
  885. {
  886. if (swingAngle > swingLimit * softness)
  887. swingAngle = swingLimit * softness;
  888. else if (swingAngle < -swingLimit * softness)
  889. swingAngle = -swingLimit * softness;
  890. qTargetCone = btQuaternion(swingAxis, swingAngle);
  891. }
  892. }
  893. // clamp twist
  894. if (m_twistSpan >= btScalar(0.05f))
  895. {
  896. btScalar twistAngle;
  897. btVector3 twistAxis;
  898. computeTwistLimitInfo(qTargetTwist, twistAngle, twistAxis);
  899. if (fabs(twistAngle) > SIMD_EPSILON)
  900. {
  901. // eddy todo: limitSoftness used here???
  902. if (twistAngle > m_twistSpan * softness)
  903. twistAngle = m_twistSpan * softness;
  904. else if (twistAngle < -m_twistSpan * softness)
  905. twistAngle = -m_twistSpan * softness;
  906. qTargetTwist = btQuaternion(twistAxis, twistAngle);
  907. }
  908. }
  909. m_qTarget = qTargetCone * qTargetTwist;
  910. }
  911. }
  912. ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
  913. ///If no axis is provided, it uses the default axis for this constraint.
  914. void btConeTwistConstraint::setParam(int num, btScalar value, int axis)
  915. {
  916. switch (num)
  917. {
  918. case BT_CONSTRAINT_ERP:
  919. case BT_CONSTRAINT_STOP_ERP:
  920. if ((axis >= 0) && (axis < 3))
  921. {
  922. m_linERP = value;
  923. m_flags |= BT_CONETWIST_FLAGS_LIN_ERP;
  924. }
  925. else
  926. {
  927. m_biasFactor = value;
  928. }
  929. break;
  930. case BT_CONSTRAINT_CFM:
  931. case BT_CONSTRAINT_STOP_CFM:
  932. if ((axis >= 0) && (axis < 3))
  933. {
  934. m_linCFM = value;
  935. m_flags |= BT_CONETWIST_FLAGS_LIN_CFM;
  936. }
  937. else
  938. {
  939. m_angCFM = value;
  940. m_flags |= BT_CONETWIST_FLAGS_ANG_CFM;
  941. }
  942. break;
  943. default:
  944. btAssertConstrParams(0);
  945. break;
  946. }
  947. }
  948. ///return the local value of parameter
  949. btScalar btConeTwistConstraint::getParam(int num, int axis) const
  950. {
  951. btScalar retVal = 0;
  952. switch (num)
  953. {
  954. case BT_CONSTRAINT_ERP:
  955. case BT_CONSTRAINT_STOP_ERP:
  956. if ((axis >= 0) && (axis < 3))
  957. {
  958. btAssertConstrParams(m_flags & BT_CONETWIST_FLAGS_LIN_ERP);
  959. retVal = m_linERP;
  960. }
  961. else if ((axis >= 3) && (axis < 6))
  962. {
  963. retVal = m_biasFactor;
  964. }
  965. else
  966. {
  967. btAssertConstrParams(0);
  968. }
  969. break;
  970. case BT_CONSTRAINT_CFM:
  971. case BT_CONSTRAINT_STOP_CFM:
  972. if ((axis >= 0) && (axis < 3))
  973. {
  974. btAssertConstrParams(m_flags & BT_CONETWIST_FLAGS_LIN_CFM);
  975. retVal = m_linCFM;
  976. }
  977. else if ((axis >= 3) && (axis < 6))
  978. {
  979. btAssertConstrParams(m_flags & BT_CONETWIST_FLAGS_ANG_CFM);
  980. retVal = m_angCFM;
  981. }
  982. else
  983. {
  984. btAssertConstrParams(0);
  985. }
  986. break;
  987. default:
  988. btAssertConstrParams(0);
  989. }
  990. return retVal;
  991. }
  992. void btConeTwistConstraint::setFrames(const btTransform& frameA, const btTransform& frameB)
  993. {
  994. m_rbAFrame = frameA;
  995. m_rbBFrame = frameB;
  996. buildJacobian();
  997. //calculateTransforms();
  998. }