From d1da33cd1d4790ed0fccb470827f4ee17ad3b60f Mon Sep 17 00:00:00 2001 From: Max Lyon Date: Mon, 10 Feb 2020 09:19:09 +0100 Subject: [PATCH] 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))); } }