1 /* 2 Bullet Continuous Collision Detection and Physics Library 3 Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ 4 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: 10 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. 14 */ 15 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" 23 24 //'temporarily' global variables 25 btScalar gDeactivationTime = btScalar(2.); 26 bool gDisableDeactivation = false; 27 static int uniqueId = 0; 28 29 30 btRigidBody::btRigidBody(const btRigidBody::btRigidBodyConstructionInfo& constructionInfo) 31 { 32 setupRigidBody(constructionInfo); 33 } 34 35 btRigidBody::btRigidBody(btScalar mass, btMotionState *motionState, btCollisionShape *collisionShape, const btVector3 &localInertia) 36 { 37 btRigidBodyConstructionInfo cinfo(mass,motionState,collisionShape,localInertia); 38 setupRigidBody(cinfo); 39 } 40 41 void btRigidBody::setupRigidBody(const btRigidBody::btRigidBodyConstructionInfo& constructionInfo) 42 { 43 44 m_internalType=CO_RIGID_BODY; 45 46 m_linearVelocity.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)); 47 m_angularVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); 48 m_angularFactor.setValue(1,1,1); 49 m_linearFactor.setValue(1,1,1); 50 m_gravity.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)); 51 m_gravity_acceleration.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)); 52 m_totalForce.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)); 53 m_totalTorque.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)), 54 setDamping(constructionInfo.m_linearDamping, constructionInfo.m_angularDamping); 55 56 m_linearSleepingThreshold = constructionInfo.m_linearSleepingThreshold; 57 m_angularSleepingThreshold = constructionInfo.m_angularSleepingThreshold; 58 m_optionalMotionState = constructionInfo.m_motionState; 59 m_contactSolverType = 0; 60 m_frictionSolverType = 0; 61 m_additionalDamping = constructionInfo.m_additionalDamping; 62 m_additionalDampingFactor = constructionInfo.m_additionalDampingFactor; 63 m_additionalLinearDampingThresholdSqr = constructionInfo.m_additionalLinearDampingThresholdSqr; 64 m_additionalAngularDampingThresholdSqr = constructionInfo.m_additionalAngularDampingThresholdSqr; 65 m_additionalAngularDampingFactor = constructionInfo.m_additionalAngularDampingFactor; 66 67 if (m_optionalMotionState) 68 { 69 m_optionalMotionState->getWorldTransform(m_worldTransform); 70 } else 71 { 72 m_worldTransform = constructionInfo.m_startWorldTransform; 73 } 74 75 m_interpolationWorldTransform = m_worldTransform; 76 m_interpolationLinearVelocity.setValue(0,0,0); 77 m_interpolationAngularVelocity.setValue(0,0,0); 78 79 //moved to btCollisionObject 80 m_friction = constructionInfo.m_friction; 81 m_rollingFriction = constructionInfo.m_rollingFriction; 82 m_restitution = constructionInfo.m_restitution; 83 84 setCollisionShape( constructionInfo.m_collisionShape ); 85 m_debugBodyId = uniqueId++; 86 87 setMassProps(constructionInfo.m_mass, constructionInfo.m_localInertia); 88 updateInertiaTensor(); 89 90 m_rigidbodyFlags = BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_BODY; 91 92 93 m_deltaLinearVelocity.setZero(); 94 m_deltaAngularVelocity.setZero(); 95 m_invMass = m_inverseMass*m_linearFactor; 96 m_pushVelocity.setZero(); 97 m_turnVelocity.setZero(); 98 99 100 101 } 102 103 104 void btRigidBody::predictIntegratedTransform(btScalar timeStep,btTransform& predictedTransform) 105 { 106 btTransformUtil::integrateTransform(m_worldTransform,m_linearVelocity,m_angularVelocity,timeStep,predictedTransform); 107 } 108 109 void btRigidBody::saveKinematicState(btScalar timeStep) 110 { 111 //todo: clamp to some (user definable) safe minimum timestep, to limit maximum angular/linear velocities 112 if (timeStep != btScalar(0.)) 113 { 114 //if we use motionstate to synchronize world transforms, get the new kinematic/animated world transform 115 if (getMotionState()) 116 getMotionState()->getWorldTransform(m_worldTransform); 117 btVector3 linVel,angVel; 118 119 btTransformUtil::calculateVelocity(m_interpolationWorldTransform,m_worldTransform,timeStep,m_linearVelocity,m_angularVelocity); 120 m_interpolationLinearVelocity = m_linearVelocity; 121 m_interpolationAngularVelocity = m_angularVelocity; 122 m_interpolationWorldTransform = m_worldTransform; 123 //printf("angular = %f %f %f\n",m_angularVelocity.getX(),m_angularVelocity.getY(),m_angularVelocity.getZ()); 124 } 125 } 126 127 void btRigidBody::getAabb(btVector3& aabbMin,btVector3& aabbMax) const 128 { 129 getCollisionShape()->getAabb(m_worldTransform,aabbMin,aabbMax); 130 } 131 132 133 134 135 void btRigidBody::setGravity(const btVector3& acceleration) 136 { 137 if (m_inverseMass != btScalar(0.0)) 138 { 139 m_gravity = acceleration * (btScalar(1.0) / m_inverseMass); 140 } 141 m_gravity_acceleration = acceleration; 142 } 143 144 145 146 147 148 149 void btRigidBody::setDamping(btScalar lin_damping, btScalar ang_damping) 150 { 151 m_linearDamping = btClamped(lin_damping, (btScalar)btScalar(0.0), (btScalar)btScalar(1.0)); 152 m_angularDamping = btClamped(ang_damping, (btScalar)btScalar(0.0), (btScalar)btScalar(1.0)); 153 } 154 155 156 157 158 ///applyDamping damps the velocity, using the given m_linearDamping and m_angularDamping 159 void btRigidBody::applyDamping(btScalar timeStep) 160 { 161 //On new damping: see discussion/issue report here: http://code.google.com/p/bullet/issues/detail?id=74 162 //todo: do some performance comparisons (but other parts of the engine are probably bottleneck anyway 163 164 //#define USE_OLD_DAMPING_METHOD 1 165 #ifdef USE_OLD_DAMPING_METHOD 166 m_linearVelocity *= GEN_clamped((btScalar(1.) - timeStep * m_linearDamping), (btScalar)btScalar(0.0), (btScalar)btScalar(1.0)); 167 m_angularVelocity *= GEN_clamped((btScalar(1.) - timeStep * m_angularDamping), (btScalar)btScalar(0.0), (btScalar)btScalar(1.0)); 168 #else 169 m_linearVelocity *= btPow(btScalar(1)-m_linearDamping, timeStep); 170 m_angularVelocity *= btPow(btScalar(1)-m_angularDamping, timeStep); 171 #endif 172 173 if (m_additionalDamping) 174 { 175 //Additional damping can help avoiding lowpass jitter motion, help stability for ragdolls etc. 176 //Such damping is undesirable, so once the overall simulation quality of the rigid body dynamics system has improved, this should become obsolete 177 if ((m_angularVelocity.length2() < m_additionalAngularDampingThresholdSqr) && 178 (m_linearVelocity.length2() < m_additionalLinearDampingThresholdSqr)) 179 { 180 m_angularVelocity *= m_additionalDampingFactor; 181 m_linearVelocity *= m_additionalDampingFactor; 182 } 183 184 185 btScalar speed = m_linearVelocity.length(); 186 if (speed < m_linearDamping) 187 { 188 btScalar dampVel = btScalar(0.005); 189 if (speed > dampVel) 190 { 191 btVector3 dir = m_linearVelocity.normalized(); 192 m_linearVelocity -= dir * dampVel; 193 } else 194 { 195 m_linearVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); 196 } 197 } 198 199 btScalar angSpeed = m_angularVelocity.length(); 200 if (angSpeed < m_angularDamping) 201 { 202 btScalar angDampVel = btScalar(0.005); 203 if (angSpeed > angDampVel) 204 { 205 btVector3 dir = m_angularVelocity.normalized(); 206 m_angularVelocity -= dir * angDampVel; 207 } else 208 { 209 m_angularVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); 210 } 211 } 212 } 213 } 214 215 216 void btRigidBody::applyGravity() 217 { 218 if (isStaticOrKinematicObject()) 219 return; 220 221 applyCentralForce(m_gravity); 222 223 } 224 225 void btRigidBody::proceedToTransform(const btTransform& newTrans) 226 { 227 setCenterOfMassTransform( newTrans ); 228 } 229 230 231 void btRigidBody::setMassProps(btScalar mass, const btVector3& inertia) 232 { 233 if (mass == btScalar(0.)) 234 { 235 m_collisionFlags |= btCollisionObject::CF_STATIC_OBJECT; 236 m_inverseMass = btScalar(0.); 237 } else 238 { 239 m_collisionFlags &= (~btCollisionObject::CF_STATIC_OBJECT); 240 m_inverseMass = btScalar(1.0) / mass; 241 } 242 243 //Fg = m * a 244 m_gravity = mass * m_gravity_acceleration; 245 246 m_invInertiaLocal.setValue(inertia.x() != btScalar(0.0) ? btScalar(1.0) / inertia.x(): btScalar(0.0), 247 inertia.y() != btScalar(0.0) ? btScalar(1.0) / inertia.y(): btScalar(0.0), 248 inertia.z() != btScalar(0.0) ? btScalar(1.0) / inertia.z(): btScalar(0.0)); 249 250 m_invMass = m_linearFactor*m_inverseMass; 251 } 252 253 254 void btRigidBody::updateInertiaTensor() 255 { 256 m_invInertiaTensorWorld = m_worldTransform.getBasis().scaled(m_invInertiaLocal) * m_worldTransform.getBasis().transpose(); 257 } 258 259 260 261 btVector3 btRigidBody::getLocalInertia() const 262 { 263 264 btVector3 inertiaLocal; 265 const btVector3 inertia = m_invInertiaLocal; 266 inertiaLocal.setValue(inertia.x() != btScalar(0.0) ? btScalar(1.0) / inertia.x() : btScalar(0.0), 267 inertia.y() != btScalar(0.0) ? btScalar(1.0) / inertia.y() : btScalar(0.0), 268 inertia.z() != btScalar(0.0) ? btScalar(1.0) / inertia.z() : btScalar(0.0)); 269 return inertiaLocal; 270 } 271 272 inline btVector3 evalEulerEqn(const btVector3& w1, const btVector3& w0, const btVector3& T, const btScalar dt, 273 const btMatrix3x3 &I) 274 { 275 const btVector3 w2 = I*w1 + w1.cross(I*w1)*dt - (T*dt + I*w0); 276 return w2; 277 } 278 279 inline btMatrix3x3 evalEulerEqnDeriv(const btVector3& w1, const btVector3& w0, const btScalar dt, 280 const btMatrix3x3 &I) 281 { 282 283 btMatrix3x3 w1x, Iw1x; 284 const btVector3 Iwi = (I*w1); 285 w1.getSkewSymmetricMatrix(&w1x[0], &w1x[1], &w1x[2]); 286 Iwi.getSkewSymmetricMatrix(&Iw1x[0], &Iw1x[1], &Iw1x[2]); 287 288 const btMatrix3x3 dfw1 = I + (w1x*I - Iw1x)*dt; 289 return dfw1; 290 } 291 292 btVector3 btRigidBody::computeGyroscopicForceExplicit(btScalar maxGyroscopicForce) const 293 { 294 btVector3 inertiaLocal = getLocalInertia(); 295 btMatrix3x3 inertiaTensorWorld = getWorldTransform().getBasis().scaled(inertiaLocal) * getWorldTransform().getBasis().transpose(); 296 btVector3 tmp = inertiaTensorWorld*getAngularVelocity(); 297 btVector3 gf = getAngularVelocity().cross(tmp); 298 btScalar l2 = gf.length2(); 299 if (l2>maxGyroscopicForce*maxGyroscopicForce) 300 { 301 gf *= btScalar(1.)/btSqrt(l2)*maxGyroscopicForce; 302 } 303 return gf; 304 } 305 306 void btSetCrossMatrixMinus(btMatrix3x3& res, const btVector3& a) 307 { 308 const btScalar a_0 = a[0], a_1 = a[1], a_2 = a[2]; 309 res.setValue(0, +a_2, -a_1, 310 -a_2, 0, +a_0, 311 +a_1, -a_0, 0); 312 } 313 314 btVector3 btRigidBody::computeGyroscopicImpulseImplicit_Body(btScalar step) const 315 { 316 btVector3 idl = getLocalInertia(); 317 btVector3 omega1 = getAngularVelocity(); 318 btQuaternion q = getWorldTransform().getRotation(); 319 320 // Convert to body coordinates 321 btVector3 omegab = quatRotate(q.inverse(), omega1); 322 btMatrix3x3 Ib; 323 Ib.setValue(idl.x(),0,0, 324 0,idl.y(),0, 325 0,0,idl.z()); 326 327 btVector3 ibo = Ib*omegab; 328 329 // Residual vector 330 btVector3 f = step * omegab.cross(ibo); 331 332 btMatrix3x3 skew0; 333 omegab.getSkewSymmetricMatrix(&skew0[0], &skew0[1], &skew0[2]); 334 btVector3 om = Ib*omegab; 335 btMatrix3x3 skew1; 336 om.getSkewSymmetricMatrix(&skew1[0],&skew1[1],&skew1[2]); 337 338 // Jacobian 339 btMatrix3x3 J = Ib + (skew0*Ib - skew1)*step; 340 341 // btMatrix3x3 Jinv = J.inverse(); 342 // btVector3 omega_div = Jinv*f; 343 btVector3 omega_div = J.solve33(f); 344 345 // Single Newton-Raphson update 346 omegab = omegab - omega_div;//Solve33(J, f); 347 // Back to world coordinates 348 btVector3 omega2 = quatRotate(q,omegab); 349 btVector3 gf = omega2-omega1; 350 return gf; 351 } 352 353 354 355 btVector3 btRigidBody::computeGyroscopicImpulseImplicit_World(btScalar step) const 356 { 357 // use full newton-euler equations. common practice to drop the wxIw term. want it for better tumbling behavior. 358 // calculate using implicit euler step so it's stable. 359 360 const btVector3 inertiaLocal = getLocalInertia(); 361 const btVector3 w0 = getAngularVelocity(); 362 363 btMatrix3x3 I; 364 365 I = m_worldTransform.getBasis().scaled(inertiaLocal) * 366 m_worldTransform.getBasis().transpose(); 367 368 // use newtons method to find implicit solution for new angular velocity (w') 369 // f(w') = -(T*step + Iw) + Iw' + w' + w'xIw'*step = 0 370 // df/dw' = I + 1xIw'*step + w'xI*step 371 372 btVector3 w1 = w0; 373 374 // one step of newton's method 375 { 376 const btVector3 fw = evalEulerEqn(w1, w0, btVector3(0, 0, 0), step, I); 377 const btMatrix3x3 dfw = evalEulerEqnDeriv(w1, w0, step, I); 378 379 btVector3 dw; 380 dw = dfw.solve33(fw); 381 //const btMatrix3x3 dfw_inv = dfw.inverse(); 382 //dw = dfw_inv*fw; 383 384 w1 -= dw; 385 } 386 387 btVector3 gf = (w1 - w0); 388 return gf; 389 } 390 391 392 void btRigidBody::integrateVelocities(btScalar step) 393 { 394 if (isStaticOrKinematicObject()) 395 return; 396 397 m_linearVelocity += m_totalForce * (m_inverseMass * step); 398 m_angularVelocity += m_invInertiaTensorWorld * m_totalTorque * step; 399 400 #define MAX_ANGVEL SIMD_HALF_PI 401 /// clamp angular velocity. collision calculations will fail on higher angular velocities 402 btScalar angvel = m_angularVelocity.length(); 403 if (angvel*step > MAX_ANGVEL) 404 { 405 m_angularVelocity *= (MAX_ANGVEL/step) /angvel; 406 } 407 408 } 409 410 btQuaternion btRigidBody::getOrientation() const 411 { 412 btQuaternion orn; 413 m_worldTransform.getBasis().getRotation(orn); 414 return orn; 415 } 416 417 418 void btRigidBody::setCenterOfMassTransform(const btTransform& xform) 419 { 420 421 if (isKinematicObject()) 422 { 423 m_interpolationWorldTransform = m_worldTransform; 424 } else 425 { 426 m_interpolationWorldTransform = xform; 427 } 428 m_interpolationLinearVelocity = getLinearVelocity(); 429 m_interpolationAngularVelocity = getAngularVelocity(); 430 m_worldTransform = xform; 431 updateInertiaTensor(); 432 } 433 434 435 436 437 438 void btRigidBody::addConstraintRef(btTypedConstraint* c) 439 { 440 ///disable collision with the 'other' body 441 442 int index = m_constraintRefs.findLinearSearch(c); 443 //don't add constraints that are already referenced 444 //btAssert(index == m_constraintRefs.size()); 445 if (index == m_constraintRefs.size()) 446 { 447 m_constraintRefs.push_back(c); 448 btCollisionObject* colObjA = &c->getRigidBodyA(); 449 btCollisionObject* colObjB = &c->getRigidBodyB(); 450 if (colObjA == this) 451 { 452 colObjA->setIgnoreCollisionCheck(colObjB, true); 453 } 454 else 455 { 456 colObjB->setIgnoreCollisionCheck(colObjA, true); 457 } 458 } 459 } 460 461 void btRigidBody::removeConstraintRef(btTypedConstraint* c) 462 { 463 int index = m_constraintRefs.findLinearSearch(c); 464 //don't remove constraints that are not referenced 465 if(index < m_constraintRefs.size()) 466 { 467 m_constraintRefs.remove(c); 468 btCollisionObject* colObjA = &c->getRigidBodyA(); 469 btCollisionObject* colObjB = &c->getRigidBodyB(); 470 if (colObjA == this) 471 { 472 colObjA->setIgnoreCollisionCheck(colObjB, false); 473 } 474 else 475 { 476 colObjB->setIgnoreCollisionCheck(colObjA, false); 477 } 478 } 479 } 480 481 int btRigidBody::calculateSerializeBufferSize() const 482 { 483 int sz = sizeof(btRigidBodyData); 484 return sz; 485 } 486 487 ///fills the dataBuffer and returns the struct name (and 0 on failure) 488 const char* btRigidBody::serialize(void* dataBuffer, class btSerializer* serializer) const 489 { 490 btRigidBodyData* rbd = (btRigidBodyData*) dataBuffer; 491 492 btCollisionObject::serialize(&rbd->m_collisionObjectData, serializer); 493 494 m_invInertiaTensorWorld.serialize(rbd->m_invInertiaTensorWorld); 495 m_linearVelocity.serialize(rbd->m_linearVelocity); 496 m_angularVelocity.serialize(rbd->m_angularVelocity); 497 rbd->m_inverseMass = m_inverseMass; 498 m_angularFactor.serialize(rbd->m_angularFactor); 499 m_linearFactor.serialize(rbd->m_linearFactor); 500 m_gravity.serialize(rbd->m_gravity); 501 m_gravity_acceleration.serialize(rbd->m_gravity_acceleration); 502 m_invInertiaLocal.serialize(rbd->m_invInertiaLocal); 503 m_totalForce.serialize(rbd->m_totalForce); 504 m_totalTorque.serialize(rbd->m_totalTorque); 505 rbd->m_linearDamping = m_linearDamping; 506 rbd->m_angularDamping = m_angularDamping; 507 rbd->m_additionalDamping = m_additionalDamping; 508 rbd->m_additionalDampingFactor = m_additionalDampingFactor; 509 rbd->m_additionalLinearDampingThresholdSqr = m_additionalLinearDampingThresholdSqr; 510 rbd->m_additionalAngularDampingThresholdSqr = m_additionalAngularDampingThresholdSqr; 511 rbd->m_additionalAngularDampingFactor = m_additionalAngularDampingFactor; 512 rbd->m_linearSleepingThreshold=m_linearSleepingThreshold; 513 rbd->m_angularSleepingThreshold = m_angularSleepingThreshold; 514 515 return btRigidBodyDataName; 516 } 517 518 519 520 void btRigidBody::serializeSingleObject(class btSerializer* serializer) const 521 { 522 btChunk* chunk = serializer->allocate(calculateSerializeBufferSize(),1); 523 const char* structType = serialize(chunk->m_oldPtr, serializer); 524 serializer->finalizeChunk(chunk,structType,BT_RIGIDBODY_CODE,(void*)this); 525 } 526 527 528