• 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.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 
CharacterControl()36     public CharacterControl() {
37     }
38 
CharacterControl(CollisionShape shape, float stepHeight)39     public CharacterControl(CollisionShape shape, float stepHeight) {
40         super(shape, stepHeight);
41     }
42 
isApplyPhysicsLocal()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      */
setApplyPhysicsLocal(boolean applyPhysicsLocal)52     public void setApplyPhysicsLocal(boolean applyPhysicsLocal) {
53         applyLocal = applyPhysicsLocal;
54     }
55 
getSpatialTranslation()56     private Vector3f getSpatialTranslation() {
57         if (applyLocal) {
58             return spatial.getLocalTranslation();
59         }
60         return spatial.getWorldTranslation();
61     }
62 
cloneForSpatial(Spatial spatial)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 
setSpatial(Spatial spatial)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 
setEnabled(boolean enabled)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 
isEnabled()111     public boolean isEnabled() {
112         return enabled;
113     }
114 
setViewDirection(Vector3f vec)115     public void setViewDirection(Vector3f vec) {
116         viewDirection.set(vec);
117     }
118 
getViewDirection()119     public Vector3f getViewDirection() {
120         return viewDirection;
121     }
122 
isUseViewDirection()123     public boolean isUseViewDirection() {
124         return useViewDirection;
125     }
126 
setUseViewDirection(boolean viewDirectionEnabled)127     public void setUseViewDirection(boolean viewDirectionEnabled) {
128         this.useViewDirection = viewDirectionEnabled;
129     }
130 
update(float tpf)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 
render(RenderManager rm, ViewPort vp)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 
setPhysicsSpace(PhysicsSpace space)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 
getPhysicsSpace()182     public PhysicsSpace getPhysicsSpace() {
183         return space;
184     }
185 
186     @Override
write(JmeExporter ex)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
read(JmeImporter im)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