Home | History | Annotate | Download | only in control
      1 /*
      2  * To change this template, choose Tools | Templates
      3  * and open the template in the editor.
      4  */
      5 package com.jme3.bullet.control;
      6 
      7 import com.jme3.bullet.PhysicsSpace;
      8 import com.jme3.bullet.collision.shapes.CollisionShape;
      9 import com.jme3.bullet.objects.PhysicsCharacter;
     10 import com.jme3.export.InputCapsule;
     11 import com.jme3.export.JmeExporter;
     12 import com.jme3.export.JmeImporter;
     13 import com.jme3.export.OutputCapsule;
     14 import com.jme3.math.Quaternion;
     15 import com.jme3.math.Vector3f;
     16 import com.jme3.renderer.RenderManager;
     17 import com.jme3.renderer.ViewPort;
     18 import com.jme3.scene.Spatial;
     19 import com.jme3.scene.control.Control;
     20 import java.io.IOException;
     21 
     22 /**
     23  *
     24  * @author normenhansen
     25  */
     26 public class CharacterControl extends PhysicsCharacter implements PhysicsControl {
     27 
     28     protected Spatial spatial;
     29     protected boolean enabled = true;
     30     protected boolean added = false;
     31     protected PhysicsSpace space = null;
     32     protected Vector3f viewDirection = new Vector3f(Vector3f.UNIT_Z);
     33     protected boolean useViewDirection = true;
     34     protected boolean applyLocal = false;
     35 
     36     public CharacterControl() {
     37     }
     38 
     39     public CharacterControl(CollisionShape shape, float stepHeight) {
     40         super(shape, stepHeight);
     41     }
     42 
     43     public boolean isApplyPhysicsLocal() {
     44         return applyLocal;
     45     }
     46 
     47     /**
     48      * When set to true, the physics coordinates will be applied to the local
     49      * translation of the Spatial
     50      * @param applyPhysicsLocal
     51      */
     52     public void setApplyPhysicsLocal(boolean applyPhysicsLocal) {
     53         applyLocal = applyPhysicsLocal;
     54     }
     55 
     56     private Vector3f getSpatialTranslation() {
     57         if (applyLocal) {
     58             return spatial.getLocalTranslation();
     59         }
     60         return spatial.getWorldTranslation();
     61     }
     62 
     63     public Control cloneForSpatial(Spatial spatial) {
     64         CharacterControl control = new CharacterControl(collisionShape, stepHeight);
     65         control.setCcdMotionThreshold(getCcdMotionThreshold());
     66         control.setCcdSweptSphereRadius(getCcdSweptSphereRadius());
     67         control.setCollideWithGroups(getCollideWithGroups());
     68         control.setCollisionGroup(getCollisionGroup());
     69         control.setFallSpeed(getFallSpeed());
     70         control.setGravity(getGravity());
     71         control.setJumpSpeed(getJumpSpeed());
     72         control.setMaxSlope(getMaxSlope());
     73         control.setPhysicsLocation(getPhysicsLocation());
     74         control.setUpAxis(getUpAxis());
     75         control.setApplyPhysicsLocal(isApplyPhysicsLocal());
     76 
     77         control.setSpatial(spatial);
     78         return control;
     79     }
     80 
     81     public void setSpatial(Spatial spatial) {
     82         if (getUserObject() == null || getUserObject() == this.spatial) {
     83             setUserObject(spatial);
     84         }
     85         this.spatial = spatial;
     86         if (spatial == null) {
     87             if (getUserObject() == spatial) {
     88                 setUserObject(null);
     89             }
     90             return;
     91         }
     92         setPhysicsLocation(getSpatialTranslation());
     93     }
     94 
     95     public void setEnabled(boolean enabled) {
     96         this.enabled = enabled;
     97         if (space != null) {
     98             if (enabled && !added) {
     99                 if (spatial != null) {
    100                     warp(getSpatialTranslation());
    101                 }
    102                 space.addCollisionObject(this);
    103                 added = true;
    104             } else if (!enabled && added) {
    105                 space.removeCollisionObject(this);
    106                 added = false;
    107             }
    108         }
    109     }
    110 
    111     public boolean isEnabled() {
    112         return enabled;
    113     }
    114 
    115     public void setViewDirection(Vector3f vec) {
    116         viewDirection.set(vec);
    117     }
    118 
    119     public Vector3f getViewDirection() {
    120         return viewDirection;
    121     }
    122 
    123     public boolean isUseViewDirection() {
    124         return useViewDirection;
    125     }
    126 
    127     public void setUseViewDirection(boolean viewDirectionEnabled) {
    128         this.useViewDirection = viewDirectionEnabled;
    129     }
    130 
    131     public void update(float tpf) {
    132         if (enabled && spatial != null) {
    133             Quaternion localRotationQuat = spatial.getLocalRotation();
    134             Vector3f localLocation = spatial.getLocalTranslation();
    135             if (!applyLocal && spatial.getParent() != null) {
    136                 getPhysicsLocation(localLocation);
    137                 localLocation.subtractLocal(spatial.getParent().getWorldTranslation());
    138                 localLocation.divideLocal(spatial.getParent().getWorldScale());
    139                 tmp_inverseWorldRotation.set(spatial.getParent().getWorldRotation()).inverseLocal().multLocal(localLocation);
    140                 spatial.setLocalTranslation(localLocation);
    141 
    142                 if (useViewDirection) {
    143                     localRotationQuat.lookAt(viewDirection, Vector3f.UNIT_Y);
    144                     spatial.setLocalRotation(localRotationQuat);
    145                 }
    146             } else {
    147                 spatial.setLocalTranslation(getPhysicsLocation());
    148                 localRotationQuat.lookAt(viewDirection, Vector3f.UNIT_Y);
    149                 spatial.setLocalRotation(localRotationQuat);
    150             }
    151         }
    152     }
    153 
    154     public void render(RenderManager rm, ViewPort vp) {
    155         if (enabled && space != null && space.getDebugManager() != null) {
    156             if (debugShape == null) {
    157                 attachDebugShape(space.getDebugManager());
    158             }
    159             debugShape.setLocalTranslation(getPhysicsLocation());
    160             debugShape.updateLogicalState(0);
    161             debugShape.updateGeometricState();
    162             rm.renderScene(debugShape, vp);
    163         }
    164     }
    165 
    166     public void setPhysicsSpace(PhysicsSpace space) {
    167         if (space == null) {
    168             if (this.space != null) {
    169                 this.space.removeCollisionObject(this);
    170                 added = false;
    171             }
    172         } else {
    173             if (this.space == space) {
    174                 return;
    175             }
    176             space.addCollisionObject(this);
    177             added = true;
    178         }
    179         this.space = space;
    180     }
    181 
    182     public PhysicsSpace getPhysicsSpace() {
    183         return space;
    184     }
    185 
    186     @Override
    187     public void write(JmeExporter ex) throws IOException {
    188         super.write(ex);
    189         OutputCapsule oc = ex.getCapsule(this);
    190         oc.write(enabled, "enabled", true);
    191         oc.write(applyLocal, "applyLocalPhysics", false);
    192         oc.write(useViewDirection, "viewDirectionEnabled", true);
    193         oc.write(viewDirection, "viewDirection", new Vector3f(Vector3f.UNIT_Z));
    194         oc.write(spatial, "spatial", null);
    195     }
    196 
    197     @Override
    198     public void read(JmeImporter im) throws IOException {
    199         super.read(im);
    200         InputCapsule ic = im.getCapsule(this);
    201         enabled = ic.readBoolean("enabled", true);
    202         useViewDirection = ic.readBoolean("viewDirectionEnabled", true);
    203         viewDirection = (Vector3f) ic.readSavable("viewDirection", new Vector3f(Vector3f.UNIT_Z));
    204         applyLocal = ic.readBoolean("applyLocalPhysics", false);
    205         spatial = (Spatial) ic.readSavable("spatial", null);
    206         setUserObject(spatial);
    207     }
    208 }
    209