0

I'm following this tutorial to write an OpenGL application. I have a dataset of 3D objects, where each object is described by:

  • position (a 3D vector)
  • bounding-box (lower and upper 3D vectors)
  • point cloud (in my case, a pcd file)

So far, I managed to draw a point cloud loaded from a pcd file (here you can find the code). In the render loop I wrote:

  //3) bind VAO
  glBindVertexArray(_VAO);

  //4) draw
  glDrawArrays(GL_POINTS,0,_num_vertices);

where in the GL_BUFFER_ARRAY I stored the vertices of the cloud.

Now, my question is the following:

For this object I want also to draw a bounding-box (as a wireframe rectangle) and a set of 3d axis centered in its position (as a set of three cylinders). What is the best way to do that?


@MichaelIV

Thanks for your reply. I'm following your advice, but I get a weird behavior.

To populate the buffer I wrote the following code:

  Eigen::Vector3f min(1.7921,-0.2782,0.0);
  Eigen::Vector3f max(2.1521,0.1994,0.9915);

  insertVertex(_box_vertices,min.x(),min.y(),min.z(),0.0,0.0,1.0);
  insertVertex(_box_vertices,max.x(),min.y(),min.z(),0.0,0.0,1.0);
  insertVertex(_box_vertices,max.x(),max.y(),min.z(),0.0,0.0,1.0);
  insertVertex(_box_vertices,min.x(),max.y(),min.z(),0.0,0.0,1.0);

  _num_box_vertices = _box_vertices.size()/6.0f;
  std::cerr << "Box vertices:" << std::endl;
  for(size_t i=0; i<_num_box_vertices; ++i){
    std::cerr << _box_vertices[6*i] << " " << _box_vertices[6*i+1] << " " << _box_vertices[6*i+2] << " ";
    std::cerr << _box_vertices[6*i+3] << " " << _box_vertices[6*i+4] << " " << _box_vertices[6*i+5] << std::endl;
  }

where _box_vertices is a std::vector<float> array and insertVertex is just an utility function. If I print the array this is what I get:

dede@srrg-02:~/source/develop/opengl_viewer/bin$ ./opengl_viewer
Box vertices:
1.7921 -0.2782 0 0 0 1
2.1521 -0.2782 0 0 0 1
2.1521 0.1994 0 0 0 1
1.7921 0.1994 0 0 0 1

So, it should be correct. Then I use this code (OpenGL 3.3) to allocate gl objects:

  //[OPENGL] create box buffers
  glGenBuffers(1, &_bVBO);
  glBindBuffer(GL_ARRAY_BUFFER, _bVBO);
  glBufferData(GL_ARRAY_BUFFER, _box_vertices.size()*sizeof(float), &_box_vertices[0], GL_STATIC_DRAW);

  glGenVertexArrays(1, &_bVAO);
  glBindVertexArray(_bVAO);

  //[OPENGL] link box vertex attributes
  glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
  glEnableVertexAttribArray(0);
  glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3* sizeof(float)));
  glEnableVertexAttribArray(1);

and this to render them:

  //3) bind box VAO
  glBindVertexArray(_bVAO);

  //4) draw box
  glDrawArrays(GL_LINE_LOOP,0,_num_box_vertices);

but the result is not what I would expect:

enter image description here

It looks like each line starts from (0,0,0) instead of starting from my desired point.

Can you please explain me how to fix that?

Thanks.

Federico Nardi
  • 510
  • 7
  • 19
  • see [complete GL+GLSL+VAO/VBO C++ example](https://stackoverflow.com/a/31913542/2521214) and look at the VAO/VBO example of cube. Your bbox will have almost the same points (use min,max values instead of `+/-1.0`) but different primitive (`GL_LINES`) and slightly different indices. However doing bbox in the old style api is easier (not posible in core profile) ... – Spektre Jul 13 '18 at 08:36
  • You should put lines start/end positions into a buffer and do the same you do for other geometry but with GL_LINES, or LINE_STRIP mode. – Michael IV Jul 13 '18 at 15:13

1 Answers1

1

Here is how I draw bounds (GL 4.5 API):

Init once:

         Gluint mVao = 0;
          //CReate VAO:
         glCreateVertexArrays(1, &mVao);

         glEnableVertexArrayAttrib(mVao, 0);
         glVertexArrayAttribFormat(mVao, 0, 3, GL_FLOAT, GL_FALSE, 0);
         //Create VBO
         glCreateBuffers(1,&mVbo);
         glNamedBufferData(mVbo, dataSize, NULL, GL_DYNAMIC_DRAW);
         //Bind VBO to VAO
         glVertexArrayAttribBinding(mVao, 0, 0);
         glVertexArrayVertexBuffer(mVao, 0, mVbo, 0, sizeof(float) * 3);

On every frame:

Prepare AABB vertices (using GLM math lib),aabb may come as some DrawDebug() function argument:

        const GLfloat data[48] = {
        // Loop 1: XY Z (min)
        aabb.mMin.x, aabb.mMin.y, aabb.mMin.z,
        aabb.mMax.x, aabb.mMin.y, aabb.mMin.z,
        aabb.mMax.x, aabb.mMax.y, aabb.mMin.z,
        aabb.mMin.x, aabb.mMax.y, aabb.mMin.z,

        // Loop 2: XY Z (max)
        aabb.mMin.x, aabb.mMin.y, aabb.mMax.z,
        aabb.mMax.x, aabb.mMin.y, aabb.mMax.z,
        aabb.mMax.x, aabb.mMax.y, aabb.mMax.z,
        aabb.mMin.x, aabb.mMax.y, aabb.mMax.z,

        // Lists:
        // 1
        aabb.mMin.x, aabb.mMin.y, aabb.mMin.z,
        aabb.mMin.x, aabb.mMin.y, aabb.mMax.z,
        // 2
        aabb.mMax.x, aabb.mMin.y, aabb.mMin.z,
        aabb.mMax.x, aabb.mMin.y, aabb.mMax.z,
        // 3
        aabb.mMax.x, aabb.mMax.y, aabb.mMin.z,
        aabb.mMax.x, aabb.mMax.y, aabb.mMax.z,
        // 4
        aabb.mMin.x, aabb.mMax.y, aabb.mMin.z,
        aabb.mMin.x, aabb.mMax.y, aabb.mMax.z,
    };

    glNamedBufferSubData(mVbo,0, mDataSize, data);

   //combine line loop and line drawing to minimize number of draw calls:
    glDrawArrays(GL_LINE_LOOP, 0, 4);
    glDrawArrays(GL_LINE_LOOP, 4, 4);
    glDrawArrays(GL_LINES, 8, 8));

IMPORTANT note: I omitted here shader program binding as there is nothing special there.But you must provide shader program,where vertex shader performs transformation of the aabb coordinates with MVP (model-view-projection) matrix,or only with view - projection matrix if you transformed aabb vertices with model matrix on the client side.

Michael IV
  • 11,016
  • 12
  • 92
  • 223