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.PhysicsCharacter; 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 * 2459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @author normenhansen 2559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 2659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapublic class CharacterControl extends PhysicsCharacter implements PhysicsControl { 2759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 2859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected Spatial spatial; 2959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected boolean enabled = true; 3059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected boolean added = false; 3159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected PhysicsSpace space = null; 3259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected Vector3f viewDirection = new Vector3f(Vector3f.UNIT_Z); 3359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected boolean useViewDirection = true; 3459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected boolean applyLocal = false; 3559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 3659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public CharacterControl() { 3759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 3859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 3959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public CharacterControl(CollisionShape shape, float stepHeight) { 4059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta super(shape, stepHeight); 4159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 4259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 4359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public boolean isApplyPhysicsLocal() { 4459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return applyLocal; 4559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 4659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 4759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 4859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * When set to true, the physics coordinates will be applied to the local 4959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * translation of the Spatial 5059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param applyPhysicsLocal 5159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 5259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void setApplyPhysicsLocal(boolean applyPhysicsLocal) { 5359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta applyLocal = applyPhysicsLocal; 5459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 5559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 5659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private Vector3f getSpatialTranslation() { 5759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (applyLocal) { 5859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return spatial.getLocalTranslation(); 5959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 6059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return spatial.getWorldTranslation(); 6159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 6259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 6359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public Control cloneForSpatial(Spatial spatial) { 6459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta CharacterControl control = new CharacterControl(collisionShape, stepHeight); 6559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta control.setCcdMotionThreshold(getCcdMotionThreshold()); 6659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta control.setCcdSweptSphereRadius(getCcdSweptSphereRadius()); 6759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta control.setCollideWithGroups(getCollideWithGroups()); 6859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta control.setCollisionGroup(getCollisionGroup()); 6959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta control.setFallSpeed(getFallSpeed()); 7059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta control.setGravity(getGravity()); 7159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta control.setJumpSpeed(getJumpSpeed()); 7259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta control.setMaxSlope(getMaxSlope()); 7359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta control.setPhysicsLocation(getPhysicsLocation()); 7459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta control.setUpAxis(getUpAxis()); 7559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta control.setApplyPhysicsLocal(isApplyPhysicsLocal()); 7659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 7759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta control.setSpatial(spatial); 7859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return control; 7959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 8059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 8159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void setSpatial(Spatial spatial) { 8259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (getUserObject() == null || getUserObject() == this.spatial) { 8359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta setUserObject(spatial); 8459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 8559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.spatial = spatial; 8659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (spatial == null) { 8759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (getUserObject() == spatial) { 8859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta setUserObject(null); 8959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 9059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return; 9159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 9259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta setPhysicsLocation(getSpatialTranslation()); 9359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 9459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 9559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void setEnabled(boolean enabled) { 9659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.enabled = enabled; 9759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (space != null) { 9859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (enabled && !added) { 9959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (spatial != null) { 10059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta warp(getSpatialTranslation()); 10159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 10259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta space.addCollisionObject(this); 10359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta added = true; 10459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else if (!enabled && added) { 10559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta space.removeCollisionObject(this); 10659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta added = false; 10759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 10859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 10959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 11059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 11159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public boolean isEnabled() { 11259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return enabled; 11359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 11459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 11559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void setViewDirection(Vector3f vec) { 11659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta viewDirection.set(vec); 11759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 11859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 11959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public Vector3f getViewDirection() { 12059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return viewDirection; 12159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 12259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 12359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public boolean isUseViewDirection() { 12459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return useViewDirection; 12559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 12659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 12759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void setUseViewDirection(boolean viewDirectionEnabled) { 12859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.useViewDirection = viewDirectionEnabled; 12959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 13059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 13159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void update(float tpf) { 13259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (enabled && spatial != null) { 13359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Quaternion localRotationQuat = spatial.getLocalRotation(); 13459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f localLocation = spatial.getLocalTranslation(); 13559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!applyLocal && spatial.getParent() != null) { 13659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta getPhysicsLocation(localLocation); 13759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta localLocation.subtractLocal(spatial.getParent().getWorldTranslation()); 13859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta localLocation.divideLocal(spatial.getParent().getWorldScale()); 13959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta tmp_inverseWorldRotation.set(spatial.getParent().getWorldRotation()).inverseLocal().multLocal(localLocation); 14059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta spatial.setLocalTranslation(localLocation); 14159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 14259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (useViewDirection) { 14359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta localRotationQuat.lookAt(viewDirection, Vector3f.UNIT_Y); 14459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta spatial.setLocalRotation(localRotationQuat); 14559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 14659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 14759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta spatial.setLocalTranslation(getPhysicsLocation()); 14859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta localRotationQuat.lookAt(viewDirection, Vector3f.UNIT_Y); 14959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta spatial.setLocalRotation(localRotationQuat); 15059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 15159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 15259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 15359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 15459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void render(RenderManager rm, ViewPort vp) { 15559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (enabled && space != null && space.getDebugManager() != null) { 15659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (debugShape == null) { 15759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta attachDebugShape(space.getDebugManager()); 15859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 15959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta debugShape.setLocalTranslation(getPhysicsLocation()); 16059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta debugShape.updateLogicalState(0); 16159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta debugShape.updateGeometricState(); 16259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rm.renderScene(debugShape, vp); 16359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 16459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 16559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 16659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void setPhysicsSpace(PhysicsSpace space) { 16759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (space == null) { 16859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (this.space != null) { 16959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.space.removeCollisionObject(this); 17059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta added = false; 17159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 17259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 17359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (this.space == space) { 17459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return; 17559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 17659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta space.addCollisionObject(this); 17759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta added = true; 17859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 17959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.space = space; 18059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 18159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 18259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public PhysicsSpace getPhysicsSpace() { 18359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return space; 18459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 18559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 18659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta @Override 18759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void write(JmeExporter ex) throws IOException { 18859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta super.write(ex); 18959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta OutputCapsule oc = ex.getCapsule(this); 19059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta oc.write(enabled, "enabled", true); 19159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta oc.write(applyLocal, "applyLocalPhysics", false); 19259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta oc.write(useViewDirection, "viewDirectionEnabled", true); 19359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta oc.write(viewDirection, "viewDirection", new Vector3f(Vector3f.UNIT_Z)); 19459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta oc.write(spatial, "spatial", null); 19559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 19659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 19759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta @Override 19859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void read(JmeImporter im) throws IOException { 19959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta super.read(im); 20059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta InputCapsule ic = im.getCapsule(this); 20159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta enabled = ic.readBoolean("enabled", true); 20259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta useViewDirection = ic.readBoolean("viewDirectionEnabled", true); 20359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta viewDirection = (Vector3f) ic.readSavable("viewDirection", new Vector3f(Vector3f.UNIT_Z)); 20459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta applyLocal = ic.readBoolean("applyLocalPhysics", false); 20559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta spatial = (Spatial) ic.readSavable("spatial", null); 20659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta setUserObject(spatial); 20759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 20859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta} 209