All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.jme3.bullet.objects.PhysicsRigidBody Maven / Gradle / Ivy

/*
 * Copyright (c) 2009-2018 jMonkeyEngine
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
 *   may be used to endorse or promote products derived from this software
 *   without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package com.jme3.bullet.objects;

import com.jme3.bullet.PhysicsSpace;
import com.jme3.bullet.collision.PhysicsCollisionObject;
import com.jme3.bullet.collision.shapes.CollisionShape;
import com.jme3.bullet.collision.shapes.MeshCollisionShape;
import com.jme3.bullet.joints.PhysicsJoint;
import com.jme3.bullet.objects.infos.RigidBodyMotionState;
import com.jme3.export.InputCapsule;
import com.jme3.export.JmeExporter;
import com.jme3.export.JmeImporter;
import com.jme3.export.OutputCapsule;
import com.jme3.math.Matrix3f;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * A collision object for a rigid body, based on Bullet's btRigidBody.
 *
 * @author normenhansen
 */
public class PhysicsRigidBody extends PhysicsCollisionObject {

    /**
     * motion state
     */
    protected RigidBodyMotionState motionState = new RigidBodyMotionState();
    /**
     * copy of mass (>0) of a dynamic body, or 0 for a static body
     * (default=1)
     */
    protected float mass = 1.0f;
    /**
     * copy of kinematic flag: true→set kinematic mode (spatial controls
     * body), false→dynamic/static mode (body controls spatial)
     * (default=false)
     */
    protected boolean kinematic = false;
    /**
     * joint list
     */
    protected ArrayList joints = new ArrayList(4);

    /**
     * No-argument constructor needed by SavableClassUtil. Do not invoke
     * directly!
     */
    public PhysicsRigidBody() {
    }

    /**
     * Instantiate a dynamic body with mass=1 and the specified collision shape.
     *
     * @param shape the desired shape (not null, alias created)
     */
    public PhysicsRigidBody(CollisionShape shape) {
        collisionShape = shape;
        rebuildRigidBody();
    }

    /**
     * Instantiate a body with the specified collision shape and mass.
     *
     * @param shape the desired shape (not null, alias created)
     * @param mass if 0, a static body is created; otherwise a dynamic body is
     * created (≥0)
     */
    public PhysicsRigidBody(CollisionShape shape, float mass) {
        collisionShape = shape;
        this.mass = mass;
        rebuildRigidBody();
    }

    /**
     * Build/rebuild this body after parameters have changed.
     */
    protected void rebuildRigidBody() {
        boolean removed = false;
        if (collisionShape instanceof MeshCollisionShape && mass != 0) {
            throw new IllegalStateException("Dynamic rigidbody can not have mesh collision shape!");
        }
        if (objectId != 0) {
            if (isInWorld(objectId)) {
                PhysicsSpace.getPhysicsSpace().remove(this);
                removed = true;
            }
            Logger.getLogger(this.getClass().getName()).log(Level.FINE, "Clearing RigidBody {0}", Long.toHexString(objectId));
            finalizeNative(objectId);
        }
        preRebuild();
        objectId = createRigidBody(mass, motionState.getObjectId(), collisionShape.getObjectId());
        Logger.getLogger(this.getClass().getName()).log(Level.FINE, "Created RigidBody {0}", Long.toHexString(objectId));
        postRebuild();
        if (removed) {
            PhysicsSpace.getPhysicsSpace().add(this);
        }
    }

    /**
     * For use by subclasses.
     */
    protected void preRebuild() {
    }

    private native long createRigidBody(float mass, long motionStateId, long collisionShapeId);

    /**
     * For use by subclasses.
     */
    protected void postRebuild() {
        if (mass == 0.0f) {
            setStatic(objectId, true);
        } else {
            setStatic(objectId, false);
        }
        initUserPointer();
    }

