0
votes

I can't seem to get a proper physics behavior with a basic bullet c++ simulation. I am trying to initialize btRigidBody from a mesh loaded from an STL file, for that I am using lib assimp.

When using a cube the physics behavior seems valid but not with a rectangular shape. What am I missing in the way I load the meshes into the physics?

void SimulationManager::addRigidBodyFromMesh (const BodyInfo& bodyInfo, const aiMesh* mesh) {

    btTriangleMesh* trimesh = new btTriangleMesh();

    for (int i=0;i<mesh->mNumFaces; ++i) {

        const aiFace& face = mesh->mFaces[i];

        aiVector3D v0 = mesh->mVertices[face.mIndices[0]];
        aiVector3D v1 = mesh->mVertices[face.mIndices[1]];
        aiVector3D v2 = mesh->mVertices[face.mIndices[2]];

        trimesh->addTriangle(
            btVector3(v0.x, v0.y, v0.z),
            btVector3(v1.x, v1.y, v1.z),
            btVector3(v2.x, v2.y, v2.z));
    }

    btCollisionShape* colShape = new btConvexTriangleMeshShape(trimesh);

    //static, non-moving world environment geometry
    //bool useQuantization = true;
    //shape  = new btBvhTriangleMeshShape(trimesh,useQuantization);

    this->_collisionShapes.push_back(colShape);

    btTransform transform;
    transform.setIdentity();

    btScalar mass(1.f);
    btVector3 localInertia(0, 0, 0);
    colShape->calculateLocalInertia(mass, localInertia);

    transform.setOrigin(btVector3(bodyInfo.x, bodyInfo.y, bodyInfo.z));

    btDefaultMotionState* motionState = new btDefaultMotionState(transform);
    btRigidBody::btRigidBodyConstructionInfo rbInfo(mass, motionState, colShape, localInertia);
    btRigidBody* body = new btRigidBody(rbInfo);

    body->setAngularVelocity(btVector3(bodyInfo.aX, bodyInfo.aY, bodyInfo.aZ));

    this->_pDynamicsWorld->addRigidBody(body);
}

I then update the simulation and retrieve rigidbody transform as follow:

void SimulationManager::update(double dt, std::vector<BodyTransform>& transforms){

    this->_pDynamicsWorld->stepSimulation(dt, 10);

    for (int i = 0; i < this->_pDynamicsWorld->getNumCollisionObjects(); ++i) {

        btCollisionObject* obj = this->_pDynamicsWorld->getCollisionObjectArray()[i];
        btRigidBody* body = btRigidBody::upcast(obj);

        float invMass = body->getInvMass();

        if (invMass > 0) {

            btTransform trans;
            body->getMotionState()->getWorldTransform(trans);

            BodyTransform bodyTransform;

            bodyTransform.matrix = new btScalar[16];

            trans.getOpenGLMatrix(bodyTransform.matrix);

            transforms.push_back(bodyTransform);
        }
    }
};

And update the opengl meshes as follow:

std::vector<BodyTransform> transforms;

simulationManager.update(0.005, transforms);

for (std::vector<BodyTransform>::iterator it = transforms.begin() ; it != transforms.end(); ++it) {

    glPushMatrix();
    glMultMatrixf((GLfloat*)it->matrix);
    drawModel(bar);
    glPopMatrix();

    delete [] it->matrix;
}

Here is how my simulation looks like with cubes:

enter image description here

But with rectangles, the meshes are initially laying on the floor and they stabilize vertically, quite strange:

enter image description here

I would be very grateful for any help on the topic. Thanks!

1
How much more code would you have to provide to make this a complete working example? - Brent Bradburn
Well, I was hoping that an experienced bullet developer could help me by looking at the code I have in addRigidBodyFromMesh. That's really where all the physics initialization occurs. The problem is most likely a mismatch between the mesh and the btCollisionShape. But I couldn't find a concrete example on initializing that object from an stl. There is an example with .obj but doing similar approach doesn't work for me. - Felipe
Sometimes it's more fun to look at code while it's live. - Brent Bradburn

1 Answers

1
votes

After struggling for a while I found out what was the problem, so I will answer my own question in case it can be useful to someone else: bullet expects the center of gravity of the mesh to be placed at its origin, if it's not the case you will get the strange behaviour that you cab see above.