初始化内容
This commit is contained in:
@@ -0,0 +1,138 @@
|
||||
/* ========================================================================= *
|
||||
* *
|
||||
* OpenMesh *
|
||||
* Copyright (c) 2001-2015, RWTH-Aachen University *
|
||||
* Department of Computer Graphics and Multimedia *
|
||||
* All rights reserved. *
|
||||
* www.openmesh.org *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* This file is part of OpenMesh. *
|
||||
*---------------------------------------------------------------------------*
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or without *
|
||||
* modification, are permitted provided that the following conditions *
|
||||
* are met: *
|
||||
* *
|
||||
* 1. Redistributions of source code must retain the above copyright notice, *
|
||||
* this list of conditions and the following disclaimer. *
|
||||
* *
|
||||
* 2. Redistributions in binary form must reproduce the above copyright *
|
||||
* notice, this list of conditions and the following disclaimer in the *
|
||||
* documentation and/or other materials provided with the distribution. *
|
||||
* *
|
||||
* 3. Neither the name of the copyright holder nor the names of its *
|
||||
* contributors may be used to endorse or promote products derived from *
|
||||
* this software without specific prior written permission. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
|
||||
* *
|
||||
* ========================================================================= */
|
||||
|
||||
|
||||
#include <iostream>
|
||||
// -------------------- OpenMesh
|
||||
#include <OpenMesh/Core/IO/MeshIO.hh>
|
||||
#include <OpenMesh/Core/Mesh/PolyMesh_ArrayKernelT.hh>
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
typedef OpenMesh::PolyMesh_ArrayKernelT<> MyMesh;
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Build a simple cube and write it to std::cout
|
||||
|
||||
int main()
|
||||
{
|
||||
MyMesh mesh;
|
||||
|
||||
// generate vertices
|
||||
|
||||
MyMesh::VertexHandle vhandle[8];
|
||||
|
||||
vhandle[0] = mesh.add_vertex(MyMesh::Point(-1, -1, 1));
|
||||
vhandle[1] = mesh.add_vertex(MyMesh::Point( 1, -1, 1));
|
||||
vhandle[2] = mesh.add_vertex(MyMesh::Point( 1, 1, 1));
|
||||
vhandle[3] = mesh.add_vertex(MyMesh::Point(-1, 1, 1));
|
||||
vhandle[4] = mesh.add_vertex(MyMesh::Point(-1, -1, -1));
|
||||
vhandle[5] = mesh.add_vertex(MyMesh::Point( 1, -1, -1));
|
||||
vhandle[6] = mesh.add_vertex(MyMesh::Point( 1, 1, -1));
|
||||
vhandle[7] = mesh.add_vertex(MyMesh::Point(-1, 1, -1));
|
||||
|
||||
|
||||
// generate (quadrilateral) faces
|
||||
|
||||
std::vector<MyMesh::VertexHandle> face_vhandles;
|
||||
|
||||
face_vhandles.clear();
|
||||
face_vhandles.push_back(vhandle[0]);
|
||||
face_vhandles.push_back(vhandle[1]);
|
||||
face_vhandles.push_back(vhandle[2]);
|
||||
face_vhandles.push_back(vhandle[3]);
|
||||
mesh.add_face(face_vhandles);
|
||||
|
||||
face_vhandles.clear();
|
||||
face_vhandles.push_back(vhandle[7]);
|
||||
face_vhandles.push_back(vhandle[6]);
|
||||
face_vhandles.push_back(vhandle[5]);
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
mesh.add_face(face_vhandles);
|
||||
|
||||
face_vhandles.clear();
|
||||
face_vhandles.push_back(vhandle[1]);
|
||||
face_vhandles.push_back(vhandle[0]);
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
face_vhandles.push_back(vhandle[5]);
|
||||
mesh.add_face(face_vhandles);
|
||||
|
||||
face_vhandles.clear();
|
||||
face_vhandles.push_back(vhandle[2]);
|
||||
face_vhandles.push_back(vhandle[1]);
|
||||
face_vhandles.push_back(vhandle[5]);
|
||||
face_vhandles.push_back(vhandle[6]);
|
||||
mesh.add_face(face_vhandles);
|
||||
|
||||
face_vhandles.clear();
|
||||
face_vhandles.push_back(vhandle[3]);
|
||||
face_vhandles.push_back(vhandle[2]);
|
||||
face_vhandles.push_back(vhandle[6]);
|
||||
face_vhandles.push_back(vhandle[7]);
|
||||
mesh.add_face(face_vhandles);
|
||||
|
||||
face_vhandles.clear();
|
||||
face_vhandles.push_back(vhandle[0]);
|
||||
face_vhandles.push_back(vhandle[3]);
|
||||
face_vhandles.push_back(vhandle[7]);
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
mesh.add_face(face_vhandles);
|
||||
|
||||
|
||||
// write mesh to output.obj
|
||||
try
|
||||
{
|
||||
if ( !OpenMesh::IO::write_mesh(mesh, "output.off") )
|
||||
{
|
||||
std::cerr << "Cannot write mesh to file 'output.off'" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
catch( std::exception& x )
|
||||
{
|
||||
std::cerr << x.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
// -------------------- OpenMesh
|
||||
#include <OpenMesh/Core/IO/MeshIO.hh>
|
||||
#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
|
||||
|
||||
typedef OpenMesh::TriMesh_ArrayKernelT<> MyMesh;
|
||||
|
||||
|
||||
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 vector stores the computed centers of gravity
|
||||
std::vector<MyMesh::Point> cogs;
|
||||
std::vector<MyMesh::Point>::iterator cog_it;
|
||||
cogs.reserve(mesh.n_vertices());
|
||||
|
||||
|
||||
// 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)
|
||||
{
|
||||
cogs.clear();
|
||||
for (v_it=mesh.vertices_begin(); v_it!=v_end; ++v_it)
|
||||
{
|
||||
cog[0] = cog[1] = cog[2] = valence = 0.0;
|
||||
|
||||
for (vv_it=mesh.vv_iter( *v_it ); vv_it.is_valid(); ++vv_it)
|
||||
{
|
||||
cog += mesh.point( *vv_it );
|
||||
++valence;
|
||||
}
|
||||
|
||||
cogs.push_back(cog / valence);
|
||||
}
|
||||
|
||||
for (v_it=mesh.vertices_begin(), cog_it=cogs.begin();
|
||||
v_it!=v_end; ++v_it, ++cog_it)
|
||||
if ( !mesh.is_boundary( *v_it ) )
|
||||
mesh.set_point( *v_it, *cog_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;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
#include <OpenMesh/Core/IO/MeshIO.hh>
|
||||
#include <OpenMesh/Core/Mesh/DefaultTriMesh.hh>
|
||||
#include <OpenMesh/Core/Utils/PropertyManager.hh>
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
using MyMesh = OpenMesh::TriMesh;
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
// 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];
|
||||
|
||||
// Read mesh file
|
||||
if (!OpenMesh::IO::read_mesh(mesh, infile)) {
|
||||
std::cerr << "Error: Cannot read mesh from " << infile << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
{
|
||||
// Add a vertex property storing the computed centers of gravity
|
||||
auto cog = OpenMesh::VProp<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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
// -------------------- OpenMesh
|
||||
#include <OpenMesh/Core/IO/MeshIO.hh>
|
||||
#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
|
||||
// --------------------
|
||||
#include "smooth_algo.hh"
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#ifndef DOXY_IGNORE_THIS
|
||||
|
||||
struct MyTraits : public OpenMesh::DefaultTraits
|
||||
{
|
||||
HalfedgeAttributes(OpenMesh::Attributes::PrevHalfedge);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
typedef OpenMesh::TriMesh_ArrayKernelT<MyTraits> MyMesh;
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
// smoothing mesh argv[1] times
|
||||
SmootherT<MyMesh> smoother(mesh);
|
||||
smoother.smooth(atoi(argv[1]));
|
||||
|
||||
|
||||
// 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;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
#include <algorithm>
|
||||
#include <OpenMesh/Core/Utils/Property.hh>
|
||||
|
||||
#ifndef DOXY_IGNORE_THIS
|
||||
|
||||
template <class Mesh> class SmootherT
|
||||
{
|
||||
public:
|
||||
|
||||
typedef typename Mesh::Point cog_t;
|
||||
typedef OpenMesh::VPropHandleT< cog_t > Property_cog;
|
||||
|
||||
public:
|
||||
|
||||
// construct with a given mesh
|
||||
explicit SmootherT(Mesh& _mesh)
|
||||
: mesh_(_mesh)
|
||||
{
|
||||
mesh_.add_property( cog_ );
|
||||
}
|
||||
|
||||
~SmootherT()
|
||||
{
|
||||
mesh_.remove_property( cog_ );
|
||||
}
|
||||
|
||||
// smooth mesh _iterations times
|
||||
void smooth(unsigned int _iterations)
|
||||
{
|
||||
for (unsigned int i=0; i < _iterations; ++i)
|
||||
{
|
||||
std::for_each(mesh_.vertices_begin(),
|
||||
mesh_.vertices_end(),
|
||||
ComputeCOG(mesh_, cog_));
|
||||
|
||||
std::for_each(mesh_.vertices_begin(),
|
||||
mesh_.vertices_end(),
|
||||
SetCOG(mesh_, cog_));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
|
||||
//--- private classes ---
|
||||
|
||||
class ComputeCOG
|
||||
{
|
||||
public:
|
||||
ComputeCOG(Mesh& _mesh, Property_cog& _cog)
|
||||
: mesh_(_mesh), cog_(_cog)
|
||||
{}
|
||||
|
||||
void operator()(const typename Mesh::VertexHandle& _vh)
|
||||
{
|
||||
typename Mesh::VertexVertexIter vv_it;
|
||||
typename Mesh::Scalar valence(0.0);
|
||||
|
||||
mesh_.property(cog_, _vh) = typename Mesh::Point(0.0, 0.0, 0.0);
|
||||
|
||||
for (vv_it=mesh_.vv_iter(_vh); vv_it.is_valid(); ++vv_it)
|
||||
{
|
||||
mesh_.property(cog_, _vh) += mesh_.point( *vv_it );
|
||||
++valence;
|
||||
}
|
||||
|
||||
mesh_.property(cog_, _vh ) /= valence;
|
||||
}
|
||||
|
||||
private:
|
||||
Mesh& mesh_;
|
||||
Property_cog& cog_;
|
||||
};
|
||||
|
||||
|
||||
class SetCOG
|
||||
{
|
||||
public:
|
||||
SetCOG(Mesh& _mesh, Property_cog& _cog)
|
||||
: mesh_(_mesh), cog_(_cog)
|
||||
{}
|
||||
|
||||
void operator()(const typename Mesh::VertexHandle& _vh)
|
||||
{
|
||||
|
||||
if (!mesh_.is_boundary(_vh))
|
||||
mesh_.set_point( _vh, mesh_.property(cog_, _vh) );
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Mesh& mesh_;
|
||||
Property_cog& cog_;
|
||||
};
|
||||
|
||||
|
||||
//--- private elements ---
|
||||
|
||||
Mesh& mesh_;
|
||||
Property_cog cog_;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,71 @@
|
||||
#include <iostream>
|
||||
// --------------------
|
||||
#include <OpenMesh/Core/IO/MeshIO.hh>
|
||||
#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
|
||||
|
||||
|
||||
typedef OpenMesh::TriMesh_ArrayKernelT<> MyMesh;
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
MyMesh mesh;
|
||||
|
||||
if (argc!=2)
|
||||
{
|
||||
std::cerr << "Usage: " << argv[0] << " <input>\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
// request vertex normals, so the mesh reader can use normal information
|
||||
// if available
|
||||
mesh.request_vertex_normals();
|
||||
|
||||
// assure we have vertex normals
|
||||
if (!mesh.has_vertex_normals())
|
||||
{
|
||||
std::cerr << "ERROR: Standard vertex property 'Normals' not available!\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
OpenMesh::IO::Options opt;
|
||||
if ( ! OpenMesh::IO::read_mesh(mesh,argv[1], opt))
|
||||
{
|
||||
std::cerr << "Error loading mesh from file " << argv[1] << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// If the file did not provide vertex normals, then calculate them
|
||||
if ( !opt.check( OpenMesh::IO::Options::VertexNormal ) )
|
||||
{
|
||||
// we need face normals to update the vertex normals
|
||||
mesh.request_face_normals();
|
||||
|
||||
// let the mesh update the normals
|
||||
mesh.update_normals();
|
||||
|
||||
// dispose the face normals, as we don't need them anymore
|
||||
mesh.release_face_normals();
|
||||
}
|
||||
|
||||
// move all vertices one unit length along it's normal direction
|
||||
for (MyMesh::VertexIter v_it = mesh.vertices_begin();
|
||||
v_it != mesh.vertices_end(); ++v_it)
|
||||
{
|
||||
std::cout << "Vertex #" << *v_it << ": " << mesh.point( *v_it );
|
||||
mesh.set_point( *v_it, mesh.point(*v_it)+mesh.normal(*v_it) );
|
||||
std::cout << " moved to " << mesh.point( *v_it ) << std::endl;
|
||||
}
|
||||
|
||||
// don't need the normals anymore? Remove them!
|
||||
mesh.release_vertex_normals();
|
||||
|
||||
// just check if it really works
|
||||
if (mesh.has_vertex_normals())
|
||||
{
|
||||
std::cerr << "Ouch! ERROR! Shouldn't have any vertex normals anymore!\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
#include <iostream>
|
||||
#include <typeinfo>
|
||||
// --------------------
|
||||
#include <OpenMesh/Core/IO/MeshIO.hh>
|
||||
|
||||
#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
|
||||
#include <OpenMesh/Core/Geometry/VectorT.hh>
|
||||
|
||||
#ifndef DOXY_IGNORE_THIS
|
||||
|
||||
// Define my personal traits
|
||||
struct MyTraits : OpenMesh::DefaultTraits
|
||||
{
|
||||
// Let Point and Normal be a vector of doubles
|
||||
typedef OpenMesh::Vec3d Point;
|
||||
typedef OpenMesh::Vec3d Normal;
|
||||
|
||||
// Already defined in OpenMesh::DefaultTraits
|
||||
// HalfedgeAttributes( OpenMesh::Attributes::PrevHalfedge );
|
||||
|
||||
// Uncomment next line to disable attribute PrevHalfedge
|
||||
// HalfedgeAttributes( OpenMesh::Attributes::None );
|
||||
//
|
||||
// or
|
||||
//
|
||||
// HalfedgeAttributes( 0 );
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
// Define my mesh with the new traits!
|
||||
typedef OpenMesh::TriMesh_ArrayKernelT<MyTraits> MyMesh;
|
||||
|
||||
// ------------------------------------------------------------------ main ----
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
MyMesh mesh;
|
||||
|
||||
if (argc!=2)
|
||||
{
|
||||
std::cerr << "Usage: " << argv[0] << " <input>\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Just make sure that point element type is double
|
||||
if ( typeid( OpenMesh::vector_traits<MyMesh::Point>::value_type )
|
||||
!= typeid(double) )
|
||||
{
|
||||
std::cerr << "Ouch! ERROR! Data type is wrong!\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Make sure that normal element type is double
|
||||
if ( typeid( OpenMesh::vector_traits<MyMesh::Normal>::value_type )
|
||||
!= typeid(double) )
|
||||
{
|
||||
std::cerr << "Ouch! ERROR! Data type is wrong!\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Add vertex normals as default property (ref. previous tutorial)
|
||||
mesh.request_vertex_normals();
|
||||
|
||||
// Add face normals as default property
|
||||
mesh.request_face_normals();
|
||||
|
||||
// load a mesh
|
||||
OpenMesh::IO::Options opt;
|
||||
if ( ! OpenMesh::IO::read_mesh(mesh,argv[1], opt))
|
||||
{
|
||||
std::cerr << "Error loading mesh from file " << argv[1] << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// If the file did not provide vertex normals, then calculate them
|
||||
if ( !opt.check( OpenMesh::IO::Options::VertexNormal ) &&
|
||||
mesh.has_face_normals() && mesh.has_vertex_normals() )
|
||||
{
|
||||
// let the mesh update the normals
|
||||
mesh.update_normals();
|
||||
}
|
||||
|
||||
// move all vertices one unit length along it's normal direction
|
||||
for (MyMesh::VertexIter v_it = mesh.vertices_begin();
|
||||
v_it != mesh.vertices_end(); ++v_it)
|
||||
{
|
||||
std::cout << "Vertex #" << *v_it << ": " << mesh.point( *v_it );
|
||||
mesh.set_point( *v_it, mesh.point(*v_it)+mesh.normal(*v_it) );
|
||||
std::cout << " moved to " << mesh.point( *v_it ) << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
// -------------------- OpenMesh
|
||||
#include <OpenMesh/Core/IO/MeshIO.hh>
|
||||
#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
|
||||
#include <OpenMesh/Core/Mesh/Traits.hh>
|
||||
|
||||
struct MyTraits : public OpenMesh::DefaultTraits
|
||||
{
|
||||
// store barycenter of neighbors in this member
|
||||
VertexTraits
|
||||
{
|
||||
private:
|
||||
Point cog_;
|
||||
public:
|
||||
|
||||
VertexT() : cog_( Point(0.0f, 0.0f, 0.0f ) ) { }
|
||||
|
||||
const Point& cog() const { return cog_; }
|
||||
void set_cog(const Point& _p) { cog_ = _p; }
|
||||
};
|
||||
};
|
||||
|
||||
typedef OpenMesh::TriMesh_ArrayKernelT<MyTraits> MyMesh;
|
||||
typedef OpenMesh::TriMesh_ArrayKernelT<> MyMesh2;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
#define SIZEOF( entity,b ) \
|
||||
std::cout << _prefix << "size of " << #entity << ": " \
|
||||
<< sizeof( entity ) << std::endl; \
|
||||
b += sizeof( entity )
|
||||
|
||||
template <typename Mesh>
|
||||
void print_size(const std::string& _prefix = "")
|
||||
{
|
||||
size_t total=0;
|
||||
SIZEOF(typename Mesh::Vertex, total);
|
||||
SIZEOF(typename Mesh::Halfedge, total);
|
||||
SIZEOF(typename Mesh::Edge, total);
|
||||
SIZEOF(typename Mesh::Face, total);
|
||||
std::cout << _prefix << "total: " << total << std::endl;
|
||||
}
|
||||
|
||||
#undef SIZEOF
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
MyMesh mesh;
|
||||
|
||||
// check command line options
|
||||
if (argc < 4 || argc > 5)
|
||||
{
|
||||
std::cerr << "Usage: " << argv[0] << " [-s] #iterations infile outfile\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int idx=2;
|
||||
|
||||
// display size of entities of the enhanced and the default mesh type
|
||||
// when commandline option '-s' has been used.
|
||||
if (argc == 5)
|
||||
{
|
||||
if (std::string("-s")==argv[idx-1])
|
||||
{
|
||||
std::cout << "Enhanced mesh size statistics\n";
|
||||
print_size<MyMesh>(" ");
|
||||
|
||||
std::cout << "Default mesh size statistics\n";
|
||||
print_size<MyMesh2>(" ");
|
||||
}
|
||||
// else ignore!
|
||||
++idx;
|
||||
}
|
||||
|
||||
|
||||
// read mesh from stdin
|
||||
std::cout<< " Input mesh: " << argv[idx] << std::endl;
|
||||
if ( ! OpenMesh::IO::read_mesh(mesh, argv[idx]) )
|
||||
{
|
||||
std::cerr << "Error: Cannot read mesh from " << argv[idx] << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 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[idx-1]));
|
||||
|
||||
std::cout<< "Smooth mesh " << N << " times\n";
|
||||
|
||||
for (i=0; i < N; ++i)
|
||||
{
|
||||
for (v_it=mesh.vertices_begin(); v_it!=v_end; ++v_it)
|
||||
{
|
||||
cog[0] = cog[1] = cog[2] = valence = 0.0;
|
||||
|
||||
for (vv_it=mesh.vv_iter(*v_it); vv_it.is_valid(); ++vv_it)
|
||||
{
|
||||
cog += mesh.point( *vv_it );
|
||||
++valence;
|
||||
}
|
||||
|
||||
mesh.data(*v_it).set_cog(cog / valence);
|
||||
}
|
||||
|
||||
for (v_it=mesh.vertices_begin(); v_it!=v_end; ++v_it)
|
||||
if (!mesh.is_boundary(*v_it))
|
||||
mesh.set_point( *v_it, mesh.data(*v_it).cog());
|
||||
}
|
||||
|
||||
|
||||
// write mesh to stdout
|
||||
std::cout<< "Output mesh: " << argv[idx+1] << std::endl;
|
||||
|
||||
if ( ! OpenMesh::IO::write_mesh(mesh, argv[idx+1]) )
|
||||
{
|
||||
std::cerr << "Error: cannot write mesh to " << argv[idx+1] << std::endl;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
/* ========================================================================= *
|
||||
* *
|
||||
* OpenMesh *
|
||||
* Copyright (c) 2001-2015, RWTH-Aachen University *
|
||||
* Department of Computer Graphics and Multimedia *
|
||||
* All rights reserved. *
|
||||
* www.openmesh.org *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* This file is part of OpenMesh. *
|
||||
*---------------------------------------------------------------------------*
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or without *
|
||||
* modification, are permitted provided that the following conditions *
|
||||
* are met: *
|
||||
* *
|
||||
* 1. Redistributions of source code must retain the above copyright notice, *
|
||||
* this list of conditions and the following disclaimer. *
|
||||
* *
|
||||
* 2. Redistributions in binary form must reproduce the above copyright *
|
||||
* notice, this list of conditions and the following disclaimer in the *
|
||||
* documentation and/or other materials provided with the distribution. *
|
||||
* *
|
||||
* 3. Neither the name of the copyright holder nor the names of its *
|
||||
* contributors may be used to endorse or promote products derived from *
|
||||
* this software without specific prior written permission. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
|
||||
* *
|
||||
* ========================================================================= */
|
||||
|
||||
#include <iostream>
|
||||
// -------------------- OpenMesh
|
||||
#include <OpenMesh/Core/IO/MeshIO.hh>
|
||||
#include <OpenMesh/Core/Mesh/PolyMesh_ArrayKernelT.hh>
|
||||
#include <OpenMesh/Core/System/config.h>
|
||||
#include <OpenMesh/Core/Mesh/Status.hh>
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
struct MyTraits : public OpenMesh::DefaultTraits
|
||||
{
|
||||
};
|
||||
|
||||
|
||||
typedef OpenMesh::PolyMesh_ArrayKernelT<MyTraits> MyMesh;
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Build a simple cube and delete it except one face
|
||||
|
||||
int main()
|
||||
{
|
||||
MyMesh mesh;
|
||||
|
||||
// the request has to be called before a vertex/face/edge can be deleted. it grants access to the status attribute
|
||||
mesh.request_face_status();
|
||||
mesh.request_edge_status();
|
||||
mesh.request_vertex_status();
|
||||
|
||||
// generate vertices
|
||||
|
||||
MyMesh::VertexHandle vhandle[8];
|
||||
MyMesh::FaceHandle fhandle[6];
|
||||
|
||||
vhandle[0] = mesh.add_vertex(MyMesh::Point(-1, -1, 1));
|
||||
vhandle[1] = mesh.add_vertex(MyMesh::Point( 1, -1, 1));
|
||||
vhandle[2] = mesh.add_vertex(MyMesh::Point( 1, 1, 1));
|
||||
vhandle[3] = mesh.add_vertex(MyMesh::Point(-1, 1, 1));
|
||||
vhandle[4] = mesh.add_vertex(MyMesh::Point(-1, -1, -1));
|
||||
vhandle[5] = mesh.add_vertex(MyMesh::Point( 1, -1, -1));
|
||||
vhandle[6] = mesh.add_vertex(MyMesh::Point( 1, 1, -1));
|
||||
vhandle[7] = mesh.add_vertex(MyMesh::Point(-1, 1, -1));
|
||||
|
||||
|
||||
// generate (quadrilateral) faces
|
||||
|
||||
std::vector<MyMesh::VertexHandle> tmp_face_vhandles;
|
||||
|
||||
tmp_face_vhandles.clear();
|
||||
tmp_face_vhandles.push_back(vhandle[0]);
|
||||
tmp_face_vhandles.push_back(vhandle[1]);
|
||||
tmp_face_vhandles.push_back(vhandle[2]);
|
||||
tmp_face_vhandles.push_back(vhandle[3]);
|
||||
fhandle[0] = mesh.add_face(tmp_face_vhandles);
|
||||
|
||||
tmp_face_vhandles.clear();
|
||||
tmp_face_vhandles.push_back(vhandle[7]);
|
||||
tmp_face_vhandles.push_back(vhandle[6]);
|
||||
tmp_face_vhandles.push_back(vhandle[5]);
|
||||
tmp_face_vhandles.push_back(vhandle[4]);
|
||||
fhandle[1] = mesh.add_face(tmp_face_vhandles);
|
||||
|
||||
tmp_face_vhandles.clear();
|
||||
tmp_face_vhandles.push_back(vhandle[1]);
|
||||
tmp_face_vhandles.push_back(vhandle[0]);
|
||||
tmp_face_vhandles.push_back(vhandle[4]);
|
||||
tmp_face_vhandles.push_back(vhandle[5]);
|
||||
fhandle[2] = mesh.add_face(tmp_face_vhandles);
|
||||
|
||||
|
||||
tmp_face_vhandles.clear();
|
||||
tmp_face_vhandles.push_back(vhandle[2]);
|
||||
tmp_face_vhandles.push_back(vhandle[1]);
|
||||
tmp_face_vhandles.push_back(vhandle[5]);
|
||||
tmp_face_vhandles.push_back(vhandle[6]);
|
||||
fhandle[3] = mesh.add_face(tmp_face_vhandles);
|
||||
|
||||
|
||||
tmp_face_vhandles.clear();
|
||||
tmp_face_vhandles.push_back(vhandle[3]);
|
||||
tmp_face_vhandles.push_back(vhandle[2]);
|
||||
tmp_face_vhandles.push_back(vhandle[6]);
|
||||
tmp_face_vhandles.push_back(vhandle[7]);
|
||||
fhandle[4] = mesh.add_face(tmp_face_vhandles);
|
||||
|
||||
|
||||
tmp_face_vhandles.clear();
|
||||
tmp_face_vhandles.push_back(vhandle[0]);
|
||||
tmp_face_vhandles.push_back(vhandle[3]);
|
||||
tmp_face_vhandles.push_back(vhandle[7]);
|
||||
tmp_face_vhandles.push_back(vhandle[4]);
|
||||
fhandle[5] = mesh.add_face(tmp_face_vhandles);
|
||||
|
||||
// And now delete all faces and vertices
|
||||
// except face (vh[7], vh[6], vh[5], vh[4])
|
||||
// whose handle resides in fhandle[1]
|
||||
|
||||
|
||||
// Delete face 0
|
||||
mesh.delete_face(fhandle[0], false);
|
||||
// ... face 2
|
||||
mesh.delete_face(fhandle[2], false);
|
||||
// ... face 3
|
||||
mesh.delete_face(fhandle[3], false);
|
||||
// ... face 4
|
||||
mesh.delete_face(fhandle[4], false);
|
||||
// ... face 5
|
||||
mesh.delete_face(fhandle[5], false);
|
||||
|
||||
|
||||
// If isolated vertices result in a face deletion
|
||||
// they have to be deleted manually. If you want this
|
||||
// to happen automatically, change the second parameter
|
||||
// to true.
|
||||
|
||||
// Now delete the isolated vertices 0, 1, 2 and 3
|
||||
mesh.delete_vertex(vhandle[0], false);
|
||||
mesh.delete_vertex(vhandle[1], false);
|
||||
mesh.delete_vertex(vhandle[2], false);
|
||||
mesh.delete_vertex(vhandle[3], false);
|
||||
|
||||
// Delete all elements that are marked as deleted
|
||||
// from memory.
|
||||
mesh.garbage_collection();
|
||||
|
||||
// write mesh to output.obj
|
||||
try {
|
||||
if ( !OpenMesh::IO::write_mesh(mesh, "output.off") ) {
|
||||
std::cerr << "Cannot write mesh to file 'output.off'" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
catch( std::exception& x )
|
||||
{
|
||||
std::cerr << x.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,297 @@
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
// -------------------- OpenMesh
|
||||
#include <OpenMesh/Core/IO/MeshIO.hh>
|
||||
#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
|
||||
#include <OpenMesh/Tools/Utils/getopt.h>
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
using namespace OpenMesh;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
typedef TriMesh_ArrayKernelT<> MyMesh;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#define CHKROPT( Option ) \
|
||||
std::cout << " provides " << #Option \
|
||||
<< (ropt.check(IO::Options:: Option)?": yes\n":": no\n")
|
||||
|
||||
#define CHKWOPT( Option ) \
|
||||
std::cout << " write " << #Option \
|
||||
<< (wopt.check(IO::Options:: Option)?": yes\n":": no\n")
|
||||
|
||||
#define MESHOPT( msg, tf ) \
|
||||
std::cout << " " << msg << ": " << ((tf)?"yes\n":"no\n")
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void parse_commandline( int _argc, char **_argv, MyMesh& _mesh,
|
||||
IO::Options &ropt, IO::Options &wopt );
|
||||
|
||||
void usage_and_exit(int xcode);
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
MyMesh mesh;
|
||||
IO::Options ropt, wopt;
|
||||
|
||||
// -------------------- evaluate commandline
|
||||
|
||||
parse_commandline( argc, argv, mesh, ropt, wopt );
|
||||
|
||||
// -------------------- read mesh
|
||||
|
||||
if ( ! IO::read_mesh(mesh,argv[optind], ropt))
|
||||
{
|
||||
std::cerr << "Error loading mesh from file " << argv[optind] << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// -------------------- show options
|
||||
|
||||
std::cout << "File " << argv[optind] << std::endl;
|
||||
|
||||
std::cout << " is binary: "
|
||||
<< (ropt.check(IO::Options::Binary) ? " yes\n" : " no\n");
|
||||
|
||||
std::cout << " byte order: ";
|
||||
if (ropt.check(IO::Options::Swap))
|
||||
std::cout << "swapped\n";
|
||||
else if (ropt.check(IO::Options::LSB))
|
||||
std::cout << "little endian\n";
|
||||
else if (ropt.check(IO::Options::MSB))
|
||||
std::cout << "big endian\n";
|
||||
else
|
||||
std::cout << "don't care\n";
|
||||
|
||||
std::cout << " provides VertexNormal"
|
||||
<< ( // strange layout for doxygen
|
||||
ropt.check(IO::Options::VertexNormal)
|
||||
? ": yes\n":": no\n");
|
||||
CHKROPT( VertexColor );
|
||||
CHKROPT( VertexTexCoord );
|
||||
CHKROPT( FaceNormal );
|
||||
CHKROPT( FaceColor );
|
||||
|
||||
|
||||
// -------------------- mesh stats
|
||||
|
||||
std::cout << "# Vertices: " << mesh.n_vertices() << std::endl;
|
||||
std::cout << "# Edges : " << mesh.n_faces() << std::endl;
|
||||
std::cout << "# Faces : " << mesh.n_faces() << std::endl;
|
||||
|
||||
|
||||
// -------------------- show write options
|
||||
|
||||
std::cout << "Selected write options:\n";
|
||||
std::cout << " use binary: "
|
||||
<< (wopt.check(IO::Options::Binary) ? " yes\n" : " no\n");
|
||||
|
||||
std::cout << " byte order: ";
|
||||
if (wopt.check(IO::Options::Swap))
|
||||
std::cout << "swapped\n";
|
||||
else if (wopt.check(IO::Options::LSB))
|
||||
std::cout << "little endian\n";
|
||||
else if (wopt.check(IO::Options::MSB))
|
||||
std::cout << "big endian\n";
|
||||
else
|
||||
std::cout << "don't care\n";
|
||||
|
||||
std::cout << " write VertexNormal"
|
||||
<< (wopt.check(IO::Options::VertexNormal) ? ": yes\n":": no\n");
|
||||
CHKWOPT( VertexColor );
|
||||
CHKWOPT( VertexTexCoord );
|
||||
CHKWOPT( FaceNormal );
|
||||
CHKWOPT( FaceColor );
|
||||
|
||||
// -------------------- show mesh capabilities
|
||||
|
||||
std::cout << "Mesh supports\n";
|
||||
MESHOPT("vertex normals", mesh.has_vertex_normals());
|
||||
MESHOPT("vertex colors", mesh.has_vertex_colors());
|
||||
MESHOPT("texcoords", mesh.has_vertex_texcoords2D());
|
||||
MESHOPT("face normals", mesh.has_face_normals());
|
||||
MESHOPT("face colors", mesh.has_face_colors());
|
||||
|
||||
// -------------------- write mesh
|
||||
|
||||
std::cout << "Write mesh to " << argv[optind+1] << "..";
|
||||
if ( !IO::write_mesh( mesh, argv[optind+1], wopt ) )
|
||||
{
|
||||
std::cerr << "Error" << std::endl;
|
||||
std::cerr << "Possible reasons:\n";
|
||||
std::cerr << "1. Chosen format cannot handle an option!\n";
|
||||
std::cerr << "2. Mesh does not provide necessary information!\n";
|
||||
std::cerr << "3. Or simply cannot open file for writing!\n";
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
std::cout << "Ok.\n";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void parse_commandline( int _argc, char **_argv, MyMesh& _mesh,
|
||||
IO::Options &ropt, IO::Options &wopt )
|
||||
{
|
||||
int c;
|
||||
while ((c=getopt(_argc, _argv, "bhsBF:LMSV:X:"))!=-1)
|
||||
{
|
||||
switch(c)
|
||||
{
|
||||
// -------------------- read options
|
||||
|
||||
// force binary input
|
||||
case 'b':
|
||||
ropt += IO::Options::Binary;
|
||||
break;
|
||||
|
||||
// force swapping the byte order, when reading a binary file
|
||||
case 's':
|
||||
ropt += IO::Options::Swap;
|
||||
break;
|
||||
|
||||
// -------------------- write options
|
||||
|
||||
// Write binary variant of format if possible
|
||||
case 'B':
|
||||
wopt += IO::Options::Binary;
|
||||
break;
|
||||
|
||||
//
|
||||
case 'F':
|
||||
for(size_t i=0; optarg[i]; ++i)
|
||||
switch(optarg[i]) {
|
||||
case 'n' : wopt += IO::Options::FaceNormal; break;
|
||||
case 'c' : wopt += IO::Options::FaceColor; break;
|
||||
}
|
||||
break;
|
||||
|
||||
// Use little endian when writing binary data
|
||||
case 'L':
|
||||
wopt += IO::Options::LSB;
|
||||
break;
|
||||
|
||||
// Use big endian when writing binary data
|
||||
case 'M':
|
||||
wopt += IO::Options::MSB;
|
||||
break;
|
||||
|
||||
// Swap byte order when writing binary data
|
||||
case 'S':
|
||||
wopt += IO::Options::Swap;
|
||||
break;
|
||||
|
||||
//
|
||||
case 'V':
|
||||
{
|
||||
for(size_t i=0; optarg[i]; ++i)
|
||||
switch(optarg[i]) {
|
||||
case 'n' : // dont't change layout!!
|
||||
wopt += IO::Options::VertexNormal;
|
||||
break;
|
||||
case 't' : wopt += IO::Options::VertexTexCoord; break;
|
||||
case 'c' : wopt += IO::Options::VertexColor; break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// -------------------- request mesh' standard properties
|
||||
case 'X':
|
||||
{
|
||||
char entity='\0';
|
||||
for(size_t i=0; optarg[i]; ++i)
|
||||
switch(optarg[i]) {
|
||||
case 'v':
|
||||
case 'f': entity = optarg[i]; break;
|
||||
case 'n':
|
||||
switch(entity) {
|
||||
case 'v': _mesh.request_vertex_normals(); break;
|
||||
case 'f': _mesh.request_face_normals(); break;
|
||||
}
|
||||
break;
|
||||
case 'c':
|
||||
switch(entity) {
|
||||
case 'v': _mesh.request_vertex_colors(); break;
|
||||
case 'f': _mesh.request_face_colors(); break;
|
||||
}
|
||||
break;
|
||||
case 't':
|
||||
switch(entity) {
|
||||
case 'v': _mesh.request_vertex_texcoords2D(); break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// -------------------- help
|
||||
case 'h':
|
||||
usage_and_exit(0);
|
||||
default:
|
||||
usage_and_exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if ( _argc-optind != 2)
|
||||
usage_and_exit(1);
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void usage_and_exit(int xcode)
|
||||
{
|
||||
std::ostream &os = xcode ? std::cerr : std::cout;
|
||||
|
||||
os << "Usage: io_options [Options] <input> <output>\n"
|
||||
<< std::endl;
|
||||
os << " Read and write a mesh, using OpenMesh::IO::Options\n"
|
||||
<< std::endl;
|
||||
os << "Options:\n"
|
||||
<< std::endl;
|
||||
os << "a) read options\n"
|
||||
<< std::endl
|
||||
<< " -b\n"
|
||||
<< "\tAssume input file is a binary file\n"
|
||||
<< std::endl
|
||||
<< " -s\n"
|
||||
<< "\tSwap byte order when reading a binary file!\n"
|
||||
<< std::endl;
|
||||
os << "b) write options\n"
|
||||
<< std::endl
|
||||
<< " -B\n"
|
||||
<< "\tWrite binary data\n"
|
||||
<< std::endl
|
||||
<< " -S\n"
|
||||
<< "\tSwap byte order, when writing binary data\n"
|
||||
<< std::endl
|
||||
<< " -M/-L\n"
|
||||
<< "\tUse MSB/LSB byte ordering, when writing binary data\n"
|
||||
<< std::endl
|
||||
<< " -V{n|t|c}\n"
|
||||
<< "\tWrite vertex normals, texcoords, and/or colors\n"
|
||||
<< std::endl
|
||||
<< " -F{n|c}\n"
|
||||
<< "\tWrite face normals, and/or colors\n"
|
||||
<< std::endl;
|
||||
os << "c) Mesh properties\n"
|
||||
<< std::endl
|
||||
<< " -Xv{n|c|t}\n"
|
||||
<< "\tRequest vertex property normals|colors|texcoords\n"
|
||||
<< std::endl
|
||||
<< " -Xf{n|c}\n"
|
||||
<< "\tRequest face property normals|colors\n"
|
||||
<< std::endl;
|
||||
exit(xcode);
|
||||
}
|
||||
|
||||
// end of file
|
||||
// ============================================================================
|
||||
@@ -0,0 +1,119 @@
|
||||
#ifndef FILL_PROPS_HH
|
||||
#define FILL_PROPS_HH
|
||||
|
||||
#include <OpenMesh/Core/Utils/Property.hh>
|
||||
#include "int2roman.hh"
|
||||
|
||||
|
||||
template <typename Mesh>
|
||||
bool
|
||||
fill_props( Mesh& _m, OpenMesh::VPropHandleT<float> _ph, bool _check=false)
|
||||
{
|
||||
static float a[9] = { 1.1f, 2.2f, 3.3f, 4.4f, 5.5f, 6.6f, 7.7f, 8.8f, 9.9f };
|
||||
|
||||
for(typename Mesh::VertexIter it=_m.vertices_begin();
|
||||
it != _m.vertices_end(); ++it)
|
||||
{
|
||||
const float v = a[it->idx()%9];
|
||||
if ( _check && !(_m.property( _ph, *it ) == v) )
|
||||
return false;
|
||||
else
|
||||
_m.property( _ph, *it ) = v;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template <typename Mesh>
|
||||
bool
|
||||
fill_props( Mesh& _m, OpenMesh::EPropHandleT<bool> _ph, bool _check=false )
|
||||
{
|
||||
|
||||
for( typename Mesh::EdgeIter it=_m.edges_begin();
|
||||
it != _m.edges_end(); ++it)
|
||||
{
|
||||
const size_t n = it->idx();
|
||||
const bool v = ((n&(n-1))==0); // true for 0,1,2,4,8,..
|
||||
|
||||
if (_check && _m.property( _ph, *it ) != v)
|
||||
{
|
||||
std::cout << " eprop_bool: " << n << " -> "
|
||||
<< _m.property(_ph, *it ) << " != " << v << std::endl;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
_m.property( _ph, *it ) = v;
|
||||
std::cout << " eprop_bool: " << n << " -> " << v << std::endl;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename Mesh>
|
||||
bool
|
||||
fill_props(Mesh& _m, OpenMesh::FPropHandleT<std::string> _ph, bool _check=false)
|
||||
{
|
||||
|
||||
for( typename Mesh::FaceIter it=_m.faces_begin();
|
||||
it != _m.faces_end(); ++it)
|
||||
{
|
||||
const int n = (it->idx()) + 1;
|
||||
_m.property( _ph, *it ) = int2roman(n);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template <typename Mesh, typename T>
|
||||
bool
|
||||
fill_props( Mesh& _m, OpenMesh::HPropHandleT<T> _ph, bool _check=false)
|
||||
{
|
||||
T v;
|
||||
static float a[9] = { 1.1f, 2.2f, 3.3f, 4.4f, 5.5f, 6.6f, 7.7f, 8.8f, 9.9f };
|
||||
static float b[9] = { 2.2f, 3.3f, 4.4f, 5.5f, 6.6f, 7.7f, 8.8f, 9.9f, 1.1f };
|
||||
static float c[9] = { 3.3f, 4.4f, 5.5f, 6.6f, 7.7f, 8.8f, 9.9f, 1.1f, 2.2f };
|
||||
static float d[9] = { 4.4f, 5.5f, 6.6f, 7.7f, 8.8f, 9.9f, 1.1f, 2.2f, 3.3f };
|
||||
static double values[9] = { 0.1, 0.02, 0.003, 0.0004, 0.00005, 0.000006,
|
||||
0.0000007, 0.00000008, 0.000000009 };
|
||||
|
||||
for( typename Mesh::HalfedgeIter it=_m.halfedges_begin();
|
||||
it != _m.halfedges_end(); ++it)
|
||||
{
|
||||
const int n = it->idx();
|
||||
|
||||
v = it->idx()+1; // ival
|
||||
v = values[n%9]; // dval
|
||||
v = ((n&(n-1))==0); // bval
|
||||
v.vec4fval[0] = a[n%9];
|
||||
v.vec4fval[1] = b[n%9];
|
||||
v.vec4fval[2] = c[n%9];
|
||||
v.vec4fval[3] = d[n%9];
|
||||
|
||||
if ( _check && _m.property( _ph, *it ) != v )
|
||||
return false;
|
||||
else
|
||||
_m.property( _ph, *it ) = v;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Mesh, typename T>
|
||||
bool
|
||||
fill_props( Mesh& _m, OpenMesh::MPropHandleT<T> _ph, bool _check=false)
|
||||
{
|
||||
for( typename Mesh::FaceIter it=_m.faces_begin(); it != _m.faces_end(); ++it)
|
||||
{
|
||||
const size_t idx = it->idx();
|
||||
if ( _check && _m.property( _ph )[int2roman(idx+1)] != idx )
|
||||
return false;
|
||||
else
|
||||
_m.property( _ph )[int2roman(idx+1)] = idx;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,70 @@
|
||||
#ifndef GENERATE_CUBE_HH
|
||||
#define GENERATE_CUBE_HH
|
||||
|
||||
template <typename MeshType>
|
||||
size_t generate_cube( MeshType& mesh )
|
||||
{
|
||||
typedef typename MeshType::VertexHandle VertexHandle;
|
||||
typedef typename MeshType::Point Point;
|
||||
|
||||
typename MeshType::VertexHandle vhandle[8];
|
||||
|
||||
vhandle[0] = mesh.add_vertex(Point(-1, -1, 1));
|
||||
vhandle[1] = mesh.add_vertex(Point( 1, -1, 1));
|
||||
vhandle[2] = mesh.add_vertex(Point( 1, 1, 1));
|
||||
vhandle[3] = mesh.add_vertex(Point(-1, 1, 1));
|
||||
vhandle[4] = mesh.add_vertex(Point(-1, -1, -1));
|
||||
vhandle[5] = mesh.add_vertex(Point( 1, -1, -1));
|
||||
vhandle[6] = mesh.add_vertex(Point( 1, 1, -1));
|
||||
vhandle[7] = mesh.add_vertex(Point(-1, 1, -1));
|
||||
|
||||
// generate (quadrilateral) faces
|
||||
|
||||
std::vector< VertexHandle > face_vhandles;
|
||||
|
||||
face_vhandles.clear();
|
||||
face_vhandles.push_back(vhandle[0]);
|
||||
face_vhandles.push_back(vhandle[1]);
|
||||
face_vhandles.push_back(vhandle[2]);
|
||||
face_vhandles.push_back(vhandle[3]);
|
||||
mesh.add_face(face_vhandles);
|
||||
|
||||
face_vhandles.clear();
|
||||
face_vhandles.push_back(vhandle[7]);
|
||||
face_vhandles.push_back(vhandle[6]);
|
||||
face_vhandles.push_back(vhandle[5]);
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
mesh.add_face(face_vhandles);
|
||||
|
||||
face_vhandles.clear();
|
||||
face_vhandles.push_back(vhandle[1]);
|
||||
face_vhandles.push_back(vhandle[0]);
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
face_vhandles.push_back(vhandle[5]);
|
||||
mesh.add_face(face_vhandles);
|
||||
|
||||
face_vhandles.clear();
|
||||
face_vhandles.push_back(vhandle[2]);
|
||||
face_vhandles.push_back(vhandle[1]);
|
||||
face_vhandles.push_back(vhandle[5]);
|
||||
face_vhandles.push_back(vhandle[6]);
|
||||
mesh.add_face(face_vhandles);
|
||||
|
||||
face_vhandles.clear();
|
||||
face_vhandles.push_back(vhandle[3]);
|
||||
face_vhandles.push_back(vhandle[2]);
|
||||
face_vhandles.push_back(vhandle[6]);
|
||||
face_vhandles.push_back(vhandle[7]);
|
||||
mesh.add_face(face_vhandles);
|
||||
|
||||
face_vhandles.clear();
|
||||
face_vhandles.push_back(vhandle[0]);
|
||||
face_vhandles.push_back(vhandle[3]);
|
||||
face_vhandles.push_back(vhandle[7]);
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
mesh.add_face(face_vhandles);
|
||||
|
||||
return mesh.n_vertices();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,42 @@
|
||||
#include <OpenMesh/Core/System/config.hh>
|
||||
#if defined(OM_CC_MIPS)
|
||||
# include <assert.h>
|
||||
#else
|
||||
# include <cassert>
|
||||
#endif
|
||||
#include "int2roman.hh"
|
||||
|
||||
|
||||
std::string int2roman( size_t decimal, size_t length )
|
||||
{
|
||||
assert( decimal > 0 && decimal < 1000 );
|
||||
|
||||
const size_t nrows = 4;
|
||||
const size_t ncols = 4;
|
||||
|
||||
static size_t table_arabs[ nrows ][ ncols ] = { { 1000, 1000, 1000, 1000 },
|
||||
{ 900, 500, 400, 100 },
|
||||
{ 90, 50, 40, 10 },
|
||||
{ 9, 5, 4, 1 } };
|
||||
|
||||
static char *table_romans[ nrows ][ ncols ] = { { "M", "M", "M", "M" },
|
||||
{ "CM", "D", "CD", "C" },
|
||||
{ "XC", "L", "XL", "X" },
|
||||
{ "IX", "V", "IV", "I" } };
|
||||
|
||||
size_t power; // power of ten
|
||||
size_t index; // Indexes thru values to subtract
|
||||
|
||||
std::string roman = "";
|
||||
roman.reserve(length);
|
||||
|
||||
for ( power = 0; power < nrows; power++ )
|
||||
for ( index = 0; index < ncols; index++ )
|
||||
while ( decimal >= table_arabs[ power ][ index ] )
|
||||
{
|
||||
roman += table_romans[ power ][ index ];
|
||||
decimal -= table_arabs[ power ][ index ];
|
||||
}
|
||||
|
||||
return roman;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#ifndef INT2ROMAN_HH
|
||||
#define INT2ROMAN_HH
|
||||
|
||||
#include <string>
|
||||
|
||||
std::string int2roman( size_t decimal, size_t length=30 );
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,348 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <map>
|
||||
// -------------------- OpenMesh
|
||||
#include <OpenMesh/Core/IO/MeshIO.hh>
|
||||
#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
|
||||
#include <OpenMesh/Core/Mesh/PolyMesh_ArrayKernelT.hh>
|
||||
// -------------------- little helper
|
||||
#include "generate_cube.hh"
|
||||
#include "stats.hh"
|
||||
#include "fill_props.hh"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// Set to 1 to use an PolyMesh type.
|
||||
#define UsePolyMesh 1
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
using namespace OpenMesh;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
typedef TriMesh_ArrayKernelT<> TriMesh;
|
||||
typedef PolyMesh_ArrayKernelT<> PolyMesh;
|
||||
|
||||
#if UsePolyMesh
|
||||
typedef PolyMesh Mesh;
|
||||
#else
|
||||
typedef TriMesh Mesh;
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#ifndef DOXY_IGNORE_THIS
|
||||
struct MyData
|
||||
{
|
||||
int ival;
|
||||
double dval;
|
||||
bool bval;
|
||||
OpenMesh::Vec4f vec4fval;
|
||||
|
||||
MyData()
|
||||
: ival(0), dval(0.0), bval(false)
|
||||
{ }
|
||||
|
||||
MyData( const MyData& _cpy )
|
||||
: ival(_cpy.ival), dval(_cpy.dval), bval(_cpy.bval),
|
||||
vec4fval(_cpy.vec4fval)
|
||||
{ }
|
||||
|
||||
|
||||
// ---------- assignment
|
||||
|
||||
MyData& operator = (const MyData& _rhs)
|
||||
{
|
||||
ival = _rhs.ival;
|
||||
dval = _rhs.dval;
|
||||
bval = _rhs.bval;
|
||||
vec4fval = _rhs.vec4fval;
|
||||
return *this;
|
||||
}
|
||||
|
||||
MyData& operator = (int _rhs) { ival = _rhs; return *this; }
|
||||
MyData& operator = (double _rhs) { dval = _rhs; return *this; }
|
||||
MyData& operator = (bool _rhs) { bval = _rhs; return *this; }
|
||||
MyData& operator = (const OpenMesh::Vec4f& _rhs)
|
||||
{ vec4fval = _rhs; return *this; }
|
||||
|
||||
|
||||
// ---------- comparison
|
||||
|
||||
bool operator == (const MyData& _rhs) const
|
||||
{
|
||||
return ival == _rhs.ival
|
||||
&& dval == _rhs.dval
|
||||
&& bval == _rhs.bval
|
||||
&& vec4fval == _rhs.vec4fval;
|
||||
}
|
||||
|
||||
bool operator != (const MyData& _rhs) const { return !(*this == _rhs); }
|
||||
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
typedef std::map< std::string, unsigned int > MyMap;
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#ifndef DOXY_IGNORE_THIS
|
||||
|
||||
namespace OpenMesh {
|
||||
namespace IO {
|
||||
|
||||
// support persistence for struct MyData
|
||||
|
||||
template <> struct binary<MyData>
|
||||
{
|
||||
typedef MyData value_type;
|
||||
|
||||
static const bool is_streamable = true;
|
||||
|
||||
// return binary size of the value
|
||||
|
||||
static size_t size_of(void)
|
||||
{
|
||||
return sizeof(int)+sizeof(double)+sizeof(bool)+sizeof(OpenMesh::Vec4f);
|
||||
}
|
||||
|
||||
static size_t size_of(const value_type&)
|
||||
{
|
||||
return size_of();
|
||||
}
|
||||
|
||||
static std::string type_identifier(void)
|
||||
{
|
||||
return "RegisteredDataType";
|
||||
}
|
||||
|
||||
static size_t store(std::ostream& _os, const value_type& _v, bool _swap=false)
|
||||
{
|
||||
size_t bytes;
|
||||
bytes = IO::store( _os, _v.ival, _swap );
|
||||
bytes += IO::store( _os, _v.dval, _swap );
|
||||
bytes += IO::store( _os, _v.bval, _swap );
|
||||
bytes += IO::store( _os, _v.vec4fval, _swap );
|
||||
return _os.good() ? bytes : 0;
|
||||
}
|
||||
|
||||
static size_t restore( std::istream& _is, value_type& _v, bool _swap=false)
|
||||
{
|
||||
size_t bytes;
|
||||
bytes = IO::restore( _is, _v.ival, _swap );
|
||||
bytes += IO::restore( _is, _v.dval, _swap );
|
||||
bytes += IO::restore( _is, _v.bval, _swap );
|
||||
bytes += IO::restore( _is, _v.vec4fval, _swap );
|
||||
return _is.good() ? bytes : 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <> struct binary< MyMap >
|
||||
{
|
||||
typedef MyMap value_type;
|
||||
|
||||
static const bool is_streamable = true;
|
||||
|
||||
// return generic binary size of self, if known
|
||||
static size_t size_of(void) { return UnknownSize; }
|
||||
|
||||
// return binary size of the value
|
||||
static size_t size_of(const value_type& _v)
|
||||
{
|
||||
if (_v.empty())
|
||||
return sizeof(unsigned int);
|
||||
|
||||
value_type::const_iterator it = _v.begin();
|
||||
unsigned int N = _v.size();
|
||||
size_t bytes = IO::size_of(N);
|
||||
|
||||
for(;it!=_v.end(); ++it)
|
||||
{
|
||||
bytes += IO::size_of( it->first );
|
||||
bytes += IO::size_of( it->second );
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
static
|
||||
size_t store(std::ostream& _os, const value_type& _v, bool _swap=false)
|
||||
{
|
||||
size_t bytes = 0;
|
||||
unsigned int N = _v.size();
|
||||
|
||||
value_type::const_iterator it = _v.begin();
|
||||
|
||||
bytes += IO::store( _os, N, _swap );
|
||||
|
||||
for (; it != _v.end() && _os.good(); ++it)
|
||||
{
|
||||
bytes += IO::store( _os, it->first, _swap );
|
||||
bytes += IO::store( _os, it->second, _swap );
|
||||
}
|
||||
return _os.good() ? bytes : 0;
|
||||
}
|
||||
|
||||
static
|
||||
size_t restore( std::istream& _is, value_type& _v, bool _swap=false)
|
||||
{
|
||||
size_t bytes = 0;
|
||||
unsigned int N = 0;
|
||||
|
||||
_v.clear();
|
||||
|
||||
bytes += IO::restore( _is, N, _swap );
|
||||
value_type::key_type key;
|
||||
value_type::mapped_type val;
|
||||
|
||||
for (size_t i=0; i<N && _is.good(); ++i)
|
||||
{
|
||||
bytes += IO::restore( _is, key, _swap );
|
||||
bytes += IO::restore( _is, val, _swap );
|
||||
_v[key] = val;
|
||||
}
|
||||
return _is.good() ? bytes : 0;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
int main(void)
|
||||
{
|
||||
//
|
||||
Mesh mesh;
|
||||
|
||||
|
||||
// generate a geometry
|
||||
generate_cube<Mesh>(mesh);
|
||||
|
||||
|
||||
// should display 8 vertices, 18/12 edges, 12/6 faces (Tri/Poly)
|
||||
mesh_stats(mesh);
|
||||
|
||||
|
||||
// print out information about properties
|
||||
mesh_property_stats(mesh);
|
||||
|
||||
|
||||
std::cout << "Define some custom properties..\n";
|
||||
|
||||
OpenMesh::VPropHandleT<float> vprop_float;
|
||||
OpenMesh::EPropHandleT<bool> eprop_bool;
|
||||
OpenMesh::FPropHandleT<std::string> fprop_string;
|
||||
OpenMesh::HPropHandleT<MyData> hprop_mydata;
|
||||
OpenMesh::MPropHandleT<MyMap> mprop_map;
|
||||
|
||||
std::cout << ".. and registrate them at the mesh object.\n";
|
||||
|
||||
mesh.add_property(vprop_float, "vprop_float");
|
||||
mesh.add_property(eprop_bool, "eprop_bool");
|
||||
mesh.add_property(fprop_string, "fprop_string");
|
||||
mesh.add_property(hprop_mydata, "hprop_mydata");
|
||||
mesh.add_property(mprop_map, "mprop_map");
|
||||
|
||||
|
||||
mesh_property_stats(mesh);
|
||||
|
||||
|
||||
std::cout << "Now let's fill the props..\n";
|
||||
|
||||
fill_props(mesh, vprop_float);
|
||||
fill_props(mesh, eprop_bool);
|
||||
fill_props(mesh, fprop_string);
|
||||
fill_props(mesh, hprop_mydata);
|
||||
fill_props(mesh, mprop_map);
|
||||
|
||||
|
||||
std::cout << "Check props..\n";
|
||||
#define CHK_PROP( PH ) \
|
||||
std::cout << " " << #PH << " " \
|
||||
<< (fill_props(mesh, PH, true)?"ok\n":"error\n")
|
||||
|
||||
CHK_PROP(vprop_float);
|
||||
CHK_PROP(eprop_bool);
|
||||
CHK_PROP(fprop_string);
|
||||
CHK_PROP(hprop_mydata);
|
||||
CHK_PROP(mprop_map);
|
||||
#undef CHK_PROP
|
||||
|
||||
|
||||
std::cout << "Set persistent flag..\n";
|
||||
#define SET_PERS( PH ) \
|
||||
mesh.property(PH).set_persistent(true); \
|
||||
std::cout << " " << #PH << " " \
|
||||
<< (mesh.property(PH).persistent()?"ok\n":"failed!\n")
|
||||
|
||||
mesh.property(vprop_float).set_persistent(true);
|
||||
std::cout << " vprop_float "
|
||||
<< (mesh.property(vprop_float).persistent()?"ok\n":"failed!\n");
|
||||
|
||||
SET_PERS( eprop_bool );
|
||||
SET_PERS( fprop_string );
|
||||
SET_PERS( hprop_mydata );
|
||||
mesh.mproperty(mprop_map).set_persistent(true);
|
||||
std::cout << " mprop_map "
|
||||
<< (mesh.mproperty(mprop_map).persistent()?"ok\n":"failed!\n");
|
||||
|
||||
|
||||
std::cout << "Write mesh..";
|
||||
if (IO::write_mesh( mesh, "persistence-check.om" ))
|
||||
std::cout << " ok\n";
|
||||
else
|
||||
{
|
||||
std::cout << " failed\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
std::cout << "Clear mesh\n";
|
||||
mesh.clear();
|
||||
mesh_stats(mesh, " ");
|
||||
|
||||
|
||||
std::cout << "Read back mesh..";
|
||||
try
|
||||
{
|
||||
if (IO::read_mesh( mesh, "persistence-check.om" ))
|
||||
std::cout << " ok\n";
|
||||
else
|
||||
{
|
||||
std::cout << " failed!\n";
|
||||
return 1;
|
||||
}
|
||||
mesh_stats(mesh, " ");
|
||||
}
|
||||
catch( std::exception &x )
|
||||
{
|
||||
std::cerr << x.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
std::cout << "Check props..\n";
|
||||
#define CHK_PROP( PH ) \
|
||||
std::cout << " " << #PH << " " \
|
||||
<< (fill_props(mesh, PH, true)?"ok\n":"error\n")
|
||||
CHK_PROP(vprop_float);
|
||||
CHK_PROP(eprop_bool);
|
||||
CHK_PROP(fprop_string);
|
||||
CHK_PROP(hprop_mydata);
|
||||
CHK_PROP(mprop_map);
|
||||
#undef CHK_PROP
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// end of file
|
||||
// ============================================================================
|
||||
@@ -0,0 +1,20 @@
|
||||
#ifndef STATS_HH
|
||||
#define STATS_HH
|
||||
|
||||
template <typename Mesh>
|
||||
void mesh_stats( Mesh& _m, const std::string& prefix = "" )
|
||||
{
|
||||
std::cout << prefix
|
||||
<< _m.n_vertices() << " vertices, "
|
||||
<< _m.n_edges() << " edges, "
|
||||
<< _m.n_faces() << " faces\n";
|
||||
}
|
||||
|
||||
template <typename Mesh>
|
||||
void mesh_property_stats(Mesh& _m)
|
||||
{
|
||||
std::cout << "Current set of properties:\n";
|
||||
_m.property_stats(std::cout);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,62 @@
|
||||
|
||||
#include <OpenMesh/Core/IO/MeshIO.hh>
|
||||
#include <OpenMesh/Core/Mesh/DefaultTriMesh.hh>
|
||||
#include <OpenMesh/Core/Utils/PropertyManager.hh>
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
using MyMesh = OpenMesh::TriMesh;
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
// 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];
|
||||
|
||||
// Read mesh file
|
||||
if (!OpenMesh::IO::read_mesh(mesh, infile)) {
|
||||
std::cerr << "Error: Cannot read mesh from " << infile << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
{
|
||||
// Add a vertex property storing the laplace vector
|
||||
auto laplace = OpenMesh::VProp<MyMesh::Point>(mesh);
|
||||
|
||||
// Add a vertex property storing the laplace of the laplace
|
||||
auto bi_laplace = OpenMesh::VProp<MyMesh::Point>(mesh);
|
||||
|
||||
// Get a propertymanager of the points property of the mesh to use as functor
|
||||
auto points = OpenMesh::getPointsProperty(mesh);
|
||||
|
||||
// Smooth the mesh several times
|
||||
for (int i = 0; i < iterations; ++i) {
|
||||
// Iterate over all vertices to compute laplace vector
|
||||
for (const auto& vh : mesh.vertices())
|
||||
laplace(vh) = vh.vertices().avg(points) - points(vh);
|
||||
|
||||
// Iterate over all vertices to compute the laplace vector of the laplace vectors
|
||||
for (const auto& vh : mesh.vertices())
|
||||
bi_laplace(vh) = (vh.vertices().avg(laplace) - laplace(vh));
|
||||
|
||||
// update points by substracting the bi-laplacian damped by a factor of 0.5
|
||||
for (const auto& vh : mesh.vertices())
|
||||
points(vh) += -0.5 * bi_laplace(vh);
|
||||
}
|
||||
} // The laplace and update properties are 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
|
||||
#include <OpenMesh/Core/IO/MeshIO.hh>
|
||||
#include <OpenMesh/Core/Mesh/DefaultTriMesh.hh>
|
||||
#include <OpenMesh/Core/Utils/PropertyManager.hh>
|
||||
#include <OpenMesh/Core/Utils/Predicates.hh>
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
using MyMesh = OpenMesh::TriMesh;
|
||||
|
||||
bool is_divisible_by_3(OpenMesh::FaceHandle vh) { return vh.idx() % 3 == 0; }
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
using namespace OpenMesh::Predicates; // for easier access to predicates
|
||||
|
||||
// Read command line options
|
||||
MyMesh mesh;
|
||||
if (argc != 4) {
|
||||
std::cerr << "Usage: " << argv[0] << " infile" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
const std::string infile = argv[1];
|
||||
|
||||
// Read mesh file
|
||||
if (!OpenMesh::IO::read_mesh(mesh, infile)) {
|
||||
std::cerr << "Error: Cannot read mesh from " << infile << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Count boundary vertices
|
||||
std::cout << "Mesh contains " << mesh.vertices().count_if(Boundary()) << " boundary vertices";
|
||||
|
||||
// Selected inner vertices
|
||||
std::cout << "These are the selected inner vertices: " << std::endl;
|
||||
for (auto vh : mesh.vertices().filtered(!Boundary() && Selected()))
|
||||
std::cout << vh.idx() << ", ";
|
||||
std::cout << std::endl;
|
||||
|
||||
// Faces whose id is divisible by 3
|
||||
auto vec = mesh.faces().filtered(is_divisible_by_3).to_vector();
|
||||
std::cout << "There are " << vec.size() << " faces whose id is divisible by 3" << std::endl;
|
||||
|
||||
// Faces which are tagged or whose id is not divisible by 3
|
||||
auto vec2 = mesh.faces().filtered(Tagged() || !make_predicate(is_divisible_by_3)).to_vector();
|
||||
std::cout << "There are " << vec2.size() << " faces which are tagged or whose id is not divisible by 3" << std::endl;
|
||||
|
||||
// Edges that are longer than 10 or shorter than 2
|
||||
OpenMesh::EProp<bool> longer_than_10(mesh);
|
||||
for (auto eh : mesh.edges())
|
||||
longer_than_10[eh] = mesh.calc_edge_length(eh) > 10;
|
||||
std::cout << "There are " <<
|
||||
mesh.edges().count_if(make_predicate(longer_than_10) || make_predicate([&](OpenMesh::EdgeHandle eh) { return mesh.calc_edge_length(eh) < 2; })) <<
|
||||
" edges which are shorter than 2 or longer than 10" << std::endl;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
cmake_minimum_required(VERSION 3.25)
|
||||
|
||||
project(OpenMesh-Example)
|
||||
|
||||
find_package(OpenMesh)
|
||||
|
||||
set (targetName MyOwnProject)
|
||||
|
||||
add_executable (${targetName} build_cube.cc)
|
||||
target_link_libraries(${targetName} PRIVATE OpenMeshCore OpenMeshTools)
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
include (VCICommon)
|
||||
|
||||
include_directories (
|
||||
../../..
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
|
||||
set (targetName MyOwnProject)
|
||||
|
||||
# collect all header and source files
|
||||
vci_append_files (headers "*.hh" .)
|
||||
vci_append_files (sources "*.cc" .)
|
||||
|
||||
vci_add_executable (${targetName} ${headers} ${sources})
|
||||
|
||||
target_link_libraries (${targetName}
|
||||
OpenMeshCore
|
||||
OpenMeshTools
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user