How to apply Bullet physics to drawn Opengl 3d shapes

After you downloaded Bullet Physics SDK, look the file GL_ShapeDrawer.cpp,you will find some interresting functions such like drawSphere, drawCylinder,drawOpenGl.. the last one i mentionned lets you draw any type of suported shape :

  • CUSTOM_CONVEX_SHAPE_TYPE
  • BOX_SHAPE_PROXYTYPE
  • UNIFORM_SCALING_SHAPE_PROXYTYPE
  • COMPOUND_SHAPE_PROXYTYPE
  • BOX_SHAPE_PROXYTYPE
  • SPHERE_SHAPE_PROXYTYPE

Each type of shape from shape->getShapeType() has its own dedicated function for rendering with opengl

But my method involves to

  • 1 - Load the 3D model with a mesh loader
  • 2 - Create the graphics shape with opengl functions using the previous mesh loader
  • 3 - Create bullet shapes from the vertices used by the mesh loader
  • 4 - Implement the Bullet Motion State (when a shape is going to be rotated or translated or just "transformed", you syncronize the "btTransform" of your bullet shape with the transformation matrix of the graphic shape, then update the graphics vertices)

Personnaly, i'm using Irrlicht because Irrlicht is the "write less,do more" solution of opengl :p


Bullet Example Browser

The in-tree example browser has some OpenGL-physics bindings so you can easily visualize simulations.

To see it working, you can compile and run it with:

sudo apt build-dep libbullet-dev
git clone https://github.com/bulletphysics/bullet3
cd bullet3
git checkout 2.89
./build_cmake_pybullet_double.sh
./build_cmake/examples/ExampleBrowser/App_ExampleBrowser

Screenshot:

enter image description here

Tested on Ubuntu 20.04.

Example browser 2.83 code analysis

The Bullet example browser has moved away from the examples/ExampleBrowser/GL_ShapeDrawer.cpp by default, which uses outdated immediate OpenGL 2 methods. It can still be turned on depending on the value of the NO_OPENGL3 macro and command line arguments.

OpenGLWindow/GLInstancingRenderer.cpp is the new OpenGL 3 rendering centerpiece, and contains the glBindVertexArray call in GLInstancingRenderer::registerShape.

This method is indirectly called from OpenGLGuiHelper::autogenerateGraphicsObjects, which loops over the objects in the btDiscreteDynamicsWorld and generates a graphic version of those shapes.

The central part of the conversion seems to be OpenGLGuiHelper::createCollisionShapeGraphicsObjectInternal.

The color of the objects simply loops over 4 possible colors from OpenGLGuiHelper::sColors.

autogenerateGraphicsObjects is called from the initPhysics of several examples.

There are also some explicitly encoded cubes and spheres at: SimpleOpenGL3App.cpp, which can serve as a starting point if you want the possibility of graphics that differ from physics, as should be the case for every serious project: graphics should be more detailed, as they are less computationally expensive. Those are used only in a few examples.

If you are going to study the example browser, I recommend using an IDE with a debugger: it is too much indirection from my brain's static analysis. I've done this analysis with KDevelop4.


Bullet is independent of OpenGL, it's up to you to apply the transformation to your geometry.

You can store your transforms into separate objects instead of modifying your vertices. It's what do Vehicle Dynamics Engine Demo (JOGL + JBullet) and JMonkeyEngine 3 which has its own Bullet binding and a renderer based on JOGL 2 (and some other renderers that I don't use).

Please look at our demos using JOGL and JBullet here: https://github.com/sgothel/jogl-demos/tree/master/src/jbullet