| /* |
| * To change this template, choose Tools | Templates |
| * and open the template in the editor. |
| */ |
| package com.jme3.bullet.control; |
| |
| import com.jme3.bullet.PhysicsSpace; |
| import com.jme3.bullet.collision.shapes.BoxCollisionShape; |
| import com.jme3.bullet.collision.shapes.CollisionShape; |
| import com.jme3.bullet.collision.shapes.SphereCollisionShape; |
| import com.jme3.bullet.objects.PhysicsRigidBody; |
| import com.jme3.bullet.util.CollisionShapeFactory; |
| import com.jme3.export.InputCapsule; |
| import com.jme3.export.JmeExporter; |
| import com.jme3.export.JmeImporter; |
| import com.jme3.export.OutputCapsule; |
| 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.Spatial; |
| import com.jme3.scene.control.Control; |
| import com.jme3.scene.shape.Box; |
| import com.jme3.scene.shape.Sphere; |
| import java.io.IOException; |
| |
| /** |
| * |
| * @author normenhansen |
| */ |
| public class RigidBodyControl extends PhysicsRigidBody implements PhysicsControl { |
| |
| protected Spatial spatial; |
| protected boolean enabled = true; |
| protected boolean added = false; |
| protected PhysicsSpace space = null; |
| protected boolean kinematicSpatial = true; |
| |
| public RigidBodyControl() { |
| } |
| |
| /** |
| * When using this constructor, the CollisionShape for the RigidBody is generated |
| * automatically when the Control is added to a Spatial. |
| * @param mass When not 0, a HullCollisionShape is generated, otherwise a MeshCollisionShape is used. For geometries with box or sphere meshes the proper box or sphere collision shape is used. |
| */ |
| public RigidBodyControl(float mass) { |
| this.mass = mass; |
| } |
| |
| /** |
| * Creates a new PhysicsNode with the supplied collision shape and mass 1 |
| * @param shape |
| */ |
| public RigidBodyControl(CollisionShape shape) { |
| super(shape); |
| } |
| |
| public RigidBodyControl(CollisionShape shape, float mass) { |
| super(shape, mass); |
| } |
| |
| public Control cloneForSpatial(Spatial spatial) { |
| RigidBodyControl control = new RigidBodyControl(collisionShape, mass); |
| control.setAngularFactor(getAngularFactor()); |
| control.setAngularSleepingThreshold(getAngularSleepingThreshold()); |
| control.setCcdMotionThreshold(getCcdMotionThreshold()); |
| control.setCcdSweptSphereRadius(getCcdSweptSphereRadius()); |
| control.setCollideWithGroups(getCollideWithGroups()); |
| control.setCollisionGroup(getCollisionGroup()); |
| control.setDamping(getLinearDamping(), getAngularDamping()); |
| control.setFriction(getFriction()); |
| control.setGravity(getGravity()); |
| control.setKinematic(isKinematic()); |
| control.setKinematicSpatial(isKinematicSpatial()); |
| control.setLinearSleepingThreshold(getLinearSleepingThreshold()); |
| control.setPhysicsLocation(getPhysicsLocation(null)); |
| control.setPhysicsRotation(getPhysicsRotationMatrix(null)); |
| control.setRestitution(getRestitution()); |
| |
| if (mass > 0) { |
| control.setAngularVelocity(getAngularVelocity()); |
| control.setLinearVelocity(getLinearVelocity()); |
| } |
| control.setApplyPhysicsLocal(isApplyPhysicsLocal()); |
| |
| control.setSpatial(spatial); |
| return control; |
| } |
| |
| public void setSpatial(Spatial spatial) { |
| if (getUserObject() == null || getUserObject() == this.spatial) { |
| setUserObject(spatial); |
| } |
| this.spatial = spatial; |
| if (spatial == null) { |
| if (getUserObject() == spatial) { |
| setUserObject(null); |
| } |
| spatial = null; |
| collisionShape = null; |
| return; |
| } |
| if (collisionShape == null) { |
| createCollisionShape(); |
| rebuildRigidBody(); |
| } |
| setPhysicsLocation(getSpatialTranslation()); |
| setPhysicsRotation(getSpatialRotation()); |
| } |
| |
| protected void createCollisionShape() { |
| if (spatial == null) { |
| return; |
| } |
| if (spatial instanceof Geometry) { |
| Geometry geom = (Geometry) spatial; |
| Mesh mesh = geom.getMesh(); |
| if (mesh instanceof Sphere) { |
| collisionShape = new SphereCollisionShape(((Sphere) mesh).getRadius()); |
| return; |
| } else if (mesh instanceof Box) { |
| collisionShape = new BoxCollisionShape(new Vector3f(((Box) mesh).getXExtent(), ((Box) mesh).getYExtent(), ((Box) mesh).getZExtent())); |
| return; |
| } |
| } |
| if (mass > 0) { |
| collisionShape = CollisionShapeFactory.createDynamicMeshShape(spatial); |
| } else { |
| collisionShape = CollisionShapeFactory.createMeshShape(spatial); |
| } |
| } |
| |
| public void setEnabled(boolean enabled) { |
| this.enabled = enabled; |
| if (space != null) { |
| if (enabled && !added) { |
| if (spatial != null) { |
| setPhysicsLocation(getSpatialTranslation()); |
| setPhysicsRotation(getSpatialRotation()); |
| } |
| space.addCollisionObject(this); |
| added = true; |
| } else if (!enabled && added) { |
| space.removeCollisionObject(this); |
| added = false; |
| } |
| } |
| } |
| |
| public boolean isEnabled() { |
| return enabled; |
| } |
| |
| /** |
| * Checks if this control is in kinematic spatial mode. |
| * @return true if the spatial location is applied to this kinematic rigidbody |
| */ |
| public boolean isKinematicSpatial() { |
| return kinematicSpatial; |
| } |
| |
| /** |
| * Sets this control to kinematic spatial mode so that the spatials transform will |
| * be applied to the rigidbody in kinematic mode, defaults to true. |
| * @param kinematicSpatial |
| */ |
| public void setKinematicSpatial(boolean kinematicSpatial) { |
| this.kinematicSpatial = kinematicSpatial; |
| } |
| |
| public boolean isApplyPhysicsLocal() { |
| return motionState.isApplyPhysicsLocal(); |
| } |
| |
| /** |
| * When set to true, the physics coordinates will be applied to the local |
| * translation of the Spatial instead of the world traslation. |
| * @param applyPhysicsLocal |
| */ |
| public void setApplyPhysicsLocal(boolean applyPhysicsLocal) { |
| motionState.setApplyPhysicsLocal(applyPhysicsLocal); |
| } |
| |
| private Vector3f getSpatialTranslation(){ |
| if(motionState.isApplyPhysicsLocal()){ |
| return spatial.getLocalTranslation(); |
| } |
| return spatial.getWorldTranslation(); |
| } |
| |
| private Quaternion getSpatialRotation(){ |
| if(motionState.isApplyPhysicsLocal()){ |
| return spatial.getLocalRotation(); |
| } |
| return spatial.getWorldRotation(); |
| } |
| |
| public void update(float tpf) { |
| if (enabled && spatial != null) { |
| if (isKinematic() && kinematicSpatial) { |
| super.setPhysicsLocation(getSpatialTranslation()); |
| super.setPhysicsRotation(getSpatialRotation()); |
| } else { |
| getMotionState().applyTransform(spatial); |
| } |
| } |
| } |
| |
| public void render(RenderManager rm, ViewPort vp) { |
| if (enabled && space != null && space.getDebugManager() != null) { |
| if (debugShape == null) { |
| attachDebugShape(space.getDebugManager()); |
| } |
| //TODO: using spatial traslation/rotation.. |
| debugShape.setLocalTranslation(spatial.getWorldTranslation()); |
| debugShape.setLocalRotation(spatial.getWorldRotation()); |
| debugShape.updateLogicalState(0); |
| debugShape.updateGeometricState(); |
| rm.renderScene(debugShape, vp); |
| } |
| } |
| |
| public void setPhysicsSpace(PhysicsSpace space) { |
| if (space == null) { |
| if (this.space != null) { |
| this.space.removeCollisionObject(this); |
| added = false; |
| } |
| } else { |
| if(this.space==space) return; |
| space.addCollisionObject(this); |
| added = true; |
| } |
| this.space = space; |
| } |
| |
| public PhysicsSpace getPhysicsSpace() { |
| return space; |
| } |
| |
| @Override |
| public void write(JmeExporter ex) throws IOException { |
| super.write(ex); |
| OutputCapsule oc = ex.getCapsule(this); |
| oc.write(enabled, "enabled", true); |
| oc.write(motionState.isApplyPhysicsLocal(), "applyLocalPhysics", false); |
| oc.write(kinematicSpatial, "kinematicSpatial", true); |
| oc.write(spatial, "spatial", null); |
| } |
| |
| @Override |
| public void read(JmeImporter im) throws IOException { |
| super.read(im); |
| InputCapsule ic = im.getCapsule(this); |
| enabled = ic.readBoolean("enabled", true); |
| kinematicSpatial = ic.readBoolean("kinematicSpatial", true); |
| spatial = (Spatial) ic.readSavable("spatial", null); |
| motionState.setApplyPhysicsLocal(ic.readBoolean("applyLocalPhysics", false)); |
| setUserObject(spatial); |
| } |
| } |