简体   繁体   中英

Drawing .obj with VBO

I have a problem with drawing a cube with VBO from a .obj file.

Here is the .obj :

# cube.obj
#

g cube

v  0.0  0.0  0.0
v  0.0  0.0  1.0
v  0.0  1.0  0.0
v  0.0  1.0  1.0
v  1.0  0.0  0.0
v  1.0  0.0  1.0
v  1.0  1.0  0.0
v  1.0  1.0  1.0

vn  0.0  0.0  1.0
vn  0.0  0.0 -1.0
vn  0.0  1.0  0.0
vn  0.0 -1.0  0.0
vn  1.0  0.0  0.0
vn -1.0  0.0  0.0

f  1//2  7//2  5//2
f  1//2  3//2  7//2 
f  1//6  4//6  3//6 
f  1//6  2//6  4//6 
f  3//3  8//3  7//3 
f  3//3  4//3  8//3 
f  5//5  7//5  8//5 
f  5//5  8//5  6//5 
f  1//4  5//4  6//4 
f  1//4  6//4  2//4 
f  2//1  6//1  8//1 
f  2//1  8//1  4//1 

To draw it, I first read the objet with the glmReadOBJ function. Next, I extract the information contained in the model generated (with the "trianglulate" function) to be able to create the VBO object and then draw it, here is what I do :

void triangulate(GLfloat* vertices, GLfloat* normals, GLMmodel *model)
  {
      int i, j;
      int it = 0;
      GLuint *tempN, *tempV;

      for (int i = 0; i < model->numtriangles; i++)
      {
          tempV = model->triangles[i].vindices;
          tempN = model->triangles[i].nindices;

          for (int j = 0; j < 3; j++)
          {
              vertices[it] = model->vertices[tempV[j] - 1];
              normals[it] = model->normals[tempN[j] - 1];

              it++;
          }

      }  
  }

  void glmInitVBO(GLMmodel* model, int* vboId)
  {
      GLfloat *vertices = (GLfloat*)malloc(model->numtriangles * 3 * sizeof(GLfloat));
      GLfloat *normals = (GLfloat*)malloc(model->numtriangles * 3 * sizeof(GLfloat));
      triangulate(vertices, normals, model);

      glGenBuffersARB(1, vboId);
      glBindBufferARB(GL_ARRAY_BUFFER_ARB, vboId);

      glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(vertices) + sizeof(normals), 0, GL_STATIC_DRAW_ARB);
      glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(vertices),vertices);                             // copy vertices starting from 0 offest
      glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, sizeof(vertices), sizeof(normals), normals);         // copy normals after vertices

  }

  void glmDrawVBO(GLMmodel* model, int* vboId)
  {
      GLfloat *vertices = (GLfloat*)malloc(model->numtriangles * 3 * sizeof(GLfloat));
      GLfloat *normals = (GLfloat*)malloc(model->numtriangles * 3 * sizeof(GLfloat));
      triangulate(vertices, normals, model);

      glBindBufferARB(GL_ARRAY_BUFFER_ARB, *vboId);


      glEnableClientState(GL_NORMAL_ARRAY);
      glEnableClientState(GL_VERTEX_ARRAY);

      glNormalPointer(GL_FLOAT, 0, (void*)sizeof(vertices));
      glVertexPointer(3, GL_FLOAT, 0, 0);

      glDrawArrays(GL_TRIANGLES, 0, 36);

      glDisableClientState(GL_VERTEX_ARRAY);  // disable vertex arrays
      glDisableClientState(GL_NORMAL_ARRAY);

      glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
  }

In my main, I call glmReadOBJ, then glmInitVBO and finally glmDrawVBO but nothing happens : the window remains black, nothing is drawn. I don't know what I did wrong and tried many things for hours, but the only thing I obtain in the end is a black window ...

Thank you for your help !

The main issue I see is unrelated to your OpenGL usage, but just a misunderstanding of how the sizeof operator works. For example in this code segment (there are more similar cases in the rest of the code):

GLfloat *vertices = (GLfloat*)malloc(model->numtriangles * 3 * sizeof(GLfloat));
GLfloat *normals = (GLfloat*)malloc(model->numtriangles * 3 * sizeof(GLfloat));
...
glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(vertices) + sizeof(normals), 0, GL_STATIC_DRAW_ARB);
glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(vertices),vertices);                             // copy vertices starting from 0 offest
glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, sizeof(vertices), sizeof(normals), normals);         // copy normals after vertices

vertices and normal are declared as pointer variables. Their sizes are therefore 32 bits (4 bytes) when building in 32-bit mode, and 64 bits (8 bytes) when building in 64-bit mode. So 4/8 are the values you get when using the sizeof operator on the variables.

What you need to pass to the glBufferData() and glBufferSubData() functions is the actual size of the data you allocated, not the size of the pointer. For example:

glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, model->numtriangles * 3 * sizeof(GLfloat), vertices);

Another problem is with this call in glmInitVBO() :

glBindBufferARB(GL_ARRAY_BUFFER_ARB, vboId);

where vboId is declared as a pointer to the int value that contains the VBO id. However, glBindBuffer() takes the id as an argument, not a pointer to the id. So the call should be:

glBindBufferARB(GL_ARRAY_BUFFER_ARB, *vboId);

BTW, these functions have been part of standard OpenGL since about version 1.1. There really shouldn't be a need to use the extension version.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM