Developer Documentation
OMReader.cc
1 /* ========================================================================= *
2  * *
3  * OpenMesh *
4  * Copyright (c) 2001-2015, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openmesh.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenMesh. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39  * *
40  * ========================================================================= */
41 
42 
43 
44 
45 //== INCLUDES =================================================================
46 
47 
48 //STL
49 #include <vector>
50 #include <istream>
51 #include <fstream>
52 
53 // OpenMesh
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>
60 
61 
62 //=== NAMESPACES ==============================================================
63 
64 
65 namespace OpenMesh {
66 namespace IO {
67 
68 
69 //=== INSTANCIATE =============================================================
70 
71 
72 // register the OMReader singleton with MeshReader
74 _OMReader_& OMReader() { return __OMReaderInstance; }
75 
76 
77 
78 //=== IMPLEMENTATION ==========================================================
79 
80 
81 _OMReader_::_OMReader_()
82 {
83  IOManager().register_module(this);
84 }
85 
86 
87 //-----------------------------------------------------------------------------
88 
89 
90 bool _OMReader_::read(const std::string& _filename, BaseImporter& _bi, Options& _opt)
91 {
92  // check whether importer can give us an OpenMesh BaseKernel
93  if (!_bi.kernel())
94  return false;
95 
96  _opt += Options::Binary; // only binary format supported!
97  fileOptions_ = Options::Binary;
98 
99  // Open file
100  std::ifstream ifs(_filename.c_str(), std::ios::binary);
101 
102  /* Clear formatting flag skipws (Skip whitespaces). If set, operator>> will
103  * skip bytes set to whitespace chars (e.g. 0x20 bytes) in
104  * Property<bool>::restore.
105  */
106  ifs.unsetf(std::ios::skipws);
107 
108  if (!ifs.is_open() || !ifs.good()) {
109  omerr() << "[OMReader] : cannot not open file " << _filename << std::endl;
110  return false;
111  }
112 
113  // Pass stream to read method, remember result
114  bool result = read(ifs, _bi, _opt);
115 
116  // close input stream
117  ifs.close();
118 
119  _opt = _opt & fileOptions_;
120 
121  return result;
122 }
123 
124 //-----------------------------------------------------------------------------
125 
126 
127 bool _OMReader_::read(std::istream& _is, BaseImporter& _bi, Options& _opt)
128 {
129  // check whether importer can give us an OpenMesh BaseKernel
130  if (!_bi.kernel())
131  return false;
132 
133  _opt += Options::Binary; // only binary format supported!
134  fileOptions_ = Options::Binary;
135 
136  if (!_is.good()) {
137  omerr() << "[OMReader] : cannot read from stream " << std::endl;
138  return false;
139  }
140 
141  // Pass stream to read method, remember result
142  bool result = read_binary(_is, _bi, _opt);
143 
144  if (result)
145  _opt += Options::Binary;
146 
147  _opt = _opt & fileOptions_;
148 
149  return result;
150 }
151 
152 
153 
154 //-----------------------------------------------------------------------------
155 
156 bool _OMReader_::read_ascii(std::istream& /* _is */, BaseImporter& /* _bi */, Options& /* _opt */) const
157 {
158  // not supported yet!
159  return false;
160 }
161 
162 
163 //-----------------------------------------------------------------------------
164 
165 bool _OMReader_::read_binary(std::istream& _is, BaseImporter& _bi, Options& _opt) const
166 {
167  bool swap = _opt.check(Options::Swap) || (Endian::local() == Endian::MSB);
168 
169  // Initialize byte counter
170  bytes_ = 0;
171 
172  bytes_ += restore(_is, header_, swap);
173 
174 
175  if (header_.version_ > _OMWriter_::get_version())
176  {
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;
180  return false;
181  }
182 
183 
184  while (!_is.eof()) {
185  bytes_ += restore(_is, chunk_header_, swap);
186 
187  if (_is.eof())
188  break;
189 
190  // Is this a named property restore the name
191  if (chunk_header_.name_) {
192  OMFormat::Chunk::PropertyName pn;
193  bytes_ += restore(_is, property_name_, swap);
194  }
195 
196  // Read in the property data. If it is an anonymous or unknown named
197  // property, then skip data.
198  switch (chunk_header_.entity_) {
199  case OMFormat::Chunk::Entity_Vertex:
200  if (!read_binary_vertex_chunk(_is, _bi, _opt, swap))
201  return false;
202  break;
203  case OMFormat::Chunk::Entity_Face:
204  if (!read_binary_face_chunk(_is, _bi, _opt, swap))
205  return false;
206  break;
207  case OMFormat::Chunk::Entity_Edge:
208  if (!read_binary_edge_chunk(_is, _bi, _opt, swap))
209  return false;
210  break;
211  case OMFormat::Chunk::Entity_Halfedge:
212  if (!read_binary_halfedge_chunk(_is, _bi, _opt, swap))
213  return false;
214  break;
215  case OMFormat::Chunk::Entity_Mesh:
216  if (!read_binary_mesh_chunk(_is, _bi, _opt, swap))
217  return false;
218  break;
219  case OMFormat::Chunk::Entity_Sentinel:
220  return true;
221  default:
222  return false;
223  }
224 
225  }
226 
227  // File was successfully parsed.
228  return true;
229 }
230 
231 
232 //-----------------------------------------------------------------------------
233 
234 bool _OMReader_::can_u_read(const std::string& _filename) const
235 {
236  // !!! Assuming BaseReader::can_u_parse( std::string& )
237  // does not call BaseReader::read_magic()!!!
238  if (this->BaseReader::can_u_read(_filename)) {
239  std::ifstream ifile(_filename.c_str());
240  if (ifile && can_u_read(ifile))
241  return true;
242  }
243  return false;
244 }
245 
246 //-----------------------------------------------------------------------------
247 
248 bool _OMReader_::can_u_read(std::istream& _is) const
249 {
250  std::vector<char> evt;
251  evt.reserve(20);
252 
253  // read first 4 characters into a buffer
254  while (evt.size() < 4)
255  evt.push_back(static_cast<char>(_is.get()));
256 
257  // put back all read characters
258  std::vector<char>::reverse_iterator it = evt.rbegin();
259  while (it != evt.rend())
260  _is.putback(*it++);
261 
262  // evaluate header information
263  OMFormat::Header *hdr = (OMFormat::Header*) &evt[0];
264 
265  // first two characters must be 'OM'
266  if (hdr->magic_[0] != 'O' || hdr->magic_[1] != 'M')
267  return false;
268 
269  // 3rd characters defines the mesh type:
270  switch (hdr->mesh_) {
271  case 'T': // Triangle Mesh
272  case 'Q': // Quad Mesh
273  case 'P': // Polygonal Mesh
274  break;
275  default: // ?
276  return false;
277  }
278 
279  // 4th characters encodes the version
280  return supports(hdr->version_);
281 }
282 
283 //-----------------------------------------------------------------------------
284 
285 bool _OMReader_::supports(const OMFormat::uint8 /* version */) const
286 {
287  return true;
288 }
289 
290 
291 //-----------------------------------------------------------------------------
292 
293 bool _OMReader_::read_binary_vertex_chunk(std::istream &_is, BaseImporter &_bi, Options &_opt, bool _swap) const
294 {
295  using OMFormat::Chunk;
296 
297  assert( chunk_header_.entity_ == Chunk::Entity_Vertex);
298 
299  OpenMesh::Vec3f v3f;
300  OpenMesh::Vec3d v3d;
301  OpenMesh::Vec2f v2f;
302  OpenMesh::Vec3uc v3uc; // rgb
304 
305  OMFormat::Chunk::PropertyName custom_prop;
306 
307  size_t vidx = 0;
308  switch (chunk_header_.type_) {
309  case Chunk::Type_Pos:
310  if (chunk_header_.bits_ == OMFormat::bits(0.0f)) // read floats
311  {
312  assert( OMFormat::dimensions(chunk_header_) == size_t(OpenMesh::Vec3f::dim()));
313 
314  for (; vidx < header_.n_vertices_ && !_is.eof(); ++vidx) {
315  bytes_ += vector_restore(_is, v3f, _swap);
316  _bi.add_vertex(v3f);
317  }
318  }
319  else if (chunk_header_.bits_ == OMFormat::bits(0.0)) // read doubles
320  {
321  assert( OMFormat::dimensions(chunk_header_) == size_t(OpenMesh::Vec3d::dim()));
322 
323  for (; vidx < header_.n_vertices_ && !_is.eof(); ++vidx) {
324  bytes_ += vector_restore(_is, v3d, _swap);
325  _bi.add_vertex(v3d);
326  }
327  }
328  else
329  {
330  omerr() << "unknown Vector size" << std::endl;
331  }
332  break;
333 
334  case Chunk::Type_Normal:
335 
336  if (chunk_header_.bits_ == OMFormat::bits(0.0f)) // read floats
337  {
338  assert( OMFormat::dimensions(chunk_header_) == size_t(OpenMesh::Vec3f::dim()));
339 
340  fileOptions_ += Options::VertexNormal;
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())
344  _bi.set_normal(VertexHandle(int(vidx)), v3f);
345  }
346  }
347  else if (chunk_header_.bits_ == OMFormat::bits(0.0)) // read doubles
348  {
349  assert( OMFormat::dimensions(chunk_header_) == size_t(OpenMesh::Vec3d::dim()));
350 
351  fileOptions_ += Options::VertexNormal;
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())
355  _bi.set_normal(VertexHandle(int(vidx)), v3d);
356  }
357  }
358  else
359  {
360  omerr() << "Unknown vertex normal format" << std::endl;
361  }
362  break;
363 
364  case Chunk::Type_Texcoord:
365  assert( OMFormat::dimensions(chunk_header_) == size_t(OpenMesh::Vec2f::dim()));
366 
367  fileOptions_ += Options::VertexTexCoord;
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())
371  _bi.set_texcoord(VertexHandle(int(vidx)), v2f);
372  }
373  break;
374 
375  case Chunk::Type_Color:
376 
377  assert( OMFormat::dimensions(chunk_header_) == 3);
378 
379  fileOptions_ += Options::VertexColor;
380 
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())
384  _bi.set_color(VertexHandle(int(vidx)), v3uc);
385  }
386  break;
387 
388  case Chunk::Type_Status:
389  {
390  assert( OMFormat::dimensions(chunk_header_) == 1);
391 
392  fileOptions_ += Options::Status;
393 
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())
397  _bi.set_status(VertexHandle(int(vidx)), status);
398  }
399  break;
400  }
401 
402  case Chunk::Type_Custom:
403 
404  bytes_ += restore_binary_custom_data(_is, _bi.kernel()->_get_vprop(property_name_), header_.n_vertices_, _swap);
405 
406  vidx = header_.n_vertices_;
407 
408  break;
409 
410  case Chunk::Type_Topology:
411  {
412  for (; vidx < header_.n_vertices_; ++vidx)
413  {
414  int halfedge_id = 0;
415  bytes_ += restore( _is, halfedge_id, OMFormat::Chunk::Integer_Size(chunk_header_.bits_), _swap );
416 
417  _bi.set_halfedge(VertexHandle(static_cast<int>(vidx)), HalfedgeHandle(halfedge_id));
418  }
419  }
420 
421  break;
422 
423  default: // skip unknown chunks
424  {
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;
429  break;
430  }
431 
432  }
433 
434  // all chunk data has been read..?!
435  return vidx == header_.n_vertices_;
436 }
437 
438 
439 //-----------------------------------------------------------------------------
440 
441 bool _OMReader_::read_binary_face_chunk(std::istream &_is, BaseImporter &_bi, Options &_opt, bool _swap) const
442 {
443  using OMFormat::Chunk;
444 
445  assert( chunk_header_.entity_ == Chunk::Entity_Face);
446 
447  size_t fidx = 0;
448  OpenMesh::Vec3f v3f; // normal
449  OpenMesh::Vec3d v3d; // normal as double
450  OpenMesh::Vec3uc v3uc; // rgb
452 
453  switch (chunk_header_.type_) {
454  case Chunk::Type_Topology:
455  {
456  if (header_.version_ < OMFormat::mk_version(2,0))
457  {
458  // add faces based on vertex indices
459  BaseImporter::VHandles vhandles;
460  size_t nV = 0;
461  size_t vidx = 0;
462 
463  switch (header_.mesh_) {
464  case 'T':
465  nV = 3;
466  break;
467  case 'Q':
468  nV = 4;
469  break;
470  }
471 
472  for (; fidx < header_.n_faces_; ++fidx) {
473  if (header_.mesh_ == 'P')
474  bytes_ += restore(_is, nV, Chunk::Integer_16, _swap);
475 
476  vhandles.clear();
477  for (size_t j = 0; j < nV; ++j) {
478  bytes_ += restore(_is, vidx, Chunk::Integer_Size(chunk_header_.bits_), _swap);
479 
480  vhandles.push_back(VertexHandle(int(vidx)));
481  }
482 
483  _bi.add_face(vhandles);
484  }
485  }
486  else
487  {
488  // add faces by simply setting an incident halfedge
489  for (; fidx < header_.n_faces_; ++fidx)
490  {
491  int halfedge_id = 0;
492  bytes_ += restore( _is, halfedge_id, OMFormat::Chunk::Integer_Size(chunk_header_.bits_), _swap );
493 
494  _bi.add_face(HalfedgeHandle(halfedge_id));
495  }
496  }
497  }
498  break;
499 
500  case Chunk::Type_Normal:
501  assert( OMFormat::dimensions(chunk_header_) == size_t(OpenMesh::Vec3f::dim()));
502 
503  fileOptions_ += Options::FaceNormal;
504 
505  if (chunk_header_.bits_ == OMFormat::bits(0.0f)) // read floats
506  {
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())
510  _bi.set_normal(FaceHandle(int(fidx)), v3f);
511  }
512  }
513  else if (chunk_header_.bits_ == OMFormat::bits(0.0)) // read doubles
514  {
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())
518  _bi.set_normal(FaceHandle(int(fidx)), v3d);
519  }
520  }
521  else
522  {
523  omerr() << "Unknown face normal format" << std::endl;
524  }
525  break;
526 
527  case Chunk::Type_Color:
528 
529  assert( OMFormat::dimensions(chunk_header_) == 3);
530 
531  fileOptions_ += Options::FaceColor;
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())
535  _bi.set_color(FaceHandle(int(fidx)), v3uc);
536  }
537  break;
538  case Chunk::Type_Status:
539  {
540  assert( OMFormat::dimensions(chunk_header_) == 1);
541 
542  fileOptions_ += Options::Status;
543 
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);
548  }
549  break;
550  }
551 
552  case Chunk::Type_Custom:
553 
554  bytes_ += restore_binary_custom_data(_is, _bi.kernel()->_get_fprop(property_name_), header_.n_faces_, _swap);
555 
556  fidx = header_.n_faces_;
557 
558  break;
559 
560  default: // skip unknown chunks
561  {
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;
566  }
567  }
568  return fidx == header_.n_faces_;
569 }
570 
571 
572 //-----------------------------------------------------------------------------
573 
574 bool _OMReader_::read_binary_edge_chunk(std::istream &_is, BaseImporter &_bi, Options &_opt, bool _swap) const
575 {
576  using OMFormat::Chunk;
577 
578  assert( chunk_header_.entity_ == Chunk::Entity_Edge);
579 
580  size_t b = bytes_;
581 
583 
584  switch (chunk_header_.type_) {
585  case Chunk::Type_Custom:
586 
587  bytes_ += restore_binary_custom_data(_is, _bi.kernel()->_get_eprop(property_name_), header_.n_edges_, _swap);
588 
589  break;
590 
591  case Chunk::Type_Status:
592  {
593  assert( OMFormat::dimensions(chunk_header_) == 1);
594 
595  fileOptions_ += Options::Status;
596 
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);
601  }
602  break;
603  }
604 
605  default:
606  // skip unknown type
607  size_t chunk_size = OMFormat::chunk_data_size(header_, chunk_header_);
608  _is.ignore(chunk_size);
609  bytes_ += chunk_size;
610  }
611 
612  return b < bytes_;
613 }
614 
615 
616 //-----------------------------------------------------------------------------
617 
618 bool _OMReader_::read_binary_halfedge_chunk(std::istream &_is, BaseImporter &_bi, Options & _opt, bool _swap) const
619 {
620  using OMFormat::Chunk;
621 
622  assert( chunk_header_.entity_ == Chunk::Entity_Halfedge);
623 
624  size_t b = bytes_;
626 
627  switch (chunk_header_.type_) {
628  case Chunk::Type_Custom:
629 
630  bytes_ += restore_binary_custom_data(_is, _bi.kernel()->_get_hprop(property_name_), 2 * header_.n_edges_, _swap);
631  break;
632 
633  case Chunk::Type_Topology:
634  {
635  std::vector<HalfedgeHandle> next_halfedges;
636  for (size_t e_idx = 0; e_idx < header_.n_edges_; ++e_idx)
637  {
638  int next_id_0 = -1;
639  int to_vertex_id_0 = -1;
640  int face_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 );
644 
645  int next_id_1 = -1;
646  int to_vertex_id_1 = -1;
647  int face_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 );
651 
652  auto heh0 = _bi.add_edge(VertexHandle(to_vertex_id_1), VertexHandle(to_vertex_id_0));
653  auto heh1 = HalfedgeHandle(heh0.idx() + 1);
654 
655  next_halfedges.push_back(HalfedgeHandle(next_id_0));
656  next_halfedges.push_back(HalfedgeHandle(next_id_1));
657 
658  _bi.set_face(heh0, FaceHandle(face_id_0));
659  _bi.set_face(heh1, FaceHandle(face_id_1));
660  }
661 
662  for (size_t i = 0; i < next_halfedges.size(); ++i)
663  _bi.set_next(HalfedgeHandle(static_cast<int>(i)), next_halfedges[i]);
664  }
665 
666  break;
667 
668  case Chunk::Type_Status:
669  {
670  assert( OMFormat::dimensions(chunk_header_) == 1);
671 
672  fileOptions_ += Options::Status;
673 
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())
677  _bi.set_status(HalfedgeHandle(int(hidx)), status);
678  }
679  break;
680  }
681 
682  default:
683  // skip unknown chunk
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;
688  }
689 
690  return b < bytes_;
691 }
692 
693 
694 //-----------------------------------------------------------------------------
695 
696 bool _OMReader_::read_binary_mesh_chunk(std::istream &_is, BaseImporter &_bi, Options & /* _opt */, bool _swap) const
697 {
698  using OMFormat::Chunk;
699 
700  assert( chunk_header_.entity_ == Chunk::Entity_Mesh);
701 
702  size_t b = bytes_;
703 
704  switch (chunk_header_.type_) {
705  case Chunk::Type_Custom:
706 
707  bytes_ += restore_binary_custom_data(_is, _bi.kernel()->_get_mprop(property_name_), 1, _swap);
708 
709  break;
710 
711  default:
712  // skip unknown chunk
713  size_t chunk_size = OMFormat::chunk_data_size(header_, chunk_header_);
714  _is.ignore(chunk_size);
715  bytes_ += chunk_size;
716  }
717 
718  return b < bytes_;
719 }
720 
721 
722 //-----------------------------------------------------------------------------
723 
724 
725 size_t _OMReader_::restore_binary_custom_data(std::istream& _is, BaseProperty* _bp, size_t _n_elem, bool _swap) const
726 {
727  assert( !_bp || (_bp->name() == property_name_));
728 
729  using OMFormat::Chunk;
730 
731  size_t bytes = 0;
732  Chunk::esize_t block_size;
733  Chunk::PropertyName custom_prop;
734 
735  bytes += restore(_is, block_size, OMFormat::Chunk::Integer_32, _swap);
736 
737  if (_bp) {
738  size_t n_bytes = _bp->size_of(_n_elem);
739 
740  if (((n_bytes == BaseProperty::UnknownSize) || (n_bytes == block_size))
741  && (_bp->element_size() == BaseProperty::UnknownSize || (_n_elem * _bp->element_size() == block_size))) {
742 #if defined(OM_DEBUG)
743  size_t b;
744  bytes += (b=_bp->restore( _is, _swap ));
745 #else
746  bytes += _bp->restore(_is, _swap);
747 #endif
748 
749 #if defined(OM_DEBUG)
750  assert( block_size == b );
751 #endif
752 
753  assert( block_size == _bp->size_of());
754 
755  block_size = 0;
756  } else {
757  omerr() << "Warning! Property " << _bp->name() << " not loaded: " << "Mismatching data sizes!n";
758  }
759  }
760 
761  if (block_size) {
762  _is.ignore(block_size);
763  bytes += block_size;
764  }
765 
766  return bytes;
767 }
768 
769 
770 //-----------------------------------------------------------------------------
771 
772 //=============================================================================
773 } // namespace IO
774 } // namespace OpenMesh
775 //=============================================================================
Swap byte order in binary mode.
Definition: Options.hh:103
Handle for a edge entity.
Definition: Handles.hh:134
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...
Definition: BaseReader.cc:77
Handle for a face entity.
Definition: Handles.hh:141
_OMReader_ __OMReaderInstance
Declare the single entity of the OM reader.
Definition: OMReader.cc:73
Has (r) / store (w) vertex colors.
Definition: Options.hh:105
Has (r) / store (w) face colors.
Definition: Options.hh:109
Handle for a halfedge entity.
Definition: Handles.hh:127
Handle for a vertex entity.
Definition: Handles.hh:120
static constexpr int dim()
returns dimension of the vector (deprecated)
Definition: Vector11T.hh:102
bool register_module(BaseReader *_bl)
Definition: IOManager.hh:217
virtual size_t size_of() const
Return size of property in bytes.
bool read(const std::string &_filename, BaseImporter &_bi, Options &_opt) override
Definition: OMReader.cc:90
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.
Definition: Options.hh:90
Has (r) / store (w) status properties.
Definition: Options.hh:114
virtual size_t restore(std::istream &_istr, bool _swap)=0
Has (r) / store (w) vertex normals.
Definition: Options.hh:104
static const size_t UnknownSize
Indicates an error when a size is returned by a member.
Definition: BaseProperty.hh:65
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...
Definition: OMReader.cc:234
_IOManager_ & IOManager()
Definition: IOManager.cc:72
Has (r) / store (w) face normals.
Definition: Options.hh:108
big endian (Motorola&#39;s 68x family, DEC Alpha, MIPS)
Definition: Endian.hh:79
Set binary mode for r/w.
Definition: Options.hh:100
Has (r) / store (w) texture coordinates.
Definition: Options.hh:106
static Type local()
Return endian type of host system.
Definition: Endian.hh:83