2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
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;
29 extern btScalar gDeactivationTime;
30 extern bool gDisableDeactivation;
32 #ifdef BT_USE_DOUBLE_PRECISION
33 #define btRigidBodyData btRigidBodyDoubleData
34 #define btRigidBodyDataName "btRigidBodyDoubleData"
36 #define btRigidBodyData btRigidBodyFloatData
37 #define btRigidBodyDataName "btRigidBodyFloatData"
38 #endif //BT_USE_DOUBLE_PRECISION
43 BT_DISABLE_WORLD_GRAVITY = 1
47 ///The btRigidBody is the main class for rigid body objects. It is derived from btCollisionObject, so it keeps a pointer to a btCollisionShape.
48 ///It is recommended for performance and memory use to share btCollisionShape objects whenever possible.
49 ///There are 3 types of rigid bodies:
50 ///- A) Dynamic rigid bodies, with positive mass. Motion is controlled by rigid body dynamics.
51 ///- B) Fixed objects with zero mass. They are not moving (basically collision objects)
52 ///- 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.
53 ///Bullet automatically deactivates dynamic rigid bodies, when the velocity is below a threshold for a given time.
54 ///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)
55 class btRigidBody : public btCollisionObject
58 btMatrix3x3 m_invInertiaTensorWorld;
59 btVector3 m_linearVelocity;
60 btVector3 m_angularVelocity;
61 btScalar m_inverseMass;
62 btVector3 m_linearFactor;
65 btVector3 m_gravity_acceleration;
66 btVector3 m_invInertiaLocal;
67 btVector3 m_totalForce;
68 btVector3 m_totalTorque;
70 btScalar m_linearDamping;
71 btScalar m_angularDamping;
73 bool m_additionalDamping;
74 btScalar m_additionalDampingFactor;
75 btScalar m_additionalLinearDampingThresholdSqr;
76 btScalar m_additionalAngularDampingThresholdSqr;
77 btScalar m_additionalAngularDampingFactor;
80 btScalar m_linearSleepingThreshold;
81 btScalar m_angularSleepingThreshold;
83 //m_optionalMotionState allows to automatic synchronize the world transform for active objects
84 btMotionState* m_optionalMotionState;
86 //keep track of typed constraints referencing this rigid body
87 btAlignedObjectArray<btTypedConstraint*> m_constraintRefs;
96 ATTRIBUTE_ALIGNED64(btVector3 m_deltaLinearVelocity);
97 btVector3 m_deltaAngularVelocity;
98 btVector3 m_angularFactor;
100 btVector3 m_pushVelocity;
101 btVector3 m_turnVelocity;
107 ///The btRigidBodyConstructionInfo structure provides information to create a rigid body. Setting mass to zero creates a fixed (non-dynamic) rigid body.
108 ///For dynamic objects, you can use the collision shape to approximate the local inertia tensor, otherwise use the zero vector (default argument)
109 ///You can use the motion state to synchronize the world transform between physics and graphics objects.
110 ///And if the motion state is provided, the rigid body will initialize its initial world transform from the motion state,
111 ///m_startWorldTransform is only used when you don't provide a motion state.
112 struct btRigidBodyConstructionInfo
116 ///When a motionState is provided, the rigid body will initialize its world transform from the motion state
117 ///In this case, m_startWorldTransform is ignored.
118 btMotionState* m_motionState;
119 btTransform m_startWorldTransform;
121 btCollisionShape* m_collisionShape;
122 btVector3 m_localInertia;
123 btScalar m_linearDamping;
124 btScalar m_angularDamping;
126 ///best simulation results when friction is non-zero
128 ///best simulation results using zero restitution.
129 btScalar m_restitution;
131 btScalar m_linearSleepingThreshold;
132 btScalar m_angularSleepingThreshold;
134 //Additional damping can help avoiding lowpass jitter motion, help stability for ragdolls etc.
135 //Such damping is undesirable, so once the overall simulation quality of the rigid body dynamics system has improved, this should become obsolete
136 bool m_additionalDamping;
137 btScalar m_additionalDampingFactor;
138 btScalar m_additionalLinearDampingThresholdSqr;
139 btScalar m_additionalAngularDampingThresholdSqr;
140 btScalar m_additionalAngularDampingFactor;
142 btRigidBodyConstructionInfo( btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia=btVector3(0,0,0)):
144 m_motionState(motionState),
145 m_collisionShape(collisionShape),
146 m_localInertia(localInertia),
147 m_linearDamping(btScalar(0.)),
148 m_angularDamping(btScalar(0.)),
149 m_friction(btScalar(0.5)),
150 m_restitution(btScalar(0.)),
151 m_linearSleepingThreshold(btScalar(0.8)),
152 m_angularSleepingThreshold(btScalar(1.f)),
153 m_additionalDamping(false),
154 m_additionalDampingFactor(btScalar(0.005)),
155 m_additionalLinearDampingThresholdSqr(btScalar(0.01)),
156 m_additionalAngularDampingThresholdSqr(btScalar(0.01)),
157 m_additionalAngularDampingFactor(btScalar(0.01))
159 m_startWorldTransform.setIdentity();
163 ///btRigidBody constructor using construction info
164 btRigidBody( const btRigidBodyConstructionInfo& constructionInfo);
166 ///btRigidBody constructor for backwards compatibility.
167 ///To specify friction (etc) during rigid body construction, please use the other constructor (using btRigidBodyConstructionInfo)
168 btRigidBody( btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia=btVector3(0,0,0));
171 virtual ~btRigidBody()
173 //No constraints should point to this rigidbody
174 //Remove constraints from the dynamics world before you delete the related rigidbodies.
175 btAssert(m_constraintRefs.size()==0);
180 ///setupRigidBody is only used internally by the constructor
181 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);
209 void setGravity(const btVector3& acceleration);
211 const btVector3& getGravity() const
213 return m_gravity_acceleration;
216 void setDamping(btScalar lin_damping, btScalar ang_damping);
218 btScalar getLinearDamping() const
220 return m_linearDamping;
223 btScalar getAngularDamping() const
225 return m_angularDamping;
228 btScalar getLinearSleepingThreshold() const
230 return m_linearSleepingThreshold;
233 btScalar getAngularSleepingThreshold() const
235 return m_angularSleepingThreshold;
238 void applyDamping(btScalar timeStep);
240 SIMD_FORCE_INLINE const btCollisionShape* getCollisionShape() const {
241 return m_collisionShape;
244 SIMD_FORCE_INLINE btCollisionShape* getCollisionShape() {
245 return m_collisionShape;
248 void setMassProps(btScalar mass, const btVector3& inertia);
250 const btVector3& getLinearFactor() const
252 return m_linearFactor;
254 void setLinearFactor(const btVector3& linearFactor)
256 m_linearFactor = linearFactor;
257 m_invMass = m_linearFactor*m_inverseMass;
259 btScalar getInvMass() const { return m_inverseMass; }
260 const btMatrix3x3& getInvInertiaTensorWorld() const {
261 return m_invInertiaTensorWorld;
264 void integrateVelocities(btScalar step);
266 void setCenterOfMassTransform(const btTransform& xform);
268 void applyCentralForce(const btVector3& force)
270 m_totalForce += force*m_linearFactor;
273 const btVector3& getTotalForce() const
278 const btVector3& getTotalTorque() const
280 return m_totalTorque;
283 const btVector3& getInvInertiaDiagLocal() const
285 return m_invInertiaLocal;
288 void setInvInertiaDiagLocal(const btVector3& diagInvInertia)
290 m_invInertiaLocal = diagInvInertia;
293 void setSleepingThresholds(btScalar linear,btScalar angular)
295 m_linearSleepingThreshold = linear;
296 m_angularSleepingThreshold = angular;
299 void applyTorque(const btVector3& torque)
301 m_totalTorque += torque*m_angularFactor;
304 void applyForce(const btVector3& force, const btVector3& rel_pos)
306 applyCentralForce(force);
307 applyTorque(rel_pos.cross(force*m_linearFactor));
310 void applyCentralImpulse(const btVector3& impulse)
312 m_linearVelocity += impulse *m_linearFactor * m_inverseMass;
315 void applyTorqueImpulse(const btVector3& torque)
317 m_angularVelocity += m_invInertiaTensorWorld * torque * m_angularFactor;
320 void applyImpulse(const btVector3& impulse, const btVector3& rel_pos)
322 if (m_inverseMass != btScalar(0.))
324 applyCentralImpulse(impulse);
327 applyTorqueImpulse(rel_pos.cross(impulse*m_linearFactor));
334 m_totalForce.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
335 m_totalTorque.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
338 void updateInertiaTensor();
340 const btVector3& getCenterOfMassPosition() const {
341 return m_worldTransform.getOrigin();
343 btQuaternion getOrientation() const;
345 const btTransform& getCenterOfMassTransform() const {
346 return m_worldTransform;
348 const btVector3& getLinearVelocity() const {
349 return m_linearVelocity;
351 const btVector3& getAngularVelocity() const {
352 return m_angularVelocity;
356 inline void setLinearVelocity(const btVector3& lin_vel)
358 m_linearVelocity = lin_vel;
361 inline void setAngularVelocity(const btVector3& ang_vel)
363 m_angularVelocity = ang_vel;
366 btVector3 getVelocityInLocalPoint(const btVector3& rel_pos) const
368 //we also calculate lin/ang velocity for kinematic objects
369 return m_linearVelocity + m_angularVelocity.cross(rel_pos);
371 //for kinematic objects, we could also use use:
372 // return (m_worldTransform(rel_pos) - m_interpolationWorldTransform(rel_pos)) / m_kinematicTimeStep;
375 void translate(const btVector3& v)
377 m_worldTransform.getOrigin() += v;
381 void getAabb(btVector3& aabbMin,btVector3& aabbMax) const;
387 SIMD_FORCE_INLINE btScalar computeImpulseDenominator(const btVector3& pos, const btVector3& normal) const
389 btVector3 r0 = pos - getCenterOfMassPosition();
391 btVector3 c0 = (r0).cross(normal);
393 btVector3 vec = (c0 * getInvInertiaTensorWorld()).cross(r0);
395 return m_inverseMass + normal.dot(vec);
399 SIMD_FORCE_INLINE btScalar computeAngularImpulseDenominator(const btVector3& axis) const
401 btVector3 vec = axis * getInvInertiaTensorWorld();
402 return axis.dot(vec);
405 SIMD_FORCE_INLINE void updateDeactivation(btScalar timeStep)
407 if ( (getActivationState() == ISLAND_SLEEPING) || (getActivationState() == DISABLE_DEACTIVATION))
410 if ((getLinearVelocity().length2() < m_linearSleepingThreshold*m_linearSleepingThreshold) &&
411 (getAngularVelocity().length2() < m_angularSleepingThreshold*m_angularSleepingThreshold))
413 m_deactivationTime += timeStep;
416 m_deactivationTime=btScalar(0.);
417 setActivationState(0);
422 SIMD_FORCE_INLINE bool wantsSleeping()
425 if (getActivationState() == DISABLE_DEACTIVATION)
428 //disable deactivation
429 if (gDisableDeactivation || (gDeactivationTime == btScalar(0.)))
432 if ( (getActivationState() == ISLAND_SLEEPING) || (getActivationState() == WANTS_DEACTIVATION))
435 if (m_deactivationTime> gDeactivationTime)
444 const btBroadphaseProxy* getBroadphaseProxy() const
446 return m_broadphaseHandle;
448 btBroadphaseProxy* getBroadphaseProxy()
450 return m_broadphaseHandle;
452 void setNewBroadphaseProxy(btBroadphaseProxy* broadphaseProxy)
454 m_broadphaseHandle = broadphaseProxy;
457 //btMotionState allows to automatic synchronize the world transform for active objects
458 btMotionState* getMotionState()
460 return m_optionalMotionState;
462 const btMotionState* getMotionState() const
464 return m_optionalMotionState;
466 void setMotionState(btMotionState* motionState)
468 m_optionalMotionState = motionState;
469 if (m_optionalMotionState)
470 motionState->getWorldTransform(m_worldTransform);
473 //for experimental overriding of friction/contact solver func
474 int m_contactSolverType;
475 int m_frictionSolverType;
477 void setAngularFactor(const btVector3& angFac)
479 m_angularFactor = angFac;
482 void setAngularFactor(btScalar angFac)
484 m_angularFactor.setValue(angFac,angFac,angFac);
486 const btVector3& getAngularFactor() const
488 return m_angularFactor;
491 //is this rigidbody added to a btCollisionWorld/btDynamicsWorld/btBroadphase?
492 bool isInWorld() const
494 return (getBroadphaseProxy() != 0);
497 virtual bool checkCollideWithOverride(btCollisionObject* co);
499 void addConstraintRef(btTypedConstraint* c);
500 void removeConstraintRef(btTypedConstraint* c);
502 btTypedConstraint* getConstraintRef(int index)
504 return m_constraintRefs[index];
507 int getNumConstraintRefs() const
509 return m_constraintRefs.size();
512 void setFlags(int flags)
514 m_rigidbodyFlags = flags;
519 return m_rigidbodyFlags;
522 const btVector3& getDeltaLinearVelocity() const
524 return m_deltaLinearVelocity;
527 const btVector3& getDeltaAngularVelocity() const
529 return m_deltaAngularVelocity;
532 const btVector3& getPushVelocity() const
534 return m_pushVelocity;
537 const btVector3& getTurnVelocity() const
539 return m_turnVelocity;
543 ////////////////////////////////////////////////
544 ///some internal methods, don't use them
546 btVector3& internalGetDeltaLinearVelocity()
548 return m_deltaLinearVelocity;
551 btVector3& internalGetDeltaAngularVelocity()
553 return m_deltaAngularVelocity;
556 const btVector3& internalGetAngularFactor() const
558 return m_angularFactor;
561 const btVector3& internalGetInvMass() const
566 btVector3& internalGetPushVelocity()
568 return m_pushVelocity;
571 btVector3& internalGetTurnVelocity()
573 return m_turnVelocity;
576 SIMD_FORCE_INLINE void internalGetVelocityInLocalPointObsolete(const btVector3& rel_pos, btVector3& velocity ) const
578 velocity = getLinearVelocity()+m_deltaLinearVelocity + (getAngularVelocity()+m_deltaAngularVelocity).cross(rel_pos);
581 SIMD_FORCE_INLINE void internalGetAngularVelocity(btVector3& angVel) const
583 angVel = getAngularVelocity()+m_deltaAngularVelocity;
587 //Optimization for the iterative solver: avoid calculating constant terms involving inertia, normal, relative position
588 SIMD_FORCE_INLINE void internalApplyImpulse(const btVector3& linearComponent, const btVector3& angularComponent,const btScalar impulseMagnitude)
592 m_deltaLinearVelocity += linearComponent*impulseMagnitude;
593 m_deltaAngularVelocity += angularComponent*(impulseMagnitude*m_angularFactor);
597 SIMD_FORCE_INLINE void internalApplyPushImpulse(const btVector3& linearComponent, const btVector3& angularComponent,btScalar impulseMagnitude)
601 m_pushVelocity += linearComponent*impulseMagnitude;
602 m_turnVelocity += angularComponent*(impulseMagnitude*m_angularFactor);
606 void internalWritebackVelocity()
610 setLinearVelocity(getLinearVelocity()+ m_deltaLinearVelocity);
611 setAngularVelocity(getAngularVelocity()+m_deltaAngularVelocity);
612 //m_deltaLinearVelocity.setZero();
613 //m_deltaAngularVelocity .setZero();
614 //m_originalBody->setCompanionId(-1);
619 void internalWritebackVelocity(btScalar timeStep);
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;
634 //@todo add m_optionalMotionState and m_constraintRefs to btRigidBodyData
635 ///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
636 struct btRigidBodyFloatData
638 btCollisionObjectFloatData m_collisionObjectData;
639 btMatrix3x3FloatData m_invInertiaTensorWorld;
640 btVector3FloatData m_linearVelocity;
641 btVector3FloatData m_angularVelocity;
642 btVector3FloatData m_angularFactor;
643 btVector3FloatData m_linearFactor;
644 btVector3FloatData m_gravity;
645 btVector3FloatData m_gravity_acceleration;
646 btVector3FloatData m_invInertiaLocal;
647 btVector3FloatData m_totalForce;
648 btVector3FloatData m_totalTorque;
650 float m_linearDamping;
651 float m_angularDamping;
652 float m_additionalDampingFactor;
653 float m_additionalLinearDampingThresholdSqr;
654 float m_additionalAngularDampingThresholdSqr;
655 float m_additionalAngularDampingFactor;
656 float m_linearSleepingThreshold;
657 float m_angularSleepingThreshold;
658 int m_additionalDamping;
661 ///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
662 struct btRigidBodyDoubleData
664 btCollisionObjectDoubleData m_collisionObjectData;
665 btMatrix3x3DoubleData m_invInertiaTensorWorld;
666 btVector3DoubleData m_linearVelocity;
667 btVector3DoubleData m_angularVelocity;
668 btVector3DoubleData m_angularFactor;
669 btVector3DoubleData m_linearFactor;
670 btVector3DoubleData m_gravity;
671 btVector3DoubleData m_gravity_acceleration;
672 btVector3DoubleData m_invInertiaLocal;
673 btVector3DoubleData m_totalForce;
674 btVector3DoubleData m_totalTorque;
675 double m_inverseMass;
676 double m_linearDamping;
677 double m_angularDamping;
678 double m_additionalDampingFactor;
679 double m_additionalLinearDampingThresholdSqr;
680 double m_additionalAngularDampingThresholdSqr;
681 double m_additionalAngularDampingFactor;
682 double m_linearSleepingThreshold;
683 double m_angularSleepingThreshold;
684 int m_additionalDamping;
690 #endif //BT_RIGIDBODY_H