读写网格到文件
本部分介绍了如何从文件中读取网格,及如何将网格写出到文件。
相应的函数接口定义在OpenMesh::MeshIO命名空间中。这部分主要分为三部分,第一部分给定了个例子说明如何使用OpenMesh IOManager,第二部分给出IOManager工作原理,最后一部分说明如何向IOManager添加自己的模块。
第一部分:快速使用IOManager
您可以将以下代码复制到自己的项目中,快速使用IOManager。
注意:
- 如果您链接了OpenMesh静态库,需要在您的应用中添加OM_STATIC_BUILD宏定义,这能够保证正确初始化读写接口。
- IOManager使用文件扩展名来选择相应的读写接口。例如,如果使用文件参数名为“inputmesh.obj”,则会调用OBJ-File读写接口。
代码如下:
#include <OpenMesh/Core/IO/MeshIO.hh>
MyMesh mesh;
if (!OpenMesh::IO::read_mesh(mesh, "some input file"))
{
std::cerr << "read error\n";
exit(1);
}
// do something with your mesh ...
if (!OpenMesh::IO::write_mesh(mesh, "some output file"))
{
std::cerr << "write error\n";
exit(1);
}
第二部分:IOManager工作原理
通常来说,读写器只支持固定的数据结构与文件格式。这种方法的主要缺点是使用其他类型的数据结构或者文件格式,会导致代码重复。
IOManager读写模块和导入/导出模块,工作形式类似于一种接口,用来实现任意数据结构与固定数据结构的交互。如下图所示:
任意格式的数据可以通过数据读入模块进行解释。然后,数据通过指定的接口导入目标数据结构,写出的过程与此类似。
IOManager控制整个流程。读写模块不支持用户访问,但是,对于特定的数据结构,对于导入/导出器需要显式指明。
固定数据格式与任意数据格式的分离能够轻易地实现现有代码的维护以及功能拓展,如下面第三部分所示。
也可以查看以下代码:
OpenMesh::IO::IOManager
第三部分:如何扩展IOManager
a.添加对新文件格式的支持
支持新文件格式需要添加读写模块。读模块是OpenMesh::IO::BaseReader派生的类。需要定义的接口部分如下所示:
class BaseReader
{
public:
virtual std::string get_description() const = 0;
virtual std::string get_extensions() const = 0;
virtual std::string get_magic() const { return std::string(""); }
virtual bool read(std::istream& _is, BaseImporter& _bi) const = 0;
virtual bool read(const std::string& _filename, BaseImporter& _bi) const = 0;
...
};
通过文件扩展名来确定使用哪个读模块,然后通过OpenMesh::IO::BaseImporter中派生的方法来解析文件格式与数据信息。
写模块工作原理与读模块类似,派生于OpenMesh::IO::BaseWriter。
b.添加对新数据结构的支持
正如前所述,导入器通过读模块获取数据。读模块通过特定的接口传递信息,如下所示:
class BaseImporter
{
public:
virtual void add_vertex (const OpenMesh::Vec3f&) {};
virtual void add_normal (const OpenMesh::Vec3f&) {};
virtual void add_texture (const OpenMesh::Vec2f&) {};
virtual void add_face (const FaceType&) {};
};
导入器负责填充目标数据结构。从数据结构中导出数据比导入数据稍显复杂,写出器需要遍历所有的向量/纹理/面。因此,
导出器需要包含三个迭代器:
class BaseExporter
{
public:
virtual void update() = 0;
virtual PVertexIter const_vertices_begin() = 0;
virtual PVertexIter const_vertices_end() = 0;
virtual PTexCoordIter const_texcoords_begin() = 0;
virtual PTexCoordIter const_texcoords_end() = 0;
virtual PIdxFaceIter const_idx_faces_begin() = 0;
virtual PIdxFaceIter const_idx_faces_end() = 0;
virtual PFaceIter const_set_faces_begin() = 0;
virtual PFaceIter const_set_faces_end() = 0;
virtual unsigned int n_faces() = 0;
virtual unsigned int n_vertices() = 0;
virtual unsigned int n_texcoords() = 0;
};
可能需要导出器临时缓存引用数据,每个BaseWriter::save()前需要添加update(),用来确保缓存的信息是最新的。
有关详细信息,建议您查看OpenMesh提供的模块,这些模块可以在IO子目录中找到。
译者说明:因科研需要,避免重复造轮子,近来借用OpenMesh,因其结构封装严谨,灵活可靠,且十分方便,故抽出时间对官网的说明做点翻译。英文水平不高,如翻译有误请多多包涵,也请您多多指正。
上一篇:OpenMesh译稿:使用并理解OpenMesh-网格的导航
英文原文地址:http://www.openmesh.org/Documentation/OpenMesh-Doc-Latest/index.html
---------------------
作者:feengg
来源:优快云
原文:https://blog.youkuaiyun.com/feengg/article/details/86539590
版权声明:本文为博主原创文章,转载请附上博文链接!