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();
384 torque = xform.getBasis()*torque;
386 m_body->applyTorque(torque);
389 void CcdPhysicsController::ApplyForce(float forceX,float forceY,float forceZ,bool local)
391 btVector3 force(forceX,forceY,forceZ);
392 btTransform xform = m_body->getCenterOfMassTransform();
395 force = xform.getBasis()*force;
397 m_body->applyCentralForce(force);
399 void CcdPhysicsController::SetAngularVelocity(float ang_velX,float ang_velY,float ang_velZ,bool local)
401 btVector3 angvel(ang_velX,ang_velY,ang_velZ);
402 if (angvel.length2() > (SIMD_EPSILON*SIMD_EPSILON))
404 m_body->activate(true);
408 btTransform xform = m_body->getCenterOfMassTransform();
411 angvel = xform.getBasis()*angvel;
414 m_body->setAngularVelocity(angvel);
418 void CcdPhysicsController::SetLinearVelocity(float lin_velX,float lin_velY,float lin_velZ,bool local)
421 btVector3 linVel(lin_velX,lin_velY,lin_velZ);
422 if (linVel.length2() > (SIMD_EPSILON*SIMD_EPSILON))
424 m_body->activate(true);
428 btTransform xform = m_body->getCenterOfMassTransform();
431 linVel = xform.getBasis()*linVel;
433 m_body->setLinearVelocity(linVel);
436 void CcdPhysicsController::applyImpulse(float attachX,float attachY,float attachZ, float impulseX,float impulseY,float impulseZ)
438 btVector3 impulse(impulseX,impulseY,impulseZ);
440 if (impulse.length2() > (SIMD_EPSILON*SIMD_EPSILON))
444 btVector3 pos(attachX,attachY,attachZ);
448 m_body->applyImpulse(impulse,pos);
452 void CcdPhysicsController::SetActive(bool active)
455 // reading out information from physics
456 void CcdPhysicsController::GetLinearVelocity(float& linvX,float& linvY,float& linvZ)
458 const btVector3& linvel = this->m_body->getLinearVelocity();
465 void CcdPhysicsController::GetAngularVelocity(float& angVelX,float& angVelY,float& angVelZ)
467 const btVector3& angvel= m_body->getAngularVelocity();
468 angVelX = angvel.x();
469 angVelY = angvel.y();
470 angVelZ = angvel.z();
473 void CcdPhysicsController::GetVelocity(const float posX,const float posY,const float posZ,float& linvX,float& linvY,float& linvZ)
475 btVector3 pos(posX,posY,posZ);
476 btVector3 rel_pos = pos-m_body->getCenterOfMassPosition();
477 btVector3 linvel = m_body->getVelocityInLocalPoint(rel_pos);
482 void CcdPhysicsController::getReactionForce(float& forceX,float& forceY,float& forceZ)
486 // dyna's that are rigidbody are free in orientation, dyna's with non-rigidbody are restricted
487 void CcdPhysicsController::setRigidBody(bool rigid)
492 btVector3 inertia = m_body->getInvInertiaDiagLocal();
494 m_body->setInvInertiaDiagLocal(inertia);
495 m_body->updateInertiaTensor();
499 // clientinfo for raycasts for example
500 void* CcdPhysicsController::getNewClientInfo()
502 return m_newClientInfo;
504 void CcdPhysicsController::setNewClientInfo(void* clientinfo)
506 m_newClientInfo = clientinfo;
510 void CcdPhysicsController::UpdateDeactivation(float timeStep)
512 m_body->updateDeactivation( timeStep);
515 bool CcdPhysicsController::wantsSleeping()
518 return m_body->wantsSleeping();
521 PHY_IPhysicsController* CcdPhysicsController::GetReplica()
523 //very experimental, shape sharing is not implemented yet.
524 //just support btSphereShape/ConeShape for now
526 CcdConstructionInfo cinfo = m_cci;
527 if (cinfo.m_collisionShape)
529 switch (cinfo.m_collisionShape->getShapeType())
531 case SPHERE_SHAPE_PROXYTYPE:
533 btSphereShape* orgShape = (btSphereShape*)cinfo.m_collisionShape;
534 cinfo.m_collisionShape = new btSphereShape(*orgShape);
538 case CONE_SHAPE_PROXYTYPE:
540 btConeShape* orgShape = (btConeShape*)cinfo.m_collisionShape;
541 cinfo.m_collisionShape = new btConeShape(*orgShape);
553 cinfo.m_MotionState = new DefaultMotionState();
555 CcdPhysicsController* replica = new CcdPhysicsController(cinfo);
559 ///////////////////////////////////////////////////////////
560 ///A small utility class, DefaultMotionState
562 ///////////////////////////////////////////////////////////
564 DefaultMotionState::DefaultMotionState()
566 m_worldTransform.setIdentity();
567 m_localScaling.setValue(1.f,1.f,1.f);
571 DefaultMotionState::~DefaultMotionState()
576 void DefaultMotionState::getWorldPosition(float& posX,float& posY,float& posZ)
578 posX = m_worldTransform.getOrigin().x();
579 posY = m_worldTransform.getOrigin().y();
580 posZ = m_worldTransform.getOrigin().z();
583 void DefaultMotionState::getWorldScaling(float& scaleX,float& scaleY,float& scaleZ)
585 scaleX = m_localScaling.getX();
586 scaleY = m_localScaling.getY();
587 scaleZ = m_localScaling.getZ();
590 void DefaultMotionState::getWorldOrientation(float& quatIma0,float& quatIma1,float& quatIma2,float& quatReal)
592 quatIma0 = m_worldTransform.getRotation().x();
593 quatIma1 = m_worldTransform.getRotation().y();
594 quatIma2 = m_worldTransform.getRotation().z();
595 quatReal = m_worldTransform.getRotation()[3];
598 void DefaultMotionState::setWorldPosition(float posX,float posY,float posZ)
600 btPoint3 pos(posX,posY,posZ);
601 m_worldTransform.setOrigin( pos );
604 void DefaultMotionState::setWorldOrientation(float quatIma0,float quatIma1,float quatIma2,float quatReal)
606 btQuaternion orn(quatIma0,quatIma1,quatIma2,quatReal);
607 m_worldTransform.setRotation( orn );
610 void DefaultMotionState::calculateWorldTransformations()