OMReader.cc 21.6 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
  OpenMesh::Vec3uc v3uc; // rgb
297
  OpenMesh::Attributes::StatusInfo status;
Jan Möbius's avatar
Jan Möbius committed
298
299
300

  OMFormat::Chunk::PropertyName custom_prop;

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

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

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

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

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

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

    case Chunk::Type_Color:

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

338
      fileOptions_ += Options::VertexColor;
339

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

347
348
349
350
351
352
353
354
355
356
357
358
359
360
    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
361
    case Chunk::Type_Custom:
362

363
      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
364
365
366
367
368

      vidx = header_.n_vertices_;

      break;

369
370
371
372
373
374
375
376
377
378
379
380
381
    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
382
383
384
    default: // skip unknown chunks
    {
      omerr() << "Unknown chunk type ignored!\n";
385
386
      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
387
388
389
390
391
392
393
394
395
396
397
      bytes_ += size_of;
    }
  }

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


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

398
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
399
400
401
{
  using OMFormat::Chunk;

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

404
405
  size_t fidx = 0;
  OpenMesh::Vec3f v3f;  // normal
Jan Möbius's avatar
Jan Möbius committed
406
  OpenMesh::Vec3uc v3uc; // rgb
407
  OpenMesh::Attributes::StatusInfo status;
Jan Möbius's avatar
Jan Möbius committed
408

409
  switch (chunk_header_.type_) {
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
    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;
        }
427

428
429
430
        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
431

432
433
434
          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
435

436
437
            vhandles.push_back(VertexHandle(int(vidx)));
          }
Jan Möbius's avatar
Jan Möbius committed
438

439
440
441
442
443
          _bi.add_face(vhandles);
        }
      }
      else
      {
Max Lyon's avatar
Max Lyon committed
444
        // add faces by simply setting an incident halfedge
445
446
447
448
449
450
451
        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
452
453
      }
    }
454
      break;
Jan Möbius's avatar
Jan Möbius committed
455
456

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

459
      fileOptions_ += Options::FaceNormal;
460
461
      for (; fidx < header_.n_faces_ && !_is.eof(); ++fidx) {
        bytes_ += vector_restore(_is, v3f, _swap);
462
        if( fileOptions_.face_has_normal() && _opt.face_has_normal())
463
          _bi.set_normal(FaceHandle(int(fidx)), v3f);
Jan Möbius's avatar
Jan Möbius committed
464
465
466
467
468
      }
      break;

    case Chunk::Type_Color:

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

471
      fileOptions_ += Options::FaceColor;
472
473
      for (; fidx < header_.n_faces_ && !_is.eof(); ++fidx) {
        bytes_ += vector_restore(_is, v3uc, _swap);
474
        if( fileOptions_.face_has_color() && _opt.face_has_color())
475
          _bi.set_color(FaceHandle(int(fidx)), v3uc);
Jan Möbius's avatar
Jan Möbius committed
476
477
      }
      break;
478
479
480
481
482
483
484
485
486
487
488
489
490
    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
491
492

    case Chunk::Type_Custom:
493

494
      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
495
496
497
498

      fidx = header_.n_faces_;

      break;
499

Jan Möbius's avatar
Jan Möbius committed
500
501
502
503
    default: // skip unknown chunks
    {
      omerr() << "Unknown chunk type ignore!\n";
      size_t size_of = OMFormat::chunk_data_size(header_, chunk_header_);
504
      _is.ignore(size_of);
505
      bytes_ += size_of;
Jan Möbius's avatar
Jan Möbius committed
506
507
508
509
510
511
512
513
    }
  }
  return fidx == header_.n_faces_;
}


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

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

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

520
  size_t b = bytes_;
Jan Möbius's avatar
Jan Möbius committed
521

522
523
524
  size_t eidx = 0;
  OpenMesh::Attributes::StatusInfo status;

