Home | History | Annotate | Download | only in objects
      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.bulletphysics.collision.dispatch.CollisionFlags;
     35 import com.bulletphysics.collision.dispatch.PairCachingGhostObject;
     36 import com.bulletphysics.linearmath.Transform;
     37 import com.jme3.bullet.collision.PhysicsCollisionObject;
     38 import com.jme3.bullet.collision.shapes.CollisionShape;
     39 import com.jme3.bullet.util.Converter;
     40 import com.jme3.export.InputCapsule;
     41 import com.jme3.export.JmeExporter;
     42 import com.jme3.export.JmeImporter;
     43 import com.jme3.export.OutputCapsule;
     44 import com.jme3.math.Matrix3f;
     45 import com.jme3.math.Quaternion;
     46 import com.jme3.math.Vector3f;
     47 import com.jme3.scene.Spatial;
     48 import java.io.IOException;
     49 import java.util.LinkedList;
     50 import java.util.List;
     51 
     52 /**
     53  * <i>From Bullet manual:</i><br>
     54  * GhostObject can keep track of all objects that are overlapping.
     55  * By default, this overlap is based on the AABB.
     56  * This is useful for creating a character controller,
     57  * collision sensors/triggers, explosions etc.<br>
     58  * @author normenhansen
     59  */
     60 public class PhysicsGhostObject extends PhysicsCollisionObject {
     61 
     62     protected PairCachingGhostObject gObject;
     63     protected boolean locationDirty = false;
     64     //TEMP VARIABLES
     65     protected final Quaternion tmp_inverseWorldRotation = new Quaternion();
     66     protected Transform tempTrans = new Transform(Converter.convert(new Matrix3f()));
     67     private com.jme3.math.Transform physicsLocation = new com.jme3.math.Transform();
     68     protected javax.vecmath.Quat4f tempRot = new javax.vecmath.Quat4f();
     69     private List<PhysicsCollisionObject> overlappingObjects = new LinkedList<PhysicsCollisionObject>();
     70 
     71     public PhysicsGhostObject() {
     72     }
     73 
     74     public PhysicsGhostObject(CollisionShape shape) {
     75         collisionShape = shape;
     76         buildObject();
     77     }
     78 
     79     public PhysicsGhostObject(Spatial child, CollisionShape shape) {
     80         collisionShape = shape;
     81         buildObject();
     82     }
     83 
     84     protected void buildObject() {
     85         if (gObject == null) {
     86             gObject = new PairCachingGhostObject();
     87             gObject.setCollisionFlags(gObject.getCollisionFlags() | CollisionFlags.NO_CONTACT_RESPONSE);
     88         }
     89         gObject.setCollisionShape(collisionShape.getCShape());
     90         gObject.setUserPointer(this);
     91     }
     92 
     93     @Override
     94     public void setCollisionShape(CollisionShape collisionShape) {
     95         super.setCollisionShape(collisionShape);
     96         if (gObject == null) {
     97             buildObject();
     98         }else{
     99             gObject.setCollisionShape(collisionShape.getCShape());
    100         }
    101     }
    102 
    103     /**
    104      * Sets the physics object location
    105      * @param location the location of the actual physics object
    106      */
    107     public void setPhysicsLocation(Vector3f location) {
    108         gObject.getWorldTransform(tempTrans);
    109         Converter.convert(location, tempTrans.origin);
    110         gObject.setWorldTransform(tempTrans);
    111     }
    112 
    113     /**
    114      * Sets the physics object rotation
    115      * @param rotation the rotation of the actual physics object
    116      */
    117     public void setPhysicsRotation(Matrix3f rotation) {
    118         gObject.getWorldTransform(tempTrans);
    119         Converter.convert(rotation, tempTrans.basis);
    120         gObject.setWorldTransform(tempTrans);
    121     }
    122 
    123     /**
    124      * Sets the physics object rotation
    125      * @param rotation the rotation of the actual physics object
    126      */
    127     public void setPhysicsRotation(Quaternion rotation) {
    128         gObject.getWorldTransform(tempTrans);
    129         Converter.convert(rotation, tempTrans.basis);
    130         gObject.setWorldTransform(tempTrans);
    131     }
    132 
    133     /**
    134      * @return the physicsLocation
    135      */
    136     public com.jme3.math.Transform getPhysicsTransform() {
    137         return physicsLocation;
    138     }
    139 
    140     /**
    141      * @return the physicsLocation
    142      */
    143     public Vector3f getPhysicsLocation(Vector3f trans) {
    144         if (trans == null) {
    145             trans = new Vector3f();
    146         }
    147         gObject.getWorldTransform(tempTrans);
    148         Converter.convert(tempTrans.origin, physicsLocation.getTranslation());
    149         return trans.set(physicsLocation.getTranslation());
    150     }
    151 
    152     /**
    153      * @return the physicsLocation
    154      */
    155     public Quaternion getPhysicsRotation(Quaternion rot) {
    156         if (rot == null) {
    157             rot = new Quaternion();
    158         }
    159         gObject.getWorldTransform(tempTrans);
    160         Converter.convert(tempTrans.getRotation(tempRot), physicsLocation.getRotation());
    161         return rot.set(physicsLocation.getRotation());
    162     }
    163 
    164     /**
    165      * @return the physicsLocation
    166      */
    167     public Matrix3f getPhysicsRotationMatrix(Matrix3f rot) {
    168         if (rot == null) {
    169             rot = new Matrix3f();
    170         }
    171         gObject.getWorldTransform(tempTrans);
    172         Converter.convert(tempTrans.getRotation(tempRot), physicsLocation.getRotation());
    173         return rot.set(physicsLocation.getRotation());
    174     }
    175 
    176     /**
    177      * @return the physicsLocation
    178      */
    179     public Vector3f getPhysicsLocation() {
    180         gObject.getWorldTransform(tempTrans);
    181         Converter.convert(tempTrans.origin, physicsLocation.getTranslation());
    182         return physicsLocation.getTranslation();
    183     }
    184 
    185     /**
    186      * @return the physicsLocation
    187      */
    188     public Quaternion getPhysicsRotation() {
    189         gObject.getWorldTransform(tempTrans);
    190         Converter.convert(tempTrans.getRotation(tempRot), physicsLocation.getRotation());
    191         return physicsLocation.getRotation();
    192     }
    193 
    194     public Matrix3f getPhysicsRotationMatrix() {
    195         gObject.getWorldTransform(tempTrans);
    196         Converter.convert(tempTrans.getRotation(tempRot), physicsLocation.getRotation());
    197         return physicsLocation.getRotation().toRotationMatrix();
    198     }
    199 
    200     /**
    201      * used internally
    202      */
    203     public PairCachingGhostObject getObjectId() {
    204         return gObject;
    205     }
    206 
    207     /**
    208      * destroys this PhysicsGhostNode and removes it from memory
    209      */
    210     public void destroy() {
    211     }
    212 
    213     /**
    214      * Another Object is overlapping with this GhostNode,
    215      * if and if only there CollisionShapes overlaps.
    216      * They could be both regular PhysicsRigidBodys or PhysicsGhostObjects.
    217      * @return All CollisionObjects overlapping with this GhostNode.
    218      */
    219     public List<PhysicsCollisionObject> getOverlappingObjects() {
    220         overlappingObjects.clear();
    221         for (com.bulletphysics.collision.dispatch.CollisionObject collObj : gObject.getOverlappingPairs()) {
    222             overlappingObjects.add((PhysicsCollisionObject) collObj.getUserPointer());
    223         }
    224         return overlappingObjects;
    225     }
    226 
    227     /**
    228      *
    229      * @return With how many other CollisionObjects this GhostNode is currently overlapping.
    230      */
    231     public int getOverlappingCount() {
    232         return gObject.getNumOverlappingObjects();
    233     }
    234 
    235     /**
    236      *
    237      * @param index The index of the overlapping Node to retrieve.
    238      * @return The Overlapping CollisionObject at the given index.
    239      */
    240     public PhysicsCollisionObject getOverlapping(int index) {
    241         return overlappingObjects.get(index);
    242     }
    243 
    244     public void setCcdSweptSphereRadius(float radius) {
    245         gObject.setCcdSweptSphereRadius(radius);
    246     }
    247 
    248     public void setCcdMotionThreshold(float threshold) {
    249         gObject.setCcdMotionThreshold(threshold);
    250     }
    251 
    252     public float getCcdSweptSphereRadius() {
    253         return gObject.getCcdSweptSphereRadius();
    254     }
    255 
    256     public float getCcdMotionThreshold() {
    257         return gObject.getCcdMotionThreshold();
    258     }
    259 
    260     public float getCcdSquareMotionThreshold() {
    261         return gObject.getCcdSquareMotionThreshold();
    262     }
    263 
    264     @Override
    265     public void write(JmeExporter e) throws IOException {
    266         super.write(e);
    267         OutputCapsule capsule = e.getCapsule(this);
    268         capsule.write(getPhysicsLocation(new Vector3f()), "physicsLocation", new Vector3f());
    269         capsule.write(getPhysicsRotationMatrix(new Matrix3f()), "physicsRotation", new Matrix3f());
    270         capsule.write(getCcdMotionThreshold(), "ccdMotionThreshold", 0);
    271         capsule.write(getCcdSweptSphereRadius(), "ccdSweptSphereRadius", 0);
    272     }
    273 
    274     @Override
    275     public void read(JmeImporter e) throws IOException {
    276         super.read(e);
    277         InputCapsule capsule = e.getCapsule(this);
    278         buildObject();
    279         setPhysicsLocation((Vector3f) capsule.readSavable("physicsLocation", new Vector3f()));
    280         setPhysicsRotation(((Matrix3f) capsule.readSavable("physicsRotation", new Matrix3f())));
    281         setCcdMotionThreshold(capsule.readFloat("ccdMotionThreshold", 0));
    282         setCcdSweptSphereRadius(capsule.readFloat("ccdSweptSphereRadius", 0));
    283     }
    284 }
    285