gpt4 book ai didi

c++ - 带有 OpenGL 的 OBJ 文件解析器

转载 作者:行者123 更新时间:2023-11-28 01:59:18 27 4
gpt4 key购买 nike

我正在编写一个简单的 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

等等...一行恰好是一个顶点:顶点位置、纹理坐标、法 vector 。

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

我通过这样的属性指针设置:

    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 被绘制。我想不通为什么...

最佳答案

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 的组合是否已经添加到顶点列表中,如果已经是这种情况,则只添加正确的索引。

关于c++ - 带有 OpenGL 的 OBJ 文件解析器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40107359/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com