初始化内容

This commit is contained in:
2026-09-16 14:07:40 +08:00
parent 6934b390bf
commit 4f643c1e7c
18350 changed files with 6088489 additions and 305 deletions
+4
View File
@@ -0,0 +1,4 @@
The changelog can be found in the html Documentation.
The latest changelog for the master can be found here:
http://openmesh.org/Daily-Builds/Doc/
+205
View File
@@ -0,0 +1,205 @@
cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR)
# Set and enforce C++-11 flags
#set( CMAKE_CXX_STANDARD_REQUIRED TRUE )
#set( CMAKE_CXX_STANDARD 11 )
enable_testing()
project (OpenMesh
VERSION 11.0.0
LANGUAGES C CXX )
# Set AUTO UIC/MOC Policy to new for CMAKE 3.17 or higher
if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.17")
cmake_policy(SET CMP0100 NEW)
endif()
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "6.0" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "4.9" OR CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL "4.9")
message(WARNING "Your version of GCC contains an optimizer bug. Please verify that you do not use -O3!")
string(REPLACE "-O3" "-O2" CMAKE_CXX_FLAGS_RELEASE_NEW "${CMAKE_CXX_FLAGS_RELEASE}")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE_NEW}" CACHE STRING "" FORCE)
endif()
endif()
if ( WIN32 )
# This is the base directory for windows library search used in the finders we ship.
set(CMAKE_WINDOWS_LIBS_DIR "c:/libs" CACHE STRING "Default Library search dir on windows." )
endif()
if (NOT WIN32 AND NOT CMAKE_BUILD_TYPE)
message(STATUS "No build type selected, default to Release")
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." FORCE)
endif()
# add our macro directory to cmake search path
set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake ${CMAKE_CURRENT_SOURCE_DIR}/cmake ${CMAKE_CURRENT_SOURCE_DIR}/cmake-library/finders ${CMAKE_CURRENT_SOURCE_DIR}/cmake-library/VCI )
set (CMAKE_DEBUG_POSTFIX "d")
# include our cmake files
include (VCICommon)
# Disable package building when built as an external library
if(${CMAKE_PROJECT_NAME} MATCHES "OpenMesh")
include(OpenMeshPackage)
endif()
include (VCIOutput)
include(VCIQt)
# ========================================================================
# Definitions
# ========================================================================
if (WIN32)
add_definitions(
-D_USE_MATH_DEFINES -DNOMINMAX
-D_CRT_SECURE_NO_WARNINGS
)
endif ()
set(NO_DECREMENT_DEPRECATED_WARNINGS OFF CACHE BOOL "Disables all deprecated warnings warning about decrement operations on normal circulators.")
if(NO_DECREMENT_DEPRECATED_WARNINGS)
add_definitions( -DNO_DECREMENT_DEPRECATED_WARNINGS )
endif()
# ========================================================================
# Windows build style control
# ========================================================================
if ( WIN32 )
if ( NOT DEFINED OPENMESH_BUILD_SHARED )
set( OPENMESH_BUILD_SHARED false CACHE BOOL "Build as shared library(DLL)?" )
endif()
endif()
# ========================================================================
# Add bundle targets here
# ========================================================================
if ( NOT DEFINED BUILD_APPS )
set( BUILD_APPS true CACHE BOOL "Enable or disable building of apps" )
endif()
# Only call fixbundle, when we are building OpenMesh standalone
if( (${CMAKE_PROJECT_NAME} MATCHES "OpenMesh") AND BUILD_APPS )
if (WIN32)
if ( NOT "${CMAKE_GENERATOR}" MATCHES "MinGW Makefiles" AND BUILD_APPS )
add_custom_target (fixbundle ALL
COMMAND ${CMAKE_COMMAND} -P "${CMAKE_BINARY_DIR}/fixbundle.win.cmake" )
endif()
endif()
if (APPLE)
add_custom_target (fixbundle ALL
COMMAND ${CMAKE_COMMAND} -P "${CMAKE_BINARY_DIR}/fixbundle.cmake"
)
endif()
endif() # project OpenMesh
# ========================================================================
# Call the subdirectories with there projects
# ========================================================================
add_subdirectory (src/OpenMesh/Core)
add_subdirectory (src/OpenMesh/Tools)
add_subdirectory (src/OpenMesh/Apps)
set(OPENMESH_BENCHMARK_DIR CACHE PATH "Source path of benchmark (https://github.com/google/benchmark).")
if (OPENMESH_BENCHMARK_DIR)
add_subdirectory(${OPENMESH_BENCHMARK_DIR} benchmark)
add_subdirectory(src/Benchmark)
endif()
# Do not build unit tests when build as external library
if(${CMAKE_PROJECT_NAME} MATCHES "OpenMesh")
add_subdirectory (src/Unittests)
else()
# If built as a dependent project simulate effects of
# successful finder run:
set (OPENMESH_FOUND true PARENT_SCOPE)
set (OPENMESH_LIBRARIES OpenMeshCore OpenMeshTools PARENT_SCOPE)
set (OPENMESH_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src" PARENT_SCOPE)
set (OPENMESH_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/src" PARENT_SCOPE)
# Also define variables provided by the old legacy finder.
set (OPENMESH_CORE_LIBRARY OpenMeshCore PARENT_SCOPE)
set (OPENMESH_TOOLS_LIBRARY OpenMeshTools PARENT_SCOPE)
set (OPENMESH_TOOLS_LIBRARY OpenMeshTools PARENT_SCOPE)
set (OPENMESH_LIBRARY OpenMeshCore OpenMeshTools PARENT_SCOPE)
get_target_property(_OPENMESH_LIBRARY_DIR OpenMeshCore LIBRARY_OUTPUT_DIRECTORY)
set (OPENMESH_LIBRARY_DIR "${_OPENMESH_LIBRARY_DIR}" CACHE PATH "The directory where the OpenMesh libraries can be found.")
endif()
if ( NOT DEFINED OPENMESH_DOCS )
set( OPENMESH_DOCS true CACHE BOOL "Enable or disable building of documentation" )
endif()
if (OPENMESH_DOCS)
add_subdirectory (Doc)
endif()
# ========================================================================
# Bundle generation (Targets exist, now configure them)
# ========================================================================
# Only call fixbundle, when we are building OpenMesh standalone
if(${CMAKE_PROJECT_NAME} MATCHES "OpenMesh")
if (WIN32 AND BUILD_APPS)
# prepare bundle generation cmake file and add a build target for it
configure_file ("${CMAKE_CURRENT_SOURCE_DIR}/cmake/fixbundle.cmake.win.in"
"${CMAKE_CURRENT_BINARY_DIR}/fixbundle.win.cmake" @ONLY IMMEDIATE)
if ( NOT "${CMAKE_GENERATOR}" MATCHES "MinGW Makefiles" )
# let bundle generation depend on all targets
add_dependencies (fixbundle QtViewer DecimaterGui)
endif()
endif()
# On apple we do a fixbundle, which is only necessary for the apps and not for the libs
if (APPLE AND BUILD_APPS)
# prepare bundle generation cmake file and add a build target for it
configure_file ("${CMAKE_SOURCE_DIR}/cmake/fixbundle.cmake.in"
"${CMAKE_BINARY_DIR}/fixbundle.cmake" @ONLY IMMEDIATE)
# let bundle generation depend on all targets
if (QT_FOUND)
add_dependencies (fixbundle DecimaterGui ProgViewer QtViewer SubdividerGui)
endif()
# Required for Snow leopard, and the latest qt. Then the resources have to be copied
if ( EXISTS "/opt/local/libexec/qt4-mac/lib/QtGui.framework/Versions/4/Resources/qt_menu.nib" )
add_custom_command(TARGET OpenMesh POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory "/opt/local/libexec/qt4-mac/lib/QtGui.framework/Versions/4/Resources/qt_menu.nib"
"${CMAKE_BINARY_DIR}/Build/Libraries/qt_menu.nib" )
endif ()
endif ()
endif()
# ========================================================================
# Generate openmesh.pc file
set(DEST_DIR "${CMAKE_INSTALL_PREFIX}")
set(PRIVATE_LIBS "-lOpenMeshCore -lOpenMeshTools")
configure_file("openmesh.pc.in" "${CMAKE_CURRENT_BINARY_DIR}/openmesh.pc" @ONLY)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/openmesh.pc DESTINATION libdata/pkgconfig)
# generate target file
install(EXPORT OpenMeshConfig DESTINATION share/OpenMesh/cmake)
export(TARGETS OpenMeshCore OpenMeshTools FILE OpenMeshConfig.cmake)
# display results
vci_print_configure_header (OPENMESH "OpenMesh")
+12
View File
@@ -0,0 +1,12 @@
include (VCIDoxygen)
IF (DOXYGEN_FOUND)
# Add a documentation install target
vci_create_doc_target(doc-install)
if (TARGET doc-install)
vci_copy_after_build (doc-install "${CMAKE_BINARY_DIR}/Build/${VCI_PROJECT_DATADIR}/Doc/html" "${CMAKE_INSTALL_PREFIX}/${VCI_PROJECT_DATADIR}/doc/html")
endif()
ENDIF(DOXYGEN_FOUND)
+202
View File
@@ -0,0 +1,202 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
//=============================================================================
//
// 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
//=============================================================================
+588
View File
@@ -0,0 +1,588 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
//=============================================================================
//
// 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( size_t _n_vertices,
size_t _n_edges,
size_t _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.
* The properties will also be removed from the mesh
*/
void clear();
/** Delete all items, i.e. clear all item containers.
* The properties will be kept
*/
void clean();
/** Remove all items that are marked as deleted from the
corresponding containers.
\note All handles (and indices) to any entity (face, vertex,
edge, halfedge) created before garbage collection
will be out of sync with the mesh, do not use them anymore!
See also \ref deletedElements.
\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
size_t n_vertices() const;
/// Returns number of halfedges (should be 2*n_edges())
size_t n_halfedges() const;
/// Returns number of edges
size_t n_edges() const;
/// Returns number of faces
size_t 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 Normal& normal(HalfedgeHandle _heh) const; ///< Get normal of the to vertex of the given Halfedge (per face per vertex normals)
void set_normal(HalfedgeHandle _heh, const Normal& _n); ///< Set normal of the to vertex of the given Halfedge (per face per vertex normals)
const Color& color(VertexHandle _vh) const; ///< Get color
void set_color(VertexHandle _vh, const Color& _c); ///< Set color
const TexCoord1D& texcoord1D(VertexHandle _vh) const; ///< Get texture coordinate.
void set_texcoord1D(VertexHandle _vh, const TexCoord1D& _t); ///< Set texture coordinate.
const TexCoord2D& texcoord2D(VertexHandle _vh) const; ///< Get texture coordinate.
void set_texcoord2D(VertexHandle _vh, const TexCoord2D& _t); ///< Set texture coordinate.
const TexCoord3D& texcoord3D(VertexHandle _vh) const; ///< Get texture coordinate.
void set_texcoord3D(VertexHandle _vh, const TexCoord3D& _t); ///< Set texture coordinate.
const TexCoord1D& texcoord1D(HalfedgeHandle _hh) const; ///< Get texture coordinate of the to vertex for the current face (per face per vertex texcoords)
void set_texcoord1D(HalfedgeHandle _hh, const TexCoord1D& _t); ///< Set texture coordinate of the to vertex of the given Halfedge (per face per vertex texcoords)
const TexCoord2D& texcoord2D(HalfedgeHandle _hh) const; ///< Get texture coordinate of the to vertex for the current face (per face per vertex texcoords)
void set_texcoord2D(HalfedgeHandle _hh, const TexCoord2D& _t); ///< Set texture coordinate of the to vertex of the given Halfedge (per face per vertex texcoords)
const TexCoord3D& texcoord3D(HalfedgeHandle _hh) const; ///< Get texture coordinate of the to vertex for the current face (per face per vertex texcoords)
void set_texcoord3D(HalfedgeHandle _hh, const TexCoord3D& _t); ///< Set texture coordinate of the to vertex of the given Halfedge (per face per vertex texcoords)
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
const Color& color(HalfedgeHandle _heh) const; ///< Get color
void set_color(HalfedgeHandle _heh, const Color& _c); ///< Set color
// edge
const Color& color(EdgeHandle _eh) const; ///< Get color
void set_color(EdgeHandle _eh, const Color& _c); ///< Set color
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_texcoords1D();
void request_vertex_texcoords2D();
void request_vertex_texcoords3D();
void request_vertex_status();
void request_halfedge_status();
void request_halfedge_normals();
void request_halfedge_colors();
void request_halfedge_texcoords1D();
void request_halfedge_texcoords2D();
void request_halfedge_texcoords3D();
void request_edge_status();
void request_edge_colors();
void request_face_normals();
void request_face_colors();
void request_face_status();
void request_face_texture_index();
//@}
/// \name Remove standard properties
//@{
/// Remove property
void release_vertex_normals();
void release_vertex_colors();
void release_vertex_texcoords1D();
void release_vertex_texcoords2D();
void release_vertex_texcoords3D();
void release_vertex_status();
void release_halfedge_status();
void release_halfedge_normals();
void release_halfedge_colors();
void release_halfedge_texcoords1D();
void release_halfedge_texcoords2D();
void release_halfedge_texcoords3D();
void release_edge_status();
void release_edge_colors();
void release_face_normals();
void release_face_colors();
void release_face_status();
void release_face_texture_index();
//@}
/// \name Check availability of standard properties
//@{
/// Is property available?
bool has_vertex_normals() const;
bool has_vertex_colors() const;
bool has_vertex_texcoords1D() const;
bool has_vertex_texcoords2D() const;
bool has_vertex_texcoords3D() const;
bool has_vertex_status() const;
bool has_halfedge_status() const;
bool has_halfedge_normals() const;
bool has_halfedge_colors() const;
bool has_halfedge_texcoords1D() const;
bool has_halfedge_texcoords2D() const;
bool has_halfedge_texcoords3D() const;
bool has_edge_status() const;
bool has_edge_colors() const;
bool has_face_normals() const;
bool has_face_colors() const;
bool has_face_status() const;
bool has_face_texture_index() const;
//@}
public: // Property Management
/// \anchor concepts_kernelt_property_management
/// \name Property management - add property
//@{
/// Add property.
/// @copydoc OpenMesh::BaseKernel::add_property()
template <typename T> void 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
//=============================================================================
+22
View 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
View 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
View 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
View 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
View 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;
};
+47
View File
@@ -0,0 +1,47 @@
/**************************************************
* Vertex circulators
**************************************************/
// Get the vertex-vertex circulator (1-ring) of vertex _vh
VertexVertexIter OpenMesh::PolyConnectivity::vv_iter (VertexHandle _vh);
// Get the vertex-incoming halfedges circulator of vertex _vh
VertexIHalfedgeIter OpenMesh::PolyConnectivity::vih_iter (VertexHandle _vh);
// Get the vertex-outgoing halfedges circulator of vertex _vh
VertexOHalfedgeIter OpenMesh::PolyConnectivity::voh_iter (VertexHandle _vh);
// Get the vertex-edge circulator of vertex _vh
VertexEdgeIter OpenMesh::PolyConnectivity::ve_iter (VertexHandle _vh);
// Get the vertex-face circulator of vertex _vh
VertexFaceIter OpenMesh::PolyConnectivity::vf_iter (VertexHandle _vh);
/**************************************************
* Face circulators
**************************************************/
// Get the face-vertex circulator of face _fh
FaceVertexIter OpenMesh::PolyConnectivity::fv_iter (FaceHandle _fh);
// Get the face-halfedge circulator of face _fh
FaceHalfedgeIter OpenMesh::PolyConnectivity::fh_iter (FaceHandle _fh);
// Get the face-edge circulator of face _fh
FaceEdgeIter OpenMesh::PolyConnectivity::fe_iter (FaceHandle _fh);
// Get the face-face circulator of face _fh
FaceFaceIter OpenMesh::PolyConnectivity::ff_iter (FaceHandle _fh);
/**************************************************
* Edge circulators
**************************************************/
// Get the edge-vertex circulator of edge _eh
EdgeVertexIter OpenMesh::PolyConnectivity::ev_iter (EdgeHandle _eh);
// Get the edge-halfedge circulator of edge _eh
EdgeHalfedgeIter OpenMesh::PolyConnectivity::eh_iter (EdgeHandle _eh);
// Get the edge-face circulator of of edge _eh
EdgeFaceIter OpenMesh::PolyConnectivity::ef_iter (EdgeHandle _eh);
+11
View File
@@ -0,0 +1,11 @@
MyMesh mesh;
// (linearly) iterate over all vertices
for (MyMesh::VertexIter v_it=mesh.vertices_sbegin(); v_it!=mesh.vertices_end(); ++v_it)
{
// circulate around the current vertex
for (MyMesh::VertexVertexIter vv_it=mesh.vv_iter(*v_it); vv_it.is_valid(); ++vv_it)
{
// do something with e.g. mesh.point(*vv_it)
}
}
+25
View File
@@ -0,0 +1,25 @@
using namespace OpenMesh;
typedef TriMesh_ArrayKernelT<> Mesh;
typedef Decimater::DecimaterT<Mesh> Decimater;
typedef Decimater::ModQuadricT<Mesh>::Handle HModQuadric;
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; // module access
/*
* since we need exactly one priority module (non-binary)
* we have to call set_binary(false) for our priority module
* in the case of HModQuadric, unset_max_err() calls set_binary(false) internally
*/
decimater.module(hModQuadric).unset_max_err();
decimater.initialize();
decimater.decimate();
// after decimation: remove decimated elements from the mesh
mesh.garbage_collection();
+14
View 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
View 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
// iterate over all halfedges
for (MyMesh::HalfedgeIter h_it=mesh.halfedges_begin(); h_it!=mesh.halfedges_end(); ++h_it)
...; // do something with *h_it, h_it->, or *h_it
// iterate over all edges
for (MyMesh::EdgeIter e_it=mesh.edges_begin(); e_it!=mesh.edges_end(); ++e_it)
...; // do something with *e_it, e_it->, or *e_it
// iterator over all faces
for (MyMesh::FaceIter f_it=mesh.faces_begin(); f_it!=mesh.faces_end(); ++f_it)
...; // do something with *f_it, f_it->, or *f_it
+17
View 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
View 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
...;
}
+19
View File
@@ -0,0 +1,19 @@
[...]
TriMesh::HalfedgeHandle heh, heh_init;
// Get the halfedge handle assigned to vertex[0]
heh = heh_init = mesh.halfedge_handle(vertex[0].handle());
// heh now holds the handle to the initial halfedge.
// We now get further on the boundary by requesting
// the next halfedge adjacent to the vertex heh
// points to...
heh = mesh.next_halfedge_handle(heh);
// We can do this as often as we want:
while(heh != heh_init) {
heh = mesh.next_halfedge_handle(heh);
}
[...]
+13
View File
@@ -0,0 +1,13 @@
// Test if a halfedge lies at a boundary (is not adjacent to a face)
bool is_boundary (HalfedgeHandle _heh) const
// Test if an edge lies at a boundary
bool is_boundary (EdgeHandle _eh) const
// Test if a vertex is adjacent to a boundary edge
bool is_boundary (VertexHandle _vh) const
// Test if a face has at least one adjacent boundary edge.
// If _check_vertex=true, this function also tests if at least one
// of the adjacent vertices is a boundary vertex
bool is_boundary (FaceHandle _fh, bool _check_vertex=false) const
+14
View File
@@ -0,0 +1,14 @@
[...]
// Get some vertex handle
PolyMesh::VertexHandle v = ...;
for(PolyMesh::VertexIHalfedgeIter vih_it = mesh.vih_iter(v); vih_it; ++vih_it) {
// Iterate over all incoming halfedges...
}
for(PolyMesh::VertexOHalfedgeIter voh_it = mesh.voh_iter(v); voh_it; ++voh_it) {
// Iterate over all outgoing halfedges...
}
[...]
+11
View File
@@ -0,0 +1,11 @@
// Get the face adjacent to the opposite halfedge
OpenMesh::PolyConnectivity::opposite_face_handle();
// Get the handle to the opposite halfedge
OpenMesh::Concepts::KernelT::opposite_halfedge_handle();
// Get the opposite vertex to the opposite halfedge
OpenMesh::TriConnectivity::opposite_he_opposite_vh();
// Get the vertex assigned to the opposite halfedge
OpenMesh::TriConnectivity::opposite_vh();
+7
View File
@@ -0,0 +1,7 @@
// Get the halfedge handle of i.e. the halfedge
// that is associated to the first vertex
// of our set of vertices
PolyMesh::HalfedgeHandle heh = mesh.halfedge_handle(*(mesh.vertices_begin()));
// Now get the handle of its opposing halfedge
PolyMesh::HalfedgeHandle opposite_heh = mesh.opposite_halfedge_handle(heh);
+5
View File
@@ -0,0 +1,5 @@
// Get the handle of the to vertex
OpenMesh::Concepts::KernelT::to_vertex_handle();
// Get the handle of the from vertex
OpenMesh::Concepts::KernelT::from_vertex_handle();
+17
View 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
View File
@@ -0,0 +1,4 @@
struct MyTraits : public OpenMesh::DefaultTraits
{
typedef OpenMesh::Vec3d Point; // use double-values points
};
+7
View File
@@ -0,0 +1,7 @@
struct MyTraits : public OpenMesh::DefaultTraits
{
VertexTraits
{
int some_additional_index;
};
};
+7
View File
@@ -0,0 +1,7 @@
struct MyTraits : public OpenMesh::DefaultTraits
{
template <class Base, class Refs> struct VertexT : public Base
{
int some_additional_index;
};
};
+8
View File
@@ -0,0 +1,8 @@
struct MyTraits : public OpenMesh::DefaultTraits
{
VertexTraits
{
int some_additional_index;
typename Base::Refs::FaceHandle my_face_handle;
};
};
+7
View File
@@ -0,0 +1,7 @@
struct MyTraits : public OpenMesh::DefaultTraits
{
VertexAttributes( OpenMesh::Attributes::Normal |
OpenMesh::Attributes::Color );
FaceAttributes( OpenMesh::Attributes::Normal );
};
+138
View File
@@ -0,0 +1,138 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
#include <iostream>
// -------------------- OpenMesh
#include <OpenMesh/Core/IO/MeshIO.hh>
#include <OpenMesh/Core/Mesh/PolyMesh_ArrayKernelT.hh>
// ----------------------------------------------------------------------------
typedef OpenMesh::PolyMesh_ArrayKernelT<> MyMesh;
// ----------------------------------------------------------------------------
// Build a simple cube and write it to std::cout
int main()
{
MyMesh mesh;
// generate vertices
MyMesh::VertexHandle vhandle[8];
vhandle[0] = mesh.add_vertex(MyMesh::Point(-1, -1, 1));
vhandle[1] = mesh.add_vertex(MyMesh::Point( 1, -1, 1));
vhandle[2] = mesh.add_vertex(MyMesh::Point( 1, 1, 1));
vhandle[3] = mesh.add_vertex(MyMesh::Point(-1, 1, 1));
vhandle[4] = mesh.add_vertex(MyMesh::Point(-1, -1, -1));
vhandle[5] = mesh.add_vertex(MyMesh::Point( 1, -1, -1));
vhandle[6] = mesh.add_vertex(MyMesh::Point( 1, 1, -1));
vhandle[7] = mesh.add_vertex(MyMesh::Point(-1, 1, -1));
// generate (quadrilateral) faces
std::vector<MyMesh::VertexHandle> face_vhandles;
face_vhandles.clear();
face_vhandles.push_back(vhandle[0]);
face_vhandles.push_back(vhandle[1]);
face_vhandles.push_back(vhandle[2]);
face_vhandles.push_back(vhandle[3]);
mesh.add_face(face_vhandles);
face_vhandles.clear();
face_vhandles.push_back(vhandle[7]);
face_vhandles.push_back(vhandle[6]);
face_vhandles.push_back(vhandle[5]);
face_vhandles.push_back(vhandle[4]);
mesh.add_face(face_vhandles);
face_vhandles.clear();
face_vhandles.push_back(vhandle[1]);
face_vhandles.push_back(vhandle[0]);
face_vhandles.push_back(vhandle[4]);
face_vhandles.push_back(vhandle[5]);
mesh.add_face(face_vhandles);
face_vhandles.clear();
face_vhandles.push_back(vhandle[2]);
face_vhandles.push_back(vhandle[1]);
face_vhandles.push_back(vhandle[5]);
face_vhandles.push_back(vhandle[6]);
mesh.add_face(face_vhandles);
face_vhandles.clear();
face_vhandles.push_back(vhandle[3]);
face_vhandles.push_back(vhandle[2]);
face_vhandles.push_back(vhandle[6]);
face_vhandles.push_back(vhandle[7]);
mesh.add_face(face_vhandles);
face_vhandles.clear();
face_vhandles.push_back(vhandle[0]);
face_vhandles.push_back(vhandle[3]);
face_vhandles.push_back(vhandle[7]);
face_vhandles.push_back(vhandle[4]);
mesh.add_face(face_vhandles);
// write mesh to output.obj
try
{
if ( !OpenMesh::IO::write_mesh(mesh, "output.off") )
{
std::cerr << "Cannot write mesh to file 'output.off'" << std::endl;
return 1;
}
}
catch( std::exception& x )
{
std::cerr << x.what() << std::endl;
return 1;
}
return 0;
}
+76
View 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.is_valid(); ++vv_it)
{
cog += mesh.point( *vv_it );
++valence;
}
cogs.push_back(cog / valence);
}
for (v_it=mesh.vertices_begin(), cog_it=cogs.begin();
v_it!=v_end; ++v_it, ++cog_it)
if ( !mesh.is_boundary( *v_it ) )
mesh.set_point( *v_it, *cog_it );
}
// write mesh to stdout
if ( ! OpenMesh::IO::write_mesh(mesh, argv[3]) )
{
std::cerr << "Error: cannot write mesh to " << argv[3] << std::endl;
return 1;
}
return 0;
}
+57
View File
@@ -0,0 +1,57 @@
#include <OpenMesh/Core/IO/MeshIO.hh>
#include <OpenMesh/Core/Mesh/DefaultTriMesh.hh>
#include <OpenMesh/Core/Utils/PropertyManager.hh>
#include <iostream>
#include <vector>
using MyMesh = OpenMesh::TriMesh;
int main(int argc, char** argv)
{
// Read command line options
MyMesh mesh;
if (argc != 4) {
std::cerr << "Usage: " << argv[0] << " #iterations infile outfile" << std::endl;
return 1;
}
const int iterations = argv[1];
const std::string infile = argv[2];
const std::string outfile = argv[3];
// Read mesh file
if (!OpenMesh::IO::read_mesh(mesh, infile)) {
std::cerr << "Error: Cannot read mesh from " << infile << std::endl;
return 1;
}
{
// Add a vertex property storing the computed centers of gravity
auto cog = OpenMesh::VProp<MyMesh::Point>(mesh);
// Smooth the mesh several times
for (int i = 0; i < iterations; ++i) {
// Iterate over all vertices to compute centers of gravity
for (const auto& vh : mesh.vertices()) {
cog[vh] = {0,0,0};
int valence = 0;
// Iterate over all 1-ring vertices around vh
for (const auto& vvh : mesh.vv_range(vh)) {
cog[vh] += mesh.point(vvh);
++valence;
}
cog[vh] /= valence;
}
// Move all vertices to the previously computed positions
for (const auto& vh : mesh.vertices()) {
mesh.point(vh) = cog[vh];
}
}
} // The cog vertex property is removed from the mesh at the end of this scope
// Write mesh file
if (!OpenMesh::IO::read_mesh(mesh, outfile)) {
std::cerr << "Error: Cannot write mesh to " << outfile << std::endl;
return 1;
}
}
+59
View 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;
}
@@ -0,0 +1,104 @@
#include <algorithm>
#include <OpenMesh/Core/Utils/Property.hh>
#ifndef DOXY_IGNORE_THIS
template <class Mesh> class SmootherT
{
public:
typedef typename Mesh::Point cog_t;
typedef OpenMesh::VPropHandleT< cog_t > Property_cog;
public:
// construct with a given mesh
explicit SmootherT(Mesh& _mesh)
: mesh_(_mesh)
{
mesh_.add_property( cog_ );
}
~SmootherT()
{
mesh_.remove_property( cog_ );
}
// smooth mesh _iterations times
void smooth(unsigned int _iterations)
{
for (unsigned int i=0; i < _iterations; ++i)
{
std::for_each(mesh_.vertices_begin(),
mesh_.vertices_end(),
ComputeCOG(mesh_, cog_));
std::for_each(mesh_.vertices_begin(),
mesh_.vertices_end(),
SetCOG(mesh_, cog_));
}
}
private:
//--- private classes ---
class ComputeCOG
{
public:
ComputeCOG(Mesh& _mesh, Property_cog& _cog)
: mesh_(_mesh), cog_(_cog)
{}
void operator()(const typename Mesh::VertexHandle& _vh)
{
typename Mesh::VertexVertexIter vv_it;
typename Mesh::Scalar valence(0.0);
mesh_.property(cog_, _vh) = typename Mesh::Point(0.0, 0.0, 0.0);
for (vv_it=mesh_.vv_iter(_vh); vv_it.is_valid(); ++vv_it)
{
mesh_.property(cog_, _vh) += mesh_.point( *vv_it );
++valence;
}
mesh_.property(cog_, _vh ) /= valence;
}
private:
Mesh& mesh_;
Property_cog& cog_;
};
class SetCOG
{
public:
SetCOG(Mesh& _mesh, Property_cog& _cog)
: mesh_(_mesh), cog_(_cog)
{}
void operator()(const typename Mesh::VertexHandle& _vh)
{
if (!mesh_.is_boundary(_vh))
mesh_.set_point( _vh, mesh_.property(cog_, _vh) );
}
private:
Mesh& mesh_;
Property_cog& cog_;
};
//--- private elements ---
Mesh& mesh_;
Property_cog cog_;
};
#endif
@@ -0,0 +1,71 @@
#include <iostream>
// --------------------
#include <OpenMesh/Core/IO/MeshIO.hh>
#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
typedef OpenMesh::TriMesh_ArrayKernelT<> MyMesh;
int main(int argc, char **argv)
{
MyMesh mesh;
if (argc!=2)
{
std::cerr << "Usage: " << argv[0] << " <input>\n";
return 1;
}
// request vertex normals, so the mesh reader can use normal information
// if available
mesh.request_vertex_normals();
// assure we have vertex normals
if (!mesh.has_vertex_normals())
{
std::cerr << "ERROR: Standard vertex property 'Normals' not available!\n";
return 1;
}
OpenMesh::IO::Options opt;
if ( ! OpenMesh::IO::read_mesh(mesh,argv[1], opt))
{
std::cerr << "Error loading mesh from file " << argv[1] << std::endl;
return 1;
}
// If the file did not provide vertex normals, then calculate them
if ( !opt.check( OpenMesh::IO::Options::VertexNormal ) )
{
// we need face normals to update the vertex normals
mesh.request_face_normals();
// let the mesh update the normals
mesh.update_normals();
// dispose the face normals, as we don't need them anymore
mesh.release_face_normals();
}
// move all vertices one unit length along it's normal direction
for (MyMesh::VertexIter v_it = mesh.vertices_begin();
v_it != mesh.vertices_end(); ++v_it)
{
std::cout << "Vertex #" << *v_it << ": " << mesh.point( *v_it );
mesh.set_point( *v_it, mesh.point(*v_it)+mesh.normal(*v_it) );
std::cout << " moved to " << mesh.point( *v_it ) << std::endl;
}
// don't need the normals anymore? Remove them!
mesh.release_vertex_normals();
// just check if it really works
if (mesh.has_vertex_normals())
{
std::cerr << "Ouch! ERROR! Shouldn't have any vertex normals anymore!\n";
return 1;
}
return 0;
}
+94
View 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;
}
+127
View File
@@ -0,0 +1,127 @@
#include <iostream>
#include <vector>
// -------------------- OpenMesh
#include <OpenMesh/Core/IO/MeshIO.hh>
#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
#include <OpenMesh/Core/Mesh/Traits.hh>
struct MyTraits : public OpenMesh::DefaultTraits
{
// store barycenter of neighbors in this member
VertexTraits
{
private:
Point cog_;
public:
VertexT() : cog_( Point(0.0f, 0.0f, 0.0f ) ) { }
const Point& cog() const { return cog_; }
void set_cog(const Point& _p) { cog_ = _p; }
};
};
typedef OpenMesh::TriMesh_ArrayKernelT<MyTraits> MyMesh;
typedef OpenMesh::TriMesh_ArrayKernelT<> MyMesh2;
// ---------------------------------------------------------------------------
#define SIZEOF( entity,b ) \
std::cout << _prefix << "size of " << #entity << ": " \
<< sizeof( entity ) << std::endl; \
b += sizeof( entity )
template <typename Mesh>
void print_size(const std::string& _prefix = "")
{
size_t total=0;
SIZEOF(typename Mesh::Vertex, total);
SIZEOF(typename Mesh::Halfedge, total);
SIZEOF(typename Mesh::Edge, total);
SIZEOF(typename Mesh::Face, total);
std::cout << _prefix << "total: " << total << std::endl;
}
#undef SIZEOF
// ---------------------------------------------------------------------------
int main(int argc, char **argv)
{
MyMesh mesh;
// check command line options
if (argc < 4 || argc > 5)
{
std::cerr << "Usage: " << argv[0] << " [-s] #iterations infile outfile\n";
exit(1);
}
int idx=2;
// display size of entities of the enhanced and the default mesh type
// when commandline option '-s' has been used.
if (argc == 5)
{
if (std::string("-s")==argv[idx-1])
{
std::cout << "Enhanced mesh size statistics\n";
print_size<MyMesh>(" ");
std::cout << "Default mesh size statistics\n";
print_size<MyMesh2>(" ");
}
// else ignore!
++idx;
}
// read mesh from stdin
std::cout<< " Input mesh: " << argv[idx] << std::endl;
if ( ! OpenMesh::IO::read_mesh(mesh, argv[idx]) )
{
std::cerr << "Error: Cannot read mesh from " << argv[idx] << std::endl;
return 0;
}
// smoothing mesh argv[1] times
MyMesh::VertexIter v_it, v_end(mesh.vertices_end());
MyMesh::VertexVertexIter vv_it;
MyMesh::Point cog;
MyMesh::Scalar valence;
unsigned int i, N(atoi(argv[idx-1]));
std::cout<< "Smooth mesh " << N << " times\n";
for (i=0; i < N; ++i)
{
for (v_it=mesh.vertices_begin(); v_it!=v_end; ++v_it)
{
cog[0] = cog[1] = cog[2] = valence = 0.0;
for (vv_it=mesh.vv_iter(*v_it); vv_it.is_valid(); ++vv_it)
{
cog += mesh.point( *vv_it );
++valence;
}
mesh.data(*v_it).set_cog(cog / valence);
}
for (v_it=mesh.vertices_begin(); v_it!=v_end; ++v_it)
if (!mesh.is_boundary(*v_it))
mesh.set_point( *v_it, mesh.data(*v_it).cog());
}
// write mesh to stdout
std::cout<< "Output mesh: " << argv[idx+1] << std::endl;
if ( ! OpenMesh::IO::write_mesh(mesh, argv[idx+1]) )
{
std::cerr << "Error: cannot write mesh to " << argv[idx+1] << std::endl;
return 0;
}
return 1;
}
@@ -0,0 +1,181 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
#include <iostream>
// -------------------- OpenMesh
#include <OpenMesh/Core/IO/MeshIO.hh>
#include <OpenMesh/Core/Mesh/PolyMesh_ArrayKernelT.hh>
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/Mesh/Status.hh>
// ----------------------------------------------------------------------------
struct MyTraits : public OpenMesh::DefaultTraits
{
};
typedef OpenMesh::PolyMesh_ArrayKernelT<MyTraits> MyMesh;
// ----------------------------------------------------------------------------
// Build a simple cube and delete it except one face
int main()
{
MyMesh mesh;
// the request has to be called before a vertex/face/edge can be deleted. it grants access to the status attribute
mesh.request_face_status();
mesh.request_edge_status();
mesh.request_vertex_status();
// generate vertices
MyMesh::VertexHandle vhandle[8];
MyMesh::FaceHandle fhandle[6];
vhandle[0] = mesh.add_vertex(MyMesh::Point(-1, -1, 1));
vhandle[1] = mesh.add_vertex(MyMesh::Point( 1, -1, 1));
vhandle[2] = mesh.add_vertex(MyMesh::Point( 1, 1, 1));
vhandle[3] = mesh.add_vertex(MyMesh::Point(-1, 1, 1));
vhandle[4] = mesh.add_vertex(MyMesh::Point(-1, -1, -1));
vhandle[5] = mesh.add_vertex(MyMesh::Point( 1, -1, -1));
vhandle[6] = mesh.add_vertex(MyMesh::Point( 1, 1, -1));
vhandle[7] = mesh.add_vertex(MyMesh::Point(-1, 1, -1));
// generate (quadrilateral) faces
std::vector<MyMesh::VertexHandle> tmp_face_vhandles;
tmp_face_vhandles.clear();
tmp_face_vhandles.push_back(vhandle[0]);
tmp_face_vhandles.push_back(vhandle[1]);
tmp_face_vhandles.push_back(vhandle[2]);
tmp_face_vhandles.push_back(vhandle[3]);
fhandle[0] = mesh.add_face(tmp_face_vhandles);
tmp_face_vhandles.clear();
tmp_face_vhandles.push_back(vhandle[7]);
tmp_face_vhandles.push_back(vhandle[6]);
tmp_face_vhandles.push_back(vhandle[5]);
tmp_face_vhandles.push_back(vhandle[4]);
fhandle[1] = mesh.add_face(tmp_face_vhandles);
tmp_face_vhandles.clear();
tmp_face_vhandles.push_back(vhandle[1]);
tmp_face_vhandles.push_back(vhandle[0]);
tmp_face_vhandles.push_back(vhandle[4]);
tmp_face_vhandles.push_back(vhandle[5]);
fhandle[2] = mesh.add_face(tmp_face_vhandles);
tmp_face_vhandles.clear();
tmp_face_vhandles.push_back(vhandle[2]);
tmp_face_vhandles.push_back(vhandle[1]);
tmp_face_vhandles.push_back(vhandle[5]);
tmp_face_vhandles.push_back(vhandle[6]);
fhandle[3] = mesh.add_face(tmp_face_vhandles);
tmp_face_vhandles.clear();
tmp_face_vhandles.push_back(vhandle[3]);
tmp_face_vhandles.push_back(vhandle[2]);
tmp_face_vhandles.push_back(vhandle[6]);
tmp_face_vhandles.push_back(vhandle[7]);
fhandle[4] = mesh.add_face(tmp_face_vhandles);
tmp_face_vhandles.clear();
tmp_face_vhandles.push_back(vhandle[0]);
tmp_face_vhandles.push_back(vhandle[3]);
tmp_face_vhandles.push_back(vhandle[7]);
tmp_face_vhandles.push_back(vhandle[4]);
fhandle[5] = mesh.add_face(tmp_face_vhandles);
// And now delete all faces and vertices
// except face (vh[7], vh[6], vh[5], vh[4])
// whose handle resides in fhandle[1]
// Delete face 0
mesh.delete_face(fhandle[0], false);
// ... face 2
mesh.delete_face(fhandle[2], false);
// ... face 3
mesh.delete_face(fhandle[3], false);
// ... face 4
mesh.delete_face(fhandle[4], false);
// ... face 5
mesh.delete_face(fhandle[5], false);
// If isolated vertices result in a face deletion
// they have to be deleted manually. If you want this
// to happen automatically, change the second parameter
// to true.
// Now delete the isolated vertices 0, 1, 2 and 3
mesh.delete_vertex(vhandle[0], false);
mesh.delete_vertex(vhandle[1], false);
mesh.delete_vertex(vhandle[2], false);
mesh.delete_vertex(vhandle[3], false);
// Delete all elements that are marked as deleted
// from memory.
mesh.garbage_collection();
// write mesh to output.obj
try {
if ( !OpenMesh::IO::write_mesh(mesh, "output.off") ) {
std::cerr << "Cannot write mesh to file 'output.off'" << std::endl;
return 1;
}
}
catch( std::exception& x )
{
std::cerr << x.what() << std::endl;
return 1;
}
return 0;
}
+297
View 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
// ============================================================================
+119
View File
@@ -0,0 +1,119 @@
#ifndef FILL_PROPS_HH
#define FILL_PROPS_HH
#include <OpenMesh/Core/Utils/Property.hh>
#include "int2roman.hh"
template <typename Mesh>
bool
fill_props( Mesh& _m, OpenMesh::VPropHandleT<float> _ph, bool _check=false)
{
static float a[9] = { 1.1f, 2.2f, 3.3f, 4.4f, 5.5f, 6.6f, 7.7f, 8.8f, 9.9f };
for(typename Mesh::VertexIter it=_m.vertices_begin();
it != _m.vertices_end(); ++it)
{
const float v = a[it->idx()%9];
if ( _check && !(_m.property( _ph, *it ) == v) )
return false;
else
_m.property( _ph, *it ) = v;
}
return true;
}
template <typename Mesh>
bool
fill_props( Mesh& _m, OpenMesh::EPropHandleT<bool> _ph, bool _check=false )
{
for( typename Mesh::EdgeIter it=_m.edges_begin();
it != _m.edges_end(); ++it)
{
const size_t n = it->idx();
const bool v = ((n&(n-1))==0); // true for 0,1,2,4,8,..
if (_check && _m.property( _ph, *it ) != v)
{
std::cout << " eprop_bool: " << n << " -> "
<< _m.property(_ph, *it ) << " != " << v << std::endl;
return false;
}
else
{
_m.property( _ph, *it ) = v;
std::cout << " eprop_bool: " << n << " -> " << v << std::endl;
}
}
return true;
}
template <typename Mesh>
bool
fill_props(Mesh& _m, OpenMesh::FPropHandleT<std::string> _ph, bool _check=false)
{
for( typename Mesh::FaceIter it=_m.faces_begin();
it != _m.faces_end(); ++it)
{
const int n = (it->idx()) + 1;
_m.property( _ph, *it ) = int2roman(n);
}
return true;
}
template <typename Mesh, typename T>
bool
fill_props( Mesh& _m, OpenMesh::HPropHandleT<T> _ph, bool _check=false)
{
T v;
static float a[9] = { 1.1f, 2.2f, 3.3f, 4.4f, 5.5f, 6.6f, 7.7f, 8.8f, 9.9f };
static float b[9] = { 2.2f, 3.3f, 4.4f, 5.5f, 6.6f, 7.7f, 8.8f, 9.9f, 1.1f };
static float c[9] = { 3.3f, 4.4f, 5.5f, 6.6f, 7.7f, 8.8f, 9.9f, 1.1f, 2.2f };
static float d[9] = { 4.4f, 5.5f, 6.6f, 7.7f, 8.8f, 9.9f, 1.1f, 2.2f, 3.3f };
static double values[9] = { 0.1, 0.02, 0.003, 0.0004, 0.00005, 0.000006,
0.0000007, 0.00000008, 0.000000009 };
for( typename Mesh::HalfedgeIter it=_m.halfedges_begin();
it != _m.halfedges_end(); ++it)
{
const int n = it->idx();
v = it->idx()+1; // ival
v = values[n%9]; // dval
v = ((n&(n-1))==0); // bval
v.vec4fval[0] = a[n%9];
v.vec4fval[1] = b[n%9];
v.vec4fval[2] = c[n%9];
v.vec4fval[3] = d[n%9];
if ( _check && _m.property( _ph, *it ) != v )
return false;
else
_m.property( _ph, *it ) = v;
}
return true;
}
template <typename Mesh, typename T>
bool
fill_props( Mesh& _m, OpenMesh::MPropHandleT<T> _ph, bool _check=false)
{
for( typename Mesh::FaceIter it=_m.faces_begin(); it != _m.faces_end(); ++it)
{
const size_t idx = it->idx();
if ( _check && _m.property( _ph )[int2roman(idx+1)] != idx )
return false;
else
_m.property( _ph )[int2roman(idx+1)] = idx;
}
return true;
}
#endif
@@ -0,0 +1,70 @@
#ifndef GENERATE_CUBE_HH
#define GENERATE_CUBE_HH
template <typename MeshType>
size_t generate_cube( MeshType& mesh )
{
typedef typename MeshType::VertexHandle VertexHandle;
typedef typename MeshType::Point Point;
typename MeshType::VertexHandle vhandle[8];
vhandle[0] = mesh.add_vertex(Point(-1, -1, 1));
vhandle[1] = mesh.add_vertex(Point( 1, -1, 1));
vhandle[2] = mesh.add_vertex(Point( 1, 1, 1));
vhandle[3] = mesh.add_vertex(Point(-1, 1, 1));
vhandle[4] = mesh.add_vertex(Point(-1, -1, -1));
vhandle[5] = mesh.add_vertex(Point( 1, -1, -1));
vhandle[6] = mesh.add_vertex(Point( 1, 1, -1));
vhandle[7] = mesh.add_vertex(Point(-1, 1, -1));
// generate (quadrilateral) faces
std::vector< VertexHandle > face_vhandles;
face_vhandles.clear();
face_vhandles.push_back(vhandle[0]);
face_vhandles.push_back(vhandle[1]);
face_vhandles.push_back(vhandle[2]);
face_vhandles.push_back(vhandle[3]);
mesh.add_face(face_vhandles);
face_vhandles.clear();
face_vhandles.push_back(vhandle[7]);
face_vhandles.push_back(vhandle[6]);
face_vhandles.push_back(vhandle[5]);
face_vhandles.push_back(vhandle[4]);
mesh.add_face(face_vhandles);
face_vhandles.clear();
face_vhandles.push_back(vhandle[1]);
face_vhandles.push_back(vhandle[0]);
face_vhandles.push_back(vhandle[4]);
face_vhandles.push_back(vhandle[5]);
mesh.add_face(face_vhandles);
face_vhandles.clear();
face_vhandles.push_back(vhandle[2]);
face_vhandles.push_back(vhandle[1]);
face_vhandles.push_back(vhandle[5]);
face_vhandles.push_back(vhandle[6]);
mesh.add_face(face_vhandles);
face_vhandles.clear();
face_vhandles.push_back(vhandle[3]);
face_vhandles.push_back(vhandle[2]);
face_vhandles.push_back(vhandle[6]);
face_vhandles.push_back(vhandle[7]);
mesh.add_face(face_vhandles);
face_vhandles.clear();
face_vhandles.push_back(vhandle[0]);
face_vhandles.push_back(vhandle[3]);
face_vhandles.push_back(vhandle[7]);
face_vhandles.push_back(vhandle[4]);
mesh.add_face(face_vhandles);
return mesh.n_vertices();
};
#endif
+42
View File
@@ -0,0 +1,42 @@
#include <OpenMesh/Core/System/config.hh>
#if defined(OM_CC_MIPS)
# include <assert.h>
#else
# include <cassert>
#endif
#include "int2roman.hh"
std::string int2roman( size_t decimal, size_t length )
{
assert( decimal > 0 && decimal < 1000 );
const size_t nrows = 4;
const size_t ncols = 4;
static size_t table_arabs[ nrows ][ ncols ] = { { 1000, 1000, 1000, 1000 },
{ 900, 500, 400, 100 },
{ 90, 50, 40, 10 },
{ 9, 5, 4, 1 } };
static char *table_romans[ nrows ][ ncols ] = { { "M", "M", "M", "M" },
{ "CM", "D", "CD", "C" },
{ "XC", "L", "XL", "X" },
{ "IX", "V", "IV", "I" } };
size_t power; // power of ten
size_t index; // Indexes thru values to subtract
std::string roman = "";
roman.reserve(length);
for ( power = 0; power < nrows; power++ )
for ( index = 0; index < ncols; index++ )
while ( decimal >= table_arabs[ power ][ index ] )
{
roman += table_romans[ power ][ index ];
decimal -= table_arabs[ power ][ index ];
}
return roman;
}
@@ -0,0 +1,8 @@
#ifndef INT2ROMAN_HH
#define INT2ROMAN_HH
#include <string>
std::string int2roman( size_t decimal, size_t length=30 );
#endif
@@ -0,0 +1,348 @@
#include <iostream>
#include <string>
#include <map>
// -------------------- OpenMesh
#include <OpenMesh/Core/IO/MeshIO.hh>
#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
#include <OpenMesh/Core/Mesh/PolyMesh_ArrayKernelT.hh>
// -------------------- little helper
#include "generate_cube.hh"
#include "stats.hh"
#include "fill_props.hh"
// ----------------------------------------------------------------------------
// Set to 1 to use an PolyMesh type.
#define UsePolyMesh 1
// ----------------------------------------------------------------------------
using namespace OpenMesh;
// ----------------------------------------------------------------------------
typedef TriMesh_ArrayKernelT<> TriMesh;
typedef PolyMesh_ArrayKernelT<> PolyMesh;
#if UsePolyMesh
typedef PolyMesh Mesh;
#else
typedef TriMesh Mesh;
#endif
// ----------------------------------------------------------------------------
#ifndef DOXY_IGNORE_THIS
struct MyData
{
int ival;
double dval;
bool bval;
OpenMesh::Vec4f vec4fval;
MyData()
: ival(0), dval(0.0), bval(false)
{ }
MyData( const MyData& _cpy )
: ival(_cpy.ival), dval(_cpy.dval), bval(_cpy.bval),
vec4fval(_cpy.vec4fval)
{ }
// ---------- assignment
MyData& operator = (const MyData& _rhs)
{
ival = _rhs.ival;
dval = _rhs.dval;
bval = _rhs.bval;
vec4fval = _rhs.vec4fval;
return *this;
}
MyData& operator = (int _rhs) { ival = _rhs; return *this; }
MyData& operator = (double _rhs) { dval = _rhs; return *this; }
MyData& operator = (bool _rhs) { bval = _rhs; return *this; }
MyData& operator = (const OpenMesh::Vec4f& _rhs)
{ vec4fval = _rhs; return *this; }
// ---------- comparison
bool operator == (const MyData& _rhs) const
{
return ival == _rhs.ival
&& dval == _rhs.dval
&& bval == _rhs.bval
&& vec4fval == _rhs.vec4fval;
}
bool operator != (const MyData& _rhs) const { return !(*this == _rhs); }
};
#endif
// ----------------------------------------------------------------------------
typedef std::map< std::string, unsigned int > MyMap;
// ----------------------------------------------------------------------------
#ifndef DOXY_IGNORE_THIS
namespace OpenMesh {
namespace IO {
// support persistence for struct MyData
template <> struct binary<MyData>
{
typedef MyData value_type;
static const bool is_streamable = true;
// return binary size of the value
static size_t size_of(void)
{
return sizeof(int)+sizeof(double)+sizeof(bool)+sizeof(OpenMesh::Vec4f);
}
static size_t size_of(const value_type&)
{
return size_of();
}
static std::string type_identifier(void)
{
return "RegisteredDataType";
}
static size_t store(std::ostream& _os, const value_type& _v, bool _swap=false)
{
size_t bytes;
bytes = IO::store( _os, _v.ival, _swap );
bytes += IO::store( _os, _v.dval, _swap );
bytes += IO::store( _os, _v.bval, _swap );
bytes += IO::store( _os, _v.vec4fval, _swap );
return _os.good() ? bytes : 0;
}
static size_t restore( std::istream& _is, value_type& _v, bool _swap=false)
{
size_t bytes;
bytes = IO::restore( _is, _v.ival, _swap );
bytes += IO::restore( _is, _v.dval, _swap );
bytes += IO::restore( _is, _v.bval, _swap );
bytes += IO::restore( _is, _v.vec4fval, _swap );
return _is.good() ? bytes : 0;
}
};
template <> struct binary< MyMap >
{
typedef MyMap value_type;
static const bool is_streamable = true;
// return generic binary size of self, if known
static size_t size_of(void) { return UnknownSize; }
// return binary size of the value
static size_t size_of(const value_type& _v)
{
if (_v.empty())
return sizeof(unsigned int);
value_type::const_iterator it = _v.begin();
unsigned int N = _v.size();
size_t bytes = IO::size_of(N);
for(;it!=_v.end(); ++it)
{
bytes += IO::size_of( it->first );
bytes += IO::size_of( it->second );
}
return bytes;
}
static
size_t store(std::ostream& _os, const value_type& _v, bool _swap=false)
{
size_t bytes = 0;
unsigned int N = _v.size();
value_type::const_iterator it = _v.begin();
bytes += IO::store( _os, N, _swap );
for (; it != _v.end() && _os.good(); ++it)
{
bytes += IO::store( _os, it->first, _swap );
bytes += IO::store( _os, it->second, _swap );
}
return _os.good() ? bytes : 0;
}
static
size_t restore( std::istream& _is, value_type& _v, bool _swap=false)
{
size_t bytes = 0;
unsigned int N = 0;
_v.clear();
bytes += IO::restore( _is, N, _swap );
value_type::key_type key;
value_type::mapped_type val;
for (size_t i=0; i<N && _is.good(); ++i)
{
bytes += IO::restore( _is, key, _swap );
bytes += IO::restore( _is, val, _swap );
_v[key] = val;
}
return _is.good() ? bytes : 0;
}
};
}
}
#endif
// ----------------------------------------------------------------------------
int main(void)
{
//
Mesh mesh;
// generate a geometry
generate_cube<Mesh>(mesh);
// should display 8 vertices, 18/12 edges, 12/6 faces (Tri/Poly)
mesh_stats(mesh);
// print out information about properties
mesh_property_stats(mesh);
std::cout << "Define some custom properties..\n";
OpenMesh::VPropHandleT<float> vprop_float;
OpenMesh::EPropHandleT<bool> eprop_bool;
OpenMesh::FPropHandleT<std::string> fprop_string;
OpenMesh::HPropHandleT<MyData> hprop_mydata;
OpenMesh::MPropHandleT<MyMap> mprop_map;
std::cout << ".. and registrate them at the mesh object.\n";
mesh.add_property(vprop_float, "vprop_float");
mesh.add_property(eprop_bool, "eprop_bool");
mesh.add_property(fprop_string, "fprop_string");
mesh.add_property(hprop_mydata, "hprop_mydata");
mesh.add_property(mprop_map, "mprop_map");
mesh_property_stats(mesh);
std::cout << "Now let's fill the props..\n";
fill_props(mesh, vprop_float);
fill_props(mesh, eprop_bool);
fill_props(mesh, fprop_string);
fill_props(mesh, hprop_mydata);
fill_props(mesh, mprop_map);
std::cout << "Check props..\n";
#define CHK_PROP( PH ) \
std::cout << " " << #PH << " " \
<< (fill_props(mesh, PH, true)?"ok\n":"error\n")
CHK_PROP(vprop_float);
CHK_PROP(eprop_bool);
CHK_PROP(fprop_string);
CHK_PROP(hprop_mydata);
CHK_PROP(mprop_map);
#undef CHK_PROP
std::cout << "Set persistent flag..\n";
#define SET_PERS( PH ) \
mesh.property(PH).set_persistent(true); \
std::cout << " " << #PH << " " \
<< (mesh.property(PH).persistent()?"ok\n":"failed!\n")
mesh.property(vprop_float).set_persistent(true);
std::cout << " vprop_float "
<< (mesh.property(vprop_float).persistent()?"ok\n":"failed!\n");
SET_PERS( eprop_bool );
SET_PERS( fprop_string );
SET_PERS( hprop_mydata );
mesh.mproperty(mprop_map).set_persistent(true);
std::cout << " mprop_map "
<< (mesh.mproperty(mprop_map).persistent()?"ok\n":"failed!\n");
std::cout << "Write mesh..";
if (IO::write_mesh( mesh, "persistence-check.om" ))
std::cout << " ok\n";
else
{
std::cout << " failed\n";
return 1;
}
std::cout << "Clear mesh\n";
mesh.clear();
mesh_stats(mesh, " ");
std::cout << "Read back mesh..";
try
{
if (IO::read_mesh( mesh, "persistence-check.om" ))
std::cout << " ok\n";
else
{
std::cout << " failed!\n";
return 1;
}
mesh_stats(mesh, " ");
}
catch( std::exception &x )
{
std::cerr << x.what() << std::endl;
return 1;
}
std::cout << "Check props..\n";
#define CHK_PROP( PH ) \
std::cout << " " << #PH << " " \
<< (fill_props(mesh, PH, true)?"ok\n":"error\n")
CHK_PROP(vprop_float);
CHK_PROP(eprop_bool);
CHK_PROP(fprop_string);
CHK_PROP(hprop_mydata);
CHK_PROP(mprop_map);
#undef CHK_PROP
return 0;
}
// end of file
// ============================================================================
+20
View 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
+62
View File
@@ -0,0 +1,62 @@
#include <OpenMesh/Core/IO/MeshIO.hh>
#include <OpenMesh/Core/Mesh/DefaultTriMesh.hh>
#include <OpenMesh/Core/Utils/PropertyManager.hh>
#include <iostream>
#include <vector>
using MyMesh = OpenMesh::TriMesh;
int main(int argc, char** argv)
{
// Read command line options
MyMesh mesh;
if (argc != 4) {
std::cerr << "Usage: " << argv[0] << " #iterations infile outfile" << std::endl;
return 1;
}
const int iterations = argv[1];
const std::string infile = argv[2];
const std::string outfile = argv[3];
// Read mesh file
if (!OpenMesh::IO::read_mesh(mesh, infile)) {
std::cerr << "Error: Cannot read mesh from " << infile << std::endl;
return 1;
}
{
// Add a vertex property storing the laplace vector
auto laplace = OpenMesh::VProp<MyMesh::Point>(mesh);
// Add a vertex property storing the laplace of the laplace
auto bi_laplace = OpenMesh::VProp<MyMesh::Point>(mesh);
// Get a propertymanager of the points property of the mesh to use as functor
auto points = OpenMesh::getPointsProperty(mesh);
// Smooth the mesh several times
for (int i = 0; i < iterations; ++i) {
// Iterate over all vertices to compute laplace vector
for (const auto& vh : mesh.vertices())
laplace(vh) = vh.vertices().avg(points) - points(vh);
// Iterate over all vertices to compute the laplace vector of the laplace vectors
for (const auto& vh : mesh.vertices())
bi_laplace(vh) = (vh.vertices().avg(laplace) - laplace(vh));
// update points by substracting the bi-laplacian damped by a factor of 0.5
for (const auto& vh : mesh.vertices())
points(vh) += -0.5 * bi_laplace(vh);
}
} // The laplace and update properties are removed from the mesh at the end of this scope.
// Write mesh file
if (!OpenMesh::IO::read_mesh(mesh, outfile)) {
std::cerr << "Error: Cannot write mesh to " << outfile << std::endl;
return 1;
}
}
+58
View File
@@ -0,0 +1,58 @@
#include <OpenMesh/Core/IO/MeshIO.hh>
#include <OpenMesh/Core/Mesh/DefaultTriMesh.hh>
#include <OpenMesh/Core/Utils/PropertyManager.hh>
#include <OpenMesh/Core/Utils/Predicates.hh>
#include <iostream>
#include <vector>
using MyMesh = OpenMesh::TriMesh;
bool is_divisible_by_3(OpenMesh::FaceHandle vh) { return vh.idx() % 3 == 0; }
int main(int argc, char** argv)
{
using namespace OpenMesh::Predicates; // for easier access to predicates
// Read command line options
MyMesh mesh;
if (argc != 4) {
std::cerr << "Usage: " << argv[0] << " infile" << std::endl;
return 1;
}
const std::string infile = argv[1];
// Read mesh file
if (!OpenMesh::IO::read_mesh(mesh, infile)) {
std::cerr << "Error: Cannot read mesh from " << infile << std::endl;
return 1;
}
// Count boundary vertices
std::cout << "Mesh contains " << mesh.vertices().count_if(Boundary()) << " boundary vertices";
// Selected inner vertices
std::cout << "These are the selected inner vertices: " << std::endl;
for (auto vh : mesh.vertices().filtered(!Boundary() && Selected()))
std::cout << vh.idx() << ", ";
std::cout << std::endl;
// Faces whose id is divisible by 3
auto vec = mesh.faces().filtered(is_divisible_by_3).to_vector();
std::cout << "There are " << vec.size() << " faces whose id is divisible by 3" << std::endl;
// Faces which are tagged or whose id is not divisible by 3
auto vec2 = mesh.faces().filtered(Tagged() || !make_predicate(is_divisible_by_3)).to_vector();
std::cout << "There are " << vec2.size() << " faces which are tagged or whose id is not divisible by 3" << std::endl;
// Edges that are longer than 10 or shorter than 2
OpenMesh::EProp<bool> longer_than_10(mesh);
for (auto eh : mesh.edges())
longer_than_10[eh] = mesh.calc_edge_length(eh) > 10;
std::cout << "There are " <<
mesh.edges().count_if(make_predicate(longer_than_10) || make_predicate([&](OpenMesh::EdgeHandle eh) { return mesh.calc_edge_length(eh) < 2; })) <<
" edges which are shorter than 2 or longer than 10" << std::endl;
}
+11
View File
@@ -0,0 +1,11 @@
cmake_minimum_required(VERSION 3.25)
project(OpenMesh-Example)
find_package(OpenMesh)
set (targetName MyOwnProject)
add_executable (${targetName} build_cube.cc)
target_link_libraries(${targetName} PRIVATE OpenMeshCore OpenMeshTools)
+20
View File
@@ -0,0 +1,20 @@
include (VCICommon)
include_directories (
../../..
${CMAKE_CURRENT_SOURCE_DIR}
)
set (targetName MyOwnProject)
# collect all header and source files
vci_append_files (headers "*.hh" .)
vci_append_files (sources "*.cc" .)
vci_add_executable (${targetName} ${headers} ${sources})
target_link_libraries (${targetName}
OpenMeshCore
OpenMeshTools
)
+2128
View File
File diff suppressed because it is too large Load Diff
+195
View File
@@ -0,0 +1,195 @@
//-----------------------------------------------------------------------------
/** \page compiling Compiling OpenMesh
\section compilers Tested compilers
%OpenMesh has been successfully tested for the following operating
systems / compilers. This is only a list of tested compilers.
More might be supported but are not tested. Make sure that your compiler
supports at least C++11
<table>
<tr><td> Linux </td><td>
gcc >= 6.3<br>
clang >= 3.3<br>
</td></tr>
<tr><td> Windows </td><td>
Microsoft Visual Studio 2015<br>
Microsoft Visual Studio 2017<br>
</td></tr>
<tr><td> Tested MacOS X Compilers</td>
<td>
XCode <br>
</td></tr>
</table>
\section req_libs Required libraries (Only if you want to build the included Apps)
Install the following external libraries / frameworks if you want to use the included Applications:<br><br>
<table>
<tr><td>Qt5</td><td><a href="http://qt-project.org/downloads" target="_blank">https://www.qt.io/download</a></td></tr>
</table><br>
\section build_systems Chosing build system
%OpenMesh can be built using the <b>cmake</b> build system.
<br>
<br>
\section sec_compiling_unix Unix
\subsection linux_using_cmake Compiling OpenMesh using CMake
In order to compile %OpenMesh, create a directory named e.g. "build" in
OpenMesh's root directory. <b>Change to the newly created directory</b> and type
<br/><br/>
<tt>
cmake&nbsp;..&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;## Generates the appropriate Makefiles<br>
make&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;## Builds the project<br>
</tt><br>
\warning If your compiler does not support c++11 natively, you might have to enable it by changing the cmake call to: <br>
<tt>cmake .. -DCMAKE_CXX_FLAGS=-std=c++98</tt>
You can choose the build type by using cmake with the flag<br>
<b>-DCMAKE_BUILD_TYPE=(Debug|Release)</b> The default is: Release <br>
Other flags are:<br/>
<b>-DBUILD_APPS=OFF</b> to disable build of applications and<br/>
<b>-DCMAKE_INSTALL_PREFIX=&lt;path&gt;</b> to specify the install path.<br/>
When calling <b>make install</b> cmake will install %OpenMesh into this
directory using the subdirectories lib/include/bin.
CMake builds both shared and static under Linux.
Everything will then be build in the <b>Build</b> subdirectory containing the libraries in <b>lib</b> and the binaries in <b>bin</b>.
There are some additional targets:<br>
<b>doc</b>: Builds the Documentation<br>
<b>doc-install</b>: Builds the Documentation and installs it<br>
<br>
\note When you link against the static libraries of OpenMesh and get the error "can not be used when making a
shared object; recompile with -fPIC" you need to add "-fPIC" to the CMAKE_CXX_FLAGS. (This is usually added automatically)
\section sec_compiling_windows Windows
\subsection windows_using_cmake Compiling OpenMesh using CMake
Building OpenMesh on Windows requires cmake to generate the project files for Visual Studio.
<ul>
<li> Get Visual Studio ( 2015-2017 ) </li>
<li> Extract %OpenMesh source code. </li>
<li> Get all required libraries and install them ( including headers! ).</li>
<li> Download and install cmake: <a href="https://cmake.org/download/">www.cmake.org</a>.<br> </li>
<li> Start the cmake gui and open the %OpenMesh toplevel directory as source directory </li>
<li> Choose a build directory (e.g. create a directory called "build" in OpenMesh's root folder) </li>
<li> Click on configure .... If any libraries are left unconfigured, you can adjust the path manually. Rerun configure until everything is configured correctly. <br>
Attention: Some build variables are only visible in advanced view mode. Select Visual Studio 9 (2008), Visual Studio 10(2010), Visual Studio 11 (2012), Visual Studio 12 (2013) (Depending on your version) as
generator. </li>
<li> Click generate to create the visual studio project files </li>
<li> You can now find a Visual Studio solution file (OpenMesh.sln) in the <b>build</b> directory you chose in cmake </li>
<li> Now you can build %OpenMesh from within Visual Studio using the newly created project file. </li>
</ul>
<br>
<br>
\section sec_compiling_macosx MacOS X
To compile OpenMesh, you need cmake on your system which is the minimal requirement to build OpenMesh.
We recommend using homebrew (https://brew.sh/index_de) for installing additional packages required for
compiling OpenMesh or other projects.
After installing homebrew, you can use the following command to install cmake:<br>
<tt>
brew install cmake&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;## cmake generates the makefiles<br>
</tt><br>
Optional libraries which can be used to build OpenMesh:<br>
<tt>
brew install googletest&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# Required to compile the included tests<br>
brew install qt&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# Required to compile the included UI example apps<br>
</tt><br>
Download and install required libraries as stated above.
You can download %OpenMesh's sources from <tt>www.openmesh.org</tt> or check out the latest repository via GIT (Recommended to get the latest version of OpenMesh):<br/>
<tt>https://gitlab.vci.rwth-aachen.de:9000/OpenMesh/OpenMesh</tt>.<br/><br/>
\subsection mac_using_cmake Compiling OpenMesh using CMake
We recommend you to use CMake >= 3.7 as build system. This can also easily be installed
via Homebrew as well as the Qt >= 6.2 library which is used for some example applications
in %OpenMesh.<br/>
Once installed, change to %OpenMesh's root directory and create a directory
named e.g. "buildDebug" (assuming you want to build with debug symbols).<br/>
Then type in the following command to initially set up the build environment:
<br/><br/>
<tt>
cmake&nbsp;..&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;## Generates the appropriate Makefiles<br>
</tt>
<br/>
Note: If the build directory is not a subdirectory of %OpenMesh's root folder, replace ".." with %OpenMesh's
absolute (or relative) path.
In order to manually set specific build variables, just type:
<br/><br/>
<tt>
ccmake&nbsp;.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;## Configure build environment<br>
</tt>
<br/>
This opens the CMake configure tool. Change the CMAKE_BUILD_TYPE variable to "Release" in order to prepare build
for release configuration. Now, when everything is set up, just type:
<br/><br/>
<tt>
make&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;## Build %OpenMesh<br>
</tt>
<br/>
And optionally:
<br/><br/>
<tt>
make&nbsp;doc&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;## Build %OpenMesh's documentation<br>
</tt>
<br>
The mac application bundle will be found under "Build" in the recently created build folder.
It automatically contains all needed shared objects (libs, fonts, textures, etc.).
CMake builds both shared and static under MacOS X.
**/
/** \page compiling_tests Compiling OpenMesh unit tests
%OpenMesh comes with a set of unittests for all platforms. In order to run these
tests, you need to enable the cmake flag <b>OPENMESH_BUILD_UNIT_TESTS</b>.
You also need <a href="https://github.com/google/googletest">GoogleTest</a> on your
machine. Configure the cmake variables in OpenMesh to point to your GTest include
dirs and libraries (check the Advanced button in cmake, if you don't see these
options). Than run cmake and build OpenMesh.
Afterwards you should have a Unittests subdirectory in your binary build folder.
This directory includes the unittest executables and several test files for input
and output checks. You can run the executables directly, but
make sure, that the working directory is the directory where the executables are.
**/
//-----------------------------------------------------------------------------
+111
View File
@@ -0,0 +1,111 @@
//-----------------------------------------------------------------------------
/** \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 DecimaterLock Block vertices from beeing touched by the Decimater
You could mark vertices as locked, which should not be modified by the decimater.
\code
// That might be already requested
mesh_->request_vertex_status();
// Get an iterator over all halfedges
Mesh::HalfedgeIter he_it, he_end=mesh_->halfedges_end();
// If halfedge is boundary, lock the corresponding vertices
for (he_it = mesh_->halfedges_begin(); he_it != he_end ; ++he_it)
if (mesh_->is_boundary(*he_it)) {
mesh_->status(_mesh->to_vertex_handle(*he_it)).set_locked(true);
mesh_->status(_mesh->from_vertex_handle(*he_it)).set_locked(true);
}
\endcode
\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(Binary: B, Continuous: C, Special: X):
- OpenMesh::Decimater::ModAspectRatioT (B,C)
- OpenMesh::Decimater::ModEdgeLengthT (B,C)
- OpenMesh::Decimater::ModHausdorffT (B)
- OpenMesh::Decimater::ModIndependentSetsT (B)
- OpenMesh::Decimater::ModNormalDeviationT (B,C)
- OpenMesh::Decimater::ModNormalFlippingT (B)
- OpenMesh::Decimater::ModProgMeshT (X)
- OpenMesh::Decimater::ModQuadricT (B,C)
- OpenMesh::Decimater::ModRoundnessT (B,C)
\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
*/
+2695
View File
File diff suppressed because it is too large Load Diff
+21
View File
@@ -0,0 +1,21 @@
//-----------------------------------------------------------------------------
/** \page holefiller_docu Mesh Hole Filler
\section HoleFillerAlgo The holefilling algorithm
The holefiller (OpenMesh::HoleFiller::HoleFillerT) provides a
hole filling algorith based on the Filling Holes in Meshes paper
by Liepa in 2003.
\code
// Initialize holefiller
OpenMesh::HoleFiller::HoleFillerT<Mesh> filler(mesh_);
// Execute the algorithm and fill all holes
filler.fill_all_holes();
\endcode
*/
+8
View File
@@ -0,0 +1,8 @@
#projectlogo
{
padding-right:64px;
right:0px;
position:absolute;
}
+15
View File
@@ -0,0 +1,15 @@
<hr>
<address>
<small>
<a href="http://www.rwth-graphics.de" style="text-decoration:none;">
</a>
Project <b>$projectname</b>,
&copy;&nbsp; Visual Computing Institute, RWTH Aachen.
Documentation generated using
<a class="el" href="http://www.doxygen.org/index.html">
<b>doxygen</b>
</a>.
</small>
</address>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

