OMReader.cc 22 KB
Newer Older
Jan Möbius's avatar
Jan Möbius committed
1
/* ========================================================================= *
Jan Möbius's avatar
Jan Möbius committed
2
3
 *                                                                           *
 *                               OpenMesh                                    *
Jan Möbius's avatar
Jan Möbius committed
4
 *           Copyright (c) 2001-2015, RWTH-Aachen University                 *
Jan Möbius's avatar
Typo    
Jan Möbius committed
5
 *           Department of Computer Graphics and Multimedia                  *
Jan Möbius's avatar
Jan Möbius committed
6
7
 *                          All rights reserved.                             *
 *                            www.openmesh.org                               *
Jan Möbius's avatar
Jan Möbius committed
8
 *                                                                           *
9
 *---------------------------------------------------------------------------*
Jan Möbius's avatar
Jan Möbius committed
10
11
 * This file is part of OpenMesh.                                            *
 *---------------------------------------------------------------------------*
12
 *                                                                           *
Jan Möbius's avatar
Jan Möbius committed
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
 * Redistribution and use in source and binary forms, with or without        *
 * modification, are permitted provided that the following conditions        *
 * are met:                                                                  *
 *                                                                           *
 * 1. Redistributions of source code must retain the above copyright notice, *
 *    this list of conditions and the following disclaimer.                  *
 *                                                                           *
 * 2. Redistributions in binary form must reproduce the above copyright      *
 *    notice, this list of conditions and the following disclaimer in the    *
 *    documentation and/or other materials provided with the distribution.   *
 *                                                                           *
 * 3. Neither the name of the copyright holder nor the names of its          *
 *    contributors may be used to endorse or promote products derived from   *
 *    this software without specific prior written permission.               *
 *                                                                           *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS       *
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A           *
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  *
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,       *
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR        *
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF    *
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING      *
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS        *
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.              *
Jan Möbius's avatar
Jan Möbius committed
39
40
 *                                                                           *
 * ========================================================================= */
41
42

/*===========================================================================*\
43
 *                                                                           *
44
45
 *   $Revision$                                                         *
 *   $Date$                   *
Jan Möbius's avatar
Jan Möbius committed
46
47
48
49
50
51
52
53
 *                                                                           *
\*===========================================================================*/


//== INCLUDES =================================================================


//STL
54
55
#include <vector>
#include <istream>
Jan Möbius's avatar
Jan Möbius committed
56
57
58
59
60
61
62
63
#include <fstream>

// OpenMesh
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/System/omstream.hh>
#include <OpenMesh/Core/Utils/Endian.hh>
#include <OpenMesh/Core/IO/OMFormat.hh>
#include <OpenMesh/Core/IO/reader/OMReader.hh>
64
#include <OpenMesh/Core/IO/writer/OMWriter.hh>
Jan Möbius's avatar
Jan Möbius committed
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87


//=== NAMESPACES ==============================================================


