2 * Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
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.
19 #include "b2MouseJoint.h"
20 #include "../b2Body.h"
21 #include "../b2World.h"
23 // p = attached point, m = mouse point
29 // w k % (rx i + ry j) = w * (-ry i + rx j)
31 b2MouseJoint::b2MouseJoint(const b2MouseJointDef* def)
34 m_target = def->target;
35 m_localAnchor = b2MulT(m_body2->GetXForm(), m_target);
37 m_maxForce = B2FORCE_INV_SCALE(def->maxForce);
40 float32 mass = m_body2->m_mass;
43 float32 omega = 2.0f * b2_pi * def->frequencyHz;
45 // Damping coefficient
46 float32 d = 2.0f * mass * def->dampingRatio * omega;
49 float32 k = (def->timeStep * mass) * (omega * omega);
52 b2Assert(d + k > B2_FLT_EPSILON);
53 m_gamma = 1.0f / (d + k);
57 void b2MouseJoint::SetTarget(const b2Vec2& target)
59 if (m_body2->IsSleeping())
66 void b2MouseJoint::InitVelocityConstraints(const b2TimeStep& step)
70 // Compute the effective mass matrix.
71 b2Vec2 r = b2Mul(b->GetXForm().R, m_localAnchor - b->GetLocalCenter());
73 // K = [(1/m1 + 1/m2) * eye(2) - skew(r1) * invI1 * skew(r1) - skew(r2) * invI2 * skew(r2)]
74 // = [1/m1+1/m2 0 ] + invI1 * [r1.y*r1.y -r1.x*r1.y] + invI2 * [r1.y*r1.y -r1.x*r1.y]
75 // [ 0 1/m1+1/m2] [-r1.x*r1.y r1.x*r1.x] [-r1.x*r1.y r1.x*r1.x]
76 float32 invMass = b->m_invMass;
77 float32 invI = b->m_invI;
80 K1.col1.x = invMass; K1.col2.x = 0.0f;
81 K1.col1.y = 0.0f; K1.col2.y = invMass;
84 K2.col1.x = invI * r.y * r.y; K2.col2.x = -invI * r.x * r.y;
85 K2.col1.y = -invI * r.x * r.y; K2.col2.y = invI * r.x * r.x;
93 m_C = b->m_sweep.c + r - m_target;
95 // Cheat with some damping
96 b->m_angularVelocity *= 0.98f;
99 b2Vec2 P = B2FORCE_SCALE(step.dt) * m_impulse;
100 b->m_linearVelocity += invMass * P;
101 b->m_angularVelocity += invI * b2Cross(r, P);
104 void b2MouseJoint::SolveVelocityConstraints(const b2TimeStep& step)
108 b2Vec2 r = b2Mul(b->GetXForm().R, m_localAnchor - b->GetLocalCenter());
110 // Cdot = v + cross(w, r)
111 b2Vec2 Cdot = b->m_linearVelocity + b2Cross(b->m_angularVelocity, r);
112 b2Vec2 force = -B2FORCE_INV_SCALE(step.inv_dt) * b2Mul(m_mass, Cdot + (m_beta * step.inv_dt) * m_C + B2FORCE_SCALE(step.dt) * (m_gamma * m_impulse));
114 b2Vec2 oldForce = m_impulse;
116 float32 forceMagnitude = m_impulse.Length();
117 if (forceMagnitude > m_maxForce)
119 m_impulse *= m_maxForce / forceMagnitude;
121 force = m_impulse - oldForce;
123 b2Vec2 P = B2FORCE_SCALE(step.dt) * force;
124 b->m_linearVelocity += b->m_invMass * P;
125 b->m_angularVelocity += b->m_invI * b2Cross(r, P);
128 b2Vec2 b2MouseJoint::GetAnchor1() const
133 b2Vec2 b2MouseJoint::GetAnchor2() const
135 return m_body2->GetWorldPoint(m_localAnchor);
138 b2Vec2 b2MouseJoint::GetReactionForce() const
140 return B2FORCE_SCALE(float32(1.0))*m_impulse;
143 float32 b2MouseJoint::GetReactionTorque() const