C++ OpenGL-纹理使用GLDraweElements映射不正确

C++ OpenGL-纹理使用GLDraweElements映射不正确,c++,opengl,textures,wavefront,C++,Opengl,Textures,Wavefront,我正在创建一个OBJ解析器,它读取文件并使用gldrawerelements绘制它。这里的问题是模型是正确绘制的,但是当我尝试给它一个纹理时,它被错误地映射了。我读到“OpenGL只能使用一个索引缓冲区,而OBJ按属性使用一个索引缓冲区”。我还研究了使用GLDrawerElements时纹理映射错误的问题,发现我需要重新排列纹理,因为只有顶点是共享的,而没有纹理。说到这里,我该如何重新排列纹理呢?我应该复制一些纹理吗?我得到的示例输出请参考这里。我对OBJ不太熟悉,但您说的是,OBJ可以通过每个

我正在创建一个OBJ解析器,它读取文件并使用gldrawerelements绘制它。这里的问题是模型是正确绘制的,但是当我尝试给它一个纹理时,它被错误地映射了。我读到“OpenGL只能使用一个索引缓冲区,而OBJ按属性使用一个索引缓冲区”。我还研究了使用GLDrawerElements时纹理映射错误的问题,发现我需要重新排列纹理,因为只有顶点是共享的,而没有纹理。说到这里,我该如何重新排列纹理呢?我应该复制一些纹理吗?我得到的示例输出请参考这里。

我对OBJ不太熟悉,但您说的是,OBJ可以通过每个顶点的索引引用不同的属性。你有一个大的xyz阵列,另一个大的uv阵列。然后每个顶点在xyz数组中有一个索引,在uv数组中有另一个索引。但是opengl每个顶点只有一个索引!因此,如果xyz和uv索引不同,opengl将无法工作。解决此问题的一个简单方法是循环遍历所有顶点,如果它们的uv索引与xyz索引不同,只需将两者的数据复制到缓冲区的末尾并将索引设置为该值。

OBJ格式指定唯一的纹理坐标、顶点和面

当然,Opengl与OBJ无关,所以它所需要的只是在正确的位置提供正确的信息

想象在OBJ中有两个这样的面(注意两个面中的顶点1 texcoords)

您的索引缓冲区如下所示:

1 2 3     1 4 5
v1 v2 v3 v4 v5
f:    v1 |t1|      v2 t2      v3 t3 
f:    v1 |t1|      v4 t4      v5 t5 
v1 |t1|      v2 t2       v3 t3       v1 |t2|       v4 t4        v5 t5
opengl顶点缓冲区首先如下所示:

1 2 3     1 4 5
v1 v2 v3 v4 v5
f:    v1 |t1|      v2 t2      v3 t3 
f:    v1 |t1|      v4 t4      v5 t5 
v1 |t1|      v2 t2       v3 t3       v1 |t2|       v4 t4        v5 t5
如果添加纹理坐标,则在何处添加它们?像这样

v1 t1     v2 t2     v3 t3     v4 t4      v5 t5
这很可能是您现在所拥有的,这是错误的,因为opengl使面如下所示:

1 2 3     1 4 5
v1 v2 v3 v4 v5
f:    v1 |t1|      v2 t2      v3 t3 
f:    v1 |t1|      v4 t4      v5 t5 
v1 |t1|      v2 t2       v3 t3       v1 |t2|       v4 t4        v5 t5
由于v1和t1通过indexbuffer链接在一起,请注意OBJ和OpenGL中顶点之间的差异

有几种方法可以解决这个问题。我建议去掉indexbuffer,因为它只会使一切复杂化。如果没有索引缓冲区,只需提供所有面,就好像它们是唯一的一样,并使用不同的绘制调用(glDrawArrays)。顶点缓冲区将如下所示:

1 2 3     1 4 5
v1 v2 v3 v4 v5
f:    v1 |t1|      v2 t2      v3 t3 
f:    v1 |t1|      v4 t4      v5 t5 
v1 |t1|      v2 t2       v3 t3       v1 |t2|       v4 t4        v5 t5
您复制了v1,但实际上大部分时间都没有那么多额外的数据,因为您不再需要指定索引缓冲区


这种事情真的很烦人,我尽了最大努力让它变得平易近人,我希望我没有犯任何错误

感谢您的回复,很抱歉回复太晚。这对我来说真的很有帮助,现在我明白了。之所以使用索引缓冲区,是因为我打算使用GL_TRIANGLE_STRIP,但我无法使它在gldrawArray中工作。我会记住这一点,因为我真的想让它在glDrawElements中工作。我只是好奇,我真的应该把它们都复制到缓冲区的末尾,还是只复制纹理?