2014-10-07 62 views
1

我对Bullet相当陌生,我的目标是能够在静态和动态之间切换一个btRigidBody。要初始化我刚体我开始出来做这个:Bullet Physics Library在static_object和dynamic_object之间切换刚体

btGImpactMeshShape* triMesh=new btGImpactMeshShape(mTriMesh); 
triMesh->setLocalScaling(btVector3(1,1,1)); 
triMesh->updateBound(); 

meshInfos[currentMesh].shape=triMesh; 
meshInfos[currentMesh].motionState=new btDefaultMotionState(btTransform(btQuaternion(0,0,0,1), btVector3(position.x,position.y,position.z))); 
meshInfos[currentMesh].mass=mass; 

btVector3 inertia; 
meshInfos[currentMesh].shape->calculateLocalInertia(mass, inertia); 

btRigidBody::btRigidBodyConstructionInfo rigidBodyCI(0, meshInfos[currentMesh].motionState, meshInfos[currentMesh].shape, inertia); 
meshInfos[currentMesh].rigidBody=new btRigidBody(rigidBodyCI); 

,设置它作为static_object因为“质量”变量我必须为0开始。后来我有一个检查,如果一个布尔被开启的功能,并切换到刚体动态对象是这样的:

if(gravityOn && !addedToWorld) 
{ 
    if(mass>0) 
    { 
     world->removeRigidBody(body); 
     btVector3 inertia; 
     body->getCollisionShape()->calculateLocalInertia(mass, inertia); 
     body->setMassProps(mass, inertia); 
     body->setLinearFactor(btVector3(1,1,1)); 
     body->setAngularFactor(btVector3(1,1,1)); 
     body->updateInertiaTensor(); 
     world->addRigidBody(body); 
     addedToWorld=true; 
    } 
    else 
    { 
     std::cout << "Mass must be set to a number greater than 0" << std::endl; 
    } 
} 
else if(!gravityOn && addedToWorld) 
{ 
    world->removeRigidBody(body); 
    body->setMassProps(0, btVector3(0,0,0)); 
    body->setLinearFactor(btVector3(0,0,0)); 
    body->setAngularFactor(btVector3(0,0,0)); 
    body->updateInertiaTensor(); 
    world->addRigidBody(body); 
    addedToWorld=false; 
} 

,而addedToWorld布尔只是确保在if语句不通过继续运行代码块每更新一次。 从我研究过的这个应该可以工作,但是什么都不做。我错过了什么吗?从我看到的最佳做法是在对其进行任何更改之前先删除刚体。然后setMassProps改变惯性,setLinearFactor和setAngularFactor允许物体不会移动或移动,这取决于碰撞时它传入的矢量,updateInertiaTensor允许惯性正确更新,然后我再添加刚体。我可能会误解这一些,任何帮助将不胜感激。

回答

2

经过漫长的夜晚,我明白了。首先,由于未知原因,此时使用三角形网格(对象的网格)可能会导致应用程序崩溃。所以我使用了一个凸形碰撞形状。另外,您需要在交换机中调用一些标志以正确地在静态和动态之间切换。该代码是这样:

btConvexShape* tmpConvexShape=new btConvexTriangleMeshShape(mTriMesh); 

btShapeHull* hull=new btShapeHull(tmpConvexShape); 
btScalar margin=tmpConvexShape->getMargin(); 
hull->buildHull(margin); 
tmpConvexShape->setUserPointer(hull); 

btConvexHullShape* convexShape=new btConvexHullShape(); 
bool updateLocalAabb=false; 

for(int i=0; i<hull->numVertices(); i++) 
{ 
    convexShape->addPoint(hull->getVertexPointer()[i],updateLocalAabb); 
} 
convexShape->recalcLocalAabb(); 
convexShape->setMargin(0.001f); 

delete tmpConvexShape; 
delete hull; 

meshInfos[currentMesh].shape=convexShape; 
meshInfos[currentMesh].motionState=new btDefaultMotionState(btTransform(btQuaternion(0,0,0,1), btVector3(position.x,position.y,position.z))); 
meshInfos[currentMesh].mass=mass; 

btVector3 inertia; 
meshInfos[currentMesh].shape->calculateLocalInertia(mass, inertia); 

btRigidBody::btRigidBodyConstructionInfo rigidBodyCI(0, meshInfos[currentMesh].motionState, meshInfos[currentMesh].shape, inertia); 
meshInfos[currentMesh].rigidBody=new btRigidBody(rigidBodyCI); 

和交换:

if(gravityOn && !addedToWorld) 
{ 
    if(mass>0) 
    { 
     world->removeRigidBody(body); 
     btVector3 inertia(0,0,0); 
     body->getCollisionShape()->calculateLocalInertia(mass, inertia); 
     body->setActivationState(DISABLE_DEACTIVATION); 
     body->setMassProps(mass, inertia); 
     body->setLinearFactor(btVector3(1,1,1)); 
     body->setAngularFactor(btVector3(1,1,1)); 
     body->updateInertiaTensor(); 
     body->clearForces(); 
     btTransform transform; 
     transform.setIdentity(); 
     float x=position.x; 
     float y=position.y; 
     float z=position.z; 
     transform.setOrigin(btVector3(x, y,z)); 
     body->getCollisionShape()->setLocalScaling(btVector3(1,1,1)); 
     body->setWorldTransform(transform); 
     world->addRigidBody(body); 
     addedToWorld=true; 
    } 
    else 
    { 
     std::cout << "Mass must be set to a number greater than 0" << std::endl; 
    } 
} 
else if(!gravityOn && addedToWorld) 
{ 
    world->removeRigidBody(body); 
    btVector3 inertia(0,0,0); 
    body->getCollisionShape()->calculateLocalInertia(0, inertia); 
    body->setCollisionFlags(btCollisionObject::CF_STATIC_OBJECT); 
    body->setMassProps(0, inertia); 
    body->setLinearFactor(btVector3(0,0,0)); 
    body->setAngularFactor(btVector3(0,0,0)); 
    body->setGravity(btVector3(0,0,0)); 
    body->updateInertiaTensor(); 
    body->setAngularVelocity(btVector3(0,0,0)); 
    body->setLinearVelocity(btVector3(0,0,0)); 
    body->clearForces(); 
    body->setActivationState(WANTS_DEACTIVATION); 
    btTransform transform; 
    transform.setIdentity(); 
    float x=position.x; 
    float y=position.y; 
    float z=position.z; 
    transform.setOrigin(btVector3(x, y,z)); 
    body->getCollisionShape()->setLocalScaling(btVector3(1,1,1)); 
    body->setWorldTransform(transform); 
    world->addRigidBody(body); 
    addedToWorld=false; 
} 
0

使用短函数来改变物体的质量(静若0.0F,动态否则):

void InceptionPhysics::changeMassObject(btRigidBody* rigidBody, float mass) { 

    logFileStderr(VERBOSE, "mass... %5.2f\n", mass); 

    m_dynamicsWorld->removeRigidBody(rigidBody); 

    btVector3 inertia; 
    rigidBody->getCollisionShape()->calculateLocalInertia(mass, inertia); 
    rigidBody->setMassProps(mass, inertia); 

    m_dynamicsWorld->addRigidBody(rigidBody); 
}