org.jbox2d.dynamics.WorldView Maven / Gradle / Ivy
The newest version!
/*
* The MIT License (MIT)
*
* FXGL - JavaFX Game Library
*
* Copyright (c) 2015-2017 AlmasB ([email protected])
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.jbox2d.dynamics;
import com.almasb.fxgl.core.math.Vec2;
import javafx.scene.paint.Color;
import org.jbox2d.callbacks.DebugDraw;
import org.jbox2d.collision.AABB;
import org.jbox2d.collision.shapes.ChainShape;
import org.jbox2d.collision.shapes.CircleShape;
import org.jbox2d.collision.shapes.EdgeShape;
import org.jbox2d.collision.shapes.PolygonShape;
import org.jbox2d.common.JBoxSettings;
import org.jbox2d.common.Transform;
import org.jbox2d.dynamics.contacts.Contact;
import org.jbox2d.dynamics.joints.Joint;
import org.jbox2d.dynamics.joints.PulleyJoint;
import org.jbox2d.particle.ParticleColor;
import org.jbox2d.particle.ParticleSystem;
import org.jbox2d.pooling.arrays.Vec2Array;
/**
* @author Almas Baimagambetov ([email protected])
*/
public class WorldView {
private DebugDraw debugDraw;
private World world;
private final Transform xf = new Transform();
private final Vec2 cA = new Vec2();
private final Vec2 cB = new Vec2();
private final Vec2Array avs = new Vec2Array();
public WorldView(World world, DebugDraw debugDraw) {
this.world = world;
this.debugDraw = debugDraw;
}
/**
* Call this to draw shapes and other debug draw data.
*/
public void drawDebugData() {
Color color = Color.color(0, 0, 0);
int flags = debugDraw.getFlags();
boolean wireframe = (flags & DebugDraw.e_wireframeDrawingBit) != 0;
if ((flags & DebugDraw.e_shapeBit) != 0) {
for (Body b = world.getBodyList(); b != null; b = b.getNext()) {
xf.set(b.getTransform());
for (Fixture f : b.getFixtures()) {
if (!b.isActive()) {
color = Color.color(0.5f, 0.5f, 0.3f);
drawShape(f, xf, color, wireframe);
} else if (b.getType() == BodyType.STATIC) {
color = Color.color(0.5f, 0.9f, 0.3f);
drawShape(f, xf, color, wireframe);
} else if (b.getType() == BodyType.KINEMATIC) {
color = Color.color(0.5f, 0.5f, 0.9f);
drawShape(f, xf, color, wireframe);
} else if (!b.isAwake()) {
color = Color.color(0.5f, 0.5f, 0.5f);
drawShape(f, xf, color, wireframe);
} else {
color = Color.color(0.9f, 0.7f, 0.7f);
drawShape(f, xf, color, wireframe);
}
}
}
drawParticleSystem(world.getParticleSystem());
}
if ((flags & DebugDraw.e_jointBit) != 0) {
for (Joint j = world.getJointList(); j != null; j = j.getNext()) {
drawJoint(j);
}
}
if ((flags & DebugDraw.e_pairBit) != 0) {
color = Color.color(0.3f, 0.9f, 0.9f);
for (Contact c = world.getContactManager().m_contactList; c != null; c = c.getNext()) {
Fixture fixtureA = c.getFixtureA();
Fixture fixtureB = c.getFixtureB();
fixtureA.getAABB(c.getChildIndexA()).getCenterToOut(cA);
fixtureB.getAABB(c.getChildIndexB()).getCenterToOut(cB);
debugDraw.drawSegment(cA, cB, color);
}
}
if ((flags & DebugDraw.e_aabbBit) != 0) {
color = Color.color(0.9f, 0.3f, 0.9f);
for (Body b = world.getBodyList(); b != null; b = b.getNext()) {
if (!b.isActive()) {
continue;
}
for (Fixture f : b.getFixtures()) {
for (int i = 0; i < f.getProxyCount(); ++i) {
FixtureProxy proxy = f.m_proxies[i];
AABB aabb = world.getContactManager().m_broadPhase.getFatAABB(proxy.proxyId);
if (aabb != null) {
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);
debugDraw.drawPolygon(vs, 4, color);
}
}
}
}
}
if ((flags & DebugDraw.e_centerOfMassBit) != 0) {
for (Body b = world.getBodyList(); b != null; b = b.getNext()) {
xf.set(b.getTransform());
xf.p.set(b.getWorldCenter());
debugDraw.drawTransform(xf);
}
}
if ((flags & DebugDraw.e_dynamicTreeBit) != 0) {
world.getContactManager().m_broadPhase.drawTree(debugDraw);
}
debugDraw.flush();
}
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 = world.getPool().popVec2();
Vec2 p2 = world.getPool().popVec2();
joint.getAnchorA(p1);
joint.getAnchorB(p2);
Color color = Color.color(0.5f, 0.8f, 0.8f);
switch (joint.getType()) {
// jbox2dTODO djm write after writing joints
case DISTANCE:
debugDraw.drawSegment(p1, p2, color);
break;
case PULLEY: {
PulleyJoint pulley = (PulleyJoint) joint;
Vec2 s1 = pulley.getGroundAnchorA();
Vec2 s2 = pulley.getGroundAnchorB();
debugDraw.drawSegment(s1, p1, color);
debugDraw.drawSegment(s2, p2, color);
debugDraw.drawSegment(s1, s2, color);
}
break;
case CONSTANT_VOLUME:
case MOUSE:
// don't draw this
break;
default:
debugDraw.drawSegment(x1, p1, color);
debugDraw.drawSegment(p1, p2, color);
debugDraw.drawSegment(x2, p2, color);
}
world.getPool().pushVec2(2);
}
// NOTE this corresponds to the liquid test, so the debugdraw can draw
// the liquid particles correctly. They should be the same.
private static Integer LIQUID_INT = new Integer(1234598372);
private float liquidLength = .12f;
private float averageLinearVel = -1;
private final Vec2 liquidOffset = new Vec2();
private final Vec2 circCenterMoved = new Vec2();
private final Color liquidColor = Color.color(.4, .4, 1);
private final Vec2 center = new Vec2();
private final Vec2 axis = new Vec2();
private final Vec2 v1 = new Vec2();
private final Vec2 v2 = new Vec2();
private final Vec2Array tlvertices = new Vec2Array();
private void drawShape(Fixture fixture, Transform xf, Color color, boolean wireframe) {
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.getRadius();
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);
debugDraw.drawSegment(center, circCenterMoved, liquidColor);
return;
}
if (wireframe) {
debugDraw.drawCircle(center, radius, axis, color);
} else {
debugDraw.drawSolidCircle(center, radius, axis, color);
}
}
break;
case POLYGON: {
PolygonShape poly = (PolygonShape) fixture.getShape();
int vertexCount = poly.getVertexCount();
assert (vertexCount <= JBoxSettings.maxPolygonVertices);
Vec2[] vertices = tlvertices.get(JBoxSettings.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]);
}
if (wireframe) {
debugDraw.drawPolygon(vertices, vertexCount, color);
} else {
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);
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);
debugDraw.drawSegment(v1, v2, color);
debugDraw.drawCircle(v1, 0.05f, color);
v1.set(v2);
}
}
break;
default:
break;
}
}
private void drawParticleSystem(ParticleSystem system) {
boolean wireframe = (debugDraw.getFlags() & DebugDraw.e_wireframeDrawingBit) != 0;
int particleCount = system.getParticleCount();
if (particleCount != 0) {
float particleRadius = system.getParticleRadius();
Vec2[] positionBuffer = system.getParticlePositionBuffer();
ParticleColor[] colorBuffer = null;
if (system.m_colorBuffer.data != null) {
colorBuffer = system.getParticleColorBuffer();
}
if (wireframe) {
debugDraw.drawParticlesWireframe(positionBuffer, particleRadius, colorBuffer,
particleCount);
} else {
debugDraw.drawParticles(positionBuffer, particleRadius, colorBuffer, particleCount);
}
}
}
}