• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
VehicleControl()38     public VehicleControl() {
39     }
40 
41     /**
42      * Creates a new PhysicsNode with the supplied collision shape
43      * @param shape
44      */
VehicleControl(CollisionShape shape)45     public VehicleControl(CollisionShape shape) {
46         super(shape);
47     }
48 
VehicleControl(CollisionShape shape, float mass)49     public VehicleControl(CollisionShape shape, float mass) {
50         super(shape, mass);
51     }
52 
isApplyPhysicsLocal()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      */
setApplyPhysicsLocal(boolean applyPhysicsLocal)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 
getSpatialTranslation()70     private Vector3f getSpatialTranslation(){
71         if(motionState.isApplyPhysicsLocal()){
72             return spatial.getLocalTranslation();
73         }
74         return spatial.getWorldTranslation();
75     }
76 
getSpatialRotation()77     private Quaternion getSpatialRotation(){
78         if(motionState.isApplyPhysicsLocal()){
79             return spatial.getLocalRotation();
80         }
81         return spatial.getWorldRotation();
82     }
83 
cloneForSpatial(Spatial spatial)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 
setSpatial(Spatial spatial)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 
setEnabled(boolean enabled)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 
isEnabled()169     public boolean isEnabled() {
170         return enabled;
171     }
172 
update(float tpf)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
getDebugShape()185     protected Spatial getDebugShape() {
186         return super.getDebugShape();
187     }
188 
render(RenderManager rm, ViewPort vp)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 
setPhysicsSpace(PhysicsSpace space)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 
getPhysicsSpace()246     public PhysicsSpace getPhysicsSpace() {
247         return space;
248     }
249 
250     @Override
write(JmeExporter ex)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
read(JmeImporter im)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