Blender  V2.59
KX_BulletPhysicsController.cpp
Go to the documentation of this file.
00001 
00004 //under visual studio the #define in KX_ConvertPhysicsObject.h is quicker for recompilation
00005 #include "KX_ConvertPhysicsObject.h"
00006 
00007 #ifdef USE_BULLET
00008 
00009 #include "KX_BulletPhysicsController.h"
00010 
00011 #include "btBulletDynamicsCommon.h"
00012 #include "SG_Spatial.h"
00013 
00014 #include "KX_GameObject.h"
00015 #include "KX_MotionState.h"
00016 #include "KX_ClientObjectInfo.h"
00017 
00018 #include "PHY_IPhysicsEnvironment.h"
00019 #include "CcdPhysicsEnvironment.h"
00020 #include "BulletSoftBody/btSoftBody.h"
00021 
00022 
00023 KX_BulletPhysicsController::KX_BulletPhysicsController (const CcdConstructionInfo& ci, bool dyna, bool sensor, bool compound)
00024 : KX_IPhysicsController(dyna,sensor,compound,(PHY_IPhysicsController*)this),
00025 CcdPhysicsController(ci),
00026 m_savedCollisionFlags(0),
00027 m_savedCollisionFilterGroup(0),
00028 m_savedCollisionFilterMask(0),
00029 m_savedMass(0.0),
00030 m_savedDyna(false),
00031 m_suspended(false),
00032 m_bulletChildShape(NULL)
00033 {
00034 }
00035         
00036 KX_BulletPhysicsController::~KX_BulletPhysicsController ()
00037 {
00038         // The game object has a direct link to 
00039         if (m_pObject)
00040         {
00041                 // If we cheat in SetObject, we must also cheat here otherwise the 
00042                 // object will still things it has a physical controller
00043                 // Note that it requires that m_pObject is reset in case the object is deleted
00044                 // before the controller (usual case, see KX_Scene::RemoveNodeDestructObjec)
00045                 // The non usual case is when the object is not deleted because its reference is hanging
00046                 // in a AddObject actuator but the node is deleted. This case is covered here.
00047                 KX_GameObject* gameobj = (KX_GameObject*)       m_pObject->GetSGClientObject();
00048                 gameobj->SetPhysicsController(NULL,false);
00049         }
00050 }
00051 
00052 void    KX_BulletPhysicsController::resolveCombinedVelocities(float linvelX,float linvelY,float linvelZ,float angVelX,float angVelY,float angVelZ)
00053 {
00054         CcdPhysicsController::resolveCombinedVelocities(linvelX,linvelY,linvelZ,angVelX,angVelY,angVelZ);
00055 
00056 }
00057 
00058 
00060         //      KX_IPhysicsController interface
00062 
00063 void    KX_BulletPhysicsController::applyImpulse(const MT_Point3& attach, const MT_Vector3& impulse)
00064 {
00065                 CcdPhysicsController::applyImpulse(attach[0],attach[1],attach[2],impulse[0],impulse[1],impulse[2]);
00066 
00067 }
00068 
00069 float KX_BulletPhysicsController::GetLinVelocityMin()
00070 {
00071         return (float)CcdPhysicsController::GetLinVelocityMin();
00072 }
00073 void  KX_BulletPhysicsController::SetLinVelocityMin(float val)
00074 {
00075         CcdPhysicsController::SetLinVelocityMin(val);
00076 }
00077 
00078 float KX_BulletPhysicsController::GetLinVelocityMax()
00079 {
00080         return (float)CcdPhysicsController::GetLinVelocityMax();
00081 }
00082 void  KX_BulletPhysicsController::SetLinVelocityMax(float val)
00083 {
00084         CcdPhysicsController::SetLinVelocityMax(val);
00085 }
00086 
00087 void    KX_BulletPhysicsController::SetObject (SG_IObject* object)
00088 {
00089         SG_Controller::SetObject(object);
00090 
00091         // cheating here...
00092         //should not be necessary, is it for duplicates ?
00093 
00094         KX_GameObject* gameobj = (KX_GameObject*)       object->GetSGClientObject();
00095         gameobj->SetPhysicsController(this,gameobj->IsDynamic());
00096         CcdPhysicsController::setNewClientInfo(gameobj->getClientInfo());
00097 
00098         if (m_bSensor)
00099         {
00100                 // use a different callback function for sensor object, 
00101                 // bullet will not synchronize, we must do it explicitely
00102                 SG_Callbacks& callbacks = gameobj->GetSGNode()->GetCallBackFunctions();
00103                 callbacks.m_updatefunc = KX_GameObject::SynchronizeTransformFunc;
00104         } 
00105 }
00106 
00107 MT_Scalar KX_BulletPhysicsController::GetRadius()
00108 {
00109         return MT_Scalar(CcdPhysicsController::GetRadius());
00110 }
00111 
00112 void    KX_BulletPhysicsController::setMargin (float collisionMargin)
00113 {
00114         CcdPhysicsController::SetMargin(collisionMargin);
00115 }
00116 void    KX_BulletPhysicsController::RelativeTranslate(const MT_Vector3& dloc,bool local)
00117 {
00118         CcdPhysicsController::RelativeTranslate(dloc[0],dloc[1],dloc[2],local);
00119 
00120 }
00121 
00122 void    KX_BulletPhysicsController::RelativeRotate(const MT_Matrix3x3& drot,bool local)
00123 {
00124         float   rotval[12];
00125         drot.getValue(rotval);
00126         CcdPhysicsController::RelativeRotate(rotval,local);
00127 }
00128 
00129 void    KX_BulletPhysicsController::ApplyTorque(const MT_Vector3& torque,bool local)
00130 {
00131                 CcdPhysicsController::ApplyTorque(torque.x(),torque.y(),torque.z(),local);
00132 }
00133 void    KX_BulletPhysicsController::ApplyForce(const MT_Vector3& force,bool local)
00134 {
00135         CcdPhysicsController::ApplyForce(force.x(),force.y(),force.z(),local);
00136 }
00137 MT_Vector3 KX_BulletPhysicsController::GetLinearVelocity()
00138 {
00139         float angVel[3];
00140         //CcdPhysicsController::GetAngularVelocity(angVel[0],angVel[1],angVel[2]);
00141         CcdPhysicsController::GetLinearVelocity(angVel[0],angVel[1],angVel[2]);//rcruiz
00142         return MT_Vector3(angVel[0],angVel[1],angVel[2]);
00143 }
00144 MT_Vector3 KX_BulletPhysicsController::GetAngularVelocity()
00145 {
00146         float angVel[3];
00147         //CcdPhysicsController::GetAngularVelocity(angVel[0],angVel[1],angVel[2]);
00148         CcdPhysicsController::GetAngularVelocity(angVel[0],angVel[1],angVel[2]);//rcruiz
00149         return MT_Vector3(angVel[0],angVel[1],angVel[2]);
00150 }
00151 MT_Vector3 KX_BulletPhysicsController::GetVelocity(const MT_Point3& pos)
00152 {
00153         float linVel[3];
00154         CcdPhysicsController::GetVelocity(pos[0], pos[1], pos[2], linVel[0],linVel[1],linVel[2]);
00155         return MT_Vector3(linVel[0],linVel[1],linVel[2]);
00156 }
00157 
00158 void    KX_BulletPhysicsController::SetAngularVelocity(const MT_Vector3& ang_vel,bool local)
00159 {
00160         CcdPhysicsController::SetAngularVelocity(ang_vel.x(),ang_vel.y(),ang_vel.z(),local);
00161 
00162 }
00163 void    KX_BulletPhysicsController::SetLinearVelocity(const MT_Vector3& lin_vel,bool local)
00164 {
00165         CcdPhysicsController::SetLinearVelocity(lin_vel.x(),lin_vel.y(),lin_vel.z(),local);
00166 }
00167 void    KX_BulletPhysicsController::getOrientation(MT_Quaternion& orn)
00168 {
00169         float myorn[4];
00170         CcdPhysicsController::getOrientation(myorn[0],myorn[1],myorn[2],myorn[3]);
00171         orn = MT_Quaternion(myorn[0],myorn[1],myorn[2],myorn[3]);
00172 }
00173 void KX_BulletPhysicsController::setOrientation(const MT_Matrix3x3& orn)
00174 {
00175         btMatrix3x3 btmat(orn[0][0], orn[0][1], orn[0][2], orn[1][0], orn[1][1], orn[1][2], orn[2][0], orn[2][1], orn[2][2]);
00176         CcdPhysicsController::setWorldOrientation(btmat);
00177 }
00178 void KX_BulletPhysicsController::setPosition(const MT_Point3& pos)
00179 {
00180         CcdPhysicsController::setPosition(pos.x(),pos.y(),pos.z());
00181 }
00182 void KX_BulletPhysicsController::setScaling(const MT_Vector3& scaling)
00183 {
00184         CcdPhysicsController::setScaling(scaling.x(),scaling.y(),scaling.z());
00185 }
00186 void KX_BulletPhysicsController::SetTransform()
00187 {
00188         btVector3 pos;
00189         btVector3 scale;
00190         float ori[12];
00191         m_MotionState->getWorldPosition(pos.m_floats[0],pos.m_floats[1],pos.m_floats[2]);
00192         m_MotionState->getWorldScaling(scale.m_floats[0],scale.m_floats[1],scale.m_floats[2]);
00193         m_MotionState->getWorldOrientation(ori);
00194         btMatrix3x3 rot(ori[0], ori[4], ori[8],
00195                                         ori[1], ori[5], ori[9],
00196                                         ori[2], ori[6], ori[10]);
00197         CcdPhysicsController::forceWorldTransform(rot, pos);
00198 }
00199 
00200 MT_Scalar       KX_BulletPhysicsController::GetMass()
00201 {
00202         if (GetSoftBody())
00203                 return GetSoftBody()->getTotalMass();
00204         
00205         MT_Scalar invmass = 0.f;
00206         if (GetRigidBody())
00207                 invmass = GetRigidBody()->getInvMass();
00208         if (invmass)
00209                 return 1.f/invmass;
00210         return 0.f;
00211 
00212 }
00213 
00214 MT_Vector3 KX_BulletPhysicsController::GetLocalInertia()
00215 {
00216     MT_Vector3 inertia(0.f, 0.f, 0.f);
00217     btVector3 inv_inertia;
00218     if (GetRigidBody()) {
00219         inv_inertia = GetRigidBody()->getInvInertiaDiagLocal();
00220                 if (!btFuzzyZero(inv_inertia.getX()) && 
00221                         !btFuzzyZero(inv_inertia.getY()) && 
00222                         !btFuzzyZero(inv_inertia.getZ()))
00223                         inertia = MT_Vector3(1.f/inv_inertia.getX(), 1.f/inv_inertia.getY(), 1.f/inv_inertia.getZ());
00224     }
00225     return inertia;
00226 }
00227 
00228 MT_Vector3      KX_BulletPhysicsController::getReactionForce()
00229 {
00230         assert(0);
00231         return MT_Vector3(0.f,0.f,0.f);
00232 }
00233 void    KX_BulletPhysicsController::setRigidBody(bool rigid)
00234 {
00235 }
00236 
00237 /* This function dynamically adds the collision shape of another controller to
00238    the current controller shape provided it is a compound shape.
00239    The idea is that dynamic parenting on a compound object will dynamically extend the shape
00240 */
00241 void    KX_BulletPhysicsController::AddCompoundChild(KX_IPhysicsController* child)
00242 { 
00243         if (child == NULL || !IsCompound())
00244                 return;
00245         // other controller must be a bullet controller too
00246         // verify that body and shape exist and match
00247         KX_BulletPhysicsController* childCtrl = dynamic_cast<KX_BulletPhysicsController*>(child);
00248         btRigidBody* rootBody = GetRigidBody();
00249         btRigidBody* childBody = childCtrl->GetRigidBody();
00250         if (!rootBody || !childBody)
00251                 return;
00252         const btCollisionShape* rootShape = rootBody->getCollisionShape();
00253         const btCollisionShape* childShape = childBody->getCollisionShape();
00254         if (!rootShape || 
00255                 !childShape || 
00256                 rootShape->getShapeType() != COMPOUND_SHAPE_PROXYTYPE ||
00257                 childShape->getShapeType() == COMPOUND_SHAPE_PROXYTYPE)
00258                 return;
00259         btCompoundShape* compoundShape = (btCompoundShape*)rootShape;
00260         // compute relative transformation between parent and child
00261         btTransform rootTrans;
00262         btTransform childTrans;
00263         rootBody->getMotionState()->getWorldTransform(rootTrans);
00264         childBody->getMotionState()->getWorldTransform(childTrans);
00265         btVector3 rootScale = rootShape->getLocalScaling();
00266         rootScale[0] = 1.0/rootScale[0];
00267         rootScale[1] = 1.0/rootScale[1];
00268         rootScale[2] = 1.0/rootScale[2];
00269         // relative scale = child_scale/parent_scale
00270         btVector3 relativeScale = childShape->getLocalScaling()*rootScale;
00271         btMatrix3x3 rootRotInverse = rootTrans.getBasis().transpose();  
00272         // relative pos = parent_rot^-1 * ((parent_pos-child_pos)/parent_scale)
00273         btVector3 relativePos = rootRotInverse*((childTrans.getOrigin()-rootTrans.getOrigin())*rootScale);
00274         // relative rot = parent_rot^-1 * child_rot
00275         btMatrix3x3 relativeRot = rootRotInverse*childTrans.getBasis();
00276         // create a proxy shape info to store the transformation
00277         CcdShapeConstructionInfo* proxyShapeInfo = new CcdShapeConstructionInfo();
00278         // store the transformation to this object shapeinfo
00279         proxyShapeInfo->m_childTrans.setOrigin(relativePos);
00280         proxyShapeInfo->m_childTrans.setBasis(relativeRot);
00281         proxyShapeInfo->m_childScale.setValue(relativeScale[0], relativeScale[1], relativeScale[2]);
00282         // we will need this to make sure that we remove the right proxy later when unparenting
00283         proxyShapeInfo->m_userData = childCtrl;
00284         proxyShapeInfo->SetProxy(childCtrl->GetShapeInfo()->AddRef());
00285         // add to parent compound shapeinfo (increments ref count)
00286         GetShapeInfo()->AddShape(proxyShapeInfo);
00287         // create new bullet collision shape from the object shapeinfo and set scaling
00288         btCollisionShape* newChildShape = proxyShapeInfo->CreateBulletShape(childCtrl->GetMargin(), childCtrl->getConstructionInfo().m_bGimpact, true);
00289         newChildShape->setLocalScaling(relativeScale);
00290         // add bullet collision shape to parent compound collision shape
00291         compoundShape->addChildShape(proxyShapeInfo->m_childTrans,newChildShape);
00292         // proxyShapeInfo is not needed anymore, release it
00293         proxyShapeInfo->Release();
00294         // remember we created this shape
00295         childCtrl->m_bulletChildShape = newChildShape;
00296         // recompute inertia of parent
00297         if (!rootBody->isStaticOrKinematicObject())
00298         {
00299                 btVector3 localInertia;
00300                 float mass = 1.f/rootBody->getInvMass();
00301                 compoundShape->calculateLocalInertia(mass,localInertia);
00302                 rootBody->setMassProps(mass,localInertia);
00303         }
00304         // must update the broadphase cache,
00305         GetPhysicsEnvironment()->refreshCcdPhysicsController(this);
00306         // remove the children
00307         GetPhysicsEnvironment()->disableCcdPhysicsController(childCtrl);
00308 }
00309 
00310 /* Reverse function of the above, it will remove a shape from a compound shape
00311    provided that the former was added to the later using  AddCompoundChild()
00312 */
00313 void    KX_BulletPhysicsController::RemoveCompoundChild(KX_IPhysicsController* child)
00314 { 
00315         if (child == NULL || !IsCompound())
00316                 return;
00317         // other controller must be a bullet controller too
00318         // verify that body and shape exist and match
00319         KX_BulletPhysicsController* childCtrl = dynamic_cast<KX_BulletPhysicsController*>(child);
00320         btRigidBody* rootBody = GetRigidBody();
00321         btRigidBody* childBody = childCtrl->GetRigidBody();
00322         if (!rootBody || !childBody)
00323                 return;
00324         const btCollisionShape* rootShape = rootBody->getCollisionShape();
00325         if (!rootShape || 
00326                 rootShape->getShapeType() != COMPOUND_SHAPE_PROXYTYPE)
00327                 return;
00328         btCompoundShape* compoundShape = (btCompoundShape*)rootShape;
00329         // retrieve the shapeInfo
00330         CcdShapeConstructionInfo* childShapeInfo = childCtrl->GetShapeInfo();
00331         CcdShapeConstructionInfo* rootShapeInfo = GetShapeInfo();
00332         // and verify that the child is part of the parent
00333         int i = rootShapeInfo->FindChildShape(childShapeInfo, childCtrl);
00334         if (i < 0)
00335                 return;
00336         rootShapeInfo->RemoveChildShape(i);
00337         if (childCtrl->m_bulletChildShape)
00338         {
00339                 int numChildren = compoundShape->getNumChildShapes();
00340                 for (i=0; i<numChildren; i++)
00341                 {
00342                         if (compoundShape->getChildShape(i) == childCtrl->m_bulletChildShape)
00343                         {
00344                                 compoundShape->removeChildShapeByIndex(i);
00345                                 compoundShape->recalculateLocalAabb();
00346                                 break;
00347                         }
00348                 }
00349                 delete childCtrl->m_bulletChildShape;
00350                 childCtrl->m_bulletChildShape = NULL;
00351         }
00352         // recompute inertia of parent
00353         if (!rootBody->isStaticOrKinematicObject())
00354         {
00355                 btVector3 localInertia;
00356                 float mass = 1.f/rootBody->getInvMass();
00357                 compoundShape->calculateLocalInertia(mass,localInertia);
00358                 rootBody->setMassProps(mass,localInertia);
00359         }
00360         // must update the broadphase cache,
00361         GetPhysicsEnvironment()->refreshCcdPhysicsController(this);
00362         // reactivate the children
00363         GetPhysicsEnvironment()->enableCcdPhysicsController(childCtrl);
00364 }
00365 
00366 void KX_BulletPhysicsController::SetMass(MT_Scalar newmass)
00367 {
00368         btRigidBody *body = GetRigidBody();
00369         if (body && !m_suspended && newmass>MT_EPSILON && GetMass()>MT_EPSILON)
00370         {
00371                 btVector3 grav = body->getGravity();
00372                 btVector3 accel = grav / GetMass();
00373                 
00374                 btBroadphaseProxy* handle = body->getBroadphaseHandle();
00375                 GetPhysicsEnvironment()->updateCcdPhysicsController(this, 
00376                         newmass,
00377                         body->getCollisionFlags(),
00378                         handle->m_collisionFilterGroup, 
00379                         handle->m_collisionFilterMask);
00380                 body->setGravity(accel);
00381         }
00382 }
00383 
00384 void    KX_BulletPhysicsController::SuspendDynamics(bool ghost)
00385 {
00386         btRigidBody *body = GetRigidBody();
00387         if (body && !m_suspended && !IsSensor())
00388         {
00389                 btBroadphaseProxy* handle = body->getBroadphaseHandle();
00390                 m_savedCollisionFlags = body->getCollisionFlags();
00391                 m_savedMass = GetMass();
00392                 m_savedDyna = m_bDyna;
00393                 m_savedCollisionFilterGroup = handle->m_collisionFilterGroup;
00394                 m_savedCollisionFilterMask = handle->m_collisionFilterMask;
00395                 m_suspended = true;
00396                 GetPhysicsEnvironment()->updateCcdPhysicsController(this, 
00397                         0.0,
00398                         btCollisionObject::CF_STATIC_OBJECT|((ghost)?btCollisionObject::CF_NO_CONTACT_RESPONSE:(m_savedCollisionFlags&btCollisionObject::CF_NO_CONTACT_RESPONSE)),
00399                         btBroadphaseProxy::StaticFilter, 
00400                         btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::StaticFilter);
00401                 m_bDyna = false;
00402         }
00403 }
00404 
00405 void    KX_BulletPhysicsController::RestoreDynamics()
00406 {
00407         btRigidBody *body = GetRigidBody();
00408         if (body && m_suspended)
00409         {
00410                 // before make sure any position change that was done in this logic frame are accounted for
00411                 SetTransform();
00412                 GetPhysicsEnvironment()->updateCcdPhysicsController(this, 
00413                         m_savedMass,
00414                         m_savedCollisionFlags,
00415                         m_savedCollisionFilterGroup,
00416                         m_savedCollisionFilterMask);
00417                 body->activate();
00418                 m_bDyna = m_savedDyna;
00419                 m_suspended = false;
00420         }
00421 }
00422 
00423 SG_Controller*  KX_BulletPhysicsController::GetReplica(class SG_Node* destnode)
00424 {
00425         PHY_IMotionState* motionstate = new KX_MotionState(destnode);
00426 
00427         KX_BulletPhysicsController* physicsreplica = new KX_BulletPhysicsController(*this);
00428 
00429         //parentcontroller is here be able to avoid collisions between parent/child
00430 
00431         PHY_IPhysicsController* parentctrl = NULL;
00432         KX_BulletPhysicsController* parentKxCtrl = NULL;
00433         CcdPhysicsController* ccdParent = NULL;
00434 
00435         
00436         if (destnode != destnode->GetRootSGParent())
00437         {
00438                 KX_GameObject* clientgameobj = (KX_GameObject*) destnode->GetRootSGParent()->GetSGClientObject();
00439                 if (clientgameobj)
00440                 {
00441                         parentctrl = (KX_BulletPhysicsController*)clientgameobj->GetPhysicsController();
00442                 } else
00443                 {
00444                         // it could be a false node, try the children
00445                         NodeList::const_iterator childit;
00446                         for (
00447                                 childit = destnode->GetSGChildren().begin();
00448                         childit!= destnode->GetSGChildren().end();
00449                         ++childit
00450                                 ) {
00451                                 KX_GameObject *clientgameobj_child = static_cast<KX_GameObject*>( (*childit)->GetSGClientObject());
00452                                 if (clientgameobj_child)
00453                                 {
00454                                         parentKxCtrl = (KX_BulletPhysicsController*)clientgameobj_child->GetPhysicsController();
00455                                         parentctrl = parentKxCtrl;
00456                                         ccdParent = parentKxCtrl;
00457                                 }
00458                         }
00459                 }
00460         }
00461 
00462         physicsreplica->setParentCtrl(ccdParent);
00463         physicsreplica->PostProcessReplica(motionstate,parentctrl);
00464         physicsreplica->m_userdata = (PHY_IPhysicsController*)physicsreplica;
00465         physicsreplica->m_bulletChildShape = NULL;
00466         return physicsreplica;
00467         
00468 }
00469 
00470 
00471 
00472 void    KX_BulletPhysicsController::SetSumoTransform(bool nondynaonly)
00473 {
00474 
00475         if (!m_bDyna && !m_bSensor)
00476         {
00477                 btCollisionObject* object = GetRigidBody();
00478                 object->setActivationState(ACTIVE_TAG);
00479                 object->setCollisionFlags(object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
00480         } else
00481         {
00482                 if (!nondynaonly)
00483                 {
00484                         /*
00485                         btTransform worldTrans;
00486                         if (GetRigidBody())
00487                         {
00488                                 GetRigidBody()->getMotionState()->getWorldTransform(worldTrans);
00489                                 GetRigidBody()->setCenterOfMassTransform(worldTrans);
00490                         }
00491                         */
00492                         /*
00493                         scaling?
00494                         if (m_bDyna)
00495                         {
00496                                 m_sumoObj->setScaling(MT_Vector3(1,1,1));
00497                         } else
00498                         {
00499                                 MT_Vector3 scale;
00500                                 GetWorldScaling(scale);
00501                                 m_sumoObj->setScaling(scale);
00502                         }
00503                         */
00504 
00505                 }
00506         }
00507 }
00508 
00509 // todo: remove next line !
00510 void    KX_BulletPhysicsController::SetSimulatedTime(double time)
00511 {
00512 }
00513         
00514 // call from scene graph to update
00515 bool KX_BulletPhysicsController::Update(double time)
00516 {
00517         return false;
00518 
00519         // todo: check this code
00520         //if (GetMass())
00521         //{
00522         //      return false;//true;
00523 //      }
00524 //      return false;
00525 }
00526 
00527 
00528 const char* KX_BulletPhysicsController::getName()
00529 {
00530         if (m_pObject)
00531         {
00532                 KX_GameObject* gameobj = (KX_GameObject*)       m_pObject->GetSGClientObject();
00533                 return gameobj->GetName();
00534         }
00535         return 0;
00536 }
00537 
00538 #endif // USE_BULLET