simonet
simonet

Reputation: 295

Getting the transform of a collided object with Bullet Physics SDK

I'm trying to use Bullet Physics SDK to detect collisions between objects moving in space. I don't need any information about the dynamics that happens after the collision, but only if a collision happens or not.

In the following simplified example, I'm testing a cube that translates along the x-axis while spinning around it. Halfway along its path I placed an obstacle, which prevents the cube from reaching its target.

#include <btBulletDynamicsCommon.h>

#define PI (3.14159265358979323846)

//@note Collision groups must be powers of two, if we want to exploit the logic implemented in ConvexResultCallback::needsCollision to determine which pair of objects must be examined.
typedef enum
{
    GROUP_OBSTACLE = 1 << 0,
    GROUP_ROBOT = 1 << 1,
}collisionGroup;


int main(int argc, char** argv)
{
    btDefaultCollisionConfiguration* collisionConfiguration = new btDefaultCollisionConfiguration();
    btCollisionDispatcher* dispatcher = new btCollisionDispatcher(collisionConfiguration);
    btBroadphaseInterface* overlappingPairCache = new btDbvtBroadphase();
    btCollisionWorld* world = new btCollisionWorld(dispatcher, overlappingPairCache, collisionConfiguration);

    btCollisionShape* object1Shape = new btBoxShape(btVector3(1, 1, 1));
    btTransform startTransform1;
    startTransform1.setIdentity();
    startTransform1.setOrigin(btVector3(-20, 0, 0));
    btDefaultMotionState* motionState1 = new btDefaultMotionState(startTransform1);
    btRigidBody::btRigidBodyConstructionInfo object1RigidBodyCI(0, motionState1, object1Shape);
    btRigidBody* object1RigidBody = new btRigidBody(object1RigidBodyCI);
    world->addCollisionObject(object1RigidBody, GROUP_ROBOT, GROUP_OBSTACLE);

    btCollisionShape* object2Shape = new btBoxShape(btVector3(1, 1, 1));
    btTransform startTransform2;
    startTransform2.setIdentity();
    startTransform2.setOrigin(btVector3(0, -2, 0));
    btDefaultMotionState* motionState2 = new btDefaultMotionState(startTransform2);
    btRigidBody::btRigidBodyConstructionInfo object2RigidBodyCI(0, motionState2, object2Shape);
    btRigidBody* object2RigidBody = new btRigidBody(object2RigidBodyCI);
    world->addCollisionObject(object2RigidBody, GROUP_OBSTACLE, GROUP_ROBOT);

    btCollisionShape* object3Shape = new btBoxShape(btVector3(1, 1, 1));
    btTransform startTransform3;
    startTransform3.setIdentity();
    startTransform3.setOrigin(btVector3(0, 2, 0));
    btDefaultMotionState* motionState3 = new btDefaultMotionState(startTransform3);
    btRigidBody::btRigidBodyConstructionInfo object3RigidBodyCI(0, motionState3, object3Shape);
    btRigidBody* object3RigidBody = new btRigidBody(object3RigidBodyCI);
    world->addCollisionObject(object3RigidBody, GROUP_OBSTACLE, GROUP_ROBOT);

    btTransform endTransform;
    endTransform.setIdentity();
    endTransform.setOrigin(btVector3(20, 0, 0));
    endTransform.setRotation(btQuaternion(btVector3(1, 0, 0), btScalar(PI / 2.)));//@note If enabled, the object does not pass through the hole

    btCollisionWorld::ClosestConvexResultCallback sweepCallback(startTransform1.getOrigin(), endTransform.getOrigin());
    sweepCallback.m_collisionFilterGroup = GROUP_ROBOT;
    sweepCallback.m_collisionFilterMask = GROUP_OBSTACLE;

    btScalar allowedCcdPenetration = 0.39f;//@note should be (sqrt(2)-1) to detect collision with rotation enabled
    world->convexSweepTest((btConvexShape*)object1RigidBody->getCollisionShape(), startTransform1, endTransform, sweepCallback, allowedCcdPenetration);

    if (sweepCallback.hasHit())
    {
        printf("Collision detected at point (%f, %f, %f)\n",
            sweepCallback.m_hitPointWorld.x(),
            sweepCallback.m_hitPointWorld.y(),
            sweepCallback.m_hitPointWorld.z()
        );
    }
    else
    {
        printf("No collision detected.\n");
    }

    //delete object1RigidBody; //@todo Check why it causes crash
    //delete object2RigidBody; //@todo Check why it causes crash
    delete object1Shape;
    delete object2Shape;
    delete motionState1;
    delete motionState2;
    delete world;
    delete overlappingPairCache;
    delete dispatcher;
    delete collisionConfiguration;

    return 0;
}

The convexSweepTest works correctly as it finds a collision at point (-0.999981, -1.038976, -0.273800).

I would like, however, to be able to retrieve the position and orientation of the sweeping cube at the moment of the collision, in order to export its mesh. Is this somehow possible in Bullet?

I tried also deriving a custom implementation of class btCollisionWorld::ConvexResultCallback, but the class btCollisionWorld::LocalConvexResult seems not to contain the information I need.

Upvotes: 0

Views: 46

Answers (0)

Related Questions