WaveFront .obj 加载器未按应有的方式显示对象(VBO 和 VAO)

Posted

技术标签:

【中文标题】WaveFront .obj 加载器未按应有的方式显示对象(VBO 和 VAO)【英文标题】:WaveFront .obj loader doesn't display the object like it should (VBO & VAO) 【发布时间】:2012-09-14 12:13:26 【问题描述】:

我正在开发 WaveFront .obj 加载器,我的第一个目标是从以下 .obj 文件中加载所有顶点和索引(显示具有弯曲边缘的立方体)。

# Blender v2.62 (sub 0) OBJ File: 'Cube.blend'
# www.blender.org
o Cube
v 0.900000 -1.000000 -0.900000
v 0.900000 -1.000000 0.900000
v -0.900000 -1.000000 0.900000
v -0.900000 -1.000000 -0.900000
v 0.900000 1.000000 -0.900000
v 0.899999 1.000000 0.900001
v -0.900000 1.000000 0.900000
v -0.900000 1.000000 -0.900000
v 1.000000 -0.900000 -1.000000
v 1.000000 -0.900000 1.000000
v -1.000000 -0.900000 1.000000
v -1.000000 -0.900000 -1.000000
v 1.000000 0.905000 -0.999999
v 0.999999 0.905000 1.000001
v -1.000000 0.905000 1.000000
v -1.000000 0.905000 -1.000000
f 1//1 2//1 3//1
f 1//1 3//1 4//1
f 13//2 9//2 12//2
f 13//2 12//2 16//2
f 5//3 13//3 16//3
f 5//3 16//3 8//3
f 15//4 7//4 8//4
f 15//5 8//5 16//5
f 11//6 15//6 16//6
f 11//6 16//6 12//6
f 14//7 6//7 7//7
f 14//7 7//7 15//7
f 10//8 14//8 11//8
f 14//8 15//8 11//8
f 13//9 5//9 6//9
f 13//9 6//9 14//9
f 9//10 13//10 10//10
f 13//11 14//11 10//11
f 9//12 1//12 4//12
f 9//12 4//12 12//12
f 3//13 11//13 12//13
f 3//14 12//14 4//14
f 2//15 10//15 11//15
f 2//15 11//15 3//15
f 1//16 9//16 10//16
f 1//16 10//16 2//16
f 5//17 8//17 7//17
f 5//17 7//17 6//17

我已经在两个向量中加载了所有顶点和索引,称为 verticesVec 和 indicesVec 并且我已经检查了它们(它们的所有输入都以正确的顺序排列,verticesVec[0] = 0.9 和 indicesVec[0] = 1)。我加载 VertexBufferObject 中的顶点和 VerticArrayObject 中的索引以及着色器字段设置。

但是,当我渲染立方体时,我得到以下不正确的图像。我已经重新检查了所有代码,但找不到出错的部分。它与向量和向量的字节大小有关吗?

以下代码来自我的 Draw/Render 方法,该方法执行所有渲染。

    glUseProgram(theProgram);
    GLuint modelToCameraMatrixUnif = glGetUniformLocation(theProgram, "modelToCameraMatrix");
    GLuint perspectiveMatrixUnif = glGetUniformLocation(theProgram, "cameraToClipMatrix");
    glUniformMatrix4fv(perspectiveMatrixUnif, 1, GL_FALSE, glm::value_ptr(cameraToClipMatrix));

    glm::mat4 identity(1.0f);
    glutil::MatrixStack stack(identity); // Load identity Matrix

    // Push for Camera Stuff
    glutil::PushStack camera(stack);
    stack.Translate(glm::vec3(camX, camY, camZ));

    //Push one step further to fix object 1
    glutil::PushStack push(stack);

    stack.Translate(glm::vec3(0.0f, 0.0f, 3.0f));
    // Draw Blender object
    glBindVertexArray(this->load.vertexArrayOBject);
    glUniformMatrix4fv(modelToCameraMatrixUnif, 1, GL_FALSE, glm::value_ptr(stack.Top()));
    glDrawElements(GL_TRIANGLES, this->load.indicesVec.size(), GL_UNSIGNED_SHORT, 0);

    // Pop camera (call destructor to de-initialize all dynamic memory)
    camera.~PushStack();

    // Now reset all buffers/programs
    glBindVertexArray(0);
    glUseProgram(0);

在我的 .obj 加载器中初始化缓冲区对象:

void Loader::generateVertexBufferObjects()

     // Fils the vertex buffer object with data
    glGenBuffers(1, &vertexBufferObject);
    glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);
    glBufferData(GL_ARRAY_BUFFER, verticesVec.size() * 4, &verticesVec[0], GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);


    // Fills the index buffer object with its data
    glGenBuffers(1, &indexBufferObject);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferObject);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicesVec.size() * 4, &indicesVec[0], GL_STATIC_DRAW);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);


void Loader::generateVertexArrayObjects()

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

    glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferObject);

    glBindVertexArray(0);

【问题讨论】:

检查您的索引。 obj 中的索引从 1 开始,但在 openGL 中它们从 0 开始,因此您可能必须从所有索引中减去 1。 @VaughnCato:好一个!从来没想过。我添加了一个索引——;在将它添加到向量之前,但不幸的是它仍然是一个凌乱的立方体,所以除了索引之外还有更多错误:(。 你的指数真的很短吗?您为每个值分配了 4 个字节,但随后告诉 OpenGL 它们是无符号短的。 @Tim:蒂姆,我为你鼓掌。这确实是问题所在,出于某种原因,我认为未签名的短裤用于整数,但它们当然不是。将其更改为 GL_UNSIGNED_INT 并且有效!如果您将评论变成答案,我将接受它作为最终答案。谢谢你:) 【参考方案1】:

您将索引创建为无符号整数,但您向 OpenGL 传递了它们的类型为 GL_UNSIGNED_SHORT。 glDrawElements 的类型参数必须与上传到索引缓冲区的数据类型相匹配。

【讨论】:

这就是答案;您实际上可以在示例图片中看到正顶点的渲染。

以上是关于WaveFront .obj 加载器未按应有的方式显示对象(VBO 和 VAO)的主要内容,如果未能解决你的问题,请参考以下文章

理解 Java 中的引用; BST 的 addNode() 函数未按应有的方式运行 [重复]

HTML 引导页脚未按应有的方式响应。它没有粘在底部,也没有像我编程的那样显示 100% 宽度

迭代器未按预期运行

Sendgrid 替换包装器未按预期工作

阅读电子邮件的 html 模板未按预期显示

Jsoup :has() 选择器未按预期工作