b2_mouse_joint.cpp
Go to the documentation of this file.
1 // MIT License
2 
3 // Copyright (c) 2019 Erin Catto
4 
5 // Permission is hereby granted, free of charge, to any person obtaining a copy
6 // of this software and associated documentation files (the "Software"), to deal
7 // in the Software without restriction, including without limitation the rights
8 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 // copies of the Software, and to permit persons to whom the Software is
10 // furnished to do so, subject to the following conditions:
11 
12 // The above copyright notice and this permission notice shall be included in all
13 // copies or substantial portions of the Software.
14 
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 // SOFTWARE.
22 
23 #include "box2d/b2_body.h"
24 #include "box2d/b2_mouse_joint.h"
25 #include "box2d/b2_time_step.h"
26 
27 // p = attached point, m = mouse point
28 // C = p - m
29 // Cdot = v
30 // = v + cross(w, r)
31 // J = [I r_skew]
32 // Identity used:
33 // w k % (rx i + ry j) = w * (-ry i + rx j)
34 
36 : b2Joint(def)
37 {
38  m_targetA = def->target;
40  m_maxForce = def->maxForce;
41  m_stiffness = def->stiffness;
42  m_damping = def->damping;
43 
45  m_beta = 0.0f;
46  m_gamma = 0.0f;
47 }
48 
49 void b2MouseJoint::SetTarget(const b2Vec2& target)
50 {
51  if (target != m_targetA)
52  {
53  m_bodyB->SetAwake(true);
54  m_targetA = target;
55  }
56 }
57 
59 {
60  return m_targetA;
61 }
62 
63 void b2MouseJoint::SetMaxForce(float force)
64 {
65  m_maxForce = force;
66 }
67 
69 {
70  return m_maxForce;
71 }
72 
74 {
79 
80  b2Vec2 cB = data.positions[m_indexB].c;
81  float aB = data.positions[m_indexB].a;
82  b2Vec2 vB = data.velocities[m_indexB].v;
83  float wB = data.velocities[m_indexB].w;
84 
85  b2Rot qB(aB);
86 
87  float mass = m_bodyB->GetMass();
88 
89  float d = m_damping;
90  float k = m_stiffness;
91 
92  // magic formulas
93  // gamma has units of inverse mass.
94  // beta has units of inverse time.
95  float h = data.step.dt;
96  m_gamma = h * (d + h * k);
97  if (m_gamma != 0.0f)
98  {
99  m_gamma = 1.0f / m_gamma;
100  }
101  m_beta = h * k * m_gamma;
102 
103  // Compute the effective mass matrix.
105 
106  // K = [(1/m1 + 1/m2) * eye(2) - skew(r1) * invI1 * skew(r1) - skew(r2) * invI2 * skew(r2)]
107  // = [1/m1+1/m2 0 ] + invI1 * [r1.y*r1.y -r1.x*r1.y] + invI2 * [r1.y*r1.y -r1.x*r1.y]
108  // [ 0 1/m1+1/m2] [-r1.x*r1.y r1.x*r1.x] [-r1.x*r1.y r1.x*r1.x]
109  b2Mat22 K;
110  K.ex.x = m_invMassB + m_invIB * m_rB.y * m_rB.y + m_gamma;
111  K.ex.y = -m_invIB * m_rB.x * m_rB.y;
112  K.ey.x = K.ex.y;
113  K.ey.y = m_invMassB + m_invIB * m_rB.x * m_rB.x + m_gamma;
114 
115  m_mass = K.GetInverse();
116 
117  m_C = cB + m_rB - m_targetA;
118  m_C *= m_beta;
119 
120  // Cheat with some damping
121  wB *= 0.98f;
122 
123  if (data.step.warmStarting)
124  {
125  m_impulse *= data.step.dtRatio;
126  vB += m_invMassB * m_impulse;
127  wB += m_invIB * b2Cross(m_rB, m_impulse);
128  }
129  else
130  {
131  m_impulse.SetZero();
132  }
133 
134  data.velocities[m_indexB].v = vB;
135  data.velocities[m_indexB].w = wB;
136 }
137 
139 {
140  b2Vec2 vB = data.velocities[m_indexB].v;
141  float wB = data.velocities[m_indexB].w;
142 
143  // Cdot = v + cross(w, r)
144  b2Vec2 Cdot = vB + b2Cross(wB, m_rB);
145  b2Vec2 impulse = b2Mul(m_mass, -(Cdot + m_C + m_gamma * m_impulse));
146 
147  b2Vec2 oldImpulse = m_impulse;
148  m_impulse += impulse;
149  float maxImpulse = data.step.dt * m_maxForce;
150  if (m_impulse.LengthSquared() > maxImpulse * maxImpulse)
151  {
152  m_impulse *= maxImpulse / m_impulse.Length();
153  }
154  impulse = m_impulse - oldImpulse;
155 
156  vB += m_invMassB * impulse;
157  wB += m_invIB * b2Cross(m_rB, impulse);
158 
159  data.velocities[m_indexB].v = vB;
160  data.velocities[m_indexB].w = wB;
161 }
162 
164 {
165  B2_NOT_USED(data);
166  return true;
167 }
168 
170 {
171  return m_targetA;
172 }
173 
175 {
177 }
178 
180 {
181  return inv_dt * m_impulse;
182 }
183 
184 float b2MouseJoint::GetReactionTorque(float inv_dt) const
185 {
186  return inv_dt * 0.0f;
187 }
188 
189 void b2MouseJoint::ShiftOrigin(const b2Vec2& newOrigin)
190 {
191  m_targetA -= newOrigin;
192 }
const b2Transform & GetTransform() const
Definition: b2_body.h:479
d
bool SolvePositionConstraints(const b2SolverData &data) override
float GetMass() const
Definition: b2_body.h:544
b2Velocity * velocities
Definition: b2_time_step.h:71
int32 m_islandIndex
Definition: b2_body.h:439
float damping
The linear damping in N*s/m.
void SolveVelocityConstraints(const b2SolverData &data) override
b2Vec2 b2Mul(const b2Mat22 &A, const b2Vec2 &v)
Definition: b2_math.h:422
b2Vec2 m_localAnchorB
f
b2TimeStep step
Definition: b2_time_step.h:69
float x
Definition: b2_math.h:128
float y
Definition: b2_math.h:128
b2Vec2 c
Definition: b2_time_step.h:55
float GetMaxForce() const
void ShiftOrigin(const b2Vec2 &newOrigin) override
Implement b2Joint::ShiftOrigin.
void InitVelocityConstraints(const b2SolverData &data) override
float stiffness
The linear stiffness in N/m.
Solver Data.
Definition: b2_time_step.h:67
void SetZero()
Set this vector to all zeros.
Definition: b2_math.h:50
A 2D column vector.
Definition: b2_math.h:41
b2Vec2 ey
Definition: b2_math.h:241
float m_invI
Definition: b2_body.h:463
b2Vec2 localCenter
local center of mass position
Definition: b2_math.h:382
b2Vec2 m_localCenterB
b2Mat22 GetInverse() const
Definition: b2_math.h:211
b2Vec2 v
Definition: b2_time_step.h:62
b2Vec2 GetAnchorB() const override
Implements b2Joint.
#define B2_NOT_USED(x)
Definition: b2_common.h:36
float b2Cross(const b2Vec2 &a, const b2Vec2 &b)
Perform the cross product on two vectors. In 2D this produces a scalar.
Definition: b2_math.h:401
void SetMaxForce(float force)
Set/get the maximum force in Newtons.
const b2Vec2 & GetTarget() const
float GetReactionTorque(float inv_dt) const override
Implements b2Joint.
float m_invMass
Definition: b2_body.h:460
b2Position * positions
Definition: b2_time_step.h:70
b2Vec2 GetReactionForce(float inv_dt) const override
Implements b2Joint.
b2Vec2 b2MulT(const b2Mat22 &A, const b2Vec2 &v)
Definition: b2_math.h:429
b2Vec2 GetWorldPoint(const b2Vec2 &localPoint) const
Definition: b2_body.h:561
b2Vec2 ex
Definition: b2_math.h:241
A 2-by-2 matrix. Stored in column-major order.
Definition: b2_math.h:171
bool warmStarting
Definition: b2_time_step.h:49
Rotation.
Definition: b2_math.h:287
float dtRatio
Definition: b2_time_step.h:46
b2MouseJoint(const b2MouseJointDef *def)
void SetTarget(const b2Vec2 &target)
Use this to update the target point.
b2Vec2 GetAnchorA() const override
Implements b2Joint.
void SetAwake(bool flag)
Definition: b2_body.h:638
b2Body * m_bodyB
Definition: b2_joint.h:183
b2Sweep m_sweep
Definition: b2_body.h:442


mvsim
Author(s):
autogenerated on Tue Jul 4 2023 03:08:19