diff --git a/Doc/changelog.docu b/Doc/changelog.docu
index e977abfa..a68a7daf 100644
--- a/Doc/changelog.docu
+++ b/Doc/changelog.docu
@@ -18,6 +18,9 @@
- PLY Reader: Allowing the PLY reader to read custom face ( Thanks to morgan Leborgne for the patch)
- PLY Reader: Fixed endless loop on unknown property list type
+- OM Writer/Reader: Update file format version to 2.0. Older files can still be read, but older OpenMesh versions cannot read new format.
+- OM Writer/Reader: Fixed inconsistent writing/reading of edge properties
+- OM Writer/Reader: Add option to store status
Tools
diff --git a/src/OpenMesh/Core/IO/OMFormat.cc b/src/OpenMesh/Core/IO/OMFormat.cc
index 231dfacd..0c1a63dd 100644
--- a/src/OpenMesh/Core/IO/OMFormat.cc
+++ b/src/OpenMesh/Core/IO/OMFormat.cc
@@ -113,6 +113,19 @@ namespace OMFormat {
return hdr;
}
+//-----------------------------------------------------------------------------
+
+
+ std::string as_string(uint8 version)
+ {
+ std::stringstream ss;
+ ss << major_version(version);
+ ss << ".";
+ ss << minor_version(version);
+ return ss.str();
+ }
+
+
//-----------------------------------------------------------------------------
const char *as_string(Chunk::Entity e)
diff --git a/src/OpenMesh/Core/IO/OMFormat.hh b/src/OpenMesh/Core/IO/OMFormat.hh
index 9bbcd860..2fef1389 100644
--- a/src/OpenMesh/Core/IO/OMFormat.hh
+++ b/src/OpenMesh/Core/IO/OMFormat.hh
@@ -469,6 +469,8 @@ namespace OMFormat {
// ---------------------------------------- convenience functions
+ std::string as_string(uint8 version);
+
const char *as_string(Chunk::Type t);
const char *as_string(Chunk::Entity e);
const char *as_string(Chunk::Dim d);
diff --git a/src/OpenMesh/Core/IO/Options.hh b/src/OpenMesh/Core/IO/Options.hh
index f2667258..a703273c 100644
--- a/src/OpenMesh/Core/IO/Options.hh
+++ b/src/OpenMesh/Core/IO/Options.hh
@@ -115,7 +115,8 @@ public:
FaceTexCoord = 0x0400, ///< Has (r) / store (w) face texture coordinates
ColorAlpha = 0x0800, ///< Has (r) / store (w) alpha values for colors
ColorFloat = 0x1000, ///< Has (r) / store (w) float values for colors (currently only implemented for PLY and OFF files)
- Custom = 0x2000 ///< Has (r) custom properties (currently only implemented in PLY Reader ASCII version)
+ Custom = 0x2000, ///< Has (r) custom properties (currently only implemented in PLY Reader ASCII version)
+ Status = 0x4000 ///< Has (r) / store (w) status properties
};
public:
@@ -206,10 +207,14 @@ public:
bool vertex_has_normal() const { return check(VertexNormal); }
bool vertex_has_color() const { return check(VertexColor); }
bool vertex_has_texcoord() const { return check(VertexTexCoord); }
+ bool vertex_has_status() const { return check(Status); }
bool edge_has_color() const { return check(EdgeColor); }
+ bool edge_has_status() const { return check(Status); }
+ bool halfedge_has_status() const { return check(Status); }
bool face_has_normal() const { return check(FaceNormal); }
bool face_has_color() const { return check(FaceColor); }
bool face_has_texcoord() const { return check(FaceTexCoord); }
+ bool face_has_status() const { return check(Status); }
bool color_has_alpha() const { return check(ColorAlpha); }
bool color_is_float() const { return check(ColorFloat); }
diff --git a/src/OpenMesh/Core/IO/exporter/BaseExporter.hh b/src/OpenMesh/Core/IO/exporter/BaseExporter.hh
index 477d95a1..bbd2b9e9 100644
--- a/src/OpenMesh/Core/IO/exporter/BaseExporter.hh
+++ b/src/OpenMesh/Core/IO/exporter/BaseExporter.hh
@@ -104,12 +104,14 @@ public:
virtual Vec4f colorAf(VertexHandle _vh) const = 0;
virtual Vec2f texcoord(VertexHandle _vh) const = 0;
virtual Vec2f texcoord(HalfedgeHandle _heh) const = 0;
+ virtual OpenMesh::Attributes::StatusInfo status(VertexHandle _vh) const = 0;
// get face data
virtual unsigned int
get_vhandles(FaceHandle _fh,
std::vector& _vhandles) const=0;
+
///
/// \brief getHeh returns the HalfEdgeHandle that belongs to the face
/// specified by _fh and has a toVertexHandle that corresponds to _vh.
@@ -127,6 +129,7 @@ public:
virtual Vec4ui colorAi(FaceHandle _fh) const = 0;
virtual Vec3f colorf(FaceHandle _fh) const = 0;
virtual Vec4f colorAf(FaceHandle _fh) const = 0;
+ virtual OpenMesh::Attributes::StatusInfo status(FaceHandle _fh) const = 0;
// get edge data
virtual Vec3uc color(EdgeHandle _eh) const = 0;
@@ -135,6 +138,15 @@ public:
virtual Vec4ui colorAi(EdgeHandle _eh) const = 0;
virtual Vec3f colorf(EdgeHandle _eh) const = 0;
virtual Vec4f colorAf(EdgeHandle _eh) const = 0;
+ virtual OpenMesh::Attributes::StatusInfo status(EdgeHandle _eh) const = 0;
+
+ // get halfedge data
+ virtual int get_halfedge_id(VertexHandle _vh) = 0;
+ virtual int get_halfedge_id(FaceHandle _vh) = 0;
+ virtual int get_next_halfedge_id(HalfedgeHandle _heh) = 0;
+ virtual int get_to_vertex_id(HalfedgeHandle _heh) = 0;
+ virtual int get_face_id(HalfedgeHandle _heh) = 0;
+ virtual OpenMesh::Attributes::StatusInfo status(HalfedgeHandle _heh) const = 0;
// get reference to base kernel
virtual const BaseKernel* kernel() { return 0; }
@@ -150,10 +162,14 @@ public:
virtual bool is_triangle_mesh() const { return false; }
virtual bool has_vertex_normals() const { return false; }
virtual bool has_vertex_colors() const { return false; }
+ virtual bool has_vertex_status() const { return false; }
virtual bool has_vertex_texcoords() const { return false; }
virtual bool has_edge_colors() const { return false; }
+ virtual bool has_edge_status() const { return false; }
+ virtual bool has_halfedge_status() const { return false; }
virtual bool has_face_normals() const { return false; }
virtual bool has_face_colors() const { return false; }
+ virtual bool has_face_status() const { return false; }
};
diff --git a/src/OpenMesh/Core/IO/exporter/ExporterT.hh b/src/OpenMesh/Core/IO/exporter/ExporterT.hh
index 9a9d9b3f..84313d2f 100644
--- a/src/OpenMesh/Core/IO/exporter/ExporterT.hh
+++ b/src/OpenMesh/Core/IO/exporter/ExporterT.hh
@@ -171,6 +171,13 @@ public:
: Vec2f(0.0f, 0.0f));
}
+ OpenMesh::Attributes::StatusInfo status(VertexHandle _vh) const
+ {
+ if (mesh_.has_vertex_status())
+ return mesh_.status(_vh);
+ return OpenMesh::Attributes::StatusInfo();
+ }
+
// get edge data
Vec3uc color(EdgeHandle _eh) const
@@ -215,6 +222,47 @@ public:
: Vec4f(0, 0, 0, 0));
}
+ OpenMesh::Attributes::StatusInfo status(EdgeHandle _eh) const
+ {
+ if (mesh_.has_edge_status())
+ return mesh_.status(_eh);
+ return OpenMesh::Attributes::StatusInfo();
+ }
+
+ // get halfedge data
+
+ int get_halfedge_id(VertexHandle _vh) override
+ {
+ return mesh_.halfedge_handle(_vh).idx();
+ }
+
+ int get_halfedge_id(FaceHandle _fh) override
+ {
+ return mesh_.halfedge_handle(_fh).idx();
+ }
+
+ int get_next_halfedge_id(HalfedgeHandle _heh) override
+ {
+ return mesh_.next_halfedge_handle(_heh).idx();
+ }
+
+ int get_to_vertex_id(HalfedgeHandle _heh) override
+ {
+ return mesh_.to_vertex_handle(_heh).idx();
+ }
+
+ int get_face_id(HalfedgeHandle _heh) override
+ {
+ return mesh_.face_handle(_heh).idx();
+ }
+
+ OpenMesh::Attributes::StatusInfo status(HalfedgeHandle _heh) const
+ {
+ if (mesh_.has_halfedge_status())
+ return mesh_.status(_heh);
+ return OpenMesh::Attributes::StatusInfo();
+ }
+
// get face data
unsigned int get_vhandles(FaceHandle _fh,
@@ -304,6 +352,13 @@ public:
: Vec4f(0, 0, 0, 0));
}
+ OpenMesh::Attributes::StatusInfo status(FaceHandle _fh) const
+ {
+ if (mesh_.has_face_status())
+ return mesh_.status(_fh);
+ return OpenMesh::Attributes::StatusInfo();
+ }
+
virtual const BaseKernel* kernel() { return &mesh_; }
@@ -320,9 +375,13 @@ public:
bool has_vertex_normals() const { return mesh_.has_vertex_normals(); }
bool has_vertex_colors() const { return mesh_.has_vertex_colors(); }
bool has_vertex_texcoords() const { return mesh_.has_vertex_texcoords2D(); }
+ bool has_vertex_status() const { return mesh_.has_vertex_status(); }
bool has_edge_colors() const { return mesh_.has_edge_colors(); }
+ bool has_edge_status() const { return mesh_.has_edge_status(); }
+ bool has_halfedge_status() const { return mesh_.has_halfedge_status(); }
bool has_face_normals() const { return mesh_.has_face_normals(); }
bool has_face_colors() const { return mesh_.has_face_colors(); }
+ bool has_face_status() const { return mesh_.has_face_status(); }
private:
diff --git a/src/OpenMesh/Core/IO/importer/BaseImporter.hh b/src/OpenMesh/Core/IO/importer/BaseImporter.hh
index afcfd6ca..46630a5b 100644
--- a/src/OpenMesh/Core/IO/importer/BaseImporter.hh
+++ b/src/OpenMesh/Core/IO/importer/BaseImporter.hh
@@ -99,10 +99,16 @@ public:
// add a vertex without coordinate. Use set_point to set the position deferred
virtual VertexHandle add_vertex() = 0;
+ // add an edge. Use set_next, set_vertex and set_face to set corresponding entities for halfedges
+ virtual HalfedgeHandle add_edge(VertexHandle _vh0, VertexHandle _vh1) = 0;
+
// add a face with indices _indices refering to vertices
typedef std::vector VHandles;
virtual FaceHandle add_face(const VHandles& _indices) = 0;
+ // add a face with incident halfedge
+ virtual FaceHandle add_face(HalfedgeHandle _heh) = 0;
+
// add texture coordinates per face, _vh references the first texcoord
virtual void add_face_texcoords( FaceHandle _fh, VertexHandle _vh, const std::vector& _face_texcoords) = 0;
@@ -115,6 +121,9 @@ public:
// Set coordinate of the given vertex. Use this function, if you created a vertex without coordinate
virtual void set_point(VertexHandle _vh, const Vec3f& _point) = 0;
+ // Set outgoing halfedge for the given vertex.
+ virtual void set_halfedge(VertexHandle _vh, HalfedgeHandle _heh) = 0;
+
// set vertex normal
virtual void set_normal(VertexHandle _vh, const Vec3f& _normal) = 0;
@@ -133,6 +142,15 @@ public:
// set vertex texture coordinate
virtual void set_texcoord(VertexHandle _vh, const Vec2f& _texcoord) = 0;
+ // set vertex status
+ virtual void set_status(VertexHandle _vh, const OpenMesh::Attributes::StatusInfo& _status) = 0;
+
+ // set next halfedge handle
+ virtual void set_next(HalfedgeHandle _heh, HalfedgeHandle _next) = 0;
+
+ // set incident face handle for given halfedge
+ virtual void set_face(HalfedgeHandle _heh, FaceHandle _fh) = 0;
+
// set vertex texture coordinate
virtual void set_texcoord(HalfedgeHandle _heh, const Vec2f& _texcoord) = 0;
@@ -142,6 +160,9 @@ public:
// set 3d vertex texture coordinate
virtual void set_texcoord(HalfedgeHandle _heh, const Vec3f& _texcoord) = 0;
+ // set halfedge status
+ virtual void set_status(HalfedgeHandle _heh, const OpenMesh::Attributes::StatusInfo& _status) = 0;
+
// set edge color
virtual void set_color(EdgeHandle _eh, const Vec3uc& _color) = 0;
@@ -154,6 +175,9 @@ public:
// set edge color
virtual void set_color(EdgeHandle _eh, const Vec4f& _color) = 0;
+ // set edge status
+ virtual void set_status(EdgeHandle _eh, const OpenMesh::Attributes::StatusInfo& _status) = 0;
+
// set face normal
virtual void set_normal(FaceHandle _fh, const Vec3f& _normal) = 0;
@@ -169,6 +193,9 @@ public:
// set face color
virtual void set_color(FaceHandle _fh, const Vec4f& _color) = 0;
+ // set face status
+ virtual void set_status(FaceHandle _fh, const OpenMesh::Attributes::StatusInfo& _status) = 0;
+
// Store a property in the mesh mapping from an int to a texture file
// Use set_face_texindex to set the index for each face
virtual void add_texture_information( int _id , std::string _name ) = 0;
diff --git a/src/OpenMesh/Core/IO/importer/ImporterT.hh b/src/OpenMesh/Core/IO/importer/ImporterT.hh
index fb6b6690..d95e1cbe 100644
--- a/src/OpenMesh/Core/IO/importer/ImporterT.hh
+++ b/src/OpenMesh/Core/IO/importer/ImporterT.hh
@@ -107,6 +107,11 @@ public:
return mesh_.new_vertex();
}
+ virtual HalfedgeHandle add_edge(VertexHandle _vh0, VertexHandle _vh1) override
+ {
+ return mesh_.new_edge(_vh0, _vh1);
+ }
+
virtual FaceHandle add_face(const VHandles& _indices)
{
FaceHandle fh;
@@ -192,6 +197,13 @@ public:
return fh;
}
+ virtual FaceHandle add_face(HalfedgeHandle _heh) override
+ {
+ auto fh = mesh_.new_face();
+ mesh_.set_halfedge_handle(fh, _heh);
+ return fh;
+ }
+
// vertex attributes
virtual void set_point(VertexHandle _vh, const Vec3f& _point)
@@ -199,6 +211,11 @@ public:
mesh_.set_point(_vh,vector_cast(_point));
}
+ virtual void set_halfedge(VertexHandle _vh, HalfedgeHandle _heh) override
+ {
+ mesh_.set_halfedge_handle(_vh, _heh);
+ }
+
virtual void set_normal(VertexHandle _vh, const Vec3f& _normal)
{
if (mesh_.has_vertex_normals())
@@ -240,6 +257,24 @@ public:
mesh_.set_texcoord2D(_vh, vector_cast(_texcoord));
}
+ virtual void set_status(VertexHandle _vh, const OpenMesh::Attributes::StatusInfo& _status)
+ {
+ if (!mesh_.has_vertex_status())
+ mesh_.request_vertex_status();
+ mesh_.status(_vh) = _status;
+ }
+
+ virtual void set_next(HalfedgeHandle _heh, HalfedgeHandle _next) override
+ {
+ mesh_.set_next_halfedge_handle(_heh, _next);
+ }
+
+ virtual void set_face(HalfedgeHandle _heh, FaceHandle _fh) override
+ {
+ mesh_.set_face_handle(_heh, _fh);
+ }
+
+
virtual void set_texcoord(HalfedgeHandle _heh, const Vec2f& _texcoord)
{
if (mesh_.has_halfedge_texcoords2D())
@@ -258,6 +293,12 @@ public:
mesh_.set_texcoord3D(_heh, vector_cast(_texcoord));
}
+ virtual void set_status(HalfedgeHandle _heh, const OpenMesh::Attributes::StatusInfo& _status)
+ {
+ if (!mesh_.has_halfedge_status())
+ mesh_.request_halfedge_status();
+ mesh_.status(_heh) = _status;
+ }
// edge attributes
@@ -285,6 +326,13 @@ public:
mesh_.set_color(_eh, color_cast(_color));
}
+ virtual void set_status(EdgeHandle _eh, const OpenMesh::Attributes::StatusInfo& _status)
+ {
+ if (!mesh_.has_edge_status())
+ mesh_.request_edge_status();
+ mesh_.status(_eh) = _status;
+ }
+
// face attributes
virtual void set_normal(FaceHandle _fh, const Vec3f& _normal)
@@ -317,6 +365,13 @@ public:
mesh_.set_color(_fh, color_cast(_color));
}
+ virtual void set_status(FaceHandle _fh, const OpenMesh::Attributes::StatusInfo& _status)
+ {
+ if (!mesh_.has_face_status())
+ mesh_.request_face_status();
+ mesh_.status(_fh) = _status;
+ }
+
virtual void add_face_texcoords( FaceHandle _fh, VertexHandle _vh, const std::vector& _face_texcoords)
{
// get first halfedge handle
diff --git a/src/OpenMesh/Core/IO/reader/OMReader.cc b/src/OpenMesh/Core/IO/reader/OMReader.cc
index b66684eb..ca4655dd 100644
--- a/src/OpenMesh/Core/IO/reader/OMReader.cc
+++ b/src/OpenMesh/Core/IO/reader/OMReader.cc
@@ -61,6 +61,7 @@
#include
#include
#include
+#include
//=== NAMESPACES ==============================================================
@@ -176,6 +177,15 @@ bool _OMReader_::read_binary(std::istream& _is, BaseImporter& _bi, Options& _opt
bytes_ += restore(_is, header_, swap);
+ 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;
+ }
+
+
while (!_is.eof()) {
bytes_ += restore(_is, chunk_header_, swap);
@@ -294,6 +304,7 @@ bool _OMReader_::read_binary_vertex_chunk(std::istream &_is, BaseImporter &_bi,
OpenMesh::Vec3f v3f;
OpenMesh::Vec2f v2f;
OpenMesh::Vec3uc v3uc; // rgb
+ OpenMesh::Attributes::StatusInfo status;
OMFormat::Chunk::PropertyName custom_prop;
@@ -343,6 +354,20 @@ bool _OMReader_::read_binary_vertex_chunk(std::istream &_is, BaseImporter &_bi,
}
break;
+ 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;
+ }
+
case Chunk::Type_Custom:
bytes_ += restore_binary_custom_data(_is, _bi.kernel()->_get_vprop(property_name_), header_.n_vertices_, _swap);
@@ -351,6 +376,19 @@ bool _OMReader_::read_binary_vertex_chunk(std::istream &_is, BaseImporter &_bi,
break;
+ case Chunk::Type_Topology:
+ {
+ for (; vidx < header_.n_vertices_; ++vidx)
+ {
+ int halfedge_id;
+ bytes_ += restore( _is, halfedge_id, OMFormat::Chunk::Integer_Size(chunk_header_.bits_), _swap );
+
+ _bi.set_halfedge(VertexHandle(static_cast(vidx)), HalfedgeHandle(halfedge_id));
+ }
+ }
+
+ break;
+
default: // skip unknown chunks
{
omerr() << "Unknown chunk type ignored!\n";
@@ -376,34 +414,51 @@ bool _OMReader_::read_binary_face_chunk(std::istream &_is, BaseImporter &_bi, Op
size_t fidx = 0;
OpenMesh::Vec3f v3f; // normal
OpenMesh::Vec3uc v3uc; // rgb
+ OpenMesh::Attributes::StatusInfo status;
switch (chunk_header_.type_) {
- case Chunk::Type_Topology: {
- BaseImporter::VHandles vhandles;
- size_t nV = 0;
- size_t vidx = 0;
+ 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;
- }
-
- for (; fidx < header_.n_faces_; ++fidx) {
- if (header_.mesh_ == 'P')
- bytes_ += restore(_is, nV, Chunk::Integer_16, _swap);
-
- vhandles.clear();
- for (size_t j = 0; j < nV; ++j) {
- bytes_ += restore(_is, vidx, Chunk::Integer_Size(chunk_header_.bits_), _swap);
-
- vhandles.push_back(VertexHandle(int(vidx)));
+ switch (header_.mesh_) {
+ case 'T':
+ nV = 3;
+ break;
+ case 'Q':
+ nV = 4;
+ break;
}
- _bi.add_face(vhandles);
+ for (; fidx < header_.n_faces_; ++fidx) {
+ if (header_.mesh_ == 'P')
+ bytes_ += restore(_is, nV, Chunk::Integer_16, _swap);
+
+ vhandles.clear();
+ for (size_t j = 0; j < nV; ++j) {
+ bytes_ += restore(_is, vidx, Chunk::Integer_Size(chunk_header_.bits_), _swap);
+
+ vhandles.push_back(VertexHandle(int(vidx)));
+ }
+
+ _bi.add_face(vhandles);
+ }
+ }
+ else
+ {
+ // add faces by simply setting an incident halfedge
+ for (; fidx < header_.n_faces_; ++fidx)
+ {
+ int halfedge_id;
+ bytes_ += restore( _is, halfedge_id, OMFormat::Chunk::Integer_Size(chunk_header_.bits_), _swap );
+
+ _bi.add_face(HalfedgeHandle(halfedge_id));
+ }
}
}
break;
@@ -430,6 +485,19 @@ bool _OMReader_::read_binary_face_chunk(std::istream &_is, BaseImporter &_bi, Op
_bi.set_color(FaceHandle(int(fidx)), v3uc);
}
break;
+ 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;
+ }
case Chunk::Type_Custom:
@@ -453,7 +521,7 @@ bool _OMReader_::read_binary_face_chunk(std::istream &_is, BaseImporter &_bi, Op
//-----------------------------------------------------------------------------
-bool _OMReader_::read_binary_edge_chunk(std::istream &_is, BaseImporter &_bi, Options &/*_opt */, bool _swap) const
+bool _OMReader_::read_binary_edge_chunk(std::istream &_is, BaseImporter &_bi, Options &_opt, bool _swap) const
{
using OMFormat::Chunk;
@@ -461,6 +529,8 @@ bool _OMReader_::read_binary_edge_chunk(std::istream &_is, BaseImporter &_bi, Op
size_t b = bytes_;
+ OpenMesh::Attributes::StatusInfo status;
+
switch (chunk_header_.type_) {
case Chunk::Type_Custom:
@@ -468,6 +538,20 @@ bool _OMReader_::read_binary_edge_chunk(std::istream &_is, BaseImporter &_bi, Op
break;
+ case Chunk::Type_Status:
+ {
+ assert( OMFormat::dimensions(chunk_header_) == 1);
+
+ fileOptions_ += Options::Status;
+
+ for (size_t eidx = 0; eidx < header_.n_edges_ && !_is.eof(); ++eidx) {
+ bytes_ += restore(_is, status, _swap);
+ if (fileOptions_.edge_has_status() && _opt.edge_has_status())
+ _bi.set_status(EdgeHandle(int(eidx)), status);
+ }
+ break;
+ }
+
default:
// skip unknown type
size_t size_of = OMFormat::chunk_data_size(header_, chunk_header_);
@@ -481,13 +565,14 @@ bool _OMReader_::read_binary_edge_chunk(std::istream &_is, BaseImporter &_bi, Op
//-----------------------------------------------------------------------------
-bool _OMReader_::read_binary_halfedge_chunk(std::istream &_is, BaseImporter &_bi, Options &/* _opt */, bool _swap) const
+bool _OMReader_::read_binary_halfedge_chunk(std::istream &_is, BaseImporter &_bi, Options & _opt, bool _swap) const
{
using OMFormat::Chunk;
assert( chunk_header_.entity_ == Chunk::Entity_Halfedge);
size_t b = bytes_;
+ OpenMesh::Attributes::StatusInfo status;
switch (chunk_header_.type_) {
case Chunk::Type_Custom:
@@ -495,6 +580,55 @@ bool _OMReader_::read_binary_halfedge_chunk(std::istream &_is, BaseImporter &_bi
bytes_ += restore_binary_custom_data(_is, _bi.kernel()->_get_hprop(property_name_), 2 * header_.n_edges_, _swap);
break;
+ case Chunk::Type_Topology:
+ {
+ std::vector next_halfedges;
+ for (size_t e_idx = 0; e_idx < header_.n_edges_; ++e_idx)
+ {
+ int next_id_0;
+ int to_vertex_id_0;
+ int face_id_0;
+ 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 );
+
+ int next_id_1;
+ int to_vertex_id_1;
+ int face_id_1;
+ 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(i)), next_halfedges[i]);
+ }
+
+ break;
+
+ case Chunk::Type_Status:
+ {
+ assert( OMFormat::dimensions(chunk_header_) == 1);
+
+ fileOptions_ += Options::Status;
+
+ for (size_t hidx = 0; hidx < header_.n_edges_ * 2 && !_is.eof(); ++hidx) {
+ bytes_ += restore(_is, status, _swap);
+ if (fileOptions_.halfedge_has_status() && _opt.halfedge_has_status())
+ _bi.set_status(HalfedgeHandle(int(hidx)), status);
+ }
+ break;
+ }
+
default:
// skip unknown chunk
omerr() << "Unknown chunk type ignored!\n";
diff --git a/src/OpenMesh/Core/IO/writer/OMWriter.cc b/src/OpenMesh/Core/IO/writer/OMWriter.cc
index 9c32282f..ffcbbce4 100644
--- a/src/OpenMesh/Core/IO/writer/OMWriter.cc
+++ b/src/OpenMesh/Core/IO/writer/OMWriter.cc
@@ -86,7 +86,7 @@ _OMWriter_& OMWriter() { return __OMWriterInstance; }
const OMFormat::uchar _OMWriter_::magic_[3] = "OM";
-const OMFormat::uint8 _OMWriter_::version_ = OMFormat::mk_version(1,2);
+const OMFormat::uint8 _OMWriter_::version_ = OMFormat::mk_version(2,0);
_OMWriter_::
@@ -187,8 +187,6 @@ bool _OMWriter_::write_binary(std::ostream& _os, BaseExporter& _be,
unsigned int i, nV, nF;
Vec3f v;
Vec2f t;
- std::vector vhandles;
-
// -------------------- write header
OMFormat::Header header;
@@ -286,6 +284,50 @@ bool _OMWriter_::write_binary(std::ostream& _os, BaseExporter& _be,
}
+ // ---------- wirte halfedge data
+ if (_be.n_edges())
+ {
+ chunk_header.reserved_ = 0;
+ chunk_header.name_ = false;
+ chunk_header.entity_ = OMFormat::Chunk::Entity_Halfedge;
+ chunk_header.type_ = OMFormat::Chunk::Type_Topology;
+ chunk_header.signed_ = true;
+ chunk_header.float_ = true; // TODO: is this correct? This causes a scalar size of 1 in OMFormat.hh scalar_size which we need I think?
+ chunk_header.dim_ = OMFormat::Chunk::Dim_3D;
+ chunk_header.bits_ = OMFormat::needed_bits(_be.n_edges()*4); // *2 due to halfedge ids being stored, *2 due to signedness
+
+ bytes += store( _os, chunk_header, swap );
+ auto nE=header.n_edges_*2;
+ for (i=0; i(i)));
+ auto to_vertex_id = _be.get_to_vertex_id(HalfedgeHandle(static_cast(i)));
+ auto face_id = _be.get_face_id(HalfedgeHandle(static_cast(i)));
+
+ bytes += store( _os, next_id, OMFormat::Chunk::Integer_Size(chunk_header.bits_), swap );
+ bytes += store( _os, to_vertex_id, OMFormat::Chunk::Integer_Size(chunk_header.bits_), swap );
+ bytes += store( _os, face_id, OMFormat::Chunk::Integer_Size(chunk_header.bits_), swap );
+ }
+ }
+
+ // ---------- write vertex topology (outgoing halfedge)
+ if (_be.n_vertices())
+ {
+ chunk_header.reserved_ = 0;
+ chunk_header.name_ = false;
+ chunk_header.entity_ = OMFormat::Chunk::Entity_Vertex;
+ chunk_header.type_ = OMFormat::Chunk::Type_Topology;
+ chunk_header.signed_ = true;
+ chunk_header.float_ = true; // TODO: is this correct? This causes a scalar size of 1 in OMFormat.hh scalar_size which we need I think?
+ chunk_header.dim_ = OMFormat::Chunk::Dim_1D;
+ chunk_header.bits_ = OMFormat::needed_bits(_be.n_edges()*4); // *2 due to halfedge ids being stored, *2 due to signedness
+
+ bytes += store( _os, chunk_header, swap );
+ for (i=0, nV=header.n_vertices_; i prop;
+ mesh.add_property(prop,propName);
+ mesh.property(prop).set_persistent(true);
+
+ Mesh::EdgeHandle e1 = Mesh::EdgeHandle(0);
+ Mesh::EdgeHandle e2 = Mesh::EdgeHandle(1);
+ Mesh::EdgeHandle e3 = Mesh::EdgeHandle(2);
+ Mesh::EdgeHandle e4 = Mesh::EdgeHandle(3);
+ Mesh::EdgeHandle e5 = Mesh::EdgeHandle(4);
+ Mesh::EdgeHandle e6 = Mesh::EdgeHandle(5);
+
+ int value1 = 10,
+ value2 = 21,
+ value3 = 32,
+ value4 = 43,
+ value5 = 54,
+ value6 = 65;
+
+ mesh.property(prop,e1) = value1;
+ mesh.property(prop,e2) = value2;
+ mesh.property(prop,e3) = value3;
+ mesh.property(prop,e4) = value4;
+ mesh.property(prop,e5) = value5;
+ mesh.property(prop,e6) = value6;
+
+ // save
+ OpenMesh::IO::Options options;
+ bool ok = OpenMesh::IO::write_mesh(mesh,filename);
+ EXPECT_TRUE(ok) << "Unable to write "< vertex_deleted;
+ std::vector vertex_selected;
+ std::vector vertex_feature;
+ std::vector vertex_tagged;
+ std::vector vertex_tagged2;
+
+ for (auto vh : mesh.all_vertices())
+ {
+ vertex_deleted.push_back(mesh.status(vh).deleted());
+ vertex_selected.push_back(mesh.status(vh).selected());
+ vertex_feature.push_back(mesh.status(vh).feature());
+ vertex_tagged.push_back(mesh.status(vh).tagged());
+ vertex_tagged2.push_back(mesh.status(vh).tagged2());
+ }
+
+ Mesh::EdgeHandle e1 = Mesh::EdgeHandle(0);
+ Mesh::EdgeHandle e2 = Mesh::EdgeHandle(1);
+ Mesh::EdgeHandle e3 = Mesh::EdgeHandle(2);
+ Mesh::EdgeHandle e4 = Mesh::EdgeHandle(3);
+
+ mesh.status(e1).set_selected(true);
+ mesh.status(e2).set_feature(true);
+ mesh.status(e3).set_tagged(true);
+ mesh.status(e4).set_tagged2(true);
+
+ std::vector edge_deleted;
+ std::vector edge_selected;
+ std::vector edge_feature;
+ std::vector edge_tagged;
+ std::vector edge_tagged2;
+
+ for (auto eh : mesh.all_edges())
+ {
+ edge_deleted.push_back(mesh.status(eh).deleted());
+ edge_selected.push_back(mesh.status(eh).selected());
+ edge_feature.push_back(mesh.status(eh).feature());
+ edge_tagged.push_back(mesh.status(eh).tagged());
+ edge_tagged2.push_back(mesh.status(eh).tagged2());
+ }
+
+
+ Mesh::HalfedgeHandle he1 = Mesh::HalfedgeHandle(0);
+ Mesh::HalfedgeHandle he2 = Mesh::HalfedgeHandle(3);
+ Mesh::HalfedgeHandle he3 = Mesh::HalfedgeHandle(5);
+ Mesh::HalfedgeHandle he4 = Mesh::HalfedgeHandle(1);
+
+ mesh.status(he1).set_selected(true);
+ mesh.status(he2).set_feature(true);
+ mesh.status(he3).set_tagged(true);
+ mesh.status(he4).set_tagged2(true);
+
+ std::vector halfedge_deleted;
+ std::vector halfedge_selected;
+ std::vector halfedge_feature;
+ std::vector halfedge_tagged;
+ std::vector halfedge_tagged2;
+
+ for (auto heh : mesh.all_halfedges())
+ {
+ halfedge_deleted.push_back(mesh.status(heh).deleted());
+ halfedge_selected.push_back(mesh.status(heh).selected());
+ halfedge_feature.push_back(mesh.status(heh).feature());
+ halfedge_tagged.push_back(mesh.status(heh).tagged());
+ halfedge_tagged2.push_back(mesh.status(heh).tagged2());
+ }
+
+ Mesh::FaceHandle f1 = Mesh::FaceHandle(0);
+ Mesh::FaceHandle f2 = Mesh::FaceHandle(2);
+ Mesh::FaceHandle f3 = Mesh::FaceHandle(1);
+ Mesh::FaceHandle f4 = Mesh::FaceHandle(2);
+
+ mesh.status(f1).set_selected(true);
+ mesh.status(f2).set_feature(true);
+ mesh.status(f3).set_tagged(true);
+ mesh.status(f4).set_tagged2(true);
+
+ std::vector face_deleted;
+ std::vector face_selected;
+ std::vector face_feature;
+ std::vector face_tagged;
+ std::vector face_tagged2;
+
+ for (auto fh : mesh.all_faces())
+ {
+ face_deleted.push_back(mesh.status(fh).deleted());
+ face_selected.push_back(mesh.status(fh).selected());
+ face_feature.push_back(mesh.status(fh).feature());
+ face_tagged.push_back(mesh.status(fh).tagged());
+ face_tagged2.push_back(mesh.status(fh).tagged2());
+ }
+
+ // save
+ OpenMesh::IO::Options options = OpenMesh::IO::Options::Status;
+ bool ok = OpenMesh::IO::write_mesh(mesh,filename, options);
+ EXPECT_TRUE(ok) << "Unable to write "<