在尝试解析wavefront .obj文件时,我想到了两种方法:
IMO,选项1将非常耗费内存,但要快得多。 由于选项2涉及大量文件读取(并且因为大多数对象中的顶点数量变得非常大),因此速度会慢得多,但记忆密集程度会降低。
问题是:比较内存和速度之间的权衡,哪个选项更适合普通计算机? 而且,还有另一种方法吗?
我打算使用OpenGL和GLFW来渲染对象。
答案 0 :(得分:5)
IMO,选项1将非常耗费内存,但速度要快得多。
无论如何,你必须将这些顶点放入内存中。但是不需要2D阵列,BTW会导致两个指针间接,因此会受到重大影响。只需对数据使用简单的std::vector<Vertex>
,向量索引就是随附的面部列表的索引。
由于评论而编辑
class Vertex
{
union { struct { float x, y, z }; float pos[3] };
union { struct { float nx, ny, nz }; float normal[3] };
union { struct { float s, t }; float pos[2] };
Vertex &operator=();
}
std::vector<Vertex>;
答案 1 :(得分:4)
通常,您将顶点列表读入数组。解析ASCII文本非常慢;在加载文件时只执行一次,然后将所有内容存储在内存中。
与三角形/面相同。每个三角形通常由三个顶点索引的列表组成。那也应该存储在一个数组中。
您可能会发现VTK开源库中的OBJ阅读器非常有用:http://www.vtk.org/doc/nightly/html/classvtkOBJReader.html。我们使用它并且没有理由自己编写...直接使用VTK,或者您可能会发现学习源代码有助于进一步激发您自己读者的灵感。
在我看来,OBJ文件的一个主要缺点是使用ASCII。由于字符串解析,如果它们是ASCII,则3D ASCII文件(无论是STL,PLY,OBJ等)加载速度非常慢。二进制格式文件要快得多,如果性能有问题,应始终使用它们:好的二进制格式的加载时间是即时的。
答案 2 :(得分:2)
只需将它们加载到数组中即可。记忆不应成为问题。您的系统(通常)拥有比GPU更多的内存。如果遇到内存问题,您可能正在加载一个过于详细的模型。 (我假设您打算在OpenGL中制作游戏。如果您对这种大型模型文件有特殊需求,您仍然需要设法加载适当的块。)
答案 3 :(得分:0)
您不应该需要二维数组。您的模型应该是三角形的,然后您可以使用gluts obj loader简单地加载obj文件。只需将点,面和法线存储在3个单独的数组/缓冲区中。有一个例子,你可以做到here,但如果你想快速做,你应该采用二进制格式。
答案 4 :(得分:0)
这是一个相当不错的原型解决方案,运行一个脚本,生成用于OpenGL或首选渲染API的数组。 obj2opengl.pl是一个perl脚本,你需要安装perl才能找到here。 GitHub链接是here。
在运行perl脚本时,您可能会在第154行遇到有关if(defined(@center))
的运行时错误。将其替换为if(@center)
。
从示例中,一旦使用数据生成头文件,您可以使用它,如下所示:
/*
created with obj2opengl.pl
source file : ./banana.obj
vertices : 4032
faces : 8056
normals : 4032
texture coords : 4420
// include generated arrays
#import "./banana.h"
// set input data to arrays
glVertexPointer(3, GL_FLOAT, 0, bananaVerts);
glNormalPointer(GL_FLOAT, 0, bananaNormals);
glTexCoordPointer(2, GL_FLOAT, 0, bananaTexCoords);
// draw data
glDrawArrays(GL_TRIANGLES, 0, bananaNumVerts);
*/