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.jme3.bullet.PhysicsSpace;
     35 import com.jme3.bullet.collision.PhysicsCollisionObject;
     36 import com.jme3.bullet.collision.shapes.CollisionShape;
     37 import com.jme3.bullet.collision.shapes.MeshCollisionShape;
     38 import com.jme3.bullet.joints.PhysicsJoint;
     39 import com.jme3.bullet.objects.infos.RigidBodyMotionState;
     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.Geometry;
     48 import com.jme3.scene.Node;
     49 import com.jme3.scene.Spatial;
     50 import com.jme3.scene.debug.Arrow;
     51 import java.io.IOException;
     52 import java.util.ArrayList;
     53 import java.util.Iterator;
     54 import java.util.List;
     55 import java.util.logging.Level;
     56 import java.util.logging.Logger;
     57 
     58 /**
     59  * <p>PhysicsRigidBody - Basic physics object</p>
     60  * @author normenhansen
     61  */
     62 public class PhysicsRigidBody extends PhysicsCollisionObject {
     63 
     64     protected RigidBodyMotionState motionState = new RigidBodyMotionState();
     65     protected float mass = 1.0f;
     66     protected boolean kinematic = false;
     67     protected ArrayList<PhysicsJoint> joints = new ArrayList<PhysicsJoint>();
     68 
     69     public PhysicsRigidBody() {
     70     }
     71 
     72     /**
     73      * Creates a new PhysicsRigidBody with the supplied collision shape
     74      * @param child
     75      * @param shape
     76      */
     77     public PhysicsRigidBody(CollisionShape shape) {
     78         collisionShape = shape;
     79         rebuildRigidBody();
     80     }
     81 
     82     public PhysicsRigidBody(CollisionShape shape, float mass) {
     83         collisionShape = shape;
     84         this.mass = mass;
     85         rebuildRigidBody();
     86     }
     87 
     88     /**
     89      * Builds/rebuilds the phyiscs body when parameters have changed
     90      */
     91     protected void rebuildRigidBody() {
     92         boolean removed = false;
     93         if (collisionShape instanceof MeshCollisionShape && mass != 0) {
     94             throw new IllegalStateException("Dynamic rigidbody can not have mesh collision shape!");
     95         }
     96         if (objectId != 0) {
     97             if (isInWorld(objectId)) {
     98                 PhysicsSpace.getPhysicsSpace().remove(this);
     99                 removed = true;
    100             }
    101             Logger.getLogger(this.getClass().getName()).log(Level.INFO, "Clearing RigidBody {0}", Long.toHexString(objectId));
    102             finalizeNative(objectId);
    103         }
    104         preRebuild();
    105         objectId = createRigidBody(mass, motionState.getObjectId(), collisionShape.getObjectId());
    106         Logger.getLogger(this.getClass().getName()).log(Level.INFO, "Created RigidBody {0}", Long.toHexString(objectId));
    107         postRebuild();
    108         if (removed) {
    109             PhysicsSpace.getPhysicsSpace().add(this);
    110         }
    111     }
    112 
    113     protected void preRebuild() {
    114     }
    115 
    116     private native long createRigidBody(float mass, long motionStateId, long collisionShapeId);
    117 
    118     protected void postRebuild() {
    119         if (mass == 0.0f) {
    120             setStatic(objectId, true);
    121         } else {
    122             setStatic(objectId, false);
    123         }
    124         initUserPointer();
    125     }
    126 
    127     /**
    128      * @return the motionState
    129      */
    130     public RigidBodyMotionState getMotionState() {
    131         return motionState;
    132     }
    133 
    134     public boolean isInWorld() {
    135         return isInWorld(objectId);
    136     }
    137 
    138     private native boolean isInWorld(long objectId);
    139 
    140     /**
    141      * Sets the physics object location
    142      * @param location the location of the actual physics object
    143      */
    144     public void setPhysicsLocation(Vector3f location) {
    145         setPhysicsLocation(objectId, location);
    146     }
    147 
    148     private native void setPhysicsLocation(long objectId, Vector3f location);
    149 
    150     /**
    151      * Sets the physics object rotation
    152      * @param rotation the rotation of the actual physics object
    153      */
    154     public void setPhysicsRotation(Matrix3f rotation) {
    155         setPhysicsRotation(objectId, rotation);
    156     }
    157 
    158     private native void setPhysicsRotation(long objectId, Matrix3f rotation);
    159 
    160     /**
    161      * Sets the physics object rotation
    162      * @param rotation the rotation of the actual physics object
    163      */
    164     public void setPhysicsRotation(Quaternion rotation) {
    165         setPhysicsRotation(objectId, rotation);
    166     }
    167 
    168     private native void setPhysicsRotation(long objectId, Quaternion rotation);
    169 
    170     /**
    171      * @return the physicsLocation
    172      */
    173     public Vector3f getPhysicsLocation(Vector3f trans) {
    174         if (trans == null) {
    175             trans = new Vector3f();
    176         }
    177         getPhysicsLocation(objectId, trans);
    178         return trans;
    179     }
    180 
    181     private native void getPhysicsLocation(long objectId, Vector3f vector);
    182 
    183     /**
    184      * @return the physicsLocation
    185      */
    186     public Quaternion getPhysicsRotation(Quaternion rot) {
    187         if (rot == null) {
    188             rot = new Quaternion();
    189         }
    190         getPhysicsRotation(objectId, rot);
    191         return rot;
    192     }
    193 
    194     private native void getPhysicsRotation(long objectId, Quaternion rot);
    195 
    196     /**
    197      * @return the physicsLocation
    198      */
    199     public Matrix3f getPhysicsRotationMatrix(Matrix3f rot) {
    200         if (rot == null) {
    201             rot = new Matrix3f();
    202         }
    203         getPhysicsRotationMatrix(objectId, rot);
    204         return rot;
    205     }
    206 
    207     private native void getPhysicsRotationMatrix(long objectId, Matrix3f rot);
    208 
    209     /**
    210      * @return the physicsLocation
    211      */
    212     public Vector3f getPhysicsLocation() {
    213         Vector3f vec = new Vector3f();
    214         getPhysicsLocation(objectId, vec);
    215         return vec;
    216     }
    217 
    218     /**
    219      * @return the physicsLocation
    220      */
    221     public Quaternion getPhysicsRotation() {
    222         Quaternion quat = new Quaternion();
    223         getPhysicsRotation(objectId, quat);
    224         return quat;
    225     }
    226 
    227     public Matrix3f getPhysicsRotationMatrix() {
    228         Matrix3f mtx = new Matrix3f();
    229         getPhysicsRotationMatrix(objectId, mtx);
    230         return mtx;
    231     }
    232 
    233 //    /**
    234 //     * Gets the physics object location
    235 //     * @param location the location of the actual physics object is stored in this Vector3f
    236 //     */
    237 //    public Vector3f getInterpolatedPhysicsLocation(Vector3f location) {
    238 //        if (location == null) {
    239 //            location = new Vector3f();
    240 //        }
    241 //        rBody.getInterpolationWorldTransform(tempTrans);
    242 //        return Converter.convert(tempTrans.origin, location);
    243 //    }
    244 //
    245 //    /**
    246 //     * Gets the physics object rotation
    247 //     * @param rotation the rotation of the actual physics object is stored in this Matrix3f
    248 //     */
    249 //    public Matrix3f getInterpolatedPhysicsRotation(Matrix3f rotation) {
    250 //        if (rotation == null) {
    251 //            rotation = new Matrix3f();
    252 //        }
    253 //        rBody.getInterpolationWorldTransform(tempTrans);
    254 //        return Converter.convert(tempTrans.basis, rotation);
    255 //    }
    256     /**
    257      * Sets the node to kinematic mode. in this mode the node is not affected by physics
    258      * but affects other physics objects. Iits kinetic force is calculated by the amount
    259      * of movement it is exposed to and its weight.
    260      * @param kinematic
    261      */
    262     public void setKinematic(boolean kinematic) {
    263         this.kinematic = kinematic;
    264         setKinematic(objectId, kinematic);
    265     }
    266 
    267     private native void setKinematic(long objectId, boolean kinematic);
    268 
    269     public boolean isKinematic() {
    270         return kinematic;
    271     }
    272 
    273     public void setCcdSweptSphereRadius(float radius) {
    274         setCcdSweptSphereRadius(objectId, radius);
    275     }
    276 
    277     private native void setCcdSweptSphereRadius(long objectId, float radius);
    278 
    279     /**
    280      * Sets the amount of motion that has to happen in one physics tick to trigger the continuous motion detection<br/>
    281      * This avoids the problem of fast objects moving through other objects, set to zero to disable (default)
    282      * @param threshold
    283      */
    284     public void setCcdMotionThreshold(float threshold) {
    285         setCcdMotionThreshold(objectId, threshold);
    286     }
    287 
    288     private native void setCcdMotionThreshold(long objectId, float threshold);
    289 
    290     public float getCcdSweptSphereRadius() {
    291         return getCcdSweptSphereRadius(objectId);
    292     }
    293 
    294     private native float getCcdSweptSphereRadius(long objectId);
    295 
    296     public float getCcdMotionThreshold() {
    297         return getCcdMotionThreshold(objectId);
    298     }
    299 
    300     private native float getCcdMotionThreshold(long objectId);
    301 
    302     public float getCcdSquareMotionThreshold() {
    303         return getCcdSquareMotionThreshold(objectId);
    304     }
    305 
    306     private native float getCcdSquareMotionThreshold(long objectId);
    307 
    308     public float getMass() {
    309         return mass;
    310     }
    311 
    312     /**
    313      * Sets the mass of this PhysicsRigidBody, objects with mass=0 are static.
    314      * @param mass
    315      */
    316     public void setMass(float mass) {
    317         this.mass = mass;
    318         if (collisionShape instanceof MeshCollisionShape && mass != 0) {
    319             throw new IllegalStateException("Dynamic rigidbody can not have mesh collision shape!");
    320         }
    321         if (objectId != 0) {
    322             if (collisionShape != null) {
    323                 updateMassProps(objectId, collisionShape.getObjectId(), mass);
    324             }
    325             if (mass == 0.0f) {
    326                 setStatic(objectId, true);
    327             } else {
    328                 setStatic(objectId, false);
    329             }
    330         }
    331     }
    332 
    333     private native void setStatic(long objectId, boolean state);
    334 
    335     private native long updateMassProps(long objectId, long collisionShapeId, float mass);
    336 
    337     public Vector3f getGravity() {
    338         return getGravity(null);
    339     }
    340 
    341     public Vector3f getGravity(Vector3f gravity) {
    342         if (gravity == null) {
    343             gravity = new Vector3f();
    344         }
    345         getGravity(objectId, gravity);
    346         return gravity;
    347     }
    348 
    349     private native void getGravity(long objectId, Vector3f gravity);
    350 
    351     /**
    352      * Set the local gravity of this PhysicsRigidBody<br/>
    353      * Set this after adding the node to the PhysicsSpace,
    354      * the PhysicsSpace assigns its current gravity to the physics node when its added.
    355      * @param gravity the gravity vector to set
    356      */
    357     public void setGravity(Vector3f gravity) {
    358         setGravity(objectId, gravity);
    359     }
    360 
    361     private native void setGravity(long objectId, Vector3f gravity);
    362 
    363     public float getFriction() {
    364         return getFriction(objectId);
    365     }
    366 
    367     private native float getFriction(long objectId);
    368 
    369     /**
    370      * Sets the friction of this physics object
    371      * @param friction the friction of this physics object
    372      */
    373     public void setFriction(float friction) {
    374         setFriction(objectId, friction);
    375     }
    376 
    377     private native void setFriction(long objectId, float friction);
    378 
    379     public void setDamping(float linearDamping, float angularDamping) {
    380         setDamping(objectId, linearDamping, angularDamping);
    381     }
    382 
    383     private native void setDamping(long objectId, float linearDamping, float angularDamping);
    384 
    385 //    private native void setRestitution(long objectId, float factor);
    386 //
    387 //    public void setLinearDamping(float linearDamping) {
    388 //        constructionInfo.linearDamping = linearDamping;
    389 //        rBody.setDamping(linearDamping, constructionInfo.angularDamping);
    390 //    }
    391 //
    392 //    private native void setRestitution(long objectId, float factor);
    393 //
    394     public void setLinearDamping(float linearDamping) {
    395         setDamping(objectId, linearDamping, getAngularDamping());
    396     }
    397 
    398     public void setAngularDamping(float angularDamping) {
    399         setAngularDamping(objectId, angularDamping);
    400     }
    401     private native void setAngularDamping(long objectId, float factor);
    402 
    403     public float getLinearDamping() {
    404         return getLinearDamping(objectId);
    405     }
    406 
    407     private native float getLinearDamping(long objectId);
    408 
    409     public float getAngularDamping() {
    410         return getAngularDamping(objectId);
    411     }
    412 
    413     private native float getAngularDamping(long objectId);
    414 
    415     public float getRestitution() {
    416         return getRestitution(objectId);
    417     }
    418 
    419     private native float getRestitution(long objectId);
    420 
    421     /**
    422      * The "bouncyness" of the PhysicsRigidBody, best performance if restitution=0
    423      * @param restitution
    424      */
    425     public void setRestitution(float restitution) {
    426         setRestitution(objectId, restitution);
    427     }
    428 
    429     private native void setRestitution(long objectId, float factor);
    430 
    431     /**
    432      * Get the current angular velocity of this PhysicsRigidBody
    433      * @return the current linear velocity
    434      */
    435     public Vector3f getAngularVelocity() {
    436         Vector3f vec = new Vector3f();
    437         getAngularVelocity(objectId, vec);
    438         return vec;
    439     }
    440 
    441     private native void getAngularVelocity(long objectId, Vector3f vec);
    442 
    443     /**
    444      * Get the current angular velocity of this PhysicsRigidBody
    445      * @param vec the vector to store the velocity in
    446      */
    447     public void getAngularVelocity(Vector3f vec) {
    448         getAngularVelocity(objectId, vec);
    449     }
    450 
    451     /**
    452      * Sets the angular velocity of this PhysicsRigidBody
    453      * @param vec the angular velocity of this PhysicsRigidBody
    454      */
    455     public void setAngularVelocity(Vector3f vec) {
    456         setAngularVelocity(objectId, vec);
    457         activate();
    458     }
    459 
    460     private native void setAngularVelocity(long objectId, Vector3f vec);
    461 
    462     /**
    463      * Get the current linear velocity of this PhysicsRigidBody
    464      * @return the current linear velocity
    465      */
    466     public Vector3f getLinearVelocity() {
    467         Vector3f vec = new Vector3f();
    468         getLinearVelocity(objectId, vec);
    469         return vec;
    470     }
    471 
    472     private native void getLinearVelocity(long objectId, Vector3f vec);
    473 
    474     /**
    475      * Get the current linear velocity of this PhysicsRigidBody
    476      * @param vec the vector to store the velocity in
    477      */
    478     public void getLinearVelocity(Vector3f vec) {
    479         getLinearVelocity(objectId, vec);
    480     }
    481 
    482     /**
    483      * Sets the linear velocity of this PhysicsRigidBody
    484      * @param vec the linear velocity of this PhysicsRigidBody
    485      */
    486     public void setLinearVelocity(Vector3f vec) {
    487         setLinearVelocity(objectId, vec);
    488         activate();
    489     }
    490 
    491     private native void setLinearVelocity(long objectId, Vector3f vec);
    492 
    493     /**
    494      * Apply a force to the PhysicsRigidBody, only applies force if the next physics update call
    495      * updates the physics space.<br>
    496      * To apply an impulse, use applyImpulse, use applyContinuousForce to apply continuous force.
    497      * @param force the force
    498      * @param location the location of the force
    499      */
    500     public void applyForce(Vector3f force, Vector3f location) {
    501         applyForce(objectId, force, location);
    502         activate();
    503     }
    504 
    505     private native void applyForce(long objectId, Vector3f force, Vector3f location);
    506 
    507     /**
    508      * Apply a force to the PhysicsRigidBody, only applies force if the next physics update call
    509      * updates the physics space.<br>
    510      * To apply an impulse, use applyImpulse.
    511      *
    512      * @param force the force
    513      */
    514     public void applyCentralForce(Vector3f force) {
    515         applyCentralForce(objectId, force);
    516         activate();
    517     }
    518 
    519     private native void applyCentralForce(long objectId, Vector3f force);
    520 
    521     /**
    522      * Apply a force to the PhysicsRigidBody, only applies force if the next physics update call
    523      * updates the physics space.<br>
    524      * To apply an impulse, use applyImpulse.
    525      *
    526      * @param torque the torque
    527      */
    528     public void applyTorque(Vector3f torque) {
    529         applyTorque(objectId, torque);
    530         activate();
    531     }
    532 
    533     private native void applyTorque(long objectId, Vector3f vec);
    534 
    535     /**
    536      * Apply an impulse to the PhysicsRigidBody in the next physics update.
    537      * @param impulse applied impulse
    538      * @param rel_pos location relative to object
    539      */
    540     public void applyImpulse(Vector3f impulse, Vector3f rel_pos) {
    541         applyImpulse(objectId, impulse, rel_pos);
    542         activate();
    543     }
    544 
    545     private native void applyImpulse(long objectId, Vector3f impulse, Vector3f rel_pos);
    546 
    547     /**
    548      * Apply a torque impulse to the PhysicsRigidBody in the next physics update.
    549      * @param vec
    550      */
    551     public void applyTorqueImpulse(Vector3f vec) {
    552         applyTorqueImpulse(objectId, vec);
    553         activate();
    554     }
    555 
    556     private native void applyTorqueImpulse(long objectId, Vector3f vec);
    557 
    558     /**
    559      * Clear all forces from the PhysicsRigidBody
    560      *
    561      */
    562     public void clearForces() {
    563         clearForces(objectId);
    564     }
    565 
    566     private native void clearForces(long objectId);
    567 
    568     public void setCollisionShape(CollisionShape collisionShape) {
    569         super.setCollisionShape(collisionShape);
    570         if (collisionShape instanceof MeshCollisionShape && mass != 0) {
    571             throw new IllegalStateException("Dynamic rigidbody can not have mesh collision shape!");
    572         }
    573         if (objectId == 0) {
    574             rebuildRigidBody();
    575         } else {
    576             setCollisionShape(objectId, collisionShape.getObjectId());
    577             updateMassProps(objectId, collisionShape.getObjectId(), mass);
    578         }
    579     }
    580 
    581     private native void setCollisionShape(long objectId, long collisionShapeId);
    582 
    583     /**
    584      * reactivates this PhysicsRigidBody when it has been deactivated because it was not moving
    585      */
    586     public void activate() {
    587         activate(objectId);
    588     }
    589 
    590     private native void activate(long objectId);
    591 
    592     public boolean isActive() {
    593         return isActive(objectId);
    594     }
    595 
    596     private native boolean isActive(long objectId);
    597 
    598     /**
    599      * sets the sleeping thresholds, these define when the object gets deactivated
    600      * to save ressources. Low values keep the object active when it barely moves
    601      * @param linear the linear sleeping threshold
    602      * @param angular the angular sleeping threshold
    603      */
    604     public void setSleepingThresholds(float linear, float angular) {
    605         setSleepingThresholds(objectId, linear, angular);
    606     }
    607 
    608     private native void setSleepingThresholds(long objectId, float linear, float angular);
    609 
    610     public void setLinearSleepingThreshold(float linearSleepingThreshold) {
    611         setLinearSleepingThreshold(objectId, linearSleepingThreshold);
    612     }
    613 
    614     private native void setLinearSleepingThreshold(long objectId, float linearSleepingThreshold);
    615 
    616     public void setAngularSleepingThreshold(float angularSleepingThreshold) {
    617         setAngularSleepingThreshold(objectId, angularSleepingThreshold);
    618     }
    619 
    620     private native void setAngularSleepingThreshold(long objectId, float angularSleepingThreshold);
    621 
    622     public float getLinearSleepingThreshold() {
    623         return getLinearSleepingThreshold(objectId);
    624     }
    625 
    626     private native float getLinearSleepingThreshold(long objectId);
    627 
    628     public float getAngularSleepingThreshold() {
    629         return getAngularSleepingThreshold(objectId);
    630     }
    631 
    632     private native float getAngularSleepingThreshold(long objectId);
    633 
    634     public float getAngularFactor() {
    635         return getAngularFactor(objectId);
    636     }
    637 
    638     private native float getAngularFactor(long objectId);
    639 
    640     public void setAngularFactor(float factor) {
    641         setAngularFactor(objectId, factor);
    642     }
    643 
    644     private native void setAngularFactor(long objectId, float factor);
    645 
    646     /**
    647      * do not use manually, joints are added automatically
    648      */
    649     public void addJoint(PhysicsJoint joint) {
    650         if (!joints.contains(joint)) {
    651             joints.add(joint);
    652         }
    653         updateDebugShape();
    654     }
    655 
    656     /**
    657      *
    658      */
    659     public void removeJoint(PhysicsJoint joint) {
    660         joints.remove(joint);
    661     }
    662 
    663     /**
    664      * Returns a list of connected joints. This list is only filled when
    665      * the PhysicsRigidBody is actually added to the physics space or loaded from disk.
    666      * @return list of active joints connected to this PhysicsRigidBody
    667      */
    668     public List<PhysicsJoint> getJoints() {
    669         return joints;
    670     }
    671 
    672     @Override
    673     protected Spatial getDebugShape() {
    674         //add joints
    675         Spatial shape = super.getDebugShape();
    676         Node node = null;
    677         if (shape instanceof Node) {
    678             node = (Node) shape;
    679         } else {
    680             node = new Node("DebugShapeNode");
    681             node.attachChild(shape);
    682         }
    683         int i = 0;
    684         for (Iterator<PhysicsJoint> it = joints.iterator(); it.hasNext();) {
    685             PhysicsJoint physicsJoint = it.next();
    686             Vector3f pivot = null;
    687             if (physicsJoint.getBodyA() == this) {
    688                 pivot = physicsJoint.getPivotA();
    689             } else {
    690                 pivot = physicsJoint.getPivotB();
    691             }
    692             Arrow arrow = new Arrow(pivot);
    693             Geometry geom = new Geometry("DebugBone" + i, arrow);
    694             geom.setMaterial(debugMaterialGreen);
    695             node.attachChild(geom);
    696             i++;
    697         }
    698         return node;
    699     }
    700 
    701     @Override
    702     public void write(JmeExporter e) throws IOException {
    703         super.write(e);
    704         OutputCapsule capsule = e.getCapsule(this);
    705 
    706         capsule.write(getMass(), "mass", 1.0f);
    707 
    708         capsule.write(getGravity(), "gravity", Vector3f.ZERO);
    709         capsule.write(getFriction(), "friction", 0.5f);
    710         capsule.write(getRestitution(), "restitution", 0);
    711         capsule.write(getAngularFactor(), "angularFactor", 1);
    712         capsule.write(kinematic, "kinematic", false);
    713 
    714         capsule.write(getLinearDamping(), "linearDamping", 0);
    715         capsule.write(getAngularDamping(), "angularDamping", 0);
    716         capsule.write(getLinearSleepingThreshold(), "linearSleepingThreshold", 0.8f);
    717         capsule.write(getAngularSleepingThreshold(), "angularSleepingThreshold", 1.0f);
    718 
    719         capsule.write(getCcdMotionThreshold(), "ccdMotionThreshold", 0);
    720         capsule.write(getCcdSweptSphereRadius(), "ccdSweptSphereRadius", 0);
    721 
    722         capsule.write(getPhysicsLocation(new Vector3f()), "physicsLocation", new Vector3f());
    723         capsule.write(getPhysicsRotationMatrix(new Matrix3f()), "physicsRotation", new Matrix3f());
    724 
    725         capsule.writeSavableArrayList(joints, "joints", null);
    726     }
    727 
    728     @Override
    729     public void read(JmeImporter e) throws IOException {
    730         super.read(e);
    731 
    732         InputCapsule capsule = e.getCapsule(this);
    733         float mass = capsule.readFloat("mass", 1.0f);
    734         this.mass = mass;
    735         rebuildRigidBody();
    736         setGravity((Vector3f) capsule.readSavable("gravity", Vector3f.ZERO.clone()));
    737         setFriction(capsule.readFloat("friction", 0.5f));
    738         setKinematic(capsule.readBoolean("kinematic", false));
    739 
    740         setRestitution(capsule.readFloat("restitution", 0));
    741         setAngularFactor(capsule.readFloat("angularFactor", 1));
    742         setDamping(capsule.readFloat("linearDamping", 0), capsule.readFloat("angularDamping", 0));
    743         setSleepingThresholds(capsule.readFloat("linearSleepingThreshold", 0.8f), capsule.readFloat("angularSleepingThreshold", 1.0f));
    744         setCcdMotionThreshold(capsule.readFloat("ccdMotionThreshold", 0));
    745         setCcdSweptSphereRadius(capsule.readFloat("ccdSweptSphereRadius", 0));
    746 
    747         setPhysicsLocation((Vector3f) capsule.readSavable("physicsLocation", new Vector3f()));
    748         setPhysicsRotation((Matrix3f) capsule.readSavable("physicsRotation", new Matrix3f()));
    749 
    750         joints = capsule.readSavableArrayList("joints", null);
    751     }
    752 }
    753