The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

636 lines
17KB

  1. /*
  2. * Copyright (c) 2006-2011 Erin Catto http://www.box2d.org
  3. *
  4. * This software is provided 'as-is', without any express or implied
  5. * warranty. In no event will the authors be held liable for any damages
  6. * arising from the use of this software.
  7. * Permission is granted to anyone to use this software for any purpose,
  8. * including commercial applications, and to alter it and redistribute it
  9. * freely, subject to the following restrictions:
  10. * 1. The origin of this software must not be misrepresented; you must not
  11. * claim that you wrote the original software. If you use this software
  12. * in a product, an acknowledgment in the product documentation would be
  13. * appreciated but is not required.
  14. * 2. Altered source versions must be plainly marked as such, and must not be
  15. * misrepresented as being the original software.
  16. * 3. This notice may not be removed or altered from any source distribution.
  17. */
  18. #include "b2PrismaticJoint.h"
  19. #include "../b2Body.h"
  20. #include "../b2TimeStep.h"
  21. // Linear constraint (point-to-line)
  22. // d = p2 - p1 = x2 + r2 - x1 - r1
  23. // C = dot(perp, d)
  24. // Cdot = dot(d, cross(w1, perp)) + dot(perp, v2 + cross(w2, r2) - v1 - cross(w1, r1))
  25. // = -dot(perp, v1) - dot(cross(d + r1, perp), w1) + dot(perp, v2) + dot(cross(r2, perp), v2)
  26. // J = [-perp, -cross(d + r1, perp), perp, cross(r2,perp)]
  27. //
  28. // Angular constraint
  29. // C = a2 - a1 + a_initial
  30. // Cdot = w2 - w1
  31. // J = [0 0 -1 0 0 1]
  32. //
  33. // K = J * invM * JT
  34. //
  35. // J = [-a -s1 a s2]
  36. // [0 -1 0 1]
  37. // a = perp
  38. // s1 = cross(d + r1, a) = cross(p2 - x1, a)
  39. // s2 = cross(r2, a) = cross(p2 - x2, a)
  40. // Motor/Limit linear constraint
  41. // C = dot(ax1, d)
  42. // Cdot = = -dot(ax1, v1) - dot(cross(d + r1, ax1), w1) + dot(ax1, v2) + dot(cross(r2, ax1), v2)
  43. // J = [-ax1 -cross(d+r1,ax1) ax1 cross(r2,ax1)]
  44. // Block Solver
  45. // We develop a block solver that includes the joint limit. This makes the limit stiff (inelastic) even
  46. // when the mass has poor distribution (leading to large torques about the joint anchor points).
  47. //
  48. // The Jacobian has 3 rows:
  49. // J = [-uT -s1 uT s2] // linear
  50. // [0 -1 0 1] // angular
  51. // [-vT -a1 vT a2] // limit
  52. //
  53. // u = perp
  54. // v = axis
  55. // s1 = cross(d + r1, u), s2 = cross(r2, u)
  56. // a1 = cross(d + r1, v), a2 = cross(r2, v)
  57. // M * (v2 - v1) = JT * df
  58. // J * v2 = bias
  59. //
  60. // v2 = v1 + invM * JT * df
  61. // J * (v1 + invM * JT * df) = bias
  62. // K * df = bias - J * v1 = -Cdot
  63. // K = J * invM * JT
  64. // Cdot = J * v1 - bias
  65. //
  66. // Now solve for f2.
  67. // df = f2 - f1
  68. // K * (f2 - f1) = -Cdot
  69. // f2 = invK * (-Cdot) + f1
  70. //
  71. // Clamp accumulated limit impulse.
  72. // lower: f2(3) = max(f2(3), 0)
  73. // upper: f2(3) = min(f2(3), 0)
  74. //
  75. // Solve for correct f2(1:2)
  76. // K(1:2, 1:2) * f2(1:2) = -Cdot(1:2) - K(1:2,3) * f2(3) + K(1:2,1:3) * f1
  77. // = -Cdot(1:2) - K(1:2,3) * f2(3) + K(1:2,1:2) * f1(1:2) + K(1:2,3) * f1(3)
  78. // K(1:2, 1:2) * f2(1:2) = -Cdot(1:2) - K(1:2,3) * (f2(3) - f1(3)) + K(1:2,1:2) * f1(1:2)
  79. // f2(1:2) = invK(1:2,1:2) * (-Cdot(1:2) - K(1:2,3) * (f2(3) - f1(3))) + f1(1:2)
  80. //
  81. // Now compute impulse to be applied:
  82. // df = f2 - f1
  83. void b2PrismaticJointDef::Initialize(b2Body* bA, b2Body* bB, const b2Vec2& anchor, const b2Vec2& axis)
  84. {
  85. bodyA = bA;
  86. bodyB = bB;
  87. localAnchorA = bodyA->GetLocalPoint(anchor);
  88. localAnchorB = bodyB->GetLocalPoint(anchor);
  89. localAxisA = bodyA->GetLocalVector(axis);
  90. referenceAngle = bodyB->GetAngle() - bodyA->GetAngle();
  91. }
  92. b2PrismaticJoint::b2PrismaticJoint(const b2PrismaticJointDef* def)
  93. : b2Joint(def)
  94. {
  95. m_localAnchorA = def->localAnchorA;
  96. m_localAnchorB = def->localAnchorB;
  97. m_localXAxisA = def->localAxisA;
  98. m_localXAxisA.Normalize();
  99. m_localYAxisA = b2Cross(1.0f, m_localXAxisA);
  100. m_referenceAngle = def->referenceAngle;
  101. m_impulse.SetZero();
  102. m_motorMass = 0.0f;
  103. m_motorImpulse = 0.0f;
  104. m_lowerTranslation = def->lowerTranslation;
  105. m_upperTranslation = def->upperTranslation;
  106. m_maxMotorForce = def->maxMotorForce;
  107. m_motorSpeed = def->motorSpeed;
  108. m_enableLimit = def->enableLimit;
  109. m_enableMotor = def->enableMotor;
  110. m_limitState = e_inactiveLimit;
  111. m_axis.SetZero();
  112. m_perp.SetZero();
  113. }
  114. void b2PrismaticJoint::InitVelocityConstraints(const b2SolverData& data)
  115. {
  116. m_indexA = m_bodyA->m_islandIndex;
  117. m_indexB = m_bodyB->m_islandIndex;
  118. m_localCenterA = m_bodyA->m_sweep.localCenter;
  119. m_localCenterB = m_bodyB->m_sweep.localCenter;
  120. m_invMassA = m_bodyA->m_invMass;
  121. m_invMassB = m_bodyB->m_invMass;
  122. m_invIA = m_bodyA->m_invI;
  123. m_invIB = m_bodyB->m_invI;
  124. b2Vec2 cA = data.positions[m_indexA].c;
  125. float32 aA = data.positions[m_indexA].a;
  126. b2Vec2 vA = data.velocities[m_indexA].v;
  127. float32 wA = data.velocities[m_indexA].w;
  128. b2Vec2 cB = data.positions[m_indexB].c;
  129. float32 aB = data.positions[m_indexB].a;
  130. b2Vec2 vB = data.velocities[m_indexB].v;
  131. float32 wB = data.velocities[m_indexB].w;
  132. b2Rot qA(aA), qB(aB);
  133. // Compute the effective masses.
  134. b2Vec2 rA = b2Mul(qA, m_localAnchorA - m_localCenterA);
  135. b2Vec2 rB = b2Mul(qB, m_localAnchorB - m_localCenterB);
  136. b2Vec2 d = (cB - cA) + rB - rA;
  137. float32 mA = m_invMassA, mB = m_invMassB;
  138. float32 iA = m_invIA, iB = m_invIB;
  139. // Compute motor Jacobian and effective mass.
  140. {
  141. m_axis = b2Mul(qA, m_localXAxisA);
  142. m_a1 = b2Cross(d + rA, m_axis);
  143. m_a2 = b2Cross(rB, m_axis);
  144. m_motorMass = mA + mB + iA * m_a1 * m_a1 + iB * m_a2 * m_a2;
  145. if (m_motorMass > 0.0f)
  146. {
  147. m_motorMass = 1.0f / m_motorMass;
  148. }
  149. }
  150. // Prismatic constraint.
  151. {
  152. m_perp = b2Mul(qA, m_localYAxisA);
  153. m_s1 = b2Cross(d + rA, m_perp);
  154. m_s2 = b2Cross(rB, m_perp);
  155. float32 k11 = mA + mB + iA * m_s1 * m_s1 + iB * m_s2 * m_s2;
  156. float32 k12 = iA * m_s1 + iB * m_s2;
  157. float32 k13 = iA * m_s1 * m_a1 + iB * m_s2 * m_a2;
  158. float32 k22 = iA + iB;
  159. if (k22 == 0.0f)
  160. {
  161. // For bodies with fixed rotation.
  162. k22 = 1.0f;
  163. }
  164. float32 k23 = iA * m_a1 + iB * m_a2;
  165. float32 k33 = mA + mB + iA * m_a1 * m_a1 + iB * m_a2 * m_a2;
  166. m_K.ex.Set(k11, k12, k13);
  167. m_K.ey.Set(k12, k22, k23);
  168. m_K.ez.Set(k13, k23, k33);
  169. }
  170. // Compute motor and limit terms.
  171. if (m_enableLimit)
  172. {
  173. float32 jointTranslation = b2Dot(m_axis, d);
  174. if (b2Abs(m_upperTranslation - m_lowerTranslation) < 2.0f * b2_linearSlop)
  175. {
  176. m_limitState = e_equalLimits;
  177. }
  178. else if (jointTranslation <= m_lowerTranslation)
  179. {
  180. if (m_limitState != e_atLowerLimit)
  181. {
  182. m_limitState = e_atLowerLimit;
  183. m_impulse.z = 0.0f;
  184. }
  185. }
  186. else if (jointTranslation >= m_upperTranslation)
  187. {
  188. if (m_limitState != e_atUpperLimit)
  189. {
  190. m_limitState = e_atUpperLimit;
  191. m_impulse.z = 0.0f;
  192. }
  193. }
  194. else
  195. {
  196. m_limitState = e_inactiveLimit;
  197. m_impulse.z = 0.0f;
  198. }
  199. }
  200. else
  201. {
  202. m_limitState = e_inactiveLimit;
  203. m_impulse.z = 0.0f;
  204. }
  205. if (m_enableMotor == false)
  206. {
  207. m_motorImpulse = 0.0f;
  208. }
  209. if (data.step.warmStarting)
  210. {
  211. // Account for variable time step.
  212. m_impulse *= data.step.dtRatio;
  213. m_motorImpulse *= data.step.dtRatio;
  214. b2Vec2 P = m_impulse.x * m_perp + (m_motorImpulse + m_impulse.z) * m_axis;
  215. float32 LA = m_impulse.x * m_s1 + m_impulse.y + (m_motorImpulse + m_impulse.z) * m_a1;
  216. float32 LB = m_impulse.x * m_s2 + m_impulse.y + (m_motorImpulse + m_impulse.z) * m_a2;
  217. vA -= mA * P;
  218. wA -= iA * LA;
  219. vB += mB * P;
  220. wB += iB * LB;
  221. }
  222. else
  223. {
  224. m_impulse.SetZero();
  225. m_motorImpulse = 0.0f;
  226. }
  227. data.velocities[m_indexA].v = vA;
  228. data.velocities[m_indexA].w = wA;
  229. data.velocities[m_indexB].v = vB;
  230. data.velocities[m_indexB].w = wB;
  231. }
  232. void b2PrismaticJoint::SolveVelocityConstraints(const b2SolverData& data)
  233. {
  234. b2Vec2 vA = data.velocities[m_indexA].v;
  235. float32 wA = data.velocities[m_indexA].w;
  236. b2Vec2 vB = data.velocities[m_indexB].v;
  237. float32 wB = data.velocities[m_indexB].w;
  238. float32 mA = m_invMassA, mB = m_invMassB;
  239. float32 iA = m_invIA, iB = m_invIB;
  240. // Solve linear motor constraint.
  241. if (m_enableMotor && m_limitState != e_equalLimits)
  242. {
  243. float32 Cdot = b2Dot(m_axis, vB - vA) + m_a2 * wB - m_a1 * wA;
  244. float32 impulse = m_motorMass * (m_motorSpeed - Cdot);
  245. float32 oldImpulse = m_motorImpulse;
  246. float32 maxImpulse = data.step.dt * m_maxMotorForce;
  247. m_motorImpulse = b2Clamp(m_motorImpulse + impulse, -maxImpulse, maxImpulse);
  248. impulse = m_motorImpulse - oldImpulse;
  249. b2Vec2 P = impulse * m_axis;
  250. float32 LA = impulse * m_a1;
  251. float32 LB = impulse * m_a2;
  252. vA -= mA * P;
  253. wA -= iA * LA;
  254. vB += mB * P;
  255. wB += iB * LB;
  256. }
  257. b2Vec2 Cdot1;
  258. Cdot1.x = b2Dot(m_perp, vB - vA) + m_s2 * wB - m_s1 * wA;
  259. Cdot1.y = wB - wA;
  260. if (m_enableLimit && m_limitState != e_inactiveLimit)
  261. {
  262. // Solve prismatic and limit constraint in block form.
  263. float32 Cdot2;
  264. Cdot2 = b2Dot(m_axis, vB - vA) + m_a2 * wB - m_a1 * wA;
  265. b2Vec3 Cdot(Cdot1.x, Cdot1.y, Cdot2);
  266. b2Vec3 f1 = m_impulse;
  267. b2Vec3 df = m_K.Solve33(-Cdot);
  268. m_impulse += df;
  269. if (m_limitState == e_atLowerLimit)
  270. {
  271. m_impulse.z = b2Max(m_impulse.z, 0.0f);
  272. }
  273. else if (m_limitState == e_atUpperLimit)
  274. {
  275. m_impulse.z = b2Min(m_impulse.z, 0.0f);
  276. }
  277. // f2(1:2) = invK(1:2,1:2) * (-Cdot(1:2) - K(1:2,3) * (f2(3) - f1(3))) + f1(1:2)
  278. b2Vec2 b = -Cdot1 - (m_impulse.z - f1.z) * b2Vec2(m_K.ez.x, m_K.ez.y);
  279. b2Vec2 f2r = m_K.Solve22(b) + b2Vec2(f1.x, f1.y);
  280. m_impulse.x = f2r.x;
  281. m_impulse.y = f2r.y;
  282. df = m_impulse - f1;
  283. b2Vec2 P = df.x * m_perp + df.z * m_axis;
  284. float32 LA = df.x * m_s1 + df.y + df.z * m_a1;
  285. float32 LB = df.x * m_s2 + df.y + df.z * m_a2;
  286. vA -= mA * P;
  287. wA -= iA * LA;
  288. vB += mB * P;
  289. wB += iB * LB;
  290. }
  291. else
  292. {
  293. // Limit is inactive, just solve the prismatic constraint in block form.
  294. b2Vec2 df = m_K.Solve22(-Cdot1);
  295. m_impulse.x += df.x;
  296. m_impulse.y += df.y;
  297. b2Vec2 P = df.x * m_perp;
  298. float32 LA = df.x * m_s1 + df.y;
  299. float32 LB = df.x * m_s2 + df.y;
  300. vA -= mA * P;
  301. wA -= iA * LA;
  302. vB += mB * P;
  303. wB += iB * LB;
  304. Cdot1.x = b2Dot(m_perp, vB - vA) + m_s2 * wB - m_s1 * wA;
  305. Cdot1.y = wB - wA;
  306. /*if (b2Abs(Cdot1.x) > 0.01f || b2Abs(Cdot1.y) > 0.01f)
  307. {
  308. b2Vec2 test = b2Mul22(m_K, df);
  309. Cdot1.x += 0.0f;
  310. }*/
  311. }
  312. data.velocities[m_indexA].v = vA;
  313. data.velocities[m_indexA].w = wA;
  314. data.velocities[m_indexB].v = vB;
  315. data.velocities[m_indexB].w = wB;
  316. }
  317. bool b2PrismaticJoint::SolvePositionConstraints(const b2SolverData& data)
  318. {
  319. b2Vec2 cA = data.positions[m_indexA].c;
  320. float32 aA = data.positions[m_indexA].a;
  321. b2Vec2 cB = data.positions[m_indexB].c;
  322. float32 aB = data.positions[m_indexB].a;
  323. b2Rot qA(aA), qB(aB);
  324. float32 mA = m_invMassA, mB = m_invMassB;
  325. float32 iA = m_invIA, iB = m_invIB;
  326. // Compute fresh Jacobians
  327. b2Vec2 rA = b2Mul(qA, m_localAnchorA - m_localCenterA);
  328. b2Vec2 rB = b2Mul(qB, m_localAnchorB - m_localCenterB);
  329. b2Vec2 d = cB + rB - cA - rA;
  330. b2Vec2 axis = b2Mul(qA, m_localXAxisA);
  331. float32 a1 = b2Cross(d + rA, axis);
  332. float32 a2 = b2Cross(rB, axis);
  333. b2Vec2 perp = b2Mul(qA, m_localYAxisA);
  334. float32 s1 = b2Cross(d + rA, perp);
  335. float32 s2 = b2Cross(rB, perp);
  336. b2Vec3 impulse;
  337. b2Vec2 C1;
  338. C1.x = b2Dot(perp, d);
  339. C1.y = aB - aA - m_referenceAngle;
  340. float32 linearError = b2Abs(C1.x);
  341. float32 angularError = b2Abs(C1.y);
  342. bool active = false;
  343. float32 C2 = 0.0f;
  344. if (m_enableLimit)
  345. {
  346. float32 translation = b2Dot(axis, d);
  347. if (b2Abs(m_upperTranslation - m_lowerTranslation) < 2.0f * b2_linearSlop)
  348. {
  349. // Prevent large angular corrections
  350. C2 = b2Clamp(translation, -b2_maxLinearCorrection, b2_maxLinearCorrection);
  351. linearError = b2Max(linearError, b2Abs(translation));
  352. active = true;
  353. }
  354. else if (translation <= m_lowerTranslation)
  355. {
  356. // Prevent large linear corrections and allow some slop.
  357. C2 = b2Clamp(translation - m_lowerTranslation + b2_linearSlop, -b2_maxLinearCorrection, 0.0f);
  358. linearError = b2Max(linearError, m_lowerTranslation - translation);
  359. active = true;
  360. }
  361. else if (translation >= m_upperTranslation)
  362. {
  363. // Prevent large linear corrections and allow some slop.
  364. C2 = b2Clamp(translation - m_upperTranslation - b2_linearSlop, 0.0f, b2_maxLinearCorrection);
  365. linearError = b2Max(linearError, translation - m_upperTranslation);
  366. active = true;
  367. }
  368. }
  369. if (active)
  370. {
  371. float32 k11 = mA + mB + iA * s1 * s1 + iB * s2 * s2;
  372. float32 k12 = iA * s1 + iB * s2;
  373. float32 k13 = iA * s1 * a1 + iB * s2 * a2;
  374. float32 k22 = iA + iB;
  375. if (k22 == 0.0f)
  376. {
  377. // For fixed rotation
  378. k22 = 1.0f;
  379. }
  380. float32 k23 = iA * a1 + iB * a2;
  381. float32 k33 = mA + mB + iA * a1 * a1 + iB * a2 * a2;
  382. b2Mat33 K;
  383. K.ex.Set(k11, k12, k13);
  384. K.ey.Set(k12, k22, k23);
  385. K.ez.Set(k13, k23, k33);
  386. b2Vec3 C;
  387. C.x = C1.x;
  388. C.y = C1.y;
  389. C.z = C2;
  390. impulse = K.Solve33(-C);
  391. }
  392. else
  393. {
  394. float32 k11 = mA + mB + iA * s1 * s1 + iB * s2 * s2;
  395. float32 k12 = iA * s1 + iB * s2;
  396. float32 k22 = iA + iB;
  397. if (k22 == 0.0f)
  398. {
  399. k22 = 1.0f;
  400. }
  401. b2Mat22 K;
  402. K.ex.Set(k11, k12);
  403. K.ey.Set(k12, k22);
  404. b2Vec2 impulse1 = K.Solve(-C1);
  405. impulse.x = impulse1.x;
  406. impulse.y = impulse1.y;
  407. impulse.z = 0.0f;
  408. }
  409. b2Vec2 P = impulse.x * perp + impulse.z * axis;
  410. float32 LA = impulse.x * s1 + impulse.y + impulse.z * a1;
  411. float32 LB = impulse.x * s2 + impulse.y + impulse.z * a2;
  412. cA -= mA * P;
  413. aA -= iA * LA;
  414. cB += mB * P;
  415. aB += iB * LB;
  416. data.positions[m_indexA].c = cA;
  417. data.positions[m_indexA].a = aA;
  418. data.positions[m_indexB].c = cB;
  419. data.positions[m_indexB].a = aB;
  420. return linearError <= b2_linearSlop && angularError <= b2_angularSlop;
  421. }
  422. b2Vec2 b2PrismaticJoint::GetAnchorA() const
  423. {
  424. return m_bodyA->GetWorldPoint(m_localAnchorA);
  425. }
  426. b2Vec2 b2PrismaticJoint::GetAnchorB() const
  427. {
  428. return m_bodyB->GetWorldPoint(m_localAnchorB);
  429. }
  430. b2Vec2 b2PrismaticJoint::GetReactionForce(float32 inv_dt) const
  431. {
  432. return inv_dt * (m_impulse.x * m_perp + (m_motorImpulse + m_impulse.z) * m_axis);
  433. }
  434. float32 b2PrismaticJoint::GetReactionTorque(float32 inv_dt) const
  435. {
  436. return inv_dt * m_impulse.y;
  437. }
  438. float32 b2PrismaticJoint::GetJointTranslation() const
  439. {
  440. b2Vec2 pA = m_bodyA->GetWorldPoint(m_localAnchorA);
  441. b2Vec2 pB = m_bodyB->GetWorldPoint(m_localAnchorB);
  442. b2Vec2 d = pB - pA;
  443. b2Vec2 axis = m_bodyA->GetWorldVector(m_localXAxisA);
  444. float32 translation = b2Dot(d, axis);
  445. return translation;
  446. }
  447. float32 b2PrismaticJoint::GetJointSpeed() const
  448. {
  449. b2Body* bA = m_bodyA;
  450. b2Body* bB = m_bodyB;
  451. b2Vec2 rA = b2Mul(bA->m_xf.q, m_localAnchorA - bA->m_sweep.localCenter);
  452. b2Vec2 rB = b2Mul(bB->m_xf.q, m_localAnchorB - bB->m_sweep.localCenter);
  453. b2Vec2 p1 = bA->m_sweep.c + rA;
  454. b2Vec2 p2 = bB->m_sweep.c + rB;
  455. b2Vec2 d = p2 - p1;
  456. b2Vec2 axis = b2Mul(bA->m_xf.q, m_localXAxisA);
  457. b2Vec2 vA = bA->m_linearVelocity;
  458. b2Vec2 vB = bB->m_linearVelocity;
  459. float32 wA = bA->m_angularVelocity;
  460. float32 wB = bB->m_angularVelocity;
  461. float32 speed = b2Dot(d, b2Cross(wA, axis)) + b2Dot(axis, vB + b2Cross(wB, rB) - vA - b2Cross(wA, rA));
  462. return speed;
  463. }
  464. bool b2PrismaticJoint::IsLimitEnabled() const
  465. {
  466. return m_enableLimit;
  467. }
  468. void b2PrismaticJoint::EnableLimit(bool flag)
  469. {
  470. if (flag != m_enableLimit)
  471. {
  472. m_bodyA->SetAwake(true);
  473. m_bodyB->SetAwake(true);
  474. m_enableLimit = flag;
  475. m_impulse.z = 0.0f;
  476. }
  477. }
  478. float32 b2PrismaticJoint::GetLowerLimit() const
  479. {
  480. return m_lowerTranslation;
  481. }
  482. float32 b2PrismaticJoint::GetUpperLimit() const
  483. {
  484. return m_upperTranslation;
  485. }
  486. void b2PrismaticJoint::SetLimits(float32 lower, float32 upper)
  487. {
  488. b2Assert(lower <= upper);
  489. if (lower != m_lowerTranslation || upper != m_upperTranslation)
  490. {
  491. m_bodyA->SetAwake(true);
  492. m_bodyB->SetAwake(true);
  493. m_lowerTranslation = lower;
  494. m_upperTranslation = upper;
  495. m_impulse.z = 0.0f;
  496. }
  497. }
  498. bool b2PrismaticJoint::IsMotorEnabled() const
  499. {
  500. return m_enableMotor;
  501. }
  502. void b2PrismaticJoint::EnableMotor(bool flag)
  503. {
  504. m_bodyA->SetAwake(true);
  505. m_bodyB->SetAwake(true);
  506. m_enableMotor = flag;
  507. }
  508. void b2PrismaticJoint::SetMotorSpeed(float32 speed)
  509. {
  510. m_bodyA->SetAwake(true);
  511. m_bodyB->SetAwake(true);
  512. m_motorSpeed = speed;
  513. }
  514. void b2PrismaticJoint::SetMaxMotorForce(float32 force)
  515. {
  516. m_bodyA->SetAwake(true);
  517. m_bodyB->SetAwake(true);
  518. m_maxMotorForce = force;
  519. }
  520. float32 b2PrismaticJoint::GetMotorForce(float32 inv_dt) const
  521. {
  522. return inv_dt * m_motorImpulse;
  523. }
  524. void b2PrismaticJoint::Dump()
  525. {
  526. int32 indexA = m_bodyA->m_islandIndex;
  527. int32 indexB = m_bodyB->m_islandIndex;
  528. b2Log(" b2PrismaticJointDef jd;\n");
  529. b2Log(" jd.bodyA = bodies[%d];\n", indexA);
  530. b2Log(" jd.bodyB = bodies[%d];\n", indexB);
  531. b2Log(" jd.collideConnected = bool(%d);\n", m_collideConnected);
  532. b2Log(" jd.localAnchorA.Set(%.15lef, %.15lef);\n", m_localAnchorA.x, m_localAnchorA.y);
  533. b2Log(" jd.localAnchorB.Set(%.15lef, %.15lef);\n", m_localAnchorB.x, m_localAnchorB.y);
  534. b2Log(" jd.localAxisA.Set(%.15lef, %.15lef);\n", m_localXAxisA.x, m_localXAxisA.y);
  535. b2Log(" jd.referenceAngle = %.15lef;\n", m_referenceAngle);
  536. b2Log(" jd.enableLimit = bool(%d);\n", m_enableLimit);
  537. b2Log(" jd.lowerTranslation = %.15lef;\n", m_lowerTranslation);
  538. b2Log(" jd.upperTranslation = %.15lef;\n", m_upperTranslation);
  539. b2Log(" jd.enableMotor = bool(%d);\n", m_enableMotor);
  540. b2Log(" jd.motorSpeed = %.15lef;\n", m_motorSpeed);
  541. b2Log(" jd.maxMotorForce = %.15lef;\n", m_maxMotorForce);
  542. b2Log(" joints[%d] = m_world->CreateJoint(&jd);\n", m_index);
  543. }