2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2006 Erwin Coumans https://bulletphysics.org
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:
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.
16 #ifndef BT_RIGIDBODY_H
17 #define BT_RIGIDBODY_H
19 #include "LinearMath/btAlignedObjectArray.h"
20 #include "LinearMath/btTransform.h"
21 #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
22 #include "BulletCollision/CollisionDispatch/btCollisionObject.h"
24 class btCollisionShape;
26 class btTypedConstraint;
28 extern btScalar gDeactivationTime;
29 extern bool gDisableDeactivation;
31 #ifdef BT_USE_DOUBLE_PRECISION
32 #define btRigidBodyData btRigidBodyDoubleData
33 #define btRigidBodyDataName "btRigidBodyDoubleData"
35 #define btRigidBodyData btRigidBodyFloatData
36 #define btRigidBodyDataName "btRigidBodyFloatData"
37 #endif //BT_USE_DOUBLE_PRECISION
41 BT_DISABLE_WORLD_GRAVITY = 1,
42 ///BT_ENABLE_GYROPSCOPIC_FORCE flags is enabled by default in Bullet 2.83 and onwards.
43 ///and it BT_ENABLE_GYROPSCOPIC_FORCE becomes equivalent to BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_BODY
44 ///See Demos/GyroscopicDemo and computeGyroscopicImpulseImplicit
45 BT_ENABLE_GYROSCOPIC_FORCE_EXPLICIT = 2,
46 BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_WORLD = 4,
47 BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_BODY = 8,
48 BT_ENABLE_GYROPSCOPIC_FORCE = BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_BODY,
51 ///The btRigidBody is the main class for rigid body objects. It is derived from btCollisionObject, so it keeps a pointer to a btCollisionShape.
52 ///It is recommended for performance and memory use to share btCollisionShape objects whenever possible.
53 ///There are 3 types of rigid bodies:
54 ///- A) Dynamic rigid bodies, with positive mass. Motion is controlled by rigid body dynamics.
55 ///- B) Fixed objects with zero mass. They are not moving (basically collision objects)
56 ///- C) Kinematic objects, which are objects without mass, but the user can move them. There is one-way interaction, and Bullet calculates a velocity based on the timestep and previous and current world transform.
57 ///Bullet automatically deactivates dynamic rigid bodies, when the velocity is below a threshold for a given time.
58 ///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)
59 class btRigidBody : public btCollisionObject
61 btMatrix3x3 m_invInertiaTensorWorld;
62 btVector3 m_linearVelocity;
63 btVector3 m_angularVelocity;
64 btScalar m_inverseMass;
65 btVector3 m_linearFactor;
68 btVector3 m_gravity_acceleration;
69 btVector3 m_invInertiaLocal;
70 btVector3 m_totalForce;
71 btVector3 m_totalTorque;
73 btScalar m_linearDamping;
74 btScalar m_angularDamping;
76 bool m_additionalDamping;
77 btScalar m_additionalDampingFactor;
78 btScalar m_additionalLinearDampingThresholdSqr;
79 btScalar m_additionalAngularDampingThresholdSqr;
80 btScalar m_additionalAngularDampingFactor;
82 btScalar m_linearSleepingThreshold;
83 btScalar m_angularSleepingThreshold;
85 //m_optionalMotionState allows to automatic synchronize the world transform for active objects
86 btMotionState* m_optionalMotionState;
88 //keep track of typed constraints referencing this rigid body, to disable collision between linked bodies
89 btAlignedObjectArray<btTypedConstraint*> m_constraintRefs;
96 ATTRIBUTE_ALIGNED16(btVector3 m_deltaLinearVelocity);
97 btVector3 m_deltaAngularVelocity;
98 btVector3 m_angularFactor;
100 btVector3 m_pushVelocity;
101 btVector3 m_turnVelocity;
104 ///The btRigidBodyConstructionInfo structure provides information to create a rigid body. Setting mass to zero creates a fixed (non-dynamic) rigid body.
105 ///For dynamic objects, you can use the collision shape to approximate the local inertia tensor, otherwise use the zero vector (default argument)
106 ///You can use the motion state to synchronize the world transform between physics and graphics objects.
107 ///And if the motion state is provided, the rigid body will initialize its initial world transform from the motion state,
108 ///m_startWorldTransform is only used when you don't provide a motion state.
109 struct btRigidBodyConstructionInfo
113 ///When a motionState is provided, the rigid body will initialize its world transform from the motion state
114 ///In this case, m_startWorldTransform is ignored.
115 btMotionState* m_motionState;
116 btTransform m_startWorldTransform;
118 btCollisionShape* m_collisionShape;
119 btVector3 m_localInertia;
120 btScalar m_linearDamping;
121 btScalar m_angularDamping;
123 ///best simulation results when friction is non-zero
125 ///the m_rollingFriction prevents rounded shapes, such as spheres, cylinders and capsules from rolling forever.
126 ///See Bullet/Demos/RollingFrictionDemo for usage
127 btScalar m_rollingFriction;
128 btScalar m_spinningFriction; //torsional friction around contact normal
130 ///best simulation results using zero restitution.
131 btScalar m_restitution;
133 btScalar m_linearSleepingThreshold;
134 btScalar m_angularSleepingThreshold;
136 //Additional damping can help avoiding lowpass jitter motion, help stability for ragdolls etc.
137 //Such damping is undesirable, so once the overall simulation quality of the rigid body dynamics system has improved, this should become obsolete
138 bool m_additionalDamping;
139 btScalar m_additionalDampingFactor;
140 btScalar m_additionalLinearDampingThresholdSqr;
141 btScalar m_additionalAngularDampingThresholdSqr;
142 btScalar m_additionalAngularDampingFactor;
144 btRigidBodyConstructionInfo(btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia = btVector3(0, 0, 0)) : m_mass(mass),
145 m_motionState(motionState),
146 m_collisionShape(collisionShape),
147 m_localInertia(localInertia),
148 m_linearDamping(btScalar(0.)),
149 m_angularDamping(btScalar(0.)),
150 m_friction(btScalar(0.5)),
151 m_rollingFriction(btScalar(0)),
152 m_spinningFriction(btScalar(0)),
153 m_restitution(btScalar(0.)),
154 m_linearSleepingThreshold(btScalar(0.8)),
155 m_angularSleepingThreshold(btScalar(1.f)),
156 m_additionalDamping(false),
157 m_additionalDampingFactor(btScalar(0.005)),
158 m_additionalLinearDampingThresholdSqr(btScalar(0.01)),
159 m_additionalAngularDampingThresholdSqr(btScalar(0.01)),
160 m_additionalAngularDampingFactor(btScalar(0.01))
162 m_startWorldTransform.setIdentity();
166 ///btRigidBody constructor using construction info
167 btRigidBody(const btRigidBodyConstructionInfo& constructionInfo);
169 ///btRigidBody constructor for backwards compatibility.
170 ///To specify friction (etc) during rigid body construction, please use the other constructor (using btRigidBodyConstructionInfo)
171 btRigidBody(btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia = btVector3(0, 0, 0));
173 virtual ~btRigidBody()
175 //No constraints should point to this rigidbody
176 //Remove constraints from the dynamics world before you delete the related rigidbodies.
177 btAssert(m_constraintRefs.size() == 0);
181 ///setupRigidBody is only used internally by the constructor
182 void setupRigidBody(const btRigidBodyConstructionInfo& constructionInfo);
185 void proceedToTransform(const btTransform& newTrans);
187 ///to keep collision detection and dynamics separate we don't store a rigidbody pointer
188 ///but a rigidbody is derived from btCollisionObject, so we can safely perform an upcast
189 static const btRigidBody* upcast(const btCollisionObject* colObj)
191 if (colObj->getInternalType() & btCollisionObject::CO_RIGID_BODY)
192 return (const btRigidBody*)colObj;
195 static btRigidBody* upcast(btCollisionObject* colObj)
197 if (colObj->getInternalType() & btCollisionObject::CO_RIGID_BODY)
198 return (btRigidBody*)colObj;
202 /// continuous collision detection needs prediction
203 void predictIntegratedTransform(btScalar step, btTransform& predictedTransform);
205 void saveKinematicState(btScalar step);
211 void setGravity(const btVector3& acceleration);
213 const btVector3& getGravity() const
215 return m_gravity_acceleration;
218 void setDamping(btScalar lin_damping, btScalar ang_damping);
220 btScalar getLinearDamping() const
222 return m_linearDamping;
225 btScalar getAngularDamping() const
227 return m_angularDamping;
230 btScalar getLinearSleepingThreshold() const
232 return m_linearSleepingThreshold;
235 btScalar getAngularSleepingThreshold() const
237 return m_angularSleepingThreshold;
240 void applyDamping(btScalar timeStep);
242 SIMD_FORCE_INLINE const btCollisionShape* getCollisionShape() const
244 return m_collisionShape;
247 SIMD_FORCE_INLINE btCollisionShape* getCollisionShape()
249 return m_collisionShape;
252 void setMassProps(btScalar mass, const btVector3& inertia);
254 const btVector3& getLinearFactor() const
256 return m_linearFactor;
258 void setLinearFactor(const btVector3& linearFactor)
260 m_linearFactor = linearFactor;
261 m_invMass = m_linearFactor * m_inverseMass;
263 btScalar getInvMass() const { return m_inverseMass; }
264 btScalar getMass() const { return m_inverseMass == btScalar(0.) ? btScalar(0.) : btScalar(1.0) / m_inverseMass; }
265 const btMatrix3x3& getInvInertiaTensorWorld() const
267 return m_invInertiaTensorWorld;
270 void integrateVelocities(btScalar step);
272 void setCenterOfMassTransform(const btTransform& xform);
274 void applyCentralForce(const btVector3& force)
276 m_totalForce += force * m_linearFactor;
279 const btVector3& getTotalForce() const
284 const btVector3& getTotalTorque() const
286 return m_totalTorque;
289 const btVector3& getInvInertiaDiagLocal() const
291 return m_invInertiaLocal;
294 void setInvInertiaDiagLocal(const btVector3& diagInvInertia)
296 m_invInertiaLocal = diagInvInertia;
299 void setSleepingThresholds(btScalar linear, btScalar angular)
301 m_linearSleepingThreshold = linear;
302 m_angularSleepingThreshold = angular;
305 void applyTorque(const btVector3& torque)
307 m_totalTorque += torque * m_angularFactor;
308 #if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
309 clampVelocity(m_totalTorque);
313 void applyForce(const btVector3& force, const btVector3& rel_pos)
315 applyCentralForce(force);
316 applyTorque(rel_pos.cross(force * m_linearFactor));
319 void applyCentralImpulse(const btVector3& impulse)
321 m_linearVelocity += impulse * m_linearFactor * m_inverseMass;
322 #if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
323 clampVelocity(m_linearVelocity);
327 void applyTorqueImpulse(const btVector3& torque)
329 m_angularVelocity += m_invInertiaTensorWorld * torque * m_angularFactor;
330 #if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
331 clampVelocity(m_angularVelocity);
335 void applyImpulse(const btVector3& impulse, const btVector3& rel_pos)
337 if (m_inverseMass != btScalar(0.))
339 applyCentralImpulse(impulse);
342 applyTorqueImpulse(rel_pos.cross(impulse * m_linearFactor));
347 void applyPushImpulse(const btVector3& impulse, const btVector3& rel_pos)
349 if (m_inverseMass != btScalar(0.))
351 applyCentralPushImpulse(impulse);
354 applyTorqueTurnImpulse(rel_pos.cross(impulse * m_linearFactor));
359 btVector3 getPushVelocity() const
361 return m_pushVelocity;
364 btVector3 getTurnVelocity() const
366 return m_turnVelocity;
369 void setPushVelocity(const btVector3& v)
374 #if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
375 void clampVelocity(btVector3& v) const {
377 fmax(-BT_CLAMP_VELOCITY_TO,
378 fmin(BT_CLAMP_VELOCITY_TO, v.getX()))
381 fmax(-BT_CLAMP_VELOCITY_TO,
382 fmin(BT_CLAMP_VELOCITY_TO, v.getY()))
385 fmax(-BT_CLAMP_VELOCITY_TO,
386 fmin(BT_CLAMP_VELOCITY_TO, v.getZ()))
391 void setTurnVelocity(const btVector3& v)
394 #if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
395 clampVelocity(m_turnVelocity);
399 void applyCentralPushImpulse(const btVector3& impulse)
401 m_pushVelocity += impulse * m_linearFactor * m_inverseMass;
402 #if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
403 clampVelocity(m_pushVelocity);
407 void applyTorqueTurnImpulse(const btVector3& torque)
409 m_turnVelocity += m_invInertiaTensorWorld * torque * m_angularFactor;
410 #if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
411 clampVelocity(m_turnVelocity);
417 m_totalForce.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
418 m_totalTorque.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
421 void updateInertiaTensor();
423 const btVector3& getCenterOfMassPosition() const
425 return m_worldTransform.getOrigin();
427 btQuaternion getOrientation() const;
429 const btTransform& getCenterOfMassTransform() const
431 return m_worldTransform;
433 const btVector3& getLinearVelocity() const
435 return m_linearVelocity;
437 const btVector3& getAngularVelocity() const
439 return m_angularVelocity;
442 inline void setLinearVelocity(const btVector3& lin_vel)
445 m_linearVelocity = lin_vel;
446 #if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
447 clampVelocity(m_linearVelocity);
451 inline void setAngularVelocity(const btVector3& ang_vel)
454 m_angularVelocity = ang_vel;
455 #if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
456 clampVelocity(m_angularVelocity);
460 btVector3 getVelocityInLocalPoint(const btVector3& rel_pos) const
462 //we also calculate lin/ang velocity for kinematic objects
463 return m_linearVelocity + m_angularVelocity.cross(rel_pos);
465 //for kinematic objects, we could also use use:
466 // return (m_worldTransform(rel_pos) - m_interpolationWorldTransform(rel_pos)) / m_kinematicTimeStep;
469 btVector3 getPushVelocityInLocalPoint(const btVector3& rel_pos) const
471 //we also calculate lin/ang velocity for kinematic objects
472 return m_pushVelocity + m_turnVelocity.cross(rel_pos);
475 void translate(const btVector3& v)
477 m_worldTransform.getOrigin() += v;
480 void getAabb(btVector3& aabbMin, btVector3& aabbMax) const;
482 SIMD_FORCE_INLINE btScalar computeImpulseDenominator(const btVector3& pos, const btVector3& normal) const
484 btVector3 r0 = pos - getCenterOfMassPosition();
486 btVector3 c0 = (r0).cross(normal);
488 btVector3 vec = (c0 * getInvInertiaTensorWorld()).cross(r0);
490 return m_inverseMass + normal.dot(vec);
493 SIMD_FORCE_INLINE btScalar computeAngularImpulseDenominator(const btVector3& axis) const
495 btVector3 vec = axis * getInvInertiaTensorWorld();
496 return axis.dot(vec);
499 SIMD_FORCE_INLINE void updateDeactivation(btScalar timeStep)
501 if ((getActivationState() == ISLAND_SLEEPING) || (getActivationState() == DISABLE_DEACTIVATION))
504 if ((getLinearVelocity().length2() < m_linearSleepingThreshold * m_linearSleepingThreshold) &&
505 (getAngularVelocity().length2() < m_angularSleepingThreshold * m_angularSleepingThreshold))
507 m_deactivationTime += timeStep;
511 m_deactivationTime = btScalar(0.);
512 setActivationState(0);
516 SIMD_FORCE_INLINE bool wantsSleeping()
518 if (getActivationState() == DISABLE_DEACTIVATION)
521 //disable deactivation
522 if (gDisableDeactivation || (gDeactivationTime == btScalar(0.)))
525 if ((getActivationState() == ISLAND_SLEEPING) || (getActivationState() == WANTS_DEACTIVATION))
528 if (m_deactivationTime > gDeactivationTime)
535 const btBroadphaseProxy* getBroadphaseProxy() const
537 return m_broadphaseHandle;
539 btBroadphaseProxy* getBroadphaseProxy()
541 return m_broadphaseHandle;
543 void setNewBroadphaseProxy(btBroadphaseProxy* broadphaseProxy)
545 m_broadphaseHandle = broadphaseProxy;
548 //btMotionState allows to automatic synchronize the world transform for active objects
549 btMotionState* getMotionState()
551 return m_optionalMotionState;
553 const btMotionState* getMotionState() const
555 return m_optionalMotionState;
557 void setMotionState(btMotionState* motionState)
559 m_optionalMotionState = motionState;
560 if (m_optionalMotionState)
561 motionState->getWorldTransform(m_worldTransform);
564 //for experimental overriding of friction/contact solver func
565 int m_contactSolverType;
566 int m_frictionSolverType;
568 void setAngularFactor(const btVector3& angFac)
571 m_angularFactor = angFac;
574 void setAngularFactor(btScalar angFac)
577 m_angularFactor.setValue(angFac, angFac, angFac);
579 const btVector3& getAngularFactor() const
581 return m_angularFactor;
584 //is this rigidbody added to a btCollisionWorld/btDynamicsWorld/btBroadphase?
585 bool isInWorld() const
587 return (getBroadphaseProxy() != 0);
590 void addConstraintRef(btTypedConstraint* c);
591 void removeConstraintRef(btTypedConstraint* c);
593 btTypedConstraint* getConstraintRef(int index)
595 return m_constraintRefs[index];
598 int getNumConstraintRefs() const
600 return m_constraintRefs.size();
603 void setFlags(int flags)
605 m_rigidbodyFlags = flags;
610 return m_rigidbodyFlags;
613 ///perform implicit force computation in world space
614 btVector3 computeGyroscopicImpulseImplicit_World(btScalar dt) const;
616 ///perform implicit force computation in body space (inertial frame)
617 btVector3 computeGyroscopicImpulseImplicit_Body(btScalar step) const;
619 ///explicit version is best avoided, it gains energy
620 btVector3 computeGyroscopicForceExplicit(btScalar maxGyroscopicForce) const;
621 btVector3 getLocalInertia() const;
623 ///////////////////////////////////////////////
625 virtual int calculateSerializeBufferSize() const;
627 ///fills the dataBuffer and returns the struct name (and 0 on failure)
628 virtual const char* serialize(void* dataBuffer, class btSerializer* serializer) const;
630 virtual void serializeSingleObject(class btSerializer* serializer) const;
633 //@todo add m_optionalMotionState and m_constraintRefs to btRigidBodyData
634 ///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
635 struct btRigidBodyFloatData
637 btCollisionObjectFloatData m_collisionObjectData;
638 btMatrix3x3FloatData m_invInertiaTensorWorld;
639 btVector3FloatData m_linearVelocity;
640 btVector3FloatData m_angularVelocity;
641 btVector3FloatData m_angularFactor;
642 btVector3FloatData m_linearFactor;
643 btVector3FloatData m_gravity;
644 btVector3FloatData m_gravity_acceleration;
645 btVector3FloatData m_invInertiaLocal;
646 btVector3FloatData m_totalForce;
647 btVector3FloatData m_totalTorque;
649 float m_linearDamping;
650 float m_angularDamping;
651 float m_additionalDampingFactor;
652 float m_additionalLinearDampingThresholdSqr;
653 float m_additionalAngularDampingThresholdSqr;
654 float m_additionalAngularDampingFactor;
655 float m_linearSleepingThreshold;
656 float m_angularSleepingThreshold;
657 int m_additionalDamping;
660 ///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
661 struct btRigidBodyDoubleData
663 btCollisionObjectDoubleData m_collisionObjectData;
664 btMatrix3x3DoubleData m_invInertiaTensorWorld;
665 btVector3DoubleData m_linearVelocity;
666 btVector3DoubleData m_angularVelocity;
667 btVector3DoubleData m_angularFactor;
668 btVector3DoubleData m_linearFactor;
669 btVector3DoubleData m_gravity;
670 btVector3DoubleData m_gravity_acceleration;
671 btVector3DoubleData m_invInertiaLocal;
672 btVector3DoubleData m_totalForce;
673 btVector3DoubleData m_totalTorque;
674 double m_inverseMass;
675 double m_linearDamping;
676 double m_angularDamping;
677 double m_additionalDampingFactor;
678 double m_additionalLinearDampingThresholdSqr;
679 double m_additionalAngularDampingThresholdSqr;
680 double m_additionalAngularDampingFactor;
681 double m_linearSleepingThreshold;
682 double m_angularSleepingThreshold;
683 int m_additionalDamping;
687 #endif //BT_RIGIDBODY_H