为什么我的 OBJ 解析器渲染网格是这样的? [英] Why is my OBJ parser rendering meshes like this?

查看:17
本文介绍了为什么我的 OBJ 解析器渲染网格是这样的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我自己负责将 OBJ 解析器/导入器支持添加到我一直在开发的 3D 渲染引擎中.我遵循了规范 found HERE当前的例外是将所有支持限制为组、面、顶点、法线和纹理坐标(因此目前还没有材质库或自由形式的多边形支持).我的目标是简单地逐行解析——随着我的进行生成面向对象的、分层的树状场景图——并允许开发人员通过很少的手动调用自动将数据绑定到着色器程序,以便开始操纵 &查看网格.最终结果是我的引擎成功解析了大多数(如果不是所有)有效的 OBJ 格式文件,提取适当的数据并将其发送到基本着色器进行渲染.然而,即使数据似乎在场景图中正确表示,但由于某种原因,它很少能正确渲染......

I've taken it upon myself to add OBJ parser/importer support to a 3D rendering engine I've been working on. I've followed the specification found HERE nearly 'to a tee', with the current exception of limiting all support to groups, faces, vertices, normals and texture coordinates (so no material library or free-form poly support, as of yet). My goal was to simply parse line by line -- generating an object-oriented, hierarchical tree-like scene graph as I went along -- and allow the developer to automatically bind the data to a shader program with very few manual calls in order to start manipulating & viewing the mesh. The end result is that my engine does successfully parse most (if not all) valid OBJ format files, extracting the appropriate data and sending it to a basic shader for rendering. However, even though the data appears to be represented correctly in the scene graph, for some reason or another it rarely renders properly...

请注意,一个简单的平面(从 3DS Max 导出,仅包含 4 个顶点和 2 个面)渲染得非常好,但立方体或任何更高级的东西通常最终看起来像这样:

Take note that a simple plane (exported from 3DS Max, containing only 4 vertices and 2 faces) renders perfectly fine, but a cube or anything more advanced usually ends up looking something like this:

http://youtu.be/1x6bnuhAXWY

我不知道哪里出了问题,AFAIK 我的代码实际上应该可以很好地解析和渲染基本几何体......那为什么不呢?为方便起见,我上传了我的项目在这里.它包含一个 NetBeans 项目,其中包含我的引擎的最小版本和一个测试应用程序.我还包含了 3 个不同版本的 OBJ 立方体网格和一个单平面网格.该应用程序可通过编辑Test.java 顶部的值进行配置,唯一的输入控件是A、S、W 和&D 用于网格平移,鼠标移动用于网格旋转.尽管我已经设法对项目进行了大量浏览,但最引人注目的类在文件顶部包含了额外的注释/信息.

I can't tell where things are going wrong, and AFAIK my code should actually be parsing and rendering basic geometry just fine... So why isn't it? For convenience, I have uploaded my project HERE. It contains a NetBeans project with a minimal version of my engine, and one Test application. I have also included 3 different versions of an OBJ cube mesh, and a single plane mesh. The application is configurable by editing the values at the top of Test.java, and the only input controls are A, S, W, & D for mesh translation, and mouse movement for mesh rotation. And although I've managed to skim the project down considerably, the most notable classes include extra comments/info at the top of the file.

考虑到所有因素,我会考虑我能想到的任何想法......而且它肯定不会被忽视!

All things considered, I'll take whatever thoughts I can get... and it certainly won't go unappreciated!

推荐答案

我还没有下载你的项目.在编写 OBJ 导入代码以使用 OpenGL 进行渲染时,人们最关心的是索引.正如@ratched_freak 在他的评论中也怀疑的那样,这与您的立方体的视觉外观非常一致.

I haven't downloaded your project. What people mostly struggle with when writing OBJ import code for rendering with OpenGL is the indices. And as @ratched_freak also suspects in his comment, that's very consistent with the visual appearance of your cube.

OBJ 格式对位置、法线和纹理坐标使用单独的索引.对于 OpenGL 渲染,您需要一组索引.这意味着您需要为 OBJ 文件中三角形使用的位置/法线/纹理索引的每个唯一组合生成一个顶点,为该组合分配一个新索引,然后在您的 OpenGL 索引缓冲区中使用该索引.

The OBJ format uses separate indices for positions, normals, and texture coordinates. For OpenGL rendering, you need a single set of indices. This means that you need to generate a vertex for each unique combination of position/normal/texture indices used by triangles in the OBJ file, assign a new index to the combination, and then use that index in your OpenGL index buffer.

我用伪代码写了一个答案,概述了最近如何针对类似问题执行此操作:OpenGL - 索引缓冲区困难.

I wrote an answer with pseudo-code that outlines how to do this for a similar question recently: OpenGL - Index buffers difficulties.

编辑,以进一步说明问题.这是我在网上找到的一个立方体"文件:

Edit, to illustrate the problem some more. Here is a "cube" file I found online:

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 

该文件有 8 个位置(v 记录)和 6 个正常位置(vn 记录).f 记录是面,在这种情况下是三角形.查看第一个三角形顶点,1//2 告诉您该顶点使用位置 1 和法线 2.使用 OpenGL 索引数组时,您不能为位置和法线设置单独的索引.所以我们为这个位置/法线对创建一个顶点,并为其分配第一个可用索引.7//25//2 相同,所以我们现在有 3 个 OpenGL 顶点(索引 0、1 和 2).

The file has 8 positions (v records) and 6 normal (vn records). The f records are faces, triangles in this case. Looking at the first triangle vertex, 1//2 tells you that the vertex uses position 1 and normal 2. When using OpenGL index arrays, you can't have separate indices for positions and normals. So we create a vertex for this position/normal pair, and assign it the first available index. Same for 7//2 and 5//2, so we now have 3 OpenGL vertices (indices 0, 1, and 2).

现在在第二个三角形上,我们再次找到 1//2.我们已经为这个组合创建了一个顶点,所以我们可以再次使用我们的顶点 0.3//2 是新的,所以我们为它创建一个新的顶点(索引 3).7//2我们之前看到的,和我们的顶点1一样.

Now on the second triangle, we find 1//2 again. We already created a vertex for this combination, so we can use our vertex 0 again. 3//2 is new, so we create a new vertex (index 3) for it. 7//2 we saw previously, it's the same as our vertex 1.

所以我们最终得到了第一个 2 个三角形的 4 个 OpenGL 顶点.这是有道理的,因为两个三角形描述了立方体的一个面,而我们需要 4 个顶点来表示一个正方形.

So we ended up with 4 OpenGL vertices for the fist 2 triangles. Which makes sense, since the two triangles describe one face of the cube, and we need 4 vertices for a square.

如果您在整个示例中继续此过程,您将最终得到 24 个顶点,您可以将其存储在 OpenGL 顶点缓冲区中,以及一个包含 36 个条目的索引缓冲区(12 个三角形,每个三角形有 3 个角).

If you continue this process for the whole example, you will end up with 24 vertices you can store in an OpenGL vertex buffer, and an index buffer with 36 entries (12 triangles with 3 corners each).

这篇关于为什么我的 OBJ 解析器渲染网格是这样的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