00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <Box2D/Dynamics/Joints/b2GearJoint.h>
00020 #include <Box2D/Dynamics/Joints/b2RevoluteJoint.h>
00021 #include <Box2D/Dynamics/Joints/b2PrismaticJoint.h>
00022 #include <Box2D/Dynamics/b2Body.h>
00023 #include <Box2D/Dynamics/b2TimeStep.h>
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044 b2GearJoint::b2GearJoint(const b2GearJointDef* def)
00045 : b2Joint(def)
00046 {
00047 m_joint1 = def->joint1;
00048 m_joint2 = def->joint2;
00049
00050 m_typeA = m_joint1->GetType();
00051 m_typeB = m_joint2->GetType();
00052
00053 b2Assert(m_typeA == e_revoluteJoint || m_typeA == e_prismaticJoint);
00054 b2Assert(m_typeB == e_revoluteJoint || m_typeB == e_prismaticJoint);
00055
00056 float32 coordinateA, coordinateB;
00057
00058
00059
00060 m_bodyC = m_joint1->GetBodyA();
00061 m_bodyA = m_joint1->GetBodyB();
00062
00063
00064 b2Transform xfA = m_bodyA->m_xf;
00065 float32 aA = m_bodyA->m_sweep.a;
00066 b2Transform xfC = m_bodyC->m_xf;
00067 float32 aC = m_bodyC->m_sweep.a;
00068
00069 if (m_typeA == e_revoluteJoint)
00070 {
00071 b2RevoluteJoint* revolute = (b2RevoluteJoint*)def->joint1;
00072 m_localAnchorC = revolute->m_localAnchorA;
00073 m_localAnchorA = revolute->m_localAnchorB;
00074 m_referenceAngleA = revolute->m_referenceAngle;
00075 m_localAxisC.SetZero();
00076
00077 coordinateA = aA - aC - m_referenceAngleA;
00078 }
00079 else
00080 {
00081 b2PrismaticJoint* prismatic = (b2PrismaticJoint*)def->joint1;
00082 m_localAnchorC = prismatic->m_localAnchorA;
00083 m_localAnchorA = prismatic->m_localAnchorB;
00084 m_referenceAngleA = prismatic->m_referenceAngle;
00085 m_localAxisC = prismatic->m_localXAxisA;
00086
00087 b2Vec2 pC = m_localAnchorC;
00088 b2Vec2 pA = b2MulT(xfC.q, b2Mul(xfA.q, m_localAnchorA) + (xfA.p - xfC.p));
00089 coordinateA = b2Dot(pA - pC, m_localAxisC);
00090 }
00091
00092 m_bodyD = m_joint2->GetBodyA();
00093 m_bodyB = m_joint2->GetBodyB();
00094
00095
00096 b2Transform xfB = m_bodyB->m_xf;
00097 float32 aB = m_bodyB->m_sweep.a;
00098 b2Transform xfD = m_bodyD->m_xf;
00099 float32 aD = m_bodyD->m_sweep.a;
00100
00101 if (m_typeB == e_revoluteJoint)
00102 {
00103 b2RevoluteJoint* revolute = (b2RevoluteJoint*)def->joint2;
00104 m_localAnchorD = revolute->m_localAnchorA;
00105 m_localAnchorB = revolute->m_localAnchorB;
00106 m_referenceAngleB = revolute->m_referenceAngle;
00107 m_localAxisD.SetZero();
00108
00109 coordinateB = aB - aD - m_referenceAngleB;
00110 }
00111 else
00112 {
00113 b2PrismaticJoint* prismatic = (b2PrismaticJoint*)def->joint2;
00114 m_localAnchorD = prismatic->m_localAnchorA;
00115 m_localAnchorB = prismatic->m_localAnchorB;
00116 m_referenceAngleB = prismatic->m_referenceAngle;
00117 m_localAxisD = prismatic->m_localXAxisA;
00118
00119 b2Vec2 pD = m_localAnchorD;
00120 b2Vec2 pB = b2MulT(xfD.q, b2Mul(xfB.q, m_localAnchorB) + (xfB.p - xfD.p));
00121 coordinateB = b2Dot(pB - pD, m_localAxisD);
00122 }
00123
00124 m_ratio = def->ratio;
00125
00126 m_constant = coordinateA + m_ratio * coordinateB;
00127
00128 m_impulse = 0.0f;
00129 }
00130
00131 void b2GearJoint::InitVelocityConstraints(const b2SolverData& data)
00132 {
00133 m_indexA = m_bodyA->m_islandIndex;
00134 m_indexB = m_bodyB->m_islandIndex;
00135 m_indexC = m_bodyC->m_islandIndex;
00136 m_indexD = m_bodyD->m_islandIndex;
00137 m_lcA = m_bodyA->m_sweep.localCenter;
00138 m_lcB = m_bodyB->m_sweep.localCenter;
00139 m_lcC = m_bodyC->m_sweep.localCenter;
00140 m_lcD = m_bodyD->m_sweep.localCenter;
00141 m_mA = m_bodyA->m_invMass;
00142 m_mB = m_bodyB->m_invMass;
00143 m_mC = m_bodyC->m_invMass;
00144 m_mD = m_bodyD->m_invMass;
00145 m_iA = m_bodyA->m_invI;
00146 m_iB = m_bodyB->m_invI;
00147 m_iC = m_bodyC->m_invI;
00148 m_iD = m_bodyD->m_invI;
00149
00150 float32 aA = data.positions[m_indexA].a;
00151 b2Vec2 vA = data.velocities[m_indexA].v;
00152 float32 wA = data.velocities[m_indexA].w;
00153
00154 float32 aB = data.positions[m_indexB].a;
00155 b2Vec2 vB = data.velocities[m_indexB].v;
00156 float32 wB = data.velocities[m_indexB].w;
00157
00158 float32 aC = data.positions[m_indexC].a;
00159 b2Vec2 vC = data.velocities[m_indexC].v;
00160 float32 wC = data.velocities[m_indexC].w;
00161
00162 float32 aD = data.positions[m_indexD].a;
00163 b2Vec2 vD = data.velocities[m_indexD].v;
00164 float32 wD = data.velocities[m_indexD].w;
00165
00166 b2Rot qA(aA), qB(aB), qC(aC), qD(aD);
00167
00168 m_mass = 0.0f;
00169
00170 if (m_typeA == e_revoluteJoint)
00171 {
00172 m_JvAC.SetZero();
00173 m_JwA = 1.0f;
00174 m_JwC = 1.0f;
00175 m_mass += m_iA + m_iC;
00176 }
00177 else
00178 {
00179 b2Vec2 u = b2Mul(qC, m_localAxisC);
00180 b2Vec2 rC = b2Mul(qC, m_localAnchorC - m_lcC);
00181 b2Vec2 rA = b2Mul(qA, m_localAnchorA - m_lcA);
00182 m_JvAC = u;
00183 m_JwC = b2Cross(rC, u);
00184 m_JwA = b2Cross(rA, u);
00185 m_mass += m_mC + m_mA + m_iC * m_JwC * m_JwC + m_iA * m_JwA * m_JwA;
00186 }
00187
00188 if (m_typeB == e_revoluteJoint)
00189 {
00190 m_JvBD.SetZero();
00191 m_JwB = m_ratio;
00192 m_JwD = m_ratio;
00193 m_mass += m_ratio * m_ratio * (m_iB + m_iD);
00194 }
00195 else
00196 {
00197 b2Vec2 u = b2Mul(qD, m_localAxisD);
00198 b2Vec2 rD = b2Mul(qD, m_localAnchorD - m_lcD);
00199 b2Vec2 rB = b2Mul(qB, m_localAnchorB - m_lcB);
00200 m_JvBD = m_ratio * u;
00201 m_JwD = m_ratio * b2Cross(rD, u);
00202 m_JwB = m_ratio * b2Cross(rB, u);
00203 m_mass += m_ratio * m_ratio * (m_mD + m_mB) + m_iD * m_JwD * m_JwD + m_iB * m_JwB * m_JwB;
00204 }
00205
00206
00207 m_mass = m_mass > 0.0f ? 1.0f / m_mass : 0.0f;
00208
00209 if (data.step.warmStarting)
00210 {
00211 vA += (m_mA * m_impulse) * m_JvAC;
00212 wA += m_iA * m_impulse * m_JwA;
00213 vB += (m_mB * m_impulse) * m_JvBD;
00214 wB += m_iB * m_impulse * m_JwB;
00215 vC -= (m_mC * m_impulse) * m_JvAC;
00216 wC -= m_iC * m_impulse * m_JwC;
00217 vD -= (m_mD * m_impulse) * m_JvBD;
00218 wD -= m_iD * m_impulse * m_JwD;
00219 }
00220 else
00221 {
00222 m_impulse = 0.0f;
00223 }
00224
00225 data.velocities[m_indexA].v = vA;
00226 data.velocities[m_indexA].w = wA;
00227 data.velocities[m_indexB].v = vB;
00228 data.velocities[m_indexB].w = wB;
00229 data.velocities[m_indexC].v = vC;
00230 data.velocities[m_indexC].w = wC;
00231 data.velocities[m_indexD].v = vD;
00232 data.velocities[m_indexD].w = wD;
00233 }
00234
00235 void b2GearJoint::SolveVelocityConstraints(const b2SolverData& data)
00236 {
00237 b2Vec2 vA = data.velocities[m_indexA].v;
00238 float32 wA = data.velocities[m_indexA].w;
00239 b2Vec2 vB = data.velocities[m_indexB].v;
00240 float32 wB = data.velocities[m_indexB].w;
00241 b2Vec2 vC = data.velocities[m_indexC].v;
00242 float32 wC = data.velocities[m_indexC].w;
00243 b2Vec2 vD = data.velocities[m_indexD].v;
00244 float32 wD = data.velocities[m_indexD].w;
00245
00246 float32 Cdot = b2Dot(m_JvAC, vA - vC) + b2Dot(m_JvBD, vB - vD);
00247 Cdot += (m_JwA * wA - m_JwC * wC) + (m_JwB * wB - m_JwD * wD);
00248
00249 float32 impulse = -m_mass * Cdot;
00250 m_impulse += impulse;
00251
00252 vA += (m_mA * impulse) * m_JvAC;
00253 wA += m_iA * impulse * m_JwA;
00254 vB += (m_mB * impulse) * m_JvBD;
00255 wB += m_iB * impulse * m_JwB;
00256 vC -= (m_mC * impulse) * m_JvAC;
00257 wC -= m_iC * impulse * m_JwC;
00258 vD -= (m_mD * impulse) * m_JvBD;
00259 wD -= m_iD * impulse * m_JwD;
00260
00261 data.velocities[m_indexA].v = vA;
00262 data.velocities[m_indexA].w = wA;
00263 data.velocities[m_indexB].v = vB;
00264 data.velocities[m_indexB].w = wB;
00265 data.velocities[m_indexC].v = vC;
00266 data.velocities[m_indexC].w = wC;
00267 data.velocities[m_indexD].v = vD;
00268 data.velocities[m_indexD].w = wD;
00269 }
00270
00271 bool b2GearJoint::SolvePositionConstraints(const b2SolverData& data)
00272 {
00273 b2Vec2 cA = data.positions[m_indexA].c;
00274 float32 aA = data.positions[m_indexA].a;
00275 b2Vec2 cB = data.positions[m_indexB].c;
00276 float32 aB = data.positions[m_indexB].a;
00277 b2Vec2 cC = data.positions[m_indexC].c;
00278 float32 aC = data.positions[m_indexC].a;
00279 b2Vec2 cD = data.positions[m_indexD].c;
00280 float32 aD = data.positions[m_indexD].a;
00281
00282 b2Rot qA(aA), qB(aB), qC(aC), qD(aD);
00283
00284 float32 linearError = 0.0f;
00285
00286 float32 coordinateA, coordinateB;
00287
00288 b2Vec2 JvAC, JvBD;
00289 float32 JwA, JwB, JwC, JwD;
00290 float32 mass = 0.0f;
00291
00292 if (m_typeA == e_revoluteJoint)
00293 {
00294 JvAC.SetZero();
00295 JwA = 1.0f;
00296 JwC = 1.0f;
00297 mass += m_iA + m_iC;
00298
00299 coordinateA = aA - aC - m_referenceAngleA;
00300 }
00301 else
00302 {
00303 b2Vec2 u = b2Mul(qC, m_localAxisC);
00304 b2Vec2 rC = b2Mul(qC, m_localAnchorC - m_lcC);
00305 b2Vec2 rA = b2Mul(qA, m_localAnchorA - m_lcA);
00306 JvAC = u;
00307 JwC = b2Cross(rC, u);
00308 JwA = b2Cross(rA, u);
00309 mass += m_mC + m_mA + m_iC * JwC * JwC + m_iA * JwA * JwA;
00310
00311 b2Vec2 pC = m_localAnchorC - m_lcC;
00312 b2Vec2 pA = b2MulT(qC, rA + (cA - cC));
00313 coordinateA = b2Dot(pA - pC, m_localAxisC);
00314 }
00315
00316 if (m_typeB == e_revoluteJoint)
00317 {
00318 JvBD.SetZero();
00319 JwB = m_ratio;
00320 JwD = m_ratio;
00321 mass += m_ratio * m_ratio * (m_iB + m_iD);
00322
00323 coordinateB = aB - aD - m_referenceAngleB;
00324 }
00325 else
00326 {
00327 b2Vec2 u = b2Mul(qD, m_localAxisD);
00328 b2Vec2 rD = b2Mul(qD, m_localAnchorD - m_lcD);
00329 b2Vec2 rB = b2Mul(qB, m_localAnchorB - m_lcB);
00330 JvBD = m_ratio * u;
00331 JwD = m_ratio * b2Cross(rD, u);
00332 JwB = m_ratio * b2Cross(rB, u);
00333 mass += m_ratio * m_ratio * (m_mD + m_mB) + m_iD * JwD * JwD + m_iB * JwB * JwB;
00334
00335 b2Vec2 pD = m_localAnchorD - m_lcD;
00336 b2Vec2 pB = b2MulT(qD, rB + (cB - cD));
00337 coordinateB = b2Dot(pB - pD, m_localAxisD);
00338 }
00339
00340 float32 C = (coordinateA + m_ratio * coordinateB) - m_constant;
00341
00342 float32 impulse = 0.0f;
00343 if (mass > 0.0f)
00344 {
00345 impulse = -C / mass;
00346 }
00347
00348 cA += m_mA * impulse * JvAC;
00349 aA += m_iA * impulse * JwA;
00350 cB += m_mB * impulse * JvBD;
00351 aB += m_iB * impulse * JwB;
00352 cC -= m_mC * impulse * JvAC;
00353 aC -= m_iC * impulse * JwC;
00354 cD -= m_mD * impulse * JvBD;
00355 aD -= m_iD * impulse * JwD;
00356
00357 data.positions[m_indexA].c = cA;
00358 data.positions[m_indexA].a = aA;
00359 data.positions[m_indexB].c = cB;
00360 data.positions[m_indexB].a = aB;
00361 data.positions[m_indexC].c = cC;
00362 data.positions[m_indexC].a = aC;
00363 data.positions[m_indexD].c = cD;
00364 data.positions[m_indexD].a = aD;
00365
00366
00367 return linearError < b2_linearSlop;
00368 }
00369
00370 b2Vec2 b2GearJoint::GetAnchorA() const
00371 {
00372 return m_bodyA->GetWorldPoint(m_localAnchorA);
00373 }
00374
00375 b2Vec2 b2GearJoint::GetAnchorB() const
00376 {
00377 return m_bodyB->GetWorldPoint(m_localAnchorB);
00378 }
00379
00380 b2Vec2 b2GearJoint::GetReactionForce(float32 inv_dt) const
00381 {
00382 b2Vec2 P = m_impulse * m_JvAC;
00383 return inv_dt * P;
00384 }
00385
00386 float32 b2GearJoint::GetReactionTorque(float32 inv_dt) const
00387 {
00388 float32 L = m_impulse * m_JwA;
00389 return inv_dt * L;
00390 }
00391
00392 void b2GearJoint::SetRatio(float32 ratio)
00393 {
00394 b2Assert(b2IsValid(ratio));
00395 m_ratio = ratio;
00396 }
00397
00398 float32 b2GearJoint::GetRatio() const
00399 {
00400 return m_ratio;
00401 }
00402
00403 void b2GearJoint::Dump()
00404 {
00405 int32 indexA = m_bodyA->m_islandIndex;
00406 int32 indexB = m_bodyB->m_islandIndex;
00407
00408 int32 index1 = m_joint1->m_index;
00409 int32 index2 = m_joint2->m_index;
00410
00411 b2Log(" b2GearJointDef jd;\n");
00412 b2Log(" jd.bodyA = bodies[%d];\n", indexA);
00413 b2Log(" jd.bodyB = bodies[%d];\n", indexB);
00414 b2Log(" jd.collideConnected = bool(%d);\n", m_collideConnected);
00415 b2Log(" jd.joint1 = joints[%d];\n", index1);
00416 b2Log(" jd.joint2 = joints[%d];\n", index2);
00417 b2Log(" jd.ratio = %.15lef;\n", m_ratio);
00418 b2Log(" joints[%d] = m_world->CreateJoint(&jd);\n", m_index);
00419 }