- 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-0572b91ccdca3.0
parent
2d5800d667
commit
8992563b86
@ -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) { |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue