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);
305 OMFormat::Chunk::PropertyName custom_prop;
308 switch (chunk_header_.type_) {
309 case Chunk::Type_Pos:
310 if (chunk_header_.bits_ == OMFormat::bits(0.0f))
314 for (; vidx < header_.n_vertices_ && !_is.eof(); ++vidx) {
315 bytes_ += vector_restore(_is, v3f, _swap);
319 else if (chunk_header_.bits_ == OMFormat::bits(0.0))
323 for (; vidx < header_.n_vertices_ && !_is.eof(); ++vidx) {
324 bytes_ += vector_restore(_is, v3d, _swap);
330 omerr() <<
"unknown Vector size" << std::endl;
334 case Chunk::Type_Normal:
336 if (chunk_header_.bits_ == OMFormat::bits(0.0f))
341 for (; vidx < header_.n_vertices_ && !_is.eof(); ++vidx) {
342 bytes_ += vector_restore(_is, v3f, _swap);
343 if (fileOptions_.vertex_has_normal() && _opt.vertex_has_normal())
347 else if (chunk_header_.bits_ == OMFormat::bits(0.0))
352 for (; vidx < header_.n_vertices_ && !_is.eof(); ++vidx) {
353 bytes_ += vector_restore(_is, v3d, _swap);
354 if (fileOptions_.vertex_has_normal() && _opt.vertex_has_normal())
360 omerr() <<
"Unknown vertex normal format" << std::endl;
364 case Chunk::Type_Texcoord:
368 for (; vidx < header_.n_vertices_ && !_is.eof(); ++vidx) {
369 bytes_ += vector_restore(_is, v2f, _swap);
370 if (fileOptions_.vertex_has_texcoord() && _opt.vertex_has_texcoord())
375 case Chunk::Type_Color:
377 assert( OMFormat::dimensions(chunk_header_) == 3);
381 for (; vidx < header_.n_vertices_ && !_is.eof(); ++vidx) {
382 bytes_ += vector_restore(_is, v3uc, _swap);
383 if (fileOptions_.vertex_has_color() && _opt.vertex_has_color())
388 case Chunk::Type_Status:
390 assert( OMFormat::dimensions(chunk_header_) == 1);
394 for (; vidx < header_.n_vertices_ && !_is.eof(); ++vidx) {
395 bytes_ += restore(_is, status, _swap);
396 if (fileOptions_.vertex_has_status() && _opt.vertex_has_status())
402 case Chunk::Type_Custom:
404 bytes_ += restore_binary_custom_data(_is, _bi.kernel()->_get_vprop(property_name_), header_.n_vertices_, _swap);
406 vidx = header_.n_vertices_;
410 case Chunk::Type_Topology:
412 for (; vidx < header_.n_vertices_; ++vidx)
415 bytes_ += restore( _is, halfedge_id, OMFormat::Chunk::Integer_Size(chunk_header_.bits_), _swap );
425 omerr() <<
"Unknown chunk type ignored!\n";
426 size_t chunk_size = header_.n_vertices_ * OMFormat::vector_size(chunk_header_);
427 _is.ignore(chunk_size);
428 bytes_ += chunk_size;
435 return vidx == header_.n_vertices_;
441 bool _OMReader_::read_binary_face_chunk(std::istream &_is,
BaseImporter &_bi,
Options &_opt,
bool _swap)
const 443 using OMFormat::Chunk;
445 assert( chunk_header_.entity_ == Chunk::Entity_Face);
453 switch (chunk_header_.type_) {
454 case Chunk::Type_Topology:
456 if (header_.version_ < OMFormat::mk_version(2,0))
459 BaseImporter::VHandles vhandles;
463 switch (header_.mesh_) {
472 for (; fidx < header_.n_faces_; ++fidx) {
473 if (header_.mesh_ ==
'P')
474 bytes_ += restore(_is, nV, Chunk::Integer_16, _swap);
477 for (
size_t j = 0; j < nV; ++j) {
478 bytes_ += restore(_is, vidx, Chunk::Integer_Size(chunk_header_.bits_), _swap);
483 _bi.add_face(vhandles);
489 for (; fidx < header_.n_faces_; ++fidx)
492 bytes_ += restore( _is, halfedge_id, OMFormat::Chunk::Integer_Size(chunk_header_.bits_), _swap );
500 case Chunk::Type_Normal:
505 if (chunk_header_.bits_ == OMFormat::bits(0.0f))
507 for (; fidx < header_.n_faces_ && !_is.eof(); ++fidx) {
508 bytes_ += vector_restore(_is, v3f, _swap);
509 if( fileOptions_.face_has_normal() && _opt.face_has_normal())
513 else if (chunk_header_.bits_ == OMFormat::bits(0.0))
515 for (; fidx < header_.n_faces_ && !_is.eof(); ++fidx) {
516 bytes_ += vector_restore(_is, v3d, _swap);
517 if( fileOptions_.face_has_normal() && _opt.face_has_normal())
523 omerr() <<
"Unknown face normal format" << std::endl;
527 case Chunk::Type_Color:
529 assert( OMFormat::dimensions(chunk_header_) == 3);
532 for (; fidx < header_.n_faces_ && !_is.eof(); ++fidx) {
533 bytes_ += vector_restore(_is, v3uc, _swap);
534 if( fileOptions_.face_has_color() && _opt.face_has_color())
538 case Chunk::Type_Status:
540 assert( OMFormat::dimensions(chunk_header_) == 1);
544 for (; fidx < header_.n_faces_ && !_is.eof(); ++fidx) {
545 bytes_ += restore(_is, status, _swap);
546 if (fileOptions_.face_has_status() && _opt.face_has_status())
547 _bi.set_status(
FaceHandle(
int(fidx)), status);
552 case Chunk::Type_Custom:
554 bytes_ += restore_binary_custom_data(_is, _bi.kernel()->_get_fprop(property_name_), header_.n_faces_, _swap);
556 fidx = header_.n_faces_;
562 omerr() <<
"Unknown chunk type ignore!\n";
563 size_t chunk_size = OMFormat::chunk_data_size(header_, chunk_header_);
564 _is.ignore(chunk_size);
565 bytes_ += chunk_size;
568 return fidx == header_.n_faces_;
574 bool _OMReader_::read_binary_edge_chunk(std::istream &_is,
BaseImporter &_bi,
Options &_opt,
bool _swap)
const 576 using OMFormat::Chunk;
578 assert( chunk_header_.entity_ == Chunk::Entity_Edge);
584 switch (chunk_header_.type_) {
585 case Chunk::Type_Custom:
587 bytes_ += restore_binary_custom_data(_is, _bi.kernel()->_get_eprop(property_name_), header_.n_edges_, _swap);
591 case Chunk::Type_Status:
593 assert( OMFormat::dimensions(chunk_header_) == 1);
597 for (
size_t eidx = 0; eidx < header_.n_edges_ && !_is.eof(); ++eidx) {
598 bytes_ += restore(_is, status, _swap);
599 if (fileOptions_.edge_has_status() && _opt.edge_has_status())
600 _bi.set_status(
EdgeHandle(
int(eidx)), status);
607 size_t chunk_size = OMFormat::chunk_data_size(header_, chunk_header_);
608 _is.ignore(chunk_size);
609 bytes_ += chunk_size;
618 bool _OMReader_::read_binary_halfedge_chunk(std::istream &_is,
BaseImporter &_bi,
Options & _opt,
bool _swap)
const 620 using OMFormat::Chunk;
622 assert( chunk_header_.entity_ == Chunk::Entity_Halfedge);
627 switch (chunk_header_.type_) {
628 case Chunk::Type_Custom:
630 bytes_ += restore_binary_custom_data(_is, _bi.kernel()->_get_hprop(property_name_), 2 * header_.n_edges_, _swap);
633 case Chunk::Type_Topology:
635 std::vector<HalfedgeHandle> next_halfedges;
636 for (
size_t e_idx = 0; e_idx < header_.n_edges_; ++e_idx)
639 int to_vertex_id_0 = -1;
641 bytes_ += restore( _is, next_id_0, OMFormat::Chunk::Integer_Size(chunk_header_.bits_), _swap );
642 bytes_ += restore( _is, to_vertex_id_0, OMFormat::Chunk::Integer_Size(chunk_header_.bits_), _swap );
643 bytes_ += restore( _is, face_id_0, OMFormat::Chunk::Integer_Size(chunk_header_.bits_), _swap );
646 int to_vertex_id_1 = -1;
648 bytes_ += restore( _is, next_id_1, OMFormat::Chunk::Integer_Size(chunk_header_.bits_), _swap );
649 bytes_ += restore( _is, to_vertex_id_1, OMFormat::Chunk::Integer_Size(chunk_header_.bits_), _swap );
650 bytes_ += restore( _is, face_id_1, OMFormat::Chunk::Integer_Size(chunk_header_.bits_), _swap );
662 for (
size_t i = 0; i < next_halfedges.size(); ++i)
663 _bi.set_next(
HalfedgeHandle(static_cast<int>(i)), next_halfedges[i]);
668 case Chunk::Type_Status:
670 assert( OMFormat::dimensions(chunk_header_) == 1);
674 for (
size_t hidx = 0; hidx < header_.n_edges_ * 2 && !_is.eof(); ++hidx) {
675 bytes_ += restore(_is, status, _swap);
676 if (fileOptions_.halfedge_has_status() && _opt.halfedge_has_status())
684 omerr() <<
"Unknown chunk type ignored!\n";
685 size_t chunk_size = OMFormat::chunk_data_size(header_, chunk_header_);
686 _is.ignore(chunk_size);
687 bytes_ += chunk_size;
696 bool _OMReader_::read_binary_mesh_chunk(std::istream &_is,
BaseImporter &_bi,
Options & ,
bool _swap)
const 698 using OMFormat::Chunk;
700 assert( chunk_header_.entity_ == Chunk::Entity_Mesh);
704 switch (chunk_header_.type_) {
705 case Chunk::Type_Custom:
707 bytes_ += restore_binary_custom_data(_is, _bi.kernel()->_get_mprop(property_name_), 1, _swap);
713 size_t chunk_size = OMFormat::chunk_data_size(header_, chunk_header_);
714 _is.ignore(chunk_size);
715 bytes_ += chunk_size;
725 size_t _OMReader_::restore_binary_custom_data(std::istream& _is,
BaseProperty* _bp,
size_t _n_elem,
bool _swap)
const 727 assert( !_bp || (_bp->
name() == property_name_));
729 using OMFormat::Chunk;
732 Chunk::esize_t block_size;
733 Chunk::PropertyName custom_prop;
735 bytes += restore(_is, block_size, OMFormat::Chunk::Integer_32, _swap);
738 size_t n_bytes = _bp->
size_of(_n_elem);
742 #if defined(OM_DEBUG) 744 bytes += (b=_bp->
restore( _is, _swap ));
746 bytes += _bp->
restore(_is, _swap);
749 #if defined(OM_DEBUG) 750 assert( block_size == b );
753 assert( block_size == _bp->
size_of());
757 omerr() <<
"Warning! Property " << _bp->
name() <<
" not loaded: " <<
"Mismatching data sizes!n";
762 _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.