private void drawJoint(Joint joint) { Body bodyA = joint.getBodyA(); Body bodyB = joint.getBodyB(); Transform xf1 = bodyA.getTransform(); Transform xf2 = bodyB.getTransform(); Vec2 x1 = xf1.p; Vec2 x2 = xf2.p; Vec2 p1 = pool.popVec2(); Vec2 p2 = pool.popVec2(); joint.getAnchorA(p1); joint.getAnchorB(p2); color.set(0.5f, 0.8f, 0.8f); switch (joint.getType()) { // TODO djm write after writing joints case DISTANCE: m_debugDraw.drawSegment(p1, p2, color); break; case PULLEY: { PulleyJoint pulley = (PulleyJoint) joint; Vec2 s1 = pulley.getGroundAnchorA(); Vec2 s2 = pulley.getGroundAnchorB(); m_debugDraw.drawSegment(s1, p1, color); m_debugDraw.drawSegment(s2, p2, color); m_debugDraw.drawSegment(s1, s2, color); } break; case CONSTANT_VOLUME: case MOUSE: // don't draw this break; default: m_debugDraw.drawSegment(x1, p1, color); m_debugDraw.drawSegment(p1, p2, color); m_debugDraw.drawSegment(x2, p2, color); } pool.pushVec2(2); }
@Override public void solveVelocityConstraints(TimeStep step) { Body b = m_bodyB; Vec2 r = pool.popVec2(); r.set(m_localAnchor).subLocal(b.getLocalCenter()); Mat22.mulToOut(b.getTransform().R, r, r); // Cdot = v + cross(w, r) Vec2 Cdot = pool.popVec2(); Vec2.crossToOut(b.m_angularVelocity, r, Cdot); Cdot.addLocal(b.m_linearVelocity); Vec2 impulse = pool.popVec2(); Vec2 temp = pool.popVec2(); // Mul(m_mass, -(Cdot + m_beta * m_C + m_gamma * m_impulse)); impulse.set(m_C).mulLocal(m_beta); temp.set(m_impulse).mulLocal(m_gamma); temp.addLocal(impulse).addLocal(Cdot).mulLocal(-1); Mat22.mulToOut(m_mass, temp, impulse); Vec2 oldImpulse = temp; oldImpulse.set(m_impulse); m_impulse.addLocal(impulse); float maxImpulse = step.dt * m_maxForce; if (m_impulse.lengthSquared() > maxImpulse * maxImpulse) { m_impulse.mulLocal(maxImpulse / m_impulse.length()); } impulse.set(m_impulse).subLocal(oldImpulse); // pooling oldImpulse.set(impulse).mulLocal(b.m_invMass); b.m_linearVelocity.addLocal(oldImpulse); b.m_angularVelocity += b.m_invI * Vec2.cross(r, impulse); pool.pushVec2(4); }
/** Call this to draw shapes and other debug draw data. */ public void drawDebugData() { if (m_debugDraw == null) { return; } int flags = m_debugDraw.getFlags(); if ((flags & DebugDraw.e_shapeBit) == DebugDraw.e_shapeBit) { for (Body b = m_bodyList; b != null; b = b.getNext()) { xf.set(b.getTransform()); for (Fixture f = b.getFixtureList(); f != null; f = f.getNext()) { if (b.isActive() == false) { color.set(0.5f, 0.5f, 0.3f); drawShape(f, xf, color); } else if (b.getType() == BodyType.STATIC) { color.set(0.5f, 0.9f, 0.3f); drawShape(f, xf, color); } else if (b.getType() == BodyType.KINEMATIC) { color.set(0.5f, 0.5f, 0.9f); drawShape(f, xf, color); } else if (b.isAwake() == false) { color.set(0.5f, 0.5f, 0.5f); drawShape(f, xf, color); } else { color.set(0.9f, 0.7f, 0.7f); drawShape(f, xf, color); } } } } if ((flags & DebugDraw.e_jointBit) == DebugDraw.e_jointBit) { for (Joint j = m_jointList; j != null; j = j.getNext()) { drawJoint(j); } } if ((flags & DebugDraw.e_pairBit) == DebugDraw.e_pairBit) { color.set(0.3f, 0.9f, 0.9f); for (Contact c = m_contactManager.m_contactList; c != null; c = c.getNext()) { // Fixture fixtureA = c.getFixtureA(); // Fixture fixtureB = c.getFixtureB(); // // fixtureA.getAABB(childIndex).getCenterToOut(cA); // fixtureB.getAABB().getCenterToOut(cB); // // m_debugDraw.drawSegment(cA, cB, color); } } if ((flags & DebugDraw.e_aabbBit) == DebugDraw.e_aabbBit) { color.set(0.9f, 0.3f, 0.9f); for (Body b = m_bodyList; b != null; b = b.getNext()) { if (b.isActive() == false) { continue; } for (Fixture f = b.getFixtureList(); f != null; f = f.getNext()) { for (int i = 0; i < f.m_proxyCount; ++i) { FixtureProxy proxy = f.m_proxies[i]; AABB aabb = m_contactManager.m_broadPhase.getFatAABB(proxy.proxyId); Vec2[] vs = avs.get(4); vs[0].set(aabb.lowerBound.x, aabb.lowerBound.y); vs[1].set(aabb.upperBound.x, aabb.lowerBound.y); vs[2].set(aabb.upperBound.x, aabb.upperBound.y); vs[3].set(aabb.lowerBound.x, aabb.upperBound.y); m_debugDraw.drawPolygon(vs, 4, color); } } } } if ((flags & DebugDraw.e_centerOfMassBit) == DebugDraw.e_centerOfMassBit) { for (Body b = m_bodyList; b != null; b = b.getNext()) { xf.set(b.getTransform()); xf.p.set(b.getWorldCenter()); m_debugDraw.drawTransform(xf); } } if ((flags & DebugDraw.e_dynamicTreeBit) == DebugDraw.e_dynamicTreeBit) { m_contactManager.m_broadPhase.drawTree(m_debugDraw); } }
@Override public void initVelocityConstraints(TimeStep step) { Body b = m_bodyB; float mass = b.getMass(); // Frequency float omega = 2.0f * MathUtils.PI * m_frequencyHz; // Damping coefficient float d = 2.0f * mass * m_dampingRatio * omega; // Spring stiffness float k = mass * (omega * omega); // magic formulas // gamma has units of inverse mass. // beta has units of inverse time. assert (d + step.dt * k > Settings.EPSILON); m_gamma = step.dt * (d + step.dt * k); if (m_gamma != 0.0f) { m_gamma = 1.0f / m_gamma; } m_beta = step.dt * k * m_gamma; Vec2 r = pool.popVec2(); // Compute the effective mass matrix. // Vec2 r = Mul(b.getTransform().R, m_localAnchor - b.getLocalCenter()); r.set(m_localAnchor).subLocal(b.getLocalCenter()); Mat22.mulToOut(b.getTransform().R, r, r); // K = [(1/m1 + 1/m2) * eye(2) - skew(r1) * invI1 * skew(r1) - skew(r2) * invI2 * skew(r2)] // = [1/m1+1/m2 0 ] + invI1 * [r1.y*r1.y -r1.x*r1.y] + invI2 * [r1.y*r1.y // -r1.x*r1.y] // [ 0 1/m1+1/m2] [-r1.x*r1.y r1.x*r1.x] [-r1.x*r1.y // r1.x*r1.x] float invMass = b.m_invMass; float invI = b.m_invI; Mat22 K1 = pool.popMat22(); K1.m11 = invMass; K1.m21 = 0.0f; K1.m12 = 0.0f; K1.m22 = invMass; Mat22 K2 = pool.popMat22(); K2.m11 = invI * r.y * r.y; K2.m21 = -invI * r.x * r.y; K2.m12 = -invI * r.x * r.y; K2.m22 = invI * r.x * r.x; Mat22 K = pool.popMat22(); K.set(K1).addLocal(K2); K.m11 += m_gamma; K.m22 += m_gamma; K.invertToOut(m_mass); m_C.set(b.m_sweep.c).addLocal(r).subLocal(m_target); // Cheat with some damping b.m_angularVelocity *= 0.98f; // Warm starting. m_impulse.mulLocal(step.dtRatio); // pool Vec2 temp = pool.popVec2(); temp.set(m_impulse).mulLocal(invMass); b.m_linearVelocity.addLocal(temp); b.m_angularVelocity += invI * Vec2.cross(r, m_impulse); pool.pushVec2(2); pool.pushMat22(3); }
/** * Compute the distance from this fixture. * * @param p a point in world coordinates. * @return distance */ public float computeDistance(Vec2 p, int childIndex, Vec2 normalOut) { return m_shape.computeDistanceToOut(m_body.getTransform(), p, childIndex, normalOut); }