- add new BulletDebugAppState for physics debugging
- fix non-displayed physics objects in debug view - remove dependency of base physics objects to scenegraph api, only jme math dependencies are left git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@10342 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
This commit is contained in:
parent
2d5800d667
commit
8992563b86
@ -35,6 +35,7 @@ import com.jme3.app.Application;
|
||||
import com.jme3.app.state.AppState;
|
||||
import com.jme3.app.state.AppStateManager;
|
||||
import com.jme3.bullet.PhysicsSpace.BroadphaseType;
|
||||
import com.jme3.bullet.debug.BulletDebugAppState;
|
||||
import com.jme3.math.Vector3f;
|
||||
import com.jme3.renderer.RenderManager;
|
||||
import java.util.concurrent.*;
|
||||
@ -43,6 +44,7 @@ import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* <code>BulletAppState</code> allows using bullet physics in an Application.
|
||||
*
|
||||
* @author normenhansen
|
||||
*/
|
||||
public class BulletAppState implements AppState, PhysicsTickListener {
|
||||
@ -56,31 +58,38 @@ public class BulletAppState implements AppState, PhysicsTickListener {
|
||||
protected BroadphaseType broadphaseType = BroadphaseType.DBVT;
|
||||
protected Vector3f worldMin = new Vector3f(-10000f, -10000f, -10000f);
|
||||
protected Vector3f worldMax = new Vector3f(10000f, 10000f, 10000f);
|
||||
private float speed = 1;
|
||||
protected float speed = 1;
|
||||
protected boolean active = true;
|
||||
protected boolean debugEnabled = false;
|
||||
protected BulletDebugAppState debugAppState;
|
||||
protected float tpf;
|
||||
protected Future physicsFuture;
|
||||
|
||||
/**
|
||||
* Creates a new BulletAppState running a PhysicsSpace for physics simulation,
|
||||
* use getStateManager().addState(bulletAppState) to enable physics for an Application.
|
||||
* Creates a new BulletAppState running a PhysicsSpace for physics
|
||||
* simulation, use getStateManager().addState(bulletAppState) to enable
|
||||
* physics for an Application.
|
||||
*/
|
||||
public BulletAppState() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new BulletAppState running a PhysicsSpace for physics simulation,
|
||||
* use getStateManager().addState(bulletAppState) to enable physics for an Application.
|
||||
* @param broadphaseType The type of broadphase collision detection, BroadphaseType.DVBT is the default
|
||||
* Creates a new BulletAppState running a PhysicsSpace for physics
|
||||
* simulation, use getStateManager().addState(bulletAppState) to enable
|
||||
* physics for an Application.
|
||||
*
|
||||
* @param broadphaseType The type of broadphase collision detection,
|
||||
* BroadphaseType.DVBT is the default
|
||||
*/
|
||||
public BulletAppState(BroadphaseType broadphaseType) {
|
||||
this(new Vector3f(-10000f, -10000f, -10000f), new Vector3f(10000f, 10000f, 10000f), broadphaseType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new BulletAppState running a PhysicsSpace for physics simulation,
|
||||
* use getStateManager().addState(bulletAppState) to enable physics for an Application.
|
||||
* An AxisSweep broadphase is used.
|
||||
* Creates a new BulletAppState running a PhysicsSpace for physics
|
||||
* simulation, use getStateManager().addState(bulletAppState) to enable
|
||||
* physics for an Application. An AxisSweep broadphase is used.
|
||||
*
|
||||
* @param worldMin The minimum world extent
|
||||
* @param worldMax The maximum world extent
|
||||
*/
|
||||
@ -101,7 +110,6 @@ public class BulletAppState implements AppState, PhysicsTickListener {
|
||||
executor = new ScheduledThreadPoolExecutor(1);
|
||||
final BulletAppState app = this;
|
||||
Callable<Boolean> call = new Callable<Boolean>() {
|
||||
|
||||
public Boolean call() throws Exception {
|
||||
detachedPhysicsLastUpdate = System.currentTimeMillis();
|
||||
pSpace = new PhysicsSpace(worldMin, worldMax, broadphaseType);
|
||||
@ -120,7 +128,6 @@ public class BulletAppState implements AppState, PhysicsTickListener {
|
||||
}
|
||||
}
|
||||
private Callable<Boolean> parallelPhysicsUpdate = new Callable<Boolean>() {
|
||||
|
||||
public Boolean call() throws Exception {
|
||||
pSpace.update(tpf * getSpeed());
|
||||
return true;
|
||||
@ -128,7 +135,6 @@ public class BulletAppState implements AppState, PhysicsTickListener {
|
||||
};
|
||||
long detachedPhysicsLastUpdate = 0;
|
||||
private Callable<Boolean> detachedPhysicsUpdate = new Callable<Boolean>() {
|
||||
|
||||
public Boolean call() throws Exception {
|
||||
pSpace.update(getPhysicsSpace().getAccuracy() * getSpeed());
|
||||
pSpace.distributeEvents();
|
||||
@ -144,8 +150,8 @@ public class BulletAppState implements AppState, PhysicsTickListener {
|
||||
}
|
||||
|
||||
/**
|
||||
* The physics system is started automatically on attaching, if you want to start it
|
||||
* before for some reason, you can use this method.
|
||||
* The physics system is started automatically on attaching, if you want to
|
||||
* start it before for some reason, you can use this method.
|
||||
*/
|
||||
public void startPhysics() {
|
||||
//start physics thread(pool)
|
||||
@ -165,21 +171,30 @@ public class BulletAppState implements AppState, PhysicsTickListener {
|
||||
if (!initialized) {
|
||||
startPhysics();
|
||||
}
|
||||
this.stateManager = stateManager;
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
public boolean isInitialized() {
|
||||
return initialized;
|
||||
}
|
||||
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.active = enabled;
|
||||
}
|
||||
|
||||
|
||||
public boolean isEnabled() {
|
||||
return active;
|
||||
}
|
||||
|
||||
public void setDebugEnabled(boolean debugEnabled) {
|
||||
this.debugEnabled = debugEnabled;
|
||||
}
|
||||
|
||||
public boolean isDebugEnabled() {
|
||||
return debugEnabled;
|
||||
}
|
||||
|
||||
public void stateAttached(AppStateManager stateManager) {
|
||||
if (!initialized) {
|
||||
startPhysics();
|
||||
@ -187,17 +202,36 @@ public class BulletAppState implements AppState, PhysicsTickListener {
|
||||
if (threadingType == ThreadingType.PARALLEL) {
|
||||
PhysicsSpace.setLocalThreadPhysicsSpace(pSpace);
|
||||
}
|
||||
if (debugEnabled) {
|
||||
debugAppState = new BulletDebugAppState(pSpace);
|
||||
stateManager.attach(debugAppState);
|
||||
}
|
||||
}
|
||||
|
||||
public void stateDetached(AppStateManager stateManager) {
|
||||
}
|
||||
|
||||
public void update(float tpf) {
|
||||
if (debugEnabled && debugAppState == null) {
|
||||
debugAppState = new BulletDebugAppState(pSpace);
|
||||
stateManager.attach(debugAppState);
|
||||
pSpace.enableDebug(app.getAssetManager());
|
||||
} else if (!debugEnabled && debugAppState != null) {
|
||||
stateManager.detach(debugAppState);
|
||||
debugAppState = null;
|
||||
pSpace.enableDebug(null);
|
||||
}
|
||||
//TODO: remove when deprecation of PhysicsSpace.enableDebug is through
|
||||
if (pSpace.getDebugManager() != null && !debugEnabled) {
|
||||
debugEnabled = true;
|
||||
} else if (pSpace.getDebugManager() == null && debugEnabled) {
|
||||
debugEnabled = false;
|
||||
}
|
||||
if (!active) {
|
||||
return;
|
||||
}
|
||||
// if (threadingType != ThreadingType.DETACHED) {
|
||||
pSpace.distributeEvents();
|
||||
pSpace.distributeEvents();
|
||||
// }
|
||||
this.tpf = tpf;
|
||||
}
|
||||
@ -228,6 +262,10 @@ public class BulletAppState implements AppState, PhysicsTickListener {
|
||||
}
|
||||
|
||||
public void cleanup() {
|
||||
if (debugAppState != null) {
|
||||
stateManager.detach(debugAppState);
|
||||
debugAppState = null;
|
||||
}
|
||||
if (executor != null) {
|
||||
executor.shutdown();
|
||||
executor = null;
|
||||
@ -245,6 +283,7 @@ public class BulletAppState implements AppState, PhysicsTickListener {
|
||||
|
||||
/**
|
||||
* Use before attaching state
|
||||
*
|
||||
* @param threadingType the threadingType to set
|
||||
*/
|
||||
public void setThreadingType(ThreadingType threadingType) {
|
||||
@ -289,13 +328,14 @@ public class BulletAppState implements AppState, PhysicsTickListener {
|
||||
public enum ThreadingType {
|
||||
|
||||
/**
|
||||
* Default mode; user update, physics update and rendering happen sequentially (single threaded)
|
||||
* Default mode; user update, physics update and rendering happen
|
||||
* sequentially (single threaded)
|
||||
*/
|
||||
SEQUENTIAL,
|
||||
/**
|
||||
* Parallel threaded mode; physics update and rendering are executed in parallel, update order is kept.<br/>
|
||||
* Multiple BulletAppStates will execute in parallel in this mode.
|
||||
* Parallel threaded mode; physics update and rendering are executed in
|
||||
* parallel, update order is kept.<br/> Multiple BulletAppStates will
|
||||
* execute in parallel in this mode.
|
||||
*/
|
||||
PARALLEL,
|
||||
}
|
||||
PARALLEL,}
|
||||
}
|
||||
|
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package com.jme3.bullet.debug;
|
||||
|
||||
import com.jme3.math.Quaternion;
|
||||
import com.jme3.math.Vector3f;
|
||||
import com.jme3.scene.Spatial;
|
||||
import com.jme3.scene.control.AbstractControl;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author normenhansen
|
||||
*/
|
||||
public abstract class AbstractPhysicsDebugControl extends AbstractControl {
|
||||
|
||||
private final Quaternion tmp_inverseWorldRotation = new Quaternion();
|
||||
protected final BulletDebugAppState debugAppState;
|
||||
|
||||
public AbstractPhysicsDebugControl(BulletDebugAppState debugAppState) {
|
||||
this.debugAppState = debugAppState;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called on the physics thread for debug controls
|
||||
*/
|
||||
@Override
|
||||
protected abstract void controlUpdate(float tpf);
|
||||
|
||||
protected void applyPhysicsTransform(Vector3f worldLocation, Quaternion worldRotation) {
|
||||
applyPhysicsTransform(worldLocation, worldRotation, this.spatial);
|
||||
}
|
||||
|
||||
protected void applyPhysicsTransform(Vector3f worldLocation, Quaternion worldRotation, Spatial spatial) {
|
||||
if (spatial != null) {
|
||||
Vector3f localLocation = spatial.getLocalTranslation();
|
||||
Quaternion localRotationQuat = spatial.getLocalRotation();
|
||||
if (spatial.getParent() != null) {
|
||||
localLocation.set(worldLocation).subtractLocal(spatial.getParent().getWorldTranslation());
|
||||
localLocation.divideLocal(spatial.getParent().getWorldScale());
|
||||
tmp_inverseWorldRotation.set(spatial.getParent().getWorldRotation()).inverseLocal().multLocal(localLocation);
|
||||
localRotationQuat.set(worldRotation);
|
||||
tmp_inverseWorldRotation.set(spatial.getParent().getWorldRotation()).inverseLocal().mult(localRotationQuat, localRotationQuat);
|
||||
spatial.setLocalTranslation(localLocation);
|
||||
spatial.setLocalRotation(localRotationQuat);
|
||||
} else {
|
||||
spatial.setLocalTranslation(worldLocation);
|
||||
spatial.setLocalRotation(worldRotation);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package com.jme3.bullet.debug;
|
||||
|
||||
import com.jme3.bullet.objects.PhysicsCharacter;
|
||||
import com.jme3.math.Quaternion;
|
||||
import com.jme3.math.Vector3f;
|
||||
import com.jme3.renderer.RenderManager;
|
||||
import com.jme3.renderer.ViewPort;
|
||||
import com.jme3.scene.Geometry;
|
||||
import com.jme3.scene.Mesh;
|
||||
import com.jme3.scene.Node;
|
||||
import com.jme3.scene.Spatial;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author normenhansen
|
||||
*/
|
||||
public class BulletCharacterDebugControl extends AbstractPhysicsDebugControl {
|
||||
|
||||
protected final PhysicsCharacter body;
|
||||
protected final Geometry geom;
|
||||
protected final Vector3f location = new Vector3f();
|
||||
protected final Quaternion rotation = new Quaternion();
|
||||
|
||||
public BulletCharacterDebugControl(BulletDebugAppState debugAppState, PhysicsCharacter body) {
|
||||
super(debugAppState);
|
||||
this.body = body;
|
||||
this.geom = new Geometry(body.toString());
|
||||
geom.setMaterial(debugAppState.DEBUG_PINK);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSpatial(Spatial spatial) {
|
||||
if (spatial != null && spatial instanceof Node) {
|
||||
Node node = (Node) spatial;
|
||||
node.attachChild(geom);
|
||||
} else if (spatial == null && this.spatial != null) {
|
||||
Node node = (Node) this.spatial;
|
||||
node.detachChild(geom);
|
||||
}
|
||||
super.setSpatial(spatial);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void controlUpdate(float tpf) {
|
||||
Mesh mesh = debugAppState.getShapeBuffer().getShapeMesh(body.getCollisionShape());
|
||||
if (mesh != null) {
|
||||
if (geom.getMesh() != mesh) {
|
||||
geom.setMesh(mesh);
|
||||
}
|
||||
} else {
|
||||
if (geom.getMesh() != BulletDebugAppState.CollisionShapeBuffer.NO_MESH) {
|
||||
geom.setMesh(BulletDebugAppState.CollisionShapeBuffer.NO_MESH);
|
||||
}
|
||||
}
|
||||
applyPhysicsTransform(body.getPhysicsLocation(location), Quaternion.IDENTITY);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void controlRender(RenderManager rm, ViewPort vp) {
|
||||
}
|
||||
}
|
@ -0,0 +1,361 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package com.jme3.bullet.debug;
|
||||
|
||||
import com.jme3.app.Application;
|
||||
import com.jme3.app.state.AbstractAppState;
|
||||
import com.jme3.app.state.AppStateManager;
|
||||
import com.jme3.asset.AssetManager;
|
||||
import com.jme3.bullet.PhysicsSpace;
|
||||
import com.jme3.bullet.collision.shapes.CollisionShape;
|
||||
import com.jme3.bullet.joints.PhysicsJoint;
|
||||
import com.jme3.bullet.objects.PhysicsCharacter;
|
||||
import com.jme3.bullet.objects.PhysicsGhostObject;
|
||||
import com.jme3.bullet.objects.PhysicsRigidBody;
|
||||
import com.jme3.bullet.objects.PhysicsVehicle;
|
||||
import com.jme3.bullet.util.DebugShapeFactory;
|
||||
import com.jme3.material.Material;
|
||||
import com.jme3.math.ColorRGBA;
|
||||
import com.jme3.math.Vector3f;
|
||||
import com.jme3.renderer.RenderManager;
|
||||
import com.jme3.renderer.ViewPort;
|
||||
import com.jme3.scene.Mesh;
|
||||
import com.jme3.scene.Node;
|
||||
import com.jme3.scene.Spatial;
|
||||
import com.jme3.scene.debug.Arrow;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author normenhansen
|
||||
*/
|
||||
public class BulletDebugAppState extends AbstractAppState {
|
||||
|
||||
protected static final Logger logger = Logger.getLogger(BulletDebugAppState.class.getName());
|
||||
protected final PhysicsSpace space;
|
||||
protected final CollisionShapeBuffer shapeBuffer = new CollisionShapeBuffer();
|
||||
protected final ArrowBuffer arrowBuffer = new ArrowBuffer();
|
||||
protected final Node physicsDebugRootNode = new Node("Physics Debug Root Node");
|
||||
protected ViewPort viewPort;
|
||||
protected RenderManager rm;
|
||||
public Material DEBUG_BLUE;
|
||||
public Material DEBUG_RED;
|
||||
public Material DEBUG_GREEN;
|
||||
public Material DEBUG_YELLOW;
|
||||
public Material DEBUG_MAGENTA;
|
||||
public Material DEBUG_PINK;
|
||||
protected HashMap<PhysicsRigidBody, Spatial> bodies = new HashMap<PhysicsRigidBody, Spatial>();
|
||||
protected HashMap<PhysicsJoint, Spatial> joints = new HashMap<PhysicsJoint, Spatial>();
|
||||
protected HashMap<PhysicsGhostObject, Spatial> ghosts = new HashMap<PhysicsGhostObject, Spatial>();
|
||||
protected HashMap<PhysicsCharacter, Spatial> characters = new HashMap<PhysicsCharacter, Spatial>();
|
||||
protected HashMap<PhysicsVehicle, Spatial> vehicles = new HashMap<PhysicsVehicle, Spatial>();
|
||||
|
||||
public BulletDebugAppState(PhysicsSpace space) {
|
||||
this.space = space;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(AppStateManager stateManager, Application app) {
|
||||
super.initialize(stateManager, app);
|
||||
this.rm = app.getRenderManager();
|
||||
setupMaterials(app);
|
||||
physicsDebugRootNode.setCullHint(Spatial.CullHint.Never);
|
||||
viewPort = rm.createMainView("Physics Debug Overlay", app.getCamera());
|
||||
viewPort.setClearFlags(false, true, false);
|
||||
viewPort.attachScene(physicsDebugRootNode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanup() {
|
||||
rm.removeMainView(viewPort);
|
||||
super.cleanup();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(float tpf) {
|
||||
super.update(tpf);
|
||||
//update all object links
|
||||
updateRigidBodies();
|
||||
updateGhosts();
|
||||
updateCharacters();
|
||||
updateJoints();
|
||||
updateVehicles();
|
||||
//update our debug root node
|
||||
physicsDebugRootNode.updateLogicalState(tpf);
|
||||
physicsDebugRootNode.updateGeometricState();
|
||||
//reset shapes -> this removes all meshes for shapes that were not used this update cycle
|
||||
shapeBuffer.resetShapes();
|
||||
//reset arrows -> this makes arrow meshes available for the next update cycle
|
||||
arrowBuffer.resetArrows();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(RenderManager rm) {
|
||||
super.render(rm);
|
||||
if (viewPort != null) {
|
||||
rm.renderScene(physicsDebugRootNode, viewPort);
|
||||
}
|
||||
}
|
||||
|
||||
private void setupMaterials(Application app) {
|
||||
AssetManager manager = app.getAssetManager();
|
||||
DEBUG_BLUE = new Material(manager, "Common/MatDefs/Misc/Unshaded.j3md");
|
||||
DEBUG_BLUE.getAdditionalRenderState().setWireframe(true);
|
||||
DEBUG_BLUE.setColor("Color", ColorRGBA.Blue);
|
||||
DEBUG_GREEN = new Material(manager, "Common/MatDefs/Misc/Unshaded.j3md");
|
||||
DEBUG_GREEN.getAdditionalRenderState().setWireframe(true);
|
||||
DEBUG_GREEN.setColor("Color", ColorRGBA.Green);
|
||||
DEBUG_RED = new Material(manager, "Common/MatDefs/Misc/Unshaded.j3md");
|
||||
DEBUG_RED.getAdditionalRenderState().setWireframe(true);
|
||||
DEBUG_RED.setColor("Color", ColorRGBA.Red);
|
||||
DEBUG_YELLOW = new Material(manager, "Common/MatDefs/Misc/Unshaded.j3md");
|
||||
DEBUG_YELLOW.getAdditionalRenderState().setWireframe(true);
|
||||
DEBUG_YELLOW.setColor("Color", ColorRGBA.Yellow);
|
||||
DEBUG_MAGENTA = new Material(manager, "Common/MatDefs/Misc/Unshaded.j3md");
|
||||
DEBUG_MAGENTA.getAdditionalRenderState().setWireframe(true);
|
||||
DEBUG_MAGENTA.setColor("Color", ColorRGBA.Magenta);
|
||||
DEBUG_PINK = new Material(manager, "Common/MatDefs/Misc/Unshaded.j3md");
|
||||
DEBUG_PINK.getAdditionalRenderState().setWireframe(true);
|
||||
DEBUG_PINK.setColor("Color", ColorRGBA.Pink);
|
||||
}
|
||||
|
||||
private void updateRigidBodies() {
|
||||
HashMap<PhysicsRigidBody, Spatial> oldObjects = bodies;
|
||||
bodies = new HashMap<PhysicsRigidBody, Spatial>();
|
||||
Collection<PhysicsRigidBody> current = space.getRigidBodyList();
|
||||
//create new map
|
||||
for (Iterator<PhysicsRigidBody> it = current.iterator(); it.hasNext();) {
|
||||
PhysicsRigidBody physicsObject = it.next();
|
||||
//copy existing spatials
|
||||
if (oldObjects.containsKey(physicsObject)) {
|
||||
Spatial spat = oldObjects.get(physicsObject);
|
||||
bodies.put(physicsObject, spat);
|
||||
oldObjects.remove(physicsObject);
|
||||
} else {
|
||||
logger.log(Level.FINE, "Create new debug RigidBody");
|
||||
//create new spatial
|
||||
Node node = new Node(physicsObject.toString());
|
||||
node.addControl(new BulletRigidBodyDebugControl(this, physicsObject));
|
||||
bodies.put(physicsObject, node);
|
||||
physicsDebugRootNode.attachChild(node);
|
||||
}
|
||||
}
|
||||
//remove leftover spatials
|
||||
for (Map.Entry<PhysicsRigidBody, Spatial> entry : oldObjects.entrySet()) {
|
||||
PhysicsRigidBody object = entry.getKey();
|
||||
Spatial spatial = entry.getValue();
|
||||
spatial.removeFromParent();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateJoints() {
|
||||
HashMap<PhysicsJoint, Spatial> oldObjects = joints;
|
||||
joints = new HashMap<PhysicsJoint, Spatial>();
|
||||
Collection<PhysicsJoint> current = space.getJointList();
|
||||
//create new map
|
||||
for (Iterator<PhysicsJoint> it = current.iterator(); it.hasNext();) {
|
||||
PhysicsJoint physicsObject = it.next();
|
||||
//copy existing spatials
|
||||
if (oldObjects.containsKey(physicsObject)) {
|
||||
Spatial spat = oldObjects.get(physicsObject);
|
||||
joints.put(physicsObject, spat);
|
||||
oldObjects.remove(physicsObject);
|
||||
} else {
|
||||
logger.log(Level.FINE, "Create new debug Joint");
|
||||
//create new spatial
|
||||
Node node = new Node(physicsObject.toString());
|
||||
node.addControl(new BulletJointDebugControl(this, physicsObject));
|
||||
joints.put(physicsObject, node);
|
||||
physicsDebugRootNode.attachChild(node);
|
||||
}
|
||||
}
|
||||
//remove leftover spatials
|
||||
for (Map.Entry<PhysicsJoint, Spatial> entry : oldObjects.entrySet()) {
|
||||
PhysicsJoint object = entry.getKey();
|
||||
Spatial spatial = entry.getValue();
|
||||
spatial.removeFromParent();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateGhosts() {
|
||||
HashMap<PhysicsGhostObject, Spatial> oldObjects = ghosts;
|
||||
ghosts = new HashMap<PhysicsGhostObject, Spatial>();
|
||||
Collection<PhysicsGhostObject> current = space.getGhostObjectList();
|
||||
//create new map
|
||||
for (Iterator<PhysicsGhostObject> it = current.iterator(); it.hasNext();) {
|
||||
PhysicsGhostObject physicsObject = it.next();
|
||||
//copy existing spatials
|
||||
if (oldObjects.containsKey(physicsObject)) {
|
||||
Spatial spat = oldObjects.get(physicsObject);
|
||||
ghosts.put(physicsObject, spat);
|
||||
oldObjects.remove(physicsObject);
|
||||
} else {
|
||||
logger.log(Level.FINE, "Create new debug GhostObject");
|
||||
//create new spatial
|
||||
Node node = new Node(physicsObject.toString());
|
||||
node.addControl(new BulletGhostObjectDebugControl(this, physicsObject));
|
||||
ghosts.put(physicsObject, node);
|
||||
physicsDebugRootNode.attachChild(node);
|
||||
}
|
||||
}
|
||||
//remove leftover spatials
|
||||
for (Map.Entry<PhysicsGhostObject, Spatial> entry : oldObjects.entrySet()) {
|
||||
PhysicsGhostObject object = entry.getKey();
|
||||
Spatial spatial = entry.getValue();
|
||||
spatial.removeFromParent();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateCharacters() {
|
||||
HashMap<PhysicsCharacter, Spatial> oldObjects = characters;
|
||||
characters = new HashMap<PhysicsCharacter, Spatial>();
|
||||
Collection<PhysicsCharacter> current = space.getCharacterList();
|
||||
//create new map
|
||||
for (Iterator<PhysicsCharacter> it = current.iterator(); it.hasNext();) {
|
||||
PhysicsCharacter physicsObject = it.next();
|
||||
//copy existing spatials
|
||||
if (oldObjects.containsKey(physicsObject)) {
|
||||
Spatial spat = oldObjects.get(physicsObject);
|
||||
characters.put(physicsObject, spat);
|
||||
oldObjects.remove(physicsObject);
|
||||
} else {
|
||||
logger.log(Level.FINE, "Create new debug Character");
|
||||
//create new spatial
|
||||
Node node = new Node(physicsObject.toString());
|
||||
node.addControl(new BulletCharacterDebugControl(this, physicsObject));
|
||||
characters.put(physicsObject, node);
|
||||
physicsDebugRootNode.attachChild(node);
|
||||
}
|
||||
}
|
||||
//remove leftover spatials
|
||||
for (Map.Entry<PhysicsCharacter, Spatial> entry : oldObjects.entrySet()) {
|
||||
PhysicsCharacter object = entry.getKey();
|
||||
Spatial spatial = entry.getValue();
|
||||
spatial.removeFromParent();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateVehicles() {
|
||||
HashMap<PhysicsVehicle, Spatial> oldObjects = vehicles;
|
||||
vehicles = new HashMap<PhysicsVehicle, Spatial>();
|
||||
Collection<PhysicsVehicle> current = space.getVehicleList();
|
||||
//create new map
|
||||
for (Iterator<PhysicsVehicle> it = current.iterator(); it.hasNext();) {
|
||||
PhysicsVehicle physicsObject = it.next();
|
||||
//copy existing spatials
|
||||
if (oldObjects.containsKey(physicsObject)) {
|
||||
Spatial spat = oldObjects.get(physicsObject);
|
||||
vehicles.put(physicsObject, spat);
|
||||
oldObjects.remove(physicsObject);
|
||||
} else {
|
||||
logger.log(Level.FINE, "Create new debug Vehicle");
|
||||
//create new spatial
|
||||
Node node = new Node(physicsObject.toString());
|
||||
node.addControl(new BulletVehicleDebugControl(this, physicsObject));
|
||||
vehicles.put(physicsObject, node);
|
||||
physicsDebugRootNode.attachChild(node);
|
||||
}
|
||||
}
|
||||
//remove leftover spatials
|
||||
for (Map.Entry<PhysicsVehicle, Spatial> entry : oldObjects.entrySet()) {
|
||||
PhysicsVehicle object = entry.getKey();
|
||||
Spatial spatial = entry.getValue();
|
||||
spatial.removeFromParent();
|
||||
}
|
||||
}
|
||||
|
||||
public ArrowBuffer getArrowBuffer() {
|
||||
return arrowBuffer;
|
||||
}
|
||||
|
||||
public CollisionShapeBuffer getShapeBuffer() {
|
||||
return shapeBuffer;
|
||||
}
|
||||
|
||||
public static class CollisionShapeBuffer {
|
||||
|
||||
public static final Mesh NO_MESH = new Arrow(new Vector3f(0, 0, 0));
|
||||
private HashMap<CollisionShape, Mesh> shapes = new HashMap<CollisionShape, Mesh>();
|
||||
private HashMap<CollisionShape, Mesh> usedShapes = new HashMap<CollisionShape, Mesh>();
|
||||
|
||||
public void resetShapes() {
|
||||
shapes = usedShapes;
|
||||
usedShapes = new HashMap<CollisionShape, Mesh>();
|
||||
}
|
||||
|
||||
public Mesh getShapeMesh(CollisionShape shape) {
|
||||
if (shape == null) {
|
||||
return null;
|
||||
}
|
||||
Mesh mesh = shapes.get(shape);
|
||||
if (mesh == null) {
|
||||
logger.log(Level.FINE, "Create new debug MESH");
|
||||
mesh = DebugShapeFactory.getDebugMesh(shape);
|
||||
shapes.put(shape, mesh);
|
||||
}
|
||||
usedShapes.put(shape, mesh);
|
||||
return mesh;
|
||||
}
|
||||
}
|
||||
|
||||
public static class ArrowBuffer {
|
||||
|
||||
private final Queue<Arrow> arrows = new ConcurrentLinkedQueue<Arrow>();
|
||||
private final Queue<Arrow> usedArrows = new ConcurrentLinkedQueue<Arrow>();
|
||||
|
||||
public void resetArrows() {
|
||||
arrows.addAll(usedArrows);
|
||||
}
|
||||
|
||||
public Arrow getArrow() {
|
||||
return getArrow(Vector3f.UNIT_Y);
|
||||
}
|
||||
|
||||
public Arrow getArrow(Vector3f extent) {
|
||||
Arrow arrow = arrows.poll();
|
||||
if (arrow == null) {
|
||||
arrow = new Arrow(extent);
|
||||
} else {
|
||||
arrow.setArrowExtent(extent);
|
||||
}
|
||||
usedArrows.add(arrow);
|
||||
return arrow;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package com.jme3.bullet.debug;
|
||||
|
||||
import com.jme3.bullet.objects.PhysicsGhostObject;
|
||||
import com.jme3.math.Quaternion;
|
||||
import com.jme3.math.Vector3f;
|
||||
import com.jme3.renderer.RenderManager;
|
||||
import com.jme3.renderer.ViewPort;
|
||||
import com.jme3.scene.Geometry;
|
||||
import com.jme3.scene.Mesh;
|
||||
import com.jme3.scene.Node;
|
||||
import com.jme3.scene.Spatial;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author normenhansen
|
||||
*/
|
||||
public class BulletGhostObjectDebugControl extends AbstractPhysicsDebugControl{
|
||||
protected final PhysicsGhostObject body;
|
||||
protected final Geometry geom;
|
||||
protected final Vector3f location = new Vector3f();
|
||||
protected final Quaternion rotation = new Quaternion();
|
||||
|
||||
public BulletGhostObjectDebugControl(BulletDebugAppState debugAppState, PhysicsGhostObject body) {
|
||||
super(debugAppState);
|
||||
this.body = body;
|
||||
this.geom = new Geometry(body.toString());
|
||||
geom.setMaterial(debugAppState.DEBUG_YELLOW);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSpatial(Spatial spatial) {
|
||||
if (spatial != null && spatial instanceof Node) {
|
||||
Node node = (Node) spatial;
|
||||
node.attachChild(geom);
|
||||
} else if (spatial == null && this.spatial != null) {
|
||||
Node node = (Node) this.spatial;
|
||||
node.detachChild(geom);
|
||||
}
|
||||
super.setSpatial(spatial);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void controlUpdate(float tpf) {
|
||||
Mesh mesh = debugAppState.getShapeBuffer().getShapeMesh(body.getCollisionShape());
|
||||
if (mesh != null) {
|
||||
if (geom.getMesh() != mesh) {
|
||||
geom.setMesh(mesh);
|
||||
}
|
||||
} else {
|
||||
if (geom.getMesh() != BulletDebugAppState.CollisionShapeBuffer.NO_MESH) {
|
||||
geom.setMesh(BulletDebugAppState.CollisionShapeBuffer.NO_MESH);
|
||||
}
|
||||
}
|
||||
applyPhysicsTransform(body.getPhysicsLocation(location), Quaternion.IDENTITY);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void controlRender(RenderManager rm, ViewPort vp) {
|
||||
}
|
||||
}
|
@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package com.jme3.bullet.debug;
|
||||
|
||||
import com.jme3.bullet.joints.PhysicsJoint;
|
||||
import com.jme3.math.Quaternion;
|
||||
import com.jme3.math.Transform;
|
||||
import com.jme3.math.Vector3f;
|
||||
import com.jme3.renderer.RenderManager;
|
||||
import com.jme3.renderer.ViewPort;
|
||||
import com.jme3.scene.Geometry;
|
||||
import com.jme3.scene.Node;
|
||||
import com.jme3.scene.Spatial;
|
||||
import com.jme3.scene.debug.Arrow;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author normenhansen
|
||||
*/
|
||||
public class BulletJointDebugControl extends AbstractPhysicsDebugControl {
|
||||
|
||||
protected final PhysicsJoint body;
|
||||
protected final Geometry geomA;
|
||||
protected final Arrow arrowA;
|
||||
protected final Geometry geomB;
|
||||
protected final Arrow arrowB;
|
||||
protected final Transform a = new Transform(new Vector3f(), new Quaternion());
|
||||
protected final Transform b = new Transform(new Vector3f(), new Quaternion());
|
||||
protected final Vector3f offA = new Vector3f();
|
||||
protected final Vector3f offB = new Vector3f();
|
||||
|
||||
public BulletJointDebugControl(BulletDebugAppState debugAppState, PhysicsJoint body) {
|
||||
super(debugAppState);
|
||||
this.body = body;
|
||||
this.geomA = new Geometry(body.toString());
|
||||
arrowA = new Arrow(Vector3f.ZERO);
|
||||
geomA.setMesh(arrowA);
|
||||
geomA.setMaterial(debugAppState.DEBUG_GREEN);
|
||||
this.geomB = new Geometry(body.toString());
|
||||
arrowB = new Arrow(Vector3f.ZERO);
|
||||
geomB.setMesh(arrowB);
|
||||
geomB.setMaterial(debugAppState.DEBUG_GREEN);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSpatial(Spatial spatial) {
|
||||
if (spatial != null && spatial instanceof Node) {
|
||||
Node node = (Node) spatial;
|
||||
node.attachChild(geomA);
|
||||
node.attachChild(geomB);
|
||||
} else if (spatial == null && this.spatial != null) {
|
||||
Node node = (Node) this.spatial;
|
||||
node.detachChild(geomA);
|
||||
node.detachChild(geomB);
|
||||
}
|
||||
super.setSpatial(spatial);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void controlUpdate(float tpf) {
|
||||
body.getBodyA().getPhysicsLocation(a.getTranslation());
|
||||
body.getBodyA().getPhysicsRotation(a.getRotation());
|
||||
|
||||
body.getBodyB().getPhysicsLocation(b.getTranslation());
|
||||
body.getBodyB().getPhysicsRotation(b.getRotation());
|
||||
|
||||
geomA.setLocalTransform(a);
|
||||
geomB.setLocalTransform(b);
|
||||
|
||||
arrowA.setArrowExtent(body.getPivotA());
|
||||
arrowB.setArrowExtent(body.getPivotB());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void controlRender(RenderManager rm, ViewPort vp) {
|
||||
}
|
||||
}
|
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package com.jme3.bullet.debug;
|
||||
|
||||
import com.jme3.bullet.debug.BulletDebugAppState.CollisionShapeBuffer;
|
||||
import com.jme3.bullet.objects.PhysicsRigidBody;
|
||||
import com.jme3.math.Quaternion;
|
||||
import com.jme3.math.Vector3f;
|
||||
import com.jme3.renderer.RenderManager;
|
||||
import com.jme3.renderer.ViewPort;
|
||||
import com.jme3.scene.Geometry;
|
||||
import com.jme3.scene.Mesh;
|
||||
import com.jme3.scene.Node;
|
||||
import com.jme3.scene.Spatial;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author normenhansen
|
||||
*/
|
||||
public class BulletRigidBodyDebugControl extends AbstractPhysicsDebugControl {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(BulletRigidBodyDebugControl.class.getName());
|
||||
protected final PhysicsRigidBody body;
|
||||
protected final Geometry geom;
|
||||
protected final Vector3f location = new Vector3f();
|
||||
protected final Quaternion rotation = new Quaternion();
|
||||
|
||||
public BulletRigidBodyDebugControl(BulletDebugAppState debugAppState, PhysicsRigidBody body) {
|
||||
super(debugAppState);
|
||||
this.body = body;
|
||||
this.geom = new Geometry(body.toString());
|
||||
geom.setMaterial(debugAppState.DEBUG_BLUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSpatial(Spatial spatial) {
|
||||
if (spatial != null && spatial instanceof Node) {
|
||||
Node node = (Node) spatial;
|
||||
node.attachChild(geom);
|
||||
} else if (spatial == null && this.spatial != null) {
|
||||
Node node = (Node) this.spatial;
|
||||
node.detachChild(geom);
|
||||
}
|
||||
super.setSpatial(spatial);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void controlUpdate(float tpf) {
|
||||
Mesh mesh = debugAppState.getShapeBuffer().getShapeMesh(body.getCollisionShape());
|
||||
if (mesh != null) {
|
||||
if (geom.getMesh() != mesh) {
|
||||
geom.setMesh(mesh);
|
||||
}
|
||||
} else {
|
||||
if (geom.getMesh() != CollisionShapeBuffer.NO_MESH) {
|
||||
geom.setMesh(CollisionShapeBuffer.NO_MESH);
|
||||
}
|
||||
}
|
||||
applyPhysicsTransform(body.getPhysicsLocation(location), body.getPhysicsRotation(rotation));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void controlRender(RenderManager rm, ViewPort vp) {
|
||||
}
|
||||
}
|
@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package com.jme3.bullet.debug;
|
||||
|
||||
import com.jme3.bullet.objects.PhysicsVehicle;
|
||||
import com.jme3.bullet.objects.VehicleWheel;
|
||||
import com.jme3.math.Quaternion;
|
||||
import com.jme3.math.Vector3f;
|
||||
import com.jme3.renderer.RenderManager;
|
||||
import com.jme3.renderer.ViewPort;
|
||||
import com.jme3.scene.Geometry;
|
||||
import com.jme3.scene.Node;
|
||||
import com.jme3.scene.Spatial;
|
||||
import com.jme3.scene.debug.Arrow;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author normenhansen
|
||||
*/
|
||||
public class BulletVehicleDebugControl extends AbstractPhysicsDebugControl {
|
||||
|
||||
protected final PhysicsVehicle body;
|
||||
protected final Node suspensionNode;
|
||||
protected final Vector3f location = new Vector3f();
|
||||
protected final Quaternion rotation = new Quaternion();
|
||||
|
||||
public BulletVehicleDebugControl(BulletDebugAppState debugAppState, PhysicsVehicle body) {
|
||||
super(debugAppState);
|
||||
this.body = body;
|
||||
suspensionNode = new Node("Suspension");
|
||||
createVehicle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSpatial(Spatial spatial) {
|
||||
if (spatial != null && spatial instanceof Node) {
|
||||
Node node = (Node) spatial;
|
||||
node.attachChild(suspensionNode);
|
||||
} else if (spatial == null && this.spatial != null) {
|
||||
Node node = (Node) this.spatial;
|
||||
node.detachChild(suspensionNode);
|
||||
}
|
||||
super.setSpatial(spatial);
|
||||
}
|
||||
|
||||
private void createVehicle() {
|
||||
suspensionNode.detachAllChildren();
|
||||
for (int i = 0; i < body.getNumWheels(); i++) {
|
||||
VehicleWheel physicsVehicleWheel = body.getWheel(i);
|
||||
Vector3f location = physicsVehicleWheel.getLocation().clone();
|
||||
Vector3f direction = physicsVehicleWheel.getDirection().clone();
|
||||
Vector3f axle = physicsVehicleWheel.getAxle().clone();
|
||||
float restLength = physicsVehicleWheel.getRestLength();
|
||||
float radius = physicsVehicleWheel.getRadius();
|
||||
|
||||
Arrow locArrow = new Arrow(location);
|
||||
Arrow axleArrow = new Arrow(axle.normalizeLocal().multLocal(0.3f));
|
||||
Arrow wheelArrow = new Arrow(direction.normalizeLocal().multLocal(radius));
|
||||
Arrow dirArrow = new Arrow(direction.normalizeLocal().multLocal(restLength));
|
||||
Geometry locGeom = new Geometry("WheelLocationDebugShape" + i, locArrow);
|
||||
Geometry dirGeom = new Geometry("WheelDirectionDebugShape" + i, dirArrow);
|
||||
Geometry axleGeom = new Geometry("WheelAxleDebugShape" + i, axleArrow);
|
||||
Geometry wheelGeom = new Geometry("WheelRadiusDebugShape" + i, wheelArrow);
|
||||
dirGeom.setLocalTranslation(location);
|
||||
axleGeom.setLocalTranslation(location.add(direction));
|
||||
wheelGeom.setLocalTranslation(location.add(direction));
|
||||
locGeom.setMaterial(debugAppState.DEBUG_GREEN);
|
||||
dirGeom.setMaterial(debugAppState.DEBUG_GREEN);
|
||||
axleGeom.setMaterial(debugAppState.DEBUG_GREEN);
|
||||
wheelGeom.setMaterial(debugAppState.DEBUG_GREEN);
|
||||
suspensionNode.attachChild(locGeom);
|
||||
suspensionNode.attachChild(dirGeom);
|
||||
suspensionNode.attachChild(axleGeom);
|
||||
suspensionNode.attachChild(wheelGeom);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void controlUpdate(float tpf) {
|
||||
for (int i = 0; i < body.getNumWheels(); i++) {
|
||||
VehicleWheel physicsVehicleWheel = body.getWheel(i);
|
||||
Vector3f location = physicsVehicleWheel.getLocation().clone();
|
||||
Vector3f direction = physicsVehicleWheel.getDirection().clone();
|
||||
Vector3f axle = physicsVehicleWheel.getAxle().clone();
|
||||
float restLength = physicsVehicleWheel.getRestLength();
|
||||
float radius = physicsVehicleWheel.getRadius();
|
||||
|
||||
Geometry locGeom = (Geometry) suspensionNode.getChild("WheelLocationDebugShape" + i);
|
||||
Geometry dirGeom = (Geometry) suspensionNode.getChild("WheelDirectionDebugShape" + i);
|
||||
Geometry axleGeom = (Geometry) suspensionNode.getChild("WheelAxleDebugShape" + i);
|
||||
Geometry wheelGeom = (Geometry) suspensionNode.getChild("WheelRadiusDebugShape" + i);
|
||||
|
||||
Arrow locArrow = (Arrow) locGeom.getMesh();
|
||||
locArrow.setArrowExtent(location);
|
||||
Arrow axleArrow = (Arrow) axleGeom.getMesh();
|
||||
axleArrow.setArrowExtent(axle.normalizeLocal().multLocal(0.3f));
|
||||
Arrow wheelArrow = (Arrow) wheelGeom.getMesh();
|
||||
wheelArrow.setArrowExtent(direction.normalizeLocal().multLocal(radius));
|
||||
Arrow dirArrow = (Arrow) dirGeom.getMesh();
|
||||
dirArrow.setArrowExtent(direction.normalizeLocal().multLocal(restLength));
|
||||
|
||||
dirGeom.setLocalTranslation(location);
|
||||
axleGeom.setLocalTranslation(location.addLocal(direction));
|
||||
wheelGeom.setLocalTranslation(location);
|
||||
i++;
|
||||
}
|
||||
applyPhysicsTransform(body.getPhysicsLocation(location), body.getPhysicsRotation(rotation));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void controlRender(RenderManager rm, ViewPort vp) {
|
||||
}
|
||||
}
|
@ -920,7 +920,7 @@ public class PhysicsSpace {
|
||||
/**
|
||||
* Enable debug display for physics
|
||||
* @param manager AssetManager to use to create debug materials
|
||||
* @Deprecated in favor of BulletDebugAppState, use BulletAppState.enableDebug() to add automatically
|
||||
* @Deprecated in favor of BulletDebugAppState, use BulletAppState.setDebugEnabled(boolean) to add automatically
|
||||
*/
|
||||
@Deprecated
|
||||
public void enableDebug(AssetManager manager) {
|
||||
|
@ -859,7 +859,7 @@ public class PhysicsSpace {
|
||||
/**
|
||||
* Enable debug display for physics
|
||||
* @param manager AssetManager to use to create debug materials
|
||||
* @Deprecated in favor of BulletDebugAppState, use BulletAppState.enableDebug() to add automatically
|
||||
* @Deprecated in favor of BulletDebugAppState, use BulletAppState.setDebugEnabled(boolean) to add automatically
|
||||
*/
|
||||
@Deprecated
|
||||
public void enableDebug(AssetManager manager) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user