How to apply Bullet physics to drawn Opengl 3d shapes
Asked Answered
E

4

7

I was just wondering whether there is a way to apply bullet physics to opengl drawn objects (created using glVertex3f or triangle mesh with glVertexAttribPointer). I am currently using jogl and jbullet to apply physics to my 3D objects. Specifically if I give a buffer of vertices for a triangle mesh shape for the 3d object. I need Bullet to create a CollisionShape based on the triangle mesh shape, and apply the physics to it, which at the same time apply physics to the drawn opengl objects. At the moment, the physical collision shape may move (in bullet), but the drawn opengl shape is not.

Otherwise, can I create a collision shape, get the vertices of the collision shape after the physics has been applied after each simulation step, and then draw the object based on the location of the vertices. I have looked at the Hello world example for bullet but it only help me apply physics on the position of the opengl object (based on the z,y,x axis_ and not cool things like for example a corner of the cube hitting a plane starts rolling and spinning.

It would be great if someone can give me some code or demo that can do this. Or give me some hints as to how I can make this work. I already looked at this tutorial on bullet: http://www.raywenderlich.com/53077/bullet-physics-tutorial-getting-started. But I can't seem to find the information to how bullet is applied to opengl objects.

Exciting answered 15/11, 2014 at 16:35 Comment(0)
S
6

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

Scrapbook answered 17/11, 2014 at 8:6 Comment(5)
Thanks for your post. It's very comprehensive and maybe what I'm looking for. I'm just wondering about the "syncronize the "btTransform" of your bullet shape with the transformation matrix of the graphic shape". How exactly do I apply the btTransform with the shape? Is it making a transformation for each vertex of the shape? Or is there a function in opengl that allows me to apply rotation and translation to the entire shape?Exciting
There is not any function in openGl that allow you to apply rotation and translation to any entire shape because in opengl you just manipulate vertices, so i think you need to create your own graphics shape class. This class must at least contain all the vertices used to represent your graphics shape. So let's say your graphics shape class has a function which lets you translate all the vertices contained in it, and another one which allow you to rotate all of its verticesScrapbook
Thanks user3817643, for clarifying. I'm quite new to Opengl, so I don't know much about what it can or cannot do.Exciting
The most important thing to note is: you really have to reimplement the btMotionState. When you create a btRigidBody, perhaps you are used to write btRigidBody* anyBody = new btRigidBody(mass,new btDefaultMotionState,shape,localInertia); . The instanciation of this btDefaultMotionState have to be replaced by any instanciation of your derived btMotionState class. How it works? In fact for every single step of Bullet world, the motion state that you attached with each moving bullet shape is called. The function setWorldTransform of the btMotionState must contains the code to render the shapeScrapbook
I think GL_ShapeDrawer.cpp has been replaced with OpenGL 3 GLInstancingRenderer.cpp by default: https://mcmap.net/q/1011029/-how-to-apply-bullet-physics-to-drawn-opengl-3d-shapesKossuth
K
6

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.

Kossuth answered 5/5, 2016 at 20:24 Comment(0)
M
3

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

Mislike answered 16/11, 2014 at 11:24 Comment(7)
Thanks, I will have a look at the demo and get back to youExciting
Hi, I was wondering whether you can help me find the code for transformation of objects instead of vertices in the demo? Like in the RagDoll.java, which part of the code actually allow me to transform the object? And which part actually shows how drawn JOGL object is transformed according to JBullet. I had a look at the vehicle dynamic engine demo, but I can't seem to find the main class for that demo.Exciting
Look at this class: github.com/sgothel/jogl-demos/blob/master/src/jbullet/src/… Focus on the references of CompoundShape (JBullet) used in drawOpenGL(). The transforms are stored into javabullet.linearmath.Transform.Mislike
Ok, thanks, I understand the part about storing transformation. But why store the transformation? each world's step has a new world transform for the object right? One last thing how can I get the transformation to be applied to my drawn geometry (I know you say it's up to me, but I want to find the fastest way). e.g if Bullet give me a transformation of my triangle: to translate y-axis 10. Then should I translate 3 vertices of the triangle up 10, or is there a faster function that can translate the triangle up 10 in jogl.Exciting
Modifying a single transformation is a lot faster than modifying each vertex of a mesh while you don't use a transform per vertex. Then, you can use glRotate, glScale and glTranslate just before drawing like in the simple OpenGL "robot arms" demo that you can find on Internet or you can use your transforms in a vertex shader.Mislike
Look at the example named "Interactive Robot Arm" here: cs.lmu.edu/~ray/notes/openglexamples It's in C but it's very simple and commented.Mislike
Thanks for your help, you are right, storing a transformation is the way to go rather than modifying each each vertex directly.Exciting
F
0

Without studying the specifics of Bullet or OpenGL (I've coded in OpenGL a little) it seems you wish to apply Bullet to an object twice, once for the CollisionShape (whatever that is) and then for the drawn opengl object.

It seems it would be a matter of creating your OpenGL object in a memory object, applying the Bullet method to get your CollisionShape (whatever that is), saving this data in memory, then applying the Bullet method to this new triangle list for world positioning (if my understanding of your question is right).

It would be similar to applying 2 different transforms on an object separately without the benefit of matrix math. You would calculate the new positions of the vectors based on rotation, then after you have these points move them in the world based on translation. You would have an intermediate step that is used in memory to apply your second translation. That is the way I had done it in my first 3d rendered I made without learning how it was done to see if I could come up with it on my own.

Maybe this will help you, maybe it won't. If it doesn't, perhaps you can explain where you are having troubles and I (or others) can look into the specifics of OpenGL and Bullet to come up with the actual algorithm for you (although I'm sure it probably exists somewhere). If you search enough you'll probably find code on the Interwebs that does something similar that you can modify, or you can try to do it on your own.

It could be my method wouldn't work, but I see no reason why it wouldn't if I understand your question correctly (which I may not, not knowing what a "CollisionShape" is in the first place).

Femmine answered 15/11, 2014 at 16:48 Comment(5)
A collision shape is the bounding object bullet operates on.Copyright
Thanks for the answer.Basically Bullet is a library that applies physics to a 3d object by create something called a collision shape. A collision shape is used for collision detection and transformation. It will apply rotation and translation to this collision shape based on the law of physics. The problem is I don't know how to make Bullet apply these transformations to the 3d objects (or at least vertices) in opengl, because only it applies to 'virtual' invisible shapes, the drawn opengl shapes. Though it's possible to get what the transformation is for a vertex in the 'virtual' shape.Exciting
Bullet will not apply the tranformations to OpenGL objects. You have to query them manually and apply the OpenGL transformations yourself.Copyright
Sorry, BDL, can you explain a bit more details? Does that mean that I have to apply the tranformation from Bullet to every single vertex of the drawn Opengl Triangle Mesh?Exciting
gouessej seems to be pointing at the proper solution in his post.Femmine

© 2022 - 2024 — McMap. All rights reserved.