diff options
Diffstat (limited to 'engine/src/bullet-common/com/jme3/bullet/control/CharacterControl.java')
-rw-r--r-- | engine/src/bullet-common/com/jme3/bullet/control/CharacterControl.java | 208 |
1 files changed, 208 insertions, 0 deletions
diff --git a/engine/src/bullet-common/com/jme3/bullet/control/CharacterControl.java b/engine/src/bullet-common/com/jme3/bullet/control/CharacterControl.java new file mode 100644 index 0000000..2acac53 --- /dev/null +++ b/engine/src/bullet-common/com/jme3/bullet/control/CharacterControl.java @@ -0,0 +1,208 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.bullet.control; + +import com.jme3.bullet.PhysicsSpace; +import com.jme3.bullet.collision.shapes.CollisionShape; +import com.jme3.bullet.objects.PhysicsCharacter; +import com.jme3.export.InputCapsule; +import com.jme3.export.JmeExporter; +import com.jme3.export.JmeImporter; +import com.jme3.export.OutputCapsule; +import com.jme3.math.Quaternion; +import com.jme3.math.Vector3f; +import com.jme3.renderer.RenderManager; +import com.jme3.renderer.ViewPort; +import com.jme3.scene.Spatial; +import com.jme3.scene.control.Control; +import java.io.IOException; + +/** + * + * @author normenhansen + */ +public class CharacterControl extends PhysicsCharacter implements PhysicsControl { + + protected Spatial spatial; + protected boolean enabled = true; + protected boolean added = false; + protected PhysicsSpace space = null; + protected Vector3f viewDirection = new Vector3f(Vector3f.UNIT_Z); + protected boolean useViewDirection = true; + protected boolean applyLocal = false; + + public CharacterControl() { + } + + public CharacterControl(CollisionShape shape, float stepHeight) { + super(shape, stepHeight); + } + + public boolean isApplyPhysicsLocal() { + return applyLocal; + } + + /** + * When set to true, the physics coordinates will be applied to the local + * translation of the Spatial + * @param applyPhysicsLocal + */ + public void setApplyPhysicsLocal(boolean applyPhysicsLocal) { + applyLocal = applyPhysicsLocal; + } + + private Vector3f getSpatialTranslation() { + if (applyLocal) { + return spatial.getLocalTranslation(); + } + return spatial.getWorldTranslation(); + } + + public Control cloneForSpatial(Spatial spatial) { + CharacterControl control = new CharacterControl(collisionShape, stepHeight); + control.setCcdMotionThreshold(getCcdMotionThreshold()); + control.setCcdSweptSphereRadius(getCcdSweptSphereRadius()); + control.setCollideWithGroups(getCollideWithGroups()); + control.setCollisionGroup(getCollisionGroup()); + control.setFallSpeed(getFallSpeed()); + control.setGravity(getGravity()); + control.setJumpSpeed(getJumpSpeed()); + control.setMaxSlope(getMaxSlope()); + control.setPhysicsLocation(getPhysicsLocation()); + control.setUpAxis(getUpAxis()); + control.setApplyPhysicsLocal(isApplyPhysicsLocal()); + + control.setSpatial(spatial); + return control; + } + + public void setSpatial(Spatial spatial) { + if (getUserObject() == null || getUserObject() == this.spatial) { + setUserObject(spatial); + } + this.spatial = spatial; + if (spatial == null) { + if (getUserObject() == spatial) { + setUserObject(null); + } + return; + } + setPhysicsLocation(getSpatialTranslation()); + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + if (space != null) { + if (enabled && !added) { + if (spatial != null) { + warp(getSpatialTranslation()); + } + space.addCollisionObject(this); + added = true; + } else if (!enabled && added) { + space.removeCollisionObject(this); + added = false; + } + } + } + + public boolean isEnabled() { + return enabled; + } + + public void setViewDirection(Vector3f vec) { + viewDirection.set(vec); + } + + public Vector3f getViewDirection() { + return viewDirection; + } + + public boolean isUseViewDirection() { + return useViewDirection; + } + + public void setUseViewDirection(boolean viewDirectionEnabled) { + this.useViewDirection = viewDirectionEnabled; + } + + public void update(float tpf) { + if (enabled && spatial != null) { + Quaternion localRotationQuat = spatial.getLocalRotation(); + Vector3f localLocation = spatial.getLocalTranslation(); + if (!applyLocal && spatial.getParent() != null) { + getPhysicsLocation(localLocation); + localLocation.subtractLocal(spatial.getParent().getWorldTranslation()); + localLocation.divideLocal(spatial.getParent().getWorldScale()); + tmp_inverseWorldRotation.set(spatial.getParent().getWorldRotation()).inverseLocal().multLocal(localLocation); + spatial.setLocalTranslation(localLocation); + + if (useViewDirection) { + localRotationQuat.lookAt(viewDirection, Vector3f.UNIT_Y); + spatial.setLocalRotation(localRotationQuat); + } + } else { + spatial.setLocalTranslation(getPhysicsLocation()); + localRotationQuat.lookAt(viewDirection, Vector3f.UNIT_Y); + spatial.setLocalRotation(localRotationQuat); + } + } + } + + public void render(RenderManager rm, ViewPort vp) { + if (enabled && space != null && space.getDebugManager() != null) { + if (debugShape == null) { + attachDebugShape(space.getDebugManager()); + } + debugShape.setLocalTranslation(getPhysicsLocation()); + debugShape.updateLogicalState(0); + debugShape.updateGeometricState(); + rm.renderScene(debugShape, vp); + } + } + + public void setPhysicsSpace(PhysicsSpace space) { + if (space == null) { + if (this.space != null) { + this.space.removeCollisionObject(this); + added = false; + } + } else { + if (this.space == space) { + return; + } + space.addCollisionObject(this); + added = true; + } + this.space = space; + } + + public PhysicsSpace getPhysicsSpace() { + return space; + } + + @Override + public void write(JmeExporter ex) throws IOException { + super.write(ex); + OutputCapsule oc = ex.getCapsule(this); + oc.write(enabled, "enabled", true); + oc.write(applyLocal, "applyLocalPhysics", false); + oc.write(useViewDirection, "viewDirectionEnabled", true); + oc.write(viewDirection, "viewDirection", new Vector3f(Vector3f.UNIT_Z)); + oc.write(spatial, "spatial", null); + } + + @Override + public void read(JmeImporter im) throws IOException { + super.read(im); + InputCapsule ic = im.getCapsule(this); + enabled = ic.readBoolean("enabled", true); + useViewDirection = ic.readBoolean("viewDirectionEnabled", true); + viewDirection = (Vector3f) ic.readSavable("viewDirection", new Vector3f(Vector3f.UNIT_Z)); + applyLocal = ic.readBoolean("applyLocalPhysics", false); + spatial = (Spatial) ic.readSavable("spatial", null); + setUserObject(spatial); + } +} |