From c92a666658d6a409ea203108da39e67fa288948b Mon Sep 17 00:00:00 2001 From: Max Lyon Date: Wed, 5 Feb 2020 22:09:36 +0100 Subject: [PATCH 1/8] add unittest for writing and reading double positions and normals --- src/Unittests/unittests_read_write_OM.cc | 28 ++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/Unittests/unittests_read_write_OM.cc b/src/Unittests/unittests_read_write_OM.cc index e138f4cd..044227e0 100644 --- a/src/Unittests/unittests_read_write_OM.cc +++ b/src/Unittests/unittests_read_write_OM.cc @@ -1472,4 +1472,32 @@ TEST_F(OpenMeshReadWriteOM, LoadTriMeshVersion_7_5) { EXPECT_FALSE(ok) << file_name; } + +/* + * Try to write and load positions and normals that can only be represented by doubles + */ +TEST_F(OpenMeshReadWriteOM, WriteAndLoadDoubles) { + + typedef OpenMesh::PolyMesh_ArrayKernelT DoublePolyMesh; + + DoublePolyMesh mesh; + mesh.request_vertex_normals(); + + mesh.add_vertex(DoublePolyMesh::Point(1.0/3.0, std::numeric_limits::min(), std::numeric_limits::max())); + mesh.set_normal(OpenMesh::VertexHandle(0), DoublePolyMesh::Normal(1.0/3.0, std::numeric_limits::min(), std::numeric_limits::max())); + + std::string file_name = "doubles.om"; + + OpenMesh::IO::Options opt = OpenMesh::IO::Options::VertexNormal; + ASSERT_TRUE(OpenMesh::IO::write_mesh(mesh, file_name, opt)) << "Could not write file " << file_name; + + DoublePolyMesh mesh2; + mesh2.request_vertex_normals(); + + ASSERT_TRUE(OpenMesh::IO::read_mesh(mesh2, file_name, opt)) << "Could not read file " << file_name; + + EXPECT_EQ(mesh.point(OpenMesh::VertexHandle(0)), mesh2.point(OpenMesh::VertexHandle(0))); + EXPECT_EQ(mesh.normal(OpenMesh::VertexHandle(0)), mesh2.normal(OpenMesh::VertexHandle(0))); +} + } From 2356364085035943beef26d10b33b1312603026e Mon Sep 17 00:00:00 2001 From: Max Lyon Date: Wed, 5 Feb 2020 22:11:10 +0100 Subject: [PATCH 2/8] add methods to export the check if positions or normals are double and get them as doubles --- src/OpenMesh/Core/IO/OMFormat.hh | 2 +- src/OpenMesh/Core/IO/exporter/BaseExporter.hh | 8 ++++-- src/OpenMesh/Core/IO/exporter/ExporterT.hh | 26 +++++++++++++++++-- 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/src/OpenMesh/Core/IO/OMFormat.hh b/src/OpenMesh/Core/IO/OMFormat.hh index 66aaf26a..4e041a34 100644 --- a/src/OpenMesh/Core/IO/OMFormat.hh +++ b/src/OpenMesh/Core/IO/OMFormat.hh @@ -289,7 +289,7 @@ namespace OMFormat { inline size_t chunk_header_size( void ) { return sizeof(uint16); } - /// Return the size of a scale in bytes. + /// Return the size of a scaler in bytes. inline size_t scalar_size( const Chunk::Header& _hdr ) { return _hdr.float_ ? (0x01 << _hdr.bits_) : (0x04 << _hdr.bits_); diff --git a/src/OpenMesh/Core/IO/exporter/BaseExporter.hh b/src/OpenMesh/Core/IO/exporter/BaseExporter.hh index 86290720..52f451b1 100644 --- a/src/OpenMesh/Core/IO/exporter/BaseExporter.hh +++ b/src/OpenMesh/Core/IO/exporter/BaseExporter.hh @@ -90,11 +90,15 @@ public: // get vertex data virtual Vec3f point(VertexHandle _vh) const = 0; + virtual Vec3d pointd(VertexHandle _vh) const = 0; + virtual bool is_point_double() const = 0; virtual Vec3f normal(VertexHandle _vh) const = 0; + virtual Vec3d normald(VertexHandle _vh) const = 0; + virtual bool is_normal_double() const = 0; virtual Vec3uc color(VertexHandle _vh) const = 0; virtual Vec4uc colorA(VertexHandle _vh) const = 0; - virtual Vec3ui colori(VertexHandle _vh) const = 0; - virtual Vec4ui colorAi(VertexHandle _vh) const = 0; + virtual Vec3ui colori(VertexHandle _vh) const = 0; + virtual Vec4ui colorAi(VertexHandle _vh) const = 0; virtual Vec3f colorf(VertexHandle _vh) const = 0; virtual Vec4f colorAf(VertexHandle _vh) const = 0; virtual Vec2f texcoord(VertexHandle _vh) const = 0; diff --git a/src/OpenMesh/Core/IO/exporter/ExporterT.hh b/src/OpenMesh/Core/IO/exporter/ExporterT.hh index 9de326ca..02223122 100644 --- a/src/OpenMesh/Core/IO/exporter/ExporterT.hh +++ b/src/OpenMesh/Core/IO/exporter/ExporterT.hh @@ -94,11 +94,33 @@ public: return vector_cast(mesh_.point(_vh)); } + Vec3d pointd(VertexHandle _vh) const override + { + return vector_cast(mesh_.point(_vh)); + } + + bool is_point_double() const override + { + return OMFormat::is_double(typename Mesh::Point()[0]); + } + + bool is_normal_double() const override + { + return OMFormat::is_double(typename Mesh::Normal()[0]); + } + Vec3f normal(VertexHandle _vh) const override { return (mesh_.has_vertex_normals() - ? vector_cast(mesh_.normal(_vh)) - : Vec3f(0.0f, 0.0f, 0.0f)); + ? vector_cast(mesh_.normal(_vh)) + : Vec3f(0.0f, 0.0f, 0.0f)); + } + + Vec3d normald(VertexHandle _vh) const override + { + return (mesh_.has_vertex_normals() + ? vector_cast(mesh_.normal(_vh)) + : Vec3d(0.0f, 0.0f, 0.0f)); } Vec3uc color(VertexHandle _vh) const override From 337fb4571deb7b02f49312f58e962053361a0fba Mon Sep 17 00:00:00 2001 From: Max Lyon Date: Wed, 5 Feb 2020 22:12:53 +0100 Subject: [PATCH 3/8] add methods to import to set positions and normals from doubles --- src/OpenMesh/Core/IO/importer/BaseImporter.hh | 6 ++++++ src/OpenMesh/Core/IO/importer/ImporterT.hh | 16 ++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/OpenMesh/Core/IO/importer/BaseImporter.hh b/src/OpenMesh/Core/IO/importer/BaseImporter.hh index ff86dadd..8f66ba24 100644 --- a/src/OpenMesh/Core/IO/importer/BaseImporter.hh +++ b/src/OpenMesh/Core/IO/importer/BaseImporter.hh @@ -91,6 +91,9 @@ public: // add a vertex with coordinate \c _point virtual VertexHandle add_vertex(const Vec3f& _point) = 0; + // add a vertex with coordinate \c _point + virtual VertexHandle add_vertex(const Vec3d& _point) { return add_vertex(Vec3f(_point)); } + // add a vertex without coordinate. Use set_point to set the position deferred virtual VertexHandle add_vertex() = 0; @@ -122,6 +125,9 @@ public: // set vertex normal virtual void set_normal(VertexHandle _vh, const Vec3f& _normal) = 0; + // set vertex normal + virtual void set_normal(VertexHandle _vh, const Vec3d& _normal) { set_normal(_vh, Vec3f(_normal)); } + // set vertex color virtual void set_color(VertexHandle _vh, const Vec3uc& _color) = 0; diff --git a/src/OpenMesh/Core/IO/importer/ImporterT.hh b/src/OpenMesh/Core/IO/importer/ImporterT.hh index 50ee3192..bb223e74 100644 --- a/src/OpenMesh/Core/IO/importer/ImporterT.hh +++ b/src/OpenMesh/Core/IO/importer/ImporterT.hh @@ -97,6 +97,11 @@ public: return mesh_.add_vertex(vector_cast(_point)); } + virtual VertexHandle add_vertex(const Vec3d& _point) override + { + return mesh_.add_vertex(vector_cast(_point)); + } + virtual VertexHandle add_vertex() override { return mesh_.new_vertex(); @@ -222,6 +227,17 @@ public: halfedgeNormals_[_vh] = vector_cast(_normal); } + virtual void set_normal(VertexHandle _vh, const Vec3d& _normal) override + { + if (mesh_.has_vertex_normals()) + mesh_.set_normal(_vh, vector_cast(_normal)); + + //saves normals for half edges. + //they will be written, when the face is added + if (mesh_.has_halfedge_normals()) + halfedgeNormals_[_vh] = vector_cast(_normal); + } + virtual void set_color(VertexHandle _vh, const Vec4uc& _color) override { if (mesh_.has_vertex_colors()) From 63dd997489a5cd0e59b0b6b846aff68ed533f7d9 Mon Sep 17 00:00:00 2001 From: Max Lyon Date: Wed, 5 Feb 2020 22:13:36 +0100 Subject: [PATCH 4/8] let OMReader and OMWriter read and write double positions and normals --- src/OpenMesh/Core/IO/reader/OMReader.cc | 52 +++++++++++++++++----- src/OpenMesh/Core/IO/writer/OMWriter.cc | 57 +++++++++++++++++++------ 2 files changed, 86 insertions(+), 23 deletions(-) diff --git a/src/OpenMesh/Core/IO/reader/OMReader.cc b/src/OpenMesh/Core/IO/reader/OMReader.cc index 41a4b3a9..3917fb09 100644 --- a/src/OpenMesh/Core/IO/reader/OMReader.cc +++ b/src/OpenMesh/Core/IO/reader/OMReader.cc @@ -297,6 +297,7 @@ bool _OMReader_::read_binary_vertex_chunk(std::istream &_is, BaseImporter &_bi, assert( chunk_header_.entity_ == Chunk::Entity_Vertex); OpenMesh::Vec3f v3f; + OpenMesh::Vec3d v3d; OpenMesh::Vec2f v2f; OpenMesh::Vec3uc v3uc; // rgb OpenMesh::Attributes::StatusInfo status; @@ -306,22 +307,53 @@ bool _OMReader_::read_binary_vertex_chunk(std::istream &_is, BaseImporter &_bi, size_t vidx = 0; switch (chunk_header_.type_) { case Chunk::Type_Pos: - assert( OMFormat::dimensions(chunk_header_) == size_t(OpenMesh::Vec3f::dim())); + 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); + 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; } break; case Chunk::Type_Normal: - 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); + 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); + } } break; diff --git a/src/OpenMesh/Core/IO/writer/OMWriter.cc b/src/OpenMesh/Core/IO/writer/OMWriter.cc index c7a601d6..22fbc755 100644 --- a/src/OpenMesh/Core/IO/writer/OMWriter.cc +++ b/src/OpenMesh/Core/IO/writer/OMWriter.cc @@ -81,7 +81,7 @@ _OMWriter_& OMWriter() { return __OMWriterInstance; } const OMFormat::uchar _OMWriter_::magic_[3] = "OM"; -const OMFormat::uint8 _OMWriter_::version_ = OMFormat::mk_version(2,0); +const OMFormat::uint8 _OMWriter_::version_ = OMFormat::mk_version(2,1); _OMWriter_:: @@ -181,6 +181,7 @@ bool _OMWriter_::write_binary(std::ostream& _os, BaseExporter& _be, unsigned int i, nV, nF; Vec3f v; + Vec3d vd; Vec2f t; // -------------------- write header @@ -211,14 +212,28 @@ bool _OMWriter_::write_binary(std::ostream& _os, BaseExporter& _be, chunk_header.name_ = false; chunk_header.entity_ = OMFormat::Chunk::Entity_Vertex; chunk_header.type_ = OMFormat::Chunk::Type_Pos; - chunk_header.signed_ = OMFormat::is_signed(v[0]); - chunk_header.float_ = OMFormat::is_float(v[0]); - chunk_header.dim_ = OMFormat::dim(v); - chunk_header.bits_ = OMFormat::bits(v[0]); + if (_be.is_point_double()) + { + chunk_header.signed_ = OMFormat::is_signed(vd[0]); + chunk_header.float_ = OMFormat::is_float(vd[0]); + chunk_header.dim_ = OMFormat::dim(vd); + chunk_header.bits_ = OMFormat::bits(vd[0]); + } + else + { + chunk_header.signed_ = OMFormat::is_signed(v[0]); + chunk_header.float_ = OMFormat::is_float(v[0]); + chunk_header.dim_ = OMFormat::dim(v); + chunk_header.bits_ = OMFormat::bits(v[0]); + } bytes += store( _os, chunk_header, swap ); - for (i=0, nV=header.n_vertices_; i Date: Wed, 5 Feb 2020 22:14:27 +0100 Subject: [PATCH 5/8] add missing include and is_double function --- src/OpenMesh/Core/IO/OMFormat.cc | 10 ++++++++++ src/OpenMesh/Core/IO/OMFormat.hh | 7 +++++++ src/OpenMesh/Core/IO/exporter/ExporterT.hh | 1 + 3 files changed, 18 insertions(+) diff --git a/src/OpenMesh/Core/IO/OMFormat.cc b/src/OpenMesh/Core/IO/OMFormat.cc index 97175088..ffe0ffc6 100644 --- a/src/OpenMesh/Core/IO/OMFormat.cc +++ b/src/OpenMesh/Core/IO/OMFormat.cc @@ -246,6 +246,16 @@ namespace OMFormat { } + //----------------------------------------------------------------------------- + + + template<> + bool is_double(const double&) + { + return true; + } + + } // namespace OMFormat // -------------------------------------------------------------------------- diff --git a/src/OpenMesh/Core/IO/OMFormat.hh b/src/OpenMesh/Core/IO/OMFormat.hh index 4e041a34..d66f35d2 100644 --- a/src/OpenMesh/Core/IO/OMFormat.hh +++ b/src/OpenMesh/Core/IO/OMFormat.hh @@ -350,6 +350,13 @@ namespace OMFormat { #endif } + template bool is_double(const T&) + { + return false; + } + + template <> bool is_double(const double&); + template bool is_integer(const T) { #if defined(OM_MISSING_HEADER_LIMITS) diff --git a/src/OpenMesh/Core/IO/exporter/ExporterT.hh b/src/OpenMesh/Core/IO/exporter/ExporterT.hh index 02223122..56332061 100644 --- a/src/OpenMesh/Core/IO/exporter/ExporterT.hh +++ b/src/OpenMesh/Core/IO/exporter/ExporterT.hh @@ -65,6 +65,7 @@ #include #include #include +#include //=== NAMESPACES ============================================================== From 7ee8e6e9f61fa58ca28045d4a43db5d1c4ef1d3b Mon Sep 17 00:00:00 2001 From: Max Lyon Date: Thu, 6 Feb 2020 08:27:47 +0100 Subject: [PATCH 6/8] inline is_double specialization --- src/OpenMesh/Core/IO/OMFormat.cc | 7 ------- src/OpenMesh/Core/IO/OMFormat.hh | 5 ++++- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/OpenMesh/Core/IO/OMFormat.cc b/src/OpenMesh/Core/IO/OMFormat.cc index ffe0ffc6..abebc177 100644 --- a/src/OpenMesh/Core/IO/OMFormat.cc +++ b/src/OpenMesh/Core/IO/OMFormat.cc @@ -249,13 +249,6 @@ namespace OMFormat { //----------------------------------------------------------------------------- - template<> - bool is_double(const double&) - { - return true; - } - - } // namespace OMFormat // -------------------------------------------------------------------------- diff --git a/src/OpenMesh/Core/IO/OMFormat.hh b/src/OpenMesh/Core/IO/OMFormat.hh index d66f35d2..0bc8e3da 100644 --- a/src/OpenMesh/Core/IO/OMFormat.hh +++ b/src/OpenMesh/Core/IO/OMFormat.hh @@ -355,7 +355,10 @@ namespace OMFormat { return false; } - template <> bool is_double(const double&); + template <> inline bool is_double(const double&) + { + return true; + } template bool is_integer(const T) { From 27cab45624869f358651075ddeeb0d0cef303c01 Mon Sep 17 00:00:00 2001 From: Max Lyon Date: Thu, 6 Feb 2020 08:32:01 +0100 Subject: [PATCH 7/8] update docu --- Doc/changelog.docu | 1 + 1 file changed, 1 insertion(+) diff --git a/Doc/changelog.docu b/Doc/changelog.docu index 5b291fd1..e9720768 100644 --- a/Doc/changelog.docu +++ b/Doc/changelog.docu @@ -45,6 +45,7 @@
  • PLY Reader: Fix reading doubles from PLY, missing cast (Thanks to Leo Walsh for the patch)
  • PLY Reader: Some cleanup (Thanks to Morgan Leborgne for the patch)
  • PLY Reader: Support for ushort (Thanks to Morgan Leborgne for the patch)
  • +
  • OM Reader: Positions with scalar type double will be stored as doubles.
  • From d1da33cd1d4790ed0fccb470827f4ee17ad3b60f Mon Sep 17 00:00:00 2001 From: Max Lyon Date: Mon, 10 Feb 2020 09:19:09 +0100 Subject: [PATCH 8/8] write face normals as double --- src/OpenMesh/Core/IO/exporter/BaseExporter.hh | 1 + src/OpenMesh/Core/IO/exporter/ExporterT.hh | 7 +++++ src/OpenMesh/Core/IO/importer/BaseImporter.hh | 5 +++- src/OpenMesh/Core/IO/importer/ImporterT.hh | 6 ++++ src/OpenMesh/Core/IO/reader/OMReader.cc | 29 ++++++++++++++++--- src/OpenMesh/Core/IO/writer/OMWriter.cc | 29 +++++++++++++++---- src/Unittests/unittests_read_write_OM.cc | 15 ++++++++-- 7 files changed, 78 insertions(+), 14 deletions(-) diff --git a/src/OpenMesh/Core/IO/exporter/BaseExporter.hh b/src/OpenMesh/Core/IO/exporter/BaseExporter.hh index 52f451b1..c60181ff 100644 --- a/src/OpenMesh/Core/IO/exporter/BaseExporter.hh +++ b/src/OpenMesh/Core/IO/exporter/BaseExporter.hh @@ -122,6 +122,7 @@ public: virtual unsigned int get_face_texcoords(std::vector& _hehandles) const = 0; virtual Vec3f normal(FaceHandle _fh) const = 0; + virtual Vec3d normald(FaceHandle _fh) const = 0; virtual Vec3uc color (FaceHandle _fh) const = 0; virtual Vec4uc colorA(FaceHandle _fh) const = 0; virtual Vec3ui colori(FaceHandle _fh) const = 0; diff --git a/src/OpenMesh/Core/IO/exporter/ExporterT.hh b/src/OpenMesh/Core/IO/exporter/ExporterT.hh index 56332061..8f9dde90 100644 --- a/src/OpenMesh/Core/IO/exporter/ExporterT.hh +++ b/src/OpenMesh/Core/IO/exporter/ExporterT.hh @@ -328,6 +328,13 @@ public: : Vec3f(0.0f, 0.0f, 0.0f)); } + Vec3d normald(FaceHandle _fh) const override + { + return (mesh_.has_face_normals() + ? vector_cast(mesh_.normal(_fh)) + : Vec3d(0.0, 0.0, 0.0)); + } + Vec3uc color(FaceHandle _fh) const override { return (mesh_.has_face_colors() diff --git a/src/OpenMesh/Core/IO/importer/BaseImporter.hh b/src/OpenMesh/Core/IO/importer/BaseImporter.hh index 8f66ba24..53da0ed0 100644 --- a/src/OpenMesh/Core/IO/importer/BaseImporter.hh +++ b/src/OpenMesh/Core/IO/importer/BaseImporter.hh @@ -126,7 +126,7 @@ public: virtual void set_normal(VertexHandle _vh, const Vec3f& _normal) = 0; // set vertex normal - virtual void set_normal(VertexHandle _vh, const Vec3d& _normal) { set_normal(_vh, Vec3f(_normal)); } + virtual void set_normal(VertexHandle _vh, const Vec3d& _normal) = 0; // set vertex color virtual void set_color(VertexHandle _vh, const Vec3uc& _color) = 0; @@ -182,6 +182,9 @@ public: // set face normal virtual void set_normal(FaceHandle _fh, const Vec3f& _normal) = 0; + // set face normal + virtual void set_normal(FaceHandle _fh, const Vec3d& _normal) = 0; + // set face color virtual void set_color(FaceHandle _fh, const Vec3uc& _color) = 0; diff --git a/src/OpenMesh/Core/IO/importer/ImporterT.hh b/src/OpenMesh/Core/IO/importer/ImporterT.hh index bb223e74..93de5e1b 100644 --- a/src/OpenMesh/Core/IO/importer/ImporterT.hh +++ b/src/OpenMesh/Core/IO/importer/ImporterT.hh @@ -352,6 +352,12 @@ public: mesh_.set_normal(_fh, vector_cast(_normal)); } + virtual void set_normal(FaceHandle _fh, const Vec3d& _normal) override + { + if (mesh_.has_face_normals()) + mesh_.set_normal(_fh, vector_cast(_normal)); + } + virtual void set_color(FaceHandle _fh, const Vec3uc& _color) override { if (mesh_.has_face_colors()) diff --git a/src/OpenMesh/Core/IO/reader/OMReader.cc b/src/OpenMesh/Core/IO/reader/OMReader.cc index 3917fb09..66d4e819 100644 --- a/src/OpenMesh/Core/IO/reader/OMReader.cc +++ b/src/OpenMesh/Core/IO/reader/OMReader.cc @@ -355,6 +355,10 @@ bool _OMReader_::read_binary_vertex_chunk(std::istream &_is, BaseImporter &_bi, _bi.set_normal(VertexHandle(int(vidx)), v3d); } } + else + { + omerr() << "Unknown vertex normal format" << std::endl; + } break; case Chunk::Type_Texcoord: @@ -442,6 +446,7 @@ bool _OMReader_::read_binary_face_chunk(std::istream &_is, BaseImporter &_bi, Op size_t fidx = 0; OpenMesh::Vec3f v3f; // normal + OpenMesh::Vec3d v3d; // normal as double OpenMesh::Vec3uc v3uc; // rgb OpenMesh::Attributes::StatusInfo status; @@ -496,10 +501,26 @@ bool _OMReader_::read_binary_face_chunk(std::istream &_is, BaseImporter &_bi, Op assert( OMFormat::dimensions(chunk_header_) == size_t(OpenMesh::Vec3f::dim())); fileOptions_ += Options::FaceNormal; - 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); + + 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; } break; diff --git a/src/OpenMesh/Core/IO/writer/OMWriter.cc b/src/OpenMesh/Core/IO/writer/OMWriter.cc index 22fbc755..78dfd6d3 100644 --- a/src/OpenMesh/Core/IO/writer/OMWriter.cc +++ b/src/OpenMesh/Core/IO/writer/OMWriter.cc @@ -387,19 +387,36 @@ bool _OMWriter_::write_binary(std::ostream& _os, BaseExporter& _be, { #endif Vec3f n = _be.normal(FaceHandle(0)); + Vec3d nd = _be.normald(FaceHandle(0)); chunk_header.name_ = false; chunk_header.entity_ = OMFormat::Chunk::Entity_Face; chunk_header.type_ = OMFormat::Chunk::Type_Normal; - chunk_header.signed_ = OMFormat::is_signed(n[0]); - chunk_header.float_ = OMFormat::is_float(n[0]); - chunk_header.dim_ = OMFormat::dim(n); - chunk_header.bits_ = OMFormat::bits(n[0]); + + if (_be.is_normal_double()) + { + chunk_header.signed_ = OMFormat::is_signed(nd[0]); + chunk_header.float_ = OMFormat::is_float(nd[0]); + chunk_header.dim_ = OMFormat::dim(nd); + chunk_header.bits_ = OMFormat::bits(nd[0]); + } + else + { + chunk_header.signed_ = OMFormat::is_signed(n[0]); + chunk_header.float_ = OMFormat::is_float(n[0]); + chunk_header.dim_ = OMFormat::dim(n); + chunk_header.bits_ = OMFormat::bits(n[0]); + } bytes += store( _os, chunk_header, swap ); #if !NEW_STYLE - for (i=0, nF=header.n_faces_; istore(_os, swap ); } diff --git a/src/Unittests/unittests_read_write_OM.cc b/src/Unittests/unittests_read_write_OM.cc index 044227e0..35e4522d 100644 --- a/src/Unittests/unittests_read_write_OM.cc +++ b/src/Unittests/unittests_read_write_OM.cc @@ -1482,22 +1482,31 @@ TEST_F(OpenMeshReadWriteOM, WriteAndLoadDoubles) { DoublePolyMesh mesh; mesh.request_vertex_normals(); + mesh.request_face_normals(); - mesh.add_vertex(DoublePolyMesh::Point(1.0/3.0, std::numeric_limits::min(), std::numeric_limits::max())); - mesh.set_normal(OpenMesh::VertexHandle(0), DoublePolyMesh::Normal(1.0/3.0, std::numeric_limits::min(), std::numeric_limits::max())); + std::vector vertices; + for (int i = 0; i < 3; ++i) + { + vertices.push_back(mesh.add_vertex(DoublePolyMesh::Point(1.0/3.0, std::numeric_limits::min(), std::numeric_limits::max()))); + mesh.set_normal(vertices.back(), DoublePolyMesh::Normal(1.0/3.0, std::numeric_limits::min(), std::numeric_limits::max())); + } + auto fh = mesh.add_face(vertices); + mesh.set_normal(fh, DoublePolyMesh::Normal(1.0/3.0, std::numeric_limits::min(), std::numeric_limits::max())); std::string file_name = "doubles.om"; - OpenMesh::IO::Options opt = OpenMesh::IO::Options::VertexNormal; + OpenMesh::IO::Options opt = OpenMesh::IO::Options::VertexNormal | OpenMesh::IO::Options::FaceNormal; ASSERT_TRUE(OpenMesh::IO::write_mesh(mesh, file_name, opt)) << "Could not write file " << file_name; DoublePolyMesh mesh2; mesh2.request_vertex_normals(); + mesh2.request_face_normals(); ASSERT_TRUE(OpenMesh::IO::read_mesh(mesh2, file_name, opt)) << "Could not read file " << file_name; EXPECT_EQ(mesh.point(OpenMesh::VertexHandle(0)), mesh2.point(OpenMesh::VertexHandle(0))); EXPECT_EQ(mesh.normal(OpenMesh::VertexHandle(0)), mesh2.normal(OpenMesh::VertexHandle(0))); + EXPECT_EQ(mesh.normal(OpenMesh::FaceHandle(0)), mesh2.normal(OpenMesh::FaceHandle(0))); } }