namespace OpenMesh {
namespace IO {


//=== INSTANCIATE =============================================================


// register the OMReader singleton with MeshReader
_OMReader_  __OMReaderInstance;
_OMReader_&  OMReader() { return __OMReaderInstance; }



//=== IMPLEMENTATION ==========================================================


_OMReader_::_OMReader_()
{
88
  IOManager().register_module(this);
Jan Möbius's avatar
Jan Möbius committed
89
90
91
92
93
94
}


//-----------------------------------------------------------------------------


95
bool _OMReader_::read(const std::string& _filename, BaseImporter& _bi, Options& _opt)
Jan Möbius's avatar
Jan Möbius committed
96
97
{
  // check whether importer can give us an OpenMesh BaseKernel
98
99
  if (!_bi.kernel())
    return false;
Jan Möbius's avatar
Jan Möbius committed
100
101

  _opt += Options::Binary; // only binary format supported!
102
  fileOptions_ = Options::Binary;
Jan Möbius's avatar
Jan Möbius committed
103
104

  // Open file
105
  std::ifstream ifs(_filename.c_str(), std::ios::binary);
106
107
108
109
110
111
112

  /* Clear formatting flag skipws (Skip whitespaces). If set, operator>> will
   * skip bytes set to whitespace chars (e.g. 0x20 bytes) in
   * Property<bool>::restore.
   */
  ifs.unsetf(std::ios::skipws);

113
114
  if (!ifs.is_open() || !ifs.good()) {
    omerr() << "[OMReader] : cannot not open file " << _filename << std::endl;
Jan Möbius's avatar
Jan Möbius committed
115
116
    return false;
  }
117

Jan Möbius's avatar
Jan Möbius committed
118
119
  // Pass stream to read method, remember result
  bool result = read(ifs, _bi, _opt);
120

Jan Möbius's avatar
Jan Möbius committed
121
122
  // close input stream
  ifs.close();
123

124
125
  _opt = _opt & fileOptions_;

Jan Möbius's avatar
Jan Möbius committed
126
127
128
129
130
131
  return result;
}

//-----------------------------------------------------------------------------


132
bool _OMReader_::read(std::istream& _is, BaseImporter& _bi, Options& _opt)
Jan Möbius's avatar
Jan Möbius committed
133
{
134
  // check whether importer can give us an OpenMesh BaseKernel
135
136
  if (!_bi.kernel())
    return false;
137
138

  _opt += Options::Binary; // only binary format supported!
139
  fileOptions_ = Options::Binary;
140

141
142
  if (!_is.good()) {
    omerr() << "[OMReader] : cannot read from stream " << std::endl;
143
144
145
146
147
148
    return false;
  }

  // Pass stream to read method, remember result
  bool result = read_binary(_is, _bi, _opt);

149
150
  if (result)
    _opt += Options::Binary;
Jan Möbius's avatar
Jan Möbius committed
151

152
153
  _opt = _opt & fileOptions_;

154
  return result;
Jan Möbius's avatar
Jan Möbius committed
155
156
157
158
159
160
}



//-----------------------------------------------------------------------------

161
bool _OMReader_::read_ascii(std::istream& /* _is */, BaseImporter& /* _bi */, Options& /* _opt */) const
Jan Möbius's avatar
Jan Möbius committed
162
163
164
165
166
167
168
169
{
  // not supported yet!
  return false;
}


//-----------------------------------------------------------------------------

170
bool _OMReader_::read_binary(std::istream& _is, BaseImporter& _bi, Options& _opt) const
Jan Möbius's avatar
Jan Möbius committed
171
172
173
{
  bool swap = _opt.check(Options::Swap) || (Endian::local() == Endian::MSB);

174
  // Initialize byte counter
175
  bytes_ = 0;
Jan Möbius's avatar
Jan Möbius committed
176

177
  bytes_ += restore(_is, header_, swap);
Jan Möbius's avatar
Jan Möbius committed
178
179


180
181
182
183
184
185
186
187
188
  if (header_.version_ > _OMWriter_::get_version())
  {
    omerr() << "File uses .om version " << OMFormat::as_string(header_.version_) << " but reader only "
            << "supports up to version " << OMFormat::as_string(_OMWriter_::get_version()) << ".\n"
            << "Please update your OpenMesh." << std::endl;
    return false;
  }


189
190
  while (!_is.eof()) {
    bytes_ += restore(_is, chunk_header_, swap);
Jan Möbius's avatar
Jan Möbius committed
191

192
    if (_is.eof())
Jan Möbius's avatar
Jan Möbius committed
193
194
195
      break;

    // Is this a named property restore the name
196
    if (chunk_header_.name_) {
Jan Möbius's avatar
Jan Möbius committed
197
      OMFormat::Chunk::PropertyName pn;
198
      bytes_ += restore(_is, property_name_, swap);
Jan Möbius's avatar
Jan Möbius committed
199
200
201
202
    }

    // Read in the property data. If it is an anonymous or unknown named
    // property, then skip data.
203
    switch (chunk_header_.entity_) {
204
      case OMFormat::Chunk::Entity_Vertex:
205
206
207
        if (!read_binary_vertex_chunk(_is, _bi, _opt, swap))
          return false;
        break;
Jan Möbius's avatar
Jan Möbius committed
208
      case OMFormat::Chunk::Entity_Face:
209
210
211
        if (!read_binary_face_chunk(_is, _bi, _opt, swap))
          return false;
        break;
Jan Möbius's avatar
Jan Möbius committed
212
      case OMFormat::Chunk::Entity_Edge:
213
214
215
        if (!read_binary_edge_chunk(_is, _bi, _opt, swap))
          return false;
        break;
Jan Möbius's avatar
Jan Möbius committed
216
      case OMFormat::Chunk::Entity_Halfedge:
217
218
219
        if (!read_binary_halfedge_chunk(_is, _bi, _opt, swap))
          return false;
        break;
Jan Möbius's avatar
Jan Möbius committed
220
      case OMFormat::Chunk::Entity_Mesh:
221
222
223
        if (!read_binary_mesh_chunk(_is, _bi, _opt, swap))
          return false;
        break;
224
225
      case OMFormat::Chunk::Entity_Sentinel:
        return true;
Jan Möbius's avatar
Jan Möbius committed
226
      default:
227
        return false;
Jan Möbius's avatar
Jan Möbius committed
228
    }
Jan Möbius's avatar
Jan Möbius committed
229

Jan Möbius's avatar
Jan Möbius committed
230
231
232
233
234
235
236
237
238
  }

  // File was successfully parsed.
  return true;
}


//-----------------------------------------------------------------------------

239
bool _OMReader_::can_u_read(const std::string& _filename) const
Jan Möbius's avatar
Jan Möbius committed
240
241
242
{
  // !!! Assuming BaseReader::can_u_parse( std::string& )
  // does not call BaseReader::read_magic()!!!
243
244
245
  if (this->BaseReader::can_u_read(_filename)) {
    std::ifstream ifile(_filename.c_str());
    if (ifile && can_u_read(ifile))
246
      return true;
Jan Möbius's avatar
Jan Möbius committed
247
248
249
250
251
  }
  return false;
}

//-----------------------------------------------------------------------------
252

253
bool _OMReader_::can_u_read(std::istream& _is) const
Jan Möbius's avatar
Jan Möbius committed
254
255
256
257
258
{
  std::vector<char> evt;
  evt.reserve(20);

  // read first 4 characters into a buffer
259
260
  while (evt.size() < 4)
    evt.push_back(static_cast<char>(_is.get()));
Jan Möbius's avatar
Jan Möbius committed
261

262
  // put back all read characters
Jan Möbius's avatar
Jan Möbius committed
263
  std::vector<char>::reverse_iterator it = evt.rbegin();
264
265
  while (it != evt.rend())
    _is.putback(*it++);
Jan Möbius's avatar
Jan Möbius committed
266
267

  // evaluate header information
268
  OMFormat::Header *hdr = (OMFormat::Header*) &evt[0];
Jan Möbius's avatar
Jan Möbius committed
269
270
271
272
273
274

  // first two characters must be 'OM'
  if (hdr->magic_[0] != 'O' || hdr->magic_[1] != 'M')
    return false;

  // 3rd characters defines the mesh type:
275
  switch (hdr->mesh_) {
Jan Möbius's avatar
Jan Möbius committed
276
277
278
279
280
281
282
    case 'T': // Triangle Mesh
    case 'Q': // Quad Mesh
    case 'P': // Polygonal Mesh
      break;
    default:  // ?
      return false;
  }
283

Jan Möbius's avatar
Jan Möbius committed
284
  // 4th characters encodes the version
285
  return supports(hdr->version_);
Jan Möbius's avatar
Jan Möbius committed
286
287
288
289
}

//-----------------------------------------------------------------------------

290
bool _OMReader_::supports(const OMFormat::uint8 /* version */) const
Jan Möbius's avatar
Jan Möbius committed
291
292
293
294
295
296
297
{
  return true;
}


//-----------------------------------------------------------------------------

298
bool _OMReader_::read_binary_vertex_chunk(std::istream &_is, BaseImporter &_bi, Options &_opt, bool _swap) const
Jan Möbius's avatar
Jan Möbius committed
299
300
301
{
  using OMFormat::Chunk;

302
  assert( chunk_header_.entity_ == Chunk::Entity_Vertex);
303

304
305
  OpenMesh::Vec3f v3f;
  OpenMesh::Vec2f v2f;
Jan Möbius's avatar
Jan Möbius committed
306
  OpenMesh::Vec3uc v3uc; // rgb
307
  OpenMesh::Attributes::StatusInfo status;
Jan Möbius's avatar
Jan Möbius committed
308
309
310

  OMFormat::Chunk::PropertyName custom_prop;

311
312
  size_t vidx = 0;
  switch (chunk_header_.type_) {
Jan Möbius's avatar
Jan Möbius committed
313
    case Chunk::Type_Pos:
314
      assert( OMFormat::dimensions(chunk_header_) == size_t(OpenMesh::Vec3f::dim()));
Jan Möbius's avatar
Jan Möbius committed
315

316
317
318
      for (; vidx < header_.n_vertices_ && !_is.eof(); ++vidx) {
        bytes_ += vector_restore(_is, v3f, _swap);
        _bi.add_vertex(v3f);
Jan Möbius's avatar
Jan Möbius committed
319
320
321
322
      }
      break;

    case Chunk::Type_Normal:
323
      assert( OMFormat::dimensions(chunk_header_) == size_t(OpenMesh::Vec3f::dim()));
Jan Möbius's avatar
Jan Möbius committed
324

325
      fileOptions_ += Options::VertexNormal;
326
327
      for (; vidx < header_.n_vertices_ && !_is.eof(); ++vidx) {
        bytes_ += vector_restore(_is, v3f, _swap);
328
        if (fileOptions_.vertex_has_normal() && _opt.vertex_has_normal())
329
          _bi.set_normal(VertexHandle(int(vidx)), v3f);
Jan Möbius's avatar
Jan Möbius committed
330
331
332
333
      }
      break;

    case Chunk::Type_Texcoord:
334
      assert( OMFormat::dimensions(chunk_header_) == size_t(OpenMesh::Vec2f::dim()));
Jan Möbius's avatar
Jan Möbius committed
335

336
      fileOptions_ += Options::VertexTexCoord;
337
338
      for (; vidx < header_.n_vertices_ && !_is.eof(); ++vidx) {
        bytes_ += vector_restore(_is, v2f, _swap);
339
        if (fileOptions_.vertex_has_texcoord() && _opt.vertex_has_texcoord())
340
          _bi.set_texcoord(VertexHandle(int(vidx)), v2f);
Jan Möbius's avatar
Jan Möbius committed
341
      }
342
      break;
Jan Möbius's avatar
Jan Möbius committed
343
344
345

    case Chunk::Type_Color:

346
      assert( OMFormat::dimensions(chunk_header_) == 3);
Jan Möbius's avatar
Jan Möbius committed
347

348
      fileOptions_ += Options::VertexColor;
349

350
351
      for (; vidx < header_.n_vertices_ && !_is.eof(); ++vidx) {
        bytes_ += vector_restore(_is, v3uc, _swap);
352
        if (fileOptions_.vertex_has_color() && _opt.vertex_has_color())
353
          _bi.set_color(VertexHandle(int(vidx)), v3uc);
Jan Möbius's avatar
Jan Möbius committed
354
355
356
      }
      break;

357
358
359
360
361
362
363
364
365
366
367
368
369
370
    case Chunk::Type_Status:
    {
      assert( OMFormat::dimensions(chunk_header_) == 1);

      fileOptions_ += Options::Status;

      for (; vidx < header_.n_vertices_ && !_is.eof(); ++vidx) {
        bytes_ += restore(_is, status, _swap);
        if (fileOptions_.vertex_has_status() && _opt.vertex_has_status())
          _bi.set_status(VertexHandle(int(vidx)), status);
      }
      break;
    }

Jan Möbius's avatar
Jan Möbius committed
371
    case Chunk::Type_Custom:
372

373
      bytes_ += restore_binary_custom_data(_is, _bi.kernel()->_get_vprop(property_name_), header_.n_vertices_, _swap);
Jan Möbius's avatar
Jan Möbius committed
374
375
376
377
378

      vidx = header_.n_vertices_;

      break;

379
380
381
382
383
384
385
386
387
388
389
390
391
    case Chunk::Type_Topology:
    {
      for (; vidx < header_.n_vertices_; ++vidx)
      {
        int halfedge_id;
        bytes_ += restore( _is, halfedge_id, OMFormat::Chunk::Integer_Size(chunk_header_.bits_), _swap );

        _bi.set_halfedge(VertexHandle(static_cast<int>(vidx)), HalfedgeHandle(halfedge_id));
      }
    }

      break;

Jan Möbius's avatar
Jan Möbius committed
392
393
394
    default: // skip unknown chunks
    {
      omerr() << "Unknown chunk type ignored!\n";
395
396
      size_t size_of = header_.n_vertices_ * OMFormat::vector_size(chunk_header_);
      _is.ignore(size_of);
Jan Möbius's avatar
Jan Möbius committed
397
398
399
400
401
402
403
404
405
406
407
      bytes_ += size_of;
    }
  }

  // all chunk data has been read..?!
  return vidx == header_.n_vertices_;
}


//-----------------------------------------------------------------------------

408
bool _OMReader_::read_binary_face_chunk(std::istream &_is, BaseImporter &_bi, Options &_opt, bool _swap) const
Jan Möbius's avatar
Jan Möbius committed
409
410
411
{
  using OMFormat::Chunk;

412
  assert( chunk_header_.entity_ == Chunk::Entity_Face);
Jan Möbius's avatar
Jan Möbius committed
413

414
415
  size_t fidx = 0;
  OpenMesh::Vec3f v3f;  // normal
Jan Möbius's avatar
Jan Möbius committed
416
  OpenMesh::Vec3uc v3uc; // rgb
417
  OpenMesh::Attributes::StatusInfo status;
Jan Möbius's avatar
Jan Möbius committed
418

419
  switch (chunk_header_.type_) {
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
    case Chunk::Type_Topology:
    {
      if (header_.version_ < OMFormat::mk_version(2,0))
      {
        // add faces based on vertex indices
        BaseImporter::VHandles vhandles;
        size_t nV = 0;
        size_t vidx = 0;

        switch (header_.mesh_) {
          case 'T':
            nV = 3;
            break;
          case 'Q':
            nV = 4;
            break;
        }
437

438
439
440
        for (; fidx < header_.n_faces_; ++fidx) {
          if (header_.mesh_ == 'P')
            bytes_ += restore(_is, nV, Chunk::Integer_16, _swap);
Jan Möbius's avatar
Jan Möbius committed
441

442
443
444
          vhandles.clear();
          for (size_t j = 0; j < nV; ++j) {
            bytes_ += restore(_is, vidx, Chunk::Integer_Size(chunk_header_.bits_), _swap);
Jan Möbius's avatar
Jan Möbius committed
445

446
447
            vhandles.push_back(VertexHandle(int(vidx)));
          }
Jan Möbius's avatar
Jan Möbius committed
448

449
450
451
452
453
          _bi.add_face(vhandles);
        }
      }
      else
      {
Max Lyon's avatar
Max Lyon committed
454
        // add faces by simply setting an incident halfedge
455
456
457
458
459
460
461
        for (; fidx < header_.n_faces_; ++fidx)
        {
          int halfedge_id;
          bytes_ += restore( _is, halfedge_id, OMFormat::Chunk::Integer_Size(chunk_header_.bits_), _swap );

          _bi.add_face(HalfedgeHandle(halfedge_id));
        }
Jan Möbius's avatar
Jan Möbius committed
462
463
      }
    }
464
      break;
Jan Möbius's avatar
Jan Möbius committed
465
466

    case Chunk::Type_Normal:
467
      assert( OMFormat::dimensions(chunk_header_) == size_t(OpenMesh::Vec3f::dim()));
Jan Möbius's avatar
Jan Möbius committed
468

469
      fileOptions_ += Options::FaceNormal;
470
471
      for (; fidx < header_.n_faces_ && !_is.eof(); ++fidx) {
        bytes_ += vector_restore(_is, v3f, _swap);
472
        if( fileOptions_.face_has_normal() && _opt.face_has_normal())
473
          _bi.set_normal(FaceHandle(int(fidx)), v3f);
Jan Möbius's avatar
Jan Möbius committed
474
475
476
477
478
      }
      break;

    case Chunk::Type_Color:

479
      assert( OMFormat::dimensions(chunk_header_) == 3);
Jan Möbius's avatar
Jan Möbius committed
480

481
      fileOptions_ += Options::FaceColor;
482
483
      for (; fidx < header_.n_faces_ && !_is.eof(); ++fidx) {
        bytes_ += vector_restore(_is, v3uc, _swap);
484
        if( fileOptions_.face_has_color() && _opt.face_has_color())
485
          _bi.set_color(FaceHandle(int(fidx)), v3uc);
Jan Möbius's avatar
Jan Möbius committed
486
487
      }
      break;
488
489
490
491
492
493
494
495
496
497
498
499
500
    case Chunk::Type_Status:
    {
      assert( OMFormat::dimensions(chunk_header_) == 1);

      fileOptions_ += Options::Status;

      for (; fidx < header_.n_faces_ && !_is.eof(); ++fidx) {
        bytes_ += restore(_is, status, _swap);
        if (fileOptions_.face_has_status() && _opt.face_has_status())
          _bi.set_status(FaceHandle(int(fidx)), status);
      }
      break;
    }
Jan Möbius's avatar
Jan Möbius committed
501
502

    case Chunk::Type_Custom:
503

504
      bytes_ += restore_binary_custom_data(_is, _bi.kernel()->_get_fprop(property_name_), header_.n_faces_, _swap);
Jan Möbius's avatar
Jan Möbius committed
505
506
507
508

      fidx = header_.n_faces_;

      break;
509

Jan Möbius's avatar
Jan Möbius committed
510
511
512
513
    default: // skip unknown chunks
    {
      omerr() << "Unknown chunk type ignore!\n";
      size_t size_of = OMFormat::chunk_data_size(header_, chunk_header_);
514
      _is.ignore(size_of);
515
      bytes_ += size_of;
Jan Möbius's avatar
Jan Möbius committed
516
517
518
519
520
521
522
523
    }
  }
  return fidx == header_.n_faces_;
}


//-----------------------------------------------------------------------------

524
bool _OMReader_::read_binary_edge_chunk(std::istream &_is, BaseImporter &_bi, Options &_opt, bool _swap) const
Jan Möbius's avatar
Jan Möbius committed
525
526
527
{
  using OMFormat::Chunk;

528
  assert( chunk_header_.entity_ == Chunk::Entity_Edge);
Jan Möbius's avatar
Jan Möbius committed
529

530
  size_t b = bytes_;
Jan Möbius's avatar
Jan Möbius committed
531

532
533
  OpenMesh::Attributes::StatusInfo status;

534
  switch (chunk_header_.type_) {
535
    case Chunk::Type_Custom:
Jan Möbius's avatar
Jan Möbius committed
536

537
      bytes_ += restore_binary_custom_data(_is, _bi.kernel()->_get_eprop(property_name_), header_.n_edges_, _swap);
Jan Möbius's avatar
Jan Möbius committed
538
539
540

      break;

541
542
543
544
545
546
    case Chunk::Type_Status:
    {
      assert( OMFormat::dimensions(chunk_header_) == 1);

      fileOptions_ += Options::Status;

Max Lyon's avatar
Max Lyon committed
547
      for (size_t eidx = 0; eidx < header_.n_edges_ && !_is.eof(); ++eidx) {
548
549
550
551
552
553
554
        bytes_ += restore(_is, status, _swap);
        if (fileOptions_.edge_has_status() && _opt.edge_has_status())
          _bi.set_status(EdgeHandle(int(eidx)), status);
      }
      break;
    }

Jan Möbius's avatar
Jan Möbius committed
555
556
557
    default:
      // skip unknown type
      size_t size_of = OMFormat::chunk_data_size(header_, chunk_header_);
558
      _is.ignore(size_of);
Jan Möbius's avatar
Jan Möbius committed
559
560
561
562
563
564
565
566
567
      bytes_ += size_of;
  }

  return b < bytes_;
}


//-----------------------------------------------------------------------------

568
bool _OMReader_::read_binary_halfedge_chunk(std::istream &_is, BaseImporter &_bi, Options & _opt, bool _swap) const
Jan Möbius's avatar
Jan Möbius committed
569
570
571
{
  using OMFormat::Chunk;

572
  assert( chunk_header_.entity_ == Chunk::Entity_Halfedge);
Jan Möbius's avatar
Jan Möbius committed
573
574

  size_t b = bytes_;
575
  OpenMesh::Attributes::StatusInfo status;
Jan Möbius's avatar
Jan Möbius committed
576

577
  switch (chunk_header_.type_) {
Jan Möbius's avatar
Jan Möbius committed
578
579
    case Chunk::Type_Custom:

580
      bytes_ += restore_binary_custom_data(_is, _bi.kernel()->_get_hprop(property_name_), 2 * header_.n_edges_, _swap);
Jan Möbius's avatar
Jan Möbius committed
581
582
      break;

583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
    case Chunk::Type_Topology:
    {
      std::vector<HalfedgeHandle> next_halfedges;
      for (size_t e_idx = 0; e_idx < header_.n_edges_; ++e_idx)
      {
        int next_id_0;
        int to_vertex_id_0;
        int face_id_0;
        bytes_ += restore( _is, next_id_0,      OMFormat::Chunk::Integer_Size(chunk_header_.bits_), _swap );
        bytes_ += restore( _is, to_vertex_id_0, OMFormat::Chunk::Integer_Size(chunk_header_.bits_), _swap );
        bytes_ += restore( _is, face_id_0,      OMFormat::Chunk::Integer_Size(chunk_header_.bits_), _swap );

        int next_id_1;
        int to_vertex_id_1;
        int face_id_1;
        bytes_ += restore( _is, next_id_1,      OMFormat::Chunk::Integer_Size(chunk_header_.bits_), _swap );
        bytes_ += restore( _is, to_vertex_id_1, OMFormat::Chunk::Integer_Size(chunk_header_.bits_), _swap );
        bytes_ += restore( _is, face_id_1,      OMFormat::Chunk::Integer_Size(chunk_header_.bits_), _swap );

        auto heh0 = _bi.add_edge(VertexHandle(to_vertex_id_1), VertexHandle(to_vertex_id_0));
        auto heh1 = HalfedgeHandle(heh0.idx() + 1);

        next_halfedges.push_back(HalfedgeHandle(next_id_0));
        next_halfedges.push_back(HalfedgeHandle(next_id_1));

        _bi.set_face(heh0, FaceHandle(face_id_0));
        _bi.set_face(heh1, FaceHandle(face_id_1));
      }

      for (size_t i = 0; i < next_halfedges.size(); ++i)
        _bi.set_next(HalfedgeHandle(static_cast<int>(i)), next_halfedges[i]);
    }

      break;

618
619
620
621
622
623
    case Chunk::Type_Status:
    {
      assert( OMFormat::dimensions(chunk_header_) == 1);

      fileOptions_ += Options::Status;

Max Lyon's avatar
Max Lyon committed
624
      for (size_t hidx = 0; hidx < header_.n_edges_ * 2 && !_is.eof(); ++hidx) {
625
626
627
628
629
630
631
        bytes_ += restore(_is, status, _swap);
        if (fileOptions_.halfedge_has_status() && _opt.halfedge_has_status())
          _bi.set_status(HalfedgeHandle(int(hidx)), status);
      }
      break;
    }

Jan Möbius's avatar
Jan Möbius committed
632
633
634
635
    default:
      // skip unknown chunk
      omerr() << "Unknown chunk type ignored!\n";
      size_t size_of = OMFormat::chunk_data_size(header_, chunk_header_);
636
      _is.ignore(size_of);
Jan Möbius's avatar
Jan Möbius committed
637
638
639
640
641
642
643
644
645
      bytes_ += size_of;
  }

  return b < bytes_;
}


//-----------------------------------------------------------------------------

646
bool _OMReader_::read_binary_mesh_chunk(std::istream &_is, BaseImporter &_bi, Options & /* _opt */, bool _swap) const
Jan Möbius's avatar
Jan Möbius committed
647
648
649
{
  using OMFormat::Chunk;

650
  assert( chunk_header_.entity_ == Chunk::Entity_Mesh);
Jan Möbius's avatar
Jan Möbius committed
651
652
653

  size_t b = bytes_;

654
  switch (chunk_header_.type_) {
Jan Möbius's avatar
Jan Möbius committed
655
    case Chunk::Type_Custom:
656

657
      bytes_ += restore_binary_custom_data(_is, _bi.kernel()->_get_mprop(property_name_), 1, _swap);
658

Jan Möbius's avatar
Jan Möbius committed
659
660
661
662
663
      break;

    default:
      // skip unknown chunk
      size_t size_of = OMFormat::chunk_data_size(header_, chunk_header_);
664
      _is.ignore(size_of);
Jan Möbius's avatar
Jan Möbius committed
665
666
667
668
669
670
671
672
673
674
      bytes_ += size_of;
  }

  return b < bytes_;
}


//-----------------------------------------------------------------------------


675
size_t _OMReader_::restore_binary_custom_data(std::istream& _is, BaseProperty* _bp, size_t _n_elem, bool _swap) const
676
{
677
  assert( !_bp || (_bp->name() == property_name_));
Jan Möbius's avatar
Jan Möbius committed
678
679
680

  using OMFormat::Chunk;

681
682
  size_t bytes = 0;
  Chunk::esize_t block_size;
Jan Möbius's avatar
Jan Möbius committed
683
684
  Chunk::PropertyName custom_prop;

685
  bytes += restore(_is, block_size, OMFormat::Chunk::Integer_32, _swap);
Jan Möbius's avatar
Jan Möbius committed
686

687
688
  if (_bp) {
    size_t n_bytes = _bp->size_of(_n_elem);
Jan Möbius's avatar
Jan Möbius committed
689

690
691
    if (((n_bytes == BaseProperty::UnknownSize) || (n_bytes == block_size))
        && (_bp->element_size() == BaseProperty::UnknownSize || (_n_elem * _bp->element_size() == block_size))) {
Jan Möbius's avatar
Jan Möbius committed
692
#if defined(OM_DEBUG)
Jan Möbius's avatar
Jan Möbius committed
693
      size_t b;
Jan Möbius's avatar
Jan Möbius committed
694
695
      bytes += (b=_bp->restore( _is, _swap ));
#else
696
      bytes += _bp->restore(_is, _swap);
Jan Möbius's avatar
Jan Möbius committed
697
#endif
698

Jan Möbius's avatar
Jan Möbius committed
699
700
701
#if defined(OM_DEBUG)
      assert( block_size == b );
#endif
702
703

      assert( block_size == _bp->size_of());
Jan Möbius's avatar
Jan Möbius committed
704
705

      block_size = 0;
706
707
    } else {
      omerr() << "Warning! Property " << _bp->name() << " not loaded: " << "Mismatching data sizes!n";
Jan Möbius's avatar
Jan Möbius committed
708
709
710
    }
  }

711
712
713
  if (block_size) {
    _is.ignore(block_size);
    bytes += block_size;
Jan Möbius's avatar
Jan Möbius committed
714
715
716
717
718
719
720
721
722
723
724
725
  }

  return bytes;
}


//-----------------------------------------------------------------------------

//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================