+24
View 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
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 777 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

+65
View File
@@ -0,0 +1,65 @@
\documentclass{minimal}
% Tikz
\usepackage{pgf}
\usepackage{tikz}
\usetikzlibrary{calc,trees,positioning,arrows,chains,shapes.geometric,%
decorations.pathreplacing,decorations.pathmorphing,shapes,%
matrix,shapes.symbols,positioning}
\tikzset{
kiste/.style={
rectangle,
rounded corners,
% fill=black!10,
draw=black, very thick,
text width=10em,
minimum height=3em,
text centered},
kkiste/.style={
rectangle,
rounded corners,
% fill=black!10,
draw=black, very thick,
text width=7em,
minimum height=2em,
text centered},
}
\begin{document}
\begin{center}
\begin{tikzpicture}
\node[kiste](IOM) at (0,0) {IOManager};
\node[kiste,rotate=90](PD) at (-5,-4) {Persistent Data};
\node[kiste,rotate=-90](DS) at (5,-4) {Data Structures};
\path[fill=yellow!20,rounded corners,draw=black!50, dashed]
(-3.5,-2) rectangle (-0.5,-6);
\path[fill=yellow!20,rounded corners,draw=black!50, dashed]
(.5,-2) rectangle (3.5,-6);
\node[] at (-2,-2.5) {Reader/Writer};
\node[kkiste] at (-2,-3.5) {OBJ};
\node[] at (-2,-4.25) {$\vdots$};
\node[kkiste] at (-2,-5.25) {Custom file format};
\node[] at (2,-2.5) {Importer/Exporter};
\node[kkiste] at (2,-3.5) {OpenMesh};
\node[] at (2,-4.25) {$\vdots$};
\node[kkiste] at (2,-5.25) {Custom data structure};
\path [draw,thick,>=latex,<->] (-0.1,-0.6) -- (-2,-1.9) {};
\path [draw,thick,>=latex,<->] (0.1,-0.6) -- (2,-1.9) {};
\path [draw,thick,>=latex,->] (-4.4,-3.8) -- (-3.6,-3.8) {};
\path [draw,thick,>=latex,<-] (-4.4,-4.2) -- (-3.6,-4.2) {};
\path [draw,thick,>=latex,->] (4.4,-3.8) -- (3.6,-3.8) {};
\path [draw,thick,>=latex,<-] (4.4,-4.2) -- (3.6,-4.2) {};
\end{tikzpicture}
\end{center}
\end{document}
+175
View File
@@ -0,0 +1,175 @@
\documentclass{minimal}
% Tikz
\usepackage{pgf}
\usepackage{tikz}
\usepackage{color}
\definecolor{VCI}{RGB}{55,91,64}
\begin{document}
\begin{center}
%\colorbox{VCI}{
\begin{tikzpicture}
[
vertex/.style={draw=none,circle,fill=white,minimum size=2pt},
edge/.style={draw,white,thick},
hedge/.style={->,>=latex,shorten >=5pt,draw,white,very thick},
redge/.style={line width=3pt,color=red!50!white}
]
\begin{scope}[yshift=-3.6cm]
\begin{scope}[xshift=-4cm,x={(1.4,0)},y={(0,1.4)}]
\coordinate (V1) at (-1,1);
\coordinate (V2) at (-1,3);
\coordinate (V3) at (0,0);
\coordinate (V4) at (0,2);
\coordinate (V5) at (0,4);
\coordinate (V6) at (1,3);
\coordinate (V7) at (1,1);
\draw[edge] (V1) -- (V2) {};
\draw[edge] (V2) -- (V4) {};
\draw[hedge] ([xshift=-2pt]V4) -- ([xshift=-2pt]V3) {};
\draw[hedge,color=red!50!white] ([xshift=2pt]V3) -- ([xshift=2pt]V4) {};
\draw[edge] (V3) -- (V1) {};
\draw[edge] (V4) -- (V6) {};
\draw[edge] (V6) -- (V7) {};
\draw[edge] (V7) -- (V3) {};
\draw[edge] (V2) -- (V5) {};
\draw[edge] (V5) -- (V6) {};
\node[vertex] at (V1) {};
\node[vertex] at (V2) {};
\node[vertex] at (V3) {};
\node[vertex] at (V4) {};
\node[vertex] at (V5) {};
\node[vertex] at (V6) {};
\node[vertex] at (V7) {};
\end{scope}
\draw[->,>=latex,thick,white] (-1.5, 4) arc (105:75:6);
\node[above] at (0, 4.2) {\textcolor{white}{\textbf{Collapse edge}}};
\begin{scope}[xshift=4cm,x={(1.4,0)},y={(0,1.4)}]
\coordinate (V1) at (-1,1);
\coordinate (V2) at (-1,3);
%\coordinate (V3) at (0,0);
\coordinate (V4) at (0,2);
\coordinate (V5) at (0,4);
\coordinate (V6) at (1,3);
\coordinate (V7) at (1,1);
\draw[edge] (V1) -- (V2) {};
\draw[edge] (V2) -- (V4) {};
\draw[edge] (V4) -- (V1) {};
\draw[edge] (V4) -- (V6) {};
\draw[edge] (V6) -- (V7) {};
\draw[edge] (V7) -- (V4) {};
\draw[edge] (V2) -- (V5) {};
\draw[edge] (V5) -- (V6) {};
\node[vertex] at (V1) {};
\node[vertex] at (V2) {};
\node[vertex] at (V4) {};
\node[vertex] at (V5) {};
\node[vertex] at (V6) {};
\node[vertex] at (V7) {};
\end{scope}
\end{scope}
\begin{scope}[yshift=3.6cm]
\begin{scope}[xshift=-4cm,x={(1.4,0)},y={(0,1.4)}]
\coordinate (V1) at (-1,1);
\coordinate (V2) at (-1,3);
\coordinate (V3) at (0,0);
\coordinate (V4) at (0,2);
\coordinate (V5) at (0,4);
\coordinate (V6) at (1,3);
\coordinate (V7) at (1,1);
\draw[edge] (V1) -- (V2) {};
\draw[edge] (V2) -- (V4) {};
\draw[hedge,color=red!50!white] ([xshift=-2pt]V4) -- ([xshift=-2pt]V3) {};
\draw[hedge] ([xshift=2pt]V3) -- ([xshift=2pt]V4) {};
\draw[edge] (V3) -- (V1) {};
\draw[edge] (V4) -- (V6) {};
\draw[edge] (V6) -- (V7) {};
\draw[edge] (V7) -- (V3) {};
\draw[edge] (V2) -- (V5) {};
\draw[edge] (V5) -- (V6) {};
\node[vertex] at (V1) {};
\node[vertex] at (V2) {};
\node[vertex] at (V3) {};
\node[vertex] at (V4) {};
\node[vertex] at (V5) {};
\node[vertex] at (V6) {};
\node[vertex] at (V7) {};
\end{scope}
\draw[->,>=latex,thick,white] (-1.5, 4) arc (105:75:6);
\node[above] at (0, 4.2) {\textcolor{white}{\textbf{Collapse edge}}};
\begin{scope}[xshift=4cm,x={(1.4,0)},y={(0,1.4)}]
\coordinate (V1) at (-1,1);
\coordinate (V2) at (-1,3);
\coordinate (V3) at (0,0);
%\coordinate (V4) at (0,2);
\coordinate (V5) at (0,4);
\coordinate (V6) at (1,3);
\coordinate (V7) at (1,1);
\draw[edge] (V1) -- (V2) {};
\draw[edge] (V2) -- (V3) {};
\draw[edge] (V3) -- (V1) {};
\draw[edge] (V3) -- (V6) {};
\draw[edge] (V6) -- (V7) {};
\draw[edge] (V7) -- (V3) {};
\draw[edge] (V2) -- (V5) {};
\draw[edge] (V5) -- (V6) {};
\node[vertex] at (V1) {};
\node[vertex] at (V2) {};
\node[vertex] at (V3) {};
\node[vertex] at (V5) {};
\node[vertex] at (V6) {};
\node[vertex] at (V7) {};
\end{scope}
\end{scope}
\end{tikzpicture}
%}
\end{center}
\end{document}
+79
View File
@@ -0,0 +1,79 @@
\documentclass{minimal}
% Tikz
\usepackage{pgf}
\usepackage{tikz}
\usepackage{color}
\definecolor{VCI}{RGB}{55,91,64}
\begin{document}
\begin{center}
%\colorbox{VCI}{
\begin{tikzpicture}
[
vertex/.style={draw=none,circle,fill=white,minimum size=2pt},
edge/.style={draw,white,thick},
redge/.style={line width=3pt,color=red!50!white}
]
\begin{scope}[xshift=-5cm]
\coordinate (V1) at (-3,3);
\coordinate (V2) at (0,0);
\coordinate (V3) at (0,6);
\coordinate (V4) at (3,3);
\draw[edge] (V1) to (V2) {};
\draw[edge] (V1) -- (V3) {};
\draw[redge] (V1) -- (V4) {};
\draw[edge] (V2) -- (V4) {};
\draw[edge] (V3) -- (V4) {};
\node[vertex] at (V1) {};
\node[vertex] at (V2) {};
\node[vertex] at (V3) {};
\node[vertex] at (V4) {};
\end{scope}
\draw[->,>=latex,thick,white] (-1.5, 4) arc (105:75:6);
\node[above] at (0, 4.2) {\textcolor{white}{\textbf{Flip edge}}};
\begin{scope}[xshift=5cm]
\coordinate (V1) at (-3,3);
\coordinate (V2) at (0,0);
\coordinate (V3) at (0,6);
\coordinate (V4) at (3,3);
\draw[edge] (V1) to (V2) {};
\draw[edge] (V1) -- (V3) {};
\draw[redge] (V2) -- (V3) {};
\draw[edge] (V2) -- (V4) {};
\draw[edge] (V3) -- (V4) {};
\node[vertex] at (V1) {};
\node[vertex] at (V2) {};
\node[vertex] at (V3) {};
\node[vertex] at (V4) {};
\end{scope}
\end{tikzpicture}
%}
\end{center}
\end{document}
+48
View File
@@ -0,0 +1,48 @@
\documentclass{minimal}
% Tikz
\usepackage{pgf}
\usepackage{tikz}
\begin{document}
\begin{center}
\begin{tikzpicture}
[
vertex/.style={draw=none,circle,fill=black,minimum size=2pt},
oedge/.style={->,>=latex,shorten >=6pt,draw,black,thick},
roedge/.style={->,>=latex,shorten >=6pt,draw,black,thick,color=red}
]
\coordinate (V1) at (-3,3);
\coordinate (V2) at (0,0);
\coordinate (V3) at (0,6);
\coordinate (V4) at (3,3);
\path[roedge] ([yshift=3pt]V1) to ([yshift=3pt]V2) {};
\path[oedge] ([yshift=-3pt]V2) to ([yshift=-3pt]V1) {};
\path[oedge] ([yshift=3pt]V1) -- ([yshift=3pt]V3) {};
\path[roedge] ([yshift=-3pt]V3) -- ([yshift=-3pt]V1) {};
\path[oedge] ([xshift=2pt]V3) -- ([xshift=2pt]V2) {};
\path[roedge] ([xshift=-2pt]V2) -- ([xshift=-2pt]V3) {};
\path[oedge] ([yshift=3pt]V2) -- ([yshift=3pt]V4) {};
\path[oedge] ([yshift=-3pt]V4) -- ([yshift=-3pt]V2) {};
\path[oedge] ([yshift=3pt]V3) -- ([yshift=3pt]V4) {};
\path[oedge] ([yshift=-3pt]V4) -- ([yshift=-3pt]V3) {};
\node[vertex] at (V1) {};
\node[vertex] at (V2) {};
\node[vertex] at (V3) {};
\node[vertex] at (V4) {};
\draw[->,>= latex,thick] (-0.4,3) arc (0:320:20pt);
\end{tikzpicture}
\end{center}
\end{document}
+50
View File
@@ -0,0 +1,50 @@
\documentclass{minimal}
% Tikz
\usepackage{pgf}
\usepackage{tikz}
\begin{document}
\begin{center}
\begin{tikzpicture}
[
vertex/.style={draw=none,circle,fill=white,minimum size=2pt},
vertex/.style={draw=none,circle,fill=white,minimum size=2pt},
oedge/.style={->,>=latex,shorten >=6pt,draw,white,thick},
roedge/.style={->,>=latex,shorten >=6pt,draw,thick,color=red!60!white},
boedge/.style={->,>=latex,shorten >=6pt,draw,thick,color=blue!60!white}
]
\coordinate (V1) at (-3,3);
\coordinate (V2) at (0,0);
\coordinate (V3) at (0,6);
\coordinate (V4) at (3,3);
\path[boedge] ([yshift=3pt]V1) to ([yshift=3pt]V2) {};
\path[roedge] ([yshift=-3pt]V2) to ([yshift=-3pt]V1) {};
\path[oedge] ([yshift=3pt]V1) -- ([yshift=3pt]V3) {};
\path[oedge] ([yshift=-3pt]V3) -- ([yshift=-3pt]V1) {};
\path[boedge] ([xshift=2pt]V3) -- ([xshift=2pt]V2) {};
\path[roedge] ([xshift=-2pt]V2) -- ([xshift=-2pt]V3) {};
\path[roedge] ([yshift=3pt]V2) -- ([yshift=3pt]V4) {};
\path[boedge] ([yshift=-3pt]V4) -- ([yshift=-3pt]V2) {};
\path[oedge] ([yshift=3pt]V3) -- ([yshift=3pt]V4) {};
\path[oedge] ([yshift=-3pt]V4) -- ([yshift=-3pt]V3) {};
\node[vertex] at (V1) {};
\node[vertex] at (V2) {};
\node[vertex] at (V3) {};
\node[vertex] at (V4) {};
%\draw[->, thick] (-0.4,3) arc (0:320:20pt);
\end{tikzpicture}
\end{center}
\end{document}
+48
View File
@@ -0,0 +1,48 @@
\documentclass{minimal}
% Tikz
\usepackage{pgf}
\usepackage{tikz}
\begin{document}
\begin{center}
\begin{tikzpicture}
[
vertex/.style={draw=none,circle,fill=black,minimum size=2pt},
oedge/.style={->,>=latex,shorten >=6pt,draw,black,thick},
roedge/.style={->,>=latex,shorten >=6pt,draw,black,thick,color=red}
]
\coordinate (V1) at (-3,3);
\coordinate (V2) at (0,0);
\coordinate (V3) at (0,6);
\coordinate (V4) at (3,3);
\path[oedge] ([yshift=3pt]V1) to ([yshift=3pt]V2) {};
\path[oedge] ([yshift=-3pt]V2) to ([yshift=-3pt]V1) {};
\path[oedge] ([yshift=3pt]V1) -- ([yshift=3pt]V3) {};
\path[oedge] ([yshift=-3pt]V3) -- ([yshift=-3pt]V1) {};
\path[oedge] ([xshift=2pt]V3) -- ([xshift=2pt]V2) {};
\path[oedge] ([xshift=-2pt]V2) -- ([xshift=-2pt]V3) {};
\path[oedge] ([yshift=3pt]V2) -- ([yshift=3pt]V4) {};
\path[oedge] ([yshift=-3pt]V4) -- ([yshift=-3pt]V2) {};
\path[oedge] ([yshift=3pt]V3) -- ([yshift=3pt]V4) {};
\path[oedge] ([yshift=-3pt]V4) -- ([yshift=-3pt]V3) {};
\node[vertex] at (V1) {};
\node[vertex] at (V2) {};
\node[vertex] at (V3) {};
\node[vertex] at (V4) {};
%\draw[->, thick] (-0.4,3) arc (0:320:20pt);
\end{tikzpicture}
\end{center}
\end{document}
+50
View File
@@ -0,0 +1,50 @@
\documentclass{minimal}
% Tikz
\usepackage{pgf}
\usepackage{tikz}
\begin{document}
\begin{center}
\begin{tikzpicture}
[
vertex/.style={draw=none,circle,fill=white,minimum size=2pt},
vertex/.style={draw=none,circle,fill=white,minimum size=2pt},
oedge/.style={->,>=latex,shorten >=6pt,draw,white,thick},
roedge/.style={->,>=latex,shorten >=6pt,draw,thick,color=red!60!white},
boedge/.style={->,>=latex,shorten >=6pt,draw,thick,color=blue!60!white}
]
\coordinate (V1) at (-3,3);
\coordinate (V2) at (0,0);
\coordinate (V3) at (0,6);
\coordinate (V4) at (3,3);
\path[oedge] ([yshift=3pt]V1) to ([yshift=3pt]V2) {};
\path[oedge] ([yshift=-3pt]V2) to ([yshift=-3pt]V1) {};
\path[boedge] ([yshift=3pt]V1) -- ([yshift=3pt]V3) {};
\path[roedge] ([yshift=-3pt]V3) -- ([yshift=-3pt]V1) {};
\path[oedge] ([xshift=2pt]V3) -- ([xshift=2pt]V2) {};
\path[oedge] ([xshift=-2pt]V2) -- ([xshift=-2pt]V3) {};
\path[oedge] ([yshift=3pt]V2) -- ([yshift=3pt]V4) {};
\path[oedge] ([yshift=-3pt]V4) -- ([yshift=-3pt]V2) {};
\path[oedge] ([yshift=3pt]V3) -- ([yshift=3pt]V4) {};
\path[oedge] ([yshift=-3pt]V4) -- ([yshift=-3pt]V3) {};
\node[vertex] at (V1) {};
\node[vertex] at (V2) {};
\node[vertex] at (V3) {};
\node[vertex] at (V4) {};
%\draw[->, thick] (-0.4,3) arc (0:320:20pt);
\end{tikzpicture}
\end{center}
\end{document}
+48
View File
@@ -0,0 +1,48 @@
\documentclass{minimal}
% Tikz
\usepackage{pgf}
\usepackage{tikz}
\begin{document}
\begin{center}
\begin{tikzpicture}
[
vertex/.style={draw=none,circle,fill=black,minimum size=2pt},
oedge/.style={->,>=latex,shorten >=6pt,draw,black,thick},
roedge/.style={->,>=latex,shorten >=6pt,draw,black,thick,color=red}
]
\coordinate (V1) at (-3,3);
\coordinate (V2) at (0,0);
\coordinate (V3) at (0,6);
\coordinate (V4) at (3,3);
\path[oedge] ([yshift=3pt]V1) to ([yshift=3pt]V2) {};
\path[roedge] ([yshift=-3pt]V2) to ([yshift=-3pt]V1) {};
\path[roedge] ([yshift=3pt]V1) -- ([yshift=3pt]V3) {};
\path[oedge] ([yshift=-3pt]V3) -- ([yshift=-3pt]V1) {};
\path[oedge] ([xshift=2pt]V3) -- ([xshift=2pt]V2) {};
\path[oedge] ([xshift=-2pt]V2) -- ([xshift=-2pt]V3) {};
\path[oedge] ([yshift=3pt]V2) -- ([yshift=3pt]V4) {};
\path[roedge] ([yshift=-3pt]V4) -- ([yshift=-3pt]V2) {};
\path[roedge] ([yshift=3pt]V3) -- ([yshift=3pt]V4) {};
\path[oedge] ([yshift=-3pt]V4) -- ([yshift=-3pt]V3) {};
\node[vertex] at (V1) {};
\node[vertex] at (V2) {};
\node[vertex] at (V3) {};
\node[vertex] at (V4) {};
\draw[<-,>= latex,thick] (3.3,3) arc (0:320:94pt);
\end{tikzpicture}
\end{center}
\end{document}
+29
View File
@@ -0,0 +1,29 @@
\documentclass{minimal}
% Tikz
\usepackage{pgf}
\usepackage{tikz}
\begin{document}
\begin{center}
\begin{tikzpicture}
[
vertex/.style={draw=none,circle,fill=black,minimum size=2pt},
oedge/.style={->,>=latex,shorten >=6pt,draw,black,thick},
roedge/.style={->,>=latex,shorten >=6pt,draw,black,thick,color=red}
]
\coordinate (V1) at (-3,3);
\coordinate (V2) at (0,0);
\path[oedge] ([yshift=3pt]V1) to ([yshift=3pt]V2) {};
\path[oedge] ([yshift=-3pt]V2) to ([yshift=-3pt]V1) {};
\node[vertex] at (V1) {};
\node[vertex] at (V2) {};
\end{tikzpicture}
\end{center}
\end{document}
+128
View File
@@ -0,0 +1,128 @@
/**
\if OPENMESH_INTERNAL_DOC
\mainpage OpenMesh Documentation
\else
\page OpenMeshDoc OpenMesh Documentation
\endif
\image html OpenMesh_text_128.png
Welcome to the %OpenMesh documentation. %OpenMesh is a generic and efficient library
that offers data structures for representing and manipulating polygonal meshes.
It 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.
Here you can find information on how to build projects using the %OpenMesh library
as well as further information on mesh handling in %OpenMesh.
The tutorials explain how to use %OpenMesh by demonstrating real code examples.
\section openmesh-python OpenMesh Python Bindings
We also provide python bindings for %OpenMesh. You can find them here:<br/>
<tt>https://gitlab.vci.rwth-aachen.de:9000/OpenMesh/openmesh-python</tt>
\section iov Building OpenMesh
In this section all necessary information on how to build projects using %OpenMesh
is given.
\li \subpage compiling
\li \subpage compiling_tests
<br /><br />
\subpage mesh_docu
We provide a short overview over the functionality of the %OpenMesh
library and some additional concepts in \ref tutorial. Additionally, we explain the
most important topics of %OpenMesh in the following sections:
\li \ref mesh_features
\li \ref mesh_hds
\li \ref mesh_iterators
\li \ref mesh_navigation
\li \ref mesh_io
\li \ref mesh_operations
\li \ref mesh_hierarchy
The %OpenMeshTools library that contains some useful tools
for i.e. mesh processing:
\li \subpage tools_docu
<br /><br />
\subpage tutorial
This section is supposed to introduce the basic concepts of
%OpenMesh. <!--For detailed information, consult the online documentation
(\subpage 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.-->
\li \ref mesh_type
\li \ref tutorial_01
\li \ref tutorial_build
\li \ref tutorial_build_internal_apps
\li \ref tutorial_02
\li \ref tutorial_03
\li \ref tutorial_04
\li \ref tutorial_11
\li \ref tutorial_12
\li \ref tutorial_05
\li \ref tutorial_06
\li \ref tutorial_07
\li \ref tutorial_07b
\li \ref tutorial_08
\li \ref tutorial_09
\li \ref tutorial_10
<br /><br />
\subpage additional_information
\li \ref mesh_first_to_read
\li \ref mesh_cpp
\li \ref mesh_members
\li \ref naming_conventions
\li \ref mesh_speedup
\li \ref om_changelog
\page mesh_docu Using and understanding OpenMesh
\li \subpage mesh_features
\li \subpage mesh_hds
\li \subpage mesh_iterators
\li \subpage mesh_navigation
\li \subpage mesh_io
\li \subpage mesh_operations
\li \subpage mesh_hierarchy
\li \subpage mesh_type
\li \subpage mesh_eigen
\page additional_information Additional Information on OpenMesh
\li \subpage mesh_first_to_read
\li \subpage mesh_cpp
\li \subpage mesh_members
\li \subpage naming_conventions
\li \subpage mesh_speedup
\li \subpage om_changelog
**/
+1057
View File
File diff suppressed because it is too large Load Diff
+31
View File
@@ -0,0 +1,31 @@
//-----------------------------------------------------------------------------
/** \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 MyClassT_impl.hh for Header only C++-Implementation of template 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>
**/
//-----------------------------------------------------------------------------
+82
View 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.
*/
+116
View File
@@ -0,0 +1,116 @@
/** \page mesh_navigation How to navigate on a mesh
\section nav_overview Overview
\li \ref nav_intro
\li \ref nav_he
\li \ref nav_bound
\li \ref nav_io
\li \ref nav_opposite
\li \ref nav_to_from
\section nav_intro Introduction
In this tutorial you will learn how to navigate on a mesh using
the %OpenMesh library. In the previous chapter (see \ref mesh_iterators) you have learned
how to iterate over vertices, edges, halfedges and faces as well as
circulate over certain structures such as 1-rings and many more.
So in this tutorial we will focus on efficiently using the
halfedge data structure and some very useful attributes such as
the boundary flag. We assume that you already made yourself familiar with the halfedge
structure which is used in %OpenMesh. Further information on this topic
can be found in \ref mesh_hds.
\section nav_he Navigating over halfedges
So let's start with navigating over halfedges of a mesh.
Assume we have the following mesh topology:
\image html mesh.normal.png
We can now select an arbitrary halfedge of this mesh which then offers
either one of two possible navigations:
\li If the chosen halfedge lies at a boundary or in other
words is not adjacent to a face, we can now navigate
along the boundary (or hole) of our mesh by using \c next_halfedge_handle()
or \c prev_halfedge_handle():
\image html mesh.outer.png
\li If the chosen halfedge is adjacent to a face, we can then navigate
along all halfedges that are adjacent to this face. In other words we circulate
around the inner halfedges of one face:
\image html mesh.inner.png
In both cases the code would look something like the following example.
Depending on whether the initial halfedge is adjacent to a face or not,
we will either navigate on the boundary halfedges of our mesh or along
the inner halfedges of a face:
\include nav_code1.cc
References:<br />
OpenMesh::Concepts::KernelT< FinalMeshItems >::next_halfedge_handle()<br />
OpenMesh::Concepts::KernelT< FinalMeshItems >::prev_halfedge_handle()
\section nav_bound Mesh boundaries
As you have seen in the previous section, navigating along boundaries
is very simple. In general %OpenMesh also offers a boundary attribute
for edges, vertices and faces. So testing i.e. whether a face is a boundary
face is quite simple using OpenMesh::PolyConnectivity::is_boundary().<br />
\note You can iterate along boundaries by using the next_halfedge_handle(). If you are on a boundary, the next halfedge is guaranteed to be also a boundary halfedge.
So for each type we can make use of one of the following functions:
\include nav_code2.cc
\section nav_io Using incoming and outgoing halfedges
%OpenMesh offers quite a lot of iterators and circulators to easily iterate
over the structures of a mesh. A very helpful iterator is the
OpenMesh::PolyConnectivity::VertexIHalfedgeIter or the OpenMesh::PolyConnectivity::VertexOHalfedgeIter which are used to iterate
over all incoming/outgoing halfedges of a vertex.
So, sticking to the illustration below, a OpenMesh::PolyConnectivity:V:ertexIHalfedgeIter for the
lower most vertex would iterate over all incoming halfedges (blue),
whereas the OpenMesh::PolyConnectivity::OpenMesh::PolyConnectivity::VertexOHalfedgeIter would iterate over all outgoing halfedges (red):
\image html mesh.inout.png
A schematic code example of how to use the halfedge iterators as described above:
\include nav_code3.cc
\section nav_opposite Using opposite halfedges
The halfedge structure splits every edge into two directional parts by creating two
directed edges out of one undirected edge. So for every halfedge there exists its
counterpart pointing in the opposite direction. %OpenMesh allows to easily navigate
through opposing halfedges via the function OpenMesh::Concepts::KernelT< FinalMeshItems >::opposite_halfedge_handle().
So in the illustration below \c opposite_halfedge_handle() for the blue halfedge would
return the red halfedge:
\image html mesh.opp.png
Use this function as described in the example below:
\include nav_code4a.cc
There are also a few more functions that offer easy access to opposing structures:
\include nav_code4.cc
\section nav_to_from Getting the to and from vertices
\image html mesh.to.from.png
If you have an halfedge, you can get the to and the from handles of the adjacent vertices.
\note The halfedges have a direction. Therefore the to vertex is the from vertex of the opposite halfedge and vice versa.
\include nav_code_to_from.cc
*/
+134
View File
@@ -0,0 +1,134 @@
/** \page mesh_operations Some basic operations: Flipping and collapsing edges
In this section you will learn about some basic operations on a mesh that %OpenMesh
already provides. Comprising the flipping of edges in a triangle mesh as well as
collapsing edges by joining the two adjacent vertices.
\li \ref op_flip
\li \ref op_collapse
\section op_flip Flipping edges in triangle meshes
Considering two adjacent faces of a triangle mesh, there exist exactly two
different configurations of the inner edge. Calling the function
OpenMesh::TriConnectivity::flip(EdgeHandle _eh) will flip the specified edge to
its opposite orientation as shown in the illustration below.
\image html mesh.flip.png "Flipping edges in a triangle mesh"
So, the following snippet of code shows how to use this in your applications:
\code
TriMesh mesh;
// Add some vertices
TriMesh::VertexHandle vhandle[4];
vhandle[0] = mesh.add_vertex(MyMesh::Point(0, 0, 0));
vhandle[1] = mesh.add_vertex(MyMesh::Point(0, 1, 0));
vhandle[2] = mesh.add_vertex(MyMesh::Point(1, 1, 0));
vhandle[3] = mesh.add_vertex(MyMesh::Point(1, 0, 0));
// Add two faces
std::vector<TriMesh::VertexHandle> face_vhandles;
face_vhandles.push_back(vhandle[2]);
face_vhandles.push_back(vhandle[1]);
face_vhandles.push_back(vhandle[0]);
mesh.add_face(face_vhandles);
face_vhandles.clear();
face_vhandles.push_back(vhandle[2]);
face_vhandles.push_back(vhandle[0]);
face_vhandles.push_back(vhandle[3]);
mesh.add_face(face_vhandles);
// Now the edge adjacent to the two faces connects
// vertex vhandle[0] and vhandle[2].
// Find this edge and then flip it
for(TriMesh::EdgeIter it = mesh.edges_begin(); it != mesh.edges_end(); ++it) {
if(!mesh.is_boundary(*it)) {
// Flip edge
mesh.flip(*it);
}
}
// The edge now connects vertex vhandle[1] and vhandle[3].
\endcode
\section op_collapse Collapsing edges
In this section you will learn how to collapse edges such that the
two adjacent vertices join. %OpenMesh provides the function OpenMesh::PolyConnectivity::collapse(HalfedgeHandle _heh) to
perform this operation. This will collapse the from-vertex (remeber that halfedges are directed)
to the to-vertex of the halfedge as illustrated below. Note that collapsing edges
might cause topological inconsistencies to your mesh. You should verify consistency after
collapsing edges by calling OpenMesh::PolyConnectivity::is_collapse_ok().
\note You have to request status attributes in order to use the collapse and delete functions!
\image html mesh.collapse.png "Collapsing will always be performed in the direction the halfedge points to."
A simple code example related to the illustration might look like this:
\code
PolyMesh mesh;
// Request required status flags
mesh.request_vertex_status();
mesh.request_edge_status();
mesh.request_face_status();
// Add some vertices as in the illustration above
PolyMesh::VertexHandle vhandle[7];
vhandle[0] = mesh.add_vertex(MyMesh::Point(-1, 1, 0));
vhandle[1] = mesh.add_vertex(MyMesh::Point(-1, 3, 0));
vhandle[2] = mesh.add_vertex(MyMesh::Point(0, 0, 0));
vhandle[3] = mesh.add_vertex(MyMesh::Point(0, 2, 0));
vhandle[4] = mesh.add_vertex(MyMesh::Point(0, 4, 0));
vhandle[5] = mesh.add_vertex(MyMesh::Point(1, 1, 0));
vhandle[6] = mesh.add_vertex(MyMesh::Point(1, 3, 0));
// Add three quad faces
std::vector<PolyMesh::VertexHandle> face_vhandles;
face_vhandles.push_back(vhandle[1]);
face_vhandles.push_back(vhandle[0]);
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[1]);
face_vhandles.push_back(vhandle[3]);
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[3]);
face_vhandles.push_back(vhandle[2]);
face_vhandles.push_back(vhandle[6]);
face_vhandles.push_back(vhandle[5]);
mesh.add_face(face_vhandles);
// Now find the edge between vertex vhandle[2]
// and vhandle[3]
for(PolyMesh::HalfedgeIter it = mesh.halfedges_begin(); it != mesh.halfedges_end(); ++it) {
if( mesh.to_vertex_handle(*it) == vhandle[3] &&
mesh.from_vertex_handle(*it) == vhandle[2])
{
// Collapse edge
mesh.collapse(*it);
break;
}
}
// Our mesh now looks like in the illustration above after the collapsing.
\endcode
*/
+54
View File
@@ -0,0 +1,54 @@
//-----------------------------------------------------------------------------
/** \page smoother_docu Smoother Tools
\section OM_Smoother_Overview Overview
The %OpenMesh library provides tools for smoothing Triangle- and Polymeshes
-# Smoother:
-# OpenMesh::Smoother::SmootherT
-# OpenMesh::Smoother::LaplaceSmootherT
-# OpenMesh::Smoother::JacobiLaplaceSmootherT
\section OM_Smoother_Usage Usage
The smoothers directly work on an OpenMesh. The following example shows how to use them:
\code
#include <OpenMesh/Tools/Smoother/JacobiLaplaceSmootherT.hh>
// Initialize smoother with input mesh
OpenMesh::Smoother::JacobiLaplaceSmootherT<MyMesh> smoother(mesh);
smoother.initialize( Tangential_and_Normal, //Smooth direction
C0) //Continuity
// Execute 3 smooth steps
smoother.smooth(3);
\endcode
\section Options
\subsection Continuity
\li C0: shape is continuous, but not the tangent
\li C1: shape and tangent are continuous
\li C2: preserves curvature
\subsection Component
\li Tangential: Smooth in tangential direction
\li Normal: Smooth in normal direction
\li Tangential_and_Normal: Smooth in tangential and normal direction
\subsection localError Local Error
By default, this option is disabled.
You can set local max. local errors (absolute or relative) via following functions:
\code
void OpenMesh::Smoother::SmootherT<Mesh>::set_relative_local_error(Scalar _err);
void OpenMesh::Smoother::SmootherT<Mesh>::set_absolute_local_error(Scalar _err);
void OpenMesh::Smoother::SmootherT<Mesh>::disable_local_error_check();
\endcode
*/
//-----------------------------------------------------------------------------
+25
View File
@@ -0,0 +1,25 @@
//-----------------------------------------------------------------------------
/** \page mesh_speedup Some Notes on how to speedup OpenMesh
On this page we collect some hints which can be used to speedup OpenMesh. This list is not complete, so if you
have additional hints, just tell us.
<ul>
<li> <b>Visual Studio</b>
<ul>
<li>The prebuild binaries we ship are not compiled with full optimization enabled. You can build it yourself with full
optimization. ("Full Optimization" (Project setting: C/C++ ->> Optimization) ). Please remember that you than have
to build everything with this flag to avoid incompatibilities.</li>
</ul>
</li>
</ul>
*/
//-----------------------------------------------------------------------------
+40
View File
@@ -0,0 +1,40 @@
//-----------------------------------------------------------------------------
/** \page subdivider_docu Sudivision Tools
\section OM_Subdivider_Overview Overview
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::ModifiedButterflyT
-# OpenMesh::Subdivider::Uniform::InterpolatingSqrt3LGT
-# OpenMesh::Subdivider::Uniform::CompositeT
-# OpenMesh::Subdivider::Uniform::CatmullClarkT
-# OpenMesh::Subdivider::Uniform::MidpointT
-# Adaptive subdivision
-# OpenMesh::Subdivider::Adaptive::CompositeT
-# Simple subdivision
-# OpenMesh::Subdivider::Uniform::LongestEdgeT
\section OM_Subdivider_Usage Usage
The subdividers directly work on an OpenMesh. The following example shows how to use them:
\code
#include <OpenMesh/Tools/Subdivider/Uniform/CatmullClarkT.hh>
// Initialize subdivider
OpenMesh::Subdivider::Uniform::CatmullClarkT<PolyMesh> catmull;
// Execute 3 subdivision steps
catmull.attach(mesh_);
catmull( 3 );
catmull.detach();
\endcode
*/
//-----------------------------------------------------------------------------
+16
View File
@@ -0,0 +1,16 @@
//-----------------------------------------------------------------------------
/** \page tools_docu OpenMesh Tools Documentation
\li \subpage decimater_docu
\li \subpage subdivider_docu
\li \subpage vdpm_docu
\li \subpage smoother_docu
\li \subpage holefiller_docu
\li \subpage smarttagger_docu
\li Miscellaneous
OpenMesh::StripifierT
*/
// ----------------------------------------------------------------------------
+64
View File
@@ -0,0 +1,64 @@
/** \page tutorial_01 First Steps - Building a cube
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/src/OpenMesh/Core/Mesh, 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
**/

Some files were not shown because too many files have changed in this diff Show More