1
\$\begingroup\$

Let me start off by saying that the usage of Bullet here is slightly unconventional. I'm writing a server emulator for a game, and the server is only keeping track of the triggers, players and enemies. It doesn't do a full physics simulation like the client.

Thus, the gravity is set to 0. The client is authorative over the position of the player object, so the rigidbody is just moved around on the server as the player walks through the world.

The problem is that, while Bullet can detect the collisions, it'll stop after a few steps. I presumed this is because the objects went to sleep / toggled as inactive, but moving them, setting flags telling them not to sleep, or forcing reactivation doesn't fix it.

I've created a small program that shows the problem:

void updatePos(btRigidBody* rb, btVector3 position) {
    btTransform initialTransform;

    initialTransform.setOrigin(position);

    rb->clearForces();
    rb->setWorldTransform(initialTransform);
    rb->getMotionState()->setWorldTransform(initialTransform);
}

int main() {
    btDefaultCollisionConfiguration* collisionConfiguration = new btDefaultCollisionConfiguration();
    btCollisionDispatcher* dispatcher = new btCollisionDispatcher(collisionConfiguration);
    btBroadphaseInterface* overlappingPairCache = new btDbvtBroadphase();
    btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver;

    auto* world = new btCollisionWorld(dispatcher, overlappingPairCache, collisionConfiguration);

    //Create our player:
    btDefaultMotionState* state = new btDefaultMotionState(btTransform(btQuaternion(), btVector3()));
    btCylinderShape* shape = new btCylinderShape(btVector3(1.0f, 1.5f, 1.0f));

    btVector3 localInertia(0, 0, 0);
    shape->calculateLocalInertia(1.0f, localInertia);

    btCollisionObject* rbPlayer = new btCollisionObject();
    rbPlayer->setCollisionShape(shape);

    //Create our trigger:
    state = new btDefaultMotionState(btTransform(btQuaternion(), btVector3(-227.5784454345703, 555.2715454101562, -73.29886627197266)));
    btBoxShape* trigShape = new btBoxShape(btVector3(5.0f, 0.5f, 2.5f));

    btCollisionObject* rbTrigger = new btCollisionObject();
    rbTrigger->setCollisionShape(trigShape);

    world->addCollisionObject(rbPlayer);
    world->addCollisionObject(rbTrigger);

    rbPlayer->setActivationState(ACTIVE_TAG);
    rbTrigger->setActivationState(ACTIVE_TAG);
    rbPlayer->setActivationState(DISABLE_DEACTIVATION);
    rbTrigger->setActivationState(DISABLE_DEACTIVATION);

unsigned int stepCounter = 0;

while (true)
{
    printf("step %i\n", stepCounter);

    world->performDiscreteCollisionDetection();
    if (stepCounter == 1) rbPlayer->getWorldTransform().setOrigin(btVector3(-227.0f, 560.0f, -73.0f));

    int numManifolds = world->getDispatcher()->getNumManifolds();

    for (int i = 0; i < numManifolds; i++)
    {
        btPersistentManifold* contactManifold = world->getDispatcher()->getManifoldByIndexInternal(i);
        const btCollisionObject* obA = static_cast<const btCollisionObject*>(contactManifold->getBody0());
        const btCollisionObject* obB = static_cast<const btCollisionObject*>(contactManifold->getBody1());

        int numContacts = contactManifold->getNumContacts();
        for (int j = 0; j < numContacts; j++)
        {
            printf("yes\n");
        }
    }

    stepCounter++;
    std::this_thread::sleep_for(std::chrono::milliseconds(16));

    if (stepCounter == 15) rbPlayer->getWorldTransform().setOrigin(btVector3());
    if (stepCounter == 30) rbPlayer->getWorldTransform().setOrigin(btVector3(-227.0f, 560.0f, -73.0f));

    rbPlayer->activate(true);
    rbTrigger->activate(true);

    if (stepCounter > 40) break;
}
}

I'm willing to bet it's some slight oversight that caused this, but I couldn't find anyone with the same issue as me online.

\$\endgroup\$
  • \$\begingroup\$ You are not calling stepSimulation anywhere, I'm not sure if this is required to dispatch collisions. \$\endgroup\$ – Jay Nov 24 '19 at 14:08
  • \$\begingroup\$ Also, instead of (or as well as) setting gravity to zero, set each object's mass to zero. This will make it a static object in Bullet. \$\endgroup\$ – Jay Nov 24 '19 at 14:10
  • 1
    \$\begingroup\$ @Jay That's because this version is using the btCollisionWorld. (It uses ->performDiscreteCollisionDetection()). I finally got it to work in a regular world, then setting the flags as seen above to prevent sleeping, and giving the player mass but not the trigger. \$\endgroup\$ – gie005 Nov 24 '19 at 17:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.