File indexing completed on 2024-12-29 03:29:27
0001 /* 0002 * Copyright (c) 2006-2011 Erin Catto http://www.box2d.org 0003 * 0004 * This software is provided 'as-is', without any express or implied 0005 * warranty. In no event will the authors be held liable for any damages 0006 * arising from the use of this software. 0007 * Permission is granted to anyone to use this software for any purpose, 0008 * including commercial applications, and to alter it and redistribute it 0009 * freely, subject to the following restrictions: 0010 * 1. The origin of this software must not be misrepresented; you must not 0011 * claim that you wrote the original software. If you use this software 0012 * in a product, an acknowledgment in the product documentation would be 0013 * appreciated but is not required. 0014 * 2. Altered source versions must be plainly marked as such, and must not be 0015 * misrepresented as being the original software. 0016 * 3. This notice may not be removed or altered from any source distribution. 0017 */ 0018 0019 #include <Box2D/Dynamics/Joints/b2PrismaticJoint.h> 0020 #include <Box2D/Dynamics/b2Body.h> 0021 #include <Box2D/Dynamics/b2TimeStep.h> 0022 0023 // Linear constraint (point-to-line) 0024 // d = p2 - p1 = x2 + r2 - x1 - r1 0025 // C = dot(perp, d) 0026 // Cdot = dot(d, cross(w1, perp)) + dot(perp, v2 + cross(w2, r2) - v1 - cross(w1, r1)) 0027 // = -dot(perp, v1) - dot(cross(d + r1, perp), w1) + dot(perp, v2) + dot(cross(r2, perp), v2) 0028 // J = [-perp, -cross(d + r1, perp), perp, cross(r2,perp)] 0029 // 0030 // Angular constraint 0031 // C = a2 - a1 + a_initial 0032 // Cdot = w2 - w1 0033 // J = [0 0 -1 0 0 1] 0034 // 0035 // K = J * invM * JT 0036 // 0037 // J = [-a -s1 a s2] 0038 // [0 -1 0 1] 0039 // a = perp 0040 // s1 = cross(d + r1, a) = cross(p2 - x1, a) 0041 // s2 = cross(r2, a) = cross(p2 - x2, a) 0042 0043 0044 // Motor/Limit linear constraint 0045 // C = dot(ax1, d) 0046 // Cdot = = -dot(ax1, v1) - dot(cross(d + r1, ax1), w1) + dot(ax1, v2) + dot(cross(r2, ax1), v2) 0047 // J = [-ax1 -cross(d+r1,ax1) ax1 cross(r2,ax1)] 0048 0049 // Block Solver 0050 // We develop a block solver that includes the joint limit. This makes the limit stiff (inelastic) even 0051 // when the mass has poor distribution (leading to large torques about the joint anchor points). 0052 // 0053 // The Jacobian has 3 rows: 0054 // J = [-uT -s1 uT s2] // linear 0055 // [0 -1 0 1] // angular 0056 // [-vT -a1 vT a2] // limit 0057 // 0058 // u = perp 0059 // v = axis 0060 // s1 = cross(d + r1, u), s2 = cross(r2, u) 0061 // a1 = cross(d + r1, v), a2 = cross(r2, v) 0062 0063 // M * (v2 - v1) = JT * df 0064 // J * v2 = bias 0065 // 0066 // v2 = v1 + invM * JT * df 0067 // J * (v1 + invM * JT * df) = bias 0068 // K * df = bias - J * v1 = -Cdot 0069 // K = J * invM * JT 0070 // Cdot = J * v1 - bias 0071 // 0072 // Now solve for f2. 0073 // df = f2 - f1 0074 // K * (f2 - f1) = -Cdot 0075 // f2 = invK * (-Cdot) + f1 0076 // 0077 // Clamp accumulated limit impulse. 0078 // lower: f2(3) = max(f2(3), 0) 0079 // upper: f2(3) = min(f2(3), 0) 0080 // 0081 // Solve for correct f2(1:2) 0082 // K(1:2, 1:2) * f2(1:2) = -Cdot(1:2) - K(1:2,3) * f2(3) + K(1:2,1:3) * f1 0083 // = -Cdot(1:2) - K(1:2,3) * f2(3) + K(1:2,1:2) * f1(1:2) + K(1:2,3) * f1(3) 0084 // K(1:2, 1:2) * f2(1:2) = -Cdot(1:2) - K(1:2,3) * (f2(3) - f1(3)) + K(1:2,1:2) * f1(1:2) 0085 // f2(1:2) = invK(1:2,1:2) * (-Cdot(1:2) - K(1:2,3) * (f2(3) - f1(3))) + f1(1:2) 0086 // 0087 // Now compute impulse to be applied: 0088 // df = f2 - f1 0089 0090 void b2PrismaticJointDef::Initialize(b2Body* bA, b2Body* bB, const b2Vec2& anchor, const b2Vec2& axis) 0091 { 0092 bodyA = bA; 0093 bodyB = bB; 0094 localAnchorA = bodyA->GetLocalPoint(anchor); 0095 localAnchorB = bodyB->GetLocalPoint(anchor); 0096 localAxisA = bodyA->GetLocalVector(axis); 0097 referenceAngle = bodyB->GetAngle() - bodyA->GetAngle(); 0098 } 0099 0100 b2PrismaticJoint::b2PrismaticJoint(const b2PrismaticJointDef* def) 0101 : b2Joint(def) 0102 { 0103 m_localAnchorA = def->localAnchorA; 0104 m_localAnchorB = def->localAnchorB; 0105 m_localXAxisA = def->localAxisA; 0106 m_localXAxisA.Normalize(); 0107 m_localYAxisA = b2Cross(1.0f, m_localXAxisA); 0108 m_referenceAngle = def->referenceAngle; 0109 0110 m_impulse.SetZero(); 0111 m_motorMass = 0.0f; 0112 m_motorImpulse = 0.0f; 0113 0114 m_lowerTranslation = def->lowerTranslation; 0115 m_upperTranslation = def->upperTranslation; 0116 m_maxMotorForce = def->maxMotorForce; 0117 m_motorSpeed = def->motorSpeed; 0118 m_enableLimit = def->enableLimit; 0119 m_enableMotor = def->enableMotor; 0120 m_limitState = e_inactiveLimit; 0121 0122 m_axis.SetZero(); 0123 m_perp.SetZero(); 0124 } 0125 0126 void b2PrismaticJoint::InitVelocityConstraints(const b2SolverData& data) 0127 { 0128 m_indexA = m_bodyA->m_islandIndex; 0129 m_indexB = m_bodyB->m_islandIndex; 0130 m_localCenterA = m_bodyA->m_sweep.localCenter; 0131 m_localCenterB = m_bodyB->m_sweep.localCenter; 0132 m_invMassA = m_bodyA->m_invMass; 0133 m_invMassB = m_bodyB->m_invMass; 0134 m_invIA = m_bodyA->m_invI; 0135 m_invIB = m_bodyB->m_invI; 0136 0137 b2Vec2 cA = data.positions[m_indexA].c; 0138 float32 aA = data.positions[m_indexA].a; 0139 b2Vec2 vA = data.velocities[m_indexA].v; 0140 float32 wA = data.velocities[m_indexA].w; 0141 0142 b2Vec2 cB = data.positions[m_indexB].c; 0143 float32 aB = data.positions[m_indexB].a; 0144 b2Vec2 vB = data.velocities[m_indexB].v; 0145 float32 wB = data.velocities[m_indexB].w; 0146 0147 b2Rot qA(aA), qB(aB); 0148 0149 // Compute the effective masses. 0150 b2Vec2 rA = b2Mul(qA, m_localAnchorA - m_localCenterA); 0151 b2Vec2 rB = b2Mul(qB, m_localAnchorB - m_localCenterB); 0152 b2Vec2 d = (cB - cA) + rB - rA; 0153 0154 float32 mA = m_invMassA, mB = m_invMassB; 0155 float32 iA = m_invIA, iB = m_invIB; 0156 0157 // Compute motor Jacobian and effective mass. 0158 { 0159 m_axis = b2Mul(qA, m_localXAxisA); 0160 m_a1 = b2Cross(d + rA, m_axis); 0161 m_a2 = b2Cross(rB, m_axis); 0162 0163 m_motorMass = mA + mB + iA * m_a1 * m_a1 + iB * m_a2 * m_a2; 0164 if (m_motorMass > 0.0f) 0165 { 0166 m_motorMass = 1.0f / m_motorMass; 0167 } 0168 } 0169 0170 // Prismatic constraint. 0171 { 0172 m_perp = b2Mul(qA, m_localYAxisA); 0173 0174 m_s1 = b2Cross(d + rA, m_perp); 0175 m_s2 = b2Cross(rB, m_perp); 0176 0177 float32 s1test; 0178 s1test = b2Cross(rA, m_perp); 0179 0180 float32 k11 = mA + mB + iA * m_s1 * m_s1 + iB * m_s2 * m_s2; 0181 float32 k12 = iA * m_s1 + iB * m_s2; 0182 float32 k13 = iA * m_s1 * m_a1 + iB * m_s2 * m_a2; 0183 float32 k22 = iA + iB; 0184 if (k22 == 0.0f) 0185 { 0186 // For bodies with fixed rotation. 0187 k22 = 1.0f; 0188 } 0189 float32 k23 = iA * m_a1 + iB * m_a2; 0190 float32 k33 = mA + mB + iA * m_a1 * m_a1 + iB * m_a2 * m_a2; 0191 0192 m_K.ex.Set(k11, k12, k13); 0193 m_K.ey.Set(k12, k22, k23); 0194 m_K.ez.Set(k13, k23, k33); 0195 } 0196 0197 // Compute motor and limit terms. 0198 if (m_enableLimit) 0199 { 0200 float32 jointTranslation = b2Dot(m_axis, d); 0201 if (b2Abs(m_upperTranslation - m_lowerTranslation) < 2.0f * b2_linearSlop) 0202 { 0203 m_limitState = e_equalLimits; 0204 } 0205 else if (jointTranslation <= m_lowerTranslation) 0206 { 0207 if (m_limitState != e_atLowerLimit) 0208 { 0209 m_limitState = e_atLowerLimit; 0210 m_impulse.z = 0.0f; 0211 } 0212 } 0213 else if (jointTranslation >= m_upperTranslation) 0214 { 0215 if (m_limitState != e_atUpperLimit) 0216 { 0217 m_limitState = e_atUpperLimit; 0218 m_impulse.z = 0.0f; 0219 } 0220 } 0221 else 0222 { 0223 m_limitState = e_inactiveLimit; 0224 m_impulse.z = 0.0f; 0225 } 0226 } 0227 else 0228 { 0229 m_limitState = e_inactiveLimit; 0230 m_impulse.z = 0.0f; 0231 } 0232 0233 if (m_enableMotor == false) 0234 { 0235 m_motorImpulse = 0.0f; 0236 } 0237 0238 if (data.step.warmStarting) 0239 { 0240 // Account for variable time step. 0241 m_impulse *= data.step.dtRatio; 0242 m_motorImpulse *= data.step.dtRatio; 0243 0244 b2Vec2 P = m_impulse.x * m_perp + (m_motorImpulse + m_impulse.z) * m_axis; 0245 float32 LA = m_impulse.x * m_s1 + m_impulse.y + (m_motorImpulse + m_impulse.z) * m_a1; 0246 float32 LB = m_impulse.x * m_s2 + m_impulse.y + (m_motorImpulse + m_impulse.z) * m_a2; 0247 0248 vA -= mA * P; 0249 wA -= iA * LA; 0250 0251 vB += mB * P; 0252 wB += iB * LB; 0253 } 0254 else 0255 { 0256 m_impulse.SetZero(); 0257 m_motorImpulse = 0.0f; 0258 } 0259 0260 data.velocities[m_indexA].v = vA; 0261 data.velocities[m_indexA].w = wA; 0262 data.velocities[m_indexB].v = vB; 0263 data.velocities[m_indexB].w = wB; 0264 } 0265 0266 void b2PrismaticJoint::SolveVelocityConstraints(const b2SolverData& data) 0267 { 0268 b2Vec2 vA = data.velocities[m_indexA].v; 0269 float32 wA = data.velocities[m_indexA].w; 0270 b2Vec2 vB = data.velocities[m_indexB].v; 0271 float32 wB = data.velocities[m_indexB].w; 0272 0273 float32 mA = m_invMassA, mB = m_invMassB; 0274 float32 iA = m_invIA, iB = m_invIB; 0275 0276 // Solve linear motor constraint. 0277 if (m_enableMotor && m_limitState != e_equalLimits) 0278 { 0279 float32 Cdot = b2Dot(m_axis, vB - vA) + m_a2 * wB - m_a1 * wA; 0280 float32 impulse = m_motorMass * (m_motorSpeed - Cdot); 0281 float32 oldImpulse = m_motorImpulse; 0282 float32 maxImpulse = data.step.dt * m_maxMotorForce; 0283 m_motorImpulse = b2Clamp(m_motorImpulse + impulse, -maxImpulse, maxImpulse); 0284 impulse = m_motorImpulse - oldImpulse; 0285 0286 b2Vec2 P = impulse * m_axis; 0287 float32 LA = impulse * m_a1; 0288 float32 LB = impulse * m_a2; 0289 0290 vA -= mA * P; 0291 wA -= iA * LA; 0292 0293 vB += mB * P; 0294 wB += iB * LB; 0295 } 0296 0297 b2Vec2 Cdot1; 0298 Cdot1.x = b2Dot(m_perp, vB - vA) + m_s2 * wB - m_s1 * wA; 0299 Cdot1.y = wB - wA; 0300 0301 if (m_enableLimit && m_limitState != e_inactiveLimit) 0302 { 0303 // Solve prismatic and limit constraint in block form. 0304 float32 Cdot2; 0305 Cdot2 = b2Dot(m_axis, vB - vA) + m_a2 * wB - m_a1 * wA; 0306 b2Vec3 Cdot(Cdot1.x, Cdot1.y, Cdot2); 0307 0308 b2Vec3 f1 = m_impulse; 0309 b2Vec3 df = m_K.Solve33(-Cdot); 0310 m_impulse += df; 0311 0312 if (m_limitState == e_atLowerLimit) 0313 { 0314 m_impulse.z = b2Max(m_impulse.z, 0.0f); 0315 } 0316 else if (m_limitState == e_atUpperLimit) 0317 { 0318 m_impulse.z = b2Min(m_impulse.z, 0.0f); 0319 } 0320 0321 // f2(1:2) = invK(1:2,1:2) * (-Cdot(1:2) - K(1:2,3) * (f2(3) - f1(3))) + f1(1:2) 0322 b2Vec2 b = -Cdot1 - (m_impulse.z - f1.z) * b2Vec2(m_K.ez.x, m_K.ez.y); 0323 b2Vec2 f2r = m_K.Solve22(b) + b2Vec2(f1.x, f1.y); 0324 m_impulse.x = f2r.x; 0325 m_impulse.y = f2r.y; 0326 0327 df = m_impulse - f1; 0328 0329 b2Vec2 P = df.x * m_perp + df.z * m_axis; 0330 float32 LA = df.x * m_s1 + df.y + df.z * m_a1; 0331 float32 LB = df.x * m_s2 + df.y + df.z * m_a2; 0332 0333 vA -= mA * P; 0334 wA -= iA * LA; 0335 0336 vB += mB * P; 0337 wB += iB * LB; 0338 } 0339 else 0340 { 0341 // Limit is inactive, just solve the prismatic constraint in block form. 0342 b2Vec2 df = m_K.Solve22(-Cdot1); 0343 m_impulse.x += df.x; 0344 m_impulse.y += df.y; 0345 0346 b2Vec2 P = df.x * m_perp; 0347 float32 LA = df.x * m_s1 + df.y; 0348 float32 LB = df.x * m_s2 + df.y; 0349 0350 vA -= mA * P; 0351 wA -= iA * LA; 0352 0353 vB += mB * P; 0354 wB += iB * LB; 0355 } 0356 0357 data.velocities[m_indexA].v = vA; 0358 data.velocities[m_indexA].w = wA; 0359 data.velocities[m_indexB].v = vB; 0360 data.velocities[m_indexB].w = wB; 0361 } 0362 0363 bool b2PrismaticJoint::SolvePositionConstraints(const b2SolverData& data) 0364 { 0365 b2Vec2 cA = data.positions[m_indexA].c; 0366 float32 aA = data.positions[m_indexA].a; 0367 b2Vec2 cB = data.positions[m_indexB].c; 0368 float32 aB = data.positions[m_indexB].a; 0369 0370 b2Rot qA(aA), qB(aB); 0371 0372 float32 mA = m_invMassA, mB = m_invMassB; 0373 float32 iA = m_invIA, iB = m_invIB; 0374 0375 // Compute fresh Jacobians 0376 b2Vec2 rA = b2Mul(qA, m_localAnchorA - m_localCenterA); 0377 b2Vec2 rB = b2Mul(qB, m_localAnchorB - m_localCenterB); 0378 b2Vec2 d = cB + rB - cA - rA; 0379 0380 b2Vec2 axis = b2Mul(qA, m_localXAxisA); 0381 float32 a1 = b2Cross(d + rA, axis); 0382 float32 a2 = b2Cross(rB, axis); 0383 b2Vec2 perp = b2Mul(qA, m_localYAxisA); 0384 0385 float32 s1 = b2Cross(d + rA, perp); 0386 float32 s2 = b2Cross(rB, perp); 0387 0388 b2Vec3 impulse; 0389 b2Vec2 C1; 0390 C1.x = b2Dot(perp, d); 0391 C1.y = aB - aA - m_referenceAngle; 0392 0393 float32 linearError = b2Abs(C1.x); 0394 float32 angularError = b2Abs(C1.y); 0395 0396 bool active = false; 0397 float32 C2 = 0.0f; 0398 if (m_enableLimit) 0399 { 0400 float32 translation = b2Dot(axis, d); 0401 if (b2Abs(m_upperTranslation - m_lowerTranslation) < 2.0f * b2_linearSlop) 0402 { 0403 // Prevent large angular corrections 0404 C2 = b2Clamp(translation, -b2_maxLinearCorrection, b2_maxLinearCorrection); 0405 linearError = b2Max(linearError, b2Abs(translation)); 0406 active = true; 0407 } 0408 else if (translation <= m_lowerTranslation) 0409 { 0410 // Prevent large linear corrections and allow some slop. 0411 C2 = b2Clamp(translation - m_lowerTranslation + b2_linearSlop, -b2_maxLinearCorrection, 0.0f); 0412 linearError = b2Max(linearError, m_lowerTranslation - translation); 0413 active = true; 0414 } 0415 else if (translation >= m_upperTranslation) 0416 { 0417 // Prevent large linear corrections and allow some slop. 0418 C2 = b2Clamp(translation - m_upperTranslation - b2_linearSlop, 0.0f, b2_maxLinearCorrection); 0419 linearError = b2Max(linearError, translation - m_upperTranslation); 0420 active = true; 0421 } 0422 } 0423 0424 if (active) 0425 { 0426 float32 k11 = mA + mB + iA * s1 * s1 + iB * s2 * s2; 0427 float32 k12 = iA * s1 + iB * s2; 0428 float32 k13 = iA * s1 * a1 + iB * s2 * a2; 0429 float32 k22 = iA + iB; 0430 if (k22 == 0.0f) 0431 { 0432 // For fixed rotation 0433 k22 = 1.0f; 0434 } 0435 float32 k23 = iA * a1 + iB * a2; 0436 float32 k33 = mA + mB + iA * a1 * a1 + iB * a2 * a2; 0437 0438 b2Mat33 K; 0439 K.ex.Set(k11, k12, k13); 0440 K.ey.Set(k12, k22, k23); 0441 K.ez.Set(k13, k23, k33); 0442 0443 b2Vec3 C; 0444 C.x = C1.x; 0445 C.y = C1.y; 0446 C.z = C2; 0447 0448 impulse = K.Solve33(-C); 0449 } 0450 else 0451 { 0452 float32 k11 = mA + mB + iA * s1 * s1 + iB * s2 * s2; 0453 float32 k12 = iA * s1 + iB * s2; 0454 float32 k22 = iA + iB; 0455 if (k22 == 0.0f) 0456 { 0457 k22 = 1.0f; 0458 } 0459 0460 b2Mat22 K; 0461 K.ex.Set(k11, k12); 0462 K.ey.Set(k12, k22); 0463 0464 b2Vec2 impulse1 = K.Solve(-C1); 0465 impulse.x = impulse1.x; 0466 impulse.y = impulse1.y; 0467 impulse.z = 0.0f; 0468 } 0469 0470 b2Vec2 P = impulse.x * perp + impulse.z * axis; 0471 float32 LA = impulse.x * s1 + impulse.y + impulse.z * a1; 0472 float32 LB = impulse.x * s2 + impulse.y + impulse.z * a2; 0473 0474 cA -= mA * P; 0475 aA -= iA * LA; 0476 cB += mB * P; 0477 aB += iB * LB; 0478 0479 data.positions[m_indexA].c = cA; 0480 data.positions[m_indexA].a = aA; 0481 data.positions[m_indexB].c = cB; 0482 data.positions[m_indexB].a = aB; 0483 0484 return linearError <= b2_linearSlop && angularError <= b2_angularSlop; 0485 } 0486 0487 b2Vec2 b2PrismaticJoint::GetAnchorA() const 0488 { 0489 return m_bodyA->GetWorldPoint(m_localAnchorA); 0490 } 0491 0492 b2Vec2 b2PrismaticJoint::GetAnchorB() const 0493 { 0494 return m_bodyB->GetWorldPoint(m_localAnchorB); 0495 } 0496 0497 b2Vec2 b2PrismaticJoint::GetReactionForce(float32 inv_dt) const 0498 { 0499 return inv_dt * (m_impulse.x * m_perp + (m_motorImpulse + m_impulse.z) * m_axis); 0500 } 0501 0502 float32 b2PrismaticJoint::GetReactionTorque(float32 inv_dt) const 0503 { 0504 return inv_dt * m_impulse.y; 0505 } 0506 0507 float32 b2PrismaticJoint::GetJointTranslation() const 0508 { 0509 b2Vec2 pA = m_bodyA->GetWorldPoint(m_localAnchorA); 0510 b2Vec2 pB = m_bodyB->GetWorldPoint(m_localAnchorB); 0511 b2Vec2 d = pB - pA; 0512 b2Vec2 axis = m_bodyA->GetWorldVector(m_localXAxisA); 0513 0514 float32 translation = b2Dot(d, axis); 0515 return translation; 0516 } 0517 0518 float32 b2PrismaticJoint::GetJointSpeed() const 0519 { 0520 b2Body* bA = m_bodyA; 0521 b2Body* bB = m_bodyB; 0522 0523 b2Vec2 rA = b2Mul(bA->m_xf.q, m_localAnchorA - bA->m_sweep.localCenter); 0524 b2Vec2 rB = b2Mul(bB->m_xf.q, m_localAnchorB - bB->m_sweep.localCenter); 0525 b2Vec2 p1 = bA->m_sweep.c + rA; 0526 b2Vec2 p2 = bB->m_sweep.c + rB; 0527 b2Vec2 d = p2 - p1; 0528 b2Vec2 axis = b2Mul(bA->m_xf.q, m_localXAxisA); 0529 0530 b2Vec2 vA = bA->m_linearVelocity; 0531 b2Vec2 vB = bB->m_linearVelocity; 0532 float32 wA = bA->m_angularVelocity; 0533 float32 wB = bB->m_angularVelocity; 0534 0535 float32 speed = b2Dot(d, b2Cross(wA, axis)) + b2Dot(axis, vB + b2Cross(wB, rB) - vA - b2Cross(wA, rA)); 0536 return speed; 0537 } 0538 0539 bool b2PrismaticJoint::IsLimitEnabled() const 0540 { 0541 return m_enableLimit; 0542 } 0543 0544 void b2PrismaticJoint::EnableLimit(bool flag) 0545 { 0546 if (flag != m_enableLimit) 0547 { 0548 m_bodyA->SetAwake(true); 0549 m_bodyB->SetAwake(true); 0550 m_enableLimit = flag; 0551 m_impulse.z = 0.0f; 0552 } 0553 } 0554 0555 float32 b2PrismaticJoint::GetLowerLimit() const 0556 { 0557 return m_lowerTranslation; 0558 } 0559 0560 float32 b2PrismaticJoint::GetUpperLimit() const 0561 { 0562 return m_upperTranslation; 0563 } 0564 0565 void b2PrismaticJoint::SetLimits(float32 lower, float32 upper) 0566 { 0567 b2Assert(lower <= upper); 0568 if (lower != m_lowerTranslation || upper != m_upperTranslation) 0569 { 0570 m_bodyA->SetAwake(true); 0571 m_bodyB->SetAwake(true); 0572 m_lowerTranslation = lower; 0573 m_upperTranslation = upper; 0574 m_impulse.z = 0.0f; 0575 } 0576 } 0577 0578 bool b2PrismaticJoint::IsMotorEnabled() const 0579 { 0580 return m_enableMotor; 0581 } 0582 0583 void b2PrismaticJoint::EnableMotor(bool flag) 0584 { 0585 m_bodyA->SetAwake(true); 0586 m_bodyB->SetAwake(true); 0587 m_enableMotor = flag; 0588 } 0589 0590 void b2PrismaticJoint::SetMotorSpeed(float32 speed) 0591 { 0592 m_bodyA->SetAwake(true); 0593 m_bodyB->SetAwake(true); 0594 m_motorSpeed = speed; 0595 } 0596 0597 void b2PrismaticJoint::SetMaxMotorForce(float32 force) 0598 { 0599 m_bodyA->SetAwake(true); 0600 m_bodyB->SetAwake(true); 0601 m_maxMotorForce = force; 0602 } 0603 0604 float32 b2PrismaticJoint::GetMotorForce(float32 inv_dt) const 0605 { 0606 return inv_dt * m_motorImpulse; 0607 } 0608 0609 void b2PrismaticJoint::Dump() 0610 { 0611 int32 indexA = m_bodyA->m_islandIndex; 0612 int32 indexB = m_bodyB->m_islandIndex; 0613 0614 b2Log(" b2PrismaticJointDef jd;\n"); 0615 b2Log(" jd.bodyA = bodies[%d];\n", indexA); 0616 b2Log(" jd.bodyB = bodies[%d];\n", indexB); 0617 b2Log(" jd.collideConnected = bool(%d);\n", m_collideConnected); 0618 b2Log(" jd.localAnchorA.Set(%.15lef, %.15lef);\n", m_localAnchorA.x, m_localAnchorA.y); 0619 b2Log(" jd.localAnchorB.Set(%.15lef, %.15lef);\n", m_localAnchorB.x, m_localAnchorB.y); 0620 b2Log(" jd.localAxisA.Set(%.15lef, %.15lef);\n", m_localXAxisA.x, m_localXAxisA.y); 0621 b2Log(" jd.referenceAngle = %.15lef;\n", m_referenceAngle); 0622 b2Log(" jd.enableLimit = bool(%d);\n", m_enableLimit); 0623 b2Log(" jd.lowerTranslation = %.15lef;\n", m_lowerTranslation); 0624 b2Log(" jd.upperTranslation = %.15lef;\n", m_upperTranslation); 0625 b2Log(" jd.enableMotor = bool(%d);\n", m_enableMotor); 0626 b2Log(" jd.motorSpeed = %.15lef;\n", m_motorSpeed); 0627 b2Log(" jd.maxMotorForce = %.15lef;\n", m_maxMotorForce); 0628 b2Log(" joints[%d] = m_world->CreateJoint(&jd);\n", m_index); 0629 }