1/* 2 * Copyright (c) 2009-2012 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 */ 32package com.jme3.bullet.collision; 33 34import com.jme3.asset.AssetManager; 35import com.jme3.bullet.collision.shapes.CollisionShape; 36import com.jme3.bullet.util.DebugShapeFactory; 37import com.jme3.export.*; 38import com.jme3.material.Material; 39import com.jme3.math.ColorRGBA; 40import com.jme3.math.Vector3f; 41import com.jme3.scene.Geometry; 42import com.jme3.scene.Node; 43import com.jme3.scene.Spatial; 44import com.jme3.scene.debug.Arrow; 45import java.io.IOException; 46import java.util.Iterator; 47import java.util.List; 48 49/** 50 * Base class for collision objects (PhysicsRigidBody, PhysicsGhostObject) 51 * @author normenhansen 52 */ 53public abstract class PhysicsCollisionObject implements Savable { 54 55 protected Spatial debugShape; 56 protected Arrow debugArrow; 57 protected Geometry debugArrowGeom; 58 protected Material debugMaterialBlue; 59 protected Material debugMaterialRed; 60 protected Material debugMaterialGreen; 61 protected Material debugMaterialYellow; 62 protected CollisionShape collisionShape; 63 public static final int COLLISION_GROUP_NONE = 0x00000000; 64 public static final int COLLISION_GROUP_01 = 0x00000001; 65 public static final int COLLISION_GROUP_02 = 0x00000002; 66 public static final int COLLISION_GROUP_03 = 0x00000004; 67 public static final int COLLISION_GROUP_04 = 0x00000008; 68 public static final int COLLISION_GROUP_05 = 0x00000010; 69 public static final int COLLISION_GROUP_06 = 0x00000020; 70 public static final int COLLISION_GROUP_07 = 0x00000040; 71 public static final int COLLISION_GROUP_08 = 0x00000080; 72 public static final int COLLISION_GROUP_09 = 0x00000100; 73 public static final int COLLISION_GROUP_10 = 0x00000200; 74 public static final int COLLISION_GROUP_11 = 0x00000400; 75 public static final int COLLISION_GROUP_12 = 0x00000800; 76 public static final int COLLISION_GROUP_13 = 0x00001000; 77 public static final int COLLISION_GROUP_14 = 0x00002000; 78 public static final int COLLISION_GROUP_15 = 0x00004000; 79 public static final int COLLISION_GROUP_16 = 0x00008000; 80 protected int collisionGroup = 0x00000001; 81 protected int collisionGroupsMask = 0x00000001; 82 private Object userObject; 83 84 /** 85 * Sets a CollisionShape to this physics object, note that the object should 86 * not be in the physics space when adding a new collision shape as it is rebuilt 87 * on the physics side. 88 * @param collisionShape the CollisionShape to set 89 */ 90 public void setCollisionShape(CollisionShape collisionShape) { 91 this.collisionShape = collisionShape; 92 updateDebugShape(); 93 } 94 95 /** 96 * @return the CollisionShape of this PhysicsNode, to be able to reuse it with 97 * other physics nodes (increases performance) 98 */ 99 public CollisionShape getCollisionShape() { 100 return collisionShape; 101 } 102 103 /** 104 * Returns the collision group for this collision shape 105 * @return 106 */ 107 public int getCollisionGroup() { 108 return collisionGroup; 109 } 110 111 /** 112 * Sets the collision group number for this physics object. <br> 113 * The groups are integer bit masks and some pre-made variables are available in CollisionObject. 114 * All physics objects are by default in COLLISION_GROUP_01.<br> 115 * Two object will collide when <b>one</b> of the partys has the 116 * collisionGroup of the other in its collideWithGroups set. 117 * @param collisionGroup the collisionGroup to set 118 */ 119 public void setCollisionGroup(int collisionGroup) { 120 this.collisionGroup = collisionGroup; 121 } 122 123 /** 124 * Add a group that this object will collide with.<br> 125 * Two object will collide when <b>one</b> of the partys has the 126 * collisionGroup of the other in its collideWithGroups set.<br> 127 * @param collisionGroup 128 */ 129 public void addCollideWithGroup(int collisionGroup) { 130 this.collisionGroupsMask = this.collisionGroupsMask | collisionGroup; 131 } 132 133 /** 134 * Remove a group from the list this object collides with. 135 * @param collisionGroup 136 */ 137 public void removeCollideWithGroup(int collisionGroup) { 138 this.collisionGroupsMask = this.collisionGroupsMask & ~collisionGroup; 139 } 140 141 /** 142 * Directly set the bitmask for collision groups that this object collides with. 143 * @param collisionGroups 144 */ 145 public void setCollideWithGroups(int collisionGroups) { 146 this.collisionGroupsMask = collisionGroups; 147 } 148 149 /** 150 * Gets the bitmask of collision groups that this object collides with. 151 * @return 152 */ 153 public int getCollideWithGroups() { 154 return collisionGroupsMask; 155 } 156 157 /** 158 * Creates a visual debug shape of the current collision shape of this physics object<br/> 159 * <b>Does not work with detached physics, please switch to PARALLEL or SEQUENTIAL for debugging</b> 160 * @param manager AssetManager to load the default wireframe material for the debug shape 161 */ 162 protected Spatial attachDebugShape(AssetManager manager) { 163 debugMaterialBlue = new Material(manager, "Common/MatDefs/Misc/Unshaded.j3md"); 164 debugMaterialBlue.getAdditionalRenderState().setWireframe(true); 165 debugMaterialBlue.setColor("Color", ColorRGBA.Blue); 166 debugMaterialGreen = new Material(manager, "Common/MatDefs/Misc/Unshaded.j3md"); 167 debugMaterialGreen.getAdditionalRenderState().setWireframe(true); 168 debugMaterialGreen.setColor("Color", ColorRGBA.Green); 169 debugMaterialRed = new Material(manager, "Common/MatDefs/Misc/Unshaded.j3md"); 170 debugMaterialRed.getAdditionalRenderState().setWireframe(true); 171 debugMaterialRed.setColor("Color", ColorRGBA.Red); 172 debugMaterialYellow = new Material(manager, "Common/MatDefs/Misc/Unshaded.j3md"); 173 debugMaterialYellow.getAdditionalRenderState().setWireframe(true); 174 debugMaterialYellow.setColor("Color", ColorRGBA.Yellow); 175 debugArrow = new Arrow(Vector3f.UNIT_XYZ); 176 debugArrowGeom = new Geometry("DebugArrow", debugArrow); 177 debugArrowGeom.setMaterial(debugMaterialGreen); 178 return attachDebugShape(); 179 } 180 181 /** 182 * creates a debug shape for this CollisionObject 183 * @param manager 184 * @return 185 */ 186 public Spatial createDebugShape(AssetManager manager){ 187 return attachDebugShape(manager); 188 } 189 190 protected Spatial attachDebugShape(Material material) { 191 debugMaterialBlue = material; 192 debugMaterialGreen = material; 193 debugMaterialRed = material; 194 debugMaterialYellow = material; 195 debugArrow = new Arrow(Vector3f.UNIT_XYZ); 196 debugArrowGeom = new Geometry("DebugArrow", debugArrow); 197 debugArrowGeom.setMaterial(debugMaterialGreen); 198 return attachDebugShape(); 199 } 200 201 public Spatial debugShape() { 202 return debugShape; 203 } 204 205 /** 206 * Creates a visual debug shape of the current collision shape of this physics object<br/> 207 * <b>Does not work with detached physics, please switch to PARALLEL or SEQUENTIAL for debugging</b> 208 * @param material Material to use for the debug shape 209 */ 210 protected Spatial attachDebugShape() { 211 if (debugShape != null) { 212 detachDebugShape(); 213 } 214 Spatial spatial = getDebugShape(); 215 this.debugShape = spatial; 216 return debugShape; 217 } 218 219 protected void updateDebugShape() { 220 if (debugShape != null) { 221 detachDebugShape(); 222 attachDebugShape(); 223 } 224 } 225 226 protected Spatial getDebugShape() { 227 Spatial spatial = DebugShapeFactory.getDebugShape(collisionShape); 228 if (spatial == null) { 229 return new Node("nullnode"); 230 } 231 if (spatial instanceof Node) { 232 List<Spatial> children = ((Node) spatial).getChildren(); 233 for (Iterator<Spatial> it1 = children.iterator(); it1.hasNext();) { 234 Spatial spatial1 = it1.next(); 235 Geometry geom = ((Geometry) spatial1); 236 geom.setMaterial(debugMaterialBlue); 237 geom.setCullHint(Spatial.CullHint.Never); 238 } 239 } else { 240 Geometry geom = ((Geometry) spatial); 241 geom.setMaterial(debugMaterialBlue); 242 geom.setCullHint(Spatial.CullHint.Never); 243 } 244 spatial.setCullHint(Spatial.CullHint.Never); 245 return spatial; 246 } 247 248 /** 249 * Removes the debug shape 250 */ 251 public void detachDebugShape() { 252 debugShape = null; 253 } 254 255 /** 256 * @return the userObject 257 */ 258 public Object getUserObject() { 259 return userObject; 260 } 261 262 /** 263 * @param userObject the userObject to set 264 */ 265 public void setUserObject(Object userObject) { 266 this.userObject = userObject; 267 } 268 269 @Override 270 public void write(JmeExporter e) throws IOException { 271 OutputCapsule capsule = e.getCapsule(this); 272 capsule.write(collisionGroup, "collisionGroup", 0x00000001); 273 capsule.write(collisionGroupsMask, "collisionGroupsMask", 0x00000001); 274 capsule.write(debugShape, "debugShape", null); 275 capsule.write(collisionShape, "collisionShape", null); 276 } 277 278 @Override 279 public void read(JmeImporter e) throws IOException { 280 InputCapsule capsule = e.getCapsule(this); 281 collisionGroup = capsule.readInt("collisionGroup", 0x00000001); 282 collisionGroupsMask = capsule.readInt("collisionGroupsMask", 0x00000001); 283 debugShape = (Spatial) capsule.readSavable("debugShape", null); 284 CollisionShape shape = (CollisionShape) capsule.readSavable("collisionShape", null); 285 collisionShape = shape; 286 } 287} 288