1 /* 2 Bullet Continuous Collision Detection and Physics Library 3 Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ 4 5 This software is provided 'as-is', without any express or implied warranty. 6 In no event will the authors be held liable for any damages arising from the use of this software. 7 Permission is granted to anyone to use this software for any purpose, 8 including commercial applications, and to alter it and redistribute it freely, 9 subject to the following restrictions: 10 11 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 3. This notice may not be removed or altered from any source distribution. 14 */ 15 16 #ifndef BT_RIGIDBODY_H 17 #define BT_RIGIDBODY_H 18 19 #include "LinearMath/btAlignedObjectArray.h" 20 #include "LinearMath/btTransform.h" 21 #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" 22 #include "BulletCollision/CollisionDispatch/btCollisionObject.h" 23 24 class btCollisionShape; 25 class btMotionState; 26 class btTypedConstraint; 27 28 29 extern btScalar gDeactivationTime; 30 extern bool gDisableDeactivation; 31 32 #ifdef BT_USE_DOUBLE_PRECISION 33 #define btRigidBodyData btRigidBodyDoubleData 34 #define btRigidBodyDataName "btRigidBodyDoubleData" 35 #else 36 #define btRigidBodyData btRigidBodyFloatData 37 #define btRigidBodyDataName "btRigidBodyFloatData" 38 #endif //BT_USE_DOUBLE_PRECISION 39 40 41 enum btRigidBodyFlags 42 { 43 BT_DISABLE_WORLD_GRAVITY = 1, 44 ///BT_ENABLE_GYROPSCOPIC_FORCE flags is enabled by default in Bullet 2.83 and onwards. 45 ///and it BT_ENABLE_GYROPSCOPIC_FORCE becomes equivalent to BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_BODY 46 ///See Demos/GyroscopicDemo and computeGyroscopicImpulseImplicit 47 BT_ENABLE_GYROSCOPIC_FORCE_EXPLICIT = 2, 48 BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_WORLD=4, 49 BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_BODY=8, 50 BT_ENABLE_GYROPSCOPIC_FORCE = BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_BODY, 51 }; 52 53 54 ///The btRigidBody is the main class for rigid body objects. It is derived from btCollisionObject, so it keeps a pointer to a btCollisionShape. 55 ///It is recommended for performance and memory use to share btCollisionShape objects whenever possible. 56 ///There are 3 types of rigid bodies: 57 ///- A) Dynamic rigid bodies, with positive mass. Motion is controlled by rigid body dynamics. 58 ///- B) Fixed objects with zero mass. They are not moving (basically collision objects) 59 ///- C) Kinematic objects, which are objects without mass, but the user can move them. There is on-way interaction, and Bullet calculates a velocity based on the timestep and previous and current world transform. 60 ///Bullet automatically deactivates dynamic rigid bodies, when the velocity is below a threshold for a given time. 61 ///Deactivated (sleeping) rigid bodies don't take any processing time, except a minor broadphase collision detection impact (to allow active objects to activate/wake up sleeping objects) 62 class btRigidBody : public btCollisionObject 63 { 64 65 btMatrix3x3 m_invInertiaTensorWorld; 66 btVector3 m_linearVelocity; 67 btVector3 m_angularVelocity; 68 btScalar m_inverseMass; 69 btVector3 m_linearFactor; 70 71 btVector3 m_gravity; 72 btVector3 m_gravity_acceleration; 73 btVector3 m_invInertiaLocal; 74 btVector3 m_totalForce; 75 btVector3 m_totalTorque; 76 77 btScalar m_linearDamping; 78 btScalar m_angularDamping; 79 80 bool m_additionalDamping; 81 btScalar m_additionalDampingFactor; 82 btScalar m_additionalLinearDampingThresholdSqr; 83 btScalar m_additionalAngularDampingThresholdSqr; 84 btScalar m_additionalAngularDampingFactor; 85 86 87 btScalar m_linearSleepingThreshold; 88 btScalar m_angularSleepingThreshold; 89 90 //m_optionalMotionState allows to automatic synchronize the world transform for active objects 91 btMotionState* m_optionalMotionState; 92 93 //keep track of typed constraints referencing this rigid body, to disable collision between linked bodies 94 btAlignedObjectArray<btTypedConstraint*> m_constraintRefs; 95 96 int m_rigidbodyFlags; 97 98 int m_debugBodyId; 99 100 101 protected: 102 103 ATTRIBUTE_ALIGNED16(btVector3 m_deltaLinearVelocity); 104 btVector3 m_deltaAngularVelocity; 105 btVector3 m_angularFactor; 106 btVector3 m_invMass; 107 btVector3 m_pushVelocity; 108 btVector3 m_turnVelocity; 109 110 111 public: 112 113 114 ///The btRigidBodyConstructionInfo structure provides information to create a rigid body. Setting mass to zero creates a fixed (non-dynamic) rigid body. 115 ///For dynamic objects, you can use the collision shape to approximate the local inertia tensor, otherwise use the zero vector (default argument) 116 ///You can use the motion state to synchronize the world transform between physics and graphics objects. 117 ///And if the motion state is provided, the rigid body will initialize its initial world transform from the motion state, 118 ///m_startWorldTransform is only used when you don't provide a motion state. 119 struct btRigidBodyConstructionInfo 120 { 121 btScalar m_mass; 122 123 ///When a motionState is provided, the rigid body will initialize its world transform from the motion state 124 ///In this case, m_startWorldTransform is ignored. 125 btMotionState* m_motionState; 126 btTransform m_startWorldTransform; 127 128 btCollisionShape* m_collisionShape; 129 btVector3 m_localInertia; 130 btScalar m_linearDamping; 131 btScalar m_angularDamping; 132 133 ///best simulation results when friction is non-zero 134 btScalar m_friction; 135 ///the m_rollingFriction prevents rounded shapes, such as spheres, cylinders and capsules from rolling forever. 136 ///See Bullet/Demos/RollingFrictionDemo for usage 137 btScalar m_rollingFriction; 138 ///best simulation results using zero restitution. 139 btScalar m_restitution; 140 141 btScalar m_linearSleepingThreshold; 142 btScalar m_angularSleepingThreshold; 143 144 //Additional damping can help avoiding lowpass jitter motion, help stability for ragdolls etc. 145 //Such damping is undesirable, so once the overall simulation quality of the rigid body dynamics system has improved, this should become obsolete 146 bool m_additionalDamping; 147 btScalar m_additionalDampingFactor; 148 btScalar m_additionalLinearDampingThresholdSqr; 149 btScalar m_additionalAngularDampingThresholdSqr; 150 btScalar m_additionalAngularDampingFactor; 151 152 btRigidBodyConstructionInfo( btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia=btVector3(0,0,0)): m_massbtRigidBodyConstructionInfo153 m_mass(mass), 154 m_motionState(motionState), 155 m_collisionShape(collisionShape), 156 m_localInertia(localInertia), 157 m_linearDamping(btScalar(0.)), 158 m_angularDamping(btScalar(0.)), 159 m_friction(btScalar(0.5)), 160 m_rollingFriction(btScalar(0)), 161 m_restitution(btScalar(0.)), 162 m_linearSleepingThreshold(btScalar(0.8)), 163 m_angularSleepingThreshold(btScalar(1.f)), 164 m_additionalDamping(false), 165 m_additionalDampingFactor(btScalar(0.005)), 166 m_additionalLinearDampingThresholdSqr(btScalar(0.01)), 167 m_additionalAngularDampingThresholdSqr(btScalar(0.01)), 168 m_additionalAngularDampingFactor(btScalar(0.01)) 169 { 170 m_startWorldTransform.setIdentity(); 171 } 172 }; 173 174 ///btRigidBody constructor using construction info 175 btRigidBody( const btRigidBodyConstructionInfo& constructionInfo); 176 177 ///btRigidBody constructor for backwards compatibility. 178 ///To specify friction (etc) during rigid body construction, please use the other constructor (using btRigidBodyConstructionInfo) 179 btRigidBody( btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia=btVector3(0,0,0)); 180 181 ~btRigidBody()182 virtual ~btRigidBody() 183 { 184 //No constraints should point to this rigidbody 185 //Remove constraints from the dynamics world before you delete the related rigidbodies. 186 btAssert(m_constraintRefs.size()==0); 187 } 188 189 protected: 190 191 ///setupRigidBody is only used internally by the constructor 192 void setupRigidBody(const btRigidBodyConstructionInfo& constructionInfo); 193 194 public: 195 196 void proceedToTransform(const btTransform& newTrans); 197 198 ///to keep collision detection and dynamics separate we don't store a rigidbody pointer 199 ///but a rigidbody is derived from btCollisionObject, so we can safely perform an upcast upcast(const btCollisionObject * colObj)200 static const btRigidBody* upcast(const btCollisionObject* colObj) 201 { 202 if (colObj->getInternalType()&btCollisionObject::CO_RIGID_BODY) 203 return (const btRigidBody*)colObj; 204 return 0; 205 } upcast(btCollisionObject * colObj)206 static btRigidBody* upcast(btCollisionObject* colObj) 207 { 208 if (colObj->getInternalType()&btCollisionObject::CO_RIGID_BODY) 209 return (btRigidBody*)colObj; 210 return 0; 211 } 212 213 /// continuous collision detection needs prediction 214 void predictIntegratedTransform(btScalar step, btTransform& predictedTransform) ; 215 216 void saveKinematicState(btScalar step); 217 218 void applyGravity(); 219 220 void setGravity(const btVector3& acceleration); 221 getGravity()222 const btVector3& getGravity() const 223 { 224 return m_gravity_acceleration; 225 } 226 227 void setDamping(btScalar lin_damping, btScalar ang_damping); 228 getLinearDamping()229 btScalar getLinearDamping() const 230 { 231 return m_linearDamping; 232 } 233 getAngularDamping()234 btScalar getAngularDamping() const 235 { 236 return m_angularDamping; 237 } 238 getLinearSleepingThreshold()239 btScalar getLinearSleepingThreshold() const 240 { 241 return m_linearSleepingThreshold; 242 } 243 getAngularSleepingThreshold()244 btScalar getAngularSleepingThreshold() const 245 { 246 return m_angularSleepingThreshold; 247 } 248 249 void applyDamping(btScalar timeStep); 250 getCollisionShape()251 SIMD_FORCE_INLINE const btCollisionShape* getCollisionShape() const { 252 return m_collisionShape; 253 } 254 getCollisionShape()255 SIMD_FORCE_INLINE btCollisionShape* getCollisionShape() { 256 return m_collisionShape; 257 } 258 259 void setMassProps(btScalar mass, const btVector3& inertia); 260 getLinearFactor()261 const btVector3& getLinearFactor() const 262 { 263 return m_linearFactor; 264 } setLinearFactor(const btVector3 & linearFactor)265 void setLinearFactor(const btVector3& linearFactor) 266 { 267 m_linearFactor = linearFactor; 268 m_invMass = m_linearFactor*m_inverseMass; 269 } getInvMass()270 btScalar getInvMass() const { return m_inverseMass; } getInvInertiaTensorWorld()271 const btMatrix3x3& getInvInertiaTensorWorld() const { 272 return m_invInertiaTensorWorld; 273 } 274 275 void integrateVelocities(btScalar step); 276 277 void setCenterOfMassTransform(const btTransform& xform); 278 applyCentralForce(const btVector3 & force)279 void applyCentralForce(const btVector3& force) 280 { 281 m_totalForce += force*m_linearFactor; 282 } 283 getTotalForce()284 const btVector3& getTotalForce() const 285 { 286 return m_totalForce; 287 }; 288 getTotalTorque()289 const btVector3& getTotalTorque() const 290 { 291 return m_totalTorque; 292 }; 293 getInvInertiaDiagLocal()294 const btVector3& getInvInertiaDiagLocal() const 295 { 296 return m_invInertiaLocal; 297 }; 298 setInvInertiaDiagLocal(const btVector3 & diagInvInertia)299 void setInvInertiaDiagLocal(const btVector3& diagInvInertia) 300 { 301 m_invInertiaLocal = diagInvInertia; 302 } 303 setSleepingThresholds(btScalar linear,btScalar angular)304 void setSleepingThresholds(btScalar linear,btScalar angular) 305 { 306 m_linearSleepingThreshold = linear; 307 m_angularSleepingThreshold = angular; 308 } 309 applyTorque(const btVector3 & torque)310 void applyTorque(const btVector3& torque) 311 { 312 m_totalTorque += torque*m_angularFactor; 313 } 314 applyForce(const btVector3 & force,const btVector3 & rel_pos)315 void applyForce(const btVector3& force, const btVector3& rel_pos) 316 { 317 applyCentralForce(force); 318 applyTorque(rel_pos.cross(force*m_linearFactor)); 319 } 320 applyCentralImpulse(const btVector3 & impulse)321 void applyCentralImpulse(const btVector3& impulse) 322 { 323 m_linearVelocity += impulse *m_linearFactor * m_inverseMass; 324 } 325 applyTorqueImpulse(const btVector3 & torque)326 void applyTorqueImpulse(const btVector3& torque) 327 { 328 m_angularVelocity += m_invInertiaTensorWorld * torque * m_angularFactor; 329 } 330 applyImpulse(const btVector3 & impulse,const btVector3 & rel_pos)331 void applyImpulse(const btVector3& impulse, const btVector3& rel_pos) 332 { 333 if (m_inverseMass != btScalar(0.)) 334 { 335 applyCentralImpulse(impulse); 336 if (m_angularFactor) 337 { 338 applyTorqueImpulse(rel_pos.cross(impulse*m_linearFactor)); 339 } 340 } 341 } 342 clearForces()343 void clearForces() 344 { 345 m_totalForce.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)); 346 m_totalTorque.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)); 347 } 348 349 void updateInertiaTensor(); 350 getCenterOfMassPosition()351 const btVector3& getCenterOfMassPosition() const { 352 return m_worldTransform.getOrigin(); 353 } 354 btQuaternion getOrientation() const; 355 getCenterOfMassTransform()356 const btTransform& getCenterOfMassTransform() const { 357 return m_worldTransform; 358 } getLinearVelocity()359 const btVector3& getLinearVelocity() const { 360 return m_linearVelocity; 361 } getAngularVelocity()362 const btVector3& getAngularVelocity() const { 363 return m_angularVelocity; 364 } 365 366 setLinearVelocity(const btVector3 & lin_vel)367 inline void setLinearVelocity(const btVector3& lin_vel) 368 { 369 m_updateRevision++; 370 m_linearVelocity = lin_vel; 371 } 372 setAngularVelocity(const btVector3 & ang_vel)373 inline void setAngularVelocity(const btVector3& ang_vel) 374 { 375 m_updateRevision++; 376 m_angularVelocity = ang_vel; 377 } 378 getVelocityInLocalPoint(const btVector3 & rel_pos)379 btVector3 getVelocityInLocalPoint(const btVector3& rel_pos) const 380 { 381 //we also calculate lin/ang velocity for kinematic objects 382 return m_linearVelocity + m_angularVelocity.cross(rel_pos); 383 384 //for kinematic objects, we could also use use: 385 // return (m_worldTransform(rel_pos) - m_interpolationWorldTransform(rel_pos)) / m_kinematicTimeStep; 386 } 387 translate(const btVector3 & v)388 void translate(const btVector3& v) 389 { 390 m_worldTransform.getOrigin() += v; 391 } 392 393 394 void getAabb(btVector3& aabbMin,btVector3& aabbMax) const; 395 396 397 398 399 computeImpulseDenominator(const btVector3 & pos,const btVector3 & normal)400 SIMD_FORCE_INLINE btScalar computeImpulseDenominator(const btVector3& pos, const btVector3& normal) const 401 { 402 btVector3 r0 = pos - getCenterOfMassPosition(); 403 404 btVector3 c0 = (r0).cross(normal); 405 406 btVector3 vec = (c0 * getInvInertiaTensorWorld()).cross(r0); 407 408 return m_inverseMass + normal.dot(vec); 409 410 } 411 computeAngularImpulseDenominator(const btVector3 & axis)412 SIMD_FORCE_INLINE btScalar computeAngularImpulseDenominator(const btVector3& axis) const 413 { 414 btVector3 vec = axis * getInvInertiaTensorWorld(); 415 return axis.dot(vec); 416 } 417 updateDeactivation(btScalar timeStep)418 SIMD_FORCE_INLINE void updateDeactivation(btScalar timeStep) 419 { 420 if ( (getActivationState() == ISLAND_SLEEPING) || (getActivationState() == DISABLE_DEACTIVATION)) 421 return; 422 423 if ((getLinearVelocity().length2() < m_linearSleepingThreshold*m_linearSleepingThreshold) && 424 (getAngularVelocity().length2() < m_angularSleepingThreshold*m_angularSleepingThreshold)) 425 { 426 m_deactivationTime += timeStep; 427 } else 428 { 429 m_deactivationTime=btScalar(0.); 430 setActivationState(0); 431 } 432 433 } 434 wantsSleeping()435 SIMD_FORCE_INLINE bool wantsSleeping() 436 { 437 438 if (getActivationState() == DISABLE_DEACTIVATION) 439 return false; 440 441 //disable deactivation 442 if (gDisableDeactivation || (gDeactivationTime == btScalar(0.))) 443 return false; 444 445 if ( (getActivationState() == ISLAND_SLEEPING) || (getActivationState() == WANTS_DEACTIVATION)) 446 return true; 447 448 if (m_deactivationTime> gDeactivationTime) 449 { 450 return true; 451 } 452 return false; 453 } 454 455 456 getBroadphaseProxy()457 const btBroadphaseProxy* getBroadphaseProxy() const 458 { 459 return m_broadphaseHandle; 460 } getBroadphaseProxy()461 btBroadphaseProxy* getBroadphaseProxy() 462 { 463 return m_broadphaseHandle; 464 } setNewBroadphaseProxy(btBroadphaseProxy * broadphaseProxy)465 void setNewBroadphaseProxy(btBroadphaseProxy* broadphaseProxy) 466 { 467 m_broadphaseHandle = broadphaseProxy; 468 } 469 470 //btMotionState allows to automatic synchronize the world transform for active objects getMotionState()471 btMotionState* getMotionState() 472 { 473 return m_optionalMotionState; 474 } getMotionState()475 const btMotionState* getMotionState() const 476 { 477 return m_optionalMotionState; 478 } setMotionState(btMotionState * motionState)479 void setMotionState(btMotionState* motionState) 480 { 481 m_optionalMotionState = motionState; 482 if (m_optionalMotionState) 483 motionState->getWorldTransform(m_worldTransform); 484 } 485 486 //for experimental overriding of friction/contact solver func 487 int m_contactSolverType; 488 int m_frictionSolverType; 489 setAngularFactor(const btVector3 & angFac)490 void setAngularFactor(const btVector3& angFac) 491 { 492 m_updateRevision++; 493 m_angularFactor = angFac; 494 } 495 setAngularFactor(btScalar angFac)496 void setAngularFactor(btScalar angFac) 497 { 498 m_updateRevision++; 499 m_angularFactor.setValue(angFac,angFac,angFac); 500 } getAngularFactor()501 const btVector3& getAngularFactor() const 502 { 503 return m_angularFactor; 504 } 505 506 //is this rigidbody added to a btCollisionWorld/btDynamicsWorld/btBroadphase? isInWorld()507 bool isInWorld() const 508 { 509 return (getBroadphaseProxy() != 0); 510 } 511 512 void addConstraintRef(btTypedConstraint* c); 513 void removeConstraintRef(btTypedConstraint* c); 514 getConstraintRef(int index)515 btTypedConstraint* getConstraintRef(int index) 516 { 517 return m_constraintRefs[index]; 518 } 519 getNumConstraintRefs()520 int getNumConstraintRefs() const 521 { 522 return m_constraintRefs.size(); 523 } 524 setFlags(int flags)525 void setFlags(int flags) 526 { 527 m_rigidbodyFlags = flags; 528 } 529 getFlags()530 int getFlags() const 531 { 532 return m_rigidbodyFlags; 533 } 534 535 536 537 538 ///perform implicit force computation in world space 539 btVector3 computeGyroscopicImpulseImplicit_World(btScalar dt) const; 540 541 ///perform implicit force computation in body space (inertial frame) 542 btVector3 computeGyroscopicImpulseImplicit_Body(btScalar step) const; 543 544 ///explicit version is best avoided, it gains energy 545 btVector3 computeGyroscopicForceExplicit(btScalar maxGyroscopicForce) const; 546 btVector3 getLocalInertia() const; 547 548 /////////////////////////////////////////////// 549 550 virtual int calculateSerializeBufferSize() const; 551 552 ///fills the dataBuffer and returns the struct name (and 0 on failure) 553 virtual const char* serialize(void* dataBuffer, class btSerializer* serializer) const; 554 555 virtual void serializeSingleObject(class btSerializer* serializer) const; 556 557 }; 558 559 //@todo add m_optionalMotionState and m_constraintRefs to btRigidBodyData 560 ///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 561 struct btRigidBodyFloatData 562 { 563 btCollisionObjectFloatData m_collisionObjectData; 564 btMatrix3x3FloatData m_invInertiaTensorWorld; 565 btVector3FloatData m_linearVelocity; 566 btVector3FloatData m_angularVelocity; 567 btVector3FloatData m_angularFactor; 568 btVector3FloatData m_linearFactor; 569 btVector3FloatData m_gravity; 570 btVector3FloatData m_gravity_acceleration; 571 btVector3FloatData m_invInertiaLocal; 572 btVector3FloatData m_totalForce; 573 btVector3FloatData m_totalTorque; 574 float m_inverseMass; 575 float m_linearDamping; 576 float m_angularDamping; 577 float m_additionalDampingFactor; 578 float m_additionalLinearDampingThresholdSqr; 579 float m_additionalAngularDampingThresholdSqr; 580 float m_additionalAngularDampingFactor; 581 float m_linearSleepingThreshold; 582 float m_angularSleepingThreshold; 583 int m_additionalDamping; 584 }; 585 586 ///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 587 struct btRigidBodyDoubleData 588 { 589 btCollisionObjectDoubleData m_collisionObjectData; 590 btMatrix3x3DoubleData m_invInertiaTensorWorld; 591 btVector3DoubleData m_linearVelocity; 592 btVector3DoubleData m_angularVelocity; 593 btVector3DoubleData m_angularFactor; 594 btVector3DoubleData m_linearFactor; 595 btVector3DoubleData m_gravity; 596 btVector3DoubleData m_gravity_acceleration; 597 btVector3DoubleData m_invInertiaLocal; 598 btVector3DoubleData m_totalForce; 599 btVector3DoubleData m_totalTorque; 600 double m_inverseMass; 601 double m_linearDamping; 602 double m_angularDamping; 603 double m_additionalDampingFactor; 604 double m_additionalLinearDampingThresholdSqr; 605 double m_additionalAngularDampingThresholdSqr; 606 double m_additionalAngularDampingFactor; 607 double m_linearSleepingThreshold; 608 double m_angularSleepingThreshold; 609 int m_additionalDamping; 610 char m_padding[4]; 611 }; 612 613 614 615 #endif //BT_RIGIDBODY_H 616 617