解析波前 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 文件格式的主要内容,如果未能解决你的问题,请参考以下文章