OMReader.cc 21.7 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

Jan Möbius's avatar
Jan Möbius committed
43 44 45 46 47 48


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


//STL
49 50
#include <vector>
#include <istream>
Jan Möbius's avatar
Jan Möbius committed
51 52 53 54 55 56 57 58
#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>
59
#include <OpenMesh/Core/IO/writer/OMWriter.hh>
Jan Möbius's avatar
Jan Möbius committed
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82


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


namespace OpenMesh {
namespace IO {


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


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



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


_OMReader_::_OMReader_()
{
83
  IOManager().register_module(this);
Jan Möbius's avatar
Jan Möbius committed
84 85 86 87 88 89
}


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


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

  _opt += Options::Binary; // only binary format supported!
97
  fileOptions_ = Options::Binary;
Jan Möbius's avatar
Jan Möbius committed
98 99

  // Open file
100
  std::ifstream ifs(_filename.c_str(), std::ios::binary);
101 102 103 104 105 106 107

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

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

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

Jan Möbius's avatar
Jan Möbius committed
116 117
  // close input stream
  ifs.close();
118

119 120
  _opt = _opt & fileOptions_;

Jan Möbius's avatar
Jan Möbius committed
121 122 123 124 125 126
  return result;
}

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


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

  _opt += Options::Binary; // only binary format supported!
134
  fileOptions_ = Options::Binary;
135

136 137
  if (!_is.good()) {
    omerr() << "[OMReader] : cannot read from stream " << std::endl;
138 139 140 141 142 143
    return false;
  }

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

144 145
  if (result)
    _opt += Options::Binary;
Jan Möbius's avatar
Jan Möbius committed
146

147 148
  _opt = _opt & fileOptions_;

149
  return result;
Jan Möbius's avatar
Jan Möbius committed
150 151 152 153 154 155
}



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

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


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

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

169
  // Initialize byte counter
170
  bytes_ = 0;
Jan Möbius's avatar
Jan Möbius committed
171

172
  bytes_ += restore(_is, header_, swap);
Jan Möbius's avatar
Jan Möbius committed
173 174


175 176 177 178 179 180 181 182 183
  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;
  }


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

187
    if (_is.eof())
Jan Möbius's avatar
Jan Möbius committed
188 189 190
      break;

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

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

Jan Möbius's avatar
Jan Möbius committed
225 226 227 228 229 230 231 232 233
  }

  // File was successfully parsed.
  return true;
}


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

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

//-----------------------------------------------------------------------------
247

248
bool _OMReader_::can_u_read(std::istream& _is) const
Jan Möbius's avatar
Jan Möbius committed
249 250 251 252 253
{
  std::vector<char> evt;
  evt.reserve(20);

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

257
  // put back all read characters
Jan Möbius's avatar
Jan Möbius committed
258
  std::vector<char>::reverse_iterator it = evt.rbegin();
259 260
  while (it != evt.rend())
    _is.putback(*it++);
Jan Möbius's avatar
Jan Möbius committed
261 262

  // evaluate header information
263
  OMFormat::Header *hdr = (OMFormat::Header*) &evt[0];
Jan Möbius's avatar
Jan Möbius committed
264 265 266 267 268 269

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

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

Jan Möbius's avatar
Jan Möbius committed
279
  // 4th characters encodes the version
280
  return supports(hdr->version_);
Jan Möbius's avatar
Jan Möbius committed
281 282 283 284
}

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

285
bool _OMReader_::supports(const OMFormat::uint8 /* version */) const
Jan Möbius's avatar
Jan Möbius committed
286 287 288 289 290 291 292
{
  return true;
}


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

293
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
294 295 296
{
  using OMFormat::Chunk;

297
  assert( chunk_header_.entity_ == Chunk::Entity_Vertex);
298

299 300
  OpenMesh::Vec3f v3f;
  OpenMesh::Vec2f v2f;
Jan Möbius's avatar
Jan Möbius committed
301
  OpenMesh::Vec3uc v3uc; // rgb
302
  OpenMesh::Attributes::StatusInfo status;
Jan Möbius's avatar
Jan Möbius committed
303 304 305

  OMFormat::Chunk::PropertyName custom_prop;

306 307
  size_t vidx = 0;
  switch (chunk_header_.type_) {
Jan Möbius's avatar
Jan Möbius committed
308
    case Chunk::Type_Pos:
309
      assert( OMFormat::dimensions(chunk_header_) == size_t(OpenMesh::Vec3f::dim()));
Jan Möbius's avatar
Jan Möbius committed
310

311 312 313
      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
314 315 316 317
      }
      break;

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

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

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

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

    case Chunk::Type_Color:

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

343
      fileOptions_ += Options::VertexColor;
344

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

352 353 354 355 356 357 358 359 360 361 362 363 364 365
    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
366
    case Chunk::Type_Custom:
367

368
      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
369 370 371 372 373

      vidx = header_.n_vertices_;

      break;

374 375 376 377
    case Chunk::Type_Topology:
    {
      for (; vidx < header_.n_vertices_; ++vidx)
      {
Jan Möbius's avatar
Jan Möbius committed
378
        int halfedge_id = 0;
379 380 381 382 383 384 385 386
        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
387 388 389
    default: // skip unknown chunks
    {
      omerr() << "Unknown chunk type ignored!\n";
Jan Möbius's avatar
Jan Möbius committed
390 391 392 393
      size_t chunk_size = header_.n_vertices_ * OMFormat::vector_size(chunk_header_);
      _is.ignore(chunk_size);
      bytes_ += chunk_size;
      break;
Jan Möbius's avatar
Jan Möbius committed
394
    }
Jan Möbius's avatar
Jan Möbius committed
395

Jan Möbius's avatar
Jan Möbius committed
396 397 398 399 400 401 402 403 404
  }

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


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

405
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
406 407 408
{
  using OMFormat::Chunk;

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

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

416
  switch (chunk_header_.type_) {
417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433
    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;
        }
434

435 436 437
        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
438

439 440 441
          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
442

443 444
            vhandles.push_back(VertexHandle(int(vidx)));
          }
Jan Möbius's avatar
Jan Möbius committed
445

446 447 448 449 450
          _bi.add_face(vhandles);
        }
      }
      else
      {
Max Lyon's avatar
Max Lyon committed
451
        // add faces by simply setting an incident halfedge
452 453
        for (; fidx < header_.n_faces_; ++fidx)
        {
Jan Möbius's avatar
Jan Möbius committed
454
          int halfedge_id = 0;
455 456 457 458
          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
459 460
      }
    }
