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 #include "CcdPhysicsController.h"
17 #include "btBulletDynamicsCommon.h"
19 #include "PHY_IMotionState.h"
20 #include "CcdPhysicsEnvironment.h"
25 ///todo: fill all the empty CcdPhysicsController methods, hook them up to the btRigidBody class
27 //'temporarily' global variables
28 //float gDeactivationTime = 2.f;
29 //bool gDisableDeactivation = false;
30 extern float gDeactivationTime;
31 extern bool gDisableDeactivation;
34 float gLinearSleepingTreshold = 0.8f;
35 float gAngularSleepingTreshold = 1.0f;
38 btVector3 startVel(0,0,0);//-10000);
39 CcdPhysicsController::CcdPhysicsController (const CcdConstructionInfo& ci)
45 m_MotionState = ci.m_MotionState;
46 m_bulletMotionState = 0;
54 if (m_body->getInvMass())
55 m_body->setLinearVelocity(startVel);
60 btTransform CcdPhysicsController::GetTransformFromMotionState(PHY_IMotionState* motionState)
64 motionState->getWorldPosition(tmp[0],tmp[1],tmp[2]);
65 trans.setOrigin(btVector3(tmp[0],tmp[1],tmp[2]));
68 motionState->getWorldOrientation(orn[0],orn[1],orn[2],orn[3]);
69 trans.setRotation(orn);
74 class BlenderBulletMotionState : public btMotionState
76 PHY_IMotionState* m_blenderMotionState;
80 BlenderBulletMotionState(PHY_IMotionState* bms)
81 :m_blenderMotionState(bms)
86 virtual void getWorldTransform(btTransform& worldTrans ) const
91 m_blenderMotionState->getWorldPosition(pos[0],pos[1],pos[2]);
92 m_blenderMotionState->getWorldOrientation(quatOrn[0],quatOrn[1],quatOrn[2],quatOrn[3]);
93 worldTrans.setOrigin(btVector3(pos[0],pos[1],pos[2]));
94 worldTrans.setBasis(btMatrix3x3(btQuaternion(quatOrn[0],quatOrn[1],quatOrn[2],quatOrn[3])));
97 virtual void setWorldTransform(const btTransform& worldTrans)
99 m_blenderMotionState->setWorldPosition(worldTrans.getOrigin().getX(),worldTrans.getOrigin().getY(),worldTrans.getOrigin().getZ());
100 btQuaternion rotQuat = worldTrans.getRotation();
101 m_blenderMotionState->setWorldOrientation(rotQuat[0],rotQuat[1],rotQuat[2],rotQuat[3]);
102 m_blenderMotionState->calculateWorldTransformations();
107 void CcdPhysicsController::CreateRigidbody()
110 btTransform trans = GetTransformFromMotionState(m_cci.m_MotionState);
112 m_bulletMotionState = new BlenderBulletMotionState(m_cci.m_MotionState);
114 m_body = new btRigidBody(m_cci.m_mass,
116 m_cci.m_collisionShape,
117 m_cci.m_localInertiaTensor * m_cci.m_inertiaFactor,
118 m_cci.m_linearDamping,m_cci.m_angularDamping,
119 m_cci.m_friction,m_cci.m_restitution);
124 // init the rigidbody properly
127 //setMassProps this also sets collisionFlags
128 //convert collision flags!
130 m_body->setCollisionFlags(m_body->getCollisionFlags() | m_cci.m_collisionFlags);
132 m_body->setGravity( m_cci.m_gravity);
133 m_body->setDamping(m_cci.m_linearDamping, m_cci.m_angularDamping);
137 CcdPhysicsController::~CcdPhysicsController()
139 //will be reference counted, due to sharing
140 if (m_cci.m_physicsEnv)
141 m_cci.m_physicsEnv->removeCcdPhysicsController(this);
143 delete m_MotionState;
144 if (m_bulletMotionState)
145 delete m_bulletMotionState;
150 SynchronizeMotionStates ynchronizes dynas, kinematic and deformable entities (and do 'late binding')
152 bool CcdPhysicsController::SynchronizeMotionStates(float time)
154 //sync non-static to motionstate, and static from motionstate (todo: add kinematic etc.)
156 if (!m_body->isStaticObject())
158 const btVector3& worldPos = m_body->getCenterOfMassPosition();
159 m_MotionState->setWorldPosition(worldPos[0],worldPos[1],worldPos[2]);
161 const btQuaternion& worldquat = m_body->getOrientation();
162 m_MotionState->setWorldOrientation(worldquat[0],worldquat[1],worldquat[2],worldquat[3]);
164 m_MotionState->calculateWorldTransformations();
167 m_MotionState->getWorldScaling(scale[0],scale[1],scale[2]);
168 btVector3 scaling(scale[0],scale[1],scale[2]);
169 GetCollisionShape()->setLocalScaling(scaling);
173 btQuaternion worldquat;
175 /* m_MotionState->getWorldPosition(worldPos[0],worldPos[1],worldPos[2]);
176 m_MotionState->getWorldOrientation(worldquat[0],worldquat[1],worldquat[2],worldquat[3]);
177 btTransform oldTrans = m_body->getCenterOfMassTransform();
178 btTransform newTrans(worldquat,worldPos);
180 m_body->setCenterOfMassTransform(newTrans);
181 //need to keep track of previous position for friction effects...
183 m_MotionState->calculateWorldTransformations();
186 m_MotionState->getWorldScaling(scale[0],scale[1],scale[2]);
187 btVector3 scaling(scale[0],scale[1],scale[2]);
188 GetCollisionShape()->setLocalScaling(scaling);
195 WriteMotionStateToDynamics synchronizes dynas, kinematic and deformable entities (and do 'late binding')
198 void CcdPhysicsController::WriteMotionStateToDynamics(bool nondynaonly)
202 void CcdPhysicsController::WriteDynamicsToMotionState()
205 // controller replication
206 void CcdPhysicsController::PostProcessReplica(class PHY_IMotionState* motionstate,class PHY_IPhysicsController* parentctrl)
208 m_MotionState = motionstate;
215 m_cci.m_physicsEnv->addCcdPhysicsController(this);
218 /* SM_Object* dynaparent=0;
219 SumoPhysicsController* sumoparentctrl = (SumoPhysicsController* )parentctrl;
223 dynaparent = sumoparentctrl->GetSumoObject();
226 SM_Object* orgsumoobject = m_sumoObj;
229 m_sumoObj = new SM_Object(
230 orgsumoobject->getShapeHandle(),
231 orgsumoobject->getMaterialProps(),
232 orgsumoobject->getShapeProps(),
235 m_sumoObj->setRigidBody(orgsumoobject->isRigidBody());
237 m_sumoObj->setMargin(orgsumoobject->getMargin());
238 m_sumoObj->setPosition(orgsumoobject->getPosition());
239 m_sumoObj->setOrientation(orgsumoobject->getOrientation());
240 //if it is a dyna, register for a callback
241 m_sumoObj->registerCallback(*this);
243 m_sumoScene->add(* (m_sumoObj));
251 void CcdPhysicsController::RelativeTranslate(float dlocX,float dlocY,float dlocZ,bool local)
255 m_body->activate(true);
256 if (m_body->isStaticObject())
258 m_body->setCollisionFlags(m_body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
262 btVector3 dloc(dlocX,dlocY,dlocZ);
263 btTransform xform = m_body->getCenterOfMassTransform();
267 dloc = xform.getBasis()*dloc;
270 xform.setOrigin(xform.getOrigin() + dloc);
271 m_body->setCenterOfMassTransform(xform);
276 void CcdPhysicsController::RelativeRotate(const float rotval[9],bool local)
280 m_body->activate(true);
281 if (m_body->isStaticObject())
283 m_body->setCollisionFlags(m_body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
286 btMatrix3x3 drotmat( rotval[0],rotval[1],rotval[2],
287 rotval[4],rotval[5],rotval[6],
288 rotval[8],rotval[9],rotval[10]);
291 btMatrix3x3 currentOrn;
292 GetWorldOrientation(currentOrn);
294 btTransform xform = m_body->getCenterOfMassTransform();
296 xform.setBasis(xform.getBasis()*(local ?
297 drotmat : (currentOrn.inverse() * drotmat * currentOrn)));
299 m_body->setCenterOfMassTransform(xform);
304 void CcdPhysicsController::GetWorldOrientation(btMatrix3x3& mat)
307 m_MotionState->getWorldOrientation(orn[0],orn[1],orn[2],orn[3]);
308 btQuaternion quat(orn[0],orn[1],orn[2],orn[3]);
309 mat.setRotation(quat);
312 void CcdPhysicsController::getOrientation(float &quatImag0,float &quatImag1,float &quatImag2,float &quatReal)
314 btQuaternion q = m_body->getCenterOfMassTransform().getRotation();
320 void CcdPhysicsController::setOrientation(float quatImag0,float quatImag1,float quatImag2,float quatReal)
322 m_body->activate(true);
323 if (m_body->isStaticObject())
325 m_body->setCollisionFlags(m_body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
328 m_MotionState->setWorldOrientation(quatImag0,quatImag1,quatImag2,quatReal);
329 btTransform xform = m_body->getCenterOfMassTransform();
330 xform.setRotation(btQuaternion(quatImag0,quatImag1,quatImag2,quatReal));
331 m_body->setCenterOfMassTransform(xform);
335 void CcdPhysicsController::setPosition(float posX,float posY,float posZ)
337 m_body->activate(true);
338 if (m_body->isStaticObject())
340 m_body->setCollisionFlags(m_body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
342 m_MotionState->setWorldPosition(posX,posY,posZ);
343 btTransform xform = m_body->getCenterOfMassTransform();
344 xform.setOrigin(btVector3(posX,posY,posZ));
345 m_body->setCenterOfMassTransform(xform);
348 void CcdPhysicsController::resolveCombinedVelocities(float linvelX,float linvelY,float linvelZ,float angVelX,float angVelY,float angVelZ)
352 void CcdPhysicsController::getPosition(PHY__Vector3& pos) const
354 const btTransform& xform = m_body->getCenterOfMassTransform();
355 pos[0] = xform.getOrigin().x();
356 pos[1] = xform.getOrigin().y();
357 pos[2] = xform.getOrigin().z();
360 void CcdPhysicsController::setScaling(float scaleX,float scaleY,float scaleZ)
362 if (!btFuzzyZero(m_cci.m_scaling.x()-scaleX) ||
363 !btFuzzyZero(m_cci.m_scaling.y()-scaleY) ||
364 !btFuzzyZero(m_cci.m_scaling.z()-scaleZ))
366 m_cci.m_scaling = btVector3(scaleX,scaleY,scaleZ);
368 if (m_body && m_body->getCollisionShape())
370 m_body->getCollisionShape()->setLocalScaling(m_cci.m_scaling);
371 m_body->getCollisionShape()->calculateLocalInertia(m_cci.m_mass, m_cci.m_localInertiaTensor);
372 m_body->setMassProps(m_cci.m_mass, m_cci.m_localInertiaTensor * m_cci.m_inertiaFactor);
378 void CcdPhysicsController::ApplyTorque(float torqueX,float torqueY,float torqueZ,bool local)
380 btVector3 torque(torqueX,torqueY,torqueZ);
381 btTransform xform = m_body->getCenterOfMassTransform();
382 if (torque.length2() > (SIMD_EPSILON*SIMD_EPSILON))
388 torque = xform.getBasis()*torque;
390 m_body->applyTorque(torque);
393 void CcdPhysicsController::ApplyForce(float forceX,float forceY,float forceZ,bool local)
395 btVector3 force(forceX,forceY,forceZ);
397 if (force.length2() > (SIMD_EPSILON*SIMD_EPSILON))
403 btTransform xform = m_body->getCenterOfMassTransform();
406 force = xform.getBasis()*force;
408 m_body->applyCentralForce(force);
410 void CcdPhysicsController::SetAngularVelocity(float ang_velX,float ang_velY,float ang_velZ,bool local)
412 btVector3 angvel(ang_velX,ang_velY,ang_velZ);
413 if (angvel.length2() > (SIMD_EPSILON*SIMD_EPSILON))
415 m_body->activate(true);
419 btTransform xform = m_body->getCenterOfMassTransform();
422 angvel = xform.getBasis()*angvel;
425 m_body->setAngularVelocity(angvel);
429 void CcdPhysicsController::SetLinearVelocity(float lin_velX,float lin_velY,float lin_velZ,bool local)
432 btVector3 linVel(lin_velX,lin_velY,lin_velZ);
433 if (linVel.length2() > (SIMD_EPSILON*SIMD_EPSILON))
435 m_body->activate(true);
439 btTransform xform = m_body->getCenterOfMassTransform();
442 linVel = xform.getBasis()*linVel;
444 m_body->setLinearVelocity(linVel);
447 void CcdPhysicsController::applyImpulse(float attachX,float attachY,float attachZ, float impulseX,float impulseY,float impulseZ)
449 btVector3 impulse(impulseX,impulseY,impulseZ);
451 if (impulse.length2() > (SIMD_EPSILON*SIMD_EPSILON))
455 btVector3 pos(attachX,attachY,attachZ);
459 m_body->applyImpulse(impulse,pos);
463 void CcdPhysicsController::SetActive(bool active)
466 // reading out information from physics
467 void CcdPhysicsController::GetLinearVelocity(float& linvX,float& linvY,float& linvZ)
469 const btVector3& linvel = this->m_body->getLinearVelocity();
476 void CcdPhysicsController::GetAngularVelocity(float& angVelX,float& angVelY,float& angVelZ)
478 const btVector3& angvel= m_body->getAngularVelocity();
479 angVelX = angvel.x();
480 angVelY = angvel.y();
481 angVelZ = angvel.z();
484 void CcdPhysicsController::GetVelocity(const float posX,const float posY,const float posZ,float& linvX,float& linvY,float& linvZ)
486 btVector3 pos(posX,posY,posZ);
487 btVector3 rel_pos = pos-m_body->getCenterOfMassPosition();
488 btVector3 linvel = m_body->getVelocityInLocalPoint(rel_pos);
493 void CcdPhysicsController::getReactionForce(float& forceX,float& forceY,float& forceZ)
497 // dyna's that are rigidbody are free in orientation, dyna's with non-rigidbody are restricted
498 void CcdPhysicsController::setRigidBody(bool rigid)
503 btVector3 inertia = m_body->getInvInertiaDiagLocal();
505 m_body->setInvInertiaDiagLocal(inertia);
506 m_body->updateInertiaTensor();
510 // clientinfo for raycasts for example
511 void* CcdPhysicsController::getNewClientInfo()
513 return m_newClientInfo;
515 void CcdPhysicsController::setNewClientInfo(void* clientinfo)
517 m_newClientInfo = clientinfo;
521 void CcdPhysicsController::UpdateDeactivation(float timeStep)
523 m_body->updateDeactivation( timeStep);
526 bool CcdPhysicsController::wantsSleeping()
529 return m_body->wantsSleeping();
532 PHY_IPhysicsController* CcdPhysicsController::GetReplica()
534 //very experimental, shape sharing is not implemented yet.
535 //just support btSphereShape/ConeShape for now
537 CcdConstructionInfo cinfo = m_cci;
538 if (cinfo.m_collisionShape)
540 switch (cinfo.m_collisionShape->getShapeType())
542 case SPHERE_SHAPE_PROXYTYPE:
544 btSphereShape* orgShape = (btSphereShape*)cinfo.m_collisionShape;
545 cinfo.m_collisionShape = new btSphereShape(*orgShape);
549 case CONE_SHAPE_PROXYTYPE:
551 btConeShape* orgShape = (btConeShape*)cinfo.m_collisionShape;
552 cinfo.m_collisionShape = new btConeShape(*orgShape);
564 cinfo.m_MotionState = new DefaultMotionState();
566 CcdPhysicsController* replica = new CcdPhysicsController(cinfo);
570 ///////////////////////////////////////////////////////////
571 ///A small utility class, DefaultMotionState
573 ///////////////////////////////////////////////////////////
575 DefaultMotionState::DefaultMotionState()
577 m_worldTransform.setIdentity();
578 m_localScaling.setValue(1.f,1.f,1.f);
582 DefaultMotionState::~DefaultMotionState()
587 void DefaultMotionState::getWorldPosition(float& posX,float& posY,float& posZ)
589 posX = m_worldTransform.getOrigin().x();
590 posY = m_worldTransform.getOrigin().y();
591 posZ = m_worldTransform.getOrigin().z();
594 void DefaultMotionState::getWorldScaling(float& scaleX,float& scaleY,float& scaleZ)
596 scaleX = m_localScaling.getX();
597 scaleY = m_localScaling.getY();
598 scaleZ = m_localScaling.getZ();
601 void DefaultMotionState::getWorldOrientation(float& quatIma0,float& quatIma1,float& quatIma2,float& quatReal)
603 quatIma0 = m_worldTransform.getRotation().x();
604 quatIma1 = m_worldTransform.getRotation().y();
605 quatIma2 = m_worldTransform.getRotation().z();
606 quatReal = m_worldTransform.getRotation()[3];
609 void DefaultMotionState::setWorldPosition(float posX,float posY,float posZ)
611 btPoint3 pos(posX,posY,posZ);
612 m_worldTransform.setOrigin( pos );
615 void DefaultMotionState::setWorldOrientation(float quatIma0,float quatIma1,float quatIma2,float quatReal)
617 btQuaternion orn(quatIma0,quatIma1,quatIma2,quatReal);
618 m_worldTransform.setRotation( orn );
621 void DefaultMotionState::calculateWorldTransformations()