525
  switch (chunk_header_.type_) {
526
    case Chunk::Type_Custom:
Jan Möbius's avatar
Jan Möbius committed
527

528
      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
529
530
531

      break;

532
533
534
535
536
537
538
539
540
541
542
543
544
545
    case Chunk::Type_Status:
    {
      assert( OMFormat::dimensions(chunk_header_) == 1);

      fileOptions_ += Options::Status;

      for (; eidx < header_.n_edges_ && !_is.eof(); ++eidx) {
        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
546
547
548
    default:
      // skip unknown type
      size_t size_of = OMFormat::chunk_data_size(header_, chunk_header_);
549
      _is.ignore(size_of);
Jan Möbius's avatar
Jan Möbius committed
550
551
552
553
554
555
556
557
558
      bytes_ += size_of;
  }

  return b < bytes_;
}


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

559
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
560
561
562
{
  using OMFormat::Chunk;

563
  assert( chunk_header_.entity_ == Chunk::Entity_Halfedge);
Jan Möbius's avatar
Jan Möbius committed
564
565

  size_t b = bytes_;
566
567
  size_t hidx = 0;
  OpenMesh::Attributes::StatusInfo status;
Jan Möbius's avatar
Jan Möbius committed
568

569
  switch (chunk_header_.type_) {
Jan Möbius's avatar
Jan Möbius committed
570
571
    case Chunk::Type_Custom:

572
      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
573
574
      break;

575
576
577
578
579
580
581
582
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
    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;

610
611
612
613
614
615
616
617
618
619
620
621
622
623
    case Chunk::Type_Status:
    {
      assert( OMFormat::dimensions(chunk_header_) == 1);

      fileOptions_ += Options::Status;

      for (; hidx < header_.n_edges_ * 2 && !_is.eof(); ++hidx) {
        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
624
625
626
627
    default:
      // skip unknown chunk
      omerr() << "Unknown chunk type ignored!\n";
      size_t size_of = OMFormat::chunk_data_size(header_, chunk_header_);
628
      _is.ignore(size_of);
Jan Möbius's avatar
Jan Möbius committed
629
630
631
632
633
634
635
636
637
      bytes_ += size_of;
  }

  return b < bytes_;
}


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

638
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
639
640
641
{
  using OMFormat::Chunk;

642
  assert( chunk_header_.entity_ == Chunk::Entity_Mesh);
Jan Möbius's avatar
Jan Möbius committed
643
644
645

  size_t b = bytes_;

646
  switch (chunk_header_.type_) {
Jan Möbius's avatar
Jan Möbius committed
647
    case Chunk::Type_Custom:
648

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

Jan Möbius's avatar
Jan Möbius committed
651
652
653
654
655
      break;

    default:
      // skip unknown chunk
      size_t size_of = OMFormat::chunk_data_size(header_, chunk_header_);
656
      _is.ignore(size_of);
Jan Möbius's avatar
Jan Möbius committed
657
658
659
660
661
662
663
664
665
666
      bytes_ += size_of;
  }

  return b < bytes_;
}


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


667
size_t _OMReader_::restore_binary_custom_data(std::istream& _is, BaseProperty* _bp, size_t _n_elem, bool _swap) const
668
{
669
  assert( !_bp || (_bp->name() == property_name_));
Jan Möbius's avatar
Jan Möbius committed
670
671
672

  using OMFormat::Chunk;

673
674
  size_t bytes = 0;
  Chunk::esize_t block_size;
Jan Möbius's avatar
Jan Möbius committed
675
676
  Chunk::PropertyName custom_prop;

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

679
680
  if (_bp) {
    size_t n_bytes = _bp->size_of(_n_elem);
Jan Möbius's avatar
Jan Möbius committed
681

682
683
    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
684
#if defined(OM_DEBUG)
Jan Möbius's avatar
Jan Möbius committed
685
      size_t b;
Jan Möbius's avatar
Jan Möbius committed
686
687
      bytes += (b=_bp->restore( _is, _swap ));
#else
688
      bytes += _bp->restore(_is, _swap);
Jan Möbius's avatar
Jan Möbius committed
689
#endif
690

Jan Möbius's avatar
Jan Möbius committed
691
692
693
#if defined(OM_DEBUG)
      assert( block_size == b );
#endif
694
695

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

      block_size = 0;
698
699
    } else {
      omerr() << "Warning! Property " << _bp->name() << " not loaded: " << "Mismatching data sizes!n";
Jan Möbius's avatar
Jan Möbius committed
700
701
702
    }
  }

703
704
705
  if (block_size) {
    _is.ignore(block_size);
    bytes += block_size;
Jan Möbius's avatar
Jan Möbius committed
706
707
708
709
710
711
712
713
714
715
716
717
  }

  return bytes;
}


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

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