/** * Create a convex hull from the given array of points. The count must be in the range [3, * Settings.maxPolygonVertices]. This method takes an arraypool for pooling * * @warning the points may be re-ordered, even if they form a convex polygon * @warning collinear points are handled but not removed. Collinear points may lead to poor * stacking behavior. */ public final void set( final Vec2[] verts, final int num, final Vec2Array vecPool, final IntArray intPool) { assert (3 <= num && num <= Settings.maxPolygonVertices); if (num < 3) { setAsBox(1.0f, 1.0f); return; } int n = MathUtils.min(num, Settings.maxPolygonVertices); // Copy the vertices into a local buffer Vec2[] ps = (vecPool != null) ? vecPool.get(n) : new Vec2[n]; for (int i = 0; i < n; ++i) { ps[i] = verts[i]; } // Create the convex hull using the Gift wrapping algorithm // http://en.wikipedia.org/wiki/Gift_wrapping_algorithm // Find the right most point on the hull int i0 = 0; float x0 = ps[0].x; for (int i = 1; i < num; ++i) { float x = ps[i].x; if (x > x0 || (x == x0 && ps[i].y < ps[i0].y)) { i0 = i; x0 = x; } } int[] hull = (intPool != null) ? intPool.get(Settings.maxPolygonVertices) : new int[Settings.maxPolygonVertices]; int m = 0; int ih = i0; while (true) { hull[m] = ih; int ie = 0; for (int j = 1; j < n; ++j) { if (ie == ih) { ie = j; continue; } Vec2 r = pool1.set(ps[ie]).subLocal(ps[hull[m]]); Vec2 v = pool2.set(ps[j]).subLocal(ps[hull[m]]); float c = Vec2.cross(r, v); if (c < 0.0f) { ie = j; } // Collinearity check if (c == 0.0f && v.lengthSquared() > r.lengthSquared()) { ie = j; } } ++m; ih = ie; if (ie == i0) { break; } } this.m_count = m; // Copy vertices. for (int i = 0; i < m_count; ++i) { if (m_vertices[i] == null) { m_vertices[i] = new Vec2(); } m_vertices[i].set(ps[hull[i]]); } final Vec2 edge = pool1; // Compute normals. Ensure the edges have non-zero length. for (int i = 0; i < m_count; ++i) { final int i1 = i; final int i2 = i + 1 < m_count ? i + 1 : 0; edge.set(m_vertices[i2]).subLocal(m_vertices[i1]); assert (edge.lengthSquared() > Settings.EPSILON * Settings.EPSILON); Vec2.crossToOutUnsafe(edge, 1f, m_normals[i]); m_normals[i].normalize(); } // Compute the polygon centroid. computeCentroidToOut(m_vertices, m_count, m_centroid); }
private void drawShape(Fixture fixture, Transform xf, Color3f color) { switch (fixture.getType()) { case CIRCLE: { CircleShape circle = (CircleShape) fixture.getShape(); // Vec2 center = Mul(xf, circle.m_p); Transform.mulToOutUnsafe(xf, circle.m_p, center); float radius = circle.m_radius; xf.q.getXAxis(axis); if (fixture.getUserData() != null && fixture.getUserData().equals(LIQUID_INT)) { Body b = fixture.getBody(); liquidOffset.set(b.m_linearVelocity); float linVelLength = b.m_linearVelocity.length(); if (averageLinearVel == -1) { averageLinearVel = linVelLength; } else { averageLinearVel = .98f * averageLinearVel + .02f * linVelLength; } liquidOffset.mulLocal(liquidLength / averageLinearVel / 2); circCenterMoved.set(center).addLocal(liquidOffset); center.subLocal(liquidOffset); m_debugDraw.drawSegment(center, circCenterMoved, liquidColor); return; } m_debugDraw.drawSolidCircle(center, radius, axis, color); } break; case POLYGON: { PolygonShape poly = (PolygonShape) fixture.getShape(); int vertexCount = poly.m_count; assert (vertexCount <= Settings.maxPolygonVertices); Vec2[] vertices = tlvertices.get(Settings.maxPolygonVertices); for (int i = 0; i < vertexCount; ++i) { // vertices[i] = Mul(xf, poly.m_vertices[i]); Transform.mulToOutUnsafe(xf, poly.m_vertices[i], vertices[i]); } m_debugDraw.drawSolidPolygon(vertices, vertexCount, color); } break; case EDGE: { EdgeShape edge = (EdgeShape) fixture.getShape(); Transform.mulToOutUnsafe(xf, edge.m_vertex1, v1); Transform.mulToOutUnsafe(xf, edge.m_vertex2, v2); m_debugDraw.drawSegment(v1, v2, color); } break; case CHAIN: { ChainShape chain = (ChainShape) fixture.getShape(); int count = chain.m_count; Vec2[] vertices = chain.m_vertices; Transform.mulToOutUnsafe(xf, vertices[0], v1); for (int i = 1; i < count; ++i) { Transform.mulToOutUnsafe(xf, vertices[i], v2); m_debugDraw.drawSegment(v1, v2, color); m_debugDraw.drawCircle(v1, 0.05f, color); v1.set(v2); } } break; default: break; } }
/** 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); } }
public void drawAABB(AABB argAABB, Color3f color) { Vec2 vecs[] = vec2Array.get(4); argAABB.getVertices(vecs); drawPolygon(vecs, 4, color); }