Home | History | Annotate | Download | only in collision
      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  */
     32 package com.jme3.bullet.collision;
     33 
     34 import com.jme3.asset.AssetManager;
     35 import com.jme3.bullet.collision.shapes.CollisionShape;
     36 import com.jme3.bullet.util.DebugShapeFactory;
     37 import com.jme3.export.*;
     38 import com.jme3.material.Material;
     39 import com.jme3.math.ColorRGBA;
     40 import com.jme3.math.Vector3f;
     41 import com.jme3.scene.Geometry;
     42 import com.jme3.scene.Node;
     43 import com.jme3.scene.Spatial;
     44 import com.jme3.scene.debug.Arrow;
     45 import java.io.IOException;
     46 import java.util.Iterator;
     47 import java.util.List;
     48 
     49 /**
     50  * Base class for collision objects (PhysicsRigidBody, PhysicsGhostObject)
     51  * @author normenhansen
     52  */
     53 public 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