/** @see Shape#computeSweptAABB(AABB, XForm, XForm) */ @Override public void computeSweptAABB(final AABB aabb, final XForm transform1, final XForm transform2) { // djm this method is pretty hot (called every time step) final Vec2 sweptV1 = tlSwept1.get(); final Vec2 sweptV2 = tlSwept2.get(); final Vec2 sweptV3 = tlSwept3.get(); final Vec2 sweptV4 = tlSwept4.get(); XForm.mulToOut(transform1, m_v1, sweptV1); XForm.mulToOut(transform1, m_v2, sweptV2); XForm.mulToOut(transform2, m_v1, sweptV3); XForm.mulToOut(transform2, m_v2, sweptV4); // aabb.lowerBound = Vec2.min(Vec2.min(Vec2.min(v1, v2), v3), v4); // aabb.upperBound = Vec2.max(Vec2.max(Vec2.max(v1, v2), v3), v4); // djm ok here's the non object-creation-crazy way Vec2.minToOut(sweptV1, sweptV2, aabb.lowerBound); Vec2.minToOut(aabb.lowerBound, sweptV3, aabb.lowerBound); Vec2.minToOut(aabb.lowerBound, sweptV4, aabb.lowerBound); Vec2.maxToOut(sweptV1, sweptV2, aabb.upperBound); Vec2.maxToOut(aabb.upperBound, sweptV3, aabb.upperBound); Vec2.maxToOut(aabb.upperBound, sweptV4, aabb.upperBound); }
/** @see SupportsGenericDistance#support(Vec2, XForm, Vec2) */ public void support(final Vec2 dest, final XForm xf, final Vec2 d) { final Vec2 supportV1 = tlSupportV1.get(); final Vec2 supportV2 = tlSupportV2.get(); XForm.mulToOut(xf, m_coreV1, supportV1); XForm.mulToOut(xf, m_coreV2, supportV2); dest.set(Vec2.dot(supportV1, d) > Vec2.dot(supportV2, d) ? supportV1 : supportV2); }
/** @see Shape#testSegment(XForm, RaycastResult, Segment, float) */ @Override public SegmentCollide testSegment( final XForm xf, final RaycastResult out, final Segment segment, final float maxLambda) { final Vec2 r = tlR.get(); final Vec2 v1 = tlV1.get(); final Vec2 d = tlD.get(); final Vec2 n = tlN.get(); final Vec2 b = tlB.get(); r.set(segment.p2).subLocal(segment.p1); XForm.mulToOut(xf, m_v1, v1); XForm.mulToOut(xf, m_v2, d); d.subLocal(v1); Vec2.crossToOut(d, 1.0f, n); final float k_slop = 100.0f * Settings.EPSILON; final float denom = -Vec2.dot(r, n); // Cull back facing collision and ignore parallel segments. if (denom > k_slop) { // Does the segment intersect the infinite line associated with this segment? b.set(segment.p1).subLocal(v1); float a = Vec2.dot(b, n); if (0.0f <= a && a <= maxLambda * denom) { final float mu2 = -r.x * b.y + r.y * b.x; // Does the segment intersect this segment? if (-k_slop * denom <= mu2 && mu2 <= denom * (1.0f + k_slop)) { a /= denom; n.normalize(); out.lambda = a; out.normal.set(n); return SegmentCollide.HIT_COLLIDE; } } } return SegmentCollide.MISS_COLLIDE; }
/** @see Shape#computeAABB(AABB, XForm) */ @Override public void computeAABB(final AABB aabb, final XForm transform) { /*Vec2 v1 = XForm.mul(transform, m_v1); Vec2 v2 = XForm.mul(transform, m_v2); aabb.lowerBound = Vec2.min(v1, v2); aabb.upperBound = Vec2.max(v1, v2);*/ // djm we avoid one creation. crafty huh? XForm.mulToOut(transform, m_v1, aabb.lowerBound); final Vec2 v2 = tlV2.get(); XForm.mulToOut(transform, m_v2, v2); Vec2.maxToOut(aabb.lowerBound, v2, aabb.upperBound); Vec2.minToOut(aabb.lowerBound, v2, aabb.lowerBound); }
public float computeSubmergedArea(final Vec2 normal, float offset, XForm xf, Vec2 c) { final Vec2 v0 = tlV0.get(); final Vec2 v1 = tlV1.get(); final Vec2 v2 = tlV2.get(); final Vec2 temp = tlTemp.get(); // Note that v0 is independent of any details of the specific edge // We are relying on v0 being consistent between multiple edges of the same body v0.set(normal).mul(offset); // b2Vec2 v0 = xf.position + (offset - b2Dot(normal, xf.position)) * normal; XForm.mulToOut(xf, m_v1, v1); XForm.mulToOut(xf, m_v2, v2); float d1 = Vec2.dot(normal, v1) - offset; float d2 = Vec2.dot(normal, v2) - offset; if (d1 > 0.0f) { if (d2 > 0.0f) { return 0.0f; } else { temp.set(v2).mulLocal(d1 / (d1 - d2)); v1.mulLocal(-d2 / (d1 - d2)).addLocal(temp); } } else { if (d2 > 0.0f) { temp.set(v1).mulLocal(-d2 / (d1 - d2)); v2.mulLocal(d1 / (d1 - d2)).addLocal(temp); } else { // Nothing } } final Vec2 e1 = tlE1.get(); final Vec2 e2 = tlE2.get(); // v0,v1,v2 represents a fully submerged triangle float k_inv3 = 1.0f / 3.0f; // Area weighted centroid c.x = k_inv3 * (v0.x + v1.x + v2.x); c.y = k_inv3 * (v0.y + v1.y + v2.y); e1.set(v1).subLocal(v0); e2.set(v2).subLocal(v0); return 0.5f * Vec2.cross(e1, e2); }