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,
44 ///The BT_ENABLE_GYROPSCOPIC_FORCE can easily introduce instability
45 ///So generally it is best to not enable it.
46 ///If really needed, run at a high frequency like 1000 Hertz: ///See Demos/GyroscopicDemo for an example use
47 BT_ENABLE_GYROPSCOPIC_FORCE = 2
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 on-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
62 btMatrix3x3 m_invInertiaTensorWorld;
63 btVector3 m_linearVelocity;
64 btVector3 m_angularVelocity;
65 btScalar m_inverseMass;
66 btVector3 m_linearFactor;
69 btVector3 m_gravity_acceleration;
70 btVector3 m_invInertiaLocal;
71 btVector3 m_totalForce;
72 btVector3 m_totalTorque;
74 btScalar m_linearDamping;
75 btScalar m_angularDamping;
77 bool m_additionalDamping;
78 btScalar m_additionalDampingFactor;
79 btScalar m_additionalLinearDampingThresholdSqr;
80 btScalar m_additionalAngularDampingThresholdSqr;
81 btScalar m_additionalAngularDampingFactor;
84 btScalar m_linearSleepingThreshold;
85 btScalar m_angularSleepingThreshold;
87 //m_optionalMotionState allows to automatic synchronize the world transform for active objects
88 btMotionState* m_optionalMotionState;
90 //keep track of typed constraints referencing this rigid body
91 btAlignedObjectArray<btTypedConstraint*> m_constraintRefs;
100 ATTRIBUTE_ALIGNED64(btVector3 m_deltaLinearVelocity);
101 btVector3 m_deltaAngularVelocity;
102 btVector3 m_angularFactor;
104 btVector3 m_pushVelocity;
105 btVector3 m_turnVelocity;
111 ///The btRigidBodyConstructionInfo structure provides information to create a rigid body. Setting mass to zero creates a fixed (non-dynamic) rigid body.
112 ///For dynamic objects, you can use the collision shape to approximate the local inertia tensor, otherwise use the zero vector (default argument)
113 ///You can use the motion state to synchronize the world transform between physics and graphics objects.
114 ///And if the motion state is provided, the rigid body will initialize its initial world transform from the motion state,
115 ///m_startWorldTransform is only used when you don't provide a motion state.
116 struct btRigidBodyConstructionInfo
120 ///When a motionState is provided, the rigid body will initialize its world transform from the motion state
121 ///In this case, m_startWorldTransform is ignored.
122 btMotionState* m_motionState;
123 btTransform m_startWorldTransform;
125 btCollisionShape* m_collisionShape;
126 btVector3 m_localInertia;
127 btScalar m_linearDamping;
128 btScalar m_angularDamping;
130 ///best simulation results when friction is non-zero
132 ///the m_rollingFriction prevents rounded shapes, such as spheres, cylinders and capsules from rolling forever.
133 ///See Bullet/Demos/RollingFrictionDemo for usage
134 btScalar m_rollingFriction;
135 ///best simulation results using zero restitution.
136 btScalar m_restitution;
138 btScalar m_linearSleepingThreshold;
139 btScalar m_angularSleepingThreshold;
141 //Additional damping can help avoiding lowpass jitter motion, help stability for ragdolls etc.
142 //Such damping is undesirable, so once the overall simulation quality of the rigid body dynamics system has improved, this should become obsolete
143 bool m_additionalDamping;
144 btScalar m_additionalDampingFactor;
145 btScalar m_additionalLinearDampingThresholdSqr;
146 btScalar m_additionalAngularDampingThresholdSqr;
147 btScalar m_additionalAngularDampingFactor;
149 btRigidBodyConstructionInfo( btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia=btVector3(0,0,0)):
151 m_motionState(motionState),
152 m_collisionShape(collisionShape),
153 m_localInertia(localInertia),
154 m_linearDamping(btScalar(0.)),
155 m_angularDamping(btScalar(0.)),
156 m_friction(btScalar(0.5)),
157 m_rollingFriction(btScalar(0)),
158 m_restitution(btScalar(0.)),
159 m_linearSleepingThreshold(btScalar(0.8)),
160 m_angularSleepingThreshold(btScalar(1.f)),
161 m_additionalDamping(false),
162 m_additionalDampingFactor(btScalar(0.005)),
163 m_additionalLinearDampingThresholdSqr(btScalar(0.01)),
164 m_additionalAngularDampingThresholdSqr(btScalar(0.01)),
165 m_additionalAngularDampingFactor(btScalar(0.01))
167 m_startWorldTransform.setIdentity();
171 ///btRigidBody constructor using construction info
172 btRigidBody( const btRigidBodyConstructionInfo& constructionInfo);
174 ///btRigidBody constructor for backwards compatibility.
175 ///To specify friction (etc) during rigid body construction, please use the other constructor (using btRigidBodyConstructionInfo)
176 btRigidBody( btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia=btVector3(0,0,0));
179 virtual ~btRigidBody()
181 //No constraints should point to this rigidbody
182 //Remove constraints from the dynamics world before you delete the related rigidbodies.
183 btAssert(m_constraintRefs.size()==0);
188 ///setupRigidBody is only used internally by the constructor
189 void setupRigidBody(const btRigidBodyConstructionInfo& constructionInfo);
193 void proceedToTransform(const btTransform& newTrans);
195 ///to keep collision detection and dynamics separate we don't store a rigidbody pointer
196 ///but a rigidbody is derived from btCollisionObject, so we can safely perform an upcast
197 static const btRigidBody* upcast(const btCollisionObject* colObj)
199 if (colObj->getInternalType()&btCollisionObject::CO_RIGID_BODY)
200 return (const btRigidBody*)colObj;
203 static btRigidBody* upcast(btCollisionObject* colObj)
205 if (colObj->getInternalType()&btCollisionObject::CO_RIGID_BODY)
206 return (btRigidBody*)colObj;
210 /// continuous collision detection needs prediction
211 void predictIntegratedTransform(btScalar step, btTransform& predictedTransform) ;
213 void saveKinematicState(btScalar step);
217 void setGravity(const btVector3& acceleration);
219 const btVector3& getGravity() const
221 return m_gravity_acceleration;
224 void setDamping(btScalar lin_damping, btScalar ang_damping);
226 btScalar getLinearDamping() const
228 return m_linearDamping;
231 btScalar getAngularDamping() const
233 return m_angularDamping;
236 btScalar getLinearSleepingThreshold() const
238 return m_linearSleepingThreshold;
241 btScalar getAngularSleepingThreshold() const
243 return m_angularSleepingThreshold;
246 void applyDamping(btScalar timeStep);
248 SIMD_FORCE_INLINE const btCollisionShape* getCollisionShape() const {
249 return m_collisionShape;
252 SIMD_FORCE_INLINE btCollisionShape* getCollisionShape() {
253 return m_collisionShape;
256 void setMassProps(btScalar mass, const btVector3& inertia);
258 const btVector3& getLinearFactor() const
260 return m_linearFactor;
262 void setLinearFactor(const btVector3& linearFactor)
264 m_linearFactor = linearFactor;
265 m_invMass = m_linearFactor*m_inverseMass;
267 btScalar getInvMass() const { return m_inverseMass; }
268 const btMatrix3x3& getInvInertiaTensorWorld() const {
269 return m_invInertiaTensorWorld;
272 void integrateVelocities(btScalar step);
274 void setCenterOfMassTransform(const btTransform& xform);
276 void applyCentralForce(const btVector3& force)
278 m_totalForce += force*m_linearFactor;
281 const btVector3& getTotalForce() const
286 const btVector3& getTotalTorque() const
288 return m_totalTorque;
291 const btVector3& getInvInertiaDiagLocal() const
293 return m_invInertiaLocal;
296 void setInvInertiaDiagLocal(const btVector3& diagInvInertia)
298 m_invInertiaLocal = diagInvInertia;
301 void setSleepingThresholds(btScalar linear,btScalar angular)
303 m_linearSleepingThreshold = linear;
304 m_angularSleepingThreshold = angular;
307 void applyTorque(const btVector3& torque)
309 m_totalTorque += torque*m_angularFactor;
312 void applyForce(const btVector3& force, const btVector3& rel_pos)
314 applyCentralForce(force);
315 applyTorque(rel_pos.cross(force*m_linearFactor));
318 void applyCentralImpulse(const btVector3& impulse)
320 m_linearVelocity += impulse *m_linearFactor * m_inverseMass;
323 void applyTorqueImpulse(const btVector3& torque)
325 m_angularVelocity += m_invInertiaTensorWorld * torque * m_angularFactor;
328 void applyImpulse(const btVector3& impulse, const btVector3& rel_pos)
330 if (m_inverseMass != btScalar(0.))
332 applyCentralImpulse(impulse);
335 applyTorqueImpulse(rel_pos.cross(impulse*m_linearFactor));
342 m_totalForce.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
343 m_totalTorque.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
346 void updateInertiaTensor();
348 const btVector3& getCenterOfMassPosition() const {
349 return m_worldTransform.getOrigin();
351 btQuaternion getOrientation() const;
353 const btTransform& getCenterOfMassTransform() const {
354 return m_worldTransform;
356 const btVector3& getLinearVelocity() const {
357 return m_linearVelocity;
359 const btVector3& getAngularVelocity() const {
360 return m_angularVelocity;
364 inline void setLinearVelocity(const btVector3& lin_vel)
366 m_linearVelocity = lin_vel;
369 inline void setAngularVelocity(const btVector3& ang_vel)
371 m_angularVelocity = ang_vel;
374 btVector3 getVelocityInLocalPoint(const btVector3& rel_pos) const
376 //we also calculate lin/ang velocity for kinematic objects
377 return m_linearVelocity + m_angularVelocity.cross(rel_pos);
379 //for kinematic objects, we could also use use:
380 // return (m_worldTransform(rel_pos) - m_interpolationWorldTransform(rel_pos)) / m_kinematicTimeStep;
383 void translate(const btVector3& v)
385 m_worldTransform.getOrigin() += v;
389 void getAabb(btVector3& aabbMin,btVector3& aabbMax) const;
395 SIMD_FORCE_INLINE btScalar computeImpulseDenominator(const btVector3& pos, const btVector3& normal) const
397 btVector3 r0 = pos - getCenterOfMassPosition();
399 btVector3 c0 = (r0).cross(normal);
401 btVector3 vec = (c0 * getInvInertiaTensorWorld()).cross(r0);
403 return m_inverseMass + normal.dot(vec);
407 SIMD_FORCE_INLINE btScalar computeAngularImpulseDenominator(const btVector3& axis) const
409 btVector3 vec = axis * getInvInertiaTensorWorld();
410 return axis.dot(vec);
413 SIMD_FORCE_INLINE void updateDeactivation(btScalar timeStep)
415 if ( (getActivationState() == ISLAND_SLEEPING) || (getActivationState() == DISABLE_DEACTIVATION))
418 if ((getLinearVelocity().length2() < m_linearSleepingThreshold*m_linearSleepingThreshold) &&
419 (getAngularVelocity().length2() < m_angularSleepingThreshold*m_angularSleepingThreshold))
421 m_deactivationTime += timeStep;
424 m_deactivationTime=btScalar(0.);
425 setActivationState(0);
430 SIMD_FORCE_INLINE bool wantsSleeping()
433 if (getActivationState() == DISABLE_DEACTIVATION)
436 //disable deactivation
437 if (gDisableDeactivation || (gDeactivationTime == btScalar(0.)))
440 if ( (getActivationState() == ISLAND_SLEEPING) || (getActivationState() == WANTS_DEACTIVATION))
443 if (m_deactivationTime> gDeactivationTime)
452 const btBroadphaseProxy* getBroadphaseProxy() const
454 return m_broadphaseHandle;
456 btBroadphaseProxy* getBroadphaseProxy()
458 return m_broadphaseHandle;
460 void setNewBroadphaseProxy(btBroadphaseProxy* broadphaseProxy)
462 m_broadphaseHandle = broadphaseProxy;
465 //btMotionState allows to automatic synchronize the world transform for active objects
466 btMotionState* getMotionState()
468 return m_optionalMotionState;
470 const btMotionState* getMotionState() const
472 return m_optionalMotionState;
474 void setMotionState(btMotionState* motionState)
476 m_optionalMotionState = motionState;
477 if (m_optionalMotionState)
478 motionState->getWorldTransform(m_worldTransform);
481 //for experimental overriding of friction/contact solver func
482 int m_contactSolverType;
483 int m_frictionSolverType;
485 void setAngularFactor(const btVector3& angFac)
487 m_angularFactor = angFac;
490 void setAngularFactor(btScalar angFac)
492 m_angularFactor.setValue(angFac,angFac,angFac);
494 const btVector3& getAngularFactor() const
496 return m_angularFactor;
499 //is this rigidbody added to a btCollisionWorld/btDynamicsWorld/btBroadphase?
500 bool isInWorld() const
502 return (getBroadphaseProxy() != 0);
505 virtual bool checkCollideWithOverride(const btCollisionObject* co) const;
507 void addConstraintRef(btTypedConstraint* c);
508 void removeConstraintRef(btTypedConstraint* c);
510 btTypedConstraint* getConstraintRef(int index)
512 return m_constraintRefs[index];
515 int getNumConstraintRefs() const
517 return m_constraintRefs.size();
520 void setFlags(int flags)
522 m_rigidbodyFlags = flags;
527 return m_rigidbodyFlags;
530 btVector3 computeGyroscopicForce(btScalar maxGyroscopicForce) const;
532 ///////////////////////////////////////////////
534 virtual int calculateSerializeBufferSize() const;
536 ///fills the dataBuffer and returns the struct name (and 0 on failure)
537 virtual const char* serialize(void* dataBuffer, class btSerializer* serializer) const;
539 virtual void serializeSingleObject(class btSerializer* serializer) const;
543 //@todo add m_optionalMotionState and m_constraintRefs to btRigidBodyData
544 ///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
545 struct btRigidBodyFloatData
547 btCollisionObjectFloatData m_collisionObjectData;
548 btMatrix3x3FloatData m_invInertiaTensorWorld;
549 btVector3FloatData m_linearVelocity;
550 btVector3FloatData m_angularVelocity;
551 btVector3FloatData m_angularFactor;
552 btVector3FloatData m_linearFactor;
553 btVector3FloatData m_gravity;
554 btVector3FloatData m_gravity_acceleration;
555 btVector3FloatData m_invInertiaLocal;
556 btVector3FloatData m_totalForce;
557 btVector3FloatData m_totalTorque;
559 float m_linearDamping;
560 float m_angularDamping;
561 float m_additionalDampingFactor;
562 float m_additionalLinearDampingThresholdSqr;
563 float m_additionalAngularDampingThresholdSqr;
564 float m_additionalAngularDampingFactor;
565 float m_linearSleepingThreshold;
566 float m_angularSleepingThreshold;
567 int m_additionalDamping;
570 ///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
571 struct btRigidBodyDoubleData
573 btCollisionObjectDoubleData m_collisionObjectData;
574 btMatrix3x3DoubleData m_invInertiaTensorWorld;
575 btVector3DoubleData m_linearVelocity;
576 btVector3DoubleData m_angularVelocity;
577 btVector3DoubleData m_angularFactor;
578 btVector3DoubleData m_linearFactor;
579 btVector3DoubleData m_gravity;
580 btVector3DoubleData m_gravity_acceleration;
581 btVector3DoubleData m_invInertiaLocal;
582 btVector3DoubleData m_totalForce;
583 btVector3DoubleData m_totalTorque;
584 double m_inverseMass;
585 double m_linearDamping;
586 double m_angularDamping;
587 double m_additionalDampingFactor;
588 double m_additionalLinearDampingThresholdSqr;
589 double m_additionalAngularDampingThresholdSqr;
590 double m_additionalAngularDampingFactor;
591 double m_linearSleepingThreshold;
592 double m_angularSleepingThreshold;
593 int m_additionalDamping;
599 #endif //BT_RIGIDBODY_H