btRigidBody.cpp

Go to the documentation of this file.
00001 /*
00002 Bullet Continuous Collision Detection and Physics Library
00003 Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
00004 
00005 This software is provided 'as-is', without any express or implied warranty.
00006 In no event will the authors be held liable for any damages arising from the use of this software.
00007 Permission is granted to anyone to use this software for any purpose, 
00008 including commercial applications, and to alter it and redistribute it freely, 
00009 subject to the following restrictions:
00010 
00011 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.
00012 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
00013 3. This notice may not be removed or altered from any source distribution.
00014 */
00015 
00016 #include "btRigidBody.h"
00017 #include "BulletCollision/CollisionShapes/btConvexShape.h"
00018 #include "LinearMath/btMinMax.h"
00019 #include "LinearMath/btTransformUtil.h"
00020 #include "LinearMath/btMotionState.h"
00021 #include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
00022 
00023 //'temporarily' global variables
00024 btScalar        gDeactivationTime = btScalar(2.);
00025 bool    gDisableDeactivation = false;
00026 static int uniqueId = 0;
00027 
00028 
00029 btRigidBody::btRigidBody(const btRigidBody::btRigidBodyConstructionInfo& constructionInfo)
00030 {
00031         setupRigidBody(constructionInfo);
00032 }
00033 
00034 btRigidBody::btRigidBody(btScalar mass, btMotionState *motionState, btCollisionShape *collisionShape, const btVector3 &localInertia)
00035 {
00036         btRigidBodyConstructionInfo cinfo(mass,motionState,collisionShape,localInertia);
00037         setupRigidBody(cinfo);
00038 }
00039 
00040 void    btRigidBody::setupRigidBody(const btRigidBody::btRigidBodyConstructionInfo& constructionInfo)
00041 {
00042 
00043         m_internalType=CO_RIGID_BODY;
00044 
00045         m_linearVelocity.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
00046         m_angularVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
00047         m_angularFactor.setValue(1,1,1);
00048         m_linearFactor.setValue(1,1,1);
00049         m_gravity.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
00050         m_gravity_acceleration.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
00051         m_totalForce.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
00052         m_totalTorque.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)),
00053         m_linearDamping = btScalar(0.);
00054         m_angularDamping = btScalar(0.5);
00055         m_linearSleepingThreshold = constructionInfo.m_linearSleepingThreshold;
00056         m_angularSleepingThreshold = constructionInfo.m_angularSleepingThreshold;
00057         m_optionalMotionState = constructionInfo.m_motionState;
00058         m_contactSolverType = 0;
00059         m_frictionSolverType = 0;
00060         m_additionalDamping = constructionInfo.m_additionalDamping;
00061         m_additionalDampingFactor = constructionInfo.m_additionalDampingFactor;
00062         m_additionalLinearDampingThresholdSqr = constructionInfo.m_additionalLinearDampingThresholdSqr;
00063         m_additionalAngularDampingThresholdSqr = constructionInfo.m_additionalAngularDampingThresholdSqr;
00064         m_additionalAngularDampingFactor = constructionInfo.m_additionalAngularDampingFactor;
00065 
00066         if (m_optionalMotionState)
00067         {
00068                 m_optionalMotionState->getWorldTransform(m_worldTransform);
00069         } else
00070         {
00071                 m_worldTransform = constructionInfo.m_startWorldTransform;
00072         }
00073 
00074         m_interpolationWorldTransform = m_worldTransform;
00075         m_interpolationLinearVelocity.setValue(0,0,0);
00076         m_interpolationAngularVelocity.setValue(0,0,0);
00077         
00078         //moved to btCollisionObject
00079         m_friction = constructionInfo.m_friction;
00080         m_restitution = constructionInfo.m_restitution;
00081 
00082         setCollisionShape( constructionInfo.m_collisionShape );
00083         m_debugBodyId = uniqueId++;
00084         
00085         setMassProps(constructionInfo.m_mass, constructionInfo.m_localInertia);
00086     setDamping(constructionInfo.m_linearDamping, constructionInfo.m_angularDamping);
00087         updateInertiaTensor();
00088 
00089         m_rigidbodyFlags = 0;
00090 
00091 
00092         m_deltaLinearVelocity.setZero();
00093         m_deltaAngularVelocity.setZero();
00094         m_invMass = m_inverseMass*m_linearFactor;
00095         m_pushVelocity.setZero();
00096         m_turnVelocity.setZero();
00097 
00098         
00099 
00100 }
00101 
00102 
00103 void btRigidBody::predictIntegratedTransform(btScalar timeStep,btTransform& predictedTransform) 
00104 {
00105         btTransformUtil::integrateTransform(m_worldTransform,m_linearVelocity,m_angularVelocity,timeStep,predictedTransform);
00106 }
00107 
00108 void                    btRigidBody::saveKinematicState(btScalar timeStep)
00109 {
00110         //todo: clamp to some (user definable) safe minimum timestep, to limit maximum angular/linear velocities
00111         if (timeStep != btScalar(0.))
00112         {
00113                 //if we use motionstate to synchronize world transforms, get the new kinematic/animated world transform
00114                 if (getMotionState())
00115                         getMotionState()->getWorldTransform(m_worldTransform);
00116                 btVector3 linVel,angVel;
00117                 
00118                 btTransformUtil::calculateVelocity(m_interpolationWorldTransform,m_worldTransform,timeStep,m_linearVelocity,m_angularVelocity);
00119                 m_interpolationLinearVelocity = m_linearVelocity;
00120                 m_interpolationAngularVelocity = m_angularVelocity;
00121                 m_interpolationWorldTransform = m_worldTransform;
00122                 //printf("angular = %f %f %f\n",m_angularVelocity.getX(),m_angularVelocity.getY(),m_angularVelocity.getZ());
00123         }
00124 }
00125         
00126 void    btRigidBody::getAabb(btVector3& aabbMin,btVector3& aabbMax) const
00127 {
00128         getCollisionShape()->getAabb(m_worldTransform,aabbMin,aabbMax);
00129 }
00130 
00131 
00132 
00133 
00134 void btRigidBody::setGravity(const btVector3& acceleration) 
00135 {
00136         if (m_inverseMass != btScalar(0.0))
00137         {
00138                 m_gravity = acceleration * (btScalar(1.0) / m_inverseMass);
00139         }
00140         m_gravity_acceleration = acceleration;
00141 }
00142 
00143 
00144 
00145 
00146 
00147 
00148 void btRigidBody::setDamping(btScalar lin_damping, btScalar ang_damping)
00149 {
00150         m_linearDamping = GEN_clamped(lin_damping, (btScalar)btScalar(0.0), (btScalar)btScalar(1.0));
00151         m_angularDamping = GEN_clamped(ang_damping, (btScalar)btScalar(0.0), (btScalar)btScalar(1.0));
00152 }
00153 
00154 
00155 
00156 
00158 void                    btRigidBody::applyDamping(btScalar timeStep)
00159 {
00160         //On new damping: see discussion/issue report here: http://code.google.com/p/bullet/issues/detail?id=74
00161         //todo: do some performance comparisons (but other parts of the engine are probably bottleneck anyway
00162 
00163 //#define USE_OLD_DAMPING_METHOD 1
00164 #ifdef USE_OLD_DAMPING_METHOD
00165         m_linearVelocity *= GEN_clamped((btScalar(1.) - timeStep * m_linearDamping), (btScalar)btScalar(0.0), (btScalar)btScalar(1.0));
00166         m_angularVelocity *= GEN_clamped((btScalar(1.) - timeStep * m_angularDamping), (btScalar)btScalar(0.0), (btScalar)btScalar(1.0));
00167 #else
00168         m_linearVelocity *= btPow(btScalar(1)-m_linearDamping, timeStep);
00169         m_angularVelocity *= btPow(btScalar(1)-m_angularDamping, timeStep);
00170 #endif
00171 
00172         if (m_additionalDamping)
00173         {
00174                 //Additional damping can help avoiding lowpass jitter motion, help stability for ragdolls etc.
00175                 //Such damping is undesirable, so once the overall simulation quality of the rigid body dynamics system has improved, this should become obsolete
00176                 if ((m_angularVelocity.length2() < m_additionalAngularDampingThresholdSqr) &&
00177                         (m_linearVelocity.length2() < m_additionalLinearDampingThresholdSqr))
00178                 {
00179                         m_angularVelocity *= m_additionalDampingFactor;
00180                         m_linearVelocity *= m_additionalDampingFactor;
00181                 }
00182         
00183 
00184                 btScalar speed = m_linearVelocity.length();
00185                 if (speed < m_linearDamping)
00186                 {
00187                         btScalar dampVel = btScalar(0.005);
00188                         if (speed > dampVel)
00189                         {
00190                                 btVector3 dir = m_linearVelocity.normalized();
00191                                 m_linearVelocity -=  dir * dampVel;
00192                         } else
00193                         {
00194                                 m_linearVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
00195                         }
00196                 }
00197 
00198                 btScalar angSpeed = m_angularVelocity.length();
00199                 if (angSpeed < m_angularDamping)
00200                 {
00201                         btScalar angDampVel = btScalar(0.005);
00202                         if (angSpeed > angDampVel)
00203                         {
00204                                 btVector3 dir = m_angularVelocity.normalized();
00205                                 m_angularVelocity -=  dir * angDampVel;
00206                         } else
00207                         {
00208                                 m_angularVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
00209                         }
00210                 }
00211         }
00212 }
00213 
00214 
00215 void btRigidBody::applyGravity()
00216 {
00217         if (isStaticOrKinematicObject())
00218                 return;
00219         
00220         applyCentralForce(m_gravity);   
00221 
00222 }
00223 
00224 void btRigidBody::proceedToTransform(const btTransform& newTrans)
00225 {
00226         setCenterOfMassTransform( newTrans );
00227 }
00228         
00229 
00230 void btRigidBody::setMassProps(btScalar mass, const btVector3& inertia)
00231 {
00232         if (mass == btScalar(0.))
00233         {
00234                 m_collisionFlags |= btCollisionObject::CF_STATIC_OBJECT;
00235                 m_inverseMass = btScalar(0.);
00236         } else
00237         {
00238                 m_collisionFlags &= (~btCollisionObject::CF_STATIC_OBJECT);
00239                 m_inverseMass = btScalar(1.0) / mass;
00240         }
00241         
00242         m_invInertiaLocal.setValue(inertia.x() != btScalar(0.0) ? btScalar(1.0) / inertia.x(): btScalar(0.0),
00243                                    inertia.y() != btScalar(0.0) ? btScalar(1.0) / inertia.y(): btScalar(0.0),
00244                                    inertia.z() != btScalar(0.0) ? btScalar(1.0) / inertia.z(): btScalar(0.0));
00245 
00246         m_invMass = m_linearFactor*m_inverseMass;
00247 }
00248 
00249         
00250 
00251 void btRigidBody::updateInertiaTensor() 
00252 {
00253         m_invInertiaTensorWorld = m_worldTransform.getBasis().scaled(m_invInertiaLocal) * m_worldTransform.getBasis().transpose();
00254 }
00255 
00256 
00257 void btRigidBody::integrateVelocities(btScalar step) 
00258 {
00259         if (isStaticOrKinematicObject())
00260                 return;
00261 
00262         m_linearVelocity += m_totalForce * (m_inverseMass * step);
00263         m_angularVelocity += m_invInertiaTensorWorld * m_totalTorque * step;
00264 
00265 #define MAX_ANGVEL SIMD_HALF_PI
00267         btScalar angvel = m_angularVelocity.length();
00268         if (angvel*step > MAX_ANGVEL)
00269         {
00270                 m_angularVelocity *= (MAX_ANGVEL/step) /angvel;
00271         }
00272 
00273 }
00274 
00275 btQuaternion btRigidBody::getOrientation() const
00276 {
00277                 btQuaternion orn;
00278                 m_worldTransform.getBasis().getRotation(orn);
00279                 return orn;
00280 }
00281         
00282         
00283 void btRigidBody::setCenterOfMassTransform(const btTransform& xform)
00284 {
00285 
00286         if (isStaticOrKinematicObject())
00287         {
00288                 m_interpolationWorldTransform = m_worldTransform;
00289         } else
00290         {
00291                 m_interpolationWorldTransform = xform;
00292         }
00293         m_interpolationLinearVelocity = getLinearVelocity();
00294         m_interpolationAngularVelocity = getAngularVelocity();
00295         m_worldTransform = xform;
00296         updateInertiaTensor();
00297 }
00298 
00299 
00300 bool btRigidBody::checkCollideWithOverride(btCollisionObject* co)
00301 {
00302         btRigidBody* otherRb = btRigidBody::upcast(co);
00303         if (!otherRb)
00304                 return true;
00305 
00306         for (int i = 0; i < m_constraintRefs.size(); ++i)
00307         {
00308                 btTypedConstraint* c = m_constraintRefs[i];
00309                 if (&c->getRigidBodyA() == otherRb || &c->getRigidBodyB() == otherRb)
00310                         return false;
00311         }
00312 
00313         return true;
00314 }
00315 
00316 void    btRigidBody::internalWritebackVelocity(btScalar timeStep)
00317 {
00318     (void) timeStep;
00319         if (m_inverseMass)
00320         {
00321                 setLinearVelocity(getLinearVelocity()+ m_deltaLinearVelocity);
00322                 setAngularVelocity(getAngularVelocity()+m_deltaAngularVelocity);
00323                 
00324                 //correct the position/orientation based on push/turn recovery
00325                 btTransform newTransform;
00326                 btTransformUtil::integrateTransform(getWorldTransform(),m_pushVelocity,m_turnVelocity,timeStep,newTransform);
00327                 setWorldTransform(newTransform);
00328                 //m_originalBody->setCompanionId(-1);
00329         }
00330         m_deltaLinearVelocity.setZero();
00331         m_deltaAngularVelocity .setZero();
00332         m_pushVelocity.setZero();
00333         m_turnVelocity.setZero();
00334 }
00335 
00336 
00337 
00338 void btRigidBody::addConstraintRef(btTypedConstraint* c)
00339 {
00340         int index = m_constraintRefs.findLinearSearch(c);
00341         if (index == m_constraintRefs.size())
00342                 m_constraintRefs.push_back(c); 
00343 
00344         m_checkCollideWith = true;
00345 }
00346 
00347 void btRigidBody::removeConstraintRef(btTypedConstraint* c)
00348 {
00349         m_constraintRefs.remove(c);
00350         m_checkCollideWith = m_constraintRefs.size() > 0;
00351 }
00352 
00353 int     btRigidBody::calculateSerializeBufferSize()     const
00354 {
00355         int sz = sizeof(btRigidBodyData);
00356         return sz;
00357 }
00358 
00360 const char*     btRigidBody::serialize(void* dataBuffer, class btSerializer* serializer) const
00361 {
00362         btRigidBodyData* rbd = (btRigidBodyData*) dataBuffer;
00363 
00364         btCollisionObject::serialize(&rbd->m_collisionObjectData, serializer);
00365 
00366         m_invInertiaTensorWorld.serialize(rbd->m_invInertiaTensorWorld);
00367         m_linearVelocity.serialize(rbd->m_linearVelocity);
00368         m_angularVelocity.serialize(rbd->m_angularVelocity);
00369         rbd->m_inverseMass = m_inverseMass;
00370         m_angularFactor.serialize(rbd->m_angularFactor);
00371         m_linearFactor.serialize(rbd->m_linearFactor);
00372         m_gravity.serialize(rbd->m_gravity);
00373         m_gravity_acceleration.serialize(rbd->m_gravity_acceleration);
00374         m_invInertiaLocal.serialize(rbd->m_invInertiaLocal);
00375         m_totalForce.serialize(rbd->m_totalForce);
00376         m_totalTorque.serialize(rbd->m_totalTorque);
00377         rbd->m_linearDamping = m_linearDamping;
00378         rbd->m_angularDamping = m_angularDamping;
00379         rbd->m_additionalDamping = m_additionalDamping;
00380         rbd->m_additionalDampingFactor = m_additionalDampingFactor;
00381         rbd->m_additionalLinearDampingThresholdSqr = m_additionalLinearDampingThresholdSqr;
00382         rbd->m_additionalAngularDampingThresholdSqr = m_additionalAngularDampingThresholdSqr;
00383         rbd->m_additionalAngularDampingFactor = m_additionalAngularDampingFactor;
00384         rbd->m_linearSleepingThreshold=m_linearSleepingThreshold;
00385         rbd->m_angularSleepingThreshold = m_angularSleepingThreshold;
00386 
00387         return btRigidBodyDataName;
00388 }
00389 
00390 

Generated on Mon Feb 15 22:17:05 2010 for Bullet Collision Detection & Physics Library by  doxygen 1.6.1