b2MouseJoint.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. /*
  2. * Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
  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 "b2MouseJoint.h"
  19. #include "../b2Body.h"
  20. #include "../b2World.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. m_target = def->target;
  32. m_localAnchor = b2MulT(m_body2->GetXForm(), m_target);
  33. m_maxForce = def->maxForce;
  34. m_impulse.SetZero();
  35. m_frequencyHz = def->frequencyHz;
  36. m_dampingRatio = def->dampingRatio;
  37. m_beta = 0.0f;
  38. m_gamma = 0.0f;
  39. }
  40. void b2MouseJoint::SetTarget(const b2Vec2& target)
  41. {
  42. if (m_body2->IsSleeping())
  43. {
  44. m_body2->WakeUp();
  45. }
  46. m_target = target;
  47. }
  48. void b2MouseJoint::InitVelocityConstraints(const b2TimeStep& step)
  49. {
  50. b2Body* b = m_body2;
  51. float32 mass = b->GetMass();
  52. // Frequency
  53. float32 omega = 2.0f * b2_pi * m_frequencyHz;
  54. // Damping coefficient
  55. float32 d = 2.0f * mass * m_dampingRatio * omega;
  56. // Spring stiffness
  57. float32 k = mass * (omega * omega);
  58. // magic formulas
  59. // gamma has units of inverse mass.
  60. // beta has units of inverse time.
  61. b2Assert(d + step.dt * k > B2_FLT_EPSILON);
  62. m_gamma = 1.0f / (step.dt * (d + step.dt * k));
  63. m_beta = step.dt * k * m_gamma;
  64. // Compute the effective mass matrix.
  65. b2Vec2 r = b2Mul(b->GetXForm().R, m_localAnchor - b->GetLocalCenter());
  66. // K = [(1/m1 + 1/m2) * eye(2) - skew(r1) * invI1 * skew(r1) - skew(r2) * invI2 * skew(r2)]
  67. // = [1/m1+1/m2 0 ] + invI1 * [r1.y*r1.y -r1.x*r1.y] + invI2 * [r1.y*r1.y -r1.x*r1.y]
  68. // [ 0 1/m1+1/m2] [-r1.x*r1.y r1.x*r1.x] [-r1.x*r1.y r1.x*r1.x]
  69. float32 invMass = b->m_invMass;
  70. float32 invI = b->m_invI;
  71. b2Mat22 K1;
  72. K1.col1.x = invMass; K1.col2.x = 0.0f;
  73. K1.col1.y = 0.0f; K1.col2.y = invMass;
  74. b2Mat22 K2;
  75. K2.col1.x = invI * r.y * r.y; K2.col2.x = -invI * r.x * r.y;
  76. K2.col1.y = -invI * r.x * r.y; K2.col2.y = invI * r.x * r.x;
  77. b2Mat22 K = K1 + K2;
  78. K.col1.x += m_gamma;
  79. K.col2.y += m_gamma;
  80. m_mass = K.GetInverse();
  81. m_C = b->m_sweep.c + r - m_target;
  82. // Cheat with some damping
  83. b->m_angularVelocity *= 0.98f;
  84. // Warm starting.
  85. m_impulse *= step.dtRatio;
  86. b->m_linearVelocity += invMass * m_impulse;
  87. b->m_angularVelocity += invI * b2Cross(r, m_impulse);
  88. }
  89. void b2MouseJoint::SolveVelocityConstraints(const b2TimeStep& step)
  90. {
  91. b2Body* b = m_body2;
  92. b2Vec2 r = b2Mul(b->GetXForm().R, m_localAnchor - b->GetLocalCenter());
  93. // Cdot = v + cross(w, r)
  94. b2Vec2 Cdot = b->m_linearVelocity + b2Cross(b->m_angularVelocity, r);
  95. b2Vec2 impulse = b2Mul(m_mass, -(Cdot + m_beta * m_C + m_gamma * m_impulse));
  96. b2Vec2 oldImpulse = m_impulse;
  97. m_impulse += impulse;
  98. float32 maxImpulse = step.dt * m_maxForce;
  99. if (m_impulse.LengthSquared() > maxImpulse * maxImpulse)
  100. {
  101. m_impulse *= maxImpulse / m_impulse.Length();
  102. }
  103. impulse = m_impulse - oldImpulse;
  104. b->m_linearVelocity += b->m_invMass * impulse;
  105. b->m_angularVelocity += b->m_invI * b2Cross(r, impulse);
  106. }
  107. b2Vec2 b2MouseJoint::GetAnchor1() const
  108. {
  109. return m_target;
  110. }
  111. b2Vec2 b2MouseJoint::GetAnchor2() const
  112. {
  113. return m_body2->GetWorldPoint(m_localAnchor);
  114. }
  115. b2Vec2 b2MouseJoint::GetReactionForce(float32 inv_dt) const
  116. {
  117. return inv_dt * m_impulse;
  118. }
  119. float32 b2MouseJoint::GetReactionTorque(float32 inv_dt) const
  120. {
  121. return inv_dt * 0.0f;
  122. }