#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 acts as an interface between persistent data on one side and an arbitrary data structure on the other side by means of reader/writer and importer/exporter modules. This is illustrated by the following diagramm :
Persistent data of arbitrary format is first interpreted by a reader module. The data is then passed - by means of a specified interface - to an importer module for the target data structure. The process for writing data is analogous. The IOManager controls the entire process. Reader/Writer modules are invisible to the user. Importer/Exporter however have to be specified explicitely as they are specific to a data structure.
The complete separation of data structure and persistent data makes it especially easy to maintain existing code and to extend funtionality at both ends as will be shown in step three.
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; ... };
Based on the file extension or the header information the IOManager decides which reader module to use. The reader then parses the format and the information will be passed to the target data structure be means of a class derived from OpenMesh::IO::BaseImporter.
Writer modules are derived from OpenMesh::IO::BaseWriter and work the same way as reader modules.
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&) {}; };
The Importer is then responsible for filling the target data structure. Exporting information from a data structure is a little bit more involved than importing data to it. The writer modules must be able to iterate over all vectors/texcoords/faces. Therefore an exporter has to provide these iterators :
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; };
There might be the need for the exporter to cache data from the structure it refers to. The update() function should be called at the beginning of each BaseWriter::save() method and it should make sure that cached information is up to date.
For further information you are encouraged to take a look at the modules provided by OpenMesh which can be found in the IO subdirectory.