    /**
     * Access this body's motion state.
     *
     * @return the pre-existing instance
     */
    public RigidBodyMotionState getMotionState() {
        return motionState;
    }

    /**
     * Test whether this body is in a physics space.
     *
     * @return true→in a space, false→not in a space
     */
    public boolean isInWorld() {
        return isInWorld(objectId);
    }

    private native boolean isInWorld(long objectId);

    /**
     * Directly alter the location of this body's center of mass.
     *
     * @param location the desired location (not null, unaffected)
     */
    public void setPhysicsLocation(Vector3f location) {
        setPhysicsLocation(objectId, location);
    }

    private native void setPhysicsLocation(long objectId, Vector3f location);

    /**
     * Directly alter this body's orientation.
     *
     * @param rotation the desired orientation (rotation matrix, not null,
     * unaffected)
     */
    public void setPhysicsRotation(Matrix3f rotation) {
        setPhysicsRotation(objectId, rotation);
    }

    private native void setPhysicsRotation(long objectId, Matrix3f rotation);

    /**
     * Directly alter this body's orientation.
     *
     * @param rotation the desired orientation (quaternion, in physics-space
     * coordinates, not null, unaffected)
     */
    public void setPhysicsRotation(Quaternion rotation) {
        setPhysicsRotation(objectId, rotation);
    }

    private native void setPhysicsRotation(long objectId, Quaternion rotation);

    /**
     * Copy the location of this body's center of mass.
     *
     * @param trans storage for the result (modified if not null)
     * @return the location (in physics-space coordinates, either the provided 
     * storage or a new vector, not null)
     */
    public Vector3f getPhysicsLocation(Vector3f trans) {
        if (trans == null) {
            trans = new Vector3f();
        }
        getPhysicsLocation(objectId, trans);
        return trans;
    }

    private native void getPhysicsLocation(long objectId, Vector3f vector);

    /**
     * Copy this body's orientation to a quaternion.
     *
     * @param rot storage for the result (modified if not null)
     * @return the orientation (either the provided storage or a new quaternion,
     * not null)
     */
    public Quaternion getPhysicsRotation(Quaternion rot) {
        if (rot == null) {
            rot = new Quaternion();
        }
        getPhysicsRotation(objectId, rot);
        return rot;
    }

    /**
     * Alter the principal components of the local inertia tensor.
     *
     * @param gravity (not null, unaffected)
     */
    public void setInverseInertiaLocal(Vector3f gravity) {
    	setInverseInertiaLocal(objectId, gravity);
    }
    private native void setInverseInertiaLocal(long objectId, Vector3f gravity);

    /**
     * Copy the principal components of the local inverse inertia tensor.
     *
     * @param trans storage for the result (modified if not null)
     * @return a vector (either the provided storage or a new vector, not null)
     */
    public Vector3f getInverseInertiaLocal(Vector3f trans) {
        if (trans == null) {
            trans = new Vector3f();
        }
        getInverseInertiaLocal(objectId, trans);
        return trans;
    }
    
    private native void getInverseInertiaLocal(long objectId, Vector3f vector);

    private native void getPhysicsRotation(long objectId, Quaternion rot);

    /**
     * Copy this body's orientation to a matrix.
     *
     * @param rot storage for the result (modified if not null)
     * @return the orientation (in physics-space coordinates, either the 
     * provided storage or a new matrix, not null)
     */
    public Matrix3f getPhysicsRotationMatrix(Matrix3f rot) {
        if (rot == null) {
            rot = new Matrix3f();
        }
        getPhysicsRotationMatrix(objectId, rot);
        return rot;
    }

    private native void getPhysicsRotationMatrix(long objectId, Matrix3f rot);

    /**
     * Copy the location of this body's center of mass.
     *
     * @return a new location vector (not null)
     */
    public Vector3f getPhysicsLocation() {
        Vector3f vec = new Vector3f();
        getPhysicsLocation(objectId, vec);
        return vec;
    }

