public final void getSearchDirection(final Vec2 out) { switch (m_count) { case 1: out.set(m_v1.w).negateLocal(); return; case 2: e12.set(m_v2.w).subLocal(m_v1.w); // use out for a temp variable real quick out.set(m_v1.w).negateLocal(); float sgn = Vec2.cross(e12, out); if (sgn > 0f) { // Origin is left of e12. Vec2.crossToOutUnsafe(1f, e12, out); return; } else { // Origin is right of e12. Vec2.crossToOutUnsafe(e12, 1f, out); return; } default: assert (false); out.setZero(); return; } }
/** * this returns pooled objects. don't keep or modify them * * @return */ public void getClosestPoint(final Vec2 out) { switch (m_count) { case 0: assert (false); out.setZero(); return; case 1: out.set(m_v1.w); return; case 2: case22.set(m_v2.w).mulLocal(m_v2.a); case2.set(m_v1.w).mulLocal(m_v1.a).addLocal(case22); out.set(case2); return; case 3: out.setZero(); return; default: assert (false); out.setZero(); return; } }
@Override public boolean solvePositionConstraints(final SolverData data) { final Rot qA = pool.popRot(); final Rot qB = pool.popRot(); final Vec2 rA = pool.popVec2(); final Vec2 rB = pool.popVec2(); final Vec2 uA = pool.popVec2(); final Vec2 uB = pool.popVec2(); final Vec2 temp = pool.popVec2(); final Vec2 PA = pool.popVec2(); final Vec2 PB = pool.popVec2(); Vec2 cA = data.positions[m_indexA].c; float aA = data.positions[m_indexA].a; Vec2 cB = data.positions[m_indexB].c; float aB = data.positions[m_indexB].a; qA.set(aA); qB.set(aB); Rot.mulToOutUnsafe(qA, temp.set(m_localAnchorA).subLocal(m_localCenterA), rA); Rot.mulToOutUnsafe(qB, temp.set(m_localAnchorB).subLocal(m_localCenterB), rB); uA.set(cA).addLocal(rA).subLocal(m_groundAnchorA); uB.set(cB).addLocal(rB).subLocal(m_groundAnchorB); float lengthA = uA.length(); float lengthB = uB.length(); if (lengthA > 10.0f * Settings.linearSlop) { uA.mulLocal(1.0f / lengthA); } else { uA.setZero(); } if (lengthB > 10.0f * Settings.linearSlop) { uB.mulLocal(1.0f / lengthB); } else { uB.setZero(); } // Compute effective mass. float ruA = Vec2.cross(rA, uA); float ruB = Vec2.cross(rB, uB); float mA = m_invMassA + m_invIA * ruA * ruA; float mB = m_invMassB + m_invIB * ruB * ruB; float mass = mA + m_ratio * m_ratio * mB; if (mass > 0.0f) { mass = 1.0f / mass; } float C = m_constant - lengthA - m_ratio * lengthB; float linearError = MathUtils.abs(C); float impulse = -mass * C; PA.set(uA).mulLocal(-impulse); PB.set(uB).mulLocal(-m_ratio * impulse); cA.x += m_invMassA * PA.x; cA.y += m_invMassA * PA.y; aA += m_invIA * Vec2.cross(rA, PA); cB.x += m_invMassB * PB.x; cB.y += m_invMassB * PB.y; aB += m_invIB * Vec2.cross(rB, PB); // data.positions[m_indexA].c.set(cA); data.positions[m_indexA].a = aA; // data.positions[m_indexB].c.set(cB); data.positions[m_indexB].a = aB; pool.pushRot(2); pool.pushVec2(7); return linearError < Settings.linearSlop; }
@Override public void initVelocityConstraints(final SolverData data) { m_indexA = m_bodyA.m_islandIndex; m_indexB = m_bodyB.m_islandIndex; m_localCenterA.set(m_bodyA.m_sweep.localCenter); m_localCenterB.set(m_bodyB.m_sweep.localCenter); m_invMassA = m_bodyA.m_invMass; m_invMassB = m_bodyB.m_invMass; m_invIA = m_bodyA.m_invI; m_invIB = m_bodyB.m_invI; Vec2 cA = data.positions[m_indexA].c; float aA = data.positions[m_indexA].a; Vec2 vA = data.velocities[m_indexA].v; float wA = data.velocities[m_indexA].w; Vec2 cB = data.positions[m_indexB].c; float aB = data.positions[m_indexB].a; Vec2 vB = data.velocities[m_indexB].v; float wB = data.velocities[m_indexB].w; final Rot qA = pool.popRot(); final Rot qB = pool.popRot(); final Vec2 temp = pool.popVec2(); qA.set(aA); qB.set(aB); // Compute the effective masses. Rot.mulToOutUnsafe(qA, temp.set(m_localAnchorA).subLocal(m_localCenterA), m_rA); Rot.mulToOutUnsafe(qB, temp.set(m_localAnchorB).subLocal(m_localCenterB), m_rB); m_uA.set(cA).addLocal(m_rA).subLocal(m_groundAnchorA); m_uB.set(cB).addLocal(m_rB).subLocal(m_groundAnchorB); float lengthA = m_uA.length(); float lengthB = m_uB.length(); if (lengthA > 10f * Settings.linearSlop) { m_uA.mulLocal(1.0f / lengthA); } else { m_uA.setZero(); } if (lengthB > 10f * Settings.linearSlop) { m_uB.mulLocal(1.0f / lengthB); } else { m_uB.setZero(); } // Compute effective mass. float ruA = Vec2.cross(m_rA, m_uA); float ruB = Vec2.cross(m_rB, m_uB); float mA = m_invMassA + m_invIA * ruA * ruA; float mB = m_invMassB + m_invIB * ruB * ruB; m_mass = mA + m_ratio * m_ratio * mB; if (m_mass > 0.0f) { m_mass = 1.0f / m_mass; } if (data.step.warmStarting) { // Scale impulses to support variable time steps. m_impulse *= data.step.dtRatio; // Warm starting. final Vec2 PA = pool.popVec2(); final Vec2 PB = pool.popVec2(); PA.set(m_uA).mulLocal(-m_impulse); PB.set(m_uB).mulLocal(-m_ratio * m_impulse); vA.x += m_invMassA * PA.x; vA.y += m_invMassA * PA.y; wA += m_invIA * Vec2.cross(m_rA, PA); vB.x += m_invMassB * PB.x; vB.y += m_invMassB * PB.y; wB += m_invIB * Vec2.cross(m_rB, PB); pool.pushVec2(2); } else { m_impulse = 0.0f; } // data.velocities[m_indexA].v.set(vA); data.velocities[m_indexA].w = wA; // data.velocities[m_indexB].v.set(vB); data.velocities[m_indexB].w = wB; pool.pushVec2(1); pool.pushRot(2); }