用VBO绘制.obj

时间:2016-01-10 01:29:22

标签: c opengl vbo .obj

从使用.obj文件中的VBO绘制多维数据集时遇到问题。

这是.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 

要绘制它,我首先使用glmReadOBJ函数读取objet。接下来,我提取生成的模型中包含的信息(使用" trianglulate"函数)以便能够创建VBO对象然后绘制它,这是我的工作:

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);
  }

在我的主要内容中,我调用glmReadOBJ,然后调用glmInitVBO,最后调用glmDrawVBO,但没有任何反应:窗口保持黑色,没有绘制任何内容。 我不知道自己做错了什么,多次尝试了很多东西,但我最终得到的只是一个黑色的窗户......

感谢您的帮助!

1 个答案:

答案 0 :(得分:2)

我看到的主要问题与您的OpenGL使用无关,但只是对sizeof运算符如何工作的误解。例如,在此代码段中(其余代码中有更多类似的情况):

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

verticesnormal被声明为指针变量。因此,当以32位模式构建时,它们的大小为32位(4字节),而当以64位模式构建时,它们的大小为64位(8字节)。所以4/8是在变量上使用sizeof运算符时得到的值。

您需要传递给glBufferData()glBufferSubData()函数的是您分配的数据的实际大小,而不是指针的大小。例如:

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

另一个问题是glmInitVBO()中的此次调用:

glBindBufferARB(GL_ARRAY_BUFFER_ARB, vboId);

其中vboId被声明为指向包含VBO id的int值的指针。但是,glBindBuffer()将id作为参数,而不是指向id的指针。所以电话应该是:

glBindBufferARB(GL_ARRAY_BUFFER_ARB, *vboId);
BTW,这些函数自版本1.1以来一直是标准OpenGL的一部分。确实不需要使用扩展版本。