Page 1 of 1

btIDebugDraw with OpenGL 4.4 - [SOLVED]

Posted: Wed Aug 20, 2014 10:07 pm
by manmohan29
I am trying to implement btIDebugDraw interface in an OpenGL 4.4 application.

First I initialize the Physics world like this :

Code: Select all

void initPhysics()
{
    broadphase = new btDbvtBroadphase();
    collisionConfiguration = new btDefaultCollisionConfiguration();
    dispatcher = new btCollisionDispatcher(collisionConfiguration);
    solver = new btSequentialImpulseConstraintSolver;

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

    //groundShape = new btStaticPlaneShape(btVector3(0, 1, 0), 1);
    groundShape = new btBoxShape(btVector3(5, 5, 5));
    fallShape = new btBoxShape(btVector3(1, 1, 1));
    //fallShape = new btSphereShape(1);

    // Orientation and Position of Ground
    groundMotionState = new btDefaultMotionState(btTransform(btQuaternion(0, 0, 0, 1), btVector3(0, -3, 0)));
    btRigidBody::btRigidBodyConstructionInfo groundRigidBodyCI(0, groundMotionState, groundShape, btVector3(0, 0, 0));
    groundRigidBody = new btRigidBody(groundRigidBodyCI);
    dynamicsWorld->addRigidBody(groundRigidBody);

    // Orientation and Position of Falling body
    fallMotionState = new btDefaultMotionState(btTransform(btQuaternion(0, 0, 0, 1), btVector3(-1, 5, 0)));
    btScalar mass = 1;
    btVector3 fallInertia(0, 0, 0);
    fallShape->calculateLocalInertia(mass, fallInertia);
    btRigidBody::btRigidBodyConstructionInfo fallRigidBodyCI(mass, fallMotionState, fallShape, fallInertia);
    fallRigidBody = new btRigidBody(fallRigidBodyCI);
    dynamicsWorld->addRigidBody(fallRigidBody);

    bulletDebugugger.setDebugMode(btIDebugDraw::DBG_DrawWireframe);
    dynamicsWorld->setDebugDrawer(&bulletDebugugger);

}
This is my debug drawer class's definition :

Code: Select all

#pragma once
#include <LinearMath/btIDebugDraw.h>

class CDebugDraw :
    public btIDebugDraw
{
private:
    int m_debugMode;
public:
    CDebugDraw(void);
    virtual ~CDebugDraw(void);

    struct _LINE {
        btVector3 from;
        btVector3 to;

        _LINE(btVector3 f, btVector3 t) {
            from = f;
            to = t;
        }
    };

    std::vector<_LINE> LINES;

    struct _COLOR {
        btVector3 col;

        _COLOR(btVector3 c) {
            col = c;
        }
    };

    std::vector<_COLOR> COLORS;

    GLuint vao, vbo[2];

    virtual void drawLine(const btVector3& from,const btVector3& to,const btVector3& color);

    virtual void drawContactPoint(const btVector3& PointOnB,const btVector3& normalOnB,btScalar distance,int lifeTime,const btVector3& color);

    virtual void reportErrorWarning(const char* warningString);

    virtual void draw3dText(const btVector3& location,const char* textString);

    virtual void setDebugMode(int m_debugMode);

    virtual int getDebugMode() const;

    void doDrawing();
    void cleanDrawing();
};


In the Implementaion DebugDraw.cpp I push all the fromand to vertices in a std::vector struct and save that in a VBO later.

Code: Select all

void CDebugDraw::drawLine(const btVector3& from,const btVector3& to,const btVector3& color)
{
    LINES.push_back(_LINE(from, to));
    COLORS.push_back(_COLOR(color));
}

void CDebugDraw::doDrawing()
{
    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);

    glGenBuffers(2, vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
    glBufferData(GL_ARRAY_BUFFER, LINES.size() * sizeof(_LINE), &LINES[0], GL_STATIC_DRAW);
    glVertexAttribPointer((GLuint)0, 3, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(0);

    glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
    glBufferData(GL_ARRAY_BUFFER, COLORS.size() * sizeof(_COLOR), &COLORS[0], GL_STATIC_DRAW);
    glVertexAttribPointer((GLuint)1, 3, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(1);

    glBindVertexArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

}

void CDebugDraw::cleanDrawing()
{
    // delete buffers
    glDeleteBuffers(2, vbo);
    glDeleteBuffers(1, &vao);
}
now in my rendering function I draw like this :

Code: Select all

// Debug drawing
    glBindVertexArray(bulletDebugugger.vao);
    glDrawArrays(GL_LINES, 0, bulletDebugugger.LINES.size());
    // Clear vectors
    bulletDebugugger.LINES.clear();
    bulletDebugugger.COLORS.clear();

The "triangle" seems to fall from top and stop at the position shown in the screenshot attached. The color of some lines changes from blue to red.

But there are weird lines in the window, I guess that is due to the Debug Drawing function. I think I am doing something wrong in my code.

Can someone guide me where am I doing wrong ?
Has anyone implemented a debug drawer using VAO and/or VBO in OpenGL 4 ?

Re: btIDebugDraw with OpenGL 4.4

Posted: Thu Aug 21, 2014 8:20 am
by rebirth
The way I have it set up using 3.3 (core profile) is by making the line out of a triangle (start-end-start). After all the lines are collected they are passed to the vertex/index buffers and rendered without polygon fill. It's probably not the best way to do it, but it works. Another way is to maybe use a geometry shader, but I haven't tried that myself.

Re: btIDebugDraw with OpenGL 4.4

Posted: Thu Aug 21, 2014 8:39 am
by manmohan29
I got it to fix a little bit.

In my CDebugDraw::drawLine function I changed the way I was adding vertices to the vectors. I also changed the definition of structs LINE and COLORS to use glm::vec3 instead of btVector3. Now code is like this :

Code: Select all

void CDebugDraw::drawLine(const btVector3& from,const btVector3& to,const btVector3& color)
{
    // Changed these lines 
    /*LINES.push_back(_LINE(from, to));
    COLORS.push_back(_COLOR(color));*/

    // to these
    LINES.push_back(_LINE(vec3(from.getX(), from.getY(), from.getZ()), vec3(to.getX(), to.getY(), to.getZ())));
    COLORS.push_back(_COLOR(vec3(color.getX(), color.getY(), color.getZ())));
}
If I clear the vectors LINE and COLORS before next call to my render function then the sphere is not perfect. But if I DO NOT clear the vectors then, all the positions of sphere are drawn (as expected) but sphere is perfect.
pic.png
do I need to store some vertices in my LINES vector for the next call to drawLine, to draw perfect sphere ?

Re: btIDebugDraw with OpenGL 4.4

Posted: Thu Aug 21, 2014 8:51 am
by rebirth
By the looks of it, your buffers are incomplete, because the colours are also wrong. Bullet is not giving out lines which blend between two colours as can be seen by the axis widget in the centre of the cube. They should be fixed coloured RGB lines to represent the XYZ axis.

Re: btIDebugDraw with OpenGL 4.4

Posted: Thu Aug 21, 2014 9:04 am
by manmohan29
@rebirth seems like you are right about incomplete buffers.
can you post your OpenGL 3.3 core profile code (just the part where you store vertices and pass to buffer arrays) here or may be on pastebin ?

Re: btIDebugDraw with OpenGL 4.4

Posted: Thu Aug 21, 2014 9:27 am
by rebirth
I'm away from my home PC at the moment so it will have to wait a few hours. However, from the top of my head I am using indexed triangles. So, the line is created using the two points:

glm::vec3 points[2]

And rendered using 3 indices:
short indices[3] = { 0, 1, 0 }

Re: btIDebugDraw with OpenGL 4.4

Posted: Thu Aug 21, 2014 11:25 am
by manmohan29
I have two rigid bodies in my world. So if I add a condition to clear the vectors only if there have been two passes for the drawLine()

Code: Select all

++c; // increment counter
if (c == 2)
    {
        // Yes counter is equal to number of bodies, then we have all the vertices for debug drawing, now reset the vectors.
        LINES.clear();
        COLORS.clear();
        c = 0; // reset counter
    }
then I get FULL sphere (Ignore the color of vertices at the moment) as seen below in screenshot :
full.png
and if I change falling body's shape to btBoxShape, then I see full cube (Ignore the color of vertices at the moment) as seen below :
full_cube.png
So if I have say 100 rigid bodies in my world, then to debug draw all 100 objects I need 100 passes of drawLine, is it so ?
Does bullet render only one rigid body in a single pass to drawLine() ? seems like that to me.

Re: btIDebugDraw with OpenGL 4.4 - SOLVED

Posted: Fri Aug 22, 2014 10:02 am
by manmohan29
All this issue was due to incorrect count being passed to glDrawArrays().
In my previous code if I use this :

Code: Select all

glDrawArrays(GL_LINES, 0, bulletDebugugger.LINES.size() * 2); // size * 2 , because I have TWO vertices in my LINES struct.
then I have proper lines drawn.

I am not passing COLORS to VBO so all lines are in same color and have changed background color to white.
indices.png
Using indices seems to do the trick.

Code: Select all

// Debug drawing
    /*
    glBindVertexArray(bulletDebugugger.vao);
    glDrawArrays(GL_LINES, 0, bulletDebugugger.LINES.size());*/
    ///////////////////////////
    vector<GLfloat> vertices;
    vector<GLuint> indices;
    unsigned int indexI = 0;
    
    for (vector<CDebugDraw::_LINE>::iterator it = bulletDebugugger.LINES.begin(); it != bulletDebugugger.LINES.end(); it++)
    {
        CDebugDraw::_LINE l = *it;
        
        vertices.push_back(l.from.x);
        vertices.push_back(l.from.y);
        vertices.push_back(l.from.z);

        vertices.push_back(l.to.x);
        vertices.push_back(l.to.y);
        vertices.push_back(l.to.z);
        
        indices.push_back(indexI);
        indices.push_back(indexI + 1);
        indexI += 2;
    }
    glBindVertexArray(bulletDebugugger.vao);
    glDrawElements(GL_LINES, indices.size(), GL_UNSIGNED_INT, (void*)&indices[0]);
    ///////////////////////////
I found this code while surfing on YouTube !!! Yes, here's link to his cool project video : https://www.youtube.com/watch?v=nhQK1dfCxDQ
:D so unexpected !!
Thanks to "Tomáš Kimer", I found his code useful. Here's the link to it : https://github.com/david-sabata/Univers ... e.cpp#L584
For Visual Studio 2010 here's code : https://docs.google.com/file/d/0BzrGmqQ ... hyb3c/edit
so that others can refer it.

Re: btIDebugDraw with OpenGL 4.4

Posted: Fri Aug 22, 2014 1:08 pm
by Erwin Coumans
latest Bullet has OpenGL 3+ rendering, see App_AllBullet2Demos and those links:

https://github.com/bulletphysics/bullet ... .cpp#L1382
https://github.com/bulletphysics/bullet ... ugDrawer.h

Re: btIDebugDraw with OpenGL 4.4 - [SOLVED]

Posted: Wed Apr 12, 2017 2:02 pm
by Ziket
Use this in your DrawLine and it will work fine (with the correct colors represent the normals)
First u have to compile you program! Dont forgot it, and multiply the gl_FragPosition with the view and projection matrix (the position is getter in world pos)

Code: Select all

 struct btLine{
    GLfloat vertices[6];
    btLine(const btVector3& f, const btVector3& t){
      vertices[0] = f.x();
      vertices[1] = f.y();
      vertices[2] = f.z();

      vertices[3] = t.x();
      vertices[4] = t.y();
      vertices[5] = t.z();
    }
  };

Code: Select all

GME::btLine lines(from, to);
  btVector3 result = to - from;
  glm::vec3 colors = {result.x(), result.y(), result.z()};
  colors = glm::normalize(colors);
  GLuint indices[] = {0,1};

  GLuint vao, vbo, ebo;

  glGenVertexArrays(1, &vao);
  glGenBuffers(1, &vbo);
  glGenBuffers(1, &ebo);

  glBindVertexArray(vao);

  //UPLOADING VERTEX
  glBindBuffer(GL_ARRAY_BUFFER, vbo);
  glBufferData(GL_ARRAY_BUFFER,
               sizeof(GLfloat) * 6, lines.vertices, GL_STATIC_DRAW);
  //UPLOADING INDEXES
  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
  glBufferData(GL_ELEMENT_ARRAY_BUFFER,
               sizeof(GLuint) * 2,
               indices,
               GL_STATIC_DRAW);
  glEnableVertexAttribArray(0);
  glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,
                        sizeof(GLfloat) * 3, (GLvoid*)0);
  glBindVertexArray(0);


  //use program
  material_->use();
  material_->setValue(glm::value_ptr(colors), "ph_objectColor");
  material_->setProjectionMatrix(gmeinstance->getCurrentCamera()->getProjectionMatrix());
  material_->setViewMatrix(gmeinstance->getCurrentCamera()->getViewMatrix());
  //use geometry
  glBindVertexArray(vao);
  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,ebo);
  glDrawElements(GL_LINES, 2, GL_UNSIGNED_INT, 0);
  glBindVertexArray(0);

  //delete buffers
  glDeleteVertexArrays(1, &vao);
  glDeleteBuffers(1, &vbo);
  glDeleteBuffers(1, &ebo);