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 #include "btRigidBody.h"
17 #include "BulletCollision/CollisionShapes/btConvexShape.h"
18 #include "LinearMath/btMinMax.h"
19 #include "LinearMath/btTransformUtil.h"
20 #include "LinearMath/btMotionState.h"
21 #include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
22 #include "LinearMath/btSerializer.h"
24 //'temporarily' global variables
25 btScalar gDeactivationTime = btScalar(2.);
26 bool gDisableDeactivation = false;
27 static int uniqueId = 0;
29 btRigidBody::btRigidBody(const btRigidBody::btRigidBodyConstructionInfo& constructionInfo)
31 setupRigidBody(constructionInfo);
34 btRigidBody::btRigidBody(btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia)
36 btRigidBodyConstructionInfo cinfo(mass, motionState, collisionShape, localInertia);
37 setupRigidBody(cinfo);
40 void btRigidBody::setupRigidBody(const btRigidBody::btRigidBodyConstructionInfo& constructionInfo)
42 m_internalType = CO_RIGID_BODY;
44 m_linearVelocity.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
45 m_angularVelocity.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
46 m_angularFactor.setValue(1, 1, 1);
47 m_linearFactor.setValue(1, 1, 1);
48 m_gravity.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
49 m_gravity_acceleration.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
50 m_totalForce.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
51 m_totalTorque.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)),
52 setDamping(constructionInfo.m_linearDamping, constructionInfo.m_angularDamping);
54 m_linearSleepingThreshold = constructionInfo.m_linearSleepingThreshold;
55 m_angularSleepingThreshold = constructionInfo.m_angularSleepingThreshold;
56 m_optionalMotionState = constructionInfo.m_motionState;
57 m_contactSolverType = 0;
58 m_frictionSolverType = 0;
59 m_additionalDamping = constructionInfo.m_additionalDamping;
60 m_additionalDampingFactor = constructionInfo.m_additionalDampingFactor;
61 m_additionalLinearDampingThresholdSqr = constructionInfo.m_additionalLinearDampingThresholdSqr;
62 m_additionalAngularDampingThresholdSqr = constructionInfo.m_additionalAngularDampingThresholdSqr;
63 m_additionalAngularDampingFactor = constructionInfo.m_additionalAngularDampingFactor;
65 if (m_optionalMotionState)
67 m_optionalMotionState->getWorldTransform(m_worldTransform);
71 m_worldTransform = constructionInfo.m_startWorldTransform;
74 m_interpolationWorldTransform = m_worldTransform;
75 m_interpolationLinearVelocity.setValue(0, 0, 0);
76 m_interpolationAngularVelocity.setValue(0, 0, 0);
78 //moved to btCollisionObject
79 m_friction = constructionInfo.m_friction;
80 m_rollingFriction = constructionInfo.m_rollingFriction;
81 m_spinningFriction = constructionInfo.m_spinningFriction;
83 m_restitution = constructionInfo.m_restitution;
85 setCollisionShape(constructionInfo.m_collisionShape);
86 m_debugBodyId = uniqueId++;
88 setMassProps(constructionInfo.m_mass, constructionInfo.m_localInertia);
89 updateInertiaTensor();
91 m_rigidbodyFlags = BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_BODY;
93 m_deltaLinearVelocity.setZero();
94 m_deltaAngularVelocity.setZero();
95 m_invMass = m_inverseMass * m_linearFactor;
96 m_pushVelocity.setZero();
97 m_turnVelocity.setZero();
100 void btRigidBody::predictIntegratedTransform(btScalar timeStep, btTransform& predictedTransform)
102 btTransformUtil::integrateTransform(m_worldTransform, m_linearVelocity, m_angularVelocity, timeStep, predictedTransform);
105 void btRigidBody::saveKinematicState(btScalar timeStep)
107 //todo: clamp to some (user definable) safe minimum timestep, to limit maximum angular/linear velocities
108 if (timeStep != btScalar(0.))
110 //if we use motionstate to synchronize world transforms, get the new kinematic/animated world transform
111 if (getMotionState())
112 getMotionState()->getWorldTransform(m_worldTransform);
113 btVector3 linVel, angVel;
115 btTransformUtil::calculateVelocity(m_interpolationWorldTransform, m_worldTransform, timeStep, m_linearVelocity, m_angularVelocity);
116 m_interpolationLinearVelocity = m_linearVelocity;
117 m_interpolationAngularVelocity = m_angularVelocity;
118 m_interpolationWorldTransform = m_worldTransform;
119 //printf("angular = %f %f %f\n",m_angularVelocity.getX(),m_angularVelocity.getY(),m_angularVelocity.getZ());
123 void btRigidBody::getAabb(btVector3& aabbMin, btVector3& aabbMax) const
125 getCollisionShape()->getAabb(m_worldTransform, aabbMin, aabbMax);
128 void btRigidBody::setGravity(const btVector3& acceleration)
130 if (m_inverseMass != btScalar(0.0))
132 m_gravity = acceleration * (btScalar(1.0) / m_inverseMass);
134 m_gravity_acceleration = acceleration;
137 void btRigidBody::setDamping(btScalar lin_damping, btScalar ang_damping)
139 #ifdef BT_USE_OLD_DAMPING_METHOD
140 m_linearDamping = btMax(lin_damping, btScalar(0.0));
141 m_angularDamping = btMax(ang_damping, btScalar(0.0));
143 m_linearDamping = btClamped(lin_damping, btScalar(0.0), btScalar(1.0));
144 m_angularDamping = btClamped(ang_damping, btScalar(0.0), btScalar(1.0));
148 ///applyDamping damps the velocity, using the given m_linearDamping and m_angularDamping
149 void btRigidBody::applyDamping(btScalar timeStep)
151 //On new damping: see discussion/issue report here: http://code.google.com/p/bullet/issues/detail?id=74
152 //todo: do some performance comparisons (but other parts of the engine are probably bottleneck anyway
154 #ifdef BT_USE_OLD_DAMPING_METHOD
155 m_linearVelocity *= btMax((btScalar(1.0) - timeStep * m_linearDamping), btScalar(0.0));
156 m_angularVelocity *= btMax((btScalar(1.0) - timeStep * m_angularDamping), btScalar(0.0));
158 m_linearVelocity *= btPow(btScalar(1) - m_linearDamping, timeStep);
159 m_angularVelocity *= btPow(btScalar(1) - m_angularDamping, timeStep);
162 if (m_additionalDamping)
164 //Additional damping can help avoiding lowpass jitter motion, help stability for ragdolls etc.
165 //Such damping is undesirable, so once the overall simulation quality of the rigid body dynamics system has improved, this should become obsolete
166 if ((m_angularVelocity.length2() < m_additionalAngularDampingThresholdSqr) &&
167 (m_linearVelocity.length2() < m_additionalLinearDampingThresholdSqr))
169 m_angularVelocity *= m_additionalDampingFactor;
170 m_linearVelocity *= m_additionalDampingFactor;
173 btScalar speed = m_linearVelocity.length();
174 if (speed < m_linearDamping)
176 btScalar dampVel = btScalar(0.005);
179 btVector3 dir = m_linearVelocity.normalized();
180 m_linearVelocity -= dir * dampVel;
184 m_linearVelocity.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
188 btScalar angSpeed = m_angularVelocity.length();
189 if (angSpeed < m_angularDamping)
191 btScalar angDampVel = btScalar(0.005);
192 if (angSpeed > angDampVel)
194 btVector3 dir = m_angularVelocity.normalized();
195 m_angularVelocity -= dir * angDampVel;
199 m_angularVelocity.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
205 void btRigidBody::applyGravity()
207 if (isStaticOrKinematicObject())
210 applyCentralForce(m_gravity);
213 void btRigidBody::clearGravity()
215 if (isStaticOrKinematicObject())
218 applyCentralForce(-m_gravity);
221 void btRigidBody::proceedToTransform(const btTransform& newTrans)
223 setCenterOfMassTransform(newTrans);
226 void btRigidBody::setMassProps(btScalar mass, const btVector3& inertia)
228 if (mass == btScalar(0.))
230 m_collisionFlags |= btCollisionObject::CF_STATIC_OBJECT;
231 m_inverseMass = btScalar(0.);
235 m_collisionFlags &= (~btCollisionObject::CF_STATIC_OBJECT);
236 m_inverseMass = btScalar(1.0) / mass;
240 m_gravity = mass * m_gravity_acceleration;
242 m_invInertiaLocal.setValue(inertia.x() != btScalar(0.0) ? btScalar(1.0) / inertia.x() : btScalar(0.0),
243 inertia.y() != btScalar(0.0) ? btScalar(1.0) / inertia.y() : btScalar(0.0),
244 inertia.z() != btScalar(0.0) ? btScalar(1.0) / inertia.z() : btScalar(0.0));
246 m_invMass = m_linearFactor * m_inverseMass;
249 void btRigidBody::updateInertiaTensor()
251 m_invInertiaTensorWorld = m_worldTransform.getBasis().scaled(m_invInertiaLocal) * m_worldTransform.getBasis().transpose();
254 btVector3 btRigidBody::getLocalInertia() const
256 btVector3 inertiaLocal;
257 const btVector3 inertia = m_invInertiaLocal;
258 inertiaLocal.setValue(inertia.x() != btScalar(0.0) ? btScalar(1.0) / inertia.x() : btScalar(0.0),
259 inertia.y() != btScalar(0.0) ? btScalar(1.0) / inertia.y() : btScalar(0.0),
260 inertia.z() != btScalar(0.0) ? btScalar(1.0) / inertia.z() : btScalar(0.0));
264 inline btVector3 evalEulerEqn(const btVector3& w1, const btVector3& w0, const btVector3& T, const btScalar dt,
265 const btMatrix3x3& I)
267 const btVector3 w2 = I * w1 + w1.cross(I * w1) * dt - (T * dt + I * w0);
271 inline btMatrix3x3 evalEulerEqnDeriv(const btVector3& w1, const btVector3& w0, const btScalar dt,
272 const btMatrix3x3& I)
274 btMatrix3x3 w1x, Iw1x;
275 const btVector3 Iwi = (I * w1);
276 w1.getSkewSymmetricMatrix(&w1x[0], &w1x[1], &w1x[2]);
277 Iwi.getSkewSymmetricMatrix(&Iw1x[0], &Iw1x[1], &Iw1x[2]);
279 const btMatrix3x3 dfw1 = I + (w1x * I - Iw1x) * dt;
283 btVector3 btRigidBody::computeGyroscopicForceExplicit(btScalar maxGyroscopicForce) const
285 btVector3 inertiaLocal = getLocalInertia();
286 btMatrix3x3 inertiaTensorWorld = getWorldTransform().getBasis().scaled(inertiaLocal) * getWorldTransform().getBasis().transpose();
287 btVector3 tmp = inertiaTensorWorld * getAngularVelocity();
288 btVector3 gf = getAngularVelocity().cross(tmp);
289 btScalar l2 = gf.length2();
290 if (l2 > maxGyroscopicForce * maxGyroscopicForce)
292 gf *= btScalar(1.) / btSqrt(l2) * maxGyroscopicForce;
297 btVector3 btRigidBody::computeGyroscopicImpulseImplicit_Body(btScalar step) const
299 btVector3 idl = getLocalInertia();
300 btVector3 omega1 = getAngularVelocity();
301 btQuaternion q = getWorldTransform().getRotation();
303 // Convert to body coordinates
304 btVector3 omegab = quatRotate(q.inverse(), omega1);
306 Ib.setValue(idl.x(), 0, 0,
310 btVector3 ibo = Ib * omegab;
313 btVector3 f = step * omegab.cross(ibo);
316 omegab.getSkewSymmetricMatrix(&skew0[0], &skew0[1], &skew0[2]);
317 btVector3 om = Ib * omegab;
319 om.getSkewSymmetricMatrix(&skew1[0], &skew1[1], &skew1[2]);
322 btMatrix3x3 J = Ib + (skew0 * Ib - skew1) * step;
324 // btMatrix3x3 Jinv = J.inverse();
325 // btVector3 omega_div = Jinv*f;
326 btVector3 omega_div = J.solve33(f);
328 // Single Newton-Raphson update
329 omegab = omegab - omega_div; //Solve33(J, f);
330 // Back to world coordinates
331 btVector3 omega2 = quatRotate(q, omegab);
332 btVector3 gf = omega2 - omega1;
336 btVector3 btRigidBody::computeGyroscopicImpulseImplicit_World(btScalar step) const
338 // use full newton-euler equations. common practice to drop the wxIw term. want it for better tumbling behavior.
339 // calculate using implicit euler step so it's stable.
341 const btVector3 inertiaLocal = getLocalInertia();
342 const btVector3 w0 = getAngularVelocity();
346 I = m_worldTransform.getBasis().scaled(inertiaLocal) *
347 m_worldTransform.getBasis().transpose();
349 // use newtons method to find implicit solution for new angular velocity (w')
350 // f(w') = -(T*step + Iw) + Iw' + w' + w'xIw'*step = 0
351 // df/dw' = I + 1xIw'*step + w'xI*step
355 // one step of newton's method
357 const btVector3 fw = evalEulerEqn(w1, w0, btVector3(0, 0, 0), step, I);
358 const btMatrix3x3 dfw = evalEulerEqnDeriv(w1, w0, step, I);
361 dw = dfw.solve33(fw);
362 //const btMatrix3x3 dfw_inv = dfw.inverse();
368 btVector3 gf = (w1 - w0);
372 void btRigidBody::integrateVelocities(btScalar step)
374 if (isStaticOrKinematicObject())
377 m_linearVelocity += m_totalForce * (m_inverseMass * step);
378 m_angularVelocity += m_invInertiaTensorWorld * m_totalTorque * step;
380 #define MAX_ANGVEL SIMD_HALF_PI
381 /// clamp angular velocity. collision calculations will fail on higher angular velocities
382 btScalar angvel = m_angularVelocity.length();
383 if (angvel * step > MAX_ANGVEL)
385 m_angularVelocity *= (MAX_ANGVEL / step) / angvel;
387 #if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
388 clampVelocity(m_angularVelocity);
392 btQuaternion btRigidBody::getOrientation() const
395 m_worldTransform.getBasis().getRotation(orn);
399 void btRigidBody::setCenterOfMassTransform(const btTransform& xform)
401 if (isKinematicObject())
403 m_interpolationWorldTransform = m_worldTransform;
407 m_interpolationWorldTransform = xform;
409 m_interpolationLinearVelocity = getLinearVelocity();
410 m_interpolationAngularVelocity = getAngularVelocity();
411 m_worldTransform = xform;
412 updateInertiaTensor();
415 void btRigidBody::addConstraintRef(btTypedConstraint* c)
417 ///disable collision with the 'other' body
419 int index = m_constraintRefs.findLinearSearch(c);
420 //don't add constraints that are already referenced
421 //btAssert(index == m_constraintRefs.size());
422 if (index == m_constraintRefs.size())
424 m_constraintRefs.push_back(c);
425 btCollisionObject* colObjA = &c->getRigidBodyA();
426 btCollisionObject* colObjB = &c->getRigidBodyB();
429 colObjA->setIgnoreCollisionCheck(colObjB, true);
433 colObjB->setIgnoreCollisionCheck(colObjA, true);
438 void btRigidBody::removeConstraintRef(btTypedConstraint* c)
440 int index = m_constraintRefs.findLinearSearch(c);
441 //don't remove constraints that are not referenced
442 if (index < m_constraintRefs.size())
444 m_constraintRefs.remove(c);
445 btCollisionObject* colObjA = &c->getRigidBodyA();
446 btCollisionObject* colObjB = &c->getRigidBodyB();
449 colObjA->setIgnoreCollisionCheck(colObjB, false);
453 colObjB->setIgnoreCollisionCheck(colObjA, false);
458 int btRigidBody::calculateSerializeBufferSize() const
460 int sz = sizeof(btRigidBodyData);
464 ///fills the dataBuffer and returns the struct name (and 0 on failure)
465 const char* btRigidBody::serialize(void* dataBuffer, class btSerializer* serializer) const
467 btRigidBodyData* rbd = (btRigidBodyData*)dataBuffer;
469 btCollisionObject::serialize(&rbd->m_collisionObjectData, serializer);
471 m_invInertiaTensorWorld.serialize(rbd->m_invInertiaTensorWorld);
472 m_linearVelocity.serialize(rbd->m_linearVelocity);
473 m_angularVelocity.serialize(rbd->m_angularVelocity);
474 rbd->m_inverseMass = m_inverseMass;
475 m_angularFactor.serialize(rbd->m_angularFactor);
476 m_linearFactor.serialize(rbd->m_linearFactor);
477 m_gravity.serialize(rbd->m_gravity);
478 m_gravity_acceleration.serialize(rbd->m_gravity_acceleration);
479 m_invInertiaLocal.serialize(rbd->m_invInertiaLocal);
480 m_totalForce.serialize(rbd->m_totalForce);
481 m_totalTorque.serialize(rbd->m_totalTorque);
482 rbd->m_linearDamping = m_linearDamping;
483 rbd->m_angularDamping = m_angularDamping;
484 rbd->m_additionalDamping = m_additionalDamping;
485 rbd->m_additionalDampingFactor = m_additionalDampingFactor;
486 rbd->m_additionalLinearDampingThresholdSqr = m_additionalLinearDampingThresholdSqr;
487 rbd->m_additionalAngularDampingThresholdSqr = m_additionalAngularDampingThresholdSqr;
488 rbd->m_additionalAngularDampingFactor = m_additionalAngularDampingFactor;
489 rbd->m_linearSleepingThreshold = m_linearSleepingThreshold;
490 rbd->m_angularSleepingThreshold = m_angularSleepingThreshold;
492 // Fill padding with zeros to appease msan.
493 #ifdef BT_USE_DOUBLE_PRECISION
494 memset(rbd->m_padding, 0, sizeof(rbd->m_padding));
497 return btRigidBodyDataName;
500 void btRigidBody::serializeSingleObject(class btSerializer* serializer) const
502 btChunk* chunk = serializer->allocate(calculateSerializeBufferSize(), 1);
503 const char* structType = serialize(chunk->m_oldPtr, serializer);
504 serializer->finalizeChunk(chunk, structType, BT_RIGIDBODY_CODE, (void*)this);