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