2015-04-28 11:54:17 +00:00
|
|
|
/* ========================================================================= *
|
2009-02-06 13:37:46 +00:00
|
|
|
* *
|
|
|
|
|
* OpenMesh *
|
2015-04-28 11:33:32 +00:00
|
|
|
* Copyright (c) 2001-2015, RWTH-Aachen University *
|
2015-04-28 13:07:46 +00:00
|
|
|
* Department of Computer Graphics and Multimedia *
|
2015-04-28 11:33:32 +00:00
|
|
|
* All rights reserved. *
|
|
|
|
|
* www.openmesh.org *
|
2009-02-06 13:37:46 +00:00
|
|
|
* *
|
2009-11-17 13:54:16 +00:00
|
|
|
*---------------------------------------------------------------------------*
|
2015-04-28 11:33:32 +00:00
|
|
|
* This file is part of OpenMesh. *
|
|
|
|
|
*---------------------------------------------------------------------------*
|
2009-06-04 08:46:29 +00:00
|
|
|
* *
|
2015-04-28 11:33:32 +00:00
|
|
|
* 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. *
|
2015-04-28 11:54:17 +00:00
|
|
|
* *
|
|
|
|
|
* ========================================================================= */
|
2009-06-04 08:46:29 +00:00
|
|
|
|
2019-01-15 11:21:12 +01:00
|
|
|
|
2009-02-06 13:37:46 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
//== INCLUDES =================================================================
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//STL
|
2015-06-09 08:58:41 +00:00
|
|
|
#include <vector>
|
|
|
|
|
#include <istream>
|
2009-02-06 13:37:46 +00:00
|
|
|
#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>
|
2018-10-23 11:21:01 +02:00
|
|
|
#include <OpenMesh/Core/IO/writer/OMWriter.hh>
|
2020-11-26 17:51:43 +01:00
|
|
|
#include <OpenMesh/Core/Utils/typename.hh>
|
|
|
|
|
|
2020-12-21 15:22:46 +01:00
|
|
|
#include <OpenMesh/Core/Utils/PropertyCreator.hh>
|
|
|
|
|
|
2009-02-06 13:37:46 +00:00
|
|
|
//=== NAMESPACES ==============================================================
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace OpenMesh {
|
|
|
|
|
namespace IO {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//=== INSTANCIATE =============================================================
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// register the OMReader singleton with MeshReader
|
|
|
|
|
_OMReader_ __OMReaderInstance;
|
|
|
|
|
_OMReader_& OMReader() { return __OMReaderInstance; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//=== IMPLEMENTATION ==========================================================
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_OMReader_::_OMReader_()
|
|
|
|
|
{
|
2009-11-17 13:54:16 +00:00
|
|
|
IOManager().register_module(this);
|
2009-02-06 13:37:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
2012-05-22 09:15:15 +00:00
|
|
|
bool _OMReader_::read(const std::string& _filename, BaseImporter& _bi, Options& _opt)
|
2009-02-06 13:37:46 +00:00
|
|
|
{
|
|
|
|
|
// check whether importer can give us an OpenMesh BaseKernel
|
2012-05-22 09:15:15 +00:00
|
|
|
if (!_bi.kernel())
|
|
|
|
|
return false;
|
2009-02-06 13:37:46 +00:00
|
|
|
|
|
|
|
|
_opt += Options::Binary; // only binary format supported!
|
2012-10-08 13:25:36 +00:00
|
|
|
fileOptions_ = Options::Binary;
|
2009-02-06 13:37:46 +00:00
|
|
|
|
|
|
|
|
// Open file
|
2012-05-22 09:15:15 +00:00
|
|
|
std::ifstream ifs(_filename.c_str(), std::ios::binary);
|
2013-09-17 13:09:19 +00:00
|
|
|
|
|
|
|
|
/* 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);
|
|
|
|
|
|
2012-05-22 09:15:15 +00:00
|
|
|
if (!ifs.is_open() || !ifs.good()) {
|
|
|
|
|
omerr() << "[OMReader] : cannot not open file " << _filename << std::endl;
|
2009-02-06 13:37:46 +00:00
|
|
|
return false;
|
|
|
|
|
}
|
2009-11-17 13:54:16 +00:00
|
|
|
|
2009-02-06 13:37:46 +00:00
|
|
|
// Pass stream to read method, remember result
|
|
|
|
|
bool result = read(ifs, _bi, _opt);
|
2009-11-17 13:54:16 +00:00
|
|
|
|
2009-02-06 13:37:46 +00:00
|
|
|
// close input stream
|
|
|
|
|
ifs.close();
|
2009-11-17 13:54:16 +00:00
|
|
|
|
2012-10-08 13:25:36 +00:00
|
|
|
_opt = _opt & fileOptions_;
|
|
|
|
|
|
2009-02-06 13:37:46 +00:00
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
2012-05-22 09:15:15 +00:00
|
|
|
bool _OMReader_::read(std::istream& _is, BaseImporter& _bi, Options& _opt)
|
2009-02-06 13:37:46 +00:00
|
|
|
{
|
2009-11-17 13:54:16 +00:00
|
|
|
// check whether importer can give us an OpenMesh BaseKernel
|
2012-05-22 09:15:15 +00:00
|
|
|
if (!_bi.kernel())
|
|
|
|
|
return false;
|
2009-11-17 13:54:16 +00:00
|
|
|
|
|
|
|
|
_opt += Options::Binary; // only binary format supported!
|
2012-10-08 13:25:36 +00:00
|
|
|
fileOptions_ = Options::Binary;
|
2009-11-17 13:54:16 +00:00
|
|
|
|
2012-05-22 09:15:15 +00:00
|
|
|
if (!_is.good()) {
|
|
|
|
|
omerr() << "[OMReader] : cannot read from stream " << std::endl;
|
2009-11-17 13:54:16 +00:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Pass stream to read method, remember result
|
|
|
|
|
bool result = read_binary(_is, _bi, _opt);
|
|
|
|
|
|
2012-05-22 09:15:15 +00:00
|
|
|
if (result)
|
|
|
|
|
_opt += Options::Binary;
|
2009-02-06 13:37:46 +00:00
|
|
|
|
2012-10-08 13:25:36 +00:00
|
|
|
_opt = _opt & fileOptions_;
|
|
|
|
|
|
2009-11-17 13:54:16 +00:00
|
|
|
return result;
|
2009-02-06 13:37:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
2012-05-22 09:15:15 +00:00
|
|
|
bool _OMReader_::read_ascii(std::istream& /* _is */, BaseImporter& /* _bi */, Options& /* _opt */) const
|
2009-02-06 13:37:46 +00:00
|
|
|
{
|
|
|
|
|
// not supported yet!
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
2012-05-22 09:15:15 +00:00
|
|
|
bool _OMReader_::read_binary(std::istream& _is, BaseImporter& _bi, Options& _opt) const
|
2009-02-06 13:37:46 +00:00
|
|
|
{
|
|
|
|
|
bool swap = _opt.check(Options::Swap) || (Endian::local() == Endian::MSB);
|
|
|
|
|
|
2012-05-22 09:15:15 +00:00
|
|
|
// Initialize byte counter
|
2009-11-17 13:54:16 +00:00
|
|
|
bytes_ = 0;
|
2009-02-06 13:37:46 +00:00
|
|
|
|
2012-05-22 09:15:15 +00:00
|
|
|
bytes_ += restore(_is, header_, swap);
|
2009-02-06 13:37:46 +00:00
|
|
|
|
|
|
|
|
|
2018-10-23 11:21:01 +02:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2012-05-22 09:15:15 +00:00
|
|
|
while (!_is.eof()) {
|
|
|
|
|
bytes_ += restore(_is, chunk_header_, swap);
|
2009-02-06 13:37:46 +00:00
|
|
|
|
2012-05-22 09:15:15 +00:00
|
|
|
if (_is.eof())
|
2009-02-06 13:37:46 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
// Is this a named property restore the name
|
2012-05-22 09:15:15 +00:00
|
|
|
if (chunk_header_.name_) {
|
2009-02-06 13:37:46 +00:00
|
|
|
OMFormat::Chunk::PropertyName pn;
|
2012-05-22 09:15:15 +00:00
|
|
|
bytes_ += restore(_is, property_name_, swap);
|
2009-02-06 13:37:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Read in the property data. If it is an anonymous or unknown named
|
|
|
|
|
// property, then skip data.
|
2012-05-22 09:15:15 +00:00
|
|
|
switch (chunk_header_.entity_) {
|
2009-11-17 13:54:16 +00:00
|
|
|
case OMFormat::Chunk::Entity_Vertex:
|
2012-05-22 09:15:15 +00:00
|
|
|
if (!read_binary_vertex_chunk(_is, _bi, _opt, swap))
|
|
|
|
|
return false;
|
|
|
|
|
break;
|
2009-02-06 13:37:46 +00:00
|
|
|
case OMFormat::Chunk::Entity_Face:
|
2012-05-22 09:15:15 +00:00
|
|
|
if (!read_binary_face_chunk(_is, _bi, _opt, swap))
|
|
|
|
|
return false;
|
|
|
|
|
break;
|
2009-02-06 13:37:46 +00:00
|
|
|
case OMFormat::Chunk::Entity_Edge:
|
2012-05-22 09:15:15 +00:00
|
|
|
if (!read_binary_edge_chunk(_is, _bi, _opt, swap))
|
|
|
|
|
return false;
|
|
|
|
|
break;
|
2009-02-06 13:37:46 +00:00
|
|
|
case OMFormat::Chunk::Entity_Halfedge:
|
2012-05-22 09:15:15 +00:00
|
|
|
if (!read_binary_halfedge_chunk(_is, _bi, _opt, swap))
|
|
|
|
|
return false;
|
|
|
|
|
break;
|
2009-02-06 13:37:46 +00:00
|
|
|
case OMFormat::Chunk::Entity_Mesh:
|
2012-05-22 09:15:15 +00:00
|
|
|
if (!read_binary_mesh_chunk(_is, _bi, _opt, swap))
|
|
|
|
|
return false;
|
|
|
|
|
break;
|
2016-12-27 08:10:10 +01:00
|
|
|
case OMFormat::Chunk::Entity_Sentinel:
|
|
|
|
|
return true;
|
2009-02-06 13:37:46 +00:00
|
|
|
default:
|
2012-05-22 09:15:15 +00:00
|
|
|
return false;
|
2009-02-06 13:37:46 +00:00
|
|
|
}
|
2013-08-21 11:34:24 +00:00
|
|
|
|
2009-02-06 13:37:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// File was successfully parsed.
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
2012-05-22 09:15:15 +00:00
|
|
|
bool _OMReader_::can_u_read(const std::string& _filename) const
|
2009-02-06 13:37:46 +00:00
|
|
|
{
|
|
|
|
|
// !!! Assuming BaseReader::can_u_parse( std::string& )
|
|
|
|
|
// does not call BaseReader::read_magic()!!!
|
2012-05-22 09:15:15 +00:00
|
|
|
if (this->BaseReader::can_u_read(_filename)) {
|
|
|
|
|
std::ifstream ifile(_filename.c_str());
|
|
|
|
|
if (ifile && can_u_read(ifile))
|
2009-11-17 13:54:16 +00:00
|
|
|
return true;
|
2009-02-06 13:37:46 +00:00
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
2009-11-17 13:54:16 +00:00
|
|
|
|
2012-05-22 09:15:15 +00:00
|
|
|
bool _OMReader_::can_u_read(std::istream& _is) const
|
2009-02-06 13:37:46 +00:00
|
|
|
{
|
|
|
|
|
std::vector<char> evt;
|
|
|
|
|
evt.reserve(20);
|
|
|
|
|
|
|
|
|
|
// read first 4 characters into a buffer
|
2012-05-22 09:15:15 +00:00
|
|
|
while (evt.size() < 4)
|
|
|
|
|
evt.push_back(static_cast<char>(_is.get()));
|
2009-02-06 13:37:46 +00:00
|
|
|
|
2009-11-17 13:54:16 +00:00
|
|
|
// put back all read characters
|
2009-02-06 13:37:46 +00:00
|
|
|
std::vector<char>::reverse_iterator it = evt.rbegin();
|
2012-05-22 09:15:15 +00:00
|
|
|
while (it != evt.rend())
|
|
|
|
|
_is.putback(*it++);
|
2009-02-06 13:37:46 +00:00
|
|
|
|
|
|
|
|
// evaluate header information
|
2012-05-22 09:15:15 +00:00
|
|
|
OMFormat::Header *hdr = (OMFormat::Header*) &evt[0];
|
2009-02-06 13:37:46 +00:00
|
|
|
|
|
|
|
|
// first two characters must be 'OM'
|
|
|
|
|
if (hdr->magic_[0] != 'O' || hdr->magic_[1] != 'M')
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
// 3rd characters defines the mesh type:
|
2012-05-22 09:15:15 +00:00
|
|
|
switch (hdr->mesh_) {
|
2009-02-06 13:37:46 +00:00
|
|
|
case 'T': // Triangle Mesh
|
|
|
|
|
case 'Q': // Quad Mesh
|
|
|
|
|
case 'P': // Polygonal Mesh
|
|
|
|
|
break;
|
|
|
|
|
default: // ?
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2009-11-17 13:54:16 +00:00
|
|
|
|
2009-02-06 13:37:46 +00:00
|
|
|
// 4th characters encodes the version
|
2012-05-22 09:15:15 +00:00
|
|
|
return supports(hdr->version_);
|
2009-02-06 13:37:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
2012-05-22 09:15:15 +00:00
|
|
|
bool _OMReader_::supports(const OMFormat::uint8 /* version */) const
|
2009-02-06 13:37:46 +00:00
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
2012-05-22 09:15:15 +00:00
|
|
|
bool _OMReader_::read_binary_vertex_chunk(std::istream &_is, BaseImporter &_bi, Options &_opt, bool _swap) const
|
2009-02-06 13:37:46 +00:00
|
|
|
{
|
|
|
|
|
using OMFormat::Chunk;
|
|
|
|
|
|
2012-05-22 09:15:15 +00:00
|
|
|
assert( chunk_header_.entity_ == Chunk::Entity_Vertex);
|
2009-11-17 13:54:16 +00:00
|
|
|
|
2012-05-22 09:15:15 +00:00
|
|
|
OpenMesh::Vec3f v3f;
|
2020-02-05 22:13:36 +01:00
|
|
|
OpenMesh::Vec3d v3d;
|
2012-05-22 09:15:15 +00:00
|
|
|
OpenMesh::Vec2f v2f;
|
2009-02-06 13:37:46 +00:00
|
|
|
OpenMesh::Vec3uc v3uc; // rgb
|
2018-10-12 11:35:18 +02:00
|
|
|
OpenMesh::Attributes::StatusInfo status;
|
2009-02-06 13:37:46 +00:00
|
|
|
|
|
|
|
|
OMFormat::Chunk::PropertyName custom_prop;
|
|
|
|
|
|
2012-05-22 09:15:15 +00:00
|
|
|
size_t vidx = 0;
|
|
|
|
|
switch (chunk_header_.type_) {
|
2009-02-06 13:37:46 +00:00
|
|
|
case Chunk::Type_Pos:
|
2020-02-05 22:13:36 +01:00
|
|
|
if (chunk_header_.bits_ == OMFormat::bits(0.0f)) // read floats
|
|
|
|
|
{
|
|
|
|
|
assert( OMFormat::dimensions(chunk_header_) == size_t(OpenMesh::Vec3f::dim()));
|
|
|
|
|
|
|
|
|
|
for (; vidx < header_.n_vertices_ && !_is.eof(); ++vidx) {
|
|
|
|
|
bytes_ += vector_restore(_is, v3f, _swap);
|
|
|
|
|
_bi.add_vertex(v3f);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (chunk_header_.bits_ == OMFormat::bits(0.0)) // read doubles
|
|
|
|
|
{
|
|
|
|
|
assert( OMFormat::dimensions(chunk_header_) == size_t(OpenMesh::Vec3d::dim()));
|
|
|
|
|
|
|
|
|
|
for (; vidx < header_.n_vertices_ && !_is.eof(); ++vidx) {
|
|
|
|
|
bytes_ += vector_restore(_is, v3d, _swap);
|
|
|
|
|
_bi.add_vertex(v3d);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
omerr() << "unknown Vector size" << std::endl;
|
2009-02-06 13:37:46 +00:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case Chunk::Type_Normal:
|
|
|
|
|
|
2020-02-05 22:13:36 +01:00
|
|
|
if (chunk_header_.bits_ == OMFormat::bits(0.0f)) // read floats
|
|
|
|
|
{
|
|
|
|
|
assert( OMFormat::dimensions(chunk_header_) == size_t(OpenMesh::Vec3f::dim()));
|
|
|
|
|
|
|
|
|
|
fileOptions_ += Options::VertexNormal;
|
|
|
|
|
for (; vidx < header_.n_vertices_ && !_is.eof(); ++vidx) {
|
|
|
|
|
bytes_ += vector_restore(_is, v3f, _swap);
|
|
|
|
|
if (fileOptions_.vertex_has_normal() && _opt.vertex_has_normal())
|
|
|
|
|
_bi.set_normal(VertexHandle(int(vidx)), v3f);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (chunk_header_.bits_ == OMFormat::bits(0.0)) // read doubles
|
|
|
|
|
{
|
|
|
|
|
assert( OMFormat::dimensions(chunk_header_) == size_t(OpenMesh::Vec3d::dim()));
|
|
|
|
|
|
|
|
|
|
fileOptions_ += Options::VertexNormal;
|
|
|
|
|
for (; vidx < header_.n_vertices_ && !_is.eof(); ++vidx) {
|
|
|
|
|
bytes_ += vector_restore(_is, v3d, _swap);
|
|
|
|
|
if (fileOptions_.vertex_has_normal() && _opt.vertex_has_normal())
|
|
|
|
|
_bi.set_normal(VertexHandle(int(vidx)), v3d);
|
|
|
|
|
}
|
2009-02-06 13:37:46 +00:00
|
|
|
}
|
2020-02-10 09:19:09 +01:00
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
omerr() << "Unknown vertex normal format" << std::endl;
|
|
|
|
|
}
|
2009-02-06 13:37:46 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case Chunk::Type_Texcoord:
|
2012-05-22 09:15:15 +00:00
|
|
|
assert( OMFormat::dimensions(chunk_header_) == size_t(OpenMesh::Vec2f::dim()));
|
2009-02-06 13:37:46 +00:00
|
|
|
|
2012-10-08 13:25:36 +00:00
|
|
|
fileOptions_ += Options::VertexTexCoord;
|
2012-05-22 09:15:15 +00:00
|
|
|
for (; vidx < header_.n_vertices_ && !_is.eof(); ++vidx) {
|
|
|
|
|
bytes_ += vector_restore(_is, v2f, _swap);
|
2012-10-08 13:25:36 +00:00
|
|
|
if (fileOptions_.vertex_has_texcoord() && _opt.vertex_has_texcoord())
|
2013-07-23 20:17:42 +00:00
|
|
|
_bi.set_texcoord(VertexHandle(int(vidx)), v2f);
|
2009-02-06 13:37:46 +00:00
|
|
|
}
|
2009-11-17 13:54:16 +00:00
|
|
|
break;
|
2009-02-06 13:37:46 +00:00
|
|
|
|
|
|
|
|
case Chunk::Type_Color:
|
|
|
|
|
|
2012-05-22 09:15:15 +00:00
|
|
|
assert( OMFormat::dimensions(chunk_header_) == 3);
|
2009-02-06 13:37:46 +00:00
|
|
|
|
2012-10-08 13:25:36 +00:00
|
|
|
fileOptions_ += Options::VertexColor;
|
2009-11-17 13:54:16 +00:00
|
|
|
|
2012-05-22 09:15:15 +00:00
|
|
|
for (; vidx < header_.n_vertices_ && !_is.eof(); ++vidx) {
|
|
|
|
|
bytes_ += vector_restore(_is, v3uc, _swap);
|
2012-10-08 13:25:36 +00:00
|
|
|
if (fileOptions_.vertex_has_color() && _opt.vertex_has_color())
|
2013-07-23 20:17:42 +00:00
|
|
|
_bi.set_color(VertexHandle(int(vidx)), v3uc);
|
2009-02-06 13:37:46 +00:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
2018-10-12 11:35:18 +02:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2009-02-06 13:37:46 +00:00
|
|
|
case Chunk::Type_Custom:
|
2020-11-17 21:35:07 +01:00
|
|
|
{
|
2020-11-26 17:51:43 +01:00
|
|
|
if(header_.version_ > OMFormat::mk_version(2,1))
|
|
|
|
|
{
|
|
|
|
|
Chunk::PropertyName property_type;
|
|
|
|
|
bytes_ += restore(_is, property_type, _swap);
|
|
|
|
|
add_generic_property(property_type, _bi);
|
|
|
|
|
}
|
2009-11-17 13:54:16 +00:00
|
|
|
|
2012-05-22 09:15:15 +00:00
|
|
|
bytes_ += restore_binary_custom_data(_is, _bi.kernel()->_get_vprop(property_name_), header_.n_vertices_, _swap);
|
2009-02-06 13:37:46 +00:00
|
|
|
vidx = header_.n_vertices_;
|
2020-11-17 21:35:07 +01:00
|
|
|
}
|
2009-02-06 13:37:46 +00:00
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
2018-08-08 10:59:51 +02:00
|
|
|
case Chunk::Type_Topology:
|
|
|
|
|
{
|
|
|
|
|
for (; vidx < header_.n_vertices_; ++vidx)
|
|
|
|
|
{
|
2018-12-14 14:27:50 +01:00
|
|
|
int halfedge_id = 0;
|
2018-08-08 10:59:51 +02:00
|
|
|
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;
|
|
|
|
|
|
2009-02-06 13:37:46 +00:00
|
|
|
default: // skip unknown chunks
|
|
|
|
|
{
|
|
|
|
|
omerr() << "Unknown chunk type ignored!\n";
|
2019-05-28 13:39:03 +02:00
|
|
|
size_t chunk_size = header_.n_vertices_ * OMFormat::vector_size(chunk_header_);
|
|
|
|
|
_is.ignore(chunk_size);
|
|
|
|
|
bytes_ += chunk_size;
|
|
|
|
|
break;
|
2009-02-06 13:37:46 +00:00
|
|
|
}
|
2019-05-28 13:39:03 +02:00
|
|
|
|
2009-02-06 13:37:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// all chunk data has been read..?!
|
|
|
|
|
return vidx == header_.n_vertices_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
2012-05-22 09:15:15 +00:00
|
|
|
bool _OMReader_::read_binary_face_chunk(std::istream &_is, BaseImporter &_bi, Options &_opt, bool _swap) const
|
2009-02-06 13:37:46 +00:00
|
|
|
{
|
|
|
|
|
using OMFormat::Chunk;
|
|
|
|
|
|
2012-05-22 09:15:15 +00:00
|
|
|
assert( chunk_header_.entity_ == Chunk::Entity_Face);
|
2009-02-06 13:37:46 +00:00
|
|
|
|
2012-05-22 09:15:15 +00:00
|
|
|
size_t fidx = 0;
|
|
|
|
|
OpenMesh::Vec3f v3f; // normal
|
2020-02-10 09:19:09 +01:00
|
|
|
OpenMesh::Vec3d v3d; // normal as double
|
2009-02-06 13:37:46 +00:00
|
|
|
OpenMesh::Vec3uc v3uc; // rgb
|
2018-10-12 11:35:18 +02:00
|
|
|
OpenMesh::Attributes::StatusInfo status;
|
2009-02-06 13:37:46 +00:00
|
|
|
|
2012-05-22 09:15:15 +00:00
|
|
|
switch (chunk_header_.type_) {
|
2018-08-08 10:59:51 +02:00
|
|
|
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;
|
|
|
|
|
}
|
2009-11-17 13:54:16 +00:00
|
|
|
|
2018-08-08 10:59:51 +02:00
|
|
|
for (; fidx < header_.n_faces_; ++fidx) {
|
|
|
|
|
if (header_.mesh_ == 'P')
|
|
|
|
|
bytes_ += restore(_is, nV, Chunk::Integer_16, _swap);
|
2009-02-06 13:37:46 +00:00
|
|
|
|
2018-08-08 10:59:51 +02:00
|
|
|
vhandles.clear();
|
|
|
|
|
for (size_t j = 0; j < nV; ++j) {
|
|
|
|
|
bytes_ += restore(_is, vidx, Chunk::Integer_Size(chunk_header_.bits_), _swap);
|
2009-02-06 13:37:46 +00:00
|
|
|
|
2018-08-08 10:59:51 +02:00
|
|
|
vhandles.push_back(VertexHandle(int(vidx)));
|
|
|
|
|
}
|
2009-02-06 13:37:46 +00:00
|
|
|
|
2018-08-08 10:59:51 +02:00
|
|
|
_bi.add_face(vhandles);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2018-08-08 14:38:07 +02:00
|
|
|
// add faces by simply setting an incident halfedge
|
2018-08-08 10:59:51 +02:00
|
|
|
for (; fidx < header_.n_faces_; ++fidx)
|
|
|
|
|
{
|
2018-12-14 14:27:50 +01:00
|
|
|
int halfedge_id = 0;
|
2018-08-08 10:59:51 +02:00
|
|
|
bytes_ += restore( _is, halfedge_id, OMFormat::Chunk::Integer_Size(chunk_header_.bits_), _swap );
|
|
|
|
|
|
|
|
|
|
_bi.add_face(HalfedgeHandle(halfedge_id));
|
|
|
|
|
}
|
2009-02-06 13:37:46 +00:00
|
|
|
}
|
|
|
|
|
}
|
2012-05-22 09:15:15 +00:00
|
|
|
break;
|
2009-02-06 13:37:46 +00:00
|
|
|
|
|
|
|
|
case Chunk::Type_Normal:
|
2012-05-22 09:15:15 +00:00
|
|
|
assert( OMFormat::dimensions(chunk_header_) == size_t(OpenMesh::Vec3f::dim()));
|
2009-02-06 13:37:46 +00:00
|
|
|
|
2012-10-08 13:25:36 +00:00
|
|
|
fileOptions_ += Options::FaceNormal;
|
2020-02-10 09:19:09 +01:00
|
|
|
|
|
|
|
|
if (chunk_header_.bits_ == OMFormat::bits(0.0f)) // read floats
|
|
|
|
|
{
|
|
|
|
|
for (; fidx < header_.n_faces_ && !_is.eof(); ++fidx) {
|
|
|
|
|
bytes_ += vector_restore(_is, v3f, _swap);
|
|
|
|
|
if( fileOptions_.face_has_normal() && _opt.face_has_normal())
|
|
|
|
|
_bi.set_normal(FaceHandle(int(fidx)), v3f);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (chunk_header_.bits_ == OMFormat::bits(0.0)) // read doubles
|
|
|
|
|
{
|
|
|
|
|
for (; fidx < header_.n_faces_ && !_is.eof(); ++fidx) {
|
|
|
|
|
bytes_ += vector_restore(_is, v3d, _swap);
|
|
|
|
|
if( fileOptions_.face_has_normal() && _opt.face_has_normal())
|
|
|
|
|
_bi.set_normal(FaceHandle(int(fidx)), v3d);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
omerr() << "Unknown face normal format" << std::endl;
|
2009-02-06 13:37:46 +00:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case Chunk::Type_Color:
|
|
|
|
|
|
2012-05-22 09:15:15 +00:00
|
|
|
assert( OMFormat::dimensions(chunk_header_) == 3);
|
2009-02-06 13:37:46 +00:00
|
|
|
|
2012-10-08 13:25:36 +00:00
|
|
|
fileOptions_ += Options::FaceColor;
|
2012-05-22 09:15:15 +00:00
|
|
|
for (; fidx < header_.n_faces_ && !_is.eof(); ++fidx) {
|
|
|
|
|
bytes_ += vector_restore(_is, v3uc, _swap);
|
2012-10-08 13:25:36 +00:00
|
|
|
if( fileOptions_.face_has_color() && _opt.face_has_color())
|
2013-07-23 20:17:42 +00:00
|
|
|
_bi.set_color(FaceHandle(int(fidx)), v3uc);
|
2009-02-06 13:37:46 +00:00
|
|
|
}
|
|
|
|
|
break;
|
2018-10-12 11:35:18 +02:00
|
|
|
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;
|
|
|
|
|
}
|
2009-02-06 13:37:46 +00:00
|
|
|
|
|
|
|
|
case Chunk::Type_Custom:
|
2020-11-17 21:35:07 +01:00
|
|
|
{
|
2020-11-26 17:51:43 +01:00
|
|
|
if(header_.version_ > OMFormat::mk_version(2,1))
|
|
|
|
|
{
|
|
|
|
|
Chunk::PropertyName property_type;
|
|
|
|
|
bytes_ += restore(_is, property_type, _swap);
|
|
|
|
|
add_generic_property(property_type, _bi);
|
|
|
|
|
}
|
2009-11-17 13:54:16 +00:00
|
|
|
|
2012-05-22 09:15:15 +00:00
|
|
|
bytes_ += restore_binary_custom_data(_is, _bi.kernel()->_get_fprop(property_name_), header_.n_faces_, _swap);
|
2009-02-06 13:37:46 +00:00
|
|
|
|
|
|
|
|
fidx = header_.n_faces_;
|
|
|
|
|
|
|
|
|
|
break;
|
2020-11-17 21:35:07 +01:00
|
|
|
}
|
2009-11-17 13:54:16 +00:00
|
|
|
|
2009-02-06 13:37:46 +00:00
|
|
|
default: // skip unknown chunks
|
|
|
|
|
{
|
|
|
|
|
omerr() << "Unknown chunk type ignore!\n";
|
2019-05-28 13:39:03 +02:00
|
|
|
size_t chunk_size = OMFormat::chunk_data_size(header_, chunk_header_);
|
|
|
|
|
_is.ignore(chunk_size);
|
|
|
|
|
bytes_ += chunk_size;
|
2009-02-06 13:37:46 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return fidx == header_.n_faces_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
2018-10-12 14:05:25 +02:00
|
|
|
bool _OMReader_::read_binary_edge_chunk(std::istream &_is, BaseImporter &_bi, Options &_opt, bool _swap) const
|
2009-02-06 13:37:46 +00:00
|
|
|
{
|
|
|
|
|
using OMFormat::Chunk;
|
|
|
|
|
|
2012-05-22 09:15:15 +00:00
|
|
|
assert( chunk_header_.entity_ == Chunk::Entity_Edge);
|
2009-02-06 13:37:46 +00:00
|
|
|
|
2012-05-22 09:15:15 +00:00
|
|
|
size_t b = bytes_;
|
2009-02-06 13:37:46 +00:00
|
|
|
|
2018-10-12 14:05:25 +02:00
|
|
|
OpenMesh::Attributes::StatusInfo status;
|
|
|
|
|
|
2012-05-22 09:15:15 +00:00
|
|
|
switch (chunk_header_.type_) {
|
2009-11-17 13:54:16 +00:00
|
|
|
case Chunk::Type_Custom:
|
2020-11-17 21:35:07 +01:00
|
|
|
{
|
2020-11-26 17:51:43 +01:00
|
|
|
if(header_.version_ > OMFormat::mk_version(2,1))
|
|
|
|
|
{
|
|
|
|
|
Chunk::PropertyName property_type;
|
|
|
|
|
bytes_ += restore(_is, property_type, _swap);
|
|
|
|
|
add_generic_property(property_type, _bi);
|
|
|
|
|
}
|
2009-02-06 13:37:46 +00:00
|
|
|
|
2012-05-22 09:15:15 +00:00
|
|
|
bytes_ += restore_binary_custom_data(_is, _bi.kernel()->_get_eprop(property_name_), header_.n_edges_, _swap);
|
2009-02-06 13:37:46 +00:00
|
|
|
|
|
|
|
|
break;
|
2020-11-17 21:35:07 +01:00
|
|
|
}
|
2018-10-12 14:05:25 +02:00
|
|
|
case Chunk::Type_Status:
|
|
|
|
|
{
|
|
|
|
|
assert( OMFormat::dimensions(chunk_header_) == 1);
|
|
|
|
|
|
|
|
|
|
fileOptions_ += Options::Status;
|
|
|
|
|
|
2018-10-12 15:16:33 +02:00
|
|
|
for (size_t eidx = 0; eidx < header_.n_edges_ && !_is.eof(); ++eidx) {
|
2018-10-12 14:05:25 +02:00
|
|
|
bytes_ += restore(_is, status, _swap);
|
|
|
|
|
if (fileOptions_.edge_has_status() && _opt.edge_has_status())
|
|
|
|
|
_bi.set_status(EdgeHandle(int(eidx)), status);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2009-02-06 13:37:46 +00:00
|
|
|
default:
|
|
|
|
|
// skip unknown type
|
2019-05-28 13:39:03 +02:00
|
|
|
size_t chunk_size = OMFormat::chunk_data_size(header_, chunk_header_);
|
|
|
|
|
_is.ignore(chunk_size);
|
|
|
|
|
bytes_ += chunk_size;
|
2009-02-06 13:37:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return b < bytes_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
2018-10-12 14:05:25 +02:00
|
|
|
bool _OMReader_::read_binary_halfedge_chunk(std::istream &_is, BaseImporter &_bi, Options & _opt, bool _swap) const
|
2009-02-06 13:37:46 +00:00
|
|
|
{
|
|
|
|
|
using OMFormat::Chunk;
|
|
|
|
|
|
2012-05-22 09:15:15 +00:00
|
|
|
assert( chunk_header_.entity_ == Chunk::Entity_Halfedge);
|
2009-02-06 13:37:46 +00:00
|
|
|
|
|
|
|
|
size_t b = bytes_;
|
2018-10-12 14:05:25 +02:00
|
|
|
OpenMesh::Attributes::StatusInfo status;
|
2009-02-06 13:37:46 +00:00
|
|
|
|
2012-05-22 09:15:15 +00:00
|
|
|
switch (chunk_header_.type_) {
|
2009-02-06 13:37:46 +00:00
|
|
|
case Chunk::Type_Custom:
|
2020-11-17 21:35:07 +01:00
|
|
|
{
|
2020-11-26 17:51:43 +01:00
|
|
|
if(header_.version_ > OMFormat::mk_version(2,1))
|
|
|
|
|
{
|
|
|
|
|
Chunk::PropertyName property_type;
|
|
|
|
|
bytes_ += restore(_is, property_type, _swap);
|
|
|
|
|
add_generic_property(property_type, _bi);
|
|
|
|
|
}
|
2009-02-06 13:37:46 +00:00
|
|
|
|
2012-05-22 09:15:15 +00:00
|
|
|
bytes_ += restore_binary_custom_data(_is, _bi.kernel()->_get_hprop(property_name_), 2 * header_.n_edges_, _swap);
|
2009-02-06 13:37:46 +00:00
|
|
|
break;
|
2020-11-17 21:35:07 +01:00
|
|
|
}
|
2018-08-08 10:59:51 +02:00
|
|
|
case Chunk::Type_Topology:
|
|
|
|
|
{
|
|
|
|
|
std::vector<HalfedgeHandle> next_halfedges;
|
|
|
|
|
for (size_t e_idx = 0; e_idx < header_.n_edges_; ++e_idx)
|
|
|
|
|
{
|
2018-12-14 14:27:50 +01:00
|
|
|
int next_id_0 = -1;
|
|
|
|
|
int to_vertex_id_0 = -1;
|
|
|
|
|
int face_id_0 = -1;
|
2018-08-08 10:59:51 +02:00
|
|
|
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 );
|
|
|
|
|
|
2018-12-14 14:27:50 +01:00
|
|
|
int next_id_1 = -1;
|
|
|
|
|
int to_vertex_id_1 = -1;
|
|
|
|
|
int face_id_1 = -1;
|
2018-08-08 10:59:51 +02:00
|
|
|
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;
|
|
|
|
|
|
2018-10-12 14:05:25 +02:00
|
|
|
case Chunk::Type_Status:
|
|
|
|
|
{
|
|
|
|
|
assert( OMFormat::dimensions(chunk_header_) == 1);
|
|
|
|
|
|
|
|
|
|
fileOptions_ += Options::Status;
|
|
|
|
|
|
2018-10-12 15:16:33 +02:00
|
|
|
for (size_t hidx = 0; hidx < header_.n_edges_ * 2 && !_is.eof(); ++hidx) {
|
2018-10-12 14:05:25 +02:00
|
|
|
bytes_ += restore(_is, status, _swap);
|
|
|
|
|
if (fileOptions_.halfedge_has_status() && _opt.halfedge_has_status())
|
|
|
|
|
_bi.set_status(HalfedgeHandle(int(hidx)), status);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2009-02-06 13:37:46 +00:00
|
|
|
default:
|
|
|
|
|
// skip unknown chunk
|
|
|
|
|
omerr() << "Unknown chunk type ignored!\n";
|
2019-05-28 13:39:03 +02:00
|
|
|
size_t chunk_size = OMFormat::chunk_data_size(header_, chunk_header_);
|
|
|
|
|
_is.ignore(chunk_size);
|
|
|
|
|
bytes_ += chunk_size;
|
2009-02-06 13:37:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return b < bytes_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
2012-05-22 09:15:15 +00:00
|
|
|
bool _OMReader_::read_binary_mesh_chunk(std::istream &_is, BaseImporter &_bi, Options & /* _opt */, bool _swap) const
|
2009-02-06 13:37:46 +00:00
|
|
|
{
|
|
|
|
|
using OMFormat::Chunk;
|
|
|
|
|
|
2012-05-22 09:15:15 +00:00
|
|
|
assert( chunk_header_.entity_ == Chunk::Entity_Mesh);
|
2009-02-06 13:37:46 +00:00
|
|
|
|
|
|
|
|
size_t b = bytes_;
|
|
|
|
|
|
2012-05-22 09:15:15 +00:00
|
|
|
switch (chunk_header_.type_) {
|
2009-02-06 13:37:46 +00:00
|
|
|
case Chunk::Type_Custom:
|
2020-11-17 21:35:07 +01:00
|
|
|
{
|
2020-11-26 17:51:43 +01:00
|
|
|
if(header_.version_ > OMFormat::mk_version(2,1))
|
|
|
|
|
{
|
|
|
|
|
Chunk::PropertyName property_type;
|
|
|
|
|
bytes_ += restore(_is, property_type, _swap);
|
|
|
|
|
add_generic_property(property_type, _bi);
|
|
|
|
|
}
|
2009-11-17 13:54:16 +00:00
|
|
|
|
2012-05-22 09:15:15 +00:00
|
|
|
bytes_ += restore_binary_custom_data(_is, _bi.kernel()->_get_mprop(property_name_), 1, _swap);
|
2009-11-17 13:54:16 +00:00
|
|
|
|
2009-02-06 13:37:46 +00:00
|
|
|
break;
|
2020-11-17 21:35:07 +01:00
|
|
|
}
|
2009-02-06 13:37:46 +00:00
|
|
|
default:
|
|
|
|
|
// skip unknown chunk
|
2019-05-28 13:39:03 +02:00
|
|
|
size_t chunk_size = OMFormat::chunk_data_size(header_, chunk_header_);
|
|
|
|
|
_is.ignore(chunk_size);
|
|
|
|
|
bytes_ += chunk_size;
|
2009-02-06 13:37:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return b < bytes_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
2012-05-22 09:15:15 +00:00
|
|
|
size_t _OMReader_::restore_binary_custom_data(std::istream& _is, BaseProperty* _bp, size_t _n_elem, bool _swap) const
|
2009-11-17 13:54:16 +00:00
|
|
|
{
|
2012-05-22 09:15:15 +00:00
|
|
|
assert( !_bp || (_bp->name() == property_name_));
|
2009-02-06 13:37:46 +00:00
|
|
|
|
|
|
|
|
using OMFormat::Chunk;
|
|
|
|
|
|
2012-05-22 09:15:15 +00:00
|
|
|
size_t bytes = 0;
|
|
|
|
|
Chunk::esize_t block_size;
|
2009-02-06 13:37:46 +00:00
|
|
|
Chunk::PropertyName custom_prop;
|
|
|
|
|
|
2012-07-17 10:13:27 +00:00
|
|
|
bytes += restore(_is, block_size, OMFormat::Chunk::Integer_32, _swap);
|
2009-02-06 13:37:46 +00:00
|
|
|
|
2012-05-22 09:15:15 +00:00
|
|
|
if (_bp) {
|
|
|
|
|
size_t n_bytes = _bp->size_of(_n_elem);
|
2009-02-06 13:37:46 +00:00
|
|
|
|
2012-05-22 09:15:15 +00:00
|
|
|
if (((n_bytes == BaseProperty::UnknownSize) || (n_bytes == block_size))
|
|
|
|
|
&& (_bp->element_size() == BaseProperty::UnknownSize || (_n_elem * _bp->element_size() == block_size))) {
|
2009-02-06 13:37:46 +00:00
|
|
|
#if defined(OM_DEBUG)
|
2012-01-12 09:15:18 +00:00
|
|
|
size_t b;
|
2009-02-06 13:37:46 +00:00
|
|
|
bytes += (b=_bp->restore( _is, _swap ));
|
|
|
|
|
#else
|
2012-05-22 09:15:15 +00:00
|
|
|
bytes += _bp->restore(_is, _swap);
|
2009-02-06 13:37:46 +00:00
|
|
|
#endif
|
2012-05-22 09:15:15 +00:00
|
|
|
|
2009-02-06 13:37:46 +00:00
|
|
|
#if defined(OM_DEBUG)
|
|
|
|
|
assert( block_size == b );
|
|
|
|
|
#endif
|
2012-05-22 09:15:15 +00:00
|
|
|
|
|
|
|
|
assert( block_size == _bp->size_of());
|
2009-02-06 13:37:46 +00:00
|
|
|
|
|
|
|
|
block_size = 0;
|
2012-05-22 09:15:15 +00:00
|
|
|
} else {
|
2020-11-30 20:51:56 +01:00
|
|
|
omerr() << "Warning! Property " << _bp->name() << " not loaded: " << "Mismatching data sizes!" << std::endl;
|
2009-02-06 13:37:46 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-22 09:15:15 +00:00
|
|
|
if (block_size) {
|
|
|
|
|
_is.ignore(block_size);
|
|
|
|
|
bytes += block_size;
|
2009-02-06 13:37:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return bytes;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2020-11-17 21:35:07 +01:00
|
|
|
//--------------------------------helper
|
|
|
|
|
void _OMReader_:: add_generic_property(OMFormat::Chunk::PropertyName& _property_type, BaseImporter& _bi) const
|
|
|
|
|
{
|
2020-12-21 15:22:46 +01:00
|
|
|
PropertyCreationManager& manager = PropertyCreationManager::instance();
|
|
|
|
|
switch (chunk_header_.entity_)
|
2020-11-17 21:35:07 +01:00
|
|
|
{
|
2020-12-21 15:22:46 +01:00
|
|
|
case OMFormat::Chunk::Entity_Vertex:
|
2020-11-17 21:35:07 +01:00
|
|
|
{
|
2020-12-21 15:22:46 +01:00
|
|
|
manager.create_property<OpenMesh::VertexHandle>(*_bi.kernel(), _property_type, property_name_);
|
|
|
|
|
break;
|
2020-11-17 21:35:07 +01:00
|
|
|
}
|
2020-12-21 15:22:46 +01:00
|
|
|
case OMFormat::Chunk::Entity_Face:
|
2020-11-17 21:35:07 +01:00
|
|
|
{
|
2020-12-21 15:22:46 +01:00
|
|
|
manager.create_property<OpenMesh::FaceHandle>(*_bi.kernel(), _property_type, property_name_);
|
|
|
|
|
break;
|
2020-11-17 21:35:07 +01:00
|
|
|
}
|
2020-12-21 15:22:46 +01:00
|
|
|
case OMFormat::Chunk::Entity_Edge:
|
2020-11-17 21:35:07 +01:00
|
|
|
{
|
2020-12-21 15:22:46 +01:00
|
|
|
manager.create_property<OpenMesh::EdgeHandle>(*_bi.kernel(), _property_type, property_name_);
|
|
|
|
|
break;
|
2020-11-17 21:35:07 +01:00
|
|
|
}
|
2020-12-21 15:22:46 +01:00
|
|
|
case OMFormat::Chunk::Entity_Halfedge:
|
2020-11-17 21:35:07 +01:00
|
|
|
{
|
2020-12-21 15:22:46 +01:00
|
|
|
manager.create_property<OpenMesh::HalfedgeHandle>(*_bi.kernel(), _property_type, property_name_);
|
|
|
|
|
break;
|
2020-11-17 21:35:07 +01:00
|
|
|
}
|
2020-12-21 15:22:46 +01:00
|
|
|
case OMFormat::Chunk::Entity_Mesh:
|
2020-11-17 21:35:07 +01:00
|
|
|
{
|
2020-12-21 15:22:46 +01:00
|
|
|
manager.create_property<OpenMesh::MeshHandle>(*_bi.kernel(), _property_type, property_name_);
|
|
|
|
|
break;
|
2020-11-17 21:35:07 +01:00
|
|
|
}
|
2020-12-21 15:22:46 +01:00
|
|
|
case OMFormat::Chunk::Entity_Sentinel:
|
|
|
|
|
;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
;
|
2020-11-29 17:38:34 +01:00
|
|
|
}
|
2020-12-21 15:22:46 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
// if(_property_type == get_string_for_type(bool()))
|
|
|
|
|
// {
|
|
|
|
|
// add_generic_property_aux<bool>(_bi);
|
|
|
|
|
// }
|
|
|
|
|
// else if(_property_type == get_string_for_type(char()))
|
|
|
|
|
// {
|
|
|
|
|
// add_generic_property_aux<char>(_bi);
|
|
|
|
|
// }
|
|
|
|
|
// else if(_property_type == get_string_for_type(double()))
|
|
|
|
|
// {
|
|
|
|
|
// add_generic_property_aux<double>(_bi);
|
|
|
|
|
// }
|
|
|
|
|
// else if(_property_type == get_string_for_type(float()))
|
|
|
|
|
// {
|
|
|
|
|
// add_generic_property_aux<float>(_bi);
|
|
|
|
|
// }
|
|
|
|
|
// else if(_property_type == get_string_for_type(int()))
|
|
|
|
|
// {
|
|
|
|
|
// add_generic_property_aux<int>(_bi);
|
|
|
|
|
// }
|
|
|
|
|
// else if(_property_type == get_string_for_type(long()))
|
|
|
|
|
// {
|
|
|
|
|
// add_generic_property_aux<long>(_bi);
|
|
|
|
|
// }
|
|
|
|
|
// else if(_property_type == get_string_for_type(short()))
|
|
|
|
|
// {
|
|
|
|
|
// add_generic_property_aux<short>(_bi);
|
|
|
|
|
// }
|
|
|
|
|
// else if(_property_type == get_string_for_type(uchar()))
|
|
|
|
|
// {
|
|
|
|
|
// add_generic_property_aux<uchar>(_bi);
|
|
|
|
|
// }
|
|
|
|
|
// else if(_property_type == get_string_for_type(uint()))
|
|
|
|
|
// {
|
|
|
|
|
// add_generic_property_aux<uint>(_bi);
|
|
|
|
|
// }
|
|
|
|
|
// else if(_property_type == get_string_for_type(ulong()))
|
|
|
|
|
// {
|
|
|
|
|
// add_generic_property_aux<ulong>(_bi);
|
|
|
|
|
// }
|
|
|
|
|
// else
|
|
|
|
|
// {
|
|
|
|
|
// check_all_vector_types(_property_type, _bi);
|
|
|
|
|
// }
|
2020-11-29 17:38:34 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void _OMReader_::check_all_vector_types(OMFormat::Chunk::PropertyName& _property_type, BaseImporter& _bi) const
|
|
|
|
|
{
|
|
|
|
|
check_all_vector_types_aux<1>(_property_type, _bi);
|
|
|
|
|
check_all_vector_types_aux<2>(_property_type, _bi);
|
|
|
|
|
check_all_vector_types_aux<3>(_property_type, _bi);
|
|
|
|
|
check_all_vector_types_aux<4>(_property_type, _bi);
|
|
|
|
|
check_all_std_vector_types_aux(_property_type, _bi);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void _OMReader_::check_all_std_vector_types_aux(OMFormat::Chunk::PropertyName& _property_type, BaseImporter& _bi) const
|
|
|
|
|
{
|
|
|
|
|
if(_property_type == get_string_for_type(std::vector<bool>()))
|
|
|
|
|
{
|
|
|
|
|
add_generic_property_aux<std::vector<bool>>(_bi);
|
|
|
|
|
}
|
|
|
|
|
else if(_property_type == get_string_for_type(std::vector<char>()))
|
|
|
|
|
{
|
|
|
|
|
add_generic_property_aux<std::vector<char>>(_bi);
|
|
|
|
|
}
|
2020-12-01 16:34:40 +01:00
|
|
|
else if(_property_type == get_string_for_type(std::vector<signed char>()))
|
|
|
|
|
{
|
|
|
|
|
add_generic_property_aux<std::vector<signed char>>(_bi);
|
|
|
|
|
}
|
2020-11-29 17:38:34 +01:00
|
|
|
else if(_property_type == get_string_for_type(std::vector<double>()))
|
|
|
|
|
{
|
|
|
|
|
add_generic_property_aux<std::vector<double>>(_bi);
|
|
|
|
|
}
|
|
|
|
|
else if(_property_type == get_string_for_type(std::vector<float>()))
|
|
|
|
|
{
|
|
|
|
|
add_generic_property_aux<std::vector<float>>(_bi);
|
|
|
|
|
}
|
|
|
|
|
else if(_property_type == get_string_for_type(std::vector<int>()))
|
|
|
|
|
{
|
|
|
|
|
add_generic_property_aux<std::vector<int>>(_bi);
|
|
|
|
|
}
|
|
|
|
|
else if(_property_type == get_string_for_type(std::vector<long>()))
|
|
|
|
|
{
|
|
|
|
|
add_generic_property_aux<std::vector<long>>(_bi);
|
|
|
|
|
}
|
|
|
|
|
else if(_property_type == get_string_for_type(std::vector<short>()))
|
|
|
|
|
{
|
|
|
|
|
add_generic_property_aux<std::vector<short>>(_bi);
|
|
|
|
|
}
|
|
|
|
|
else if(_property_type == get_string_for_type(std::vector<uchar>()))
|
|
|
|
|
{
|
|
|
|
|
add_generic_property_aux<std::vector<uchar>>(_bi);
|
|
|
|
|
}
|
|
|
|
|
else if(_property_type == get_string_for_type(std::vector<uint>()))
|
|
|
|
|
{
|
|
|
|
|
add_generic_property_aux<std::vector<uint>>(_bi);
|
|
|
|
|
}
|
|
|
|
|
else if(_property_type == get_string_for_type(std::vector<ulong>()))
|
|
|
|
|
{
|
|
|
|
|
add_generic_property_aux<std::vector<ulong>>(_bi);
|
|
|
|
|
}
|
|
|
|
|
else if(_property_type == get_string_for_type(std::vector<ushort>()))
|
|
|
|
|
{
|
|
|
|
|
add_generic_property_aux<std::vector<ushort>>(_bi);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<int Dim>
|
|
|
|
|
void _OMReader_::check_all_vector_types_aux(OMFormat::Chunk::PropertyName& _property_type, BaseImporter& _bi) const
|
|
|
|
|
{
|
|
|
|
|
if(_property_type == get_string_for_type(OpenMesh::VectorT<bool, Dim>()))
|
|
|
|
|
{
|
|
|
|
|
add_generic_property_aux<OpenMesh::VectorT<bool, Dim>>(_bi);
|
|
|
|
|
}
|
|
|
|
|
else if(_property_type == get_string_for_type(OpenMesh::VectorT<char, Dim>()))
|
|
|
|
|
{
|
|
|
|
|
add_generic_property_aux<OpenMesh::VectorT<char, Dim>>(_bi);
|
|
|
|
|
}
|
2020-12-01 16:34:40 +01:00
|
|
|
else if(_property_type == get_string_for_type(OpenMesh::VectorT<signed char, Dim>()))
|
|
|
|
|
{
|
|
|
|
|
add_generic_property_aux<OpenMesh::VectorT<signed char, Dim>>(_bi);
|
|
|
|
|
}
|
2020-11-29 17:38:34 +01:00
|
|
|
else if(_property_type == get_string_for_type(OpenMesh::VectorT<double, Dim>()))
|
|
|
|
|
{
|
|
|
|
|
add_generic_property_aux<OpenMesh::VectorT<double, Dim>>(_bi);
|
|
|
|
|
}
|
|
|
|
|
else if(_property_type == get_string_for_type(OpenMesh::VectorT<float, Dim>()))
|
|
|
|
|
{
|
|
|
|
|
add_generic_property_aux<OpenMesh::VectorT<float, Dim>>(_bi);
|
|
|
|
|
}
|
|
|
|
|
else if(_property_type == get_string_for_type(OpenMesh::VectorT<int, Dim>()))
|
|
|
|
|
{
|
|
|
|
|
add_generic_property_aux<OpenMesh::VectorT<int, Dim>>(_bi);
|
|
|
|
|
}
|
|
|
|
|
else if(_property_type == get_string_for_type(OpenMesh::VectorT<long, Dim>()))
|
|
|
|
|
{
|
|
|
|
|
add_generic_property_aux<OpenMesh::VectorT<long, Dim>>(_bi);
|
|
|
|
|
}
|
|
|
|
|
else if(_property_type == get_string_for_type(OpenMesh::VectorT<short, Dim>()))
|
|
|
|
|
{
|
|
|
|
|
add_generic_property_aux<OpenMesh::VectorT<short, Dim>>(_bi);
|
|
|
|
|
}
|
|
|
|
|
else if(_property_type == get_string_for_type(OpenMesh::VectorT<uchar, Dim>()))
|
|
|
|
|
{
|
|
|
|
|
add_generic_property_aux<OpenMesh::VectorT<uchar, Dim>>(_bi);
|
|
|
|
|
}
|
|
|
|
|
else if(_property_type == get_string_for_type(OpenMesh::VectorT<uint, Dim>()))
|
|
|
|
|
{
|
|
|
|
|
add_generic_property_aux<OpenMesh::VectorT<uint, Dim>>(_bi);
|
|
|
|
|
}
|
|
|
|
|
else if(_property_type == get_string_for_type(OpenMesh::VectorT<ulong, Dim>()))
|
|
|
|
|
{
|
|
|
|
|
add_generic_property_aux<OpenMesh::VectorT<ulong, Dim>>(_bi);
|
|
|
|
|
}
|
|
|
|
|
else if(_property_type == get_string_for_type(OpenMesh::VectorT<ushort, Dim>()))
|
|
|
|
|
{
|
|
|
|
|
add_generic_property_aux<OpenMesh::VectorT<ushort, Dim>>(_bi);
|
|
|
|
|
}
|
2020-11-17 21:35:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
|
void _OMReader_::add_generic_property_aux(BaseImporter& _bi) const
|
|
|
|
|
{
|
|
|
|
|
switch (chunk_header_.entity_)
|
|
|
|
|
{
|
|
|
|
|
case OMFormat::Chunk::Entity_Vertex:
|
|
|
|
|
{
|
|
|
|
|
VPropHandleT<T> prop;
|
|
|
|
|
_bi.kernel()->add_property(prop, property_name_);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case OMFormat::Chunk::Entity_Face:
|
|
|
|
|
{
|
|
|
|
|
FPropHandleT<T> prop;
|
|
|
|
|
_bi.kernel()->add_property(prop, property_name_);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case OMFormat::Chunk::Entity_Edge:
|
|
|
|
|
{
|
|
|
|
|
EPropHandleT<T> prop;
|
|
|
|
|
_bi.kernel()->add_property(prop, property_name_);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case OMFormat::Chunk::Entity_Halfedge:
|
|
|
|
|
{
|
|
|
|
|
HPropHandleT<T> prop;
|
|
|
|
|
_bi.kernel()->add_property(prop, property_name_);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case OMFormat::Chunk::Entity_Mesh:
|
|
|
|
|
{
|
|
|
|
|
MPropHandleT<T> prop;
|
|
|
|
|
_bi.kernel()->add_property(prop, property_name_);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case OMFormat::Chunk::Entity_Sentinel:
|
|
|
|
|
;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2009-02-06 13:37:46 +00:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
//=============================================================================
|
|
|
|
|
} // namespace IO
|
|
|
|
|
} // namespace OpenMesh
|
|
|
|
|
//=============================================================================
|