diff options
Diffstat (limited to 'engine/src/bullet-common/com/jme3/bullet/control/RigidBodyControl.java')
-rw-r--r-- | engine/src/bullet-common/com/jme3/bullet/control/RigidBodyControl.java | 264 |
1 files changed, 264 insertions, 0 deletions
diff --git a/engine/src/bullet-common/com/jme3/bullet/control/RigidBodyControl.java b/engine/src/bullet-common/com/jme3/bullet/control/RigidBodyControl.java new file mode 100644 index 0000000..4fbce1e --- /dev/null +++ b/engine/src/bullet-common/com/jme3/bullet/control/RigidBodyControl.java @@ -0,0 +1,264 @@ +/* + * 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.BoxCollisionShape; +import com.jme3.bullet.collision.shapes.CollisionShape; +import com.jme3.bullet.collision.shapes.SphereCollisionShape; +import com.jme3.bullet.objects.PhysicsRigidBody; +import com.jme3.bullet.util.CollisionShapeFactory; +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.Geometry; +import com.jme3.scene.Mesh; +import com.jme3.scene.Spatial; +import com.jme3.scene.control.Control; +import com.jme3.scene.shape.Box; +import com.jme3.scene.shape.Sphere; +import java.io.IOException; + +/** + * + * @author normenhansen + */ +public class RigidBodyControl extends PhysicsRigidBody implements PhysicsControl { + + protected Spatial spatial; + protected boolean enabled = true; + protected boolean added = false; + protected PhysicsSpace space = null; + protected boolean kinematicSpatial = true; + + public RigidBodyControl() { + } + + /** + * When using this constructor, the CollisionShape for the RigidBody is generated + * automatically when the Control is added to a Spatial. + * @param mass When not 0, a HullCollisionShape is generated, otherwise a MeshCollisionShape is used. For geometries with box or sphere meshes the proper box or sphere collision shape is used. + */ + public RigidBodyControl(float mass) { + this.mass = mass; + } + + /** + * Creates a new PhysicsNode with the supplied collision shape and mass 1 + * @param shape + */ + public RigidBodyControl(CollisionShape shape) { + super(shape); + } + + public RigidBodyControl(CollisionShape shape, float mass) { + super(shape, mass); + } + + public Control cloneForSpatial(Spatial spatial) { + RigidBodyControl control = new RigidBodyControl(collisionShape, mass); + control.setAngularFactor(getAngularFactor()); + control.setAngularSleepingThreshold(getAngularSleepingThreshold()); + control.setCcdMotionThreshold(getCcdMotionThreshold()); + control.setCcdSweptSphereRadius(getCcdSweptSphereRadius()); + control.setCollideWithGroups(getCollideWithGroups()); + control.setCollisionGroup(getCollisionGroup()); + control.setDamping(getLinearDamping(), getAngularDamping()); + control.setFriction(getFriction()); + control.setGravity(getGravity()); + control.setKinematic(isKinematic()); + control.setKinematicSpatial(isKinematicSpatial()); + control.setLinearSleepingThreshold(getLinearSleepingThreshold()); + control.setPhysicsLocation(getPhysicsLocation(null)); + control.setPhysicsRotation(getPhysicsRotationMatrix(null)); + control.setRestitution(getRestitution()); + + if (mass > 0) { + control.setAngularVelocity(getAngularVelocity()); + control.setLinearVelocity(getLinearVelocity()); + } + 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); + } + spatial = null; + collisionShape = null; + return; + } + if (collisionShape == null) { + createCollisionShape(); + rebuildRigidBody(); + } + setPhysicsLocation(getSpatialTranslation()); + setPhysicsRotation(getSpatialRotation()); + } + + protected void createCollisionShape() { + if (spatial == null) { + return; + } + if (spatial instanceof Geometry) { + Geometry geom = (Geometry) spatial; + Mesh mesh = geom.getMesh(); + if (mesh instanceof Sphere) { + collisionShape = new SphereCollisionShape(((Sphere) mesh).getRadius()); + return; + } else if (mesh instanceof Box) { + collisionShape = new BoxCollisionShape(new Vector3f(((Box) mesh).getXExtent(), ((Box) mesh).getYExtent(), ((Box) mesh).getZExtent())); + return; + } + } + if (mass > 0) { + collisionShape = CollisionShapeFactory.createDynamicMeshShape(spatial); + } else { + collisionShape = CollisionShapeFactory.createMeshShape(spatial); + } + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + if (space != null) { + if (enabled && !added) { + if (spatial != null) { + setPhysicsLocation(getSpatialTranslation()); + setPhysicsRotation(getSpatialRotation()); + } + space.addCollisionObject(this); + added = true; + } else if (!enabled && added) { + space.removeCollisionObject(this); + added = false; + } + } + } + + public boolean isEnabled() { + return enabled; + } + + /** + * Checks if this control is in kinematic spatial mode. + * @return true if the spatial location is applied to this kinematic rigidbody + */ + public boolean isKinematicSpatial() { + return kinematicSpatial; + } + + /** + * Sets this control to kinematic spatial mode so that the spatials transform will + * be applied to the rigidbody in kinematic mode, defaults to true. + * @param kinematicSpatial + */ + public void setKinematicSpatial(boolean kinematicSpatial) { + this.kinematicSpatial = kinematicSpatial; + } + + public boolean isApplyPhysicsLocal() { + return motionState.isApplyPhysicsLocal(); + } + + /** + * When set to true, the physics coordinates will be applied to the local + * translation of the Spatial instead of the world traslation. + * @param applyPhysicsLocal + */ + public void setApplyPhysicsLocal(boolean applyPhysicsLocal) { + motionState.setApplyPhysicsLocal(applyPhysicsLocal); + } + + private Vector3f getSpatialTranslation(){ + if(motionState.isApplyPhysicsLocal()){ + return spatial.getLocalTranslation(); + } + return spatial.getWorldTranslation(); + } + + private Quaternion getSpatialRotation(){ + if(motionState.isApplyPhysicsLocal()){ + return spatial.getLocalRotation(); + } + return spatial.getWorldRotation(); + } + + public void update(float tpf) { + if (enabled && spatial != null) { + if (isKinematic() && kinematicSpatial) { + super.setPhysicsLocation(getSpatialTranslation()); + super.setPhysicsRotation(getSpatialRotation()); + } else { + getMotionState().applyTransform(spatial); + } + } + } + + public void render(RenderManager rm, ViewPort vp) { + if (enabled && space != null && space.getDebugManager() != null) { + if (debugShape == null) { + attachDebugShape(space.getDebugManager()); + } + //TODO: using spatial traslation/rotation.. + debugShape.setLocalTranslation(spatial.getWorldTranslation()); + debugShape.setLocalRotation(spatial.getWorldRotation()); + 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(motionState.isApplyPhysicsLocal(), "applyLocalPhysics", false); + oc.write(kinematicSpatial, "kinematicSpatial", true); + 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); + kinematicSpatial = ic.readBoolean("kinematicSpatial", true); + spatial = (Spatial) ic.readSavable("spatial", null); + motionState.setApplyPhysicsLocal(ic.readBoolean("applyLocalPhysics", false)); + setUserObject(spatial); + } +} |