Page 1 of 1

Updating btCollisionObject position (collision detection only)

Posted: Wed May 15, 2019 9:29 am
by bi1cimer
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 ?


Re: Updating btCollisionObject position (collision detection only)

Posted: Wed May 15, 2019 9:52 am
by bi1cimer
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);
Adding objects

Code: Select all

auto compoundShape = new btCompoundShape();

btTransform transform;

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);
        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();
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];

        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);

        auto newObject = new btCollisionObject();

for (btCollisionObject* object : objects)
Computing collisions

Code: Select all

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;

Re: Updating btCollisionObject position (collision detection only)

Posted: Wed May 15, 2019 3:47 pm
by drleviathan
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.

Re: Updating btCollisionObject position (collision detection only)

Posted: Wed May 15, 2019 4:29 pm
by bi1cimer
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