Search code examples
c++bulletphysics

Bullet 3 dynamics not working for non-sphere


I have a simple program spawning balls to drop on some terrain which works perfectly. But trying to add a box yields extreme performance drop and a box that doesn't fall.

Here's the full extent of the bullet code

  // create the physics world
  auto collisionConfiguration = new btDefaultCollisionConfiguration();
  auto dispatcher = new btCollisionDispatcher(collisionConfiguration);
  auto broadphase = new btDbvtBroadphase();
  auto solver = new btSequentialImpulseConstraintSolver;

  auto dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher, broadphase, solver, collisionConfiguration);
  dynamicsWorld->setGravity(btVector3(0, 0, -10));

  // create terrain
  auto terrainIndices = std::vector<int>(terrainModel.faceData.size() / 11);
  std::iota(terrainIndices.begin(), terrainIndices.end(), 0);
  auto terrainVertices = terrainModel.faceData;
  auto terrainMesh = new btTriangleIndexVertexArray(terrainIndices.size() / 3, terrainIndices.data(), 3 * sizeof(int), terrainVertices.size() / 11, terrainVertices.data(), 11 * sizeof(int));
  auto terrainShape = new btBvhTriangleMeshShape(terrainMesh, false);
  auto terrainMotionState = new btDefaultMotionState();
  auto terrainBody = new btRigidBody(0.0, terrainMotionState, terrainShape);
  dynamicsWorld->addRigidBody(terrainBody);

  // vvvvvvvvvvvvvvvvvvv new code

  // create box
  auto boxShape = new btBoxShape(btVector3(0.3, 0.3, 0.3));
  //auto boxShape = new btSphereShape(0.3); // this works just fine
  auto boxMotionState = new btDefaultMotionState(btTransform(btMatrix3x3(), btVector3(0, 0, 5)));
  auto boxBody = new btRigidBody(1.0, boxMotionState, boxShape);
  dynamicsWorld->addRigidBody(boxBody);
  // bind body to renderable 

  // ^^^^^^^^^^^^^^^^^^^

  // create balls (called later on key press)
  auto ballShape = new btSphereShape(0.1);
  auto spawnBall = [&]() {
    auto ballMotionState = new btDefaultMotionState(btTransform(btMatrix3x3(), btVector3(0, 0, 5)));
    auto ballBody = new btRigidBody(1.0, ballMotionState, ballShape);
    ballBody->setCcdMotionThreshold(0.1);
    ballBody->setCcdSweptSphereRadius(0.2);
    dynamicsWorld->addRigidBody(ballBody);

    // bind body to renderable 
  };

  while(...)
  {
    // process input

    dynamicsWorld->stepSimulation(1.0f / 144.0f);

    // render
  }

I've also tried using a capsule with the same effect. To be clear, the issue is that the new object doesn't seem to behave dynamically if its a box or a capsule, it works as expected if its a sphere. The initial position is well above the terrain height.

Curiously, the performance drop only happens after newly spawned balls have dropped for a bit.

This is running on Bullet 3 v2.87 compiled from source running in debug mode in Visual Studio 2017.


Solution

  • Wow, I figured it out. btMatrix3x3() doesn't create an identity matrix (its either zeroes or uninitialized). So the rotation/transformation wasn't right. Using btMatrix3x3::getIdentity() fixed the problem.

    So, it appears that a proper rotation transform is not required for physics calculations on spheres (kinda makes sense in a way) which only added to my confusion.