b2MouseJoint.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. /*
  2. * Copyright (c) 2006-2007 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 <Box2D/Dynamics/Joints/b2MouseJoint.h>
  19. #include <Box2D/Dynamics/b2Body.h>
  20. #include <Box2D/Dynamics/b2TimeStep.h>
  21. // p = attached point, m = mouse point
  22. // C = p - m
  23. // Cdot = v
  24. // = v + cross(w, r)
  25. // J = [I r_skew]
  26. // Identity used:
  27. // w k % (rx i + ry j) = w * (-ry i + rx j)
  28. b2MouseJoint::b2MouseJoint(const b2MouseJointDef* def)
  29. : b2Joint(def)
  30. {
  31. b2Assert(def->target.IsValid());
  32. b2Assert(b2IsValid(def->maxForce) && def->maxForce >= 0.0f);
  33. b2Assert(b2IsValid(def->frequencyHz) && def->frequencyHz >= 0.0f);
  34. b2Assert(b2IsValid(def->dampingRatio) && def->dampingRatio >= 0.0f);
  35. m_targetA = def->target;
  36. m_localAnchorB = b2MulT(m_bodyB->GetTransform(), m_targetA);
  37. m_maxForce = def->maxForce;
  38. m_impulse.SetZero();
  39. m_frequencyHz = def->frequencyHz;
  40. m_dampingRatio = def->dampingRatio;
  41. m_beta = 0.0f;
  42. m_gamma = 0.0f;
  43. }
  44. void b2MouseJoint::SetTarget(const b2Vec2& target)
  45. {
  46. if (m_bodyB->IsAwake() == false)
  47. {
  48. m_bodyB->SetAwake(true);
  49. }
  50. m_targetA = target;
  51. }
  52. const b2Vec2& b2MouseJoint::GetTarget() const
  53. {
  54. return m_targetA;
  55. }
  56. void b2MouseJoint::SetMaxForce(float32 force)
  57. {
  58. m_maxForce = force;
  59. }
  60. float32 b2MouseJoint::GetMaxForce() const
  61. {
  62. return m_maxForce;
  63. }
  64. void b2MouseJoint::SetFrequency(float32 hz)
  65. {
  66. m_frequencyHz = hz;
  67. }
  68. float32 b2MouseJoint::GetFrequency() const
  69. {
  70. return m_frequencyHz;
  71. }
  72. void b2MouseJoint::SetDampingRatio(float32 ratio)
  73. {
  74. m_dampingRatio = ratio;
  75. }
  76. float32 b2MouseJoint::GetDampingRatio() const
  77. {
  78. return m_dampingRatio;
  79. }
  80. void b2MouseJoint::InitVelocityConstraints(const b2SolverData& data)
  81. {
  82. m_indexB = m_bodyB->m_islandIndex;
  83. m_localCenterB = m_bodyB->m_sweep.localCenter;
  84. m_invMassB = m_bodyB->m_invMass;
  85. m_invIB = m_bodyB->m_invI;
  86. b2Vec2 cB = data.positions[m_indexB].c;
  87. float32 aB = data.positions[m_indexB].a;
  88. b2Vec2 vB = data.velocities[m_indexB].v;
  89. float32 wB = data.velocities[m_indexB].w;
  90. b2Rot qB(aB);
  91. float32 mass = m_bodyB->GetMass();
  92. // Frequency
  93. float32 omega = 2.0f * b2_pi * m_frequencyHz;
  94. // Damping coefficient
  95. float32 d = 2.0f * mass * m_dampingRatio * omega;
  96. // Spring stiffness
  97. float32 k = mass * (omega * omega);
  98. // magic formulas
  99. // gamma has units of inverse mass.
  100. // beta has units of inverse time.
  101. float32 h = data.step.dt;
  102. b2Assert(d + h * k > b2_epsilon);
  103. m_gamma = h * (d + h * k);
  104. if (m_gamma != 0.0f)
  105. {
  106. m_gamma = 1.0f / m_gamma;
  107. }
  108. m_beta = h * k * m_gamma;
  109. // Compute the effective mass matrix.
  110. m_rB = b2Mul(qB, m_localAnchorB - m_localCenterB);
  111. // K = [(1/m1 + 1/m2) * eye(2) - skew(r1) * invI1 * skew(r1) - skew(r2) * invI2 * skew(r2)]
  112. // = [1/m1+1/m2 0 ] + invI1 * [r1.y*r1.y -r1.x*r1.y] + invI2 * [r1.y*r1.y -r1.x*r1.y]
  113. // [ 0 1/m1+1/m2] [-r1.x*r1.y r1.x*r1.x] [-r1.x*r1.y r1.x*r1.x]
  114. b2Mat22 K;
  115. K.ex.x = m_invMassB + m_invIB * m_rB.y * m_rB.y + m_gamma;
  116. K.ex.y = -m_invIB * m_rB.x * m_rB.y;
  117. K.ey.x = K.ex.y;
  118. K.ey.y = m_invMassB + m_invIB * m_rB.x * m_rB.x + m_gamma;
  119. m_mass = K.GetInverse();
  120. m_C = cB + m_rB - m_targetA;
  121. m_C *= m_beta;
  122. // Cheat with some damping
  123. wB *= 0.98f;
  124. if (data.step.warmStarting)
  125. {
  126. m_impulse *= data.step.dtRatio;
  127. vB += m_invMassB * m_impulse;
  128. wB += m_invIB * b2Cross(m_rB, m_impulse);
  129. }
  130. else
  131. {
  132. m_impulse.SetZero();
  133. }
  134. data.velocities[m_indexB].v = vB;
  135. data.velocities[m_indexB].w = wB;
  136. }
  137. void b2MouseJoint::SolveVelocityConstraints(const b2SolverData& data)
  138. {
  139. b2Vec2 vB = data.velocities[m_indexB].v;
  140. float32 wB = data.velocities[m_indexB].w;
  141. // Cdot = v + cross(w, r)
  142. b2Vec2 Cdot = vB + b2Cross(wB, m_rB);
  143. b2Vec2 impulse = b2Mul(m_mass, -(Cdot + m_C + m_gamma * m_impulse));
  144. b2Vec2 oldImpulse = m_impulse;
  145. m_impulse += impulse;
  146. float32 maxImpulse = data.step.dt * m_maxForce;
  147. if (m_impulse.LengthSquared() > maxImpulse * maxImpulse)
  148. {
  149. m_impulse *= maxImpulse / m_impulse.Length();
  150. }
  151. impulse = m_impulse - oldImpulse;
  152. vB += m_invMassB * impulse;
  153. wB += m_invIB * b2Cross(m_rB, impulse);
  154. data.velocities[m_indexB].v = vB;
  155. data.velocities[m_indexB].w = wB;
  156. }
  157. bool b2MouseJoint::SolvePositionConstraints(const b2SolverData& data)
  158. {
  159. B2_NOT_USED(data);
  160. return true;
  161. }
  162. b2Vec2 b2MouseJoint::GetAnchorA() const
  163. {
  164. return m_targetA;
  165. }
  166. b2Vec2 b2MouseJoint::GetAnchorB() const
  167. {
  168. return m_bodyB->GetWorldPoint(m_localAnchorB);
  169. }
  170. b2Vec2 b2MouseJoint::GetReactionForce(float32 inv_dt) const
  171. {
  172. return inv_dt * m_impulse;
  173. }
  174. float32 b2MouseJoint::GetReactionTorque(float32 inv_dt) const
  175. {
  176. return inv_dt * 0.0f;
  177. }
  178. void b2MouseJoint::ShiftOrigin(const b2Vec2& newOrigin)
  179. {
  180. m_targetA -= newOrigin;
  181. }