Updating btCollisionObject position (collision detection only)

Post Reply
bi1cimer
Posts: 3
Joined: Tue May 14, 2019 11:01 pm

Updating btCollisionObject position (collision detection only)

Post by bi1cimer » Wed May 15, 2019 9:29 am

Hi everyone,

I use Bullet Physics only for collision detection. My goal is to detect collision in a Mass-Spring system.

So, I have a btCollisionWorld in which i add some btCollisionObject, with a btCollisionShape corresponding to a btCompoundShape. Those btCompoundShape have btTriangleShapes as children. To update my btCollisionWorld, i created a unordered_map which associate a ptr btVector3 of each btTriangleSHapes to a ptr of a particle from the MSS, so i can update the child shape btVector3s positions depending on the particle it is associated to.

The problem is the following : after manually updating the btVector3s, i need to recreate the btCollisionObjects, readd them to the world, and delete the old ones so the collisions are detected. If i just update the btVector3 position, the collision are not detected (even if the collision shape is moving in the debugger).

Do you have any idea why this happens ?

Thanks

bi1cimer
Posts: 3
Joined: Tue May 14, 2019 11:01 pm

Re: Updating btCollisionObject position (collision detection only)

Post by bi1cimer » Wed May 15, 2019 9:52 am

Oh, and it might be better with some code :

My members

Code: Select all

btCollisionConfiguration* m_collision_configuration;
btCollisionDispatcher* m_dispatcher;
btBroadphaseInterface* m_broadphase;
btCollisionWorld* m_collision_world;
std::map<btVector3*, vec3*> map_btVector3_Vector;
Creating the world

Code: Select all

double scene_size = 500;
unsigned int max_objects = 16000;

m_collision_configuration = new btDefaultCollisionConfiguration();
m_dispatcher = new btCollisionDispatcher(m_collision_configuration);

btScalar sscene_size = (btScalar) scene_size;
btVector3 worldAabbMin(-sscene_size, -sscene_size, -sscene_size);
btVector3 worldAabbMax(sscene_size, sscene_size, sscene_size);
m_broadphase = new bt32BitAxisSweep3(worldAabbMin, worldAabbMax, max_objects, 0, true);  // true for disabling raycast accelerator

m_collision_world = new btCollisionWorld(m_dispatcher, m_broadphase, m_collision_configuration);
m_collision_world->setForceUpdateAllAabbs(true);
Adding objects

Code: Select all

auto compoundShape = new btCompoundShape();

btTransform transform;
transform.setIdentity();
transform.setOrigin(btVector3(0,0,0));

int a, b, c;

for(unsigned int i=0; i< mesh.triangle_count(); ++i)
{
    	a= mesh.indices()[i*3];
        b= mesh.indices()[i*3 +1];
        c= mesh.indices()[i*3 +2];

        btVector3 v1(mesh.positions()[a].x, mesh.positions()[a].y, mesh.positions()[a].z);
        btVector3 v2(mesh.positions()[b].x, mesh.positions()[b].y, mesh.positions()[b].z);
        btVector3 v3(mesh.positions()[c].x, mesh.positions()[c].y, mesh.positions()[c].z);

        auto triangle = new btTriangleShape(v1, v2, v3);
        triangle->setMargin(0);
        compoundShape->addChildShape(transform, triangle);

        map_btVector3_Vector.insert(std::pair<btVector3*, vec3*>(&triangle->getVertexPtr(0), &mesh.positions()[a]));
        map_btVector3_Vector.insert(std::pair<btVector3*, vec3*>(&triangle->getVertexPtr(1), &mesh.positions()[b]));
        map_btVector3_Vector.insert(std::pair<btVector3*, vec3*>(&triangle->getVertexPtr(2), &mesh.positions()[c]));
        }

    auto* object = new btCollisionObject();
    object->setCollisionShape(compoundShape);
    object->setActivationState(1);
    m_collision_world->addCollisionObject(object);
Updating the world

Code: Select all

for (auto& element : map_btVector3_Vector)
{

        btVector3* btVector = element.first;
        vec3* vector = element.second;
        btVector->m_floats[0] = vector->x;
        btVector->m_floats[1] = vector->y;
        btVector->m_floats[2] = vector->z;
}
        
int nb_objects = m_collision_world->getCollisionObjectArray().size();

std::vector<btCollisionObject*> objects;

for (int k = 0; k < nb_objects; k++)
{
        auto* object = m_collision_world->getCollisionObjectArray()[k];
        objects.emplace_back(object);

        auto compoundShape = dynamic_cast<btCompoundShape*> (object->getCollisionShape());

        auto newCompoundShape = new btCompoundShape();

        //std::cout << "NB CHILDREN" << compoundShape->getNumChildShapes() << std::endl;

        for (int nb_children = 0; nb_children < compoundShape->getNumChildShapes(); nb_children++)
        {
            btTransform newChildTransform = compoundShape->getChildTransform(nb_children);
            newCompoundShape->addChildShape(newChildTransform,compoundShape->getChildShape(nb_children));
        }

        auto newObject = new btCollisionObject();
        newObject->setCollisionShape(newCompoundShape);
        m_collision_world->addCollisionObject(newObject);
        
}

for (btCollisionObject* object : objects)
{
     m_collision_world->removeCollisionObject(object);
}
Computing collisions

Code: Select all

m_collision_world->performDiscreteCollisionDetection();
bool one_collision = false;

int numContacts = 0;

int numManifolds = m_collision_world->getDispatcher()->getNumManifolds();
//For each contact manifold
for (int i = 0; i < numManifolds; i++)
{
            btPersistentManifold* contactManifold = m_collision_world->getDispatcher()->getManifoldByIndexInternal(i);

            const btCollisionObject* ob0 = contactManifold->getBody0();
            const btCollisionObject* ob1 = contactManifold->getBody1();

            contactManifold->refreshContactPoints(ob0->getWorldTransform(), ob1->getWorldTransform());
            numContacts = contactManifold->getNumContacts();

            for (int j = 0; j < numContacts; j++)
            {
                    one_collision = true;
                    std::cout << "----------------- contact number : " << j <<std::endl;
            }
}

User avatar
drleviathan
Posts: 545
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: Updating btCollisionObject position (collision detection only)

Post by drleviathan » Wed May 15, 2019 3:47 pm

The btCompoundShape has an internal AabbTree which is supposed to be automatically updated by default whenever you add/remove/transform one of the children. This AabbTree is used to optimize narrow-phase collision detection.

If you weren't already: you should be using using btCompoundShape::updateChildTransform() to communicate the new local-frame transform of each child, not by poking the child shape directly.

If you were already using that then... I dunno. Show us the old not-working code rather than the new semi-working-but-not-ideal code.

bi1cimer
Posts: 3
Joined: Tue May 14, 2019 11:01 pm

Re: Updating btCollisionObject position (collision detection only)

Post by bi1cimer » Wed May 15, 2019 4:29 pm

Thanks for the reply and for the hint !

I thought earlier about btCompoundShape::updateChildTransform(), but seeing that it needed a btTransform, i told myself that I couldn't compute the new transform of the triangle

But creating a btTransform with origin btVector3(0,0,0) and updating all child shapes with it made it work. Hope it's a not too bad method

Thanks

Post Reply