159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/* 259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * To change this template, choose Tools | Templates 359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * and open the template in the editor. 459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapackage com.jme3.bullet.control; 659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.bullet.PhysicsSpace; 859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.bullet.collision.shapes.CollisionShape; 959b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.bullet.objects.PhysicsGhostObject; 1059b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.export.InputCapsule; 1159b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.export.JmeExporter; 1259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.export.JmeImporter; 1359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.export.OutputCapsule; 1459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.math.Quaternion; 1559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.math.Vector3f; 1659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.renderer.RenderManager; 1759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.renderer.ViewPort; 1859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.Spatial; 1959b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.control.Control; 2059b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.io.IOException; 2159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 2259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/** 2359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * A GhostControl moves with the spatial it is attached to and can be used to check 2459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * overlaps with other physics objects (e.g. aggro radius). 2559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @author normenhansen 2659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 2759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapublic class GhostControl extends PhysicsGhostObject implements PhysicsControl { 2859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 2959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected Spatial spatial; 3059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected boolean enabled = true; 3159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected boolean added = false; 3259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected PhysicsSpace space = null; 3359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected boolean applyLocal = false; 3459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 3559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public GhostControl() { 3659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 3759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 3859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public GhostControl(CollisionShape shape) { 3959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta super(shape); 4059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 4159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 4259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public boolean isApplyPhysicsLocal() { 4359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return applyLocal; 4459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 4559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 4659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 4759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * When set to true, the physics coordinates will be applied to the local 4859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * translation of the Spatial 4959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param applyPhysicsLocal 5059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 5159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void setApplyPhysicsLocal(boolean applyPhysicsLocal) { 5259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta applyLocal = applyPhysicsLocal; 5359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 5459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 5559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private Vector3f getSpatialTranslation() { 5659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (applyLocal) { 5759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return spatial.getLocalTranslation(); 5859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 5959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return spatial.getWorldTranslation(); 6059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 6159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 6259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private Quaternion getSpatialRotation() { 6359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (applyLocal) { 6459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return spatial.getLocalRotation(); 6559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 6659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return spatial.getWorldRotation(); 6759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 6859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 6959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public Control cloneForSpatial(Spatial spatial) { 7059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta GhostControl control = new GhostControl(collisionShape); 7159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta control.setCcdMotionThreshold(getCcdMotionThreshold()); 7259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta control.setCcdSweptSphereRadius(getCcdSweptSphereRadius()); 7359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta control.setCollideWithGroups(getCollideWithGroups()); 7459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta control.setCollisionGroup(getCollisionGroup()); 7559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta control.setPhysicsLocation(getPhysicsLocation()); 7659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta control.setPhysicsRotation(getPhysicsRotationMatrix()); 7759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta control.setApplyPhysicsLocal(isApplyPhysicsLocal()); 7859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 7959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta control.setSpatial(spatial); 8059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return control; 8159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 8259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 8359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void setSpatial(Spatial spatial) { 8459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (getUserObject() == null || getUserObject() == this.spatial) { 8559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta setUserObject(spatial); 8659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 8759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.spatial = spatial; 8859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (spatial == null) { 8959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (getUserObject() == spatial) { 9059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta setUserObject(null); 9159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 9259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return; 9359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 9459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta setPhysicsLocation(getSpatialTranslation()); 9559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta setPhysicsRotation(getSpatialRotation()); 9659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 9759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 9859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void setEnabled(boolean enabled) { 9959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.enabled = enabled; 10059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (space != null) { 10159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (enabled && !added) { 10259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (spatial != null) { 10359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta setPhysicsLocation(getSpatialTranslation()); 10459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta setPhysicsRotation(getSpatialRotation()); 10559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 10659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta space.addCollisionObject(this); 10759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta added = true; 10859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else if (!enabled && added) { 10959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta space.removeCollisionObject(this); 11059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta added = false; 11159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 11259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 11359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 11459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 11559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public boolean isEnabled() { 11659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return enabled; 11759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 11859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 11959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void update(float tpf) { 12059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!enabled) { 12159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return; 12259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 12359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta setPhysicsLocation(getSpatialTranslation()); 12459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta setPhysicsRotation(getSpatialRotation()); 12559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 12659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 12759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void render(RenderManager rm, ViewPort vp) { 12859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (enabled && space != null && space.getDebugManager() != null) { 12959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (debugShape == null) { 13059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta attachDebugShape(space.getDebugManager()); 13159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 13259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta debugShape.setLocalTranslation(spatial.getWorldTranslation()); 13359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta debugShape.setLocalRotation(spatial.getWorldRotation()); 13459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta debugShape.updateLogicalState(0); 13559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta debugShape.updateGeometricState(); 13659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rm.renderScene(debugShape, vp); 13759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 13859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 13959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 14059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void setPhysicsSpace(PhysicsSpace space) { 14159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (space == null) { 14259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (this.space != null) { 14359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.space.removeCollisionObject(this); 14459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta added = false; 14559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 14659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 14759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (this.space == space) { 14859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return; 14959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 15059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta space.addCollisionObject(this); 15159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta added = true; 15259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 15359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.space = space; 15459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 15559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 15659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public PhysicsSpace getPhysicsSpace() { 15759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return space; 15859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 15959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 16059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta @Override 16159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void write(JmeExporter ex) throws IOException { 16259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta super.write(ex); 16359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta OutputCapsule oc = ex.getCapsule(this); 16459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta oc.write(enabled, "enabled", true); 16559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta oc.write(applyLocal, "applyLocalPhysics", false); 16659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta oc.write(spatial, "spatial", null); 16759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 16859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 16959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta @Override 17059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void read(JmeImporter im) throws IOException { 17159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta super.read(im); 17259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta InputCapsule ic = im.getCapsule(this); 17359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta enabled = ic.readBoolean("enabled", true); 17459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta spatial = (Spatial) ic.readSavable("spatial", null); 17559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta applyLocal = ic.readBoolean("applyLocalPhysics", false); 17659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta setUserObject(spatial); 17759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 17859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta} 179