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.PhysicsVehicle;
1059b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.bullet.objects.VehicleWheel;
1159b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.export.InputCapsule;
1259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.export.JmeExporter;
1359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.export.JmeImporter;
1459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.export.OutputCapsule;
1559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.math.Quaternion;
1659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.math.Vector3f;
1759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.renderer.RenderManager;
1859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.renderer.ViewPort;
1959b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.Geometry;
2059b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.Node;
2159b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.Spatial;
2259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.control.Control;
2359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.debug.Arrow;
2459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.io.IOException;
2559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.Iterator;
2659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
2759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/**
2859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
2959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @author normenhansen
3059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */
3159b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapublic class VehicleControl extends PhysicsVehicle implements PhysicsControl {
3259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
3359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    protected Spatial spatial;
3459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    protected boolean enabled = true;
3559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    protected PhysicsSpace space = null;
3659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    protected boolean added = false;
3759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
3859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public VehicleControl() {
3959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
4059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
4159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
4259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Creates a new PhysicsNode with the supplied collision shape
4359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param shape
4459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
4559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public VehicleControl(CollisionShape shape) {
4659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        super(shape);
4759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
4859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
4959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public VehicleControl(CollisionShape shape, float mass) {
5059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        super(shape, mass);
5159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
5259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
5359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public boolean isApplyPhysicsLocal() {
5459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return motionState.isApplyPhysicsLocal();
5559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
5659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
5759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
5859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * When set to true, the physics coordinates will be applied to the local
5959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * translation of the Spatial
6059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param applyPhysicsLocal
6159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
6259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setApplyPhysicsLocal(boolean applyPhysicsLocal) {
6359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        motionState.setApplyPhysicsLocal(applyPhysicsLocal);
6459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        for (Iterator<VehicleWheel> it = wheels.iterator(); it.hasNext();) {
6559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            VehicleWheel vehicleWheel = it.next();
6659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            vehicleWheel.setApplyLocal(applyPhysicsLocal);
6759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
6859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
6959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
7059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private Vector3f getSpatialTranslation(){
7159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if(motionState.isApplyPhysicsLocal()){
7259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return spatial.getLocalTranslation();
7359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
7459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return spatial.getWorldTranslation();
7559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
7659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
7759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private Quaternion getSpatialRotation(){
7859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if(motionState.isApplyPhysicsLocal()){
7959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return spatial.getLocalRotation();
8059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
8159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return spatial.getWorldRotation();
8259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
8359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
8459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Control cloneForSpatial(Spatial spatial) {
8559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        VehicleControl control = new VehicleControl(collisionShape, mass);
8659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        control.setAngularFactor(getAngularFactor());
8759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        control.setAngularSleepingThreshold(getAngularSleepingThreshold());
8859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        control.setAngularVelocity(getAngularVelocity());
8959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        control.setCcdMotionThreshold(getCcdMotionThreshold());
9059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        control.setCcdSweptSphereRadius(getCcdSweptSphereRadius());
9159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        control.setCollideWithGroups(getCollideWithGroups());
9259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        control.setCollisionGroup(getCollisionGroup());
9359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        control.setDamping(getLinearDamping(), getAngularDamping());
9459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        control.setFriction(getFriction());
9559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        control.setGravity(getGravity());
9659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        control.setKinematic(isKinematic());
9759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        control.setLinearSleepingThreshold(getLinearSleepingThreshold());
9859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        control.setLinearVelocity(getLinearVelocity());
9959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        control.setPhysicsLocation(getPhysicsLocation());
10059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        control.setPhysicsRotation(getPhysicsRotationMatrix());
10159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        control.setRestitution(getRestitution());
10259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
10359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        control.setFrictionSlip(getFrictionSlip());
10459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        control.setMaxSuspensionTravelCm(getMaxSuspensionTravelCm());
10559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        control.setSuspensionStiffness(getSuspensionStiffness());
10659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        control.setSuspensionCompression(tuning.suspensionCompression);
10759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        control.setSuspensionDamping(tuning.suspensionDamping);
10859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        control.setMaxSuspensionForce(getMaxSuspensionForce());
10959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
11059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        for (Iterator<VehicleWheel> it = wheels.iterator(); it.hasNext();) {
11159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            VehicleWheel wheel = it.next();
11259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            VehicleWheel newWheel = control.addWheel(wheel.getLocation(), wheel.getDirection(), wheel.getAxle(), wheel.getRestLength(), wheel.getRadius(), wheel.isFrontWheel());
11359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            newWheel.setFrictionSlip(wheel.getFrictionSlip());
11459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            newWheel.setMaxSuspensionTravelCm(wheel.getMaxSuspensionTravelCm());
11559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            newWheel.setSuspensionStiffness(wheel.getSuspensionStiffness());
11659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            newWheel.setWheelsDampingCompression(wheel.getWheelsDampingCompression());
11759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            newWheel.setWheelsDampingRelaxation(wheel.getWheelsDampingRelaxation());
11859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            newWheel.setMaxSuspensionForce(wheel.getMaxSuspensionForce());
11959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
12059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            //TODO: bad way finding children!
12159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (spatial instanceof Node) {
12259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                Node node = (Node) spatial;
12359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                Spatial wheelSpat = node.getChild(wheel.getWheelSpatial().getName());
12459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                if (wheelSpat != null) {
12559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    newWheel.setWheelSpatial(wheelSpat);
12659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                }
12759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
12859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
12959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        control.setApplyPhysicsLocal(isApplyPhysicsLocal());
13059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
13159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        control.setSpatial(spatial);
13259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return control;
13359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
13459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
13559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setSpatial(Spatial spatial) {
13659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (getUserObject() == null || getUserObject() == this.spatial) {
13759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            setUserObject(spatial);
13859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
13959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.spatial = spatial;
14059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (spatial == null) {
14159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (getUserObject() == spatial) {
14259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                setUserObject(null);
14359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
14459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            this.spatial = null;
14559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            this.collisionShape = null;
14659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return;
14759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
14859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        setPhysicsLocation(getSpatialTranslation());
14959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        setPhysicsRotation(getSpatialRotation());
15059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
15159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
15259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setEnabled(boolean enabled) {
15359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.enabled = enabled;
15459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (space != null) {
15559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (enabled && !added) {
15659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                if(spatial!=null){
15759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    setPhysicsLocation(getSpatialTranslation());
15859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    setPhysicsRotation(getSpatialRotation());
15959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                }
16059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                space.addCollisionObject(this);
16159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                added = true;
16259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            } else if (!enabled && added) {
16359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                space.removeCollisionObject(this);
16459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                added = false;
16559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
16659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
16759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
16859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
16959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public boolean isEnabled() {
17059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return enabled;
17159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
17259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
17359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void update(float tpf) {
17459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (enabled && spatial != null) {
17559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (getMotionState().applyTransform(spatial)) {
17659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                spatial.getWorldTransform();
17759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                applyWheelTransforms();
17859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
17959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else if (enabled) {
18059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            applyWheelTransforms();
18159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
18259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
18359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
18459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    @Override
18559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    protected Spatial getDebugShape() {
18659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return super.getDebugShape();
18759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
18859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
18959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void render(RenderManager rm, ViewPort vp) {
19059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (enabled && space != null && space.getDebugManager() != null) {
19159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (debugShape == null) {
19259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                attachDebugShape(space.getDebugManager());
19359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
19459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            Node debugNode = (Node) debugShape;
19559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            debugShape.setLocalTranslation(spatial.getWorldTranslation());
19659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            debugShape.setLocalRotation(spatial.getWorldRotation());
19759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            int i = 0;
19859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            for (Iterator<VehicleWheel> it = wheels.iterator(); it.hasNext();) {
19959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                VehicleWheel physicsVehicleWheel = it.next();
20059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                Vector3f location = physicsVehicleWheel.getLocation().clone();
20159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                Vector3f direction = physicsVehicleWheel.getDirection().clone();
20259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                Vector3f axle = physicsVehicleWheel.getAxle().clone();
20359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                float restLength = physicsVehicleWheel.getRestLength();
20459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                float radius = physicsVehicleWheel.getRadius();
20559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
20659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                Geometry locGeom = (Geometry) debugNode.getChild("WheelLocationDebugShape" + i);
20759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                Geometry dirGeom = (Geometry) debugNode.getChild("WheelDirectionDebugShape" + i);
20859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                Geometry axleGeom = (Geometry) debugNode.getChild("WheelAxleDebugShape" + i);
20959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                Geometry wheelGeom = (Geometry) debugNode.getChild("WheelRadiusDebugShape" + i);
21059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
21159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                Arrow locArrow = (Arrow) locGeom.getMesh();
21259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                locArrow.setArrowExtent(location);
21359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                Arrow axleArrow = (Arrow) axleGeom.getMesh();
21459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                axleArrow.setArrowExtent(axle.normalizeLocal().multLocal(0.3f));
21559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                Arrow wheelArrow = (Arrow) wheelGeom.getMesh();
21659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                wheelArrow.setArrowExtent(direction.normalizeLocal().multLocal(radius));
21759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                Arrow dirArrow = (Arrow) dirGeom.getMesh();
21859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                dirArrow.setArrowExtent(direction.normalizeLocal().multLocal(restLength));
21959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
22059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                dirGeom.setLocalTranslation(location);
22159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                axleGeom.setLocalTranslation(location.addLocal(direction));
22259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                wheelGeom.setLocalTranslation(location);
22359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                i++;
22459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
22559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            debugShape.updateLogicalState(0);
22659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            debugShape.updateGeometricState();
22759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            rm.renderScene(debugShape, vp);
22859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
22959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
23059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
23159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setPhysicsSpace(PhysicsSpace space) {
23259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        createVehicle(space);
23359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (space == null) {
23459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (this.space != null) {
23559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                this.space.removeCollisionObject(this);
23659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                added = false;
23759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
23859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else {
23959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if(this.space==space) return;
24059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            space.addCollisionObject(this);
24159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            added = true;
24259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
24359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.space = space;
24459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
24559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
24659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public PhysicsSpace getPhysicsSpace() {
24759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return space;
24859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
24959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
25059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    @Override
25159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void write(JmeExporter ex) throws IOException {
25259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        super.write(ex);
25359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        OutputCapsule oc = ex.getCapsule(this);
25459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        oc.write(enabled, "enabled", true);
25559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        oc.write(motionState.isApplyPhysicsLocal(), "applyLocalPhysics", false);
25659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        oc.write(spatial, "spatial", null);
25759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
25859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
25959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    @Override
26059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void read(JmeImporter im) throws IOException {
26159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        super.read(im);
26259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        InputCapsule ic = im.getCapsule(this);
26359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        enabled = ic.readBoolean("enabled", true);
26459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        spatial = (Spatial) ic.readSavable("spatial", null);
26559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        motionState.setApplyPhysicsLocal(ic.readBoolean("applyLocalPhysics", false));
26659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        setUserObject(spatial);
26759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
26859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta}
269