56 #include <OpenMesh/Core/Utils/Endian.hh> 57 #include <OpenMesh/Core/IO/OMFormat.hh> 58 #include <OpenMesh/Core/IO/reader/OMReader.hh> 59 #include <OpenMesh/Core/IO/writer/OMWriter.hh> 81 _OMReader_::_OMReader_()
100 std::ifstream ifs(_filename.c_str(), std::ios::binary);
106 ifs.unsetf(std::ios::skipws);
108 if (!ifs.is_open() || !ifs.good()) {
109 omerr() <<
"[OMReader] : cannot not open file " << _filename << std::endl;
114 bool result =
read(ifs, _bi, _opt);
119 _opt = _opt & fileOptions_;
137 omerr() <<
"[OMReader] : cannot read from stream " << std::endl;
142 bool result = read_binary(_is, _bi, _opt);
147 _opt = _opt & fileOptions_;
172 bytes_ += restore(_is, header_, swap);
175 if (header_.version_ > _OMWriter_::get_version())
177 omerr() <<
"File uses .om version " << OMFormat::as_string(header_.version_) <<
" but reader only " 178 <<
"supports up to version " << OMFormat::as_string(_OMWriter_::get_version()) <<
".\n" 179 <<
"Please update your OpenMesh." << std::endl;
185 bytes_ += restore(_is, chunk_header_, swap);
191 if (chunk_header_.name_) {
192 OMFormat::Chunk::PropertyName pn;
193 bytes_ += restore(_is, property_name_, swap);
198 switch (chunk_header_.entity_) {
199 case OMFormat::Chunk::Entity_Vertex:
200 if (!read_binary_vertex_chunk(_is, _bi, _opt, swap))
203 case OMFormat::Chunk::Entity_Face:
204 if (!read_binary_face_chunk(_is, _bi, _opt, swap))
207 case OMFormat::Chunk::Entity_Edge:
208 if (!read_binary_edge_chunk(_is, _bi, _opt, swap))
211 case OMFormat::Chunk::Entity_Halfedge:
212 if (!read_binary_halfedge_chunk(_is, _bi, _opt, swap))
215 case OMFormat::Chunk::Entity_Mesh:
216 if (!read_binary_mesh_chunk(_is, _bi, _opt, swap))
219 case OMFormat::Chunk::Entity_Sentinel:
239 std::ifstream ifile(_filename.c_str());
250 std::vector<char> evt;
254 while (evt.size() < 4)
255 evt.push_back(static_cast<char>(_is.get()));
258 std::vector<char>::reverse_iterator it = evt.rbegin();
259 while (it != evt.rend())
263 OMFormat::Header *hdr = (OMFormat::Header*) &evt[0];
266 if (hdr->magic_[0] !=
'O' || hdr->magic_[1] !=
'M')
270 switch (hdr->mesh_) {
280 return supports(hdr->version_);
285 bool _OMReader_::supports(
const OMFormat::uint8 )
const 293 bool _OMReader_::read_binary_vertex_chunk(std::istream &_is,
BaseImporter &_bi,
Options &_opt,
bool _swap)
const 295 using OMFormat::Chunk;
297 assert( chunk_header_.entity_ == Chunk::Entity_Vertex);
304 OMFormat::Chunk::PropertyName custom_prop;
307 switch (chunk_header_.type_) {
308 case Chunk::Type_Pos:
311 for (; vidx < header_.n_vertices_ && !_is.eof(); ++vidx) {
312 bytes_ += vector_restore(_is, v3f, _swap);
317 case Chunk::Type_Normal:
321 for (; vidx < header_.n_vertices_ && !_is.eof(); ++vidx) {
322 bytes_ += vector_restore(_is, v3f, _swap);
323 if (fileOptions_.vertex_has_normal() && _opt.vertex_has_normal())
328 case Chunk::Type_Texcoord:
332 for (; vidx < header_.n_vertices_ && !_is.eof(); ++vidx) {
333 bytes_ += vector_restore(_is, v2f, _swap);
334 if (fileOptions_.vertex_has_texcoord() && _opt.vertex_has_texcoord())
339 case Chunk::Type_Color:
341 assert( OMFormat::dimensions(chunk_header_) == 3);
345 for (; vidx < header_.n_vertices_ && !_is.eof(); ++vidx) {
346 bytes_ += vector_restore(_is, v3uc, _swap);
347 if (fileOptions_.vertex_has_color() && _opt.vertex_has_color())
352 case Chunk::Type_Status:
354 assert( OMFormat::dimensions(chunk_header_) == 1);
358 for (; vidx < header_.n_vertices_ && !_is.eof(); ++vidx) {
359 bytes_ += restore(_is, status, _swap);
360 if (fileOptions_.vertex_has_status() && _opt.vertex_has_status())
366 case Chunk::Type_Custom:
368 bytes_ += restore_binary_custom_data(_is, _bi.kernel()->_get_vprop(property_name_), header_.n_vertices_, _swap);
370 vidx = header_.n_vertices_;
374 case Chunk::Type_Topology:
376 for (; vidx < header_.n_vertices_; ++vidx)
379 bytes_ += restore( _is, halfedge_id, OMFormat::Chunk::Integer_Size(chunk_header_.bits_), _swap );
389 omerr() <<
"Unknown chunk type ignored!\n";
390 size_t chunk_size = header_.n_vertices_ * OMFormat::vector_size(chunk_header_);
391 _is.ignore(chunk_size);
392 bytes_ += chunk_size;
399 return vidx == header_.n_vertices_;
405 bool _OMReader_::read_binary_face_chunk(std::istream &_is,
BaseImporter &_bi,
Options &_opt,
bool _swap)
const 407 using OMFormat::Chunk;
409 assert( chunk_header_.entity_ == Chunk::Entity_Face);
416 switch (chunk_header_.type_) {
417 case Chunk::Type_Topology:
419 if (header_.version_ < OMFormat::mk_version(2,0))
422 BaseImporter::VHandles vhandles;
426 switch (header_.mesh_) {
435 for (; fidx < header_.n_faces_; ++fidx) {
436 if (header_.mesh_ ==
'P')
437 bytes_ += restore(_is, nV, Chunk::Integer_16, _swap);
440 for (
size_t j = 0; j < nV; ++j) {
441 bytes_ += restore(_is, vidx, Chunk::Integer_Size(chunk_header_.bits_), _swap);
446 _bi.add_face(vhandles);
452 for (; fidx < header_.n_faces_; ++fidx)
455 bytes_ += restore( _is, halfedge_id, OMFormat::Chunk::Integer_Size(chunk_header_.bits_), _swap );
463 case Chunk::Type_Normal:
467 for (; fidx < header_.n_faces_ && !_is.eof(); ++fidx) {
468 bytes_ += vector_restore(_is, v3f, _swap);
469 if( fileOptions_.face_has_normal() && _opt.face_has_normal())
474 case Chunk::Type_Color:
476 assert( OMFormat::dimensions(chunk_header_) == 3);
479 for (; fidx < header_.n_faces_ && !_is.eof(); ++fidx) {
480 bytes_ += vector_restore(_is, v3uc, _swap);
481 if( fileOptions_.face_has_color() && _opt.face_has_color())
485 case Chunk::Type_Status:
487 assert( OMFormat::dimensions(chunk_header_) == 1);
491 for (; fidx < header_.n_faces_ && !_is.eof(); ++fidx) {
492 bytes_ += restore(_is, status, _swap);
493 if (fileOptions_.face_has_status() && _opt.face_has_status())
494 _bi.set_status(
FaceHandle(
int(fidx)), status);
499 case Chunk::Type_Custom:
501 bytes_ += restore_binary_custom_data(_is, _bi.kernel()->_get_fprop(property_name_), header_.n_faces_, _swap);
503 fidx = header_.n_faces_;
509 omerr() <<
"Unknown chunk type ignore!\n";
510 size_t chunk_size = OMFormat::chunk_data_size(header_, chunk_header_);
511 _is.ignore(chunk_size);
512 bytes_ += chunk_size;
515 return fidx == header_.n_faces_;
521 bool _OMReader_::read_binary_edge_chunk(std::istream &_is,
BaseImporter &_bi,
Options &_opt,
bool _swap)
const 523 using OMFormat::Chunk;
525 assert( chunk_header_.entity_ == Chunk::Entity_Edge);
531 switch (chunk_header_.type_) {
532 case Chunk::Type_Custom:
534 bytes_ += restore_binary_custom_data(_is, _bi.kernel()->_get_eprop(property_name_), header_.n_edges_, _swap);
538 case Chunk::Type_Status:
540 assert( OMFormat::dimensions(chunk_header_) == 1);
544 for (
size_t eidx = 0; eidx < header_.n_edges_ && !_is.eof(); ++eidx) {
545 bytes_ += restore(_is, status, _swap);
546 if (fileOptions_.edge_has_status() && _opt.edge_has_status())
547 _bi.set_status(
EdgeHandle(
int(eidx)), status);
554 size_t chunk_size = OMFormat::chunk_data_size(header_, chunk_header_);
555 _is.ignore(chunk_size);
556 bytes_ += chunk_size;
565 bool _OMReader_::read_binary_halfedge_chunk(std::istream &_is,
BaseImporter &_bi,
Options & _opt,
bool _swap)
const 567 using OMFormat::Chunk;
569 assert( chunk_header_.entity_ == Chunk::Entity_Halfedge);
574 switch (chunk_header_.type_) {
575 case Chunk::Type_Custom:
577 bytes_ += restore_binary_custom_data(_is, _bi.kernel()->_get_hprop(property_name_), 2 * header_.n_edges_, _swap);
580 case Chunk::Type_Topology:
582 std::vector<HalfedgeHandle> next_halfedges;
583 for (
size_t e_idx = 0; e_idx < header_.n_edges_; ++e_idx)
586 int to_vertex_id_0 = -1;
588 bytes_ += restore( _is, next_id_0, OMFormat::Chunk::Integer_Size(chunk_header_.bits_), _swap );
589 bytes_ += restore( _is, to_vertex_id_0, OMFormat::Chunk::Integer_Size(chunk_header_.bits_), _swap );
590 bytes_ += restore( _is, face_id_0, OMFormat::Chunk::Integer_Size(chunk_header_.bits_), _swap );
593 int to_vertex_id_1 = -1;
595 bytes_ += restore( _is, next_id_1, OMFormat::Chunk::Integer_Size(chunk_header_.bits_), _swap );
596 bytes_ += restore( _is, to_vertex_id_1, OMFormat::Chunk::Integer_Size(chunk_header_.bits_), _swap );
597 bytes_ += restore( _is, face_id_1, OMFormat::Chunk::Integer_Size(chunk_header_.bits_), _swap );
609 for (
size_t i = 0; i < next_halfedges.size(); ++i)
610 _bi.set_next(
HalfedgeHandle(static_cast<int>(i)), next_halfedges[i]);
615 case Chunk::Type_Status:
617 assert( OMFormat::dimensions(chunk_header_) == 1);
621 for (
size_t hidx = 0; hidx < header_.n_edges_ * 2 && !_is.eof(); ++hidx) {
622 bytes_ += restore(_is, status, _swap);
623 if (fileOptions_.halfedge_has_status() && _opt.halfedge_has_status())
631 omerr() <<
"Unknown chunk type ignored!\n";
632 size_t chunk_size = OMFormat::chunk_data_size(header_, chunk_header_);
633 _is.ignore(chunk_size);
634 bytes_ += chunk_size;
643 bool _OMReader_::read_binary_mesh_chunk(std::istream &_is,
BaseImporter &_bi,
Options & ,
bool _swap)
const 645 using OMFormat::Chunk;
647 assert( chunk_header_.entity_ == Chunk::Entity_Mesh);
651 switch (chunk_header_.type_) {
652 case Chunk::Type_Custom:
654 bytes_ += restore_binary_custom_data(_is, _bi.kernel()->_get_mprop(property_name_), 1, _swap);
660 size_t chunk_size = OMFormat::chunk_data_size(header_, chunk_header_);
661 _is.ignore(chunk_size);
662 bytes_ += chunk_size;
672 size_t _OMReader_::restore_binary_custom_data(std::istream& _is,
BaseProperty* _bp,
size_t _n_elem,
bool _swap)
const 674 assert( !_bp || (_bp->
name() == property_name_));
676 using OMFormat::Chunk;
679 Chunk::esize_t block_size;
680 Chunk::PropertyName custom_prop;
682 bytes += restore(_is, block_size, OMFormat::Chunk::Integer_32, _swap);
685 size_t n_bytes = _bp->
size_of(_n_elem);
689 #if defined(OM_DEBUG) 691 bytes += (b=_bp->
restore( _is, _swap ));
693 bytes += _bp->
restore(_is, _swap);
696 #if defined(OM_DEBUG) 697 assert( block_size == b );
700 assert( block_size == _bp->
size_of());
704 omerr() <<
"Warning! Property " << _bp->
name() <<
" not loaded: " <<
"Mismatching data sizes!n";
709 _is.ignore(block_size);
Swap byte order in binary mode.
Handle for a edge entity.
virtual bool can_u_read(const std::string &_filename) const
Returns true if writer can parse _filename (checks extension). _filename can also provide an extensio...
Handle for a face entity.
_OMReader_ __OMReaderInstance
Declare the single entity of the OM reader.
Has (r) / store (w) vertex colors.
Has (r) / store (w) face colors.
Handle for a halfedge entity.
Handle for a vertex entity.
static constexpr int dim()
returns dimension of the vector (deprecated)
bool register_module(BaseReader *_bl)
virtual size_t size_of() const
Return size of property in bytes.
bool read(const std::string &_filename, BaseImporter &_bi, Options &_opt) override
virtual size_t element_size() const =0
Size of one element in bytes or UnknownSize if not known.
const std::string & name() const
Return the name of the property.
Set options for reader/writer modules.
Has (r) / store (w) status properties.
virtual size_t restore(std::istream &_istr, bool _swap)=0
Has (r) / store (w) vertex normals.
static const size_t UnknownSize
Indicates an error when a size is returned by a member.
virtual bool can_u_read(const std::string &_filename) const override
Returns true if writer can parse _filename (checks extension). _filename can also provide an extensio...
_IOManager_ & IOManager()
Has (r) / store (w) face normals.
big endian (Motorola's 68x family, DEC Alpha, MIPS)
Has (r) / store (w) texture coordinates.
static Type local()
Return endian type of host system.