- 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.AppState;
|
||||||
import com.jme3.app.state.AppStateManager;
|
import com.jme3.app.state.AppStateManager;
|
||||||
import com.jme3.bullet.PhysicsSpace.BroadphaseType;
|
import com.jme3.bullet.PhysicsSpace.BroadphaseType;
|
||||||
|
import com.jme3.bullet.debug.BulletDebugAppState;
|
||||||
import com.jme3.math.Vector3f;
|
import com.jme3.math.Vector3f;
|
||||||
import com.jme3.renderer.RenderManager;
|
import com.jme3.renderer.RenderManager;
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
@ -43,6 +44,7 @@ import java.util.logging.Logger;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* <code>BulletAppState</code> allows using bullet physics in an Application.
|
* <code>BulletAppState</code> allows using bullet physics in an Application.
|
||||||
|
*
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
public class BulletAppState implements AppState, PhysicsTickListener {
|
public class BulletAppState implements AppState, PhysicsTickListener {
|
||||||
@ -56,31 +58,38 @@ public class BulletAppState implements AppState, PhysicsTickListener {
|
|||||||
protected BroadphaseType broadphaseType = BroadphaseType.DBVT;
|
protected BroadphaseType broadphaseType = BroadphaseType.DBVT;
|
||||||
protected Vector3f worldMin = new Vector3f(-10000f, -10000f, -10000f);
|
protected Vector3f worldMin = new Vector3f(-10000f, -10000f, -10000f);
|
||||||
protected Vector3f worldMax = 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 active = true;
|
||||||
|
protected boolean debugEnabled = false;
|
||||||
|
protected BulletDebugAppState debugAppState;
|
||||||
protected float tpf;
|
protected float tpf;
|
||||||
protected Future physicsFuture;
|
protected Future physicsFuture;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new BulletAppState running a PhysicsSpace for physics simulation,
|
* Creates a new BulletAppState running a PhysicsSpace for physics
|
||||||
* use getStateManager().addState(bulletAppState) to enable physics for an Application.
|
* simulation, use getStateManager().addState(bulletAppState) to enable
|
||||||
|
* physics for an Application.
|
||||||
*/
|
*/
|
||||||
public BulletAppState() {
|
public BulletAppState() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new BulletAppState running a PhysicsSpace for physics simulation,
|
* Creates a new BulletAppState running a PhysicsSpace for physics
|
||||||
* use getStateManager().addState(bulletAppState) to enable physics for an Application.
|
* simulation, use getStateManager().addState(bulletAppState) to enable
|
||||||
* @param broadphaseType The type of broadphase collision detection, BroadphaseType.DVBT is the default
|
* physics for an Application.
|
||||||
|
*
|
||||||
|
* @param broadphaseType The type of broadphase collision detection,
|
||||||
|
* BroadphaseType.DVBT is the default
|
||||||
*/
|
*/
|
||||||
public BulletAppState(BroadphaseType broadphaseType) {
|
public BulletAppState(BroadphaseType broadphaseType) {
|
||||||
this(new Vector3f(-10000f, -10000f, -10000f), new Vector3f(10000f, 10000f, 10000f), broadphaseType);
|
this(new Vector3f(-10000f, -10000f, -10000f), new Vector3f(10000f, 10000f, 10000f), broadphaseType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new BulletAppState running a PhysicsSpace for physics simulation,
|
* Creates a new BulletAppState running a PhysicsSpace for physics
|
||||||
* use getStateManager().addState(bulletAppState) to enable physics for an Application.
|
* simulation, use getStateManager().addState(bulletAppState) to enable
|
||||||
* An AxisSweep broadphase is used.
|
* physics for an Application. An AxisSweep broadphase is used.
|
||||||
|
*
|
||||||
* @param worldMin The minimum world extent
|
* @param worldMin The minimum world extent
|
||||||
* @param worldMax The maximum world extent
|
* @param worldMax The maximum world extent
|
||||||
*/
|
*/
|
||||||
@ -101,7 +110,6 @@ public class BulletAppState implements AppState, PhysicsTickListener {
|
|||||||
executor = new ScheduledThreadPoolExecutor(1);
|
executor = new ScheduledThreadPoolExecutor(1);
|
||||||
final BulletAppState app = this;
|
final BulletAppState app = this;
|
||||||
Callable<Boolean> call = new Callable<Boolean>() {
|
Callable<Boolean> call = new Callable<Boolean>() {
|
||||||
|
|
||||||
public Boolean call() throws Exception {
|
public Boolean call() throws Exception {
|
||||||
detachedPhysicsLastUpdate = System.currentTimeMillis();
|
detachedPhysicsLastUpdate = System.currentTimeMillis();
|
||||||
pSpace = new PhysicsSpace(worldMin, worldMax, broadphaseType);
|
pSpace = new PhysicsSpace(worldMin, worldMax, broadphaseType);
|
||||||
@ -120,7 +128,6 @@ public class BulletAppState implements AppState, PhysicsTickListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
private Callable<Boolean> parallelPhysicsUpdate = new Callable<Boolean>() {
|
private Callable<Boolean> parallelPhysicsUpdate = new Callable<Boolean>() {
|
||||||
|
|
||||||
public Boolean call() throws Exception {
|
public Boolean call() throws Exception {
|
||||||
pSpace.update(tpf * getSpeed());
|
pSpace.update(tpf * getSpeed());
|
||||||
return true;
|
return true;
|
||||||
@ -128,7 +135,6 @@ public class BulletAppState implements AppState, PhysicsTickListener {
|
|||||||
};
|
};
|
||||||
long detachedPhysicsLastUpdate = 0;
|
long detachedPhysicsLastUpdate = 0;
|
||||||
private Callable<Boolean> detachedPhysicsUpdate = new Callable<Boolean>() {
|
private Callable<Boolean> detachedPhysicsUpdate = new Callable<Boolean>() {
|
||||||
|
|
||||||
public Boolean call() throws Exception {
|
public Boolean call() throws Exception {
|
||||||
pSpace.update(getPhysicsSpace().getAccuracy() * getSpeed());
|
pSpace.update(getPhysicsSpace().getAccuracy() * getSpeed());
|
||||||
pSpace.distributeEvents();
|
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
|
* The physics system is started automatically on attaching, if you want to
|
||||||
* before for some reason, you can use this method.
|
* start it before for some reason, you can use this method.
|
||||||
*/
|
*/
|
||||||
public void startPhysics() {
|
public void startPhysics() {
|
||||||
//start physics thread(pool)
|
//start physics thread(pool)
|
||||||
@ -165,6 +171,7 @@ public class BulletAppState implements AppState, PhysicsTickListener {
|
|||||||
if (!initialized) {
|
if (!initialized) {
|
||||||
startPhysics();
|
startPhysics();
|
||||||
}
|
}
|
||||||
|
this.stateManager = stateManager;
|
||||||
initialized = true;
|
initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,6 +187,14 @@ public class BulletAppState implements AppState, PhysicsTickListener {
|
|||||||
return active;
|
return active;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setDebugEnabled(boolean debugEnabled) {
|
||||||
|
this.debugEnabled = debugEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isDebugEnabled() {
|
||||||
|
return debugEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
public void stateAttached(AppStateManager stateManager) {
|
public void stateAttached(AppStateManager stateManager) {
|
||||||
if (!initialized) {
|
if (!initialized) {
|
||||||
startPhysics();
|
startPhysics();
|
||||||
@ -187,17 +202,36 @@ public class BulletAppState implements AppState, PhysicsTickListener {
|
|||||||
if (threadingType == ThreadingType.PARALLEL) {
|
if (threadingType == ThreadingType.PARALLEL) {
|
||||||
PhysicsSpace.setLocalThreadPhysicsSpace(pSpace);
|
PhysicsSpace.setLocalThreadPhysicsSpace(pSpace);
|
||||||
}
|
}
|
||||||
|
if (debugEnabled) {
|
||||||
|
debugAppState = new BulletDebugAppState(pSpace);
|
||||||
|
stateManager.attach(debugAppState);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void stateDetached(AppStateManager stateManager) {
|
public void stateDetached(AppStateManager stateManager) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update(float tpf) {
|
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) {
|
if (!active) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// if (threadingType != ThreadingType.DETACHED) {
|
// if (threadingType != ThreadingType.DETACHED) {
|
||||||
pSpace.distributeEvents();
|
pSpace.distributeEvents();
|
||||||
// }
|
// }
|
||||||
this.tpf = tpf;
|
this.tpf = tpf;
|
||||||
}
|
}
|
||||||
@ -228,6 +262,10 @@ public class BulletAppState implements AppState, PhysicsTickListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void cleanup() {
|
public void cleanup() {
|
||||||
|
if (debugAppState != null) {
|
||||||
|
stateManager.detach(debugAppState);
|
||||||
|
debugAppState = null;
|
||||||
|
}
|
||||||
if (executor != null) {
|
if (executor != null) {
|
||||||
executor.shutdown();
|
executor.shutdown();
|
||||||
executor = null;
|
executor = null;
|
||||||
@ -245,6 +283,7 @@ public class BulletAppState implements AppState, PhysicsTickListener {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Use before attaching state
|
* Use before attaching state
|
||||||
|
*
|
||||||
* @param threadingType the threadingType to set
|
* @param threadingType the threadingType to set
|
||||||
*/
|
*/
|
||||||
public void setThreadingType(ThreadingType threadingType) {
|
public void setThreadingType(ThreadingType threadingType) {
|
||||||
@ -289,13 +328,14 @@ public class BulletAppState implements AppState, PhysicsTickListener {
|
|||||||
public enum ThreadingType {
|
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,
|
SEQUENTIAL,
|
||||||
/**
|
/**
|
||||||
* Parallel threaded mode; physics update and rendering are executed in parallel, update order is kept.<br/>
|
* Parallel threaded mode; physics update and rendering are executed in
|
||||||
* Multiple BulletAppStates will execute in parallel in this mode.
|
* 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
|
* Enable debug display for physics
|
||||||
* @param manager AssetManager to use to create debug materials
|
* @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
|
@Deprecated
|
||||||
public void enableDebug(AssetManager manager) {
|
public void enableDebug(AssetManager manager) {
|
||||||
|
@ -859,7 +859,7 @@ public class PhysicsSpace {
|
|||||||
/**
|
/**
|
||||||
* Enable debug display for physics
|
* Enable debug display for physics
|
||||||
* @param manager AssetManager to use to create debug materials
|
* @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
|
@Deprecated
|
||||||
public void enableDebug(AssetManager manager) {
|
public void enableDebug(AssetManager manager) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user