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.
diff --git a/src/OpenMesh/Core/IO/OMFormat.cc b/src/OpenMesh/Core/IO/OMFormat.cc
index 97175088..abebc177 100644
--- a/src/OpenMesh/Core/IO/OMFormat.cc
+++ b/src/OpenMesh/Core/IO/OMFormat.cc
@@ -246,6 +246,9 @@ namespace OMFormat {
}
+ //-----------------------------------------------------------------------------
+
+
} // namespace OMFormat
// --------------------------------------------------------------------------
diff --git a/src/OpenMesh/Core/IO/OMFormat.hh b/src/OpenMesh/Core/IO/OMFormat.hh
index 66aaf26a..0bc8e3da 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_);
@@ -350,6 +350,16 @@ namespace OMFormat {
#endif
}
+ template bool is_double(const T&)
+ {
+ return false;
+ }
+
+ template <> inline bool is_double(const double&)
+ {
+ return true;
+ }
+
template bool is_integer(const T)
{
#if defined(OM_MISSING_HEADER_LIMITS)
diff --git a/src/OpenMesh/Core/IO/exporter/BaseExporter.hh b/src/OpenMesh/Core/IO/exporter/BaseExporter.hh
index 86290720..c60181ff 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;
@@ -118,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 9de326ca..8f9dde90 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 ==============================================================
@@ -94,11 +95,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
@@ -305,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 ff86dadd..53da0ed0 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) = 0;
+
// set vertex color
virtual void set_color(VertexHandle _vh, const Vec3uc& _color) = 0;
@@ -176,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 50ee3192..93de5e1b 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())
@@ -336,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 41a4b3a9..66d4e819 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,57 @@ 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);
+ }
+ }
+ else
+ {
+ omerr() << "Unknown vertex normal format" << std::endl;
}
break;
@@ -410,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;
@@ -464,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 c7a601d6..78dfd6d3 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_; istore(_os, swap );
}
diff --git a/src/Unittests/unittests_read_write_OM.cc b/src/Unittests/unittests_read_write_OM.cc
index e138f4cd..35e4522d 100644
--- a/src/Unittests/unittests_read_write_OM.cc
+++ b/src/Unittests/unittests_read_write_OM.cc
@@ -1472,4 +1472,41 @@ 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.request_face_normals();
+
+ 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::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)));
+}
+
}