461
      break;
Jan Möbius's avatar
Jan Möbius committed
462 463

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

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

    case Chunk::Type_Color:

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

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

    case Chunk::Type_Custom:
500

501
      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
502 503 504 505

      fidx = header_.n_faces_;

      break;
506

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


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

521
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
522 523 524
{
  using OMFormat::Chunk;

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

527
  size_t b = bytes_;
Jan Möbius's avatar
Jan Möbius committed
528

529 530
  OpenMesh::Attributes::StatusInfo status;

531
  switch (chunk_header_.type_) {
532
    case Chunk::Type_Custom:
Jan Möbius's avatar
Jan Möbius committed
533

534
      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
535 536 537

      break;

538 539 540 541 542 543
    case Chunk::Type_Status:
    {
      assert( OMFormat::dimensions(chunk_header_) == 1);

      fileOptions_ += Options::Status;

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

  return b < bytes_;
}


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

565
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
566 567 568
{
  using OMFormat::Chunk;

569
  assert( chunk_header_.entity_ == Chunk::Entity_Halfedge);
Jan Möbius's avatar
Jan Möbius committed
570 571

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

574
  switch (chunk_header_.type_) {
Jan Möbius's avatar
Jan Möbius committed
575 576
    case Chunk::Type_Custom:

577
      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
578 579
      break;

580 581 582 583 584
    case Chunk::Type_Topology:
    {
      std::vector<HalfedgeHandle> next_halfedges;
      for (size_t e_idx = 0; e_idx < header_.n_edges_; ++e_idx)
      {
Jan Möbius's avatar
Jan Möbius committed
585 586 587
        int next_id_0      = -1;
        int to_vertex_id_0 = -1;
        int face_id_0      = -1; 
588 589 590 591
        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 );

Jan Möbius's avatar
Jan Möbius committed
592 593 594
        int next_id_1      = -1;
        int to_vertex_id_1 = -1;
        int face_id_1      = -1;
595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614
        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;

615 616 617 618 619 620
    case Chunk::Type_Status:
    {
      assert( OMFormat::dimensions(chunk_header_) == 1);

      fileOptions_ += Options::Status;

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

  return b < bytes_;
}


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

643
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
644 645 646
{
  using OMFormat::Chunk;

647
  assert( chunk_header_.entity_ == Chunk::Entity_Mesh);
Jan Möbius's avatar
Jan Möbius committed
648 649 650

  size_t b = bytes_;

651
  switch (chunk_header_.type_) {
Jan Möbius's avatar
Jan Möbius committed
652
    case Chunk::Type_Custom:
653

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

Jan Möbius's avatar
Jan Möbius committed
656 657 658 659
      break;

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

  return b < bytes_;
}


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


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

  using OMFormat::Chunk;

678 679
  size_t bytes = 0;
  Chunk::esize_t block_size;
Jan Möbius's avatar
Jan Möbius committed
680 681
  Chunk::PropertyName custom_prop;

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

684 685
  if (_bp) {
    size_t n_bytes = _bp->size_of(_n_elem);
Jan Möbius's avatar
Jan Möbius committed
686

687 688
    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
689
#if defined(OM_DEBUG)
Jan Möbius's avatar
Jan Möbius committed
690
      size_t b;
Jan Möbius's avatar
Jan Möbius committed
691 692
      bytes += (b=_bp->restore( _is, _swap ));
#else
693
      bytes += _bp->restore(_is, _swap);
Jan Möbius's avatar
Jan Möbius committed
694
#endif
695

Jan Möbius's avatar
Jan Möbius committed
696 697 698
#if defined(OM_DEBUG)
      assert( block_size == b );
#endif
699 700

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

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

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

  return bytes;
}


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

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