Issues with BulletPhysics & OpenGL

Started by
3 comments, last by Glass_Knife 9 years, 3 months ago

Dear community,

I'm currently programming a 3D game in pure C++ with OpenGL, GLM, ASSIMP, SFML & BulletPhysics. smile.png

But now, I'm at a point, where I'm done with it, 'cause I couldn't get the problem or find something on the internet, which can lead into the direction of a fix. huh.png
I've got a problem with updating my meshs model matrix with the world matrix, getting from the btMotionState of a btRigidBody, to render it via shader. unsure.png

The shader computes the vertex location like


gl_Position = projection_mat4 * view_mat4 * model_mat4 * vec4(position, 1.0);

Where projection is computed by glm::perspective(...), view by glm::lookAt(...) and model by the physics system, see below. smile.png

So far, I'm creating the whole physics world in a class called "PhysicsManager".
It's a test and so it creates the whole bullet physics system like that:


m_broadphase = new btDbvtBroadphase();
m_collisionConfiguration = new btDefaultCollisionConfiguration();
m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);

btGImpactCollisionAlgorithm::registerAlgorithm(m_dispatcher);

m_solver = new btSequentialImpulseConstraintSolver();
m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher, m_broadphase, m_solver, m_collisionConfiguration);
m_dynamicsWorld->setGravity(btVector3(0.0f, -9.81f, 0.0f));


// Floor
m_groundShape = new btStaticPlaneShape(btVector3(0, 1, 0), 1);
m_groundMotionState = new btDefaultMotionState(btTransform(btQuaternion(0, 0, 0, 1), btVector3(0, 0, -1)));
btRigidBody::btRigidBodyConstructionInfo groundRigidBodyCI(0, m_groundMotionState, m_groundShape, btVector3(0, 0, 0));
m_groundRigidBody = new btRigidBody(groundRigidBodyCI);

m_dynamicsWorld->addRigidBody(m_groundRigidBody);

// Model as a sphere in BulletPhysics
m_fallShape = new btSphereShape(1);
m_fallMotionState = new btDefaultMotionState(btTransform(btQuaternion(0, 0, 0, 1), btVector3(8, 50, 8)));
btScalar mass = 2;
btVector3 fallInertia(0, 0, 0);
m_fallShape->calculateLocalInertia(mass, fallInertia);
btRigidBody::btRigidBodyConstructionInfo fallRigidBodyCI(mass, m_fallMotionState, m_fallShape, fallInertia);
m_fallRigidBody = new btRigidBody(fallRigidBodyCI);

m_dynamicsWorld->addRigidBody(m_fallRigidBody);

// GLDebugDrawer from the demos of the Bullet 3.X github page
glDebugDrawer = GLDebugDrawer();
glDebugDrawer.setDebugMode(btIDebugDraw::DBG_DrawAabb | btIDebugDraw::DBG_DrawWireframe | btIDebugDraw::DBG_DrawConstraints | btIDebugDraw::DBG_DrawConstraintLimits | btIDebugDraw::DBG_DrawNormals);
m_dynamicsWorld->setDebugDrawer(&glDebugDrawer);

And I'm updating the world each frame with


m_dynamicsWorld->stepSimulation(1.0f / 60.0f, 10);

After that, I'm updating the meshs model matrix with


btTransform trans;
m_game->m_physics->m_fallRigidBody->getMotionState()->getWorldTransform(trans);
trans.getOpenGLMatrix(glm::value_ptr(m_medikits[0].m_model));

where "m_model" is a glm::mat4 initialised as "m_model = glm::mat4()". smile.png

Then rendering is done via


glBindVertexArray(mesh->vao);
glBindTexture(GL_TEXTURE_2D, mesh->tex);

GLuint uniform_model = glGetUniformLocation(p_shader, "model");

glUniformMatrix4fv(uniform_model, 1, GL_FALSE, glm::value_ptr(p_objects->at(i).m_model));
glDrawArrays(GL_TRIANGLES, 0, mesh->size);

glBindVertexArray(0);
glBindTexture(GL_TEXTURE_2D, 0);

So I bind all the stuff of the 3D mesh, draw it and unbind it.

Problem is:

Why is my rendering not aligned with the physically computed bounding boxes?
(I mean not perfectly aligned like origin/center of mass but not anywhere near the collision box?)

Can anyone give me a hint or something like that?

Here's a picture of what I mean:

8F5WdXd.png?1

Cheers,

NightDreamer

Advertisement

Alright. After many, many hours of testing and stuff, I've managed to solve the problem on my own. happy.png

The GLDebugDrawer class, I've got from the examples (GLDebugDrawer.h , GLDebugDrawer.cpp), draws stuff with old OpenGL (using glBegin()/glEnd() instead of shaders).

My shaders use a projection matrix, a view matrix and a model matrix, all three responsible for the final vertex position in the world


gl_Position = projection_matrix * view_matrix * model_matrix * local_vertex_position; 

When the GLDebugDrawer class uses their glBegin()/glEnd() directives, there's something like a fall back situation.

The model_matrix, defined by the specific model in its own model space, sums up with the model matrix internally used by old glBegin()/glEnd() like


gl_Position = projection_matrix * view_matrix * model_matrix * glBegin/glEnd-Modelmatrix * local_vertex_position

So the result will look like the image above:

  • the object is rendered with his model_matrix given by the bullet engine
  • the shapes and collision shapes are rendered with the previously uploaded model_matrix * glBegin/glEnd-Modelmatrix (so the translation/rotation is somewhat like doubled)

(Note: glPushMatrix() and glPopMatrix() in GLDebugDrawer won't help to discard the previously uploaded matrix.

I think, because these function calls don't change the shader but the old OpenGL matrix stack)

Solution is to discard the model_matrix by uploading an identity matrix, just before the draw calls with glBegin()/glEnd(). Something like:


glm::mat4 model_matrix = glm::mat4();
GLuint uniform_model_matrix = glGetUniformLocation(m_opengl->getShader("3DBasic"), "model_matrix");
glUniformMatrix4fv(uniform_model_matrix, 1, GL_FALSE, glm::value_ptr(model_matrix));
m_physics->m_dynamicsWorld->debugDrawWorld();

This results in something like multiplying with 1, so shader internal it's like:


gl_Position = projection_matrix * view_matrix * 1 * glBegin/glEnd-Modelmatrix * local_vertex_position

Now the OpenGL 1 (or 2) draw calls use ONLY their own model matrices.

Hope it's useful for other people.

Have a nice day,

NightDreamer

SOLVED

You know what I love even more than seeing someone solve their own problem? When they leave up the question and answer it so others can learn from their mistakes.

+1

Which of those libraries did you get the GLDebugDrawer from that was causing the trouble?

I think, therefore I am. I think? - "George Carlin"
My Website: Indie Game Programming

My Twitter: https://twitter.com/indieprogram

My Book: http://amzn.com/1305076532

Thanks for the upvote. happy.png

Yeah, I like it too, that's why I posted my solution. EDIT: included information above And I'll edit it and include some more information, when I've got some more free time. wink.png

The GLDebugDrawer class I've got was from the old bullet google code page -> link

There you'll find the class files I've used (GLDebugDrawer.h, GLDebugDrawer.cpp) happy.png

I've been bit before by libraries mixing old and new OpenGL. Not all platforms support both. It can be a real pain.

I think, therefore I am. I think? - "George Carlin"
My Website: Indie Game Programming

My Twitter: https://twitter.com/indieprogram

My Book: http://amzn.com/1305076532

This topic is closed to new replies.

Advertisement