Bullet Physics Library在static_object和dynamic_object之间切换刚体

时间:2014-10-07 06:28:54

标签: bulletphysics

我对Bullet很新,我的目标是能够在静态和动态之间切换btRigidBody。为了初始化我的刚性,我开始这样做:

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,因为我的“mass”变量为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 个答案:

答案 0 :(得分: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;
}

答案 1 :(得分: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);
}