Home | History | Annotate | Download | only in infos
      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.infos;
     33 
     34 import com.bulletphysics.linearmath.MotionState;
     35 import com.bulletphysics.linearmath.Transform;
     36 import com.jme3.bullet.objects.PhysicsVehicle;
     37 import com.jme3.bullet.util.Converter;
     38 import com.jme3.math.Matrix3f;
     39 import com.jme3.math.Quaternion;
     40 import com.jme3.math.Vector3f;
     41 import com.jme3.scene.Spatial;
     42 
     43 /**
     44  * stores transform info of a PhysicsNode in a threadsafe manner to
     45  * allow multithreaded access from the jme scenegraph and the bullet physicsspace
     46  * @author normenhansen
     47  */
     48 public class RigidBodyMotionState extends MotionState {
     49     //stores the bullet transform
     50 
     51     private Transform motionStateTrans = new Transform(Converter.convert(new Matrix3f()));
     52     private Vector3f worldLocation = new Vector3f();
     53     private Matrix3f worldRotation = new Matrix3f();
     54     private Quaternion worldRotationQuat = new Quaternion();
     55     private Vector3f localLocation = new Vector3f();
     56     private Quaternion localRotationQuat = new Quaternion();
     57     //keep track of transform changes
     58     private boolean physicsLocationDirty = false;
     59     private boolean jmeLocationDirty = false;
     60     //temp variable for conversion
     61     private Quaternion tmp_inverseWorldRotation = new Quaternion();
     62     private PhysicsVehicle vehicle;
     63     private boolean applyPhysicsLocal = false;
     64 //    protected LinkedList<PhysicsMotionStateListener> listeners = new LinkedList<PhysicsMotionStateListener>();
     65 
     66     public RigidBodyMotionState() {
     67     }
     68 
     69     /**
     70      * called from bullet when creating the rigidbody
     71      * @param t
     72      * @return
     73      */
     74     public synchronized Transform getWorldTransform(Transform t) {
     75         t.set(motionStateTrans);
     76         return t;
     77     }
     78 
     79     /**
     80      * called from bullet when the transform of the rigidbody changes
     81      * @param worldTrans
     82      */
     83     public synchronized void setWorldTransform(Transform worldTrans) {
     84         if (jmeLocationDirty) {
     85             return;
     86         }
     87         motionStateTrans.set(worldTrans);
     88         Converter.convert(worldTrans.origin, worldLocation);
     89         Converter.convert(worldTrans.basis, worldRotation);
     90         worldRotationQuat.fromRotationMatrix(worldRotation);
     91 //        for (Iterator<PhysicsMotionStateListener> it = listeners.iterator(); it.hasNext();) {
     92 //            PhysicsMotionStateListener physicsMotionStateListener = it.next();
     93 //            physicsMotionStateListener.stateChanged(worldLocation, worldRotation);
     94 //        }
     95         physicsLocationDirty = true;
     96         if (vehicle != null) {
     97             vehicle.updateWheels();
     98         }
     99     }
    100 
    101     /**
    102      * applies the current transform to the given jme Node if the location has been updated on the physics side
    103      * @param spatial
    104      */
    105     public synchronized boolean applyTransform(Spatial spatial) {
    106         if (!physicsLocationDirty) {
    107             return false;
    108         }
    109         if (!applyPhysicsLocal && spatial.getParent() != null) {
    110             localLocation.set(worldLocation).subtractLocal(spatial.getParent().getWorldTranslation());
    111             localLocation.divideLocal(spatial.getParent().getWorldScale());
    112             tmp_inverseWorldRotation.set(spatial.getParent().getWorldRotation()).inverseLocal().multLocal(localLocation);
    113 
    114             localRotationQuat.set(worldRotationQuat);
    115             tmp_inverseWorldRotation.set(spatial.getParent().getWorldRotation()).inverseLocal().mult(localRotationQuat, localRotationQuat);
    116 
    117             spatial.setLocalTranslation(localLocation);
    118             spatial.setLocalRotation(localRotationQuat);
    119         } else {
    120             spatial.setLocalTranslation(worldLocation);
    121             spatial.setLocalRotation(worldRotationQuat);
    122         }
    123         physicsLocationDirty = false;
    124         return true;
    125     }
    126 
    127     /**
    128      * @return the worldLocation
    129      */
    130     public Vector3f getWorldLocation() {
    131         return worldLocation;
    132     }
    133 
    134     /**
    135      * @return the worldRotation
    136      */
    137     public Matrix3f getWorldRotation() {
    138         return worldRotation;
    139     }
    140 
    141     /**
    142      * @return the worldRotationQuat
    143      */
    144     public Quaternion getWorldRotationQuat() {
    145         return worldRotationQuat;
    146     }
    147 
    148     /**
    149      * @param vehicle the vehicle to set
    150      */
    151     public void setVehicle(PhysicsVehicle vehicle) {
    152         this.vehicle = vehicle;
    153     }
    154 
    155     public boolean isApplyPhysicsLocal() {
    156         return applyPhysicsLocal;
    157     }
    158 
    159     public void setApplyPhysicsLocal(boolean applyPhysicsLocal) {
    160         this.applyPhysicsLocal = applyPhysicsLocal;
    161     }
    162 //    public void addMotionStateListener(PhysicsMotionStateListener listener){
    163 //        listeners.add(listener);
    164 //    }
    165 //
    166 //    public void removeMotionStateListener(PhysicsMotionStateListener listener){
    167 //        listeners.remove(listener);
    168 //    }
    169 //    public synchronized boolean applyTransform(com.jme3.math.Transform trans) {
    170 //        if (!physicsLocationDirty) {
    171 //            return false;
    172 //        }
    173 //        trans.setTranslation(worldLocation);
    174 //        trans.setRotation(worldRotationQuat);
    175 //        physicsLocationDirty = false;
    176 //        return true;
    177 //    }
    178 //
    179 //    /**
    180 //     * called from jme when the location of the jme Node changes
    181 //     * @param location
    182 //     * @param rotation
    183 //     */
    184 //    public synchronized void setWorldTransform(Vector3f location, Quaternion rotation) {
    185 //        worldLocation.set(location);
    186 //        worldRotationQuat.set(rotation);
    187 //        worldRotation.set(rotation.toRotationMatrix());
    188 //        Converter.convert(worldLocation, motionStateTrans.origin);
    189 //        Converter.convert(worldRotation, motionStateTrans.basis);
    190 //        jmeLocationDirty = true;
    191 //    }
    192 //
    193 //    /**
    194 //     * applies the current transform to the given RigidBody if the value has been changed on the jme side
    195 //     * @param rBody
    196 //     */
    197 //    public synchronized void applyTransform(RigidBody rBody) {
    198 //        if (!jmeLocationDirty) {
    199 //            return;
    200 //        }
    201 //        assert (rBody != null);
    202 //        rBody.setWorldTransform(motionStateTrans);
    203 //        rBody.activate();
    204 //        jmeLocationDirty = false;
    205 //    }
    206 }
    207