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.PhysicsGhostObject; 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 * A GhostControl moves with the spatial it is attached to and can be used to check 24 * overlaps with other physics objects (e.g. aggro radius). 25 * @author normenhansen 26 */ 27 public class GhostControl extends PhysicsGhostObject implements PhysicsControl { 28 29 protected Spatial spatial; 30 protected boolean enabled = true; 31 protected boolean added = false; 32 protected PhysicsSpace space = null; 33 protected boolean applyLocal = false; 34 35 public GhostControl() { 36 } 37 38 public GhostControl(CollisionShape shape) { 39 super(shape); 40 } 41 42 public boolean isApplyPhysicsLocal() { 43 return applyLocal; 44 } 45 46 /** 47 * When set to true, the physics coordinates will be applied to the local 48 * translation of the Spatial 49 * @param applyPhysicsLocal 50 */ 51 public void setApplyPhysicsLocal(boolean applyPhysicsLocal) { 52 applyLocal = applyPhysicsLocal; 53 } 54 55 private Vector3f getSpatialTranslation() { 56 if (applyLocal) { 57 return spatial.getLocalTranslation(); 58 } 59 return spatial.getWorldTranslation(); 60 } 61 62 private Quaternion getSpatialRotation() { 63 if (applyLocal) { 64 return spatial.getLocalRotation(); 65 } 66 return spatial.getWorldRotation(); 67 } 68 69 public Control cloneForSpatial(Spatial spatial) { 70 GhostControl control = new GhostControl(collisionShape); 71 control.setCcdMotionThreshold(getCcdMotionThreshold()); 72 control.setCcdSweptSphereRadius(getCcdSweptSphereRadius()); 73 control.setCollideWithGroups(getCollideWithGroups()); 74 control.setCollisionGroup(getCollisionGroup()); 75 control.setPhysicsLocation(getPhysicsLocation()); 76 control.setPhysicsRotation(getPhysicsRotationMatrix()); 77 control.setApplyPhysicsLocal(isApplyPhysicsLocal()); 78 79 control.setSpatial(spatial); 80 return control; 81 } 82 83 public void setSpatial(Spatial spatial) { 84 if (getUserObject() == null || getUserObject() == this.spatial) { 85 setUserObject(spatial); 86 } 87 this.spatial = spatial; 88 if (spatial == null) { 89 if (getUserObject() == spatial) { 90 setUserObject(null); 91 } 92 return; 93 } 94 setPhysicsLocation(getSpatialTranslation()); 95 setPhysicsRotation(getSpatialRotation()); 96 } 97 98 public void setEnabled(boolean enabled) { 99 this.enabled = enabled; 100 if (space != null) { 101 if (enabled && !added) { 102 if (spatial != null) { 103 setPhysicsLocation(getSpatialTranslation()); 104 setPhysicsRotation(getSpatialRotation()); 105 } 106 space.addCollisionObject(this); 107 added = true; 108 } else if (!enabled && added) { 109 space.removeCollisionObject(this); 110 added = false; 111 } 112 } 113 } 114 115 public boolean isEnabled() { 116 return enabled; 117 } 118 119 public void update(float tpf) { 120 if (!enabled) { 121 return; 122 } 123 setPhysicsLocation(getSpatialTranslation()); 124 setPhysicsRotation(getSpatialRotation()); 125 } 126 127 public void render(RenderManager rm, ViewPort vp) { 128 if (enabled && space != null && space.getDebugManager() != null) { 129 if (debugShape == null) { 130 attachDebugShape(space.getDebugManager()); 131 } 132 debugShape.setLocalTranslation(spatial.getWorldTranslation()); 133 debugShape.setLocalRotation(spatial.getWorldRotation()); 134 debugShape.updateLogicalState(0); 135 debugShape.updateGeometricState(); 136 rm.renderScene(debugShape, vp); 137 } 138 } 139 140 public void setPhysicsSpace(PhysicsSpace space) { 141 if (space == null) { 142 if (this.space != null) { 143 this.space.removeCollisionObject(this); 144 added = false; 145 } 146 } else { 147 if (this.space == space) { 148 return; 149 } 150 space.addCollisionObject(this); 151 added = true; 152 } 153 this.space = space; 154 } 155 156 public PhysicsSpace getPhysicsSpace() { 157 return space; 158 } 159 160 @Override 161 public void write(JmeExporter ex) throws IOException { 162 super.write(ex); 163 OutputCapsule oc = ex.getCapsule(this); 164 oc.write(enabled, "enabled", true); 165 oc.write(applyLocal, "applyLocalPhysics", false); 166 oc.write(spatial, "spatial", null); 167 } 168 169 @Override 170 public void read(JmeImporter im) throws IOException { 171 super.read(im); 172 InputCapsule ic = im.getCapsule(this); 173 enabled = ic.readBoolean("enabled", true); 174 spatial = (Spatial) ic.readSavable("spatial", null); 175 applyLocal = ic.readBoolean("applyLocalPhysics", false); 176 setUserObject(spatial); 177 } 178 } 179