    /**
     * Copy this body's orientation to a quaternion.
     *
     * @return a new quaternion (not null)
     */
    public Quaternion getPhysicsRotation() {
        Quaternion quat = new Quaternion();
        getPhysicsRotation(objectId, quat);
        return quat;
    }

    /**
     * Copy this body's orientation to a matrix.
     *
     * @return a new matrix (not null)
     */
    public Matrix3f getPhysicsRotationMatrix() {
        Matrix3f mtx = new Matrix3f();
        getPhysicsRotationMatrix(objectId, mtx);
        return mtx;
    }

//    /**
//     * Gets the physics object location
//     * @param location the location of the actual physics object is stored in this Vector3f
//     */
//    public Vector3f getInterpolatedPhysicsLocation(Vector3f location) {
//        if (location == null) {
//            location = new Vector3f();
//        }
//        rBody.getInterpolationWorldTransform(tempTrans);
//        return Converter.convert(tempTrans.origin, location);
//    }
//
//    /**
//     * Gets the physics object rotation
//     * @param rotation the rotation of the actual physics object is stored in this Matrix3f
//     */
//    public Matrix3f getInterpolatedPhysicsRotation(Matrix3f rotation) {
//        if (rotation == null) {
//            rotation = new Matrix3f();
//        }
//        rBody.getInterpolationWorldTransform(tempTrans);
//        return Converter.convert(tempTrans.basis, rotation);
//    }
    /**
     * Put this body into kinematic mode or take it out of kinematic mode.
     * 

* In kinematic mode, the body is not influenced by physics but can affect * other physics objects. Its kinetic force is calculated based on its * movement and weight. * * @param kinematic true→set kinematic mode, false→set * dynamic/static mode (default=false) */ public void setKinematic(boolean kinematic) { this.kinematic = kinematic; setKinematic(objectId, kinematic); } private native void setKinematic(long objectId, boolean kinematic); /** * Test whether this body is in kinematic mode. *

* In kinematic mode, the body is not influenced by physics but can affect * other physics objects. Its kinetic force is calculated based on its * movement and weight. * * @return true if in kinematic mode, otherwise false (dynamic/static mode) */ public boolean isKinematic() { return kinematic; } /** * Alter the radius of the swept sphere used for continuous collision * detection (CCD). * * @param radius the desired radius (≥0, default=0) */ public void setCcdSweptSphereRadius(float radius) { setCcdSweptSphereRadius(objectId, radius); } private native void setCcdSweptSphereRadius(long objectId, float radius); /** * Alter the amount of motion required to activate continuous collision * detection (CCD). *

* This addresses the issue of fast objects passing through other objects * with no collision detected. * * @param threshold the desired threshold velocity (>0) or zero to * disable CCD (default=0) */ public void setCcdMotionThreshold(float threshold) { setCcdMotionThreshold(objectId, threshold); } private native void setCcdMotionThreshold(long objectId, float threshold); /** * Read the radius of the swept sphere used for continuous collision * detection (CCD). * * @return radius (≥0) */ public float getCcdSweptSphereRadius() { return getCcdSweptSphereRadius(objectId); } private native float getCcdSweptSphereRadius(long objectId); /** * Calculate this body's continuous collision detection (CCD) motion * threshold. * * @return the threshold velocity (≥0) */ public float getCcdMotionThreshold() { return getCcdMotionThreshold(objectId); } private native float getCcdMotionThreshold(long objectId); /** * Calculate the square of this body's continuous collision detection (CCD) * motion threshold. * * @return the threshold velocity squared (≥0) */ public float getCcdSquareMotionThreshold() { return getCcdSquareMotionThreshold(objectId); } private native float getCcdSquareMotionThreshold(long objectId); /** * Read this body's mass. * * @return the mass (>0) or zero for a static body */ public float getMass() { return mass; } /** * Alter this body's mass. Bodies with mass=0 are static. For dynamic * bodies, it is best to keep the mass around 1. * * @param mass the desired mass (>0) or 0 for a static body (default=1) */ public void setMass(float mass) { this.mass = mass; if (collisionShape instanceof MeshCollisionShape && mass != 0) { throw new IllegalStateException("Dynamic rigidbody can not have mesh collision shape!"); } if (objectId != 0) { if (collisionShape != null) { updateMassProps(objectId, collisionShape.getObjectId(), mass); } if (mass == 0.0f) { setStatic(objectId, true); } else { setStatic(objectId, false); } } } private native void setStatic(long objectId, boolean state); private native long updateMassProps(long objectId, long collisionShapeId, float mass); /** * Copy this body's gravitational acceleration. * * @return a new acceleration vector (in physics-space coordinates, not * null) */ public Vector3f getGravity() { return getGravity(null); } /** * Copy this body's gravitational acceleration. * * @param gravity storage for the result (modified if not null) * @return an acceleration vector (in physics-space coordinates, either the * provided storage or a new vector, not null) */ public Vector3f getGravity(Vector3f gravity) { if (gravity == null) { gravity = new Vector3f(); } getGravity(objectId, gravity); return gravity; } private native void getGravity(long objectId, Vector3f gravity); /** * Alter this body's gravitational acceleration. *

* Invoke this after adding the body to a PhysicsSpace. Adding a body to a * PhysicsSpace alters its gravity. * * @param gravity the desired acceleration vector (not null, unaffected) */ public void setGravity(Vector3f gravity) { setGravity(objectId, gravity); } private native void setGravity(long objectId, Vector3f gravity); /** * Read this body's friction. * * @return friction value */ public float getFriction() { return getFriction(objectId); } private native float getFriction(long objectId); /** * Alter this body's friction. * * @param friction the desired friction value (default=0.5) */ public void setFriction(float friction) { setFriction(objectId, friction); } private native void setFriction(long objectId, float friction); /** * Alter this body's damping. * * @param linearDamping the desired linear damping value (default=0) * @param angularDamping the desired angular damping value (default=0) */ public void setDamping(float linearDamping, float angularDamping) { setDamping(objectId, linearDamping, angularDamping); } private native void setDamping(long objectId, float linearDamping, float angularDamping); // private native void setRestitution(long objectId, float factor); // // public void setLinearDamping(float linearDamping) { // constructionInfo.linearDamping = linearDamping; // rBody.setDamping(linearDamping, constructionInfo.angularDamping); // } // // private native void setRestitution(long objectId, float factor); // /** * Alter this body's linear damping. * * @param linearDamping the desired linear damping value (default=0) */ public void setLinearDamping(float linearDamping) { setDamping(objectId, linearDamping, getAngularDamping()); } /** * Alter this body's angular damping. * * @param angularDamping the desired angular damping value (default=0) */ public void setAngularDamping(float angularDamping) { setAngularDamping(objectId, angularDamping); } private native void setAngularDamping(long objectId, float factor); /** * Read this body's linear damping. * * @return damping value */ public float getLinearDamping() { return getLinearDamping(objectId); } private native float getLinearDamping(long objectId); /** * Read this body's angular damping. * * @return damping value */ public float getAngularDamping() { return getAngularDamping(objectId); } private native float getAngularDamping(long objectId); /** * Read this body's restitution (bounciness). * * @return restitution value */ public float getRestitution() { return getRestitution(objectId); } private native float getRestitution(long objectId); /** * Alter this body's restitution (bounciness). For best performance, set * restitution=0. * * @param restitution the desired value (default=0) */ public void setRestitution(float restitution) { setRestitution(objectId, restitution); } private native void setRestitution(long objectId, float factor); /** * Copy this body's angular velocity. * * @return a new velocity vector (in physics-space coordinates, not null) */ public Vector3f getAngularVelocity() { Vector3f vec = new Vector3f(); getAngularVelocity(objectId, vec); return vec; } private native void getAngularVelocity(long objectId, Vector3f vec); /** * Copy this body's angular velocity. * * @param vec storage for the result (in physics-space coordinates, not * null, modified) */ public void getAngularVelocity(Vector3f vec) { getAngularVelocity(objectId, vec); } /** * Alter this body's angular velocity. * * @param vec the desired angular velocity vector (not null, unaffected) */ public void setAngularVelocity(Vector3f vec) { setAngularVelocity(objectId, vec); activate(); } private native void setAngularVelocity(long objectId, Vector3f vec); /** * Copy the linear velocity of this body's center of mass. * * @return a new velocity vector (in physics-space coordinates, not null) */ public Vector3f getLinearVelocity() { Vector3f vec = new Vector3f(); getLinearVelocity(objectId, vec); return vec; } private native void getLinearVelocity(long objectId, Vector3f vec); /** * Copy the linear velocity of this body's center of mass. * * @param vec storage for the result (in physics-space coordinates, not * null, modified) */ public void getLinearVelocity(Vector3f vec) { getLinearVelocity(objectId, vec); } /** * Alter the linear velocity of this body's center of mass. * * @param vec the desired velocity vector (not null) */ public void setLinearVelocity(Vector3f vec) { setLinearVelocity(objectId, vec); activate(); } private native void setLinearVelocity(long objectId, Vector3f vec); /** * Apply a force to the PhysicsRigidBody. Effective only if the next physics * update steps the physics space. *

* To apply an impulse, use applyImpulse, use applyContinuousForce to apply * continuous force. * * @param force the force (not null, unaffected) * @param location the location of the force */ public void applyForce(Vector3f force, Vector3f location) { applyForce(objectId, force, location); activate(); } private native void applyForce(long objectId, Vector3f force, Vector3f location); /** * Apply a force to the PhysicsRigidBody. Effective only if the next physics * update steps the physics space. *

* To apply an impulse, use * {@link #applyImpulse(com.jme3.math.Vector3f, com.jme3.math.Vector3f)}. * * @param force the force (not null, unaffected) */ public void applyCentralForce(Vector3f force) { applyCentralForce(objectId, force); activate(); } private native void applyCentralForce(long objectId, Vector3f force); /** * Apply a force to the PhysicsRigidBody. Effective only if the next physics * update steps the physics space. *

* To apply an impulse, use * {@link #applyImpulse(com.jme3.math.Vector3f, com.jme3.math.Vector3f)}. * * @param torque the torque (not null, unaffected) */ public void applyTorque(Vector3f torque) { applyTorque(objectId, torque); activate(); } private native void applyTorque(long objectId, Vector3f vec); /** * Apply an impulse to the body the next physics update. * * @param impulse applied impulse (not null, unaffected) * @param rel_pos location relative to object (not null, unaffected) */ public void applyImpulse(Vector3f impulse, Vector3f rel_pos) { applyImpulse(objectId, impulse, rel_pos); activate(); } private native void applyImpulse(long objectId, Vector3f impulse, Vector3f rel_pos); /** * Apply a torque impulse to the body in the next physics update. * * @param vec the torque to apply */ public void applyTorqueImpulse(Vector3f vec) { applyTorqueImpulse(objectId, vec); activate(); } private native void applyTorqueImpulse(long objectId, Vector3f vec); /** * Clear all forces acting on this body. */ public void clearForces() { clearForces(objectId); } private native void clearForces(long objectId); /** * Apply the specified CollisionShape to this body. *

* Note that the body should not be in any physics space while changing * shape; the body gets rebuilt on the physics side. * * @param collisionShape the shape to apply (not null, alias created) */ public void setCollisionShape(CollisionShape collisionShape) { super.setCollisionShape(collisionShape); if (collisionShape instanceof MeshCollisionShape && mass != 0) { throw new IllegalStateException("Dynamic rigidbody can not have mesh collision shape!"); } if (objectId == 0) { rebuildRigidBody(); } else { setCollisionShape(objectId, collisionShape.getObjectId()); updateMassProps(objectId, collisionShape.getObjectId(), mass); } } private native void setCollisionShape(long objectId, long collisionShapeId); /** * Reactivates this body if it has been deactivated due to lack of motion. */ public void activate() { activate(objectId); } private native void activate(long objectId); /** * Test whether this body has been deactivated due to lack of motion. * * @return true if still active, false if deactivated */ public boolean isActive() { return isActive(objectId); } private native boolean isActive(long objectId); /** * Alter this body's sleeping thresholds. *

* These thresholds determine when the body can be deactivated to save * resources. Low values keep the body active when it barely moves. * * @param linear the desired linear sleeping threshold (≥0, default=0.8) * @param angular the desired angular sleeping threshold (≥0, default=1) */ public void setSleepingThresholds(float linear, float angular) { setSleepingThresholds(objectId, linear, angular); } private native void setSleepingThresholds(long objectId, float linear, float angular); /** * Alter this body's linear sleeping threshold. * * @param linearSleepingThreshold the desired threshold (≥0, default=0.8) */ public void setLinearSleepingThreshold(float linearSleepingThreshold) { setLinearSleepingThreshold(objectId, linearSleepingThreshold); } private native void setLinearSleepingThreshold(long objectId, float linearSleepingThreshold); /** * Alter this body's angular sleeping threshold. * * @param angularSleepingThreshold the desired threshold (≥0, default=1) */ public void setAngularSleepingThreshold(float angularSleepingThreshold) { setAngularSleepingThreshold(objectId, angularSleepingThreshold); } private native void setAngularSleepingThreshold(long objectId, float angularSleepingThreshold); /** * Read this body's linear sleeping threshold. * * @return the linear sleeping threshold (≥0) */ public float getLinearSleepingThreshold() { return getLinearSleepingThreshold(objectId); } private native float getLinearSleepingThreshold(long objectId); /** * Read this body's angular sleeping threshold. * * @return the angular sleeping threshold (≥0) */ public float getAngularSleepingThreshold() { return getAngularSleepingThreshold(objectId); } private native float getAngularSleepingThreshold(long objectId); /** * Read this body's angular factor for the X axis. * * @return the angular factor */ public float getAngularFactor() { return getAngularFactor(null).getX(); } /** * Copy this body's angular factors. * * @param store storage for the result (modified if not null) * @return the angular factor for each axis (either the provided storage or * new vector, not null) */ public Vector3f getAngularFactor(Vector3f store) { // Done this way to prevent breaking the API. if (store == null) { store = new Vector3f(); } getAngularFactor(objectId, store); return store; } private native void getAngularFactor(long objectId, Vector3f vec); /** * Alter this body's angular factor. * * @param factor the desired angular factor for all axes (not null, * unaffected, default=1) */ public void setAngularFactor(float factor) { setAngularFactor(objectId, new Vector3f(factor, factor, factor)); } /** * Alter this body's angular factors. * * @param factor the desired angular factor for each axis (not null, * unaffected, default=(1,1,1)) */ public void setAngularFactor(Vector3f factor) { setAngularFactor(objectId, factor); } private native void setAngularFactor(long objectId, Vector3f factor); /** * Copy this body's linear factors. * * @return the linear factor for each axis (not null) */ public Vector3f getLinearFactor() { Vector3f vec = new Vector3f(); getLinearFactor(objectId, vec); return vec; } private native void getLinearFactor(long objectId, Vector3f vec); /** * Alter this body's linear factors. * * @param factor the desired linear factor for each axis (not null, * unaffected, default=(1,1,1)) */ public void setLinearFactor(Vector3f factor) { setLinearFactor(objectId, factor); } private native void setLinearFactor(long objectId, Vector3f factor); /** * Do not invoke directly! Joints are added automatically when created. * * @param joint the joint to add (not null) */ public void addJoint(PhysicsJoint joint) { if (!joints.contains(joint)) { joints.add(joint); } } /** * Do not invoke directly! Joints are removed automatically when destroyed. * * @param joint the joint to remove (not null) */ public void removeJoint(PhysicsJoint joint) { joints.remove(joint); } /** * Access the list of joints connected with this body. *

* This list is only filled when the PhysicsRigidBody is added to a physics * space. * * @return the pre-existing list (not null) */ public List getJoints() { return joints; } /** * Serialize this body, for example when saving to a J3O file. * * @param e exporter (not null) * @throws IOException from exporter */ @Override public void write(JmeExporter e) throws IOException { super.write(e); OutputCapsule capsule = e.getCapsule(this); capsule.write(getMass(), "mass", 1.0f); capsule.write(getGravity(), "gravity", Vector3f.ZERO); capsule.write(getFriction(), "friction", 0.5f); capsule.write(getRestitution(), "restitution", 0); Vector3f angularFactor = getAngularFactor(null); if (angularFactor.x == angularFactor.y && angularFactor.y == angularFactor.z) { capsule.write(getAngularFactor(), "angularFactor", 1); } else { capsule.write(getAngularFactor(null), "angularFactor", Vector3f.UNIT_XYZ); capsule.write(getLinearFactor(), "linearFactor", Vector3f.UNIT_XYZ); } capsule.write(kinematic, "kinematic", false); capsule.write(getLinearDamping(), "linearDamping", 0); capsule.write(getAngularDamping(), "angularDamping", 0); capsule.write(getLinearSleepingThreshold(), "linearSleepingThreshold", 0.8f); capsule.write(getAngularSleepingThreshold(), "angularSleepingThreshold", 1.0f); capsule.write(getCcdMotionThreshold(), "ccdMotionThreshold", 0); capsule.write(getCcdSweptSphereRadius(), "ccdSweptSphereRadius", 0); capsule.write(getPhysicsLocation(new Vector3f()), "physicsLocation", new Vector3f()); capsule.write(getPhysicsRotationMatrix(new Matrix3f()), "physicsRotation", new Matrix3f()); capsule.writeSavableArrayList(joints, "joints", null); } /** * De-serialize this body, for example when loading from a J3O file. * * @param e importer (not null) * @throws IOException from importer */ @Override public void read(JmeImporter e) throws IOException { super.read(e); InputCapsule capsule = e.getCapsule(this); float mass = capsule.readFloat("mass", 1.0f); this.mass = mass; rebuildRigidBody(); setGravity((Vector3f) capsule.readSavable("gravity", Vector3f.ZERO.clone())); setFriction(capsule.readFloat("friction", 0.5f)); setKinematic(capsule.readBoolean("kinematic", false)); setRestitution(capsule.readFloat("restitution", 0)); Vector3f angularFactor = (Vector3f) capsule.readSavable("angularFactor", null); if(angularFactor == null) { setAngularFactor(capsule.readFloat("angularFactor", 1)); } else { setAngularFactor(angularFactor); setLinearFactor((Vector3f) capsule.readSavable("linearFactor", Vector3f.UNIT_XYZ.clone())); } setDamping(capsule.readFloat("linearDamping", 0), capsule.readFloat("angularDamping", 0)); setSleepingThresholds(capsule.readFloat("linearSleepingThreshold", 0.8f), capsule.readFloat("angularSleepingThreshold", 1.0f)); setCcdMotionThreshold(capsule.readFloat("ccdMotionThreshold", 0)); setCcdSweptSphereRadius(capsule.readFloat("ccdSweptSphereRadius", 0)); setPhysicsLocation((Vector3f) capsule.readSavable("physicsLocation", new Vector3f())); setPhysicsRotation((Matrix3f) capsule.readSavable("physicsRotation", new Matrix3f())); joints = capsule.readSavableArrayList("joints", null); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy