解析波前 obj 文件格式

Posted

技术标签:

【中文标题】解析波前 obj 文件格式【英文标题】:parsing the wavefront obj file format 【发布时间】:2012-12-18 10:49:10 【问题描述】:

我想将 obj 模型导入我的 opengl 程序。我有一个类/数据格式,用于将属性数据传递到着色器:

class CustomVertex : public IVtxFmt

public:
  float m_Position[3];      // x, y, z      offset 0, size = 3*sizeof(float)    
  float m_Normal[3];        // nx, ny, nz;  offset 3
  float m_TexCoords[2];     // u, v         offset 6
  float m_Colour[4];        // r, g, b, a   offset 8
  float m_Tangent[3];       // r, g, b      offset 12
  float m_Bitangent[3];     // r, g, b      offset 15
;

所以我正在使用从 Internet 下载的小木屋模型。

小木屋有几个顶点、法线和纹理坐标定义,后面是面定义列表。

所以我的第一反应是解析 obj 文件并最终得到 ​​p>

vector<vertex>
vector<Normal>
vector<TexCoord>

转换成我的 CustomVertex 格式并不简单,因为文件中可能定义了 210 个顶点、100 个 tex 坐标和 80 个法线。

在以这种格式列出约 390 个面孔之后:

f 83/42/1 67/46/1 210/42/1 

我在文件中遇到以下内容:

#
# object tile00
#

随后是更多的顶点定义。

由此,我推断出一个模型可能由多个子对象组成,每个子对象由多个面定义;每个面由 3 x vertex / normal / texcoord 索引值定义。

所以为了得到一个 CustomVertex 的向量,我想我需要做以下事情:

创建和填充:

vector <vertex>
vector <normal>
vector <texcoord>

vector <indices>

我需要为面部定义中每个唯一的 v/vn/vt 三元组创建一个 CustomVertex。

所以我想到了创建地图:

std::vector<CustomVertex> and
std::map< nHashId, CustomVertex_index >

所以我的想法是,对于我遇到的每个 v/vn/vt,我创建这个字符串的哈希,例如nHashId = hash("80/50/1")* 并在地图中搜索哈希。如果不存在,我创建一个 CustomVertex 并将其添加到向量中,然后将新创建的哈希和 CustomVertex_index 添加到地图中。

*: 通过创建 v/vn/vt 字符串的哈希值,我创建了一个与该字符串对应的唯一数值,我希望在地图中搜索/比较它比等效文本。

如果我遇到哈希匹配,我认为 customvertex 已经存在,而不是创建新的 CustomVertex,我只是将 CustomVertex_index 条目添加到索引向量中并继续。

由于这似乎是一项计算成本很高的练习,我想我会将我的 CustomVertex 数组(和相应的索引数组)转储到磁盘以供以后检索,而不是每次都解析 obj 文件。

在我提出问题之前,我是否可以指出,由于时间限制并且不想重新设计我的 Vbo 类(一项不平凡的任务),我坚持使用 CustomVertex 格式 - 我知道它可能为我的着色器提供单独数组中的属性,但我读过像使用 CustomVertex 一样交错数据可以提高性能。

所以对于我的问题: 1. 我的方法看起来是正确的还是疯狂的?如果疯了,请指出我哪里出错了。

    您能发现任何潜在问题吗?

    以前有没有人这样做过,并且可以推荐一种更简单的方法来实现我的目标?

【问题讨论】:

如果你可以散列一些东西,为什么不直接使用unordered_map?否则你的方法看起来不错,而且不会过于复杂。 通过创建 v/vn/vt 字符串的哈希值,我正在创建一个与该字符串相对应的唯一数值,我希望在地图中搜索/比较它比等效文本。 @lapin:这就是所谓的“过早优化”。只需比较索引(作为数字,而不是文本)。如果您的分析显示它很慢,那么请解决它。 鉴于数据以字符串格式开头,并且需要比较所有 3 个索引,我实际上不确定使用字符串作为映射键是不是一个坏主意。虽然如果你真的想创建一个整数哈希,我会从索引而不是字符串创建 that 。不过,我同意上述评论,即您应该从任何可行的幼稚版本开始,并在必要时进行优化。 【参考方案1】:

你能发现任何潜在的问题吗?

你的意思是除了哈希冲突?因为我没有看到您的算法中处理该问题的部分。

以前有没有人这样做过,并且可以推荐一种更简单的方法来实现我的目标?

有一个更简单的方法:只比较索引而不使用哈希。

【讨论】:

【参考方案2】:

不是创建“v/vn/vt”的字符串散列,而是仅将 v 散列为整数。之后,您将获得一个包含共享相同 v 索引的所有“v/vn/vt”组合的存储桶。

如果发生哈希冲突(遇到相同的 v),您会将冲突的组合与桶中的组合进行比较,以查看它是否真的重复。如果没有,记得将碰撞的组合添加到桶中。

【讨论】:

以上是关于解析波前 obj 文件格式的主要内容,如果未能解决你的问题,请参考以下文章

如何在 3D 中对导入的波前 OBJ 文件实现对象碰撞

波前 OBJ 文件可以具有每个对象(或每个组)的顶点吗?

windows obj文件格式解析

obj是啥格式的文件

js怎么解析geojson 格式的

如何在搅拌机中打开 .obj 文件? [关闭]