Commits (45)
......@@ -259,21 +259,6 @@ VS2015-32-bit-static-no-apps:
- build-release/*.exe
VS2013-64-bit-shared-apps:
stage: build
variables:
BUILD_PLATFORM: "VS2013"
ARCHITECTURE: "x64"
SHARED: "TRUE"
APPS: "ON"
script: "CI\\Windows.bat"
tags:
- VS2013
artifacts:
paths:
- build-release/*.exe
VS2013-64-bit-shared-no-apps:
stage: build
variables:
......@@ -288,20 +273,6 @@ VS2013-64-bit-shared-no-apps:
paths:
- build-release/*.exe
VS2013-32-bit-shared-apps:
stage: build
variables:
BUILD_PLATFORM: "VS2013"
ARCHITECTURE: "x32"
SHARED: "TRUE"
APPS: "ON"
script: "CI\\Windows.bat"
tags:
- VS2013
artifacts:
paths:
- build-release/*.exe
VS2013-32-bit-shared-no-apps:
stage: build
variables:
......@@ -316,20 +287,6 @@ VS2013-32-bit-shared-no-apps:
paths:
- build-release/*.exe
VS2013-64-bit-static-apps:
stage: build
variables:
BUILD_PLATFORM: "VS2013"
ARCHITECTURE: "x64"
SHARED: "FALSE"
APPS: "ON"
script: "CI\\Windows.bat"
tags:
- VS2013
artifacts:
paths:
- build-release/*.exe
VS2013-64-bit-static-no-apps:
stage: build
variables:
......@@ -344,20 +301,6 @@ VS2013-64-bit-static-no-apps:
paths:
- build-release/*.exe
VS2013-32-bit-static-apps:
stage: build
variables:
BUILD_PLATFORM: "VS2013"
ARCHITECTURE: "x32"
SHARED: "FALSE"
APPS: "ON"
script: "CI\\Windows.bat"
tags:
- VS2013
artifacts:
paths:
- build-release/*.exe
VS2013-32-bit-static-no-apps:
stage: build
variables:
......
#include <iostream>
#include <vector>
// --------------------
#include <OpenMesh/Core/IO/MeshIO.hh>
#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
#include <OpenMesh/Core/Utils/PropertyManager.hh>
typedef OpenMesh::TriMesh_ArrayKernelT<> MyMesh;
#include <iostream>
#include <vector>
using MyMesh = OpenMesh::TriMesh_ArrayKernelT<>;
int main(int argc, char **argv)
int main(int argc, char** argv)
{
MyMesh mesh;
// check command line options
if (argc != 4)
{
std::cerr << "Usage: " << argv[0] << " #iterations infile outfile\n";
return 1;
}
// read mesh from stdin
if ( ! OpenMesh::IO::read_mesh(mesh, argv[2]) )
{
std::cerr << "Error: Cannot read mesh from " << argv[2] << std::endl;
return 1;
}
// this vertex property stores the computed centers of gravity
OpenMesh::VPropHandleT<MyMesh::Point> cogs;
mesh.add_property(cogs);
// smoothing mesh argv[1] times
MyMesh::VertexIter v_it, v_end(mesh.vertices_end());
MyMesh::VertexVertexIter vv_it;
MyMesh::Point cog;
MyMesh::Scalar valence;
unsigned int i, N(atoi(argv[1]));
for (i=0; i < N; ++i)
{
for (v_it=mesh.vertices_begin(); v_it!=v_end; ++v_it)
{
mesh.property(cogs,*v_it).vectorize(0.0f);
valence = 0.0;
for (vv_it=mesh.vv_iter( *v_it ); vv_it; ++vv_it)
{
mesh.property(cogs,*v_it) += mesh.point( *vv_it );
++valence;
}
mesh.property(cogs,*v_it) /= valence;
// Read command line options
MyMesh mesh;
if (argc != 4) {
std::cerr << "Usage: " << argv[0] << " #iterations infile outfile" << std::endl;
return 1;
}
const int iterations = argv[1];
const std::string infile = argv[2];
const std::string outfile = argv[3];
for (v_it=mesh.vertices_begin(); v_it!=v_end; ++v_it)
if ( !mesh.is_boundary( *v_it ) )
mesh.set_point( *v_it, mesh.property(cogs,*v_it) );
}
// write mesh to stdout
if ( ! OpenMesh::IO::write_mesh(mesh, argv[3]) )
{
std::cerr << "Error: cannot write mesh to " << argv[3] << std::endl;
return 1;
}
// Read mesh file
if (!OpenMesh::IO::read_mesh(mesh, infile)) {
std::cerr << "Error: Cannot read mesh from " << infile << std::endl;
return 1;
}
return 0;
{
// Add a vertex property storing the computed centers of gravity
auto cog = OpenMesh::makeTemporaryProperty<OpenMesh::VertexHandle, MyMesh::Point>(mesh);
// Smooth the mesh several times
for (int i = 0; i < iterations; ++i) {
// Iterate over all vertices to compute centers of gravity
for (const auto& vh : mesh.vertices()) {
cog[vh] = {0,0,0};
int valence = 0;
// Iterate over all 1-ring vertices around vh
for (const auto& vvh : mesh.vv_range(vh)) {
cog[vh] += mesh.point(vvh);
++valence;
}
cog[vh] /= valence;
}
// Move all vertices to the previously computed positions
for (const auto& vh : mesh.vertices()) {
mesh.point(vh) = cog[vh];
}
}
} // The cog vertex property is removed from the mesh at the end of this scope
// Write mesh file
if (!OpenMesh::IO::read_mesh(mesh, outfile)) {
std::cerr << "Error: Cannot write mesh to " << outfile << std::endl;
return 1;
}
}
......@@ -9,6 +9,11 @@
<tr valign=top><td><b>8.0</b> (?/?/?)</td><td>
<b>Breaking changes:</b>
<ul>
<li>Don't run and test on VS2013 anymore. As VS2013 still lacks some C++11 features, we remove it from our list of supported platforms</li>
</ul>
<b>Core</b>
<ul>
<li>TriConnectivity: Added two functions split_edge and split_edge_copy to mask the PolyConnectivity functions of the same name (Prevents creation of valence 2 vertices on trimeshes)</li>
......@@ -18,6 +23,10 @@
<ul>
<li>PLY Reader: Allowing the PLY reader to read custom face ( Thanks to morgan Leborgne for the patch)</li>
<li>PLY Reader: Fixed endless loop on unknown property list type</li>
<li>PLY Reader: Fix hang when reading directly from istream (Thanks to Paul Loré for the patch)</li>
<li>OM Writer/Reader: Update file format version to 2.0. Older files can still be read, but older OpenMesh versions cannot read new format.</li>
<li>OM Writer/Reader: Fixed inconsistent writing/reading of edge properties</li>
<li>OM Writer/Reader: Add option to store status</li>
</ul>
<b>Tools</b>
......
......@@ -12,12 +12,11 @@ supports at least C++11
<table>
<tr><td> Linux </td><td>
gcc >= 4.8.x<br>
gcc >= 6.3<br>
clang >= 3.3<br>
</td></tr>
<tr><td> Windows </td><td>
Microsoft Visual Studio 2013<br>
Microsoft Visual Studio 2015<br>
Microsoft Visual Studio 2017<br>
</td></tr>
......
/** \page tutorial_03 Using (custom) properties
This examples shows:
- How to add and remove custom properties,
- How to add and remove custom properties
- How to get and set the value of a custom property
In the last example we computed the barycenter of each vertex'
......@@ -11,44 +11,69 @@ let %OpenMesh manage the data.
It would be even more helpful if we could attach such properties
dynamically to the mesh.
%OpenMesh provides dynamic properties, which can be attached to each
mesh entity (vertex, face, edge, halfedge, and the mesh itself). We
distinguish between custom and standard properties. A custom property
is any user-defined property and is accessed via the member function
\c property(..) via a handle and an entity handle
(e.g. VertexHandle). Whereas the standard properties are accessed via
special member functions, e.g. the vertex position is accessed with \c
point(..) and a vertex handle.
Custom properties can be conveniently created and attached to meshes with the following functions:
- makeTemporaryProperty() creates a property that is temporary to the current scope.
- getOrMakeProperty() is used for creating and accessing permanent named properties on a mesh.
- getProperty() is used for accessing an existing permanent named property on a mesh.
In this example we will store the \c cog-value (see previous example)
in an additional vertex property instead of keeping it in a separate
array. To do so we define first a so-called property handle with the desired
type (\c MyMesh::Point) and register the handle at the mesh:
All three functions take two template arguments:
- First, the type of the mesh element that the property is attached to (i.e. OpenMesh::VertexHandle, OpenMesh::HalfedgeHandle, OpenMesh::EdgeHandle, or OpenMesh::FaceHandle).
- Second, the type of the property value that is attached to each element (e.g., \p int, \p double, etc.).
All three functions return a handle object (of type OpenMesh::PropertyManager) that manages the lifetime of the property and provides read / write access to its values.
In this example, we will store the \c cog value (see previous example) in a vertex property instead of keeping it in a separate array.
To do so, we first add a (temporary) property of the desired element type (OpenMesh::VertexHandle) and value type (\c %MyMesh::Point) to the mesh:
\dontinclude 03-properties/smooth.cc
\skipline vertex property stores
\until mesh.add
\skipline makeTemporaryProperty
<br>The \c mesh allocates enough memory to hold as many elements of type
\c MyMesh::Point as number of vertices exist, and of course the mesh
synchronizes all insert and delete operations on the vertices with the
vertex properties.
Enough memory is allocated to hold as many values of \c %MyMesh::Point as there are vertices.
All insert and delete operations on the mesh are synchronized with the attached properties.
Once the wanted property is registered we can use the property to
calculate the barycenter of the neighborhood of each vertex \c v_it
Once the property is created, we can use it to compute the centers of the neighborhood of each vertex:
\dontinclude 03-properties/smooth.cc
\skipline vv_it=
\skipline mesh.vertices
\until cog[vh] /= valence
\until }
\until mesh.prop
<br>and finally set the new position for each vertex \c v_it
Finally, we set the new position for each vertex:
\dontinclude 03-properties/smooth.cc
\skipline mesh.set_point
\skipline mesh.vertices
\until mesh.point
\until }
---
Since we chose to use makeTemporaryProperty(), the created property is automatically removed from the mesh as soon as we leave the scope of the associated handle variable \c cog.
If, instead, a property is desired to survive its local scope, it should be created with using getOrMakeProperty(). In that case, the property must be given a name that can later be used to retrieve the property. For example:
\code
auto face_area = OpenMesh::makeTemporaryProperty<OpenMesh::FaceHandle, double>(mesh, 'face_area');
\endcode
At a later time, we can use the getProperty() function to obtain a handle to a property that was previously created by refering to its name:
\code
try {
auto face_area = OpenMesh::getProperty<OpenMesh::FaceHandle, double>(mesh, 'face_area');
// Use the face_area property.
}
catch (const std::runtime_error& e) {
// Property not found. Handle the error here.
}
\endcode
---
The functions makeTemporaryProperty(), getOrMakeProperty(), and getProperty() are the convenient high-level interface for creating and accessing mesh properties.
Beneath these convenience functions, there is also a low-level property interface where handle and property lifetime must be managed manually. This interface is accessed through a mesh's add_property(), remove_property(), and property() functions and several property handle classes (OpenMesh::VPropHandleT, OpenMesh::HPropHandleT, OpenMesh::EPropHandleT, OpenMesh::FPropHandleT, OpenMesh::MPropHandleT).
---
<br>Below is the complete source code:
Below is the complete source code:
\include 03-properties/smooth.cc
*/
\ No newline at end of file
*/
......@@ -21,10 +21,10 @@ https://www.graphics.rwth-aachen.de:9000/OpenMesh/openmesh-python
| Visual Studio Version: | 2017 | 2015 | 2013 |
| -------- | -------- |-------- |-------- |
| 64-Bit shared, with apps | [Download](https://www.graphics.rwth-aachen.de:9000/OpenMesh/OpenMesh/-/jobs/artifacts/master/browse/build-release?job=VS2017-64-bit-shared-apps) | [Download](https://www.graphics.rwth-aachen.de:9000/OpenMesh/OpenMesh/-/jobs/artifacts/master/browse/build-release?job=VS2015-64-bit-shared-apps) | [Download](https://www.graphics.rwth-aachen.de:9000/OpenMesh/OpenMesh/-/jobs/artifacts/master/browse/build-release?job=VS2013-64-bit-shared-apps) |
| 32-Bit shared, with apps | - | [Download](https://www.graphics.rwth-aachen.de:9000/OpenMesh/OpenMesh/-/jobs/artifacts/master/browse/build-release?job=VS2015-32-bit-shared-apps) | [Download](https://www.graphics.rwth-aachen.de:9000/OpenMesh/OpenMesh/-/jobs/artifacts/master/browse/build-release?job=VS2013-32-bit-shared-apps) |
| 64-Bit static, with apps | [Download ](https://www.graphics.rwth-aachen.de:9000/OpenMesh/OpenMesh/-/jobs/artifacts/master/browse/build-release?job=VS2017-64-bit-static-apps) | [Download ](https://www.graphics.rwth-aachen.de:9000/OpenMesh/OpenMesh/-/jobs/artifacts/master/browse/build-release?job=VS2015-64-bit-static-apps) | [Download ](https://www.graphics.rwth-aachen.de:9000/OpenMesh/OpenMesh/-/jobs/artifacts/master/browse/build-release?job=VS2013-64-bit-static-apps) |
| 32-Bit static, with apps | - | [ Download ](https://www.graphics.rwth-aachen.de:9000/OpenMesh/OpenMesh/-/jobs/artifacts/master/browse/build-release?job=VS2015-32-bit-static-apps) | [ Download ](https://www.graphics.rwth-aachen.de:9000/OpenMesh/OpenMesh/-/jobs/artifacts/master/browse/build-release?job=VS2013-32-bit-static-apps) |
| 64-Bit shared, with apps | [Download](https://www.graphics.rwth-aachen.de:9000/OpenMesh/OpenMesh/-/jobs/artifacts/master/browse/build-release?job=VS2017-64-bit-shared-apps) | [Download](https://www.graphics.rwth-aachen.de:9000/OpenMesh/OpenMesh/-/jobs/artifacts/master/browse/build-release?job=VS2015-64-bit-shared-apps) | - |
| 32-Bit shared, with apps | - | [Download](https://www.graphics.rwth-aachen.de:9000/OpenMesh/OpenMesh/-/jobs/artifacts/master/browse/build-release?job=VS2015-32-bit-shared-apps) | - |
| 64-Bit static, with apps | [Download ](https://www.graphics.rwth-aachen.de:9000/OpenMesh/OpenMesh/-/jobs/artifacts/master/browse/build-release?job=VS2017-64-bit-static-apps) | [Download ](https://www.graphics.rwth-aachen.de:9000/OpenMesh/OpenMesh/-/jobs/artifacts/master/browse/build-release?job=VS2015-64-bit-static-apps) | - |
| 32-Bit static, with apps | - | [ Download ](https://www.graphics.rwth-aachen.de:9000/OpenMesh/OpenMesh/-/jobs/artifacts/master/browse/build-release?job=VS2015-32-bit-static-apps) | - |
| 64-Bit shared, no apps | [Download](https://www.graphics.rwth-aachen.de:9000/OpenMesh/OpenMesh/-/jobs/artifacts/master/browse/build-release?job=VS2017-64-bit-shared-no-apps) | [Download](https://www.graphics.rwth-aachen.de:9000/OpenMesh/OpenMesh/-/jobs/artifacts/master/browse/build-release?job=VS2015-64-bit-shared-no-apps) | [Download](https://www.graphics.rwth-aachen.de:9000/OpenMesh/OpenMesh/-/jobs/artifacts/master/browse/build-release?job=VS2013-64-bit-shared-no-apps) |
| 32-Bit shared, no apps | [Download](https://www.graphics.rwth-aachen.de:9000/OpenMesh/OpenMesh/-/jobs/artifacts/master/browse/build-release?job=VS2017-32-bit-shared-no-apps) | [Download](https://www.graphics.rwth-aachen.de:9000/OpenMesh/OpenMesh/-/jobs/artifacts/master/browse/build-release?job=VS2015-32-bit-shared-no-apps) | [Download](https://www.graphics.rwth-aachen.de:9000/OpenMesh/OpenMesh/-/jobs/artifacts/master/browse/build-release?job=VS2013-32-bit-shared-no-apps) |
| 64-Bit static, no apps | [Download ](https://www.graphics.rwth-aachen.de:9000/OpenMesh/OpenMesh/-/jobs/artifacts/master/browse/build-release?job=VS2017-64-bit-static-no-apps) | [Download ](https://www.graphics.rwth-aachen.de:9000/OpenMesh/OpenMesh/-/jobs/artifacts/master/browse/build-release?job=VS2015-64-bit-static-no-apps) | [Download ](https://www.graphics.rwth-aachen.de:9000/OpenMesh/OpenMesh/-/jobs/artifacts/master/browse/build-release?job=VS2013-64-bit-static-no-apps) |
......
......@@ -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)
......
......@@ -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);
......
......@@ -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); }
......
......@@ -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<VertexHandle>& _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; }
};
......
......@@ -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:
......
......@@ -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<VertexHandle> 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<Vec2f>& _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;
......
......@@ -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>(_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<TexCoord2D>(_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<TexCoord3D>(_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>(_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>(_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<Vec2f>& _face_texcoords)
{
// get first halfedge handle
......
......@@ -61,6 +61,7 @@
#include <OpenMesh/Core/Utils/Endian.hh>
#include <OpenMesh/Core/IO/OMFormat.hh>
#include <OpenMesh/Core/IO/reader/OMReader.hh>
#include <OpenMesh/Core/IO/writer/OMWriter.hh>
//=== 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<int>(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;
switch (header_.mesh_) {
case 'T':
nV = 3;
break;
case 'Q':
nV = 4;
break;
}
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);
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.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)));
}
vhandles.push_back(VertexHandle(int(vidx)));
}
_bi.add_face(vhandles);
_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<HalfedgeHandle> 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<int>(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";
......
......@@ -135,6 +135,14 @@ bool _PLYReader_::read(std::istream& _in, BaseImporter& _bi, Options& _opt) {
return false;
}
// Reparse the header
if (!can_u_read(_in)) {
omerr() << "[PLYReader] : Unable to parse header\n";
return false;
}
// filter relevant options for reading
bool swap = _opt.check(Options::Swap);
......@@ -281,12 +289,6 @@ void _PLYReader_::readCustomProperty(std::istream& _in, BaseImporter& _bi, Handl
bool _PLYReader_::read_ascii(std::istream& _in, BaseImporter& _bi, const Options& _opt) const {
// Reparse the header
if (!can_u_read(_in)) {
omerr() << "[PLYReader] : Unable to parse header\n";
return false;
}
unsigned int i, j, k, l, idx;
unsigned int nV;
OpenMesh::Vec3f v, n;
......@@ -507,12 +509,6 @@ bool _PLYReader_::read_ascii(std::istream& _in, BaseImporter& _bi, const Options
bool _PLYReader_::read_binary(std::istream& _in, BaseImporter& _bi, bool /*_swap*/, const Options& _opt) const {
// Reparse the header
if (!can_u_read(_in)) {
omerr() << "[PLYReader] : Unable to parse header\n";
return false;
}
OpenMesh::Vec3f v, n; // Vertex
OpenMesh::Vec2f t; // TexCoords
BaseImporter::VHandles vhandles;
......
......@@ -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<VertexHandle> 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<nE; ++i)
{
auto next_id = _be.get_next_halfedge_id(HalfedgeHandle(static_cast<int>(i)));
auto to_vertex_id = _be.get_to_vertex_id(HalfedgeHandle(static_cast<int>(i)));
auto face_id = _be.get_face_id(HalfedgeHandle(static_cast<int>(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<nV; ++i)
bytes += store( _os, _be.get_halfedge_id(VertexHandle(i)), OMFormat::Chunk::Integer_Size(chunk_header.bits_), swap );
}
// -------------------- write face data
// ---------- write topology
......@@ -293,27 +335,17 @@ bool _OMWriter_::write_binary(std::ostream& _os, BaseExporter& _be,
chunk_header.name_ = false;
chunk_header.entity_ = OMFormat::Chunk::Entity_Face;
chunk_header.type_ = OMFormat::Chunk::Type_Topology;
chunk_header.signed_ = 0;
chunk_header.float_ = 0;
chunk_header.dim_ = OMFormat::Chunk::Dim_1D; // ignored
chunk_header.bits_ = OMFormat::needed_bits(_be.n_vertices());
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, nF=header.n_faces_; i<nF; ++i)
{
//nV = _be.get_vhandles(FaceHandle(i), vhandles);
_be.get_vhandles(FaceHandle(i), vhandles);
if ( header.mesh_ == 'P' )
bytes += store( _os, vhandles.size(), OMFormat::Chunk::Integer_16, swap );
for (size_t j=0; j < vhandles.size(); ++j)
{
using namespace OMFormat;
using namespace GenProg;
bytes += store( _os, vhandles[j].idx(), Chunk::Integer_Size(chunk_header.bits_), swap );
}
auto size = OMFormat::Chunk::Integer_Size(chunk_header.bits_);
bytes += store( _os, _be.get_halfedge_id(FaceHandle(i)), size, swap);
}
}
......@@ -385,6 +417,82 @@ bool _OMWriter_::write_binary(std::ostream& _os, BaseExporter& _be,
#endif
}
// ---------- write vertex status
if (_be.n_vertices() && _be.has_vertex_status() && _opt.check(Options::Status))
{
auto s = _be.status(VertexHandle(0));
chunk_header.name_ = false;
chunk_header.entity_ = OMFormat::Chunk::Entity_Vertex;
chunk_header.type_ = OMFormat::Chunk::Type_Status;
chunk_header.signed_ = false;
chunk_header.float_ = false;
chunk_header.dim_ = OMFormat::Chunk::Dim_1D;
chunk_header.bits_ = OMFormat::bits(s);
// std::clog << chunk_header << std::endl;
bytes += store(_os, chunk_header, swap);
for (i = 0, nV = header.n_vertices_; i < nV; ++i)
bytes += store(_os, _be.status(VertexHandle(i)), swap);
}
// ---------- write edge status
if (_be.n_edges() && _be.has_edge_status() && _opt.check(Options::Status))
{
auto s = _be.status(EdgeHandle(0));
chunk_header.name_ = false;
chunk_header.entity_ = OMFormat::Chunk::Entity_Edge;
chunk_header.type_ = OMFormat::Chunk::Type_Status;
chunk_header.signed_ = false;
chunk_header.float_ = false;
chunk_header.dim_ = OMFormat::Chunk::Dim_1D;
chunk_header.bits_ = OMFormat::bits(s);
// std::clog << chunk_header << std::endl;
bytes += store(_os, chunk_header, swap);
for (i = 0, nV = header.n_edges_; i < nV; ++i)
bytes += store(_os, _be.status(EdgeHandle(i)), swap);
}
// ---------- write halfedge status
if (_be.n_edges() && _be.has_halfedge_status() && _opt.check(Options::Status))
{
auto s = _be.status(HalfedgeHandle(0));
chunk_header.name_ = false;
chunk_header.entity_ = OMFormat::Chunk::Entity_Halfedge;
chunk_header.type_ = OMFormat::Chunk::Type_Status;
chunk_header.signed_ = false;
chunk_header.float_ = false;
chunk_header.dim_ = OMFormat::Chunk::Dim_1D;
chunk_header.bits_ = OMFormat::bits(s);
// std::clog << chunk_header << std::endl;
bytes += store(_os, chunk_header, swap);
for (i = 0, nV = header.n_edges_ * 2; i < nV; ++i)
bytes += store(_os, _be.status(HalfedgeHandle(i)), swap);
}
// ---------- write face status
if (_be.n_faces() && _be.has_face_status() && _opt.check(Options::Status))
{
auto s = _be.status(FaceHandle(0));
chunk_header.name_ = false;
chunk_header.entity_ = OMFormat::Chunk::Entity_Face;
chunk_header.type_ = OMFormat::Chunk::Type_Status;
chunk_header.signed_ = false;
chunk_header.float_ = false;
chunk_header.dim_ = OMFormat::Chunk::Dim_1D;
chunk_header.bits_ = OMFormat::bits(s);
// std::clog << chunk_header << std::endl;
bytes += store(_os, chunk_header, swap);
for (i = 0, nV = header.n_faces_; i < nV; ++i)
bytes += store(_os, _be.status(FaceHandle(i)), swap);
}
// -------------------- write custom properties
......
......@@ -111,10 +111,10 @@ public:
bool write(std::ostream&, BaseExporter&, Options, std::streamsize _precision = 6) const;
size_t binary_size(BaseExporter& _be, Options _opt) const;
static OMFormat::uint8 get_version() { return version_; }
protected:
......
#ifndef HANDLETOPROPHANDLE_HH_
#define HANDLETOPROPHANDLE_HH_
#include <OpenMesh/Core/Mesh/Handles.hh>
#include <OpenMesh/Core/Utils/Property.hh>
namespace OpenMesh {
template<typename ElementT, typename T>
struct HandleToPropHandle {
};
template<typename T>
struct HandleToPropHandle<OpenMesh::VertexHandle, T> {
using type = OpenMesh::VPropHandleT<T>;
};
template<typename T>
struct HandleToPropHandle<OpenMesh::HalfedgeHandle, T> {
using type = OpenMesh::HPropHandleT<T>;
};
template<typename T>
struct HandleToPropHandle<OpenMesh::EdgeHandle, T> {
using type = OpenMesh::EPropHandleT<T>;
};
template<typename T>
struct HandleToPropHandle<OpenMesh::FaceHandle, T> {
using type = OpenMesh::FPropHandleT<T>;
};
template<typename T>
struct HandleToPropHandle<void, T> {
using type = OpenMesh::MPropHandleT<T>;
};
} // namespace OpenMesh
#endif // HANDLETOPROPHANDLE_HH_
\ No newline at end of file
......@@ -49,6 +49,8 @@
#ifndef PROPERTYMANAGER_HH_
#define PROPERTYMANAGER_HH_
#include <OpenMesh/Core/System/config.h>