First checkin for OpenMesh 2.0
git-svn-id: http://www.openmesh.org/svnrepo/OpenMesh/trunk@2 fdac6126-5c0c-442c-9429-916003d36597
28
Doc/ACGMakefile
Normal file
@@ -0,0 +1,28 @@
|
||||
#== SYSTEM PART -- DON'T TOUCH ==============================================
|
||||
include $(ACGMAKE)/Config
|
||||
#==============================================================================
|
||||
|
||||
|
||||
MODULES := doxygen
|
||||
|
||||
DOXY_PROJECT_NAME = OpenMesh
|
||||
|
||||
DOXY_FILE_PATTERNS = *.cc *.hh *.docu
|
||||
DOXY_EXCLUDE_DIRS = $(cur-dir)/Examples $(proj-dir)/Tools/Test $(proj-dir)/Apps
|
||||
DOXY_EXCLUDE_PATTERNS = CVS $(build-dir) *.moc.cc footer.hh
|
||||
DOXY_EXAMPLE_PATH = $(cur-dir)/Examples $(cur-dir)/Tutorial
|
||||
DOXY_EXAMPLE_PATTERNS = *.cc *.hh
|
||||
DOXY_MACROS = OM_Attribute=class
|
||||
|
||||
DOXY_GENERATE_HTML = YES
|
||||
DOXY_GENERATE_LATEX = NO
|
||||
DOXY_GENERATE_RTF = NO
|
||||
DOXY_GENERATE_MAN = NO
|
||||
DOXY_USE_PDFLATEX = YES
|
||||
DOXY_ACG_STYLE = YES
|
||||
DOXY_HAVE_DOT = NO
|
||||
DOXY_COLLABORATION_GRAPH = NO
|
||||
|
||||
#== SYSTEM PART -- DON'T TOUCH ==============================================
|
||||
include $(ACGMAKE)/Rules
|
||||
#==============================================================================
|
||||
188
Doc/Concepts/MeshItems.hh
Normal file
@@ -0,0 +1,188 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// OpenMesh
|
||||
// Copyright (C) 2001-2005 by Computer Graphics Group, RWTH Aachen
|
||||
// www.openmesh.org
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// License
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Library General Public License as published
|
||||
// by the Free Software Foundation, version 2.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Library General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Revision: 1.2 $
|
||||
// $Date: 2005-12-21 14:05:27 $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Mesh Items Concept
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
#error this file is for documentation purposes only
|
||||
|
||||
|
||||
//== NAMESPACES ===============================================================
|
||||
|
||||
|
||||
namespace OpenMesh {
|
||||
namespace Concepts {
|
||||
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
|
||||
/** \ingroup mesh_concepts_group
|
||||
The mesh items class encapsulates the types VertexT, HalfedgeT,
|
||||
EdgeT, and FaceT.
|
||||
\see VertexT, HalfedgeT, EdgeT, FaceT
|
||||
*/
|
||||
struct MeshItems {
|
||||
|
||||
|
||||
/** Interface for the internal vertex type. This minimal interface
|
||||
must be provided by every vertex. It's up to the mesh kernel (or
|
||||
the items used by the mesh kernel) to implement it.
|
||||
|
||||
All methods marked as internal should only be used by the mesh
|
||||
kernel.
|
||||
*/
|
||||
template <class Refs_> class VertexT
|
||||
{
|
||||
public:
|
||||
|
||||
/// Re-export the template argument Refs. This \b must be done!
|
||||
typedef Refs_ Refs;
|
||||
|
||||
/// Default constructor
|
||||
VertexT();
|
||||
|
||||
/// Get an outgoing halfedge
|
||||
HalfedgeHandle halfedge_handle() const;
|
||||
/// Set the outgoing halfedge link
|
||||
void set_halfedge_handle(HalfedgeHandle _eh);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/** Interface for the internal halfedge type. This minimal interface
|
||||
must be provided by every halfedge. It's up to the mesh kernel (or
|
||||
the items used by the mesh kernel) to implement it.
|
||||
|
||||
All methods marked as internal should only be used by the mesh
|
||||
kernel.
|
||||
*/
|
||||
template <class Refs_> class HalfedgeT
|
||||
{
|
||||
public:
|
||||
|
||||
/// Re-export the template argument Refs. This \b must be done!
|
||||
typedef Refs_ Refs;
|
||||
|
||||
/** Get the vertex the halfedge point to.
|
||||
\internal */
|
||||
VertexHandle vertex_handle() const;
|
||||
|
||||
/** Set the vertex the halfedge point to.
|
||||
\internal */
|
||||
void set_vertex_handle(VertexHandle _vh);
|
||||
|
||||
/** Get the face this halfedge belongs to.
|
||||
\internal */
|
||||
FaceHandle face_handle() const;
|
||||
|
||||
/** Set the face this halfedge belongs to.
|
||||
\internal */
|
||||
void set_face_handle(FaceHandle _fh);
|
||||
|
||||
/** Get the next halfedge inside this face.
|
||||
\internal */
|
||||
HalfedgeHandle next_halfedge_handle() const;
|
||||
|
||||
/** Set the next halfedge inside this face.
|
||||
\internal */
|
||||
void set_next_halfedge_handle(HalfedgeHandle _eh);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/** Interface for the internal edge type. This minimal interface must
|
||||
be provided by every edge. It's up to the mesh kernel (or the
|
||||
items used by the mesh kernel) to implement it.
|
||||
|
||||
All methods marked as internal should only be used by the mesh
|
||||
kernel.
|
||||
*/
|
||||
template <class Refs_> class EdgeT
|
||||
{
|
||||
public:
|
||||
|
||||
/// Re-export the template argument Refs. This \b must be done!
|
||||
typedef Refs_ Refs;
|
||||
|
||||
/** Store two halfedges.
|
||||
\internal */
|
||||
Halfedge halfedges[2];
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/** Interface for the internal face type. This minimal interface must
|
||||
be provided by every face. It's up to the mesh kernel (or the
|
||||
items used by the mesh kernel) to implement it.
|
||||
|
||||
All methods marked as internal should only be used by the mesh
|
||||
kernel.
|
||||
*/
|
||||
template <class Refs_> class FaceT
|
||||
{
|
||||
public:
|
||||
|
||||
/// Re-export the template argument Refs. This \b must be done!
|
||||
typedef Refs_ Refs;
|
||||
|
||||
/** Compile-time-tag: is this face a triangle? Should be typedef'ed
|
||||
to either GenProg::TagTrue or GenProg::TagFalse */
|
||||
typedef GenProg::TagTrue IsTriangle;
|
||||
/// Run-time test: is this face a triangle?
|
||||
static bool is_triangle();
|
||||
|
||||
/// Get the number of vertices of this face.
|
||||
unsigned char n_vertices() const;
|
||||
/** Set the number of vertices of this face.
|
||||
\internal */
|
||||
void set_n_vertices(unsigned char _n);
|
||||
|
||||
/// Get a halfedge that belongs to this face.
|
||||
HalfedgeHandle halfedge_handle() const;
|
||||
/** Set a halfedge that belongs this face.
|
||||
\internal */
|
||||
void set_halfedge_handle(HalfedgeHandle _eh);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
} // namespace Concepts
|
||||
} // namespace OpenMesh
|
||||
//=============================================================================
|
||||
510
Doc/Concepts/MeshKernel.hh
Normal file
@@ -0,0 +1,510 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// OpenMesh
|
||||
// Copyright (C) 2001-2005 by Computer Graphics Group, RWTH Aachen
|
||||
// www.openmesh.org
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// License
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Library General Public License as published
|
||||
// by the Free Software Foundation, version 2.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Library General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Revision: 1.2 $
|
||||
// $Date: 2005-12-21 14:05:27 $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Kernel Concept
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
#error this file is for documentation purposes only
|
||||
|
||||
|
||||
//== NAMESPACES ===============================================================
|
||||
|
||||
|
||||
namespace OpenMesh {
|
||||
namespace Concepts {
|
||||
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
|
||||
/** \ingroup mesh_concepts_group
|
||||
This class describes the minimum interface a mesh kernel
|
||||
has to implement (because the resulting mesh will rely on
|
||||
this interface).
|
||||
|
||||
This is the template class the actually holds the mesh kernel
|
||||
implementation. All functions marked as internal should only be used
|
||||
by the mesh class (that inherits the kernel). The mesh may then
|
||||
provide wrapper functions that provide the same functionality.
|
||||
|
||||
\todo Check, if the member list is complete.
|
||||
*/
|
||||
template <class FinalMeshItems> class KernelT
|
||||
{
|
||||
public:
|
||||
|
||||
/// \name Mesh Items
|
||||
//@{
|
||||
|
||||
/// Derive this type from the FinalMeshItems
|
||||
typedef typename FinalMeshItems::Vertex Vertex;
|
||||
typedef typename FinalMeshItems::Halfedge Halfedge;
|
||||
typedef typename FinalMeshItems::Edge Edge;
|
||||
typedef typename FinalMeshItems::Face Face;
|
||||
typedef typename FinalMeshItems::Point Point;
|
||||
typedef typename FinalMeshItems::Scalar Scalar;
|
||||
typedef typename FinalMeshItems::Normal Normal;
|
||||
typedef typename FinalMeshItems::Color Color;
|
||||
typedef typename FinalMeshItems::TexCoord TexCoord;
|
||||
typedef typename FinalMeshItems::VertexHandle VertexHandle;
|
||||
typedef typename FinalMeshItems::HalfedgeHandle HalfedgeHandle;
|
||||
typedef typename FinalMeshItems::EdgeHandle EdgeHandle;
|
||||
typedef typename FinalMeshItems::FaceHandle FaceHandle;
|
||||
|
||||
//@}
|
||||
|
||||
|
||||
/// \name Kernel Iterators
|
||||
//@{
|
||||
/// This type depends on the container type in use.
|
||||
typedef SomeIterator KernelVertexIter;
|
||||
typedef SomeIterator KernelConstVertexIter;
|
||||
typedef SomeIterator KernelEdgeIter;
|
||||
typedef SomeIterator KernelConstEdgeIter;
|
||||
typedef SomeIterator KernelFaceIter;
|
||||
typedef SomeIterator KernelConstFaceIter;
|
||||
//@}
|
||||
|
||||
/// \name Constructor/Destructor
|
||||
//@{
|
||||
/// Default constructor
|
||||
KernelT() {}
|
||||
|
||||
/// Destructor
|
||||
~KernelT();
|
||||
//@}
|
||||
|
||||
/// Assignment operator
|
||||
KernelT& operator=(const KernelT& _rhs);
|
||||
|
||||
|
||||
/** Reserve memory for vertices, edges, faces.
|
||||
*
|
||||
* Reserve memory for the mesh items vertices, edges, faces. Use
|
||||
* this method if you can estimate the memory consumption, for
|
||||
* instance in algorithm expanding the mesh. Depending on the
|
||||
* underlying array type you might be better of using this method,
|
||||
* then letting the array type decide when to increase the
|
||||
* capacity. For instance the STL vector class \c std::vector (used
|
||||
* in the supplied ArrayKernelT) doubles the capacity if it is
|
||||
* exhausted. This might lead to an memory allocation exception,
|
||||
* though an smaller increment would be enough.
|
||||
*/
|
||||
void reserve( unsigned int _n_vertices,
|
||||
unsigned int _n_edges,
|
||||
unsigned int _n_faces );
|
||||
|
||||
|
||||
/// \name Handle -> Item.
|
||||
//@{
|
||||
/// Translate handle to item (see also OpenMesh::PolyMeshT::deref())
|
||||
const Vertex& vertex(VertexHandle _h) const { return deref(_h); }
|
||||
Vertex& vertex(VertexHandle _h) { return deref(_h); }
|
||||
const Halfedge& halfedge(HalfedgeHandle _h) const { return deref(_h); }
|
||||
Halfedge& halfedge(HalfedgeHandle _h) { return deref(_h); }
|
||||
const Edge& edge(EdgeHandle _h) const { return deref(_h); }
|
||||
Edge& edge(EdgeHandle _h) { return deref(_h); }
|
||||
const Face& face(FaceHandle _h) const { return deref(_h); }
|
||||
Face& face(FaceHandle _h) { return deref(_h); }
|
||||
//@}
|
||||
|
||||
|
||||
/// \name Item -> Handle
|
||||
//@{
|
||||
/// Translate item to handle
|
||||
VertexHandle handle(const Vertex& _v) const;
|
||||
HalfedgeHandle handle(const Halfedge& _he) const;
|
||||
EdgeHandle handle(const Edge& _e) const;
|
||||
FaceHandle handle(const Face& _f) const;
|
||||
//@}
|
||||
|
||||
|
||||
/// \name Get the i'th item
|
||||
//@{
|
||||
/// Get the i'th item
|
||||
VertexHandle vertex_handle(unsigned int _i) const;
|
||||
HalfedgeHandle halfedge_handle(unsigned int _i) const;
|
||||
EdgeHandle edge_handle(unsigned int _i) const;
|
||||
FaceHandle face_handle(unsigned int _i) const;
|
||||
//@}
|
||||
|
||||
|
||||
/// \name Delete items
|
||||
//@{
|
||||
/// Delete all items, i.e. clear all item containers.
|
||||
void clear();
|
||||
/** Remove all items that are marked as deleted from the
|
||||
corresponding containers.
|
||||
\note Needs the Attributes::Status attribute
|
||||
\note This function may not be implemented for all kernels.
|
||||
*/
|
||||
void garbage_collection();
|
||||
|
||||
/** Remove the last vertex imidiately, i.e. call pop_back() for the
|
||||
VertexContainer.
|
||||
*/
|
||||
void remove_last_vertex() { vertices_.pop_back(); }
|
||||
/** Remove the last edge imidiately, i.e. call pop_back() for the
|
||||
EdgeContainer. Used e.g. by the add_face() method of PolyMeshT
|
||||
*/
|
||||
void remove_last_edge() { edges_.pop_back(); }
|
||||
/** Remove the last face imidiately, i.e. call pop_back() for the
|
||||
FaceContainer. Used e.g. by the add_face() method of PolyMeshT
|
||||
*/
|
||||
void remove_last_face() { faces_.pop_back(); }
|
||||
|
||||
//@}
|
||||
|
||||
|
||||
|
||||
|
||||
/// \name Number of elements
|
||||
//@{
|
||||
/// Returns number of vertices
|
||||
unsigned int n_vertices() const;
|
||||
/// Returns number of halfedges (should be 2*n_edges())
|
||||
unsigned int n_halfedges() const;
|
||||
/// Returns number of edges
|
||||
unsigned int n_edges() const;
|
||||
/// Returns number of faces
|
||||
unsigned int n_faces() const;
|
||||
/// Is the vertex container empty?
|
||||
bool vertices_empty() const;
|
||||
/// Is the halfedge container empty (should be the same as edges_empty()).
|
||||
bool halfedges_empty() const;
|
||||
/// Is the edge container empty?
|
||||
bool edges_empty() const;
|
||||
/// Is the face container empty?
|
||||
bool faces_empty() const;
|
||||
//@}
|
||||
|
||||
|
||||
|
||||
/// \name Vertex connectivity
|
||||
//@{
|
||||
/// Get an outgoing halfedge of a given vertex
|
||||
HalfedgeHandle halfedge_handle(VertexHandle _vh) const;
|
||||
/// Set the outgoing halfedge handle of a given vertex
|
||||
void set_halfedge_handle(VertexHandle _vh, HalfedgeHandle _heh);
|
||||
/// Get the coordinate of a vertex
|
||||
const Point& point(VertexHandle _vh) const;
|
||||
/// Get the coordinate of a vertex
|
||||
const Point& point(const Vertex& _v) const;
|
||||
/// Set the coordinate of a vertex
|
||||
void set_point(VertexHandle _vh, const Point& _p);
|
||||
/// Set the coordinate of a vertex
|
||||
void set_point(Vertex& _v, const Point& _p);
|
||||
//@}
|
||||
|
||||
|
||||
|
||||
|
||||
/// \name Halfedge connectivity
|
||||
//@{
|
||||
/// Get the vertex the halfedge points to
|
||||
VertexHandle to_vertex_handle(HalfedgeHandle _heh) const;
|
||||
/** Get the vertex the halfedge starts from (implemented as to-handle
|
||||
of the opposite halfedge, provided for convenience) */
|
||||
VertexHandle from_vertex_handle(HalfedgeHandle _heh) const;
|
||||
/// Set the to-vertex-handle of the halfedge
|
||||
void set_vertex_handle(HalfedgeHandle _heh, VertexHandle _vh);
|
||||
/** Get the face the halfedge belongs to.
|
||||
\note The handle is invalid if the halfedge is a boundary halfedge */
|
||||
FaceHandle face_handle(HalfedgeHandle _heh) const;
|
||||
/// Set the face the halfedge belongs to
|
||||
void set_face_handle(HalfedgeHandle _heh, FaceHandle _fh);
|
||||
/// Get the next halfedge handle
|
||||
HalfedgeHandle next_halfedge_handle(HalfedgeHandle _heh) const;
|
||||
/** Set the next halfedge handle. \note If the previous halfedge is
|
||||
also stored (see OpenMesh::Attributes::PrevHalfedge) then this
|
||||
method also has to set this link) */
|
||||
void set_next_halfedge_handle(HalfedgeHandle _heh, HalfedgeHandle _nheh);
|
||||
/** Get the previous halfedge of the given halfedge. The
|
||||
implementation should take care of an existing
|
||||
OpenMesh::Attributes::PrevHalfedge attribute. */
|
||||
HalfedgeHandle prev_halfedge_handle(HalfedgeHandle _heh) const;
|
||||
/// Get the opposite halfedge
|
||||
HalfedgeHandle opposite_halfedge_handle(HalfedgeHandle _heh) const;
|
||||
/// Counter-clockwise rotate the given halfedge around its from vertex
|
||||
HalfedgeHandle ccw_rotated_halfedge_handle(HalfedgeHandle _heh) const;
|
||||
/// Clockwise rotate the given halfedge around its from vertex
|
||||
HalfedgeHandle cw_rotated_halfedge_handle(HalfedgeHandle _heh) const;
|
||||
/// Get the edge the current halfedge it contained in
|
||||
EdgeHandle edge_handle(HalfedgeHandle _heh) const;
|
||||
//@}
|
||||
|
||||
|
||||
|
||||
/// \name Edge connectivity
|
||||
//@{
|
||||
/// Get the first or second halfedge of the given edge
|
||||
HalfedgeHandle halfedge_handle(EdgeHandle _eh, unsigned int _i) const;
|
||||
//@}
|
||||
|
||||
|
||||
|
||||
/// \name Face connectivity
|
||||
//@{
|
||||
/// Get a halfedge belonging to the face
|
||||
HalfedgeHandle halfedge_handle(FaceHandle _fh) const;
|
||||
/// Set one halfedge of the face
|
||||
void set_halfedge_handle(FaceHandle _fh, HalfedgeHandle _heh);
|
||||
//@}
|
||||
|
||||
|
||||
public: // Standard Property Management
|
||||
|
||||
/// \name set/get value of a standard property
|
||||
//@{
|
||||
|
||||
// vertex
|
||||
const Point& point(VertexHandle _vh) const; ///< Get position
|
||||
void set_point(VertexHandle _vh, const Point& _p); ///< Set position
|
||||
Point& point(VertexHandle _vh); ///< Convenience function
|
||||
|
||||
const Normal& normal(VertexHandle _vh) const; ///< Get normal
|
||||
void set_normal(VertexHandle _vh, const Normal& _n); ///< Set normal
|
||||
|
||||
const Color& color(VertexHandle _vh) const; ///< Get color
|
||||
void set_color(VertexHandle _vh, const Color& _c) ///< Set color
|
||||
|
||||
const TexCoord& texcoord(VertexHandle _vh) const; ///< Get texture coordinate.
|
||||
void set_texcoord(VertexHandle _vh, const TexCoord& _t); ///< Set texture coordinate.
|
||||
|
||||
const StatusInfo& status(VertexHandle _vh) const; ///< Get status
|
||||
StatusInfo& status(VertexHandle _vh); ///< Get status
|
||||
|
||||
// halfedge
|
||||
const StatusInfo& status(HalfedgeHandle _vh) const; ///< Get status
|
||||
StatusInfo& status(HalfedgeHandle _vh); ///< Get status
|
||||
|
||||
// edge
|
||||
const StatusInfo& status(EdgeHandle _vh) const; ///< Get status
|
||||
StatusInfo& status(EdgeHandle _vh); ///< Get status
|
||||
|
||||
// face
|
||||
const Normal& normal(FaceHandle _fh) const; ///< Get normal
|
||||
void set_normal(FaceHandle _fh, const Normal& _n); ///< Set normal
|
||||
|
||||
const Color& color(FaceHandle _fh) const; ///< Get color
|
||||
void set_color(FaceHandle _fh, const Color& _c); ///< Set color
|
||||
|
||||
const StatusInfo& status(FaceHandle _vh) const; ///< Get status
|
||||
StatusInfo& status(FaceHandle _vh); ///< Get status
|
||||
|
||||
//@}
|
||||
|
||||
/// \name Dynamically add standard properties
|
||||
//@{
|
||||
/// Request property
|
||||
void request_vertex_normals();
|
||||
void request_vertex_colors();
|
||||
void request_vertex_texcoords();
|
||||
void request_vertex_status();
|
||||
|
||||
void request_halfedge_status();
|
||||
|
||||
void request_edge_status();
|
||||
|
||||
void request_face_normals();
|
||||
void request_face_colors();
|
||||
void request_face_status();
|
||||
//@}
|
||||
|
||||
/// \name Remove standard properties
|
||||
//@{
|
||||
/// Remove property
|
||||
void release_vertex_normals();
|
||||
void release_vertex_colors();
|
||||
void release_vertex_texcoords();
|
||||
void release_vertex_status();
|
||||
|
||||
void release_halfedge_status();
|
||||
|
||||
void release_edge_status();
|
||||
|
||||
void release_face_normals();
|
||||
void release_face_colors();
|
||||
void release_face_status();
|
||||
//@}
|
||||
|
||||
/// \name Check availability of standard properties
|
||||
//@{
|
||||
/// Is property available?
|
||||
bool has_vertex_normals() const;
|
||||
bool has_vertex_colors() const;
|
||||
bool has_vertex_texcoords() const;
|
||||
bool has_vertex_status() const;
|
||||
bool has_edge_status() const;
|
||||
bool has_halfedge_status() const;
|
||||
bool has_face_normals() const;
|
||||
bool has_face_colors() const;
|
||||
bool has_face_status() const;
|
||||
//@}
|
||||
|
||||
public: // Property Management
|
||||
|
||||
/// \anchor concepts_kernelt_property_management
|
||||
|
||||
/// \name Property management - add property
|
||||
//@{
|
||||
/// Add property.
|
||||
/// @copydoc OpenMesh::BaseKernel::add_property()
|
||||
template <typename T> bool add_property( [VEHFM]PropHandleT<T>& _ph,
|
||||
const std::string& _name = "" );
|
||||
//@}
|
||||
|
||||
/// \name Property management - remove property
|
||||
//@{
|
||||
/// Remove property
|
||||
template <typename T> void remove_property( [VEHFM]PropHandleT<T>& );
|
||||
//@}
|
||||
|
||||
/// \name Property management - get property by name
|
||||
//@{
|
||||
/// Get property handle by name
|
||||
template <typename T>
|
||||
bool get_property_handle( [VEHFM]PropHandleT<T>& ph, const std::string& _n ) const;
|
||||
//@}
|
||||
|
||||
/// \name Property management - get property
|
||||
//@{
|
||||
/// Get property
|
||||
template <typename T> PropertyT<T>& property( [VEHF]PropHandleT<T> _ph );
|
||||
template <typename T> const PropertyT<T>& property( [VEHF]PropHandleT<T> _ph ) const;
|
||||
template <typename T> PropertyT<T>& mproperty( MPropHandleT<T> _ph );
|
||||
template <typename T> const PropertyT<T>& mproperty( MPropHandleT<T> _ph ) const;
|
||||
//@}
|
||||
|
||||
/// \name Property management - get property value for an item
|
||||
//@{
|
||||
|
||||
/// Get value for item represented by the handle.
|
||||
template <typename T>
|
||||
T& property( VPropHandleT<T> _ph, VertexHandle _vh );
|
||||
template <typename T>
|
||||
const T& property( VPropHandleT<T> _ph, VertexHandle _vh ) const;
|
||||
|
||||
template <typename T>
|
||||
T& property( EPropHandleT<T> _ph, EdgeHandle _vh );
|
||||
template <typename T>
|
||||
const T& property( EPropHandleT<T> _ph, EdgeHandle _vh ) const;
|
||||
|
||||
template <typename T>
|
||||
T& property( HPropHandleT<T> _ph, HalfedgeHandle _vh );
|
||||
template <typename T>
|
||||
const T& property( HPropHandleT<T> _ph, HalfedgeHandle _vh ) const;
|
||||
|
||||
template <typename T>
|
||||
T& property( FPropHandleT<T> _ph, FaceHandle _vh );
|
||||
template <typename T>
|
||||
const T& property( FPropHandleT<T> _ph, FaceHandle _vh ) const;
|
||||
|
||||
template <typename T>
|
||||
T& property( MPropHandleT<T> _ph );
|
||||
template <typename T>
|
||||
const T& property( MPropHandleT<T> _ph ) const;
|
||||
|
||||
//@}
|
||||
|
||||
public:
|
||||
|
||||
|
||||
/// \name Low-level adding new items
|
||||
//@{
|
||||
/** Add a new (default) vertex.
|
||||
\internal */
|
||||
VertexHandle new_vertex();
|
||||
/** Add a new vertex with a given point coordinate.
|
||||
\internal */
|
||||
VertexHandle new_vertex(const Point& _p);
|
||||
/** Add a new vertex (copied from the given one).
|
||||
\internal */
|
||||
VertexHandle new_vertex(const Vertex& _v);
|
||||
/** Add a new edge from \c _start_vertex_handle to \c _end_vertex_handle.
|
||||
This method should add an edge (i.e. two opposite halfedges) and set
|
||||
the corresponding vertex handles of these halfedges.
|
||||
\internal
|
||||
*/
|
||||
HalfedgeHandle new_edge(VertexHandle _start_vertex_handle,
|
||||
VertexHandle _end_vertex_handle);
|
||||
|
||||
/** Adding a new face
|
||||
\internal
|
||||
*/
|
||||
FaceHandle new_face();
|
||||
/** Adding a new face (copied from a \c _f).
|
||||
\internal */
|
||||
FaceHandle new_face(const Face& _f);
|
||||
//@}
|
||||
|
||||
|
||||
// --- iterators ---
|
||||
|
||||
/// \name Kernel item iterators
|
||||
//@{
|
||||
/** Kernel item iterator
|
||||
\internal */
|
||||
KernelVertexIter vertices_begin();
|
||||
KernelConstVertexIter vertices_begin() const;
|
||||
KernelVertexIter vertices_end();
|
||||
KernelConstVertexIter vertices_end() const;
|
||||
KernelEdgeIter edges_begin();
|
||||
KernelConstEdgeIter edges_begin() const;
|
||||
KernelEdgeIter edges_end();
|
||||
KernelConstEdgeIter edges_end() const;
|
||||
KernelFaceIter faces_begin();
|
||||
KernelConstFaceIter faces_begin() const;
|
||||
KernelFaceIter faces_end();
|
||||
KernelConstFaceIter faces_end() const;
|
||||
//@}
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
|
||||
// --- private functions ---
|
||||
|
||||
/// copy constructor: not used
|
||||
KernelT(const KernelT& _rhs);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
} // namespace Concepts
|
||||
} // namespace OpenMesh
|
||||
//=============================================================================
|
||||
1417
Doc/Doxyfile
Normal file
22
Doc/Examples/BaseExporter.hh
Normal file
@@ -0,0 +1,22 @@
|
||||
class BaseExporter
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void update() = 0;
|
||||
|
||||
virtual PVertexIter const_vertices_begin() = 0;
|
||||
virtual PVertexIter const_vertices_end() = 0;
|
||||
|
||||
virtual PTexCoordIter const_texcoords_begin() = 0;
|
||||
virtual PTexCoordIter const_texcoords_end() = 0;
|
||||
|
||||
virtual PIdxFaceIter const_idx_faces_begin() = 0;
|
||||
virtual PIdxFaceIter const_idx_faces_end() = 0;
|
||||
|
||||
virtual PFaceIter const_set_faces_begin() = 0;
|
||||
virtual PFaceIter const_set_faces_end() = 0;
|
||||
|
||||
virtual unsigned int n_faces() = 0;
|
||||
virtual unsigned int n_vertices() = 0;
|
||||
virtual unsigned int n_texcoords() = 0;
|
||||
};
|
||||
9
Doc/Examples/BaseImporter.hh
Normal file
@@ -0,0 +1,9 @@
|
||||
class BaseImporter
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void add_vertex (const OpenMesh::Vec3f&) {};
|
||||
virtual void add_normal (const OpenMesh::Vec3f&) {};
|
||||
virtual void add_texture (const OpenMesh::Vec2f&) {};
|
||||
virtual void add_face (const FaceType&) {};
|
||||
};
|
||||
13
Doc/Examples/BaseReader.hh
Normal file
@@ -0,0 +1,13 @@
|
||||
class BaseReader
|
||||
{
|
||||
public:
|
||||
|
||||
virtual std::string get_description() const = 0;
|
||||
virtual std::string get_extensions() const = 0;
|
||||
virtual std::string get_magic() const { return std::string(""); }
|
||||
|
||||
virtual bool read(std::istream& _is, BaseImporter& _bi) const = 0;
|
||||
virtual bool read(const std::string& _filename, BaseImporter& _bi) const = 0;
|
||||
|
||||
...
|
||||
};
|
||||
50
Doc/Examples/adasub.cc
Normal file
@@ -0,0 +1,50 @@
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <OpenMesh/Core/IO/MeshIO.hh>
|
||||
#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
|
||||
#include <OpenMesh/Tools/Subdivider/Adaptive/CompositeT.hh>
|
||||
|
||||
// ----------------------------------------
|
||||
|
||||
using OpenMesh::Subdivider::Adaptive;
|
||||
|
||||
// ---------------------------------------- necessary types
|
||||
|
||||
OpenMesh::TriMesh_ArrayKernelT< CompositeTraits > MyMesh;
|
||||
CompositeT< MyMesh > Subdivider;
|
||||
|
||||
// ---------------------------------------- setup a subdivider
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
MyMesh mesh; // create mesh and fill it
|
||||
|
||||
if (!OpenMesh::IO::read_mesh(mesh, argv[1]))
|
||||
return 1; // error reading mesh
|
||||
|
||||
Subdivider subdivider(mesh); // bind subdivider to mesh
|
||||
|
||||
// -------------------- add some rules
|
||||
|
||||
// anonymous registration
|
||||
subdivider.add< Tvv3<MyMesh>::Handle >();
|
||||
subdivider.add< VF<MyMesh>::Handle >();
|
||||
subdivider.add< FF<MyMesh>::Handle >();
|
||||
|
||||
// 'named' registration
|
||||
FVc<MyMesh>::Handle hFVc;
|
||||
subdivider.add( hFVc );
|
||||
|
||||
// print pre-computed coefficients to std::cout...
|
||||
std::copy(subdivider.rule( hFVc ).coeffs().begin(),
|
||||
subdivider.rule( hFVc ).coeffs().end(),
|
||||
std::ostream_iterator<double>(std::cout, ", "));
|
||||
|
||||
// prepare subdivider and the traits
|
||||
if (!subdivider.initialize())
|
||||
return 1; // error initializing subdivider
|
||||
|
||||
MyMesh::FaceHandle fh; // select a face
|
||||
subdivider.refine(fh);
|
||||
}
|
||||
8
Doc/Examples/build-trimesh.cc
Normal file
@@ -0,0 +1,8 @@
|
||||
template <class Traits>
|
||||
struct TriMesh_ArrayKernel_GeneratorT
|
||||
{
|
||||
typedef FinalMeshItemsT<ArrayItems, Traits, true> MeshItems;
|
||||
typedef AttribKernelT<MeshItems> AttribKernel;
|
||||
typedef ArrayKernelT<AttribKernel, MeshItems> MeshKernel;
|
||||
typedef TriMeshT<MeshKernel> Mesh;
|
||||
};
|
||||
11
Doc/Examples/circulators.cc
Normal file
@@ -0,0 +1,11 @@
|
||||
MyMesh mesh;
|
||||
|
||||
// (linearly) iterate over all vertices
|
||||
for (MyMesh::VertexIter v_it=mesh.vertices_begin(); v_it!=mesh.vertices_end(); ++v_it)
|
||||
{
|
||||
// circulate around the current vertex
|
||||
for (MyMesh::VertexVertexIter vv_it=mesh.vv_iter(v_it.handle()); vv_it; ++vv_it)
|
||||
{
|
||||
// do something with e.g. mesh.point(*vv_it)
|
||||
}
|
||||
}
|
||||
30
Doc/Examples/decimater.cc
Normal file
@@ -0,0 +1,30 @@
|
||||
//
|
||||
using namespace OpenMesh
|
||||
|
||||
// ---------------------------------------- necessary types
|
||||
|
||||
// Mesh type
|
||||
typedef TriMesh_ArrayKernelT<> Mesh;
|
||||
|
||||
// Decimater type
|
||||
typedef Decimater::DecimaterT< Mesh > Decimater;
|
||||
|
||||
// Decimation Module Handle type
|
||||
typedef Decimater::ModQuadricT< decimater >::Handle HModQuadric;
|
||||
|
||||
// ---------------------------------------- decimater setup
|
||||
|
||||
Mesh mesh; // a mesh object
|
||||
Decimater decimater(mesh); // a decimater object, connected to a mesh
|
||||
HModQuadric hModQuadric; // use a quadric module
|
||||
|
||||
decimater.add( hModQuadric ); // register module at the decimater
|
||||
|
||||
std::cout << decimater.module( hModQuadric ).name() << std::endl;
|
||||
// the way to access the module
|
||||
|
||||
decimater.initialize(); // let the decimater initialize the mesh and the
|
||||
// modules
|
||||
|
||||
decimater.decimate(); // do decimation
|
||||
|
||||
14
Doc/Examples/draw_normals.cc
Normal file
@@ -0,0 +1,14 @@
|
||||
#include <OpenMesh/Core/Utils/GenProg.hh>
|
||||
|
||||
// draw a face normal if we have one
|
||||
void drawFaceNormal(const MyMesh::Face& _f) {
|
||||
drawFaceNormal(_f, GenProg::Bool2Type<OM_Check_Attrib(MyMesh::Face, Normal)>());
|
||||
}
|
||||
|
||||
// normal exists -> use it
|
||||
void drawFaceNormal(const MyMesh::Face& _f, GenProg::Bool2Type<true>) {
|
||||
glNormal3fv(_f.normal());
|
||||
}
|
||||
|
||||
// empty dummy (no normals)
|
||||
void drawFaceNormal(const MyMesh::Face& _f, GenProg::Bool2Type<false>){}
|
||||
18
Doc/Examples/iterators.cc
Normal file
@@ -0,0 +1,18 @@
|
||||
MyMesh mesh;
|
||||
|
||||
// iterate over all vertices
|
||||
for (MyMesh::VertexIter v_it=mesh.vertices_begin(); v_it!=mesh.vertices_end(); ++v_it)
|
||||
...; // do something with *v_it, v_it->, or v_it.handle()
|
||||
|
||||
// iterate over all halfedges
|
||||
for (MyMesh::HalfedgeIter h_it=mesh.halfedges_begin(); v_it!=mesh.halfedges_end(); ++v_it)
|
||||
...; // do something with *h_it, h_it->, or h_it.handle()
|
||||
|
||||
// iterate over all edges
|
||||
for (MyMesh::EdgeIter e_it=mesh.edges_begin(); v_it!=mesh.edges_end(); ++v_it)
|
||||
...; // do something with *e_it, e_it->, or e_it.handle()
|
||||
|
||||
// iterator over all faces
|
||||
for (MyMesh::FaceIter f_it=mesh.faces_begin(); v_it!=mesh.faces_end(); ++v_it)
|
||||
...; // do something with *f_it, f_it->, or f_it.handle()
|
||||
|
||||
17
Doc/Examples/mesh_io.cc
Normal file
@@ -0,0 +1,17 @@
|
||||
#include <OpenMesh/Core/IO/MeshIO.hh>
|
||||
|
||||
MyMesh mesh;
|
||||
|
||||
if (!OpenMesh::IO::read_mesh(mesh, "some input file"))
|
||||
{
|
||||
std::cerr << "read error\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// do something with your mesh ...
|
||||
|
||||
if (!OpenMesh::IO::write_mesh(mesh, "some output file"))
|
||||
{
|
||||
std::cerr << "write error\n";
|
||||
exit(1);
|
||||
}
|
||||
51
Doc/Examples/mymesh.cc
Normal file
@@ -0,0 +1,51 @@
|
||||
#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
|
||||
|
||||
|
||||
// define traits
|
||||
struct MyTraits : public OpenMesh::DefaultTraits
|
||||
{
|
||||
// use double valued coordinates
|
||||
typedef OpenMesh::Vec3d Point;
|
||||
|
||||
// use vertex normals and vertex colors
|
||||
VertexAttributes( OpenMesh::DefaultAttributer::Normal |
|
||||
OpenMesh::DefaultAttributer::Color );
|
||||
|
||||
// store the previous halfedge
|
||||
HalfedgeAttributes( OpenMesh::DefaultAttributer::PrevHalfedge );
|
||||
|
||||
// use face normals
|
||||
FaceAttributes( OpenMesh::DefaultAttributer::Normal );
|
||||
|
||||
// store a face handle for each vertex
|
||||
VertexTraits
|
||||
{
|
||||
typename Base::Refs::FaceHandle my_face_handle;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
// Select mesh type (TriMesh) and kernel (ArrayKernel)
|
||||
// and define my personal mesh type (MyMesh)
|
||||
typedef OpenMesh::TriMesh_ArrayKernelT<MyTraits> MyMesh;
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
MyMesh mesh;
|
||||
|
||||
// -------------------- Add dynamic data
|
||||
|
||||
// for each vertex an extra double value
|
||||
OpenMesh::VPropHandleT< double > vprop_double;
|
||||
mesh.add_property( vprop_double );
|
||||
|
||||
// for the mesh an extra string
|
||||
OpenMesh::MPropHandleT< string > mprop_string;
|
||||
mesh.add_property( mprop_string );
|
||||
|
||||
// -------------------- do something
|
||||
|
||||
...;
|
||||
|
||||
}
|
||||
17
Doc/Examples/traits0.cc
Normal file
@@ -0,0 +1,17 @@
|
||||
struct DefaultTraits
|
||||
{
|
||||
typedef Vec3f Point;
|
||||
typedef Vec3f Normal;
|
||||
typedef Vec2f TexCoord;
|
||||
typedef Vec3uc Color;
|
||||
|
||||
VertexTraits {};
|
||||
HalfedgeTraits {};
|
||||
EdgeTraits {};
|
||||
FaceTraits {};
|
||||
|
||||
VertexAttributes(0);
|
||||
HalfedgeAttributes(Attributes::PrevHalfedge);
|
||||
EdgeAttributes(0);
|
||||
FaceAttributes(0);
|
||||
};
|
||||
4
Doc/Examples/traits1.cc
Normal file
@@ -0,0 +1,4 @@
|
||||
struct MyTraits : public OpenMesh::DefaultTraits
|
||||
{
|
||||
typedef OpenMesh::Vec3d Point; // use double-values points
|
||||
};
|
||||
7
Doc/Examples/traits2.cc
Normal file
@@ -0,0 +1,7 @@
|
||||
struct MyTraits : public OpenMesh::DefaultTraits
|
||||
{
|
||||
VertexTraits
|
||||
{
|
||||
int some_additional_index;
|
||||
};
|
||||
};
|
||||
7
Doc/Examples/traits3.cc
Normal file
@@ -0,0 +1,7 @@
|
||||
struct MyTraits : public OpenMesh::DefaultTraits
|
||||
{
|
||||
template <class Base, class Refs> struct VertexT : public Base
|
||||
{
|
||||
int some_additional_index;
|
||||
};
|
||||
};
|
||||
8
Doc/Examples/traits4.cc
Normal file
@@ -0,0 +1,8 @@
|
||||
struct MyTraits : public OpenMesh::DefaultTraits
|
||||
{
|
||||
VertexTraits
|
||||
{
|
||||
int some_additional_index;
|
||||
typename Base::Refs::FaceHandle my_face_handle;
|
||||
};
|
||||
};
|
||||
7
Doc/Examples/traits5.cc
Normal file
@@ -0,0 +1,7 @@
|
||||
struct MyTraits : public OpenMesh::DefaultTraits
|
||||
{
|
||||
VertexAttributes( OpenMesh::Attributes::Normal |
|
||||
OpenMesh::Attributes::Color );
|
||||
|
||||
FaceAttributes( OpenMesh::Attributes::Normal );
|
||||
};
|
||||
24
Doc/Tutorial/01-build_cube/ACGMakefile
Normal file
@@ -0,0 +1,24 @@
|
||||
#== SYSTEM PART -- DON'T TOUCH ==============================================
|
||||
include $(ACGMAKE)/Config
|
||||
#==============================================================================
|
||||
|
||||
|
||||
# subdirs to process
|
||||
SUBDIRS = $(call find-subdirs)
|
||||
|
||||
# programms (files containing main(), w/o suffix)
|
||||
EXECS = $(call cxx-find-execs)
|
||||
|
||||
# packages (qt, opengl, ...)
|
||||
PACKAGES :=
|
||||
|
||||
# project DSOs
|
||||
PROJ_LIBS := OpenMesh/Core
|
||||
|
||||
# modules to use (cxx, c, moc, uic, yacc) ! order-dependent !
|
||||
MODULES := cxx
|
||||
|
||||
|
||||
#== SYSTEM PART -- DON'T TOUCH ==============================================
|
||||
include $(ACGMAKE)/Rules
|
||||
#==============================================================================
|
||||
127
Doc/Tutorial/01-build_cube/build_cube.cc
Normal file
@@ -0,0 +1,127 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// OpenMesh
|
||||
// Copyright (C) 2001-2005 by Computer Graphics Group, RWTH Aachen
|
||||
// www.openmesh.org
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// License
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Library General Public License as published
|
||||
// by the Free Software Foundation, version 2.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Library General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Revision: 1.2 $
|
||||
// $Date: 2005-12-21 14:05:30 $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
#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;
|
||||
}
|
||||
24
Doc/Tutorial/02-iterators/ACGMakefile
Normal file
@@ -0,0 +1,24 @@
|
||||
#== SYSTEM PART -- DON'T TOUCH ==============================================
|
||||
include $(ACGMAKE)/Config
|
||||
#==============================================================================
|
||||
|
||||
|
||||
# subdirs to process
|
||||
SUBDIRS = $(call find-subdirs)
|
||||
|
||||
# programms (files containing main(), w/o suffix)
|
||||
EXECS = $(call cxx-find-execs)
|
||||
|
||||
# packages (qt, opengl, ...)
|
||||
PACKAGES :=
|
||||
|
||||
# project DSOs
|
||||
PROJ_LIBS := OpenMesh/Core
|
||||
|
||||
# modules to use (cxx, c, moc, uic, yacc) ! order-dependent !
|
||||
MODULES := cxx
|
||||
|
||||
|
||||
#== SYSTEM PART -- DON'T TOUCH ==============================================
|
||||
include $(ACGMAKE)/Rules
|
||||
#==============================================================================
|
||||
76
Doc/Tutorial/02-iterators/smooth.cc
Normal file
@@ -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; ++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;
|
||||
}
|
||||
24
Doc/Tutorial/03-properties/ACGMakefile
Normal file
@@ -0,0 +1,24 @@
|
||||
#== SYSTEM PART -- DON'T TOUCH ==============================================
|
||||
include $(ACGMAKE)/Config
|
||||
#==============================================================================
|
||||
|
||||
|
||||
# subdirs to process
|
||||
SUBDIRS = $(call find-subdirs)
|
||||
|
||||
# programms (files containing main(), w/o suffix)
|
||||
EXECS = $(call cxx-find-execs)
|
||||
|
||||
# packages (qt, opengl, ...)
|
||||
PACKAGES :=
|
||||
|
||||
# project DSOs
|
||||
PROJ_LIBS := OpenMesh/Core
|
||||
|
||||
# modules to use (cxx, c, moc, uic, yacc) ! order-dependent !
|
||||
MODULES := cxx
|
||||
|
||||
|
||||
#== SYSTEM PART -- DON'T TOUCH ==============================================
|
||||
include $(ACGMAKE)/Rules
|
||||
#==============================================================================
|
||||
74
Doc/Tutorial/03-properties/smooth.cc
Normal file
@@ -0,0 +1,74 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
// --------------------
|
||||
#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 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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
24
Doc/Tutorial/04-stl_algorithms/ACGMakefile
Normal file
@@ -0,0 +1,24 @@
|
||||
#== SYSTEM PART -- DON'T TOUCH ==============================================
|
||||
include $(ACGMAKE)/Config
|
||||
#==============================================================================
|
||||
|
||||
|
||||
# subdirs to process
|
||||
SUBDIRS = $(call find-subdirs)
|
||||
|
||||
# programms (files containing main(), w/o suffix)
|
||||
EXECS = $(call cxx-find-execs)
|
||||
|
||||
# packages (qt, opengl, ...)
|
||||
PACKAGES :=
|
||||
|
||||
# project DSOs
|
||||
PROJ_LIBS := OpenMesh/Core
|
||||
|
||||
# modules to use (cxx, c, moc, uic, yacc) ! order-dependent !
|
||||
MODULES := cxx
|
||||
|
||||
|
||||
#== SYSTEM PART -- DON'T TOUCH ==============================================
|
||||
include $(ACGMAKE)/Rules
|
||||
#==============================================================================
|
||||
59
Doc/Tutorial/04-stl_algorithms/smooth.cc
Normal file
@@ -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;
|
||||
}
|
||||
106
Doc/Tutorial/04-stl_algorithms/smooth_algo.hh
Normal file
@@ -0,0 +1,106 @@
|
||||
#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
|
||||
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()(typename Mesh::Vertex& _v)
|
||||
{
|
||||
typename Mesh::VertexHandle vh( mesh_.handle(_v) );
|
||||
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; ++vv_it)
|
||||
{
|
||||
mesh_.property(cog_, vh) += mesh_.point( vv_it );
|
||||
++valence;
|
||||
}
|
||||
|
||||
mesh_.property(cog_, mesh_.handle(_v) ) /= valence;
|
||||
}
|
||||
|
||||
private:
|
||||
Mesh& mesh_;
|
||||
Property_cog& cog_;
|
||||
};
|
||||
|
||||
|
||||
class SetCOG
|
||||
{
|
||||
public:
|
||||
SetCOG(Mesh& _mesh, Property_cog& _cog)
|
||||
: mesh_(_mesh), cog_(_cog)
|
||||
{}
|
||||
|
||||
void operator()(typename Mesh::Vertex& _v)
|
||||
{
|
||||
typename Mesh::VertexHandle vh(mesh_.handle(_v));
|
||||
|
||||
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
|
||||
24
Doc/Tutorial/05-std_properties/ACGMakefile
Normal file
@@ -0,0 +1,24 @@
|
||||
#== SYSTEM PART -- DON'T TOUCH ==============================================
|
||||
include $(ACGMAKE)/Config
|
||||
#==============================================================================
|
||||
|
||||
|
||||
# subdirs to process
|
||||
SUBDIRS = $(call find-subdirs)
|
||||
|
||||
# programms (files containing main(), w/o suffix)
|
||||
EXECS = $(call cxx-find-execs)
|
||||
|
||||
# packages (qt, opengl, ...)
|
||||
PACKAGES :=
|
||||
|
||||
# project DSOs
|
||||
PROJ_LIBS := OpenMesh/Core
|
||||
|
||||
# modules to use (cxx, c, moc, uic, yacc) ! order-dependent !
|
||||
MODULES := cxx
|
||||
|
||||
|
||||
#== SYSTEM PART -- DON'T TOUCH ==============================================
|
||||
include $(ACGMAKE)/Rules
|
||||
#==============================================================================
|
||||
71
Doc/Tutorial/05-std_properties/properties.cc
Normal file
@@ -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;
|
||||
}
|
||||
24
Doc/Tutorial/06-attributes/ACGMakefile
Normal file
@@ -0,0 +1,24 @@
|
||||
#== SYSTEM PART -- DON'T TOUCH ==============================================
|
||||
include $(ACGMAKE)/Config
|
||||
#==============================================================================
|
||||
|
||||
|
||||
# subdirs to process
|
||||
SUBDIRS = $(call find-subdirs)
|
||||
|
||||
# programms (files containing main(), w/o suffix)
|
||||
EXECS = $(call cxx-find-execs)
|
||||
|
||||
# packages (qt, opengl, ...)
|
||||
PACKAGES :=
|
||||
|
||||
# project DSOs
|
||||
PROJ_LIBS := OpenMesh/Core
|
||||
|
||||
# modules to use (cxx, c, moc, uic, yacc) ! order-dependent !
|
||||
MODULES := cxx
|
||||
|
||||
|
||||
#== SYSTEM PART -- DON'T TOUCH ==============================================
|
||||
include $(ACGMAKE)/Rules
|
||||
#==============================================================================
|
||||
94
Doc/Tutorial/06-attributes/attributes.cc
Normal file
@@ -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;
|
||||
}
|
||||
24
Doc/Tutorial/07-traits/ACGMakefile
Normal file
@@ -0,0 +1,24 @@
|
||||
#== SYSTEM PART -- DON'T TOUCH ==============================================
|
||||
include $(ACGMAKE)/Config
|
||||
#==============================================================================
|
||||
|
||||
|
||||
# subdirs to process
|
||||
SUBDIRS = $(call find-subdirs)
|
||||
|
||||
# programms (files containing main(), w/o suffix)
|
||||
EXECS = $(call cxx-find-execs)
|
||||
|
||||
# packages (qt, opengl, ...)
|
||||
PACKAGES :=
|
||||
|
||||
# project DSOs
|
||||
PROJ_LIBS := OpenMesh/Core
|
||||
|
||||
# modules to use (cxx, c, moc, uic, yacc) ! order-dependent !
|
||||
MODULES := cxx
|
||||
|
||||
|
||||
#== SYSTEM PART -- DON'T TOUCH ==============================================
|
||||
include $(ACGMAKE)/Rules
|
||||
#==============================================================================
|
||||
132
Doc/Tutorial/07-traits/smooth.cc
Normal file
@@ -0,0 +1,132 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
// -------------------- OpenMesh
|
||||
#include <OpenMesh/Core/IO/MeshIO.hh>
|
||||
#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
|
||||
|
||||
|
||||
#ifndef DOXY_IGNORE_THIS
|
||||
|
||||
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; }
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
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(Mesh::Vertex, total);
|
||||
SIZEOF(Mesh::Halfedge, total);
|
||||
SIZEOF(Mesh::Edge, total);
|
||||
SIZEOF(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.handle()); vv_it; ++vv_it)
|
||||
{
|
||||
cog += mesh.point( vv_it.handle() );
|
||||
++valence;
|
||||
}
|
||||
|
||||
v_it->set_cog(cog / valence);
|
||||
}
|
||||
|
||||
for (v_it=mesh.vertices_begin(); v_it!=v_end; ++v_it)
|
||||
if (!mesh.is_boundary(v_it.handle()))
|
||||
mesh.set_point( v_it.handle(), 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;
|
||||
}
|
||||
|
||||
24
Doc/Tutorial/08-io_options/ACGMakefile
Normal file
@@ -0,0 +1,24 @@
|
||||
#== SYSTEM PART -- DON'T TOUCH ==============================================
|
||||
include $(ACGMAKE)/Config
|
||||
#==============================================================================
|
||||
|
||||
|
||||
# subdirs to process
|
||||
SUBDIRS = $(call find-subdirs)
|
||||
|
||||
# programms (files containing main(), w/o suffix)
|
||||
EXECS = $(call cxx-find-execs)
|
||||
|
||||
# packages (qt, opengl, ...)
|
||||
PACKAGES :=
|
||||
|
||||
# project DSOs
|
||||
PROJ_LIBS := OpenMesh/Core
|
||||
|
||||
# modules to use (cxx, c, moc, uic, yacc) ! order-dependent !
|
||||
MODULES := cxx
|
||||
|
||||
|
||||
#== SYSTEM PART -- DON'T TOUCH ==============================================
|
||||
include $(ACGMAKE)/Rules
|
||||
#==============================================================================
|
||||
297
Doc/Tutorial/08-io_options/io_options.cc
Normal file
@@ -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
|
||||
// ============================================================================
|
||||
24
Doc/Tutorial/09-persistence/ACGMakefile
Normal file
@@ -0,0 +1,24 @@
|
||||
#== SYSTEM PART -- DON'T TOUCH ==============================================
|
||||
include $(ACGMAKE)/Config
|
||||
#==============================================================================
|
||||
|
||||
|
||||
# subdirs to process
|
||||
SUBDIRS = $(call find-subdirs)
|
||||
|
||||
# programms (files containing main(), w/o suffix)
|
||||
EXECS = $(call cxx-find-execs)
|
||||
|
||||
# packages (qt, opengl, ...)
|
||||
PACKAGES :=
|
||||
|
||||
# project DSOs
|
||||
PROJ_LIBS := OpenMesh/Core
|
||||
|
||||
# modules to use (cxx, c, moc, uic, yacc) ! order-dependent !
|
||||
MODULES := cxx
|
||||
|
||||
|
||||
#== SYSTEM PART -- DON'T TOUCH ==============================================
|
||||
include $(ACGMAKE)/Rules
|
||||
#==============================================================================
|
||||
123
Doc/Tutorial/09-persistence/fill_props.hh
Normal file
@@ -0,0 +1,123 @@
|
||||
#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)
|
||||
{
|
||||
float v;
|
||||
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)
|
||||
{
|
||||
v = a[it.handle().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 )
|
||||
{
|
||||
size_t n;
|
||||
bool v;
|
||||
for( typename Mesh::EdgeIter it=_m.edges_begin();
|
||||
it != _m.edges_end(); ++it)
|
||||
{
|
||||
n = it.handle().idx();
|
||||
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)
|
||||
{
|
||||
int n;
|
||||
for( typename Mesh::FaceIter it=_m.faces_begin();
|
||||
it != _m.faces_end(); ++it)
|
||||
{
|
||||
n = it.handle().idx();
|
||||
_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)
|
||||
{
|
||||
int n;
|
||||
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)
|
||||
{
|
||||
n = it.handle().idx();
|
||||
|
||||
v = it.handle().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)
|
||||
{
|
||||
size_t idx;
|
||||
for( typename Mesh::FaceIter it=_m.faces_begin(); it != _m.faces_end(); ++it)
|
||||
{
|
||||
idx = it.handle().idx();
|
||||
if ( _check && _m.property( _ph )[int2roman(idx+1)] != idx )
|
||||
return false;
|
||||
else
|
||||
_m.property( _ph )[int2roman(idx+1)] = idx;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
70
Doc/Tutorial/09-persistence/generate_cube.hh
Normal file
@@ -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
|
||||
45
Doc/Tutorial/09-persistence/int2roman.cc
Normal file
@@ -0,0 +1,45 @@
|
||||
#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);
|
||||
|
||||
roman[ 0 ] = '\0';
|
||||
|
||||
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;
|
||||
}
|
||||
8
Doc/Tutorial/09-persistence/int2roman.hh
Normal file
@@ -0,0 +1,8 @@
|
||||
#ifndef INT2ROMAN_HH
|
||||
#define INT2ROMAN_HH
|
||||
|
||||
#include <string>
|
||||
|
||||
std::string int2roman( size_t decimal, size_t length=30 );
|
||||
|
||||
#endif
|
||||
347
Doc/Tutorial/09-persistence/persistence.cc
Normal file
@@ -0,0 +1,347 @@
|
||||
#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 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::iterator it = _v.begin();
|
||||
std::string key;
|
||||
size_t 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
|
||||
// ============================================================================
|
||||
20
Doc/Tutorial/09-persistence/stats.hh
Normal 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
|
||||
17
Doc/Tutorial/ACGMakefile
Normal file
@@ -0,0 +1,17 @@
|
||||
#== SYSTEM PART -- DON'T TOUCH ==============================================
|
||||
include $(ACGMAKE)/Config
|
||||
#==============================================================================
|
||||
|
||||
|
||||
SUBDIRS = $(call find-subdirs)
|
||||
|
||||
PACKAGES :=
|
||||
|
||||
PROJ_LIBS :=
|
||||
|
||||
MODULES := cxx
|
||||
|
||||
|
||||
#== SYSTEM PART -- DON'T TOUCH ==============================================
|
||||
include $(ACGMAKE)/Rules
|
||||
#==============================================================================
|
||||
89
Doc/decimater.docu
Normal file
@@ -0,0 +1,89 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/** \page decimater_docu Mesh Decimation Framework
|
||||
|
||||
The mesh decimation framework has 3 building blocks.
|
||||
|
||||
-# \ref DecimaterAlg
|
||||
-# \ref DecimaterMod
|
||||
-# \ref DecimaterHnd
|
||||
|
||||
\section DecimaterAlg The decimation algorithm
|
||||
|
||||
The decimater (OpenMesh::Decimater::DecimaterT) provides the
|
||||
decimation algorithm, while the decimation modules provide the
|
||||
computational part. The modules compute a priority value due to some
|
||||
error metric, which is used by the decimater to feed a priority
|
||||
queue. The lower the error value, the more a potential collapse
|
||||
moves to the front of the queue. The one with the lowest error will
|
||||
always be the candidate for the next collapse.
|
||||
|
||||
This implementation does a halfedge collapse, hence simply
|
||||
collapsing one vertex into another connected by a halfedge.
|
||||
|
||||
\note The decimater ignores all 'locked' and 'deleted' vertices (see
|
||||
OpenMesh::Attributes::StatusBits)
|
||||
|
||||
\attention The decimater sets temporarily the status bit 'tagged' and
|
||||
clears it after usage regardless of a previous state.
|
||||
|
||||
\section DecimaterMod Decimating Modules
|
||||
|
||||
The vertex to be removed is determined by a decimation module, which has
|
||||
to be derived from OpenMesh::Decimater::ModBaseT. The framework
|
||||
supplies already a few decimation modules. But it's very easy to build
|
||||
your own (\ref OpenMesh::Decimater::ModBaseT). The most important
|
||||
function of a decimation module is
|
||||
OpenMesh::Decimater::ModBaseT::collapse_priority(). It takes an
|
||||
OpenMesh::Decimater::CollapseInfoT describing a potential halfedge
|
||||
collapse, and returns a value due to some error metric. The error
|
||||
value is used by the decimater to feed a priority queue. Collapses
|
||||
with low error will be executed first, and those with large error
|
||||
later. Of course a module computing the error quadric is provided
|
||||
(OpenMesh::Decimater::ModQuadricT).
|
||||
|
||||
This framework allows to use more than one decimation module with
|
||||
some restrictions. Since the error value is always normalized and
|
||||
sometimes very difficult to compare to other metrics, the framework
|
||||
allows only one non-binary module, i.e. a module computing a float
|
||||
value. Every further module must be a binary module,
|
||||
i.e. collapse_prioerity() returns
|
||||
OpenMesh::Decimater::ModBaseT::LEGAL_COLLAPSE or
|
||||
OpenMesh::Decimater::ModBaseT::ILLEGAL_COLLAPSE. In the algorithm
|
||||
the binary modules are evaluated first. If the evaluated collapse
|
||||
passes the test, then the non-binary module contributes to the
|
||||
decision step.
|
||||
|
||||
In some cases the module does not contribute anything to the
|
||||
decision engine of the decimater, but instead, e.g. simply collects
|
||||
information, while the decimater does it's work. For instance the
|
||||
module OpenMesh::Decimater::ModProgMeshT collects information from
|
||||
all collapses that have been done. This information can be used to
|
||||
generate progressive meshes as described in "Progressive meshes",
|
||||
Hoppe, 1996.
|
||||
|
||||
Provided decimation modules:
|
||||
|
||||
- OpenMesh::Decimater::ModQuadricT
|
||||
- OpenMesh::Decimater::ModRoundnessT
|
||||
- OpenMesh::Decimater::ModNormalFlippingT
|
||||
- OpenMesh::Decimater::ModIndependentSetsT
|
||||
- OpenMesh::Decimater::ModProgMeshT
|
||||
|
||||
\section DecimaterHnd Module Handles
|
||||
|
||||
Similar to properties the modules are represented outside the
|
||||
decimater by module handles. Before using the decimater a
|
||||
non-binary module must be registrated with the decimater.
|
||||
|
||||
See \ref DecimaterExa.
|
||||
|
||||
\section DecimaterExa Basic Setup
|
||||
|
||||
The following small example show the basic steps to setup up a
|
||||
decimater:
|
||||
|
||||
\include decimater.cc
|
||||
|
||||
*/
|
||||
|
||||
509
Doc/history.docu
Normal file
@@ -0,0 +1,509 @@
|
||||
/** \page history Version history
|
||||
|
||||
\htmlonly
|
||||
|
||||
<table border=1 cellpadding=4 cellspacing=2>
|
||||
|
||||
<!-- --------------------------------------------------------------------- -->
|
||||
|
||||
<tr valign=top><td><b>2.0</b> (2009/01/28)</td><td>
|
||||
<ul>
|
||||
<li>Reader / writer have been updated</li>
|
||||
<li>Some general bugfixes</li>
|
||||
<li>Improved Documentation</li>
|
||||
<li>Dropped support for acgmake which has been entirely replaced by qmake</li>
|
||||
</ul>
|
||||
</tr>
|
||||
|
||||
<!-- --------------------------------------------------------------------- -->
|
||||
|
||||
<tr valign=top><td><b>1.9.7</b> (2008/10/13)</td><td>
|
||||
<ul>
|
||||
<li>Ported applications to qt4</li>
|
||||
<li>Bugfixes in Decimater</li>
|
||||
<li>Improved Documentation</li>
|
||||
<li>Dropped support for gcc 3.x compilers (This does not mean that it does not work anymore)</li>
|
||||
<li>Dropped support for Versions of Visual Studio older than 2008</li>
|
||||
</ul>
|
||||
</tr>
|
||||
|
||||
<!-- --------------------------------------------------------------------- -->
|
||||
|
||||
<tr valign=top><td><b>1.1.0</b> (2007/02/26)</td><td>
|
||||
<ul>
|
||||
<li>Fixed a VS 2005 compilation issue regarding the Sqrt3 subdivision class.</li>
|
||||
<li>Fixed GCC-4.1 compilation problems.</li>
|
||||
<li>The STL writer routine now correctly closes the <tt>"solid"</tt> block with <tt>"endsolid"</tt>.</li>
|
||||
<li>The API of the vector class has been changed slightly due to problems with some versions of GCC:<br/>
|
||||
The cast operator to the scalar type has been removed and replaced by
|
||||
the function <tt>data()</tt>. Hence, existing code like
|
||||
<blockquote>
|
||||
<tt>Vec3f vertex;</tt><br/>
|
||||
<tt>...</tt><br/>
|
||||
<tt>glVertex3fv( vertex );</tt>
|
||||
</blockquote>
|
||||
has to be changed to
|
||||
<blockquote>
|
||||
<tt>Vec3f vertex;</tt><br/>
|
||||
<tt>...</tt><br/>
|
||||
<tt>glVertex3fv( vertex.data() );</tt>
|
||||
</blockquote>
|
||||
</li>
|
||||
</ul>
|
||||
</tr>
|
||||
|
||||
<!-- --------------------------------------------------------------------- -->
|
||||
|
||||
<tr valign=top><td><b>1.0.0</b> (2005/09/20)</td><td>
|
||||
<ul>
|
||||
<li>Mainly fixed the bugs collected in beta4.</li>
|
||||
<li>Slightly changed module handling in the Decimater.</li>
|
||||
<li>Removed some parts to keep the project maintainable.</li>
|
||||
<li>Fixed MacOS compilation problems.</li>
|
||||
<li>Compatibility for latest gcc4 compilers.</li>
|
||||
</ul>
|
||||
</tr>
|
||||
|
||||
<!-- --------------------------------------------------------------------- -->
|
||||
|
||||
<tr valign=top><td><b>1.0.0-beta4</b> (2004/01/20)</td><td>
|
||||
<ul>
|
||||
<li>Bugs fixed: 1.0.0-beta3:001</li>
|
||||
<li>Documentation of module Core completed.</li>
|
||||
<li>Documentation of module Tools::Decimater and
|
||||
Tools::Subdivider completed.</li>
|
||||
<li>Revised class structure for uniform subdivision.</li>
|
||||
<li>Revised rule handling for composite adaptive subdivision.</li>
|
||||
</ul>
|
||||
</tr>
|
||||
|
||||
<!-- --------------------------------------------------------------------- -->
|
||||
|
||||
<tr valign=top><td><b>1.0.0-beta3</b> (2003/12/04)</td><td>
|
||||
The beta3 fixes only the known bugs in beta2.
|
||||
<ul>
|
||||
<li>Bugs fixed: 1.0.0-beta2:{001, 002, 003, 004}</li>
|
||||
<li><b>Known Bugs</b>:
|
||||
<ul>
|
||||
<li>001: OFFReader: Option bit not cleared before analyzing .off header.
|
||||
<br>Symptoms: If a previously read .off file had normals/texcoords,
|
||||
a second read of another file w/o normals or texcoords, will return
|
||||
with option bits normals/texcoords enabled.
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</tr>
|
||||
|
||||
<!-- --------------------------------------------------------------------- -->
|
||||
|
||||
<tr valign=top><td><b>1.0.0-beta2</b> (2003/11/05)</td><td>
|
||||
|
||||
<ul>
|
||||
|
||||
<li>Change of directory structure
|
||||
<pre>
|
||||
+- %OpenMesh/
|
||||
+- Core/ # previously %OpenMesh
|
||||
+- Tools/ # previously OpenMeshTools
|
||||
+- Apps/ # previously OpenMeshApps
|
||||
+- Win/ # contains all solutions files and projects for MS VC++
|
||||
+- Doc/ # contains all documentation
|
||||
</pre>
|
||||
Note! The supplied script \c %OpenMesh/migrate.sh can be used to
|
||||
adjust include paths and ACGMakefiles. (It's not guarantied the
|
||||
script handles every case, but so far it did not missed a file to
|
||||
adjust.)
|
||||
</li>
|
||||
|
||||
<li><b>Porting issues</b>: Due to a number of major changes in the
|
||||
structure of %OpenMesh a few incompatibilities have been
|
||||
introduced. Have look in <b>\c %OpenMesh/porting.txt </b> for hints how to
|
||||
treat your source when updating from 0.11.x to
|
||||
1.0.0.<br>Hint! The supplied script \c %OpenMesh/migrate.sh does a
|
||||
few of the necessary modifications.
|
||||
</li>
|
||||
|
||||
<li><b>The list kernel has been removed</b>
|
||||
</li>
|
||||
|
||||
<li>Improved IO support:
|
||||
<ul>
|
||||
<li>Read/write ascii and binary STL </li>
|
||||
<li>Read/write ascii and binary OFF </li>
|
||||
<li>Support for vertex normals and vertex texcoords in OFF and OBJ</li>
|
||||
<li>Support importing diffuse material into face color property from
|
||||
OBJ files.
|
||||
</li>
|
||||
<li>Properietary binary format OM, supporting read/write of custom properties
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li>Improved coordinate class OpenMesh::VectorT:
|
||||
<ul>
|
||||
<li> <tt>VectorT::vectorize(Scalar)</tt> is no longer static, now
|
||||
it changes the vector. Use it e.g. to clear vector values.
|
||||
</li>
|
||||
<li> Casts between two vector classes of the same dimension are now
|
||||
explicit. This avoids unwanted and expensive casts.
|
||||
</li>
|
||||
<li> Optimized performance by manual loop-unrolling. These optimizations
|
||||
are partial specializations for vectors of dimension 2, 3 and 4.
|
||||
Since Microsoft's VC++ still does not support partial specialization
|
||||
and also provides rather poor loop-unrolling, users of this compiler
|
||||
are stuck to lower performance.
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li>OpenSG Support:
|
||||
<ul>
|
||||
<li>New kernel type \c class TriMesh_OSGArrayKernelT<>.
|
||||
<ul>
|
||||
<li>Uses OpenSG geometry types!</li>
|
||||
<li>PolyMesh not supported, yet!</li>
|
||||
</ul>
|
||||
<li>Use \c OpenMesh::Kernel_OSG::bind<> to link a mesh obj with an
|
||||
\c osg::Geometry and vice versa.<br>Please note that both objects
|
||||
share the same data!
|
||||
<ul>
|
||||
<li>Binding a mesh to an \c osg::Geometry changes the content
|
||||
of the \c osg::Geometry!
|
||||
<li>Triangulates non-triangular faces!</li>
|
||||
<li>Multi-indexed geometry not supported!</li>
|
||||
<li>Transfer of vertex normals</li>
|
||||
<li>Limited capability to transfer colors:
|
||||
So far, only \c osg::Color3f <-> \c OpenMesh::Vec3ub
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li>Microsoft VC++ 7.0 projects files
|
||||
<ul>
|
||||
<li>Tutorial solution file
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li> New tools/applications:
|
||||
<ul>
|
||||
<li>\c Tools/VDPM (View Dependent Progressive Mesh Library)
|
||||
<ul>
|
||||
<li>\c Apps/VDProgMesh/mkbalancedpm - Create a balanced
|
||||
progressive mesh.
|
||||
</li>
|
||||
<li>\c Apps/VDProgMesh/Analyzer - Create a view dependent
|
||||
progressive mesh file.
|
||||
</li>
|
||||
<li>\c Apps/VDProgMesh/Synthesizer - A viewer for the VDPM file.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>Apps/mconvert</li>
|
||||
<li>Apps/IvViewer - added support for Coin</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li><b>Known Bugs</b>:
|
||||
The following bugs are related to the TriMesh_OSGArrayKernelT<>:
|
||||
<ul>
|
||||
<li>001: Cannot request/release the default attribute
|
||||
<tt>halfedge_status</tt>.
|
||||
</li>
|
||||
<li>002: Cannot release the default attribute <tt>vertex_texcoords</tt>
|
||||
</li>
|
||||
<li>003: Assignment operator = () does not work properly.</li>
|
||||
<li>004: No copy-constructor available!</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</td></tr>
|
||||
|
||||
|
||||
<!-- --------------------------------------------------------------------- -->
|
||||
|
||||
|
||||
<tr valign=top><td><b>0.11.1</b> (2002/12/02)</td><td>
|
||||
<ul>
|
||||
|
||||
<li>Bugs fixed: 0.11.0:{001, 002, 003, 004, 006}<br><br>
|
||||
006: Use acgmake version 1.1.1.
|
||||
</li>
|
||||
|
||||
<li>Preprocessor warnings of gcc >= 3 fixed.
|
||||
</li>
|
||||
|
||||
<li>Added some more dynamic ways to append properties to items:
|
||||
OpenMesh::Any and OpenMesh::PropertyT .
|
||||
</li>
|
||||
|
||||
<li>VectorT: standard operator less added, Vec4f is now
|
||||
16-bit aligned using gcc compiler (for later SIMD usage).
|
||||
</li>
|
||||
|
||||
<li>Use OM_STATIC_BUILD=1 when creating a static library.
|
||||
The static version of the library needs to included IOInstances.hh,
|
||||
which is done in that case.
|
||||
When compiling with MS VC7, the define is set automatically, as
|
||||
the DLL-Version is not supported yet.
|
||||
acgmake (Version >= 1.1) set the define automatically when
|
||||
using the flag for static compiling.
|
||||
</li>
|
||||
|
||||
<li>The read_mesh() methods now clears the mesh before reading a new one.
|
||||
</li>
|
||||
|
||||
<li>Added can_read() and can_write() methods to the IOManager.
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
</td></tr>
|
||||
|
||||
|
||||
<!-- --------------------------------------------------------------------- -->
|
||||
<tr valign=top><td><b>0.11.0</b> (2002/09/07)</td><td>
|
||||
|
||||
<ul>
|
||||
|
||||
<li>Bugs fixed: 0.10.2:{001, 002, 003, 004, 005}
|
||||
</li>
|
||||
|
||||
<li>Added MS VC++ 7.0 project files for the tutorial programms.
|
||||
(Have a look in <OpenMesh>/Win32/MSVC/)
|
||||
</li>
|
||||
|
||||
<li>New Input/Output management, see \ref mesh_io. The new interface
|
||||
is as backwards-compatible as possible. Only the read_[off,obj]
|
||||
and write_[off,obj] methods do no longer exist. You should now
|
||||
include OpenMesh/IO/MeshIO.hh instead of MeshReader.hh and
|
||||
MeshWriter.hh. The old include files may be removed in a future
|
||||
release.
|
||||
</li>
|
||||
|
||||
<li>Added: Generic algorithms may now define their own traits, these traits can
|
||||
be merged with other user-defined traits by the OM_Merge_Traits macro.
|
||||
See tutorial \ref tutorial_06.
|
||||
</li>
|
||||
|
||||
<li>Added generic handle <-> item conversions, see
|
||||
<ul>
|
||||
<li> OpenMesh::Concepts::KernelT::handle() and
|
||||
<li> OpenMesh::PolyMeshT::deref().
|
||||
</ul>
|
||||
The kernel methods vertex_handle(), halfedge_handle(), edge_handle(),
|
||||
face_handle() should no longer be used, but are still existent for
|
||||
compatibility reasons. You can hide them by uncommenting the define
|
||||
OM_HIDE_DEPRECATED in OpenMesh/System/config.h.
|
||||
</li>
|
||||
|
||||
<li>Internal methods, like Vertex::halfedge_handle() or Vertex::point() are
|
||||
now hidden, since the respective kernel methods (like
|
||||
MeshKernel::halfedge_handle(VertexHandle) or
|
||||
MeshKernel::point(VertexHandle)) should be used instead.
|
||||
</li>
|
||||
|
||||
<li>Added convenience methods for the mesh kernels:
|
||||
<ul>
|
||||
<li>OpenMesh::Concepts::KernelT::n_halfedges()
|
||||
<li>OpenMesh::Concepts::KernelT::halfedges_empty()
|
||||
<li>OpenMesh::Concepts::KernelT::halfedge_handle(unsigned int _i)
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li><b>Known Bugs</b>:
|
||||
<ul>
|
||||
<li>001: Ambigous auto_ptr<> cast in ExporterT.hh.</li>
|
||||
<li>002: BaseImporter and BaseExporter have no virtual destructor.</li>
|
||||
<li>003: Reader does not work correctly, when reading from a istream.</li>
|
||||
<li>004: cross(VectorT, VectorT) returns Scalar instead of VectorT.</li>
|
||||
<li>005: PolyMeshT::calc_face_normal() may give wrong results if the
|
||||
first 3 points of the polygon are colinear or concave.</li>
|
||||
<li>006: Reading/writing (MeshIO) of files does not work when using acgmake
|
||||
with SuSE 8.1.</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</td></tr>
|
||||
|
||||
<!-- --------------------------------------------------------------------- -->
|
||||
|
||||
<tr valign=top><td><b>0.10.2</b> (2002/06/25)</td><td>
|
||||
<ul>
|
||||
<li>Bugs fixed: 0.10.1:{001, 002}
|
||||
</li>
|
||||
|
||||
<li>The edge collapse checking method TriMeshT::is_collapse_ok() is now more
|
||||
restrictive. It prohibits cases that could be handled by the
|
||||
halfedge data structure, but would probably not be regarded as a
|
||||
legal mesh.
|
||||
</li>
|
||||
|
||||
<li>The vertex split operation creates up to 3 new edges and 2 new
|
||||
faces. Up to now it was possible to pass handles to edges/faces
|
||||
that should be used instead of creating new ones. This option has
|
||||
been removed in order to get a cleaner interface.
|
||||
</li>
|
||||
|
||||
<li>The MeshCheckerT has been changed slightly: it omits deleted elements, so
|
||||
one does not have to perform a garbage collection before checking the mesh.
|
||||
It also checks for the halfedges building cycles around faces or
|
||||
boundaries.
|
||||
</li>
|
||||
|
||||
<li><b>Known Bugs</b>:
|
||||
<ul>
|
||||
<li>001: OpenMesh::PolyMeshT::operator=() does not return \c *this.
|
||||
<li>002: OpenMesh::DefaultAttributer added unnecessary 20 bits to the
|
||||
elementary mesh types.
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</td></tr>
|
||||
|
||||
<!-- --------------------------------------------------------------------- -->
|
||||
|
||||
<tr valign=top><td><b>0.10.1</b> (2002/04/22)</td><td>
|
||||
<ul>
|
||||
<li>Bugs fixed: 0.10.0:{001, 002, 003, 004, 005}
|
||||
</li>
|
||||
|
||||
<li>Added: Predefined attribute \c TexCoord.
|
||||
</li>
|
||||
|
||||
<li>Added: Support for MS VC++ 6.0 IDE with Intel Compiler.
|
||||
</li>
|
||||
|
||||
<li>Added: Tutorial 6 on generic algorithms.
|
||||
</li>
|
||||
|
||||
<li>SharedCoordArrayKernelT is now derived from ArrayKernelT.
|
||||
</li>
|
||||
|
||||
<li>Added: Assignment operator operator=() for PolyMeshT and TriMeshT.
|
||||
</li>
|
||||
|
||||
<li>Added: Method TriMeshT::is_collapse_ok(), checking topological conditions
|
||||
for a given halfedge collapse.
|
||||
</li>
|
||||
|
||||
<li><b>Known Bugs</b>:
|
||||
<ul>
|
||||
<li>001: PolyMeshT::delete_face(): Outgoing halfedge handle of
|
||||
a vertex can incorrectly be invalidated. Influences
|
||||
vertex circulators, find_halfedge() and therefore
|
||||
add_face().<br>
|
||||
Workaround: Replace <tt>v0</tt> by <tt>v1</tt> in line 585 of
|
||||
PolyMeshT.cc
|
||||
</li>
|
||||
<li>002: TriMeshT::collapse(): Some special cases are incorrectly
|
||||
handled when collapsing boundary halfedges. The same
|
||||
cases are also incorrect for the inverse operation
|
||||
TriMeshT::vertex_split() operation.
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</td></tr>
|
||||
|
||||
<!-- --------------------------------------------------------------------- -->
|
||||
|
||||
<tr valign=top><td><b>0.10.0</b> (2002/03/19)</td><td>
|
||||
<ul>
|
||||
<li>Interface for specifying the traits classes simplified (see
|
||||
Traits.hh).
|
||||
</li>
|
||||
|
||||
<li>Changed attribute handling; the attributer class (the class that
|
||||
adds and registers attributes to mesh items) can be provided by
|
||||
the user.
|
||||
</li>
|
||||
|
||||
<li>Removed MyMesh::Face::n_vertices() and
|
||||
MyMesh::Face::set_n_vertices().
|
||||
</li>
|
||||
|
||||
<li>MeshWriter::write_* changed accordingly.
|
||||
</li>
|
||||
|
||||
<li>Bug fix: PolyMeshT::delete_[face,edge,vertex] now work correctly.
|
||||
</li>
|
||||
|
||||
<li>Removed cyclic dependency between items and kernel, because MS
|
||||
VC++ cannot handle the resulting template forward declaration
|
||||
:-(. Therefore the <tt>Base::Refs</tt> class, given for the traits
|
||||
classes, no longer provides the types \c Vertex, \c Halfedge, \c
|
||||
Edge, and \c Face. It now only provides all handle types, the
|
||||
point and the scalar type.
|
||||
</li>
|
||||
|
||||
<li>Finally: MS VC++ 7.0 supported.
|
||||
</li>
|
||||
|
||||
<li><b>Known Bugs</b>:
|
||||
<ul>
|
||||
<li>001: TriMeshT.cc::vertex_split(): call to undefined
|
||||
method Face::set_n_vertices().<br>
|
||||
Workaround: Comment out the two occurences of the call.
|
||||
</li>
|
||||
<li>002: Missing <tt>\#include
|
||||
<OpenMesh/Mesh/Kernels/ListKernel/ListHandles.hh></tt>
|
||||
in OpenMesh/Mesh/Types/PolyMesh_ListKernelT.hh.
|
||||
</li>
|
||||
<li>003: Special case in TriMeshT::edge_collapse(): when collapsing a
|
||||
boundary vertex into an interior one, the outgoing halfedge of
|
||||
the resulting vertex my not be a boundary one.
|
||||
</li>
|
||||
<li>004: PolyMeshT::delete_edge did not pass its argument
|
||||
_delete_isolated_vertices to PolyMeshT::delete_face.
|
||||
</li>
|
||||
<li>005: PolyMeshT::assign() was not linked because of an \#if error.
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</td></tr>
|
||||
|
||||
<!-- --------------------------------------------------------------------- -->
|
||||
|
||||
<tr valign=top><td><b>0.9.2</b> (-) </td><td>
|
||||
<ul>
|
||||
<li>PolyMeshT::add_face() now detects more topological errors.
|
||||
</li>
|
||||
|
||||
<li>Added mesh kernel methods: remove_last_[vertex,edge,face]().
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</td></tr>
|
||||
|
||||
<!-- --------------------------------------------------------------------- -->
|
||||
|
||||
<tr valign=top><td><b>0.9.1</b> (2002/02/07)</td><td>
|
||||
<ul>
|
||||
<li>Changed the main namespace from ACG to OpenMesh.
|
||||
</li>
|
||||
|
||||
<li>Added invalid handle constants, e.g. PolyMeshT::InvalidVertexHandle.
|
||||
</li>
|
||||
|
||||
<li>Mesh provides circulators: PolyMeshT::vv_iter(VertexHandle).
|
||||
</li>
|
||||
</ul>
|
||||
</td></tr>
|
||||
|
||||
<!-- --------------------------------------------------------------------- -->
|
||||
|
||||
<tr valign=top><td><b> 0.9</b> (2002/01/25)</td><td>
|
||||
<ul>
|
||||
<li>initial release</li>
|
||||
</ul>
|
||||
</td></tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
\endhtmlonly
|
||||
|
||||
**/
|
||||
16
Doc/html/acg_footer.html
Normal file
@@ -0,0 +1,16 @@
|
||||
<hr>
|
||||
<address>
|
||||
<small>
|
||||
<a href="http://www.rwth-graphics.de" style="text-decoration:none;">
|
||||
<img src="acg_icon.gif" alt="acg pic" align="middle" border=0>
|
||||
</a>
|
||||
Project <b>$projectname</b>,
|
||||
© Computer Graphics Group, RWTH Aachen.
|
||||
Documentation generated using
|
||||
<a class="el" href="http://www.doxygen.org/index.html">
|
||||
<b>doxygen</b>
|
||||
</a>.
|
||||
</small>
|
||||
</address>
|
||||
</body>
|
||||
</html>
|
||||
7
Doc/html/acg_header.html
Normal file
@@ -0,0 +1,7 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>$title</title>
|
||||
<link href="acg_style.css" rel="stylesheet" text="text/css">
|
||||
<link href="acg_tabs.css" rel="stylesheet" type="text/css">
|
||||
</head>
|
||||
<body bgcolor="#003010">
|
||||
BIN
Doc/html/acg_icon.gif
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
367
Doc/html/acg_style.css
Normal file
@@ -0,0 +1,367 @@
|
||||
BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV {
|
||||
font-family: Geneva, Arial, Helvetica, sans-serif;
|
||||
}
|
||||
BODY,TD {
|
||||
font-size: 90%;
|
||||
}
|
||||
H1 {
|
||||
text-align: center;
|
||||
font-size: 160%;
|
||||
}
|
||||
H2 {
|
||||
font-size: 120%;
|
||||
}
|
||||
H3 {
|
||||
font-size: 100%;
|
||||
}
|
||||
CAPTION { font-weight: bold }
|
||||
DIV.qindex {
|
||||
width: 100%;
|
||||
background-color: #375b3f;
|
||||
border: 1px solid #84b0c7;
|
||||
text-align: center;
|
||||
margin: 2px;
|
||||
padding: 2px;
|
||||
line-height: 140%;
|
||||
}
|
||||
DIV.nav {
|
||||
width: 100%;
|
||||
background-color: #375b3f;
|
||||
border: 1px solid #84b0c7;
|
||||
text-align: center;
|
||||
margin: 2px;
|
||||
padding: 2px;
|
||||
line-height: 140%;
|
||||
}
|
||||
DIV.navtab {
|
||||
background-color: #375b3f;
|
||||
border: 1px solid #84b0c7;
|
||||
text-align: center;
|
||||
margin: 2px;
|
||||
margin-right: 15px;
|
||||
padding: 2px;
|
||||
}
|
||||
TD.navtab {
|
||||
font-size: 70%;
|
||||
}
|
||||
A.qindex {
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
color: #f07030;
|
||||
}
|
||||
A.qindex:visited {
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
color: #f07030
|
||||
}
|
||||
A.qindex:hover {
|
||||
text-decoration: none;
|
||||
background-color: #ddddff;
|
||||
}
|
||||
A.qindexHL {
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
background-color: #6666cc;
|
||||
color: #ffffff;
|
||||
border: 1px double #9295C2;
|
||||
}
|
||||
A.qindexHL:hover {
|
||||
text-decoration: none;
|
||||
background-color: #6666cc;
|
||||
color: #ffffff;
|
||||
}
|
||||
A.qindexHL:visited { text-decoration: none; background-color: #6666cc; color: #ffffff }
|
||||
A.el { text-decoration: none; font-weight: bold }
|
||||
A.elRef { font-weight: bold }
|
||||
A.code:link { text-decoration: none; font-weight: normal; color: #0000FF}
|
||||
A.code:visited { text-decoration: none; font-weight: normal; color: #0000FF}
|
||||
A.codeRef:link { font-weight: normal; color: #0000FF}
|
||||
A.codeRef:visited { font-weight: normal; color: #0000FF}
|
||||
A.el:hover { text-decoration: none; color: #e0e0d0}
|
||||
DL.el { margin-left: -1cm }
|
||||
.fragment {
|
||||
font-family: monospace, fixed;
|
||||
font-size: 95%;
|
||||
}
|
||||
PRE.fragment {
|
||||
color: black;
|
||||
border: 1px solid #29442F;
|
||||
background-color: #f5f5f5;
|
||||
margin-top: 4px;
|
||||
margin-bottom: 4px;
|
||||
margin-left: 2px;
|
||||
margin-right: 8px;
|
||||
padding-left: 6px;
|
||||
padding-right: 6px;
|
||||
padding-top: 4px;
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
DIV.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px }
|
||||
|
||||
DIV.groupHeader {
|
||||
margin-left: 16px;
|
||||
margin-top: 12px;
|
||||
margin-bottom: 6px;
|
||||
font-weight: bold;
|
||||
}
|
||||
DIV.groupText { margin-left: 16px; font-style: italic; font-size: 90% }
|
||||
BODY {
|
||||
background: #003010;
|
||||
color: #e0e0d0;
|
||||
margin-right: 20px;
|
||||
margin-left: 20px;
|
||||
}
|
||||
TD.indexkey {
|
||||
background-color: #375b3f;
|
||||
font-weight: bold;
|
||||
padding-right : 10px;
|
||||
padding-top : 2px;
|
||||
padding-left : 10px;
|
||||
padding-bottom : 2px;
|
||||
margin-left : 0px;
|
||||
margin-right : 0px;
|
||||
margin-top : 2px;
|
||||
margin-bottom : 2px;
|
||||
border: 1px solid #29442F;
|
||||
}
|
||||
TD.indexvalue {
|
||||
background-color: #375b3f;
|
||||
font-style: italic;
|
||||
padding-right : 10px;
|
||||
padding-top : 2px;
|
||||
padding-left : 10px;
|
||||
padding-bottom : 2px;
|
||||
margin-left : 0px;
|
||||
margin-right : 0px;
|
||||
margin-top : 2px;
|
||||
margin-bottom : 2px;
|
||||
border: 1px solid #29442F;
|
||||
}
|
||||
TR.memlist {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
P.formulaDsp { text-align: center; }
|
||||
IMG.formulaDsp { }
|
||||
IMG.formulaInl { vertical-align: middle; }
|
||||
/*SPAN.keyword { color: #008000 }
|
||||
SPAN.keywordtype { color: #604020 }
|
||||
SPAN.keywordflow { color: #e08000 }
|
||||
SPAN.comment { color: #800000 }
|
||||
SPAN.preprocessor { color: #806020 }
|
||||
SPAN.stringliteral { color: #002080 }
|
||||
SPAN.charliteral { color: #008080 }*/
|
||||
SPAN.keyword { color: #008000 }
|
||||
SPAN.keywordtype { color: #604020 }
|
||||
SPAN.keywordflow { color: #e08000 }
|
||||
SPAN.comment { color: #800000 }
|
||||
SPAN.preprocessor { color: #806020 }
|
||||
SPAN.stringliteral { color: #002080 }
|
||||
SPAN.charliteral { color: #008080 }
|
||||
|
||||
.mdescLeft {
|
||||
padding: 0px 8px 4px 8px;
|
||||
font-size: 80%;
|
||||
font-style: italic;
|
||||
background-color: #375B3F;
|
||||
border-top: 1px none #E0E0E0;
|
||||
border-right: 1px none #E0E0E0;
|
||||
border-bottom: 1px none #E0E0E0;
|
||||
border-left: 1px none #E0E0E0;
|
||||
margin: 0px;
|
||||
}
|
||||
.mdescRight {
|
||||
padding: 0px 8px 4px 8px;
|
||||
font-size: 80%;
|
||||
font-style: italic;
|
||||
background-color: #375B3F;
|
||||
border-top: 1px none #E0E0E0;
|
||||
border-right: 1px none #E0E0E0;
|
||||
border-bottom: 1px none #E0E0E0;
|
||||
border-left: 1px none #E0E0E0;
|
||||
margin: 0px;
|
||||
}
|
||||
.memItemLeft {
|
||||
padding: 1px 0px 0px 8px;
|
||||
margin: 4px;
|
||||
border-top-width: 1px;
|
||||
border-right-width: 1px;
|
||||
border-bottom-width: 1px;
|
||||
border-left-width: 1px;
|
||||
border-top-color: #E0E0E0;
|
||||
border-right-color: #E0E0E0;
|
||||
border-bottom-color: #E0E0E0;
|
||||
border-left-color: #E0E0E0;
|
||||
border-top-style: solid;
|
||||
border-right-style: none;
|
||||
border-bottom-style: none;
|
||||
border-left-style: none;
|
||||
background-color: #375B3F;
|
||||
font-size: 80%;
|
||||
}
|
||||
.memItemRight {
|
||||
padding: 1px 8px 0px 8px;
|
||||
margin: 4px;
|
||||
border-top-width: 1px;
|
||||
border-right-width: 1px;
|
||||
border-bottom-width: 1px;
|
||||
border-left-width: 1px;
|
||||
border-top-color: #E0E0E0;
|
||||
border-right-color: #E0E0E0;
|
||||
border-bottom-color: #E0E0E0;
|
||||
border-left-color: #E0E0E0;
|
||||
border-top-style: solid;
|
||||
border-right-style: none;
|
||||
border-bottom-style: none;
|
||||
border-left-style: none;
|
||||
background-color: #375B3F;
|
||||
font-size: 80%;
|
||||
}
|
||||
.memTemplItemLeft {
|
||||
padding: 1px 0px 0px 8px;
|
||||
margin: 4px;
|
||||
border-top-width: 1px;
|
||||
border-right-width: 1px;
|
||||
border-bottom-width: 1px;
|
||||
border-left-width: 1px;
|
||||
border-top-color: #E0E0E0;
|
||||
border-right-color: #E0E0E0;
|
||||
border-bottom-color: #E0E0E0;
|
||||
border-left-color: #E0E0E0;
|
||||
border-top-style: none;
|
||||
border-right-style: none;
|
||||
border-bottom-style: none;
|
||||
border-left-style: none;
|
||||
background-color: #375B3F;
|
||||
font-size: 80%;
|
||||
}
|
||||
.memTemplItemRight {
|
||||
padding: 1px 8px 0px 8px;
|
||||
margin: 4px;
|
||||
border-top-width: 1px;
|
||||
border-right-width: 1px;
|
||||
border-bottom-width: 1px;
|
||||
border-left-width: 1px;
|
||||
border-top-color: #E0E0E0;
|
||||
border-right-color: #E0E0E0;
|
||||
border-bottom-color: #E0E0E0;
|
||||
border-left-color: #E0E0E0;
|
||||
border-top-style: none;
|
||||
border-right-style: none;
|
||||
border-bottom-style: none;
|
||||
border-left-style: none;
|
||||
background-color: #375B3F;
|
||||
font-size: 80%;
|
||||
}
|
||||
.memTemplParams {
|
||||
padding: 1px 0px 0px 8px;
|
||||
margin: 4px;
|
||||
border-top-width: 1px;
|
||||
border-right-width: 1px;
|
||||
border-bottom-width: 1px;
|
||||
border-left-width: 1px;
|
||||
border-top-color: #E0E0E0;
|
||||
border-right-color: #E0E0E0;
|
||||
border-bottom-color: #E0E0E0;
|
||||
border-left-color: #E0E0E0;
|
||||
border-top-style: solid;
|
||||
border-right-style: none;
|
||||
border-bottom-style: none;
|
||||
border-left-style: none;
|
||||
color: #606060;
|
||||
background-color: #375B3F;
|
||||
font-size: 80%;
|
||||
}
|
||||
.search { color: #003399;
|
||||
font-weight: bold;
|
||||
}
|
||||
FORM.search {
|
||||
margin-bottom: 0px;
|
||||
margin-top: 0px;
|
||||
}
|
||||
INPUT.search { font-size: 75%;
|
||||
color: #000080;
|
||||
font-weight: normal;
|
||||
background-color: #375b3f;
|
||||
}
|
||||
TD.tiny { font-size: 75%;
|
||||
}
|
||||
a {
|
||||
color: #f07030;
|
||||
}
|
||||
a:visited {
|
||||
color: #f07030;
|
||||
}
|
||||
.dirtab { padding: 4px;
|
||||
border-collapse: collapse;
|
||||
border: 1px solid #84b0c7;
|
||||
}
|
||||
TH.dirtab { background: #375b3f;
|
||||
font-weight: bold;
|
||||
}
|
||||
HR { height: 1px;
|
||||
border: none;
|
||||
border-top: 1px solid #e0e0d0;
|
||||
}
|
||||
|
||||
/* Style for detailed member documentation */
|
||||
.memtemplate {
|
||||
font-size: 80%;
|
||||
color: #e0e0d0;
|
||||
font-weight: normal;
|
||||
}
|
||||
.memnav {
|
||||
background-color: #375b3f; /*375b3f;*/
|
||||
border: 1px solid #29442f; /*84b0c7;*/
|
||||
text-align: center;
|
||||
margin: 2px;
|
||||
margin-right: 15px;
|
||||
padding: 2px;
|
||||
}
|
||||
.memitem {
|
||||
padding: 4px;
|
||||
background-color: #003010; /*eef3f5;*/
|
||||
/* border-width: 1px; */
|
||||
/* border-style: solid; */
|
||||
/* border-color: #dedeee;*/
|
||||
-moz-border-radius: 8px 8px 8px 8px;
|
||||
}
|
||||
.memname {
|
||||
white-space: nowrap;
|
||||
font-weight: bold;
|
||||
}
|
||||
.memdoc{
|
||||
padding-left: 10px;
|
||||
}
|
||||
.memproto {
|
||||
background-color: #375b3f; /*#d5e1e8;*/
|
||||
width: 100%;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
border-color: #29442f; /*#84b0c7;*/
|
||||
font-weight: bold;
|
||||
-moz-border-radius: 8px 8px 8px 8px;
|
||||
}
|
||||
.paramkey {
|
||||
text-align: right;
|
||||
}
|
||||
.paramtype {
|
||||
white-space: nowrap;
|
||||
}
|
||||
.paramname {
|
||||
color: #db4949; /*602020;*/
|
||||
font-style: italic;
|
||||
white-space: nowrap;
|
||||
}
|
||||
/* End Styling for detailed member documentation */
|
||||
|
||||
/* for the tree view */
|
||||
.ftvtree {
|
||||
font-family: sans-serif;
|
||||
margin:0.5em;
|
||||
}
|
||||
.directory { font-size: 9pt; font-weight: bold; }
|
||||
.directory h3 { margin: 0px; margin-top: 1em; font-size: 11pt; }
|
||||
.directory > h3 { margin-top: 0; }
|
||||
.directory p { margin: 0px; white-space: nowrap; }
|
||||
.directory div { display: none; margin: 0px; }
|
||||
.directory img { vertical-align: -30%; }
|
||||
BIN
Doc/html/acg_tab_b.gif
Normal file
|
After Width: | Height: | Size: 35 B |
BIN
Doc/html/acg_tab_l.gif
Normal file
|
After Width: | Height: | Size: 215 B |
BIN
Doc/html/acg_tab_r.gif
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
107
Doc/html/acg_tabs.css
Normal file
@@ -0,0 +1,107 @@
|
||||
/* tabs styles, based on http://www.alistapart.com/articles/slidingdoors */
|
||||
|
||||
DIV.tabs
|
||||
{
|
||||
float : left;
|
||||
width : 100%;
|
||||
background : url("acg_tab_b.gif") repeat-x bottom;
|
||||
margin-bottom : 4px;
|
||||
}
|
||||
|
||||
DIV.tabs UL
|
||||
{
|
||||
margin : 0px;
|
||||
padding-left : 10px;
|
||||
list-style : none;
|
||||
}
|
||||
|
||||
DIV.tabs LI, DIV.tabs FORM
|
||||
{
|
||||
display : inline;
|
||||
margin : 0px;
|
||||
padding : 0px;
|
||||
}
|
||||
|
||||
DIV.tabs FORM
|
||||
{
|
||||
float : right;
|
||||
}
|
||||
|
||||
DIV.tabs A
|
||||
{
|
||||
float : left;
|
||||
background : url("acg_tab_r.gif") no-repeat right top;
|
||||
border-bottom : 1px solid #e0e0d0;
|
||||
font-size : x-small;
|
||||
font-weight : bold;
|
||||
text-decoration : none;
|
||||
}
|
||||
|
||||
DIV.tabs A:hover
|
||||
{
|
||||
background-position: 100% -150px;
|
||||
}
|
||||
|
||||
DIV.tabs A:link, DIV.tabs A:visited
|
||||
{
|
||||
color: #f07030;
|
||||
}
|
||||
|
||||
DIV.tabs A:hover,
|
||||
DIV.tabs A:active
|
||||
{
|
||||
color: #e0e0d0
|
||||
}
|
||||
|
||||
DIV.tabs SPAN
|
||||
{
|
||||
float : left;
|
||||
display : block;
|
||||
background : url("acg_tab_l.gif") no-repeat left top;
|
||||
padding : 5px 9px;
|
||||
white-space : nowrap;
|
||||
}
|
||||
|
||||
DIV.tabs INPUT
|
||||
{
|
||||
float : right;
|
||||
display : inline;
|
||||
font-size : 1em;
|
||||
}
|
||||
|
||||
DIV.tabs TD
|
||||
{
|
||||
font-size : x-small;
|
||||
font-weight : bold;
|
||||
text-decoration : none;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Commented Backslash Hack hides rule from IE5-Mac \*/
|
||||
DIV.tabs SPAN {float : none;}
|
||||
/* End IE5-Mac hack */
|
||||
|
||||
DIV.tabs A:hover SPAN
|
||||
{
|
||||
background-position: 0% -150px;
|
||||
}
|
||||
|
||||
DIV.tabs LI#current A
|
||||
{
|
||||
background-position: 100% -150px;
|
||||
border-width : 0px;
|
||||
}
|
||||
|
||||
DIV.tabs LI#current SPAN
|
||||
{
|
||||
background-position: 0% -150px;
|
||||
padding-bottom : 6px;
|
||||
}
|
||||
|
||||
DIV.nav
|
||||
{
|
||||
background : none;
|
||||
border : none;
|
||||
border-bottom : 1px solid #e0e0d0;
|
||||
}
|
||||
BIN
Doc/images/class-hierarchy.png
Normal file
|
After Width: | Height: | Size: 79 KiB |
BIN
Doc/images/class-hierarchy2.png
Normal file
|
After Width: | Height: | Size: 52 KiB |
BIN
Doc/images/collapse_info.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
Doc/images/diagrams.sxi
Normal file
BIN
Doc/images/halfedge_structure.gif
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
Doc/images/halfedge_structure2.png
Normal file
|
After Width: | Height: | Size: 5.2 KiB |
BIN
Doc/images/halfedge_structure3.png
Normal file
|
After Width: | Height: | Size: 7.8 KiB |
BIN
Doc/images/inheritance-simple.png
Normal file
|
After Width: | Height: | Size: 9.8 KiB |
BIN
Doc/images/inheritance-simple.scaled.png
Normal file
|
After Width: | Height: | Size: 7.0 KiB |
24
Doc/images/inheritance.fig
Normal file
@@ -0,0 +1,24 @@
|
||||
#FIG 3.2
|
||||
Landscape
|
||||
Center
|
||||
Inches
|
||||
Letter
|
||||
100.00
|
||||
Single
|
||||
-2
|
||||
1200 2
|
||||
2 1 0 2 0 7 50 0 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 2.00 120.00 240.00
|
||||
2550 3900 2550 3300
|
||||
2 1 0 2 0 7 50 0 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 2.00 120.00 240.00
|
||||
2550 2700 2550 2100
|
||||
2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5
|
||||
1500 1500 3600 1500 3600 2100 1500 2100 1500 1500
|
||||
2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5
|
||||
1500 2700 3600 2700 3600 3300 1500 3300 1500 2700
|
||||
2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5
|
||||
1500 3900 3600 3900 3600 4500 1500 4500 1500 3900
|
||||
4 1 0 50 0 0 25 0.0000 4 255 990 2475 1950 Kernel\001
|
||||
4 1 0 50 0 0 25 0.0000 4 345 1500 2550 3150 PolyMesh\001
|
||||
4 1 0 50 0 0 25 0.0000 4 255 1290 2550 4350 TriMesh\001
|
||||
BIN
Doc/images/inheritance.gif
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
Doc/images/iomanager.gif
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
Doc/images/om-format.png
Normal file
|
After Width: | Height: | Size: 30 KiB |
10
Doc/mainpage.docu
Normal file
@@ -0,0 +1,10 @@
|
||||
/** \mainpage OpenMesh Documentation
|
||||
|
||||
\li \ref compiling
|
||||
\li \ref naming_conventions
|
||||
\li \ref tutorial
|
||||
\li \ref history
|
||||
\li \ref mesh_docu
|
||||
\li \ref tools_docu
|
||||
|
||||
**/
|
||||
877
Doc/mesh.docu
Normal file
@@ -0,0 +1,877 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
/** \page mesh_docu OpenMesh Documentation
|
||||
|
||||
We provided a short overview over the functionality of the %OpenMesh
|
||||
library and some additional concepts in \ref tutorial, and
|
||||
will now explain the most important topics of %OpenMesh in more
|
||||
detail.
|
||||
|
||||
-# \ref mesh_first_to_read
|
||||
-# \ref mesh_features
|
||||
-# \ref mesh_cpp
|
||||
-# \ref mesh_hds
|
||||
-# \ref mesh_type
|
||||
-# \ref mesh_hierarchy
|
||||
-# \ref mesh_members
|
||||
-# \ref mesh_io
|
||||
-# \ref mesh_iterators
|
||||
|
||||
*/
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
/** \page mesh_first_to_read Read me first!!!
|
||||
|
||||
Please note, that %OpenMesh makes heavily use of C++ templates,
|
||||
generic programming and all that stuff (see \ref mesh_cpp). Therefore
|
||||
read this section carefully (else you get lost in the reference
|
||||
manual):
|
||||
|
||||
<h3>There is no such thing like the %OpenMesh class</h3>
|
||||
|
||||
The library provides a set of classes ( 99% templates ;-) ), where the
|
||||
inheritance relationship is given by template parameterization. You
|
||||
might ask: "What the heck is that?" It means, a parent class is passed
|
||||
as a template argument to another class:
|
||||
|
||||
\code
|
||||
|
||||
class P1 { }
|
||||
class P2 { }
|
||||
template <typename Parent> class B : public Parent {}
|
||||
|
||||
typedef B<P1> fooB1;
|
||||
typedef B<P2> fooB2;
|
||||
|
||||
\endcode
|
||||
|
||||
Voila, we have created two different types of B. Depending on the
|
||||
interface, the public member elements, provided by \c P1 or \c P2, \c
|
||||
fooB1 and \c fooB2 might have different behaviours or even different
|
||||
interfaces! But if \c P1 and \c P2 have the some interface or at least
|
||||
a common interface, then from programming point of view there is no
|
||||
difference using \c fooB1 or \c fooB2. And this is all
|
||||
about. %OpenMesh defines an interface concept for the kernel which is
|
||||
documented in \ref OpenMesh::Concepts::KernelT. As long as the kernel
|
||||
provides this the class handling polygonal meshes \c
|
||||
OpenMesh::PolyMeshT can use any kernel.
|
||||
|
||||
<h3>Therefore documentation resides in two spaces</h3>
|
||||
|
||||
-# Associated with the class/struct (as usual)
|
||||
-# In a concept class in cases like the example code above. Hence, if you want
|
||||
to know what a mesh type has to offer refer to OpenMesh::Concepts::KernelT,
|
||||
OpenMesh::PolyMeshT, OpenMesh::TriMeshT.
|
||||
|
||||
*/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
/** \page mesh_features Features and Goals
|
||||
|
||||
The main features of the underlying data structure are:
|
||||
|
||||
\li No restriction to triangles meshes, handle general polygonal meshes.
|
||||
\li Explicit representation of vertices, halfedges, edges, and faces.
|
||||
\li Efficient access to the one-ring neighborhood of a vertex.
|
||||
\li Ability to handle non-manifold vertices (like two faces meeting in only
|
||||
one vertex).
|
||||
|
||||
|
||||
The goals/features of the C++ implementation are:
|
||||
|
||||
<ul>
|
||||
<li> Flexibility:
|
||||
<ul>
|
||||
<li> Choose suitable types for scalars and coordinates (e.g. float,
|
||||
double, exact arithmetic and two-, three-, or n-dimensional
|
||||
points).
|
||||
<li> Enhance each item type by your own attributes/properties, like
|
||||
e.g. adding a normal vector or a \c FaceHandle to class \c
|
||||
Vertex.
|
||||
</ul>
|
||||
<li> Efficiency:
|
||||
<ul>
|
||||
<li> Avoid the overhead of virtual inheritance and virtual function calls.
|
||||
<li> Resolve as many type/attribute dependencies as possible at
|
||||
compile-time instead of testing for attributes at run-time
|
||||
(e.g. normal vectors for faces).
|
||||
</ul>
|
||||
<li> Type-safety for handles, <b>no type-casting (*)</b>: Vertices,
|
||||
(Half-)Edges, Faces know each other and their corresponding
|
||||
handles.
|
||||
|
||||
<b>(*)</b> Since version 0.10.0 the Microsoft VisualC++ compiler is
|
||||
supported. Due to the compilers inaptitude to process forwards on template
|
||||
functions correctly, the type-safety had to be given up to some extend.
|
||||
Though under the hood void pointers are used, the casting is done
|
||||
within the mesh, and the user transparently uses his handles as before.<br>
|
||||
As soon as the compiler adheres to the C++ standard the type-safe version
|
||||
will be restored.
|
||||
</ul>
|
||||
*/
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
/** \page mesh_cpp Some words on the C++ implementation
|
||||
|
||||
If one takes a look at the goals and features section it soon becomes
|
||||
obvious that these goals cannot be achieved using trivial C++ features
|
||||
only. We make heavy use of templates, (partial) template specialization,
|
||||
generative and generic programming, and the STL. This may be a challenge
|
||||
for you as well as for your compiler, as these are quite late features
|
||||
of the C++ language.
|
||||
|
||||
While knowledge of generative programming is only necessary if you
|
||||
want to create your own mesh kernels or extend iterators or similar
|
||||
types, you will \b NOT need it for simply using these things.
|
||||
Nevertheless working knowledge of C++ and basic knowlege of templates
|
||||
is required. To get into this stuff we recommend the following
|
||||
books:
|
||||
|
||||
\li Bjarne Stroustrup, <em> The C++ Programming Language </em>,
|
||||
|
||||
\li Matthew H. Austern, <em> Generic Programming and the STL: Using
|
||||
and Extending the C++ Standard Template Library </em>,
|
||||
|
||||
\li Andrei Alexandrescu, <em> Modern C++ Design: Generic Programming
|
||||
and Design Patterns Applied </em>,
|
||||
|
||||
\li Krzysztof Czarnecki, Ulrich Eisenecker, <em> Generative Programming:
|
||||
Methods, Tools, and Applications </em>.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
/** \page mesh_hds The Halfedge Data Structure
|
||||
|
||||
This section describes the underlying data structure that is used to
|
||||
store the mesh entities (items) vertices, edges, faces, and their
|
||||
connectivity information. There are many popular data structures used
|
||||
to represent polygonal meshes. For a detailed comparison of them refer
|
||||
to the papers at the end of this section.
|
||||
|
||||
The data structure used in this project is the so called <em> halfedge
|
||||
data structure </em>. While <em> face-based </em> structures store
|
||||
their connectivity in faces referencing their vertices and neighbors,
|
||||
<em> edge-based </em> structures put the connectivity information into
|
||||
the edges. Each edge references its two vertices, the faces it belongs
|
||||
to and the two next edges in these faces. If one now splits the edges
|
||||
(i.e. an edge connecting vertex \c A and vertex \c B becomes two <em>
|
||||
directed halfeges </em> from \c A to \c B and vice versa) one gets a
|
||||
<em> halfedge-based </em> data structure. The following figure
|
||||
illustrates the way connectivity is stored in this structure:
|
||||
|
||||
<table>
|
||||
<tr valign=top>
|
||||
<td> \image html halfedge_structure3.png
|
||||
<td>
|
||||
<ul>
|
||||
<li> Each \b vertex references one outgoing halfedge, i.e. a halfedge that
|
||||
starts at this vertex (1).
|
||||
<li> Each \b face references one of the halfedges bounding it (2).
|
||||
<li> Each \b halfedge provides a handle to
|
||||
<ul>
|
||||
<li> the vertex it points to (3),
|
||||
<li> the face it belongs to (4)
|
||||
<li> the next halfedge inside the face (ordered counter-clockwise) (5),
|
||||
<li> the opposite halfedge (6),
|
||||
<li> (optionally: the previous halfedge in the face (7)).
|
||||
</ul>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
Having these links between the items, it is now possible to circulate
|
||||
around a face in order to enumerate all its vertices, halgedges, or
|
||||
neighboring faces. When starting at a vertex' halfedge and iterating
|
||||
to the opposite of its previous one, one can easily circulate around
|
||||
this vertex and get all its one-ring neighbors, the incoming/outgoing
|
||||
halfedges, or the adjacent faces. All this functionality is
|
||||
encapsulated into the so-called <em> circulators </em>, described in
|
||||
\ref mesh_iterators.
|
||||
|
||||
\attention In order to efficiently classify a boundary
|
||||
vertex, the outgoing halfedge of these vertices <b> must be a boundary
|
||||
halfedge </b> (see OpenMesh::PolyMeshT::is_boundary()).
|
||||
\attention Whenever you modify the
|
||||
topology using low-level topology changing functions, be sure to
|
||||
guarantee this behaviour (see
|
||||
OpenMesh::PolyMeshT::adjust_outgoing_halfedge())
|
||||
|
||||
While one does not need to store the previous halfedge (7) explicitly,
|
||||
because it can be derived from the links to the next halfedges, one
|
||||
may do so for the sake of performance. In fact, the previous halfedge
|
||||
is stored by default (OpenMesh::DefaultTraits). Using traits and
|
||||
attributes the previous halfedge can removed, to gain memory. This
|
||||
kind of mesh customization is explained in \ref mesh_type.
|
||||
|
||||
While the halfedge-based structures usually consume more memory than
|
||||
their face-based counter-parts they have the following important
|
||||
advantages:
|
||||
|
||||
\li It is easy to mix faces of arbitrary vertex count in one mesh.
|
||||
|
||||
\li We now have an explicit representation of vertices, faces, \em and
|
||||
edges/halfedges. This becomes extremely useful if one has to store data
|
||||
per edge/halfedge since this can easily be modelled by member
|
||||
variables of these types (see \ref mesh_type).
|
||||
|
||||
\li Circulating around a vertex in order to get its one-ring neighbors is an
|
||||
important operation for many kinds of algorithms on polygonal meshes.
|
||||
For face-based structures this leads to many <tt>if-then</tt> branchings,
|
||||
the halfedge structure provides this funcionality without
|
||||
conditional branching in constant time.
|
||||
|
||||
|
||||
<b>References</b>
|
||||
|
||||
S. Campagna, L. Kobbelt, H.-P. Seidel, <em> Directed Edges - A
|
||||
Scalable Representation For Triangle Meshes </em>, ACM Journal of
|
||||
Graphics Tools 3 (4), 1998.
|
||||
|
||||
Lutz Kettner, <em> Using Generic Programming for Designing a Data
|
||||
Structure for Polyhedral Surfaces</em>, in Proc. 14th Annual ACM
|
||||
Symp. on Computational Geometry, 1998.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
/** \page mesh_hierarchy Conceptual Class Hierarchy
|
||||
|
||||
Since there is no such thing as a %OpenMesh class and the library
|
||||
makes heavy use of C++ template, we show the inheritance graph of
|
||||
OpenMesh::TriMesh_ArrayKernelT as proxy for all possible mesh types.
|
||||
|
||||
Please note! Most of the inheritence relationships are realized by
|
||||
template parameterization! Therefore some of the inheritance links are
|
||||
not documented in a inheritance graph in the reference. This picture
|
||||
shows the overall concept.
|
||||
|
||||
\image html class-hierarchy2.png
|
||||
|
||||
\subsection ch_kernel Building the kernel
|
||||
|
||||
-# The BaseKernel defines the basic operations on properties like
|
||||
add/remove/access.
|
||||
-# Next the AttribKernelT adds the standard properties all associated
|
||||
methods.
|
||||
-# Finally the ArrayKernelT provides the methods to add/remove/access
|
||||
the mesh items vertices, (half-)edges, and faces. The base class is passed
|
||||
as a template parameter, since depending on the underlying storage type the
|
||||
AttribKernel might change.
|
||||
|
||||
\subsection ch_complete Building the mesh
|
||||
|
||||
-# The PolyMeshT inherits from the kernel and provide all necessary methods
|
||||
to work with polygonal meshes.
|
||||
-# Finally we derive TriMeshT from PolyMeshT to have an specialization for
|
||||
triangle meshes.
|
||||
|
||||
Looks simple, but it isn't - it's a bit more complicated:
|
||||
|
||||
\include build-trimesh.cc
|
||||
|
||||
To generate the actual mesh type the helper template class \c
|
||||
TriMesh_ArrayKernel_GeneratorT is used. It takes the traits in a
|
||||
template argument and passes it to \c FinalMeshItemsT to get the final
|
||||
type of the mesh items (MeshItems). The \c MeshItems defines the
|
||||
types for Point, Normal, Color, TexCoord, Vertex, and for all mesh
|
||||
items. With the help of \c MeshItems create the type of the \c
|
||||
AttribKernel, which defines the apropriate standard properties for the
|
||||
items. Finally use \c AttribKernel and \c MeshItems to create the
|
||||
mesh kernel type \c MeshKernel. It's quite a way to get a kernel . As
|
||||
long as the created kernel follows the kernel concept (\ref
|
||||
mesh_kernels_group), we can easily create now the mesh. Here we
|
||||
use now \c TriMeshT to create the final mesh type \c Mesh.
|
||||
|
||||
*/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
/** \page mesh_type Specifying your MyMesh
|
||||
|
||||
This section will show how to build your own custom tailored type \c
|
||||
MyMesh. As we have seen in the section on goals and features there are
|
||||
some parameters to be specified for a mesh. This is done in the
|
||||
following four steps:
|
||||
|
||||
<ol>
|
||||
|
||||
<li> Choose between triangle mesh and general polygonal mesh.
|
||||
|
||||
<li> Select the mesh kernel
|
||||
|
||||
<li> Parameterize the mesh by a so-called \em Traits class. You can
|
||||
add arbitrary classes to the mesh items, specify the types \c Scalar,
|
||||
\c Point, \c Normal and \c Color, and use predefined attributes like
|
||||
\c Attributes::Normal and \c Attributes::Color.
|
||||
|
||||
<li> Dynamically bind data to the mesh or the mesh entities (vertex,
|
||||
(half-)edge, face) using \em custom \em properties.
|
||||
|
||||
</ol>
|
||||
|
||||
We will explain these four parameterization steps and give a code
|
||||
example at the end of this page.
|
||||
|
||||
<br><br>
|
||||
|
||||
\section sec_select_face_type Polygonal or Triangle Mesh?
|
||||
|
||||
This decision is quite simple: Whenever possible choose the triangle
|
||||
mesh. The restriction to triangular faces usually leads to more
|
||||
efficient algorithms (e.g. rendering triangles is much faster than
|
||||
rendering arbitrary polygons). Additionally some algorithms are only
|
||||
implemented for triangle meshes while triangle meshes inherit the full
|
||||
functionality of polygonal meshes. For a list of them refer to the
|
||||
following links.
|
||||
|
||||
\see OpenMesh::PolyMeshT
|
||||
\see OpenMesh::TriMeshT
|
||||
|
||||
|
||||
|
||||
<br><br>
|
||||
|
||||
\section sec_select_kernel Choosing the right kernel
|
||||
|
||||
The mesh kernel specifies how the mesh entities (vertices,
|
||||
(half-)edges, faces) are internally stored. In fact the entities are kept in
|
||||
so-called properties. A property itself provides an array like interface.
|
||||
The kernel defines the corresponding handle types,
|
||||
i.e. the way items reference each other. Since the properties have an
|
||||
array like interface the handles are represented internally as indices.
|
||||
|
||||
The default kernel is \c ArrayKernelT. Which is good for most
|
||||
situations. But depending on the application a different kernel would
|
||||
be better. E.g. the OpenSG integration has been realized be replacing
|
||||
the kernel by a custom kernel, since OpenSG provides already array like
|
||||
properties, which could be reused for the intergration. In case of a an OpenSG
|
||||
environment one might be better off using \c OSG_Kernel::ArrayKernelT.
|
||||
|
||||
\see \ref mesh_kernels_group
|
||||
|
||||
<br><br>
|
||||
|
||||
\section sec_select_traits Mesh Traits
|
||||
|
||||
While the last two sections only have chosen from a list of predefined
|
||||
meshes or kernels, respectively, we now come to the user-defined
|
||||
customization.
|
||||
|
||||
The resulting mesh \c MyMesh will provide the following types:
|
||||
|
||||
<ul>
|
||||
<li> The <i>point</i> and <i>scalar</i> type: \c MyMesh::Point and \c
|
||||
MyMesh::Scalar.
|
||||
<li> The <i>mesh items</i>: \c MyMesh::Vertex, \c MyMesh::Halfedge, \c
|
||||
MyMesh::Edge, \c MyMesh::Face.
|
||||
<li> The <i>handle</i> types: \c MyMesh::VertexHandle, \c
|
||||
MyMesh::HalfedgeHandle, \c MyMesh::EdgeHandle, \c
|
||||
MyMesh::FaceHandle.
|
||||
</ul>
|
||||
|
||||
While the handle types are fixed, the other types can be customized.
|
||||
Each mesh type (see \ref mesh_types_group) can be parameterized
|
||||
by a so-called \em traits class. Using this mechanism one can
|
||||
|
||||
<ol>
|
||||
<li> change the coordinate type \c MyMesh::Point and the resulting
|
||||
scalar type \c MyMesh::Scalar == \c MyMesh::Point::value_type,
|
||||
<li> change the normal type \c MyMesh::Normal
|
||||
<li> change the color type \c MyMesh::Color
|
||||
<li> use predefined attributes like normal vector, color, texture
|
||||
coordinates, ... for the
|
||||
mesh items.
|
||||
<li> add arbitrary classes to the mesh items.
|
||||
</ol>
|
||||
|
||||
All these customizations are encapsulated in one class \c MyTraits,
|
||||
that is used as template argument to the mesh, e.g.
|
||||
\code
|
||||
struct MyTraits {
|
||||
// your customization
|
||||
};
|
||||
typedef PolyMesh_ArrayKernelT<MyTraits> MyMesh;
|
||||
\endcode
|
||||
|
||||
The rest of this section explains the construction of this traits
|
||||
class, its application to the mesh will be the topic of the next section.
|
||||
|
||||
For each mesh entity one can control the predefined attributes to be
|
||||
attached by a traits class using some convenience macros, e.g. \c
|
||||
OpenMesh::VertexAttributes and \c OpenMesh::VertexTraits for
|
||||
vertices. The default traits class looks like this:
|
||||
|
||||
\include traits0.cc
|
||||
|
||||
Please note that for example \c VertexTraits is a define concealing a
|
||||
template declaration. The actual template class name is \c VertexT,
|
||||
which is further simplified to a specific type \c Vertex at a later
|
||||
stage during the construction of the mesh kernel.
|
||||
|
||||
Because the traits classes always have to provide the template classes
|
||||
\c VertexT, \c HalfedgeT, \c EdgeT, \c FaceT, and the types \c Point,
|
||||
\c Normal, \c Color, and \c TexCoord one should derive this class from
|
||||
the default implementation \c DefaultTraits. In this case you will
|
||||
only have to define the classes or types you want to override or substitute.
|
||||
|
||||
|
||||
<br>
|
||||
\subsection sec_change_point Changing the Point type
|
||||
|
||||
Changing the type that is used to store the point coordinates as well
|
||||
as the normal vectors can simply be done by defining this type in the
|
||||
traits class. The following code changes the coordinate type in order
|
||||
to use \c double instead of \c float.
|
||||
|
||||
\include traits1.cc
|
||||
|
||||
Using the OpenMesh::VectorT class you can easily plug in any scalar
|
||||
type for the use in point coordinates, e.g. some exact arithmetic. You
|
||||
can also exchange the whole class representing points as long as it
|
||||
provides the same interface as the OpenMesh::VectorT class.
|
||||
|
||||
|
||||
<br>
|
||||
\subsection sec_add_attributes Adding Predefined Attributes
|
||||
|
||||
There are some pre-defined attributes that can be appended to the mesh
|
||||
items. These global attributes are defined in the namespace
|
||||
OpenMesh::Attributes. The advantage of these attributes is that
|
||||
they are registered at the items they are added to. Therefore
|
||||
algorithms can check for these attributes at run-time as well as at
|
||||
compile-time. This is important if you want to implement algorithms
|
||||
acting on different meshes, that may or may not have e.g. normal
|
||||
vectors per vertex/face.
|
||||
|
||||
Adding these predefined attributes is quite simple. You provide an
|
||||
<tt>unsigned int</tt> in the traits class, whose bits control whether
|
||||
or not a certain attribute should be attached or not.
|
||||
|
||||
If you want to add a normal vector to your vertices and faces, and also
|
||||
want to have color information for vertices, the code would look like this:
|
||||
|
||||
\include traits5.cc
|
||||
|
||||
Internally each mesh item contains an \c enum defining the integer \c
|
||||
Attributes (containing the bits of used attributes OR'ed
|
||||
together). From its set/unset bits you can see whether a certain
|
||||
attribute is used. OpenMesh provides the macro OM_Check_Attrib for
|
||||
doing this:
|
||||
|
||||
\code
|
||||
if (OM_Check_Attrib(MyMesh::Vertex, Normal)
|
||||
do_something_with_normals();
|
||||
\endcode
|
||||
|
||||
These run-time checks may not be sufficient in some cases. You can also check
|
||||
for attributes at compile-time and instantiate the correct functions
|
||||
by using function overloading. The class \c GenProg::Bool2Type maps
|
||||
true/false information to two different types, \c Bool2Type<true> and
|
||||
\c Bool2Type<false>. An example that draws OpenGL normals if they are
|
||||
available would look like this:
|
||||
|
||||
\include draw_normals.cc
|
||||
|
||||
Especially the compile-time checking for attributes is extremely
|
||||
useful because it does not generate any unnecessary code and does not
|
||||
perform expensive tests at run-time.
|
||||
|
||||
\see OpenMesh::DefaultTraits
|
||||
\see OpenMesh::Attributes
|
||||
\see OpenMesh::GenProg
|
||||
|
||||
<br>
|
||||
\subsection sec_add_traits Adding User-Defined Elements
|
||||
|
||||
You can also add arbitrary types/elements/methods to the mesh items by
|
||||
providing a corresponding traits class for these items. Adding some
|
||||
index to the \c Vertex class is easily done by
|
||||
|
||||
\include traits2.cc
|
||||
|
||||
The macro \c VertexTraits hides some ugly template stuff. In fact, it
|
||||
is defined as
|
||||
|
||||
\code
|
||||
#define VertexTraits template <class Base, class Refs> struct VertexT : public Base
|
||||
\endcode
|
||||
|
||||
hence the traits class actually looks like this:
|
||||
|
||||
\include traits3.cc
|
||||
|
||||
You have to keep this in mind when you want to define constructors for
|
||||
your vertex type or when you want to derive the vertex type from other
|
||||
classes.
|
||||
|
||||
The template argument \c Base provides access to the mesh handles and
|
||||
to the \c Point and \c Scalar type by its member class \c Refs. Adding
|
||||
a \c MyMesh::FaceHandle to the vertex class can therefore be
|
||||
implemented like this:
|
||||
|
||||
\include traits4.cc
|
||||
|
||||
Adding elements to other mesh items works in the same manner.
|
||||
|
||||
|
||||
<br>
|
||||
\subsection sec_algo_traits Using traits defined by algorithms
|
||||
|
||||
From version 0.10.3 on algorithms can define traits/attributes they
|
||||
require and the user can merge these traits into his own traits. A more elegant
|
||||
way is to use dynamic properites, which can be added/removed during runtime
|
||||
by the algorithm. This is the preferred way to attach custom data to the mesh.
|
||||
|
||||
An example for an algorithm as well as the application using traits
|
||||
is given in \ref tutorial_06.
|
||||
|
||||
<br><br>
|
||||
|
||||
\section sec_properties Dynamic Properties
|
||||
|
||||
From version 1.0 on %OpenMesh provides dynamic properties. Instead of
|
||||
using traits to bind data at compile time algorithms or the
|
||||
application can use dynamic properties. Similar to entities the properties
|
||||
are accessed and manipulated via handles.
|
||||
|
||||
An example for an algorithm as well as the application using
|
||||
properties is given in \ref tutorial_03 and \ref tutorial_04.
|
||||
|
||||
<br><br>
|
||||
|
||||
\section sec_traits_example Final Implementation Example
|
||||
|
||||
Consider an application where we just want to render triangle meshes.
|
||||
This means we will select the triangle mesh and the \c
|
||||
ArrayKernelT. Faces that are not triangles will automatically be
|
||||
tesselated into triangles. Because we only display meshes and do not
|
||||
dynamically add or remove items, we can just use the \c ArrayKernelT.
|
||||
|
||||
All mesh-kernel combinations are predefined in the directory
|
||||
<tt>%OpenMesh/Mesh/Types</tt>. Refer to \ref mesh_types_group for a
|
||||
complete list of them. For our example we use the \c
|
||||
TriMesh_ArrayKernelT and parameterize it by our \c MyTraits class.
|
||||
|
||||
We will need face and vertex normals and e.g. for color coding vertex
|
||||
curvature, i.e. vertex color.
|
||||
|
||||
\include mymesh.cc
|
||||
|
||||
That's it.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
/** \page mesh_members Where do I find a list of all member functions ?
|
||||
|
||||
The following picture shows the (simplified) conceptual inheritance
|
||||
diagram for the %OpenMesh classes.
|
||||
|
||||
\image html inheritance-simple.scaled.png
|
||||
|
||||
The basis for all meshes is the corresponding \c MeshKernel, taking
|
||||
care of the internal storage of the mesh items (vertices,
|
||||
(half-)edges, faces). This kernel is inherited by the \c PolyMeshT,
|
||||
i.e. the general polygonal mesh, adding higher level
|
||||
functionality. For specialization purposes the class \c TriMeshT is
|
||||
derived from \c PolyMeshT and overrides some member functions or adds
|
||||
functions only suitable for pure triangle meshes.
|
||||
|
||||
In most cases a class (e.g. \c PolyMeshT) gets the class it should
|
||||
derive from (e.g. the mesh kernel) as a template parameter. The
|
||||
documentation class OpenMesh::Concepts::MeshKernel::KernelT lists the
|
||||
minimal interface a mesh kernel must provide. Special kernels may
|
||||
provide some more functionality, in this case refer to this kernel's
|
||||
documentation (see \ref mesh_kernels_group). Therefore your mesh
|
||||
provides the pubic member functions of
|
||||
|
||||
<ul>
|
||||
<li> The mesh kernel.
|
||||
<li> The general polygonal mesh.
|
||||
<li> The specialized triangle mesh (if you use a TriMesh instead of a PolyMesh).
|
||||
</ul>
|
||||
|
||||
|
||||
\see OpenMesh::Concepts
|
||||
\see OpenMesh::Concepts::KernelT
|
||||
\see OpenMesh::PolyMeshT
|
||||
\see OpenMesh::TriMeshT
|
||||
|
||||
**/
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
/** \page mesh_io Mesh Input and Output
|
||||
|
||||
This section explains the methods used to read a mesh from a file or
|
||||
write it to a file. The corresponding functions are defined in the
|
||||
namespace OpenMesh::MeshIO. This section is divided into three steps.
|
||||
Step one will give a short example on how to use the %OpenMesh IOManager,
|
||||
step two will give some background information on how IOManager works and
|
||||
finally step three will show you how to add your own modules to IOManager.
|
||||
|
||||
\section mesh_io_quick Step 1 - IOManager quick start
|
||||
|
||||
For a quick start you can copy the following code directly to your project.
|
||||
|
||||
\include mesh_io.cc
|
||||
|
||||
|
||||
<br><br>
|
||||
|
||||
\section mesh_io_theory Step 2 - The theory behind IOManager
|
||||
|
||||
Usually mesh reader and writer routines are written directly against
|
||||
the data structure and the respective file format they support. This
|
||||
approach has the main disadvantage that targeting a different data
|
||||
structure or adding another file format leads to duplication of code.
|
||||
|
||||
IOManager acts as an interface between persistent data on one side and
|
||||
an arbitrary data structure on the other side by means of reader/writer
|
||||
and importer/exporter modules. This is illustrated by the following
|
||||
diagramm :
|
||||
|
||||
\image html iomanager.gif
|
||||
|
||||
<br>
|
||||
|
||||
Persistent data of arbitrary format is first interpreted by a reader
|
||||
module. The data is then passed - by means of a specified interface -
|
||||
to an importer module for the target data structure. The process for
|
||||
writing data is analogous. The IOManager controls the entire process.
|
||||
Reader/Writer modules are invisible to the user. Importer/Exporter
|
||||
however have to be specified explicitely as they are specific to a
|
||||
data structure.
|
||||
|
||||
The complete separation of data structure and persistent data makes it
|
||||
especially easy to maintain existing code and to extend funtionality
|
||||
at both ends as will be shown in step three.
|
||||
|
||||
\see OpenMesh::IO::_IOManager_
|
||||
|
||||
<br><br>
|
||||
|
||||
\section mesh_io_extend Step 3 - How to extend IOManager
|
||||
|
||||
\subsection mesh_io_extend_fileformat Adding support for a new file format
|
||||
|
||||
Adding support for a new file format involves adding a reader and
|
||||
writer module. Reader modules are classes derived from
|
||||
OpenMesh::IO::BaseReader. The part of the interface that you
|
||||
usually have to define is shown below.
|
||||
|
||||
\include BaseReader.hh
|
||||
|
||||
Based on the file extension or the header information the IOManager
|
||||
decides which reader module to use. The reader then parses the format
|
||||
and the information will be passed to the target data structure be
|
||||
means of a class derived from OpenMesh::IO::BaseImporter.
|
||||
|
||||
Writer modules are derived from OpenMesh::IO::BaseWriter and work
|
||||
the same way as reader modules.
|
||||
|
||||
<br>
|
||||
|
||||
\subsection mesh_io_extend_datastruct Adding support for a new data structure
|
||||
|
||||
As we have already seen, Importers receive information from the reader modules.
|
||||
Reader modules pass information through a specified interface :
|
||||
|
||||
\include BaseImporter.hh
|
||||
|
||||
The Importer is then responsible for filling the target data structure.
|
||||
Exporting information from a data structure is a little bit more involved than
|
||||
importing data to it. The writer modules must be able to iterate over all
|
||||
vectors/texcoords/faces. Therefore an exporter has to provide these iterators :
|
||||
|
||||
\include BaseExporter.hh
|
||||
|
||||
There might be the need for the exporter to cache data from the structure it
|
||||
refers to. The update() function should be called at the beginning of
|
||||
each BaseWriter::save() method and it should make sure that cached information
|
||||
is up to date.
|
||||
|
||||
For further information you are encouraged to take a look at the modules
|
||||
provided by %OpenMesh which can be found in the IO subdirectory.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
/** \page mesh_iterators Mesh Iterators and Circulators
|
||||
|
||||
The mesh provides linear iterators (that enumerate vertices,
|
||||
halfedges, edges, and faces) and so called circulators (to iterate \em
|
||||
around a vertex or a face). These can be used to easily navigate
|
||||
through a mesh. Each iterator \c XYZIter also exists in a const
|
||||
version \c ConstXYZIter.
|
||||
|
||||
All iterators and circulators are defined in the namespace
|
||||
OpenMesh::Iterators. They are template classes that expect a mesh as
|
||||
template argument to be fully specified. You should use the
|
||||
iterator/circulator types provided by the mesh itself, i.e. \c
|
||||
MyMesh::VertexIter instead of \c
|
||||
OpenMesh::Iterators::VertexIterT<MyMesh>.
|
||||
|
||||
|
||||
|
||||
\subsection subsec_iterators Linear Iterators
|
||||
|
||||
The linear iterators are used to enumerate all mesh items, e.g. for
|
||||
rendering purposes. The iterators and their \c const counterparts are:
|
||||
|
||||
\include iterators.cc
|
||||
|
||||
The corresponding \c const counterparts are
|
||||
|
||||
\arg \c ConstVertexIter,
|
||||
\arg \c ConstHalfedgeIter,
|
||||
\arg \c ConstEdgeIter,
|
||||
\arg \c ConstFaceIter.
|
||||
|
||||
|
||||
The linear iterators are (almost) conformant to STL iterators. For a
|
||||
description of their interface see OpenMesh::Concepts::IteratorT.
|
||||
|
||||
For efficiency reasons the \c operation++(int) (post-increment)
|
||||
and \c operation--(int) (post-decrement) are not implemented.
|
||||
Additionally to the standard operations, each linear iterator
|
||||
provides a method \c handle(), which returns the handle of the
|
||||
item referred to by the iterator.
|
||||
|
||||
\note An iterator to an item usually needs more memory than a
|
||||
handle of an item. To store many references to an item, it is
|
||||
therefore better to use handles.
|
||||
|
||||
|
||||
<br><br>
|
||||
\subsection subsec_circulators Circulators
|
||||
|
||||
Circulators provide means to enumerate items adjacent to
|
||||
another item of the same or another type. For example,
|
||||
a \c VertexVertexIter allows to enumerate all vertices
|
||||
immediately adjacent to a (center) vertex (i.e. it allows
|
||||
to enumerate the so-called 1-ring of the center vertex).
|
||||
Analogously, a \c FaceHalfedgeIter enumerates all the
|
||||
halfedges belonging to a face.
|
||||
In general, \c CenterItem_AuxiliaryInformation_TargetItem_Iter
|
||||
designates a circulator that enumarates all the target items
|
||||
around a given center item.
|
||||
|
||||
The circulators around a vertex are:
|
||||
|
||||
\arg \c VertexVertexIter: iterate over all neighboring vertices.
|
||||
\arg \c VertexIHalfedgeIter: iterate over all \em incoming halfedges.
|
||||
\arg \c VertexOHalfedgeIter: iterate over all \em outgoing halfedges.
|
||||
\arg \c VertexEdgeIter: iterate over all incident edges.
|
||||
\arg \c VertexFaceIter: iterate over all adjacent faces.
|
||||
|
||||
The circulators around a face are:
|
||||
|
||||
\arg \c FaceVertexIter: iterate over the face's vertices.
|
||||
\arg \c FaceHalfedgeIter: iterate over the face's halfedges.
|
||||
\arg \c FaceEdgeIter: iterate over the face's edges.
|
||||
\arg \c FaceFaceIter: iterate over all edge-neighboring faces.
|
||||
|
||||
The constructor of a circulator is of the form
|
||||
\c Circulator(MeshType mesh, TargetHandle center_handle),
|
||||
i.e. it takes a mesh and the handle of the item to iterate
|
||||
around.
|
||||
|
||||
All circulators provide the operations listed in
|
||||
OpenMesh::Concepts::CirculatorT, which are basically the same as the
|
||||
iterator funtions.
|
||||
|
||||
Furthermore, circulators provide \c operator \c bool(), which returns
|
||||
true, as long as the circulator hasn't reached the end of the
|
||||
sequence.
|
||||
|
||||
Example: The following code enumerates the 1-ring of each vertex:
|
||||
|
||||
\include circulators.cc
|
||||
|
||||
*/
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/** \defgroup mesh_property_handle_group Mesh Property Handles
|
||||
|
||||
All custom properties are represented by the property
|
||||
handles. The handle mechanism allows to add arbitrary data to the mesh
|
||||
items. It stores the value type (by construction) and a 'reference' to the
|
||||
property. Use the mesh object to access the property values.
|
||||
|
||||
\see OpenMesh::PropertyT, OpenMesh::BaseKernel, OpenMesh::Concepts::KernelT,
|
||||
\ref tutorial_03, \ref tutorial_04, \ref tutorial_09
|
||||
|
||||
*/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
/** \defgroup mesh_kernels_group Mesh Kernels
|
||||
|
||||
This group holds all mesh kernels. Since %OpenMesh makes heavily use
|
||||
of templates especially in the kernels, there's no direct inheritence
|
||||
relationship of the kernel classes. For a conceptual overview of the
|
||||
inheritance graph see \ref mesh_hierarchy. For a list of available
|
||||
methods see OpenMesh::Concepts::KernelT.
|
||||
|
||||
\see \ref mesh_hierarchy, OpenMesh::Concepts::KernelT
|
||||
|
||||
*/
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
/** \defgroup mesh_types_group Predefined Mesh Types
|
||||
|
||||
This group holds all the predefind mesh types, i.e. all combinations
|
||||
of triangle/polygonal mesh and the set of kernels.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
/** \defgroup mesh_concepts_group Interface Concepts
|
||||
|
||||
Since for many classes no virtual inheritace is used one can't enforce
|
||||
a specific interface by pure virtual functions. Therefore these
|
||||
interfaces will be described in this group. Everyone implementing
|
||||
e.g. a new mesh kernel should at least implement the
|
||||
OpenMesh::Concepts::Kernel concept.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
93
Doc/misc.docu
Normal file
@@ -0,0 +1,93 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
/** \page naming_conventions Naming Conventions
|
||||
|
||||
The following naming conventions are used for the OpenMesh code:
|
||||
|
||||
<b>Files:</b>
|
||||
\li \c MyClass.cc for C++-Implementation of class \c MyClass
|
||||
\li \c MyClass.hh for C++-Header of class \c MyClass
|
||||
|
||||
<b>Classes:</b>
|
||||
\li Class names start with a capital letter: \c MyClass
|
||||
\li Class templates end with \c T: \c MyClassTemplateT
|
||||
|
||||
<b>Variables:</b>
|
||||
\li One leading underscore for parameters in function-calls: \c _var
|
||||
\li One trailing underscore for member-variables: \c var_
|
||||
\li Two trailing underscores for static member-variables: \c var__
|
||||
|
||||
<b>Functions:</b>
|
||||
\li Words are separated by underscores: \c my_function()
|
||||
|
||||
<b>Accessing members:</b>
|
||||
\li To get the member \c xxx_ use <tt> const& xxx() const </tt>
|
||||
\li To set the member \c xxx_ use <tt> void set_xxx(arg) </tt>
|
||||
|
||||
**/
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
/** \page compiling Compiling OpenMesh
|
||||
|
||||
\section compilers Tested compilers
|
||||
|
||||
%OpenMesh has been tested sucessfully for the following operating
|
||||
systems / compilers:
|
||||
|
||||
<table>
|
||||
|
||||
<tr><td> Linux </td><td>
|
||||
gcc 4.0.x<br>
|
||||
gcc 4.1.x<br>
|
||||
gcc 4.2.x<br>
|
||||
gcc 4.3.x<br>
|
||||
</td></tr>
|
||||
|
||||
<tr><td> Windows </td><td>
|
||||
Microsoft Visual Studio 2008<br>
|
||||
</td></tr>
|
||||
|
||||
<tr><td> MacOS X <br>(Panther and Tiger)</td><td>
|
||||
gcc 3.3 <br>
|
||||
gcc 4.0 <br>
|
||||
</td></tr>
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
\section sec_compiling_unix Unix
|
||||
|
||||
Download and install the Qt4 framework from <a href="http://www.qtsoftware.com/downloads" target="_blank">Trolltech</a>.<br>
|
||||
In order to compile and install OpenMesh, enter following commands in OpenMesh's root directory:<br><br>
|
||||
<tt>
|
||||
qmake ## Generates the appropriate Makefiles<br>
|
||||
make ## Builds the project (use 'make debug' to build debug version)<br>
|
||||
sudo make install ## Install OpenMesh (as root)
|
||||
</tt><br><br>
|
||||
When using the \c qmake command, make sure to use Qt version 4 (some linux distributions<br>
|
||||
use the link \c qmake-qt4 against the executable).
|
||||
|
||||
\section sec_compiling_windows Windows
|
||||
|
||||
For Microsoft Visual Studio 2008, you can use
|
||||
the predefined solution file <tt>Core/OpenMesh_Core.vcproj</tt> and <tt>Tools/OpenMesh_Tools.vcproj</tt>
|
||||
|
||||
\section sec_compiling_macosx MacOSX
|
||||
|
||||
Download and install the Qt4 framework from <a href="http://www.qtsoftware.com/downloads" target="_blank">Trolltech</a>.<br>
|
||||
In order to compile and install OpenMesh, open a Terminal window and enter following commands in OpenMesh's root directory:<br><br>
|
||||
<tt>
|
||||
qmake -macx ## Generates the appropriate Makefiles<br>
|
||||
make release ## Builds the project (use 'make debug' to build debug version)<br>
|
||||
sudo make install ## Install OpenMesh (as root)
|
||||
</tt>
|
||||
|
||||
|
||||
**/
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
82
Doc/namespaces.docu
Normal file
@@ -0,0 +1,82 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// Documents all used namespaces for doxygen
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
/** \namespace OpenMesh::Concepts
|
||||
Descriptions of the concepts used in OpenMesh.
|
||||
*/
|
||||
|
||||
|
||||
/** \namespace OpenMesh
|
||||
Contains all the mesh ingredients like the polygonal mesh,
|
||||
the triangle mesh, different mesh kernels and mesh traits.
|
||||
**/
|
||||
|
||||
|
||||
/** \namespace OpenMesh::Iterators
|
||||
Contains all mesh iterators and circulators. The two classes
|
||||
OpenMesh::Concepts::IteratorT and OpenMesh::Concepts::CirculatorT describe
|
||||
the interfaces provided by all iterators and circulators, respectively.
|
||||
|
||||
All iterators/circulators defined in this namespace are template classes
|
||||
that require a mesh a template parameter. Therefore you should use
|
||||
the iterators/circulators that are defined by the mesh itself. See
|
||||
OpenMesh::Mesh::PolyMeshT for a complete list of them.
|
||||
|
||||
\see The mesh docu section \ref mesh_iterators for a more detailed
|
||||
description.
|
||||
\see OpenMesh::Concepts::IteratorT
|
||||
\see OpenMesh::Concepts::CirculatorT
|
||||
*/
|
||||
|
||||
|
||||
/** \namespace OpenMesh::IO
|
||||
This namespace contains functions for reading and writing polygonal
|
||||
meshes and a list of supported file formats.
|
||||
*/
|
||||
|
||||
|
||||
/** \namespace OpenMesh::GenProg
|
||||
Utilities for generative programming.
|
||||
*/
|
||||
|
||||
|
||||
/** \namespace OpenMesh::Attributes
|
||||
This namespace holds per item attributes like normal/color.
|
||||
There are some macros provided for convenience, see Attributes.hh.
|
||||
\see Attributes.hh
|
||||
*/
|
||||
|
||||
|
||||
/** \namespace OpenMesh::Kernel_OSG
|
||||
In this namespace resides the OpenSG integration of OpenMesh.
|
||||
Here you find the class
|
||||
OpenMesh::OSG_Kernel::TriMesh_OSGArrayKernelT<> and the
|
||||
template function OpenMesh::OSG_Kernel::bindT<> to link such a
|
||||
mesh with a OpenSG Geometry. */
|
||||
|
||||
|
||||
/** \namespace OpenMesh::Decimater
|
||||
Software related to mesh decimation.
|
||||
\see DecimaterT.hh
|
||||
*/
|
||||
|
||||
|
||||
/** \namespace OpenMesh::Subdivider::Adaptive
|
||||
* Software related to adaptive subdivision of meshes.
|
||||
*/
|
||||
|
||||
/** \namespace OpenMesh::Subdivider::Uniform
|
||||
* Software related to uniform subdivision of meshes.
|
||||
*/
|
||||
|
||||
/** \namespace OpenMesh::VDPM
|
||||
* Software related to view dependent progressive meshes.
|
||||
*/
|
||||
|
||||
/** \namespace OpenMesh::Utils
|
||||
* Collection of little utility classes and helpers.
|
||||
*/
|
||||
17
Doc/subdivider.docu
Normal file
@@ -0,0 +1,17 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/** \page subdivider_docu Sudivision Tools
|
||||
|
||||
The %OpenMesh library provides a few tools for uniform and adaptive
|
||||
subdivision:
|
||||
|
||||
-# Uniform subdivision
|
||||
-# OpenMesh::Subdivider::Uniform::LoopT
|
||||
-# OpenMesh::Subdivider::Uniform::Sqrt3T
|
||||
-# OpenMesh::Subdivider::Uniform::CompositeT
|
||||
-# Adaptive subdivision
|
||||
-# OpenMesh::Subdivider::Adaptive::CompositeT
|
||||
|
||||
*/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
13
Doc/tools.docu
Normal file
@@ -0,0 +1,13 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/** \page tools_docu OpenMesh Tools Documentation
|
||||
|
||||
- \ref decimater_docu
|
||||
- \ref subdivider_docu
|
||||
- \ref vdpm_docu
|
||||
- Miscellaneous
|
||||
- \ref OpenMesh::StripifierT
|
||||
|
||||
*/
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
64
Doc/tutorial_01.docu
Normal file
@@ -0,0 +1,64 @@
|
||||
/** \page tutorial_01 First Steps
|
||||
|
||||
This small example shows:
|
||||
\li How to declare your type \c MyMesh,
|
||||
\li How to add vertices and faces to a mesh,
|
||||
\li How to write a mesh using the IO functions.
|
||||
|
||||
For each program the first step is to define your type \c
|
||||
MyMesh. %OpenMesh supports general polygonal meshes (faces are polygons
|
||||
with varying number of vertices) as well as specialized triangle
|
||||
meshes (all faces are triangles). In this example we want to build a
|
||||
cube from six quadrangles, therefore we choose the polygonal mesh.
|
||||
|
||||
%OpenMesh also supports different mesh kernels, specifying how all the
|
||||
vertices, edges, and faces are stored internally (see also \ref
|
||||
mesh_kernels_group). However, the storage must provide an array like interface.
|
||||
For the tutorial we use the supplied ArrayKernel. The predefined
|
||||
combinations of TriMesh/PolyMesh and the kernel are
|
||||
contained in \c %OpenMesh/Core/Mesh/Types/, we use the
|
||||
<tt>PolyMesh_ArrayKernelT</tt>.
|
||||
|
||||
\dontinclude build_cube.cc
|
||||
\skipline PolyMesh_ArrayKernel
|
||||
\skipline MyMesh
|
||||
|
||||
Now since we have declared our type \c MyMesh, we only have to add 8
|
||||
vertices and 6 quadrangles to build a cube. Adding a vertex is done
|
||||
using the <tt>add_vertex</tt> method. It gets a coordinate and returns
|
||||
a handle to the inserted vertex. We store all handles in an array,
|
||||
since we need them for specifying the faces.
|
||||
|
||||
\skipline vhandle[0]
|
||||
\until vhandle[3]
|
||||
|
||||
<br>In order to add a face to the mesh, we have to build a vector holding
|
||||
the handles to the face's vertices. This vector is passed to the
|
||||
\c add_face method. The following block will create a face from the first
|
||||
four vertices:
|
||||
|
||||
\skipline face_vhandles
|
||||
\until add_face
|
||||
|
||||
<br>The orientation of the face is defined by the order in which the
|
||||
vertices are given: If you look at the frontfacing side of the
|
||||
polygon, then the vertices are in counter-clockwise order.
|
||||
|
||||
After creating all of the six faces, we want to write the resulting
|
||||
mesh to standard output. %OpenMesh provides some basic input/output
|
||||
methods in the namespace OpenMesh::IO:
|
||||
|
||||
\skipline write_
|
||||
|
||||
<br>To use the IO facility of %OpenMesh make sure that the include MeshIO.hh is
|
||||
included first.
|
||||
|
||||
\dontinclude build_cube.cc
|
||||
\skipline MeshIO
|
||||
\until PolyMesh_ArrayKernel
|
||||
|
||||
<br>The complete source looks like this:
|
||||
|
||||
\include build_cube.cc
|
||||
|
||||
**/
|
||||
62
Doc/tutorial_02.docu
Normal file
@@ -0,0 +1,62 @@
|
||||
/** \page tutorial_02 Using iterators and circulators
|
||||
|
||||
This examples shows:
|
||||
|
||||
- How to use iterators,
|
||||
- How to use circulators.
|
||||
|
||||
This example is the first version of the simple mesh smoother. Here we
|
||||
will introduce \em iterators and \em circulators. These two concepts
|
||||
provide functionality to linearly enumerate e.g. all vertices of a
|
||||
mesh, and to circulate around a vertex, i.e. to enumerate all its
|
||||
one-ring neighbors. For a more detailed description, see \ref
|
||||
mesh_iterators.
|
||||
|
||||
First we have to define the mesh type we want to use. This time we use
|
||||
a triangle mesh instead of a polygonal mesh:
|
||||
|
||||
\dontinclude 02-iterators/smooth.cc
|
||||
\skipline TriMesh_ArrayKernel
|
||||
\skipline MyMesh
|
||||
|
||||
<br>We read the mesh to be smoothed from a file:
|
||||
|
||||
\skipline read_mesh
|
||||
|
||||
<br>One smoothing iteration is done in two steps:
|
||||
<ol>
|
||||
<li>For each vertex: calculate the barycenter of its one-ring neighbors.</li>
|
||||
<li>For each vertex: move the vertex to the computed barycenter.</li>
|
||||
</ol>
|
||||
|
||||
This can easily be implemented using vertex iterators. The mesh
|
||||
provides begin and end iterators by <tt>vertices_begin()</tt> and
|
||||
<tt>vertices_end()</tt>.
|
||||
|
||||
\skipline VertexIter
|
||||
\skipline v_it!=v_end
|
||||
|
||||
<br>For calculating the barycenter, we have to iterate through the
|
||||
one-ring neighborhood of the current vertex. This functionality
|
||||
is provided by the <tt>VertexVertexIter</tt>:
|
||||
|
||||
\dontinclude 02-iterators/smooth.cc
|
||||
\skipline VertexVertexIter
|
||||
\skipline vv_it=
|
||||
|
||||
<br>Now we can calculate the barycenters for each vertex and store them in
|
||||
the array <tt>cogs</tt>:
|
||||
|
||||
\dontinclude 02-iterators/smooth.cc
|
||||
\skipline std::vector
|
||||
\skipline v_it=
|
||||
\until cogs.push_back
|
||||
\until }
|
||||
|
||||
<br>After we have calculated the barycenters all that is left to do is to
|
||||
move the vertices to the corresponding barycenters. The complete source
|
||||
code is listed below.
|
||||
|
||||
\include 02-iterators/smooth.cc
|
||||
|
||||
**/
|
||||
54
Doc/tutorial_03.docu
Normal file
@@ -0,0 +1,54 @@
|
||||
/** \page tutorial_03 Using (custom) properties
|
||||
|
||||
This examples shows:
|
||||
- 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'
|
||||
neighborhood and stored it in an array. It would be more convenient
|
||||
and less error-prone if we could store this data in the mesh and
|
||||
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(..), 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.
|
||||
|
||||
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:
|
||||
|
||||
\dontinclude 03-properties/smooth.cc
|
||||
\skipline vertex property stores
|
||||
\until mesh.add
|
||||
|
||||
<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.
|
||||
|
||||
Once the wanted property is registered we can use the property to
|
||||
calculate the barycenter of the neighborhood of each vertex \c v_it
|
||||
|
||||
\dontinclude 03-properties/smooth.cc
|
||||
\skipline vv_it=
|
||||
\until }
|
||||
\until mesh.prop
|
||||
|
||||
<br>and finally set the new position for each vertex \c v_it
|
||||
|
||||
\dontinclude 03-properties/smooth.cc
|
||||
\skipline mesh.set_point
|
||||
|
||||
<br>Below is the complete source code:
|
||||
|
||||
\include 03-properties/smooth.cc
|
||||
|
||||
*/
|
||||
50
Doc/tutorial_04.docu
Normal file
@@ -0,0 +1,50 @@
|
||||
/** \page tutorial_04 Using STL algorithms
|
||||
|
||||
Since the %OpenMesh iterators are (almost) conformant to STL iterators,
|
||||
one can apply the STL algorithms on meshes. The following example
|
||||
shows how to use the STL \c for_each construct, since it is
|
||||
easier to read and may be more efficient than hand-written loops.
|
||||
|
||||
We will define a class which provides the smoothing algorithm, hence
|
||||
define a reusable component. The class must be template class because there
|
||||
is no such thing as a class %OpenMesh, but many different types of %OpenMesh:
|
||||
|
||||
\dontinclude 04-stl_algorithms/smooth_algo.hh
|
||||
\skipline template
|
||||
|
||||
The class SmootherT has two functors, one that computes the barycenter
|
||||
for a given vertex, and a second that sets the vertex position to the
|
||||
corresponding barycenter. A functor is simply a class with a function
|
||||
<tt>operator()(...)</tt>. The first functor \c ComputeCOG
|
||||
computes the barycenter and store it in a custom vertex property \c
|
||||
cog_:
|
||||
|
||||
\skipline operator
|
||||
\until }
|
||||
\until }
|
||||
|
||||
Note, that \c ComputeCOG needs to have access to the mesh object and
|
||||
the property handle. Here, both are references to member variables of
|
||||
the smoother object.
|
||||
|
||||
The second functor \c class \c SetCOG, which sets the vertex position,
|
||||
is constructed analogical.
|
||||
|
||||
Using these functors and <tt>std::for_each</tt> from the STL
|
||||
the smoothing algorithm can be realized in a member function of
|
||||
\c SmootherT:
|
||||
|
||||
\dontinclude 04-stl_algorithms/smooth_algo.hh
|
||||
\skipline void smooth
|
||||
\until }
|
||||
\until }
|
||||
|
||||
<br>The complete example looks like this:
|
||||
|
||||
\include 04-stl_algorithms/smooth_algo.hh
|
||||
|
||||
<br>and
|
||||
|
||||
\include 04-stl_algorithms/smooth.cc
|
||||
|
||||
*/
|
||||
136
Doc/tutorial_05.docu
Normal file
@@ -0,0 +1,136 @@
|
||||
/** \page tutorial_05 Using standard properties
|
||||
|
||||
This example shows:
|
||||
|
||||
- How to add and remove a standard property,
|
||||
- How to get and set the value of a standard property.
|
||||
|
||||
As we already have seen, we can bind additional data to the mesh
|
||||
entities by means of properties. %OpenMesh provides a set of so-called
|
||||
standard properties. Unlike the custom properties these have some
|
||||
special features and a different interface, which are the matter in this
|
||||
tutorial.
|
||||
|
||||
The following table lists all available standard properties and the suitable
|
||||
entity for which it can be used.
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td>Vertex</td>
|
||||
<td>Face</td>
|
||||
<td>Edge</td>
|
||||
<td>Halfedge</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Color</td>
|
||||
<td>X</td>
|
||||
<td>X</td>
|
||||
<td> </td>
|
||||
<td> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Normal</td>
|
||||
<td>X</td>
|
||||
<td>X</td>
|
||||
<td> </td>
|
||||
<td> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Position <sup> (*) </sup> </td>
|
||||
<td>X</td>
|
||||
<td> </td>
|
||||
<td> </td>
|
||||
<td> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Status</td>
|
||||
<td>X</td>
|
||||
<td>X</td>
|
||||
<td>X</td>
|
||||
<td>X</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>TexCoord</td>
|
||||
<td>X</td>
|
||||
<td> </td>
|
||||
<td> </td>
|
||||
<td> </td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
To add a standard property to an entity simply use the appropriate
|
||||
request method, e.g. \c <20>request_face_normal(). The only exception is
|
||||
the position <sup>(*)</sup>. It cannot be added because it is
|
||||
permanently available, hence it cannot be removed as well.
|
||||
|
||||
In this example we
|
||||
-# add vertex normals to a mesh object
|
||||
-# load a file
|
||||
-# check if the file provides vertex normals and calculate them if not
|
||||
-# move every vertex one unit length along its normal direction
|
||||
-# print the resulting positions to std::cout
|
||||
|
||||
Let's start with adding vertex normals to the mesh:
|
||||
|
||||
\dontinclude 05-std_properties/properties.cc
|
||||
\skipline request_vertex_normals
|
||||
|
||||
In a similar manner we can request the other standard properties. For example
|
||||
the face normals:
|
||||
|
||||
\skipline request_face_normals
|
||||
|
||||
We need them to calculate the vertex normals with \c update_normals(), if the
|
||||
file didn't provide any.
|
||||
|
||||
But we can do more with standard properties. We can verify if the mesh
|
||||
has already the property vertex normals
|
||||
|
||||
\dontinclude 05-std_properties/properties.cc
|
||||
\skipline has_vertex_normals
|
||||
\until }
|
||||
|
||||
And after usage we remove them again
|
||||
|
||||
\skipline release_vertex_normals
|
||||
|
||||
But, what happens if for example the vertex status property has been
|
||||
requested twice? Then the first release does nothing, but the second
|
||||
one will remove it. The standard properties have a reference counter,
|
||||
which is incremented by one for each request and decremented by one
|
||||
for each release. If the counter reaches 0 the property will be
|
||||
removed from memory.
|
||||
|
||||
Now we know how to add and remove standard properties, but how do we
|
||||
access them? Again we need the mesh object. Unlike the custom
|
||||
properties, where we accessed one with the mesh member function \c
|
||||
property(), for each standard property the mesh provides a get and a
|
||||
set method. We have used one pair of get/set methods already in the
|
||||
previous three tutorials, where we computed a new location for the
|
||||
vertex position. Here we move all vertices a unit length along their
|
||||
normal direction:
|
||||
|
||||
\dontinclude 05-std_properties/properties.cc
|
||||
\skipline MyMesh::VertexIter
|
||||
\until {
|
||||
\skipline mesh.set_point
|
||||
\skipline }
|
||||
|
||||
The get-methods take an entity handle and return the value of
|
||||
the desired property, and the set-methods require an additional
|
||||
parameter to pass the new value to the property. According to the
|
||||
table not every pair of get/set-methods apply to every entity. For
|
||||
example a face has normally no texture coordinates, hence a call to \c
|
||||
mesh.texcoord( _face_handle ) will result in an error when compiling
|
||||
the code.
|
||||
|
||||
Since we know how to add/remove/access standard properties, one further
|
||||
question remains. What data types do they have? And are there more hidden
|
||||
secrets? The next tutorial (\ref tutorial_06) will give the answer.
|
||||
|
||||
The complete source looks like this:
|
||||
|
||||
\include 05-std_properties/properties.cc
|
||||
|
||||
*/
|
||||
74
Doc/tutorial_06.docu
Normal file
@@ -0,0 +1,74 @@
|
||||
/** \page tutorial_06 Using mesh attributes and traits
|
||||
|
||||
this example shows how to change the data type for positions, normals, colors, and texture,
|
||||
|
||||
In the previous tutorial (\ref tutorial_05) we learned to use standard
|
||||
properties by calling the appropriate \c request method.
|
||||
Unlike the custom properties, where the user specifies the
|
||||
data type by passing the type to the handle (e.g. \c
|
||||
MyMesh::FPropHandleT< <b>int</b>>), the data types of the standard
|
||||
properties are defined by so-called mesh traits. With traits we can
|
||||
customize and extend the mesh data structure. We can do this by
|
||||
changing two important features
|
||||
|
||||
-# changing data type for positions, normals, colors, and texture
|
||||
coordinates
|
||||
-# extend mesh entities Vertex, Face, Edge, and Halfedge
|
||||
(see tutorial '\ref tutorial_07')
|
||||
|
||||
Let's start. Every custom traits should derive from the default traits
|
||||
|
||||
\dontinclude 06-attributes/attributes.cc
|
||||
\skipline struct MyTraits
|
||||
|
||||
As mentioned, we can change the basic data types for the basic types
|
||||
\c MyMesh::Point, \c MyMesh::Normal, \c MyMesh::Color, and \c MyMesh::TexCoord.
|
||||
We can use the provided vector class or we use a
|
||||
different one from another library. Here we simply replace the default
|
||||
type \c OpenMesh::Vec3f (defined in the \c OpenMesh::DefaultTraits)
|
||||
for positions and normals with \c OpenMesh::Vec3d
|
||||
|
||||
\skipline Vec3d
|
||||
\skipline Vec3d
|
||||
|
||||
(In general it's better to have the same scalar type for the point and
|
||||
normal vector, for instance \c double in this case. Otherwise we have
|
||||
to cast quite a lot depending on the implementation of the vector class.)
|
||||
|
||||
Be aware that these settings overwrite the ones of the parent traits
|
||||
class! As we usually derive from the DefaultTraits let's have a close look.
|
||||
|
||||
Actually the struct \c OpenMesh::DefaultTraits is merely empty. It solely
|
||||
defines the types for \c Point, \c Normal, \c TexCoord, and \c Color
|
||||
and one attribute, that we used implicitly all the time:
|
||||
|
||||
\skipline HalfedgeAttributes
|
||||
|
||||
The attribute \c PrevHalfedge is different, as it does not control a
|
||||
property. Yet it has a great impact on the resulting mesh type, as it
|
||||
adds additional information to the halfedge structure. The impact
|
||||
is twofold:
|
||||
|
||||
-# fast access to previous halfedge
|
||||
-# increase of memory consumption
|
||||
|
||||
Using this feature depends highly on our needs. One situation where
|
||||
the previous halfedges are quite handy, is the mesh member function
|
||||
add_face(). The execution time for the member function drops
|
||||
dramatically, when the information about the previous halfedge is
|
||||
available. Usually we want to have this information. But if not, because we
|
||||
must save memory, we can easily remove it with
|
||||
|
||||
\skipline HalfedgeAttributes
|
||||
|
||||
Then we need 8 bytes less per edge, which can be quite a lot as one can
|
||||
derive from the Euler formula <b style="background-color:#FFFFFF;">(\f$V-E+F=2 (1-g)\f$)</b>, that for a regular
|
||||
triangle meshes with genus <b style="background-color:#FFFFFF;">\f$g=0\f$</b> the number of edges
|
||||
<b style="background-color:#FFFFFF;">\f$E\f$</b> is approximately
|
||||
three times the number of vertices <b style="background-color:#FFFFFF;">\f$V\f$: \f$ E \approx 3 \cdot V\f$</b>.
|
||||
|
||||
The complete source looks like this:
|
||||
|
||||
\include 06-attributes/attributes.cc
|
||||
|
||||
*/
|
||||
46
Doc/tutorial_07.docu
Normal file
@@ -0,0 +1,46 @@
|
||||
/** \page tutorial_07 Extending the mesh using traits
|
||||
|
||||
This examples shows:
|
||||
|
||||
- How to extend the behaviour of entities using traits.
|
||||
|
||||
In the previous tutorial we used attributes and changed the type of
|
||||
the data types \c Point, \c Normal, \c TexCoord, and \c Color. But we
|
||||
can do even more with traits. We can change the behaviour of the mesh
|
||||
entities \c Vertex, \c Face, \c Edge, and \c Halfedge.
|
||||
|
||||
One goal in the design was a highly customizable data structure. Using
|
||||
the traits technique makes it possible. We pick up the smoother again
|
||||
and show an alternative way to implement it. Now we place the necessary
|
||||
data and the functions in the vertex itself
|
||||
|
||||
\dontinclude 07-traits/smooth.cc
|
||||
\skipline MyTraits
|
||||
\until };
|
||||
\until };
|
||||
|
||||
Note the definition of the vertex entity. We use the supplied define
|
||||
\c VertexTraits (which resolves in a rather inconvenient template
|
||||
definition). Similary we can use the defines \c FaceTraits, \c
|
||||
EdgeTraits, and \c HalfedgeTraits to extend these entities. Now we
|
||||
enhanced the vertex, with the additional member variable \c cog_, and
|
||||
the get/set-method pair to access the new member.
|
||||
|
||||
As before we compute in a first loop the barycenters for all vertices
|
||||
and store the information at the vertices
|
||||
|
||||
\skipline v_it->set_cog
|
||||
|
||||
In the second pass we set the new position of each vertex
|
||||
|
||||
\skipline set_point
|
||||
|
||||
It looks neat, but on the other hand we can't remove the data anymore
|
||||
as we could do with properties! By using traits one creates a 'static'
|
||||
configuration, which can't be changed during runtime.
|
||||
|
||||
The complete source looks like this:
|
||||
|
||||
\include 07-traits/smooth.cc
|
||||
|
||||
*/
|
||||
121
Doc/tutorial_08.docu
Normal file
@@ -0,0 +1,121 @@
|
||||
/** \page tutorial_08 Using IO::Options
|
||||
|
||||
This example shows:
|
||||
|
||||
- How to control the behaviour of \c Mesh::IO::read_mesh(),
|
||||
- How to control the behaviour of \c Mesh::IO::write_mesh().
|
||||
|
||||
The class \c OpenMesh::IO::Options can be used when reading/writing a
|
||||
mesh. It controls the behaviour of the reader/writer modules by means
|
||||
of enabled/disabled bits in a bitset. The class provides an interface
|
||||
for enabling, disabling and verifying the bits in the set. We
|
||||
distinguish between
|
||||
|
||||
-# mode bits - control binary reading/writing
|
||||
- Options::Binary
|
||||
- Options::MSB
|
||||
- Options::LSB
|
||||
- Options::Swap (MSB|LSB)
|
||||
-# property bits - controls which standard properties to read/write
|
||||
- Options::VertexNormal
|
||||
- Options::VertexTexCoord
|
||||
- Options::VertexColor
|
||||
- Options::FaceNormal
|
||||
- Options::FaceColor
|
||||
|
||||
These bits have different effects when reading or writing. The file
|
||||
format itself is selected by the extension of the filename. The IO
|
||||
subsystem of the %OpenMesh library supports currently four
|
||||
formats. The following table list all formats and indicates whether
|
||||
the format supports ASCII/binary storage with the apropiate extension.
|
||||
|
||||
<table border=0>
|
||||
<tr>
|
||||
<td>Format</td><td colspan=2>Ascii</td><td>Binary</td>
|
||||
</tr><tr>
|
||||
<td>OFF</td><td>.off</td><td>.off</td>
|
||||
</tr><tr>
|
||||
<td>OBJ</td><td>.obj</td><td></td>
|
||||
</tr><tr>
|
||||
<td>STL</td><td>.stla, .stl</td><td>.stlb, .stl</td>
|
||||
</tr><tr>
|
||||
<td>OM</td><td></td><td>.om</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
The program does not more than providing a command line based
|
||||
interface to select the option bits for reading/writing and to request
|
||||
mesh properties. Hence illegal combinations are possible and will
|
||||
result in a failure of the program. (The input file won't be damaged
|
||||
in this case, but be careful where you put the ouput file!)
|
||||
|
||||
<h5>Reading meshes</h5>
|
||||
|
||||
When reading a file the mode bits are used to give the reader an
|
||||
advice or hint. Depending on the format we can help the reader to
|
||||
interpret the data correctly. First of all we can tell it that the
|
||||
file contains binary data.
|
||||
|
||||
\dontinclude 08-io_options/io_options.cc
|
||||
\skipline ropt += IO::Options::Binary
|
||||
|
||||
Further on we can ask the reader two swap the byte-order.
|
||||
|
||||
\skipline ropt += IO::Options::Swap
|
||||
|
||||
(Both can be done via the command line with the options -b and -s,
|
||||
respectively.)
|
||||
|
||||
By default the geometry and the topology is restored from the
|
||||
file. The file might contain more, especially it could provide normals
|
||||
or texture coordinates. We can examine the property bits after
|
||||
reading to find out what else is available:
|
||||
|
||||
\dontinclude 08-io_options/io_options.cc
|
||||
\skipline ropt.check(IO::Options::VertexNormal)
|
||||
|
||||
If a property bit is set it does not mean, that it has been restored
|
||||
as well. The property must have been requested prior reading the
|
||||
file. (The demo program offers the command line option \c -Xv[nct] and
|
||||
\c -Xf[nc] to request vertex and face properties.)
|
||||
|
||||
<h5>Writing meshes</h5>
|
||||
|
||||
When writing the mesh the mode bits apparently control whether to use
|
||||
the binary variant and the desired byte-ordering. For example, if we
|
||||
choose binary mode and want to swap the byte order, we set
|
||||
|
||||
\skipline wopt += IO::Options::Binary
|
||||
\skipline wopt += IO::Options::Swap
|
||||
|
||||
If the format does not specify the byte order the system byte order is
|
||||
used. If the format does not support binary storage, the mode bits are
|
||||
ignored.
|
||||
|
||||
If the format supports storing additional information, which are
|
||||
conform with the standard properties, we can use the property bits to
|
||||
tell the writer what we would like to have stored. If we would like to
|
||||
store the vertex normals we simply set
|
||||
|
||||
\skipline wopt += IO::Options::VertexNormal
|
||||
|
||||
Finally we can write the data to the file
|
||||
|
||||
\dontinclude 08-io_options/io_options.cc
|
||||
\skipline write_mesh
|
||||
|
||||
The method returns false on error, which might have three different reasons:
|
||||
|
||||
-# the option is not supported by the choosen format
|
||||
-# a selected standard property is not available
|
||||
-# a 'system' error like
|
||||
- could not open the file due to access rights
|
||||
- disk space exhausted during write
|
||||
- ...
|
||||
|
||||
|
||||
The complete source looks like this:
|
||||
|
||||
\include 08-io_options/io_options.cc
|
||||
|
||||
*/
|
||||
186
Doc/tutorial_09.docu
Normal file
@@ -0,0 +1,186 @@
|
||||
/** \page tutorial_09 Storing custom properties
|
||||
|
||||
The %OpenMesh' proprietary OM format allows to store and restore
|
||||
custom properties along with the standard properties. For it we have
|
||||
to use named custom properties like the following one
|
||||
|
||||
\dontinclude 09-persistence/persistence.cc
|
||||
\skipline VPropHandleT
|
||||
\skipline mesh.add_property
|
||||
|
||||
Here we registered a float property for the vertices at the mesh with
|
||||
name "vprop_float". The name of a property, that we want to make
|
||||
persistent, must follow a few rules
|
||||
|
||||
-# max. 256 characters long
|
||||
-# The prefixes \c "v:", \c "h:", \c "e:", \c "f:" and \c "m:" are reserved.
|
||||
|
||||
If we stick to this rules we are fine. Furthermore we have to
|
||||
consider, that the names are handled case-sensitive.
|
||||
|
||||
To actually make a custom property persistent we have to set the
|
||||
persistent flag in the property with
|
||||
|
||||
\skipline mesh.property(vprop_float).set_persistent
|
||||
|
||||
Now we can use \c IO::mesh_write() to write the mesh to a file on
|
||||
disk. The custom properties are added after the standard properties
|
||||
in the file, with the name and it's binary size. These two pieces of
|
||||
information are evaluated when reading the file again. To successfully
|
||||
restore the custom properties, the mesh must have registered named
|
||||
properties with equal names (case-sensitive compare). Additionally,
|
||||
when reading the data, the number of bytes read for a property must
|
||||
match the provided number in the file. If the OM reader did not find a
|
||||
suitable named property, it will simply skip it. If the number of bytes
|
||||
do not match, the complete restore will be terminated and \c
|
||||
IO::read_mesh() will return \c false. And if the data cannot be
|
||||
restored, because the appropriate restore method is not available the
|
||||
exception std::logic_error() will be thrown.
|
||||
|
||||
Since we now know the behaviour, we need to know what kind of data can
|
||||
we store? Without any further effort, simply using named properties
|
||||
and setting the persistent flag, we can store following types
|
||||
|
||||
- bool, stored as a bitset
|
||||
- all other fundamental types except long double, (unsigned) long and size_t
|
||||
- std::string, each up to 65536 characters long
|
||||
- OpenMesh::Vec[1,2,3,4,6][c,uc,s,us,i,ui,f,d]
|
||||
|
||||
For further reading we call these types basic types. Apparently we
|
||||
cannot store non-basic types, which are
|
||||
|
||||
- pointers
|
||||
- structs/classes
|
||||
- even more complex data structures, like container of containers.
|
||||
|
||||
However there is a way to store custom types ( else we could not store
|
||||
std::string). Let's start with an more simple custom data. For
|
||||
instance we have a struct \c MyData like this
|
||||
|
||||
\dontinclude 09-persistence/persistence.cc
|
||||
\skipline struct MyData
|
||||
\until vec4fval
|
||||
\skipline };
|
||||
|
||||
Here we keep an int, bool, double value and a vector of 4 floats, which
|
||||
are all basic types. Then we need to specialize the template struct
|
||||
OpenMesh::IO::binary<> within the namespace \c OpenMesh::IO
|
||||
|
||||
\skipline binary<MyData>
|
||||
|
||||
Remember not to use long double, (unsigned) long and size_t as basic types
|
||||
because of inconsistencies between 32/64bit architectures.
|
||||
|
||||
Herein we have to implement the following set of static member
|
||||
variables and functions:
|
||||
|
||||
\skipline is_streamable
|
||||
\skipline size_of
|
||||
\skipline size_of
|
||||
\skipline store
|
||||
\skipline restore
|
||||
|
||||
The flag \c is_streamable has to be set to \c true. Else the data
|
||||
cannot be stored at all.
|
||||
|
||||
<h5>\c size_of methods </h5>
|
||||
|
||||
Since the size of the custom data can be static, which means we know
|
||||
the size at compile time, or the size of it is dynamic, which means me
|
||||
the size is known at runtime, we have to provide the two \c size_of()
|
||||
methods.
|
||||
|
||||
The first declaration is for the static case, while the second for the
|
||||
dynamic case. Though the static case is more simple, it is not
|
||||
straight forward. We cannot simply use \c sizeof() to determine the
|
||||
data size, because it will return the number ob bytes it needs in
|
||||
memory (possible 32bit alignment). Instead we need the binary size,
|
||||
hence we have to add up the single elements in the struct.
|
||||
|
||||
\dontinclude 09-persistence/persistence.cc
|
||||
\skipline return sizeof
|
||||
|
||||
Actually we would need to sum up the single elements of the vector,
|
||||
but in this case we know for sure the result (4 floats make 16 bytes,
|
||||
which is 32bit aligned therefore \c sizeof() returns the wanted
|
||||
size). But keep in mind, that this a potential location for errors,
|
||||
when writing custom binary support.
|
||||
|
||||
The second declaration is for the dynamic case, where the custom data
|
||||
contains pointers or references. This static member must properly
|
||||
count the data, by disolving the pointers/references, if this data has
|
||||
to be stored as well. In the dynamic stetting the static variant cannot return
|
||||
the size, therefore it must return \c IO::UnknownSize.
|
||||
|
||||
In this case the dynamic variant simply returns the size by calling the static
|
||||
variant, as the sizes are identical for both cases.
|
||||
|
||||
<h5>\c store / \c restore </h5>
|
||||
|
||||
For the dynamic case as for the static case, we have to make up a
|
||||
scheme how we would store the data. One option is to store the length
|
||||
of the data and then store the data itself. For instance the type \c
|
||||
std::string is implemented this way. (We store first the length in a
|
||||
16bit word (=> max. length 65536), then the characters follow. Hence
|
||||
\c size_of() returns 2 bytes for the length plus the actual length of
|
||||
the value \c v.) Since \c MyData contains only basic types we can
|
||||
implement the necessary methods \c store and \c restore, by simply
|
||||
breaking up the data into the basic types using the pre-defined
|
||||
store/restore methods for them:
|
||||
|
||||
\skipline static size_t store
|
||||
\until }
|
||||
\skipline static size_t restore
|
||||
\until }
|
||||
|
||||
It's very important, that the store/restore methods count the
|
||||
written/read bytes correctly and return the value. On error both
|
||||
functions must return 0.
|
||||
|
||||
A more complex situation is given with the following property
|
||||
|
||||
\dontinclude 09-persistence/persistence.cc
|
||||
\skipline MyMap
|
||||
\skipline mprop_map
|
||||
|
||||
In this case the data contains a container, a map from strings to
|
||||
integer numbers. If we want to store this as well, we need to make up
|
||||
a scheme how the map will be stored in a sequential layout. First we
|
||||
store the number of elements in the map. Then, since the map has an
|
||||
iterator, we simply iterate over all elements and store each pair
|
||||
(key/value). This procedure is equal for the \c size_of(), \c store(), and \c
|
||||
restore() methods. For example the \c size_of() methods look like this
|
||||
|
||||
\dontinclude 09-persistence/persistence.cc
|
||||
\skip binary< MyMap >
|
||||
\skipline static size_t size_of
|
||||
\skipline static size_t size_of
|
||||
\until }
|
||||
\until }
|
||||
|
||||
The implementation of \c store() and \c restore() follow a similar pattern.
|
||||
|
||||
The given example program does the following steps
|
||||
|
||||
-# Create a mesh and generate a cube
|
||||
-# Add a few custom properties
|
||||
-# Fill them with test data
|
||||
-# Make the properties persistent
|
||||
-# Store mesh in a file named 'persistent-check.om'
|
||||
-# Clear the mesh
|
||||
-# Restore mesh
|
||||
-# Check the content on equality with the test data.
|
||||
|
||||
Since the example is a little bit longer than usual the source is in
|
||||
several files. The main program is in \c persistence.cc, the cube
|
||||
generator in \c generate_cube.hh, \c stats.hh provides little tools to
|
||||
display information about the mesh and the properties, the file \c
|
||||
fill_props.hh providing the test data, and \c int2roman.hh/.cc, which
|
||||
is used in fill_props.hh. All necessary parts are in \c
|
||||
persistence.cc, which is displayed in full length below. For the other
|
||||
files please have a look in the directory \c
|
||||
OpenMesh/Doc/Tutorial/09-persistence/.
|
||||
|
||||
\include 09-persistence/persistence.cc
|
||||
|
||||
*/
|
||||
42
Doc/tutorial_main.docu
Normal file
@@ -0,0 +1,42 @@
|
||||
/** \page tutorial Introduction to OpenMesh (Tutorials)
|
||||
|
||||
The %OpenMesh mesh library is a powerful tool for handling polygonal
|
||||
meshes. Due to its inherent generative structure it allows the user to
|
||||
create mesh types which are custom tailored to the specific needs of
|
||||
the application. The user can either supply his own data structures
|
||||
for representing vertices, edges and faces or he can conveniently use
|
||||
the predefined structures of %OpenMesh.
|
||||
Additionally %OpenMesh offers dynamic properties allowing the user to attach
|
||||
and detach data to the mesh during runtime.
|
||||
|
||||
This document is supposed to introduce the basic concepts of
|
||||
%OpenMesh. <!--For detailed information, consult the online documentation
|
||||
(\ref mesh_docu).-->
|
||||
|
||||
In this tutorial we will introduce the %OpenMesh library by means of
|
||||
simple examples. The first one just builds a polygonal mesh
|
||||
representing a cube and writes the result to standard output. The
|
||||
following examples develop a simple mesh smoother: Recall that the
|
||||
immediate neighbors of a vertex are called the 1-ring of this
|
||||
vertex. It is well known that a polygonal mesh can be smoothed by
|
||||
repeatedly replacing each vertex' position by the center of gravity
|
||||
(cog) of its 1-ring. The basic smoother will
|
||||
|
||||
\li read a polygonal mesh from standard input,
|
||||
\li compute the cog of the 1-ring of each vertex,
|
||||
\li replace each vertex' position by its cog and finally,
|
||||
\li write the mesh to standard output.
|
||||
|
||||
<ol>
|
||||
<li> \ref tutorial_01
|
||||
<li> \ref tutorial_02
|
||||
<li> \ref tutorial_03
|
||||
<li> \ref tutorial_04
|
||||
<li> \ref tutorial_05
|
||||
<li> \ref tutorial_06
|
||||
<li> \ref tutorial_07
|
||||
<li> \ref tutorial_08
|
||||
<li> \ref tutorial_09
|
||||
</ol>
|
||||
|
||||
*/
|
||||
18
Doc/vdpm.docu
Normal file
@@ -0,0 +1,18 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/** \page vdpm_docu View Dependent Progressive Meshes
|
||||
|
||||
The VDPM software is based on <a
|
||||
href="http://www.postech.ac.kr/~leesy/ftp/gi01.pdf">"Truly Selective
|
||||
Refinement of Progressive Meshes", J. Kim and S. Lee, In
|
||||
Proc. Graphics Interface 2001</a>.
|
||||
|
||||
The library is located in \c %OpenMesh/Tools/VDPM/ and in
|
||||
\c %OpenMesh/Apps/VDProgMesh/ are demo applications:
|
||||
-# \c mkbalancedpm creates balanced progressive meshes
|
||||
-# \c vdpmanalyzer takes a progressive mesh and generates a view dependent
|
||||
progressive mesh.
|
||||
-# \c vdpmsynthezier is viewer for vdpm meshes.
|
||||
|
||||
\todo Complete VDPM documentation.
|
||||
*/
|
||||