Blender V2.61 - r43446

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 explicitly
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