Search code examples
c++openglgame-physicsphysics-enginebulletphysics

Bullet Physics - Creating ShapeHull from Mesh


I am attempting to load mesh data that I use to draw with OpenGL into the Bullet Engine.

The problem is I don't believe that the mesh data is actually being read from the pointers. Thus the physical world is not matching up and the "Character Controller" is falling through the floor.

The rendered world is fine, so I know the OpenGL data is fine.

Here is the function of my controller class that I am using to transfer the data into OpenGL.

Is there something I am missing here?

Thank you - Here's the code I am using:

void PhysicsController::AddStaticBasicMesh(PhysicsObject* NewObject, bool ReducePolygonCount = true)
{
   btTriangleMesh* OriginalTriangleMesh = new btTriangleMesh();
   btIndexedMesh* NewMesh = new btIndexedMesh();
   NewMesh->m_triangleIndexBase = (unsigned char *)NewObject->Indices;
   NewMesh->m_triangleIndexStride = 3 * sizeof(unsigned int);
   NewMesh->m_vertexBase = (unsigned char *)NewObject->Vertices;
   NewMesh->m_vertexStride = 3 * sizeof(float);
   NewMesh->m_numVertices = NewObject->NumberOfVertices;
   NewMesh->m_numTriangles = NewObject->NumberOfTriangles;
   OriginalTriangleMesh->addIndexedMesh((*NewMesh));
   btConvexShape* NewStaticMesh = new btConvexTriangleMeshShape(OriginalTriangleMesh);
   btConvexHullShape* ReducedPolygonStaticMesh;

   if (ReducePolygonCount == true) {
      btShapeHull* HullOfOriginalShape = new btShapeHull(NewStaticMesh);
      btScalar CurrentMargin = NewStaticMesh->getMargin();
      HullOfOriginalShape->buildHull(CurrentMargin);
      ReducedPolygonStaticMesh = new btConvexHullShape();

      for (int i = 0; i < HullOfOriginalShape->numVertices(); i++) {
         ReducedPolygonStaticMesh->addPoint(HullOfOriginalShape->getVertexPointer()[i], false);
      }

      ReducedPolygonStaticMesh->recalcLocalAabb();
      /*

      Find out what this line does.

      ReducedPolygonStaticMesh->initializePolyhedralFeatures();

      */

      StaticShapes.push_back(ReducedPolygonStaticMesh);
      btDefaultMotionState* StaticMotionState = new btDefaultMotionState((*NewObject->PositionAndOrientation));
      btRigidBody::btRigidBodyConstructionInfo StaticMeshRigidBodyInfo(0, StaticMotionState, ReducedPolygonStaticMesh, btVector3(0.0f, 0.0f, 0.0f));
      btRigidBody* StaticRigidMesh = new btRigidBody(StaticMeshRigidBodyInfo);
      NewObject->Body = StaticRigidMesh;
      StaticRigidMesh->setCollisionFlags(StaticRigidMesh->getCollisionFlags() | btCollisionObject::CF_STATIC_OBJECT);
      MainPhysicsWorld->addRigidBody(StaticRigidMesh, btBroadphaseProxy::StaticFilter, btBroadphaseProxy::CharacterFilter | btBroadphaseProxy::DefaultFilter);
      AllRigidBodies.push_back(NewObject);
      StaticRigidMesh->setUserPointer(AllRigidBodies[AllRigidBodies.size() - 1]);
      delete HullOfOriginalShape;
      delete NewStaticMesh;
   } else {
      StaticShapes.push_back(NewStaticMesh);;
      btDefaultMotionState* StaticMotionState = new btDefaultMotionState((*NewObject->PositionAndOrientation));
      btRigidBody::btRigidBodyConstructionInfo StaticMeshRigidBodyInfo(0, StaticMotionState, NewStaticMesh, btVector3(0.0f, 0.0f, 0.0f));
      btRigidBody* StaticRigidMesh = new btRigidBody(StaticMeshRigidBodyInfo);
      NewObject->Body = StaticRigidMesh;
      StaticRigidMesh->setCollisionFlags(StaticRigidMesh->getCollisionFlags() | btCollisionObject::CF_STATIC_OBJECT);
      MainPhysicsWorld->addRigidBody(StaticRigidMesh, btBroadphaseProxy::StaticFilter, btBroadphaseProxy::CharacterFilter | btBroadphaseProxy::DefaultFilter);
      AllRigidBodies.push_back(NewObject);
      StaticRigidMesh->setUserPointer(AllRigidBodies[AllRigidBodies.size() - 1]);
   }
}

Solution

  • Maybe, not the answer you're looking for, but probably you could use btConvexHullShape, as advised in Bullet documentation?

    http://bulletphysics.org/Bullet/BulletFull/classbtConvexTriangleMeshShape.html

    Nevertheless, most users should use the much better performing btConvexHullShape instead.

    And add vertices one by one using addPoint, which is also mentioned in documentation:

    http://bulletphysics.org/Bullet/BulletFull/classbtConvexHullShape.html

    It is easier to not pass any points in the constructor, and just add one point at a time, using addPoint

    I know it is bad to answer "just use something else" instead of answering the original question.

    Also this way you'll duplicate your vertices.

    However, if you're only beginning to learn some new tech, you might want to make everything work first and then it might be easier to return step-by-step to your original design.

    Another good idea would be to use debug drawer and actually see what your mesh looks like.

    I've created one, some time ago for OpenGL ES 2.0, maybe it will be helpful: https://github.com/kmuzykov/custom-opengl-es-game-engine/blob/master/Engine/Physics/KMPhysicsDebugDrawer.cpp