1 /* 2 * Copyright (c) 2009-2010 jMonkeyEngine 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * * Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 package com.jme3.bullet.objects; 33 34 import com.jme3.bullet.collision.PhysicsCollisionObject; 35 import com.jme3.bullet.collision.shapes.CollisionShape; 36 import com.jme3.export.InputCapsule; 37 import com.jme3.export.JmeExporter; 38 import com.jme3.export.JmeImporter; 39 import com.jme3.export.OutputCapsule; 40 import com.jme3.math.Matrix3f; 41 import com.jme3.math.Quaternion; 42 import com.jme3.math.Vector3f; 43 import com.jme3.scene.Spatial; 44 import java.io.IOException; 45 import java.util.LinkedList; 46 import java.util.List; 47 import java.util.logging.Level; 48 import java.util.logging.Logger; 49 50 /** 51 * <i>From Bullet manual:</i><br> 52 * GhostObject can keep track of all objects that are overlapping. 53 * By default, this overlap is based on the AABB. 54 * This is useful for creating a character controller, 55 * collision sensors/triggers, explosions etc.<br> 56 * @author normenhansen 57 */ 58 public class PhysicsGhostObject extends PhysicsCollisionObject { 59 60 protected boolean locationDirty = false; 61 protected final Quaternion tmp_inverseWorldRotation = new Quaternion(); 62 private List<PhysicsCollisionObject> overlappingObjects = new LinkedList<PhysicsCollisionObject>(); 63 PhysicsGhostObject()64 public PhysicsGhostObject() { 65 } 66 PhysicsGhostObject(CollisionShape shape)67 public PhysicsGhostObject(CollisionShape shape) { 68 collisionShape = shape; 69 buildObject(); 70 } 71 PhysicsGhostObject(Spatial child, CollisionShape shape)72 public PhysicsGhostObject(Spatial child, CollisionShape shape) { 73 collisionShape = shape; 74 buildObject(); 75 } 76 buildObject()77 protected void buildObject() { 78 if (objectId == 0) { 79 // gObject = new PairCachingGhostObject(); 80 objectId = createGhostObject(); 81 Logger.getLogger(this.getClass().getName()).log(Level.INFO, "Created Ghost Object {0}", Long.toHexString(objectId)); 82 setGhostFlags(objectId); 83 initUserPointer(); 84 } 85 // if (gObject == null) { 86 // gObject = new PairCachingGhostObject(); 87 // gObject.setCollisionFlags(gObject.getCollisionFlags() | CollisionFlags.NO_CONTACT_RESPONSE); 88 // } 89 attachCollisionShape(objectId, collisionShape.getObjectId()); 90 } 91 createGhostObject()92 private native long createGhostObject(); 93 setGhostFlags(long objectId)94 private native void setGhostFlags(long objectId); 95 96 @Override setCollisionShape(CollisionShape collisionShape)97 public void setCollisionShape(CollisionShape collisionShape) { 98 super.setCollisionShape(collisionShape); 99 if (objectId == 0) { 100 buildObject(); 101 } else { 102 attachCollisionShape(objectId, collisionShape.getObjectId()); 103 } 104 } 105 106 /** 107 * Sets the physics object location 108 * @param location the location of the actual physics object 109 */ setPhysicsLocation(Vector3f location)110 public void setPhysicsLocation(Vector3f location) { 111 setPhysicsLocation(objectId, location); 112 } 113 setPhysicsLocation(long objectId, Vector3f location)114 private native void setPhysicsLocation(long objectId, Vector3f location); 115 116 /** 117 * Sets the physics object rotation 118 * @param rotation the rotation of the actual physics object 119 */ setPhysicsRotation(Matrix3f rotation)120 public void setPhysicsRotation(Matrix3f rotation) { 121 setPhysicsRotation(objectId, rotation); 122 } 123 setPhysicsRotation(long objectId, Matrix3f rotation)124 private native void setPhysicsRotation(long objectId, Matrix3f rotation); 125 126 /** 127 * Sets the physics object rotation 128 * @param rotation the rotation of the actual physics object 129 */ setPhysicsRotation(Quaternion rotation)130 public void setPhysicsRotation(Quaternion rotation) { 131 setPhysicsRotation(objectId, rotation); 132 } 133 setPhysicsRotation(long objectId, Quaternion rotation)134 private native void setPhysicsRotation(long objectId, Quaternion rotation); 135 136 /** 137 * @return the physicsLocation 138 */ getPhysicsLocation(Vector3f trans)139 public Vector3f getPhysicsLocation(Vector3f trans) { 140 if (trans == null) { 141 trans = new Vector3f(); 142 } 143 getPhysicsLocation(objectId, trans); 144 return trans; 145 } 146 getPhysicsLocation(long objectId, Vector3f vector)147 private native void getPhysicsLocation(long objectId, Vector3f vector); 148 149 /** 150 * @return the physicsLocation 151 */ getPhysicsRotation(Quaternion rot)152 public Quaternion getPhysicsRotation(Quaternion rot) { 153 if (rot == null) { 154 rot = new Quaternion(); 155 } 156 getPhysicsRotation(objectId, rot); 157 return rot; 158 } 159 getPhysicsRotation(long objectId, Quaternion rot)160 private native void getPhysicsRotation(long objectId, Quaternion rot); 161 162 /** 163 * @return the physicsLocation 164 */ getPhysicsRotationMatrix(Matrix3f rot)165 public Matrix3f getPhysicsRotationMatrix(Matrix3f rot) { 166 if (rot == null) { 167 rot = new Matrix3f(); 168 } 169 getPhysicsRotationMatrix(objectId, rot); 170 return rot; 171 } 172 getPhysicsRotationMatrix(long objectId, Matrix3f rot)173 private native void getPhysicsRotationMatrix(long objectId, Matrix3f rot); 174 175 /** 176 * @return the physicsLocation 177 */ getPhysicsLocation()178 public Vector3f getPhysicsLocation() { 179 Vector3f vec = new Vector3f(); 180 getPhysicsLocation(objectId, vec); 181 return vec; 182 } 183 184 /** 185 * @return the physicsLocation 186 */ getPhysicsRotation()187 public Quaternion getPhysicsRotation() { 188 Quaternion quat = new Quaternion(); 189 getPhysicsRotation(objectId, quat); 190 return quat; 191 } 192 getPhysicsRotationMatrix()193 public Matrix3f getPhysicsRotationMatrix() { 194 Matrix3f mtx = new Matrix3f(); 195 getPhysicsRotationMatrix(objectId, mtx); 196 return mtx; 197 } 198 199 /** 200 * used internally 201 */ 202 // public PairCachingGhostObject getObjectId() { 203 // return gObject; 204 // } 205 /** 206 * destroys this PhysicsGhostNode and removes it from memory 207 */ destroy()208 public void destroy() { 209 } 210 211 /** 212 * Another Object is overlapping with this GhostNode, 213 * if and if only there CollisionShapes overlaps. 214 * They could be both regular PhysicsRigidBodys or PhysicsGhostObjects. 215 * @return All CollisionObjects overlapping with this GhostNode. 216 */ getOverlappingObjects()217 public List<PhysicsCollisionObject> getOverlappingObjects() { 218 overlappingObjects.clear(); 219 getOverlappingObjects(objectId); 220 // for (com.bulletphysics.collision.dispatch.CollisionObject collObj : gObject.getOverlappingPairs()) { 221 // overlappingObjects.add((PhysicsCollisionObject) collObj.getUserPointer()); 222 // } 223 return overlappingObjects; 224 } 225 getOverlappingObjects(long objectId)226 protected native void getOverlappingObjects(long objectId); 227 addOverlappingObject_native(PhysicsCollisionObject co)228 private void addOverlappingObject_native(PhysicsCollisionObject co) { 229 overlappingObjects.add(co); 230 } 231 232 /** 233 * 234 * @return With how many other CollisionObjects this GhostNode is currently overlapping. 235 */ getOverlappingCount()236 public int getOverlappingCount() { 237 return getOverlappingCount(objectId); 238 } 239 getOverlappingCount(long objectId)240 private native int getOverlappingCount(long objectId); 241 242 /** 243 * 244 * @param index The index of the overlapping Node to retrieve. 245 * @return The Overlapping CollisionObject at the given index. 246 */ getOverlapping(int index)247 public PhysicsCollisionObject getOverlapping(int index) { 248 return overlappingObjects.get(index); 249 } 250 setCcdSweptSphereRadius(float radius)251 public void setCcdSweptSphereRadius(float radius) { 252 setCcdSweptSphereRadius(objectId, radius); 253 } 254 setCcdSweptSphereRadius(long objectId, float radius)255 private native void setCcdSweptSphereRadius(long objectId, float radius); 256 setCcdMotionThreshold(float threshold)257 public void setCcdMotionThreshold(float threshold) { 258 setCcdMotionThreshold(objectId, threshold); 259 } 260 setCcdMotionThreshold(long objectId, float threshold)261 private native void setCcdMotionThreshold(long objectId, float threshold); 262 getCcdSweptSphereRadius()263 public float getCcdSweptSphereRadius() { 264 return getCcdSweptSphereRadius(objectId); 265 } 266 getCcdSweptSphereRadius(long objectId)267 private native float getCcdSweptSphereRadius(long objectId); 268 getCcdMotionThreshold()269 public float getCcdMotionThreshold() { 270 return getCcdMotionThreshold(objectId); 271 } 272 getCcdMotionThreshold(long objectId)273 private native float getCcdMotionThreshold(long objectId); 274 getCcdSquareMotionThreshold()275 public float getCcdSquareMotionThreshold() { 276 return getCcdSquareMotionThreshold(objectId); 277 } 278 getCcdSquareMotionThreshold(long objectId)279 private native float getCcdSquareMotionThreshold(long objectId); 280 281 @Override write(JmeExporter e)282 public void write(JmeExporter e) throws IOException { 283 super.write(e); 284 OutputCapsule capsule = e.getCapsule(this); 285 capsule.write(getPhysicsLocation(new Vector3f()), "physicsLocation", new Vector3f()); 286 capsule.write(getPhysicsRotationMatrix(new Matrix3f()), "physicsRotation", new Matrix3f()); 287 capsule.write(getCcdMotionThreshold(), "ccdMotionThreshold", 0); 288 capsule.write(getCcdSweptSphereRadius(), "ccdSweptSphereRadius", 0); 289 } 290 291 @Override read(JmeImporter e)292 public void read(JmeImporter e) throws IOException { 293 super.read(e); 294 InputCapsule capsule = e.getCapsule(this); 295 buildObject(); 296 setPhysicsLocation((Vector3f) capsule.readSavable("physicsLocation", new Vector3f())); 297 setPhysicsRotation(((Matrix3f) capsule.readSavable("physicsRotation", new Matrix3f()))); 298 setCcdMotionThreshold(capsule.readFloat("ccdMotionThreshold", 0)); 299 setCcdSweptSphereRadius(capsule.readFloat("ccdSweptSphereRadius", 0)); 300 } 301 } 302