使用OpenGL

时间:2016-10-18 11:44:44

标签: c++ parsing opengl

我正在编写一个简单的OBJ解析器。现在,当#texture_coordinates>时,我不知道如何处理这个案子。 #vertices。 我的OBJ文件如下所示:

# Blender3D v249 OBJ File: untitled.blend
# www.blender3d.org
mtllib cube.mtl
v 1.000000 -1.000000 -1.000000
v 1.000000 -1.000000 1.000000
v -1.000000 -1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v 1.000000 1.000000 -1.000000
v 0.999999 1.000000 1.000001
v -1.000000 1.000000 1.000000
v -1.000000 1.000000 -1.000000
vt 0.748573 0.750412
vt 0.749279 0.501284
vt 0.999110 0.501077
vt 0.999455 0.750380
vt 0.250471 0.500702
vt 0.249682 0.749677
vt 0.001085 0.750380
vt 0.001517 0.499994
vt 0.499422 0.500239
vt 0.500149 0.750166
vt 0.748355 0.998230
vt 0.500193 0.998728
vt 0.498993 0.250415
vt 0.748953 0.250920
vn 0.000000 0.000000 -1.000000
vn -1.000000 -0.000000 -0.000000
vn -0.000000 -0.000000 1.000000
vn -0.000001 0.000000 1.000000
vn 1.000000 -0.000000 0.000000
vn 1.000000 0.000000 0.000001
vn 0.000000 1.000000 -0.000000
vn -0.000000 -1.000000 0.000000
usemtl Material_ray.png
s off
f 5/1/1 1/2/1 4/3/1
f 5/1/1 4/3/1 8/4/1
f 3/5/2 7/6/2 8/7/2
f 3/5/2 8/7/2 4/8/2
f 2/9/3 6/10/3 3/5/3
f 6/10/4 7/6/4 3/5/4
f 1/2/5 5/1/5 2/9/5
f 5/1/6 6/10/6 2/9/6
f 5/1/7 8/11/7 6/10/7
f 8/11/7 7/12/7 6/10/7
f 1/2/8 2/9/8 3/13/8
f 1/2/8 3/13/8 4/14/8

我知道为什么我们可以拥有比顶点更多的纹理坐标,我只是不知道如何处理它们,尤其是在使用OpenGL渲染时(我这样做)。当我解析obj时,我的索引缓冲区看起来像这样:

4 0 3
4 3 7
2 6 7
2 7 3
1 5 2
5 6 2
0 4 1
4 5 1
4 7 5
7 6 5
0 1 2
0 2 3

请注意,我从所有索引中减去1,因为OpenGL以这种方式想要它们。对象绘制正常,但顶点数据当然是错误的。我顺便将顶点数据存储在专用的VBO中。因此总的来说,我的VAO有2个VBO(顶点,纹理)和一个EBO存储信息,哪些椎体形成三角形。现在如何处理纹理坐标?

建议后编辑:

所以我解压缩顶点(这意味着我总共有36个顶点)并且在一个连续的数组中包含顶点,纹理和法线数据。结果如下: enter image description here

我的VBO看起来像这样:

1.000000 1.000000 -1.000000 0.748573 0.750412 0.000000 0.000000 -1.000000
1.000000 -1.000000 -1.000000 0.749279 0.501284 0.000000 0.000000 -1.000000
-1.000000 -1.000000 -1.000000 0.999110 0.501077 0.000000 0.000000 -1.000000
1.000000 1.000000 -1.000000 0.748573 0.750412 0.000000 0.000000 -1.000000
-1.000000 -1.000000 -1.000000 0.999110 0.501077 0.000000 0.000000 -1.000000
-1.000000 1.000000 -1.000000 0.999455 0.750380 0.000000 0.000000 -1.000000

依旧...... 一行恰好是一个顶点:顶点pos,纹理坐标,法线向量。

所以三行代表一个三角形。

我按照这样的属性指针进行设置:

    glBufferData(GL_ARRAY_BUFFER, sizeof(float) * objModel2.getObjData().size(), &objModel2.getObjData()[0], GL_STATIC_DRAW);
// vertex positions
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), 0);
glEnableVertexAttribArray(0);
// texture positions
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(sizeof(GLfloat) * 3));
glEnableVertexAttribArray(1);
// normals positions
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(sizeof(GLfloat) * 5));
glEnableVertexAttribArray(2);

最后像这样绘制立方体:

    glBindVertexArray(VAO_cube_model_2);
    glDrawArrays(GL_TRIANGLES, 0, objModel2.getObjData().size() / 8);
    glBindVertexArray(0);

纹理文件是以下png文件: enter image description here

只有3和5被绘制。我无法弄清楚为什么......

2 个答案:

答案 0 :(得分:2)

OpenGL使用与obj格式不同的索引模式。在obj中,每个属性(位置,颜色,纹理坐标)都可以有自己的索引,而在OpenGL中只有一个索引可能。为了正确加载obj,您必须复制一些数据并找到新的索引。

最简单的方法是在没有任何重复检查的情况下工作。在这种情况下,您只需复制每个顶点的数据。这个过程看起来像这样:

load all v lines into v[]
load all vt lines into vt[]
load all vn lines into vn[]

float[] verts;
int[] idx;

foreach f line consisting of (vi[0]/vti[0]/vni[0] vi[1]/vti[1]/vni[1] vi[2]/vti[2]/vni[2])
    for i = 1:3
        verts.append(v[vi[i]], vt[vti[i]], vn[vni[i]]);
        idx.append(verts.size() - 1);

在这种情况下,您甚至可以放弃索引缓冲区。人们可能会注意到,这不是一种最佳方式,因为保存了大量重复数据。一个优化是识别是否已经将vi,vti,vni的组合添加到顶点列表中,并且如果已经是这种情况则只添加正确的索引。

答案 1 :(得分:0)

底部的线条:

f 5/1/1 1/2/1 4/3/1

告诉您如何组合顶点,纹理坐标和法线以创建对象。

他们是1个索引。

他们是"面对"元素并在本文档中描述:

http://www.martinreddy.net/gfx/3d/OBJ.spec