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