OMReader.cc 19.8 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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#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>


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


namespace OpenMesh {
namespace IO {


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


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



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


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


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


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

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

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

  /* 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);

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

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

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

123
124
  _opt = _opt & fileOptions_;

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

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


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

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

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

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

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

151
152
  _opt = _opt & fileOptions_;

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



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

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


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

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

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

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


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

182
    if (_is.eof())
Jan Möbius's avatar
Jan Möbius committed
183
184
185
      break;

    // Is this a named property restore the name
186
    if (chunk_header_.name_) {
Jan Möbius's avatar
Jan Möbius committed
187
      OMFormat::Chunk::PropertyName pn;
188
      bytes_ += restore(_is, property_name_, swap);
Jan Möbius's avatar
Jan Möbius committed
189
190
191
192
    }

    // Read in the property data. If it is an anonymous or unknown named
    // property, then skip data.
193
    switch (chunk_header_.entity_) {
194
      case OMFormat::Chunk::Entity_Vertex:
195
196
197
        if (!read_binary_vertex_chunk(_is, _bi, _opt, swap))
          return false;
        break;
Jan Möbius's avatar
Jan Möbius committed
198
      case OMFormat::Chunk::Entity_Face:
199
200
201
        if (!read_binary_face_chunk(_is, _bi, _opt, swap))
          return false;
        break;
Jan Möbius's avatar
Jan Möbius committed
202
      case OMFormat::Chunk::Entity_Edge:
203
204
205
        if (!read_binary_edge_chunk(_is, _bi, _opt, swap))
          return false;
        break;
Jan Möbius's avatar
Jan Möbius committed
206
      case OMFormat::Chunk::Entity_Halfedge:
207
208
209
        if (!read_binary_halfedge_chunk(_is, _bi, _opt, swap))
          return false;
        break;
Jan Möbius's avatar
Jan Möbius committed
210
      case OMFormat::Chunk::Entity_Mesh:
211
212
213
        if (!read_binary_mesh_chunk(_is, _bi, _opt, swap))
          return false;
        break;
214
215
      case OMFormat::Chunk::Entity_Sentinel:
        return true;
Jan Möbius's avatar
Jan Möbius committed
216
      default:
217
        return false;
Jan Möbius's avatar
Jan Möbius committed
218
    }
Jan Möbius's avatar
Jan Möbius committed
219

Jan Möbius's avatar
Jan Möbius committed
220
221
222
223
224
225
226
227
228
  }

  // File was successfully parsed.
  return true;
}


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

229
bool _OMReader_::can_u_read(const std::string& _filename) const
Jan Möbius's avatar
Jan Möbius committed
230
231
232
{
  // !!! Assuming BaseReader::can_u_parse( std::string& )
  // does not call BaseReader::read_magic()!!!
233
234
235
  if (this->BaseReader::can_u_read(_filename)) {
    std::ifstream ifile(_filename.c_str());
    if (ifile && can_u_read(ifile))
236
      return true;
Jan Möbius's avatar
Jan Möbius committed
237
238
239
240
241
  }
  return false;
}

//-----------------------------------------------------------------------------
242

243
bool _OMReader_::can_u_read(std::istream& _is) const
Jan Möbius's avatar
Jan Möbius committed
244
245
246
247
248
{
  std::vector<char> evt;
  evt.reserve(20);

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

252
  // put back all read characters
Jan Möbius's avatar
Jan Möbius committed
253
  std::vector<char>::reverse_iterator it = evt.rbegin();
254
255
  while (it != evt.rend())
    _is.putback(*it++);
Jan Möbius's avatar
Jan Möbius committed
256
257

  // evaluate header information
258
  OMFormat::Header *hdr = (OMFormat::Header*) &evt[0];
Jan Möbius's avatar
Jan Möbius committed
259
260
261
262
263
264

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

  // 3rd characters defines the mesh type:
265
  switch (hdr->mesh_) {
Jan Möbius's avatar
Jan Möbius committed
266
267
268
269
270
271
272
    case 'T': // Triangle Mesh
    case 'Q': // Quad Mesh
    case 'P': // Polygonal Mesh
      break;
    default:  // ?
      return false;
  }
273

Jan Möbius's avatar
Jan Möbius committed
274
  // 4th characters encodes the version
275
  return supports(hdr->version_);
Jan Möbius's avatar
Jan Möbius committed
276
277
278
279
}

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

280
bool _OMReader_::supports(const OMFormat::uint8 /* version */) const
Jan Möbius's avatar
Jan Möbius committed
281
282
283
284
285
286
287
{
  return true;
}


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

288
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
289
290
291
{
  using OMFormat::Chunk;

292
  assert( chunk_header_.entity_ == Chunk::Entity_Vertex);
293

294
295
  OpenMesh::Vec3f v3f;
  OpenMesh::Vec2f v2f;
Jan Möbius's avatar
Jan Möbius committed
296
297
298
299
  OpenMesh::Vec3uc v3uc; // rgb

  OMFormat::Chunk::PropertyName custom_prop;

300
301
  size_t vidx = 0;
  switch (chunk_header_.type_) {
Jan Möbius's avatar
Jan Möbius committed
302
    case Chunk::Type_Pos:
303
      assert( OMFormat::dimensions(chunk_header_) == size_t(OpenMesh::Vec3f::dim()));
Jan Möbius's avatar
Jan Möbius committed
304

305
306
307
      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
308
309
310
311
      }
      break;

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

314
      fileOptions_ += Options::VertexNormal;
315
316
      for (; vidx < header_.n_vertices_ && !_is.eof(); ++vidx) {
        bytes_ += vector_restore(_is, v3f, _swap);
317
        if (fileOptions_.vertex_has_normal() && _opt.vertex_has_normal())
318
          _bi.set_normal(VertexHandle(int(vidx)), v3f);
Jan Möbius's avatar
Jan Möbius committed
319
320
321
322
      }
      break;

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

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

    case Chunk::Type_Color:

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

337
      fileOptions_ += Options::VertexColor;
338

339
340
      for (; vidx < header_.n_vertices_ && !_is.eof(); ++vidx) {
        bytes_ += vector_restore(_is, v3uc, _swap);
341
        if (fileOptions_.vertex_has_color() && _opt.vertex_has_color())
342
          _bi.set_color(VertexHandle(int(vidx)), v3uc);
Jan Möbius's avatar
Jan Möbius committed
343
344
345
346
      }
      break;

    case Chunk::Type_Custom:
347

348
      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
349
350
351
352
353

      vidx = header_.n_vertices_;

      break;

354
355
356
357
358
359
360
361
362
363
364
365
366
    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
367
368
369
    default: // skip unknown chunks
    {
      omerr() << "Unknown chunk type ignored!\n";
370
371
      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
372
373
374
375
376
377
378
379
380
381
382
      bytes_ += size_of;
    }
  }

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


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

383
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
384
385
386
{
  using OMFormat::Chunk;

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

389
390
  size_t fidx = 0;
  OpenMesh::Vec3f v3f;  // normal
Jan Möbius's avatar
Jan Möbius committed
391
392
  OpenMesh::Vec3uc v3uc; // rgb

393
  switch (chunk_header_.type_) {
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
    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;
        }
411

412
413
414
        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
415

416
417
418
          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
419

420
421
            vhandles.push_back(VertexHandle(int(vidx)));
          }
Jan Möbius's avatar
Jan Möbius committed
422

423
424
425
426
427
428
429
430
431
432
433
434
435
          _bi.add_face(vhandles);
        }
      }
      else
      {
        // add faces by simple setting an incident face
        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
436
437
      }
    }
438
      break;
Jan Möbius's avatar
Jan Möbius committed
439
440

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

443
      fileOptions_ += Options::FaceNormal;
444
445
      for (; fidx < header_.n_faces_ && !_is.eof(); ++fidx) {
        bytes_ += vector_restore(_is, v3f, _swap);
446
        if( fileOptions_.face_has_normal() && _opt.face_has_normal())
447
          _bi.set_normal(FaceHandle(int(fidx)), v3f);
Jan Möbius's avatar
Jan Möbius committed
448
449
450
451
452
      }
      break;

    case Chunk::Type_Color:

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

455
      fileOptions_ += Options::FaceColor;
456
457
      for (; fidx < header_.n_faces_ && !_is.eof(); ++fidx) {
        bytes_ += vector_restore(_is, v3uc, _swap);
458
        if( fileOptions_.face_has_color() && _opt.face_has_color())
459
          _bi.set_color(FaceHandle(int(fidx)), v3uc);
Jan Möbius's avatar
Jan Möbius committed
460
461
462
463
      }
      break;

    case Chunk::Type_Custom:
464

465
      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
466
467
468
469

      fidx = header_.n_faces_;

      break;
470

Jan Möbius's avatar
Jan Möbius committed
471
472
473
474
    default: // skip unknown chunks
    {
      omerr() << "Unknown chunk type ignore!\n";
      size_t size_of = OMFormat::chunk_data_size(header_, chunk_header_);
475
      _is.ignore(size_of);
476
      bytes_ += size_of;
Jan Möbius's avatar
Jan Möbius committed
477
478
479
480
481
482
483
484
    }
  }
  return fidx == header_.n_faces_;
}


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

485
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
486
487
488
{
  using OMFormat::Chunk;

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

491
  size_t b = bytes_;
Jan Möbius's avatar
Jan Möbius committed
492

493
  switch (chunk_header_.type_) {
494
    case Chunk::Type_Custom:
Jan Möbius's avatar
Jan Möbius committed
495

496
      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
497
498
499
500
501
502

      break;

    default:
      // skip unknown type
      size_t size_of = OMFormat::chunk_data_size(header_, chunk_header_);
503
      _is.ignore(size_of);
Jan Möbius's avatar
Jan Möbius committed
504
505
506
507
508
509
510
511
512
      bytes_ += size_of;
  }

  return b < bytes_;
}


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

513
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
514
515
516
{
  using OMFormat::Chunk;

517
  assert( chunk_header_.entity_ == Chunk::Entity_Halfedge);
Jan Möbius's avatar
Jan Möbius committed
518
519
520

  size_t b = bytes_;

521
  switch (chunk_header_.type_) {
Jan Möbius's avatar
Jan Möbius committed
522
523
    case Chunk::Type_Custom:

524
      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
525
526
      break;

527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
    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;

Jan Möbius's avatar
Jan Möbius committed
562
563
564
565
    default:
      // skip unknown chunk
      omerr() << "Unknown chunk type ignored!\n";
      size_t size_of = OMFormat::chunk_data_size(header_, chunk_header_);
566
      _is.ignore(size_of);
Jan Möbius's avatar
Jan Möbius committed
567
568
569
570
571
572
573
574
575
      bytes_ += size_of;
  }

  return b < bytes_;
}


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

576
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
577
578
579
{
  using OMFormat::Chunk;

580
  assert( chunk_header_.entity_ == Chunk::Entity_Mesh);
Jan Möbius's avatar
Jan Möbius committed
581
582
583

  size_t b = bytes_;

584
  switch (chunk_header_.type_) {
Jan Möbius's avatar
Jan Möbius committed
585
    case Chunk::Type_Custom:
586

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

Jan Möbius's avatar
Jan Möbius committed
589
590
591
592
593
      break;

    default:
      // skip unknown chunk
      size_t size_of = OMFormat::chunk_data_size(header_, chunk_header_);
594
      _is.ignore(size_of);
Jan Möbius's avatar
Jan Möbius committed
595
596
597
598
599
600
601
602
603
604
      bytes_ += size_of;
  }

  return b < bytes_;
}


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


605
size_t _OMReader_::restore_binary_custom_data(std::istream& _is, BaseProperty* _bp, size_t _n_elem, bool _swap) const
606
{
607
  assert( !_bp || (_bp->name() == property_name_));
Jan Möbius's avatar
Jan Möbius committed
608
609
610

  using OMFormat::Chunk;

611
612
  size_t bytes = 0;
  Chunk::esize_t block_size;
Jan Möbius's avatar
Jan Möbius committed
613
614
  Chunk::PropertyName custom_prop;

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

617
618
  if (_bp) {
    size_t n_bytes = _bp->size_of(_n_elem);
Jan Möbius's avatar
Jan Möbius committed
619

620
621
    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
622
#if defined(OM_DEBUG)
Jan Möbius's avatar
Jan Möbius committed
623
      size_t b;
Jan Möbius's avatar
Jan Möbius committed
624
625
      bytes += (b=_bp->restore( _is, _swap ));
#else
626
      bytes += _bp->restore(_is, _swap);
Jan Möbius's avatar
Jan Möbius committed
627
#endif
628

Jan Möbius's avatar
Jan Möbius committed
629
630
631
#if defined(OM_DEBUG)
      assert( block_size == b );
#endif
632
633

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

      block_size = 0;
636
637
    } else {
      omerr() << "Warning! Property " << _bp->name() << " not loaded: " << "Mismatching data sizes!n";
Jan Möbius's avatar
Jan Möbius committed
638
639
640
    }
  }

641
642
643
  if (block_size) {
    _is.ignore(block_size);
    bytes += block_size;
Jan Möbius's avatar
Jan Möbius committed
644
645
646
647
648
649
650
651
652
653
654
655
  }

  return bytes;
}


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

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