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.PhysicsVehicle;
     10 import com.jme3.bullet.objects.VehicleWheel;
     11 import com.jme3.export.InputCapsule;
     12 import com.jme3.export.JmeExporter;
     13 import com.jme3.export.JmeImporter;
     14 import com.jme3.export.OutputCapsule;
     15 import com.jme3.math.Quaternion;
     16 import com.jme3.math.Vector3f;
     17 import com.jme3.renderer.RenderManager;
     18 import com.jme3.renderer.ViewPort;
     19 import com.jme3.scene.Geometry;
     20 import com.jme3.scene.Node;
     21 import com.jme3.scene.Spatial;
     22 import com.jme3.scene.control.Control;
     23 import com.jme3.scene.debug.Arrow;
     24 import java.io.IOException;
     25 import java.util.Iterator;
     26 
     27 /**
     28  *
     29  * @author normenhansen
     30  */
     31 public class VehicleControl extends PhysicsVehicle implements PhysicsControl {
     32 
     33     protected Spatial spatial;
     34     protected boolean enabled = true;
     35     protected PhysicsSpace space = null;
     36     protected boolean added = false;
     37 
     38     public VehicleControl() {
     39     }
     40 
     41     /**
     42      * Creates a new PhysicsNode with the supplied collision shape
     43      * @param shape
     44      */
     45     public VehicleControl(CollisionShape shape) {
     46         super(shape);
     47     }
     48 
     49     public VehicleControl(CollisionShape shape, float mass) {
     50         super(shape, mass);
     51     }
     52 
     53     public boolean isApplyPhysicsLocal() {
     54         return motionState.isApplyPhysicsLocal();
     55     }
     56 
     57     /**
     58      * When set to true, the physics coordinates will be applied to the local
     59      * translation of the Spatial
     60      * @param applyPhysicsLocal
     61      */
     62     public void setApplyPhysicsLocal(boolean applyPhysicsLocal) {
     63         motionState.setApplyPhysicsLocal(applyPhysicsLocal);
     64         for (Iterator<VehicleWheel> it = wheels.iterator(); it.hasNext();) {
     65             VehicleWheel vehicleWheel = it.next();
     66             vehicleWheel.setApplyLocal(applyPhysicsLocal);
     67         }
     68     }
     69 
     70     private Vector3f getSpatialTranslation(){
     71         if(motionState.isApplyPhysicsLocal()){
     72             return spatial.getLocalTranslation();
     73         }
     74         return spatial.getWorldTranslation();
     75     }
     76 
     77     private Quaternion getSpatialRotation(){
     78         if(motionState.isApplyPhysicsLocal()){
     79             return spatial.getLocalRotation();
     80         }
     81         return spatial.getWorldRotation();
     82     }
     83 
     84     public Control cloneForSpatial(Spatial spatial) {
     85         VehicleControl control = new VehicleControl(collisionShape, mass);
     86         control.setAngularFactor(getAngularFactor());
     87         control.setAngularSleepingThreshold(getAngularSleepingThreshold());
     88         control.setAngularVelocity(getAngularVelocity());
     89         control.setCcdMotionThreshold(getCcdMotionThreshold());
     90         control.setCcdSweptSphereRadius(getCcdSweptSphereRadius());
     91         control.setCollideWithGroups(getCollideWithGroups());
     92         control.setCollisionGroup(getCollisionGroup());
     93         control.setDamping(getLinearDamping(), getAngularDamping());
     94         control.setFriction(getFriction());
     95         control.setGravity(getGravity());
     96         control.setKinematic(isKinematic());
     97         control.setLinearSleepingThreshold(getLinearSleepingThreshold());
     98         control.setLinearVelocity(getLinearVelocity());
     99         control.setPhysicsLocation(getPhysicsLocation());
    100         control.setPhysicsRotation(getPhysicsRotationMatrix());
    101         control.setRestitution(getRestitution());
    102 
    103         control.setFrictionSlip(getFrictionSlip());
    104         control.setMaxSuspensionTravelCm(getMaxSuspensionTravelCm());
    105         control.setSuspensionStiffness(getSuspensionStiffness());
    106         control.setSuspensionCompression(tuning.suspensionCompression);
    107         control.setSuspensionDamping(tuning.suspensionDamping);
    108         control.setMaxSuspensionForce(getMaxSuspensionForce());
    109 
    110         for (Iterator<VehicleWheel> it = wheels.iterator(); it.hasNext();) {
    111             VehicleWheel wheel = it.next();
    112             VehicleWheel newWheel = control.addWheel(wheel.getLocation(), wheel.getDirection(), wheel.getAxle(), wheel.getRestLength(), wheel.getRadius(), wheel.isFrontWheel());
    113             newWheel.setFrictionSlip(wheel.getFrictionSlip());
    114             newWheel.setMaxSuspensionTravelCm(wheel.getMaxSuspensionTravelCm());
    115             newWheel.setSuspensionStiffness(wheel.getSuspensionStiffness());
    116             newWheel.setWheelsDampingCompression(wheel.getWheelsDampingCompression());
    117             newWheel.setWheelsDampingRelaxation(wheel.getWheelsDampingRelaxation());
    118             newWheel.setMaxSuspensionForce(wheel.getMaxSuspensionForce());
    119 
    120             //TODO: bad way finding children!
    121             if (spatial instanceof Node) {
    122                 Node node = (Node) spatial;
    123                 Spatial wheelSpat = node.getChild(wheel.getWheelSpatial().getName());
    124                 if (wheelSpat != null) {
    125                     newWheel.setWheelSpatial(wheelSpat);
    126                 }
    127             }
    128         }
    129         control.setApplyPhysicsLocal(isApplyPhysicsLocal());
    130 
    131         control.setSpatial(spatial);
    132         return control;
    133     }
    134 
    135     public void setSpatial(Spatial spatial) {
    136         if (getUserObject() == null || getUserObject() == this.spatial) {
    137             setUserObject(spatial);
    138         }
    139         this.spatial = spatial;
    140         if (spatial == null) {
    141             if (getUserObject() == spatial) {
    142                 setUserObject(null);
    143             }
    144             this.spatial = null;
    145             this.collisionShape = null;
    146             return;
    147         }
    148         setPhysicsLocation(getSpatialTranslation());
    149         setPhysicsRotation(getSpatialRotation());
    150     }
    151 
    152     public void setEnabled(boolean enabled) {
    153         this.enabled = enabled;
    154         if (space != null) {
    155             if (enabled && !added) {
    156                 if(spatial!=null){
    157                     setPhysicsLocation(getSpatialTranslation());
    158                     setPhysicsRotation(getSpatialRotation());
    159                 }
    160                 space.addCollisionObject(this);
    161                 added = true;
    162             } else if (!enabled && added) {
    163                 space.removeCollisionObject(this);
    164                 added = false;
    165             }
    166         }
    167     }
    168 
    169     public boolean isEnabled() {
    170         return enabled;
    171     }
    172 
    173     public void update(float tpf) {
    174         if (enabled && spatial != null) {
    175             if (getMotionState().applyTransform(spatial)) {
    176                 spatial.getWorldTransform();
    177                 applyWheelTransforms();
    178             }
    179         } else if (enabled) {
    180             applyWheelTransforms();
    181         }
    182     }
    183 
    184     @Override
    185     protected Spatial getDebugShape() {
    186         return super.getDebugShape();
    187     }
    188 
    189     public void render(RenderManager rm, ViewPort vp) {
    190         if (enabled && space != null && space.getDebugManager() != null) {
    191             if (debugShape == null) {
    192                 attachDebugShape(space.getDebugManager());
    193             }
    194             Node debugNode = (Node) debugShape;
    195             debugShape.setLocalTranslation(spatial.getWorldTranslation());
    196             debugShape.setLocalRotation(spatial.getWorldRotation());
    197             int i = 0;
    198             for (Iterator<VehicleWheel> it = wheels.iterator(); it.hasNext();) {
    199                 VehicleWheel physicsVehicleWheel = it.next();
    200                 Vector3f location = physicsVehicleWheel.getLocation().clone();
    201                 Vector3f direction = physicsVehicleWheel.getDirection().clone();
    202                 Vector3f axle = physicsVehicleWheel.getAxle().clone();
    203                 float restLength = physicsVehicleWheel.getRestLength();
    204                 float radius = physicsVehicleWheel.getRadius();
    205 
    206                 Geometry locGeom = (Geometry) debugNode.getChild("WheelLocationDebugShape" + i);
    207                 Geometry dirGeom = (Geometry) debugNode.getChild("WheelDirectionDebugShape" + i);
    208                 Geometry axleGeom = (Geometry) debugNode.getChild("WheelAxleDebugShape" + i);
    209                 Geometry wheelGeom = (Geometry) debugNode.getChild("WheelRadiusDebugShape" + i);
    210 
    211                 Arrow locArrow = (Arrow) locGeom.getMesh();
    212                 locArrow.setArrowExtent(location);
    213                 Arrow axleArrow = (Arrow) axleGeom.getMesh();
    214                 axleArrow.setArrowExtent(axle.normalizeLocal().multLocal(0.3f));
    215                 Arrow wheelArrow = (Arrow) wheelGeom.getMesh();
    216                 wheelArrow.setArrowExtent(direction.normalizeLocal().multLocal(radius));
    217                 Arrow dirArrow = (Arrow) dirGeom.getMesh();
    218                 dirArrow.setArrowExtent(direction.normalizeLocal().multLocal(restLength));
    219 
    220                 dirGeom.setLocalTranslation(location);
    221                 axleGeom.setLocalTranslation(location.addLocal(direction));
    222                 wheelGeom.setLocalTranslation(location);
    223                 i++;
    224             }
    225             debugShape.updateLogicalState(0);
    226             debugShape.updateGeometricState();
    227             rm.renderScene(debugShape, vp);
    228         }
    229     }
    230 
    231     public void setPhysicsSpace(PhysicsSpace space) {
    232         createVehicle(space);
    233         if (space == null) {
    234             if (this.space != null) {
    235                 this.space.removeCollisionObject(this);
    236                 added = false;
    237             }
    238         } else {
    239             if(this.space==space) return;
    240             space.addCollisionObject(this);
    241             added = true;
    242         }
    243         this.space = space;
    244     }
    245 
    246     public PhysicsSpace getPhysicsSpace() {
    247         return space;
    248     }
    249 
    250     @Override
    251     public void write(JmeExporter ex) throws IOException {
    252         super.write(ex);
    253         OutputCapsule oc = ex.getCapsule(this);
    254         oc.write(enabled, "enabled", true);
    255         oc.write(motionState.isApplyPhysicsLocal(), "applyLocalPhysics", false);
    256         oc.write(spatial, "spatial", null);
    257     }
    258 
    259     @Override
    260     public void read(JmeImporter im) throws IOException {
    261         super.read(im);
    262         InputCapsule ic = im.getCapsule(this);
    263         enabled = ic.readBoolean("enabled", true);
    264         spatial = (Spatial) ic.readSavable("spatial", null);
    265         motionState.setApplyPhysicsLocal(ic.readBoolean("applyLocalPhysics", false));
    266         setUserObject(spatial);
    267     }
    268 }
    269