Merge branch 'midpoint-subdivision' into 'master'
add Midpoint subdivision scheme See merge request !117
This commit is contained in:
@@ -14,6 +14,7 @@ subdivision:
|
||||
-# OpenMesh::Subdivider::Uniform::InterpolatingSqrt3LGT
|
||||
-# OpenMesh::Subdivider::Uniform::CompositeT
|
||||
-# OpenMesh::Subdivider::Uniform::CatmullClarkT
|
||||
-# OpenMesh::Subdivider::Uniform::MidpointT
|
||||
-# Adaptive subdivision
|
||||
-# OpenMesh::Subdivider::Adaptive::CompositeT
|
||||
-# Simple subdivision
|
||||
|
||||
@@ -409,6 +409,22 @@ public:
|
||||
return edge_vec.sqrnorm();
|
||||
}
|
||||
|
||||
/** Calculates the midpoint of the halfedge _heh, defined by the positions of
|
||||
the two incident vertices */
|
||||
Point calc_edge_midpoint(HalfedgeHandle _heh) const
|
||||
{
|
||||
VertexHandle vh0 = this->from_vertex_handle(_heh);
|
||||
VertexHandle vh1 = this->to_vertex_handle(_heh);
|
||||
return 0.5 * (this->point(vh0) + this->point(vh1));
|
||||
}
|
||||
|
||||
/** Calculates the midpoint of the edge _eh, defined by the positions of the
|
||||
two incident vertices */
|
||||
Point calc_edge_midpoint(EdgeHandle _eh) const
|
||||
{
|
||||
return calc_edge_midpoint(this->halfedge_handle(_eh, 0));
|
||||
}
|
||||
|
||||
/** defines a consistent representation of a sector geometry:
|
||||
the halfedge _in_heh defines the sector orientation
|
||||
the vertex pointed by _in_heh defines the sector center
|
||||
|
||||
@@ -88,7 +88,7 @@ namespace Uniform { // BEGIN_NS_UNIFORM
|
||||
|
||||
\note Needs a PolyMesh to work on!
|
||||
*/
|
||||
template <typename MeshType, typename RealType = float>
|
||||
template <typename MeshType, typename RealType = double>
|
||||
class CatmullClarkT : public SubdividerT< MeshType, RealType >
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -77,7 +77,7 @@ namespace Uniform { // BEGIN_NS_DECIMATER
|
||||
|
||||
/** Uniform composite Loop subdivision algorithm
|
||||
*/
|
||||
template <class MeshType, class RealType=float>
|
||||
template <class MeshType, class RealType = double>
|
||||
class CompositeLoopT : public CompositeT<MeshType, RealType>
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -77,7 +77,7 @@ namespace Uniform { // BEGIN_NS_UNIFORM
|
||||
|
||||
/** Uniform composite sqrt(3) subdivision algorithm
|
||||
*/
|
||||
template <typename MeshType, typename RealType=float>
|
||||
template <typename MeshType, typename RealType = double>
|
||||
class CompositeSqrt3T : public CompositeT<MeshType, RealType>
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -82,7 +82,7 @@ namespace Uniform { // BEGIN_NS_UNIFORM
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
template <typename MeshType, typename RealType = float>
|
||||
template <typename MeshType, typename RealType = double>
|
||||
class CompareLengthFunction {
|
||||
public:
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ namespace Uniform { // BEGIN_NS_DECIMATER
|
||||
* M.S. Thesis, Department of Mathematics, University of Utah, August 1987.
|
||||
*
|
||||
*/
|
||||
template <typename MeshType, typename RealType = float>
|
||||
template <typename MeshType, typename RealType = double>
|
||||
class LoopT : public SubdividerT<MeshType, RealType>
|
||||
{
|
||||
public:
|
||||
|
||||
105
src/OpenMesh/Tools/Subdivider/Uniform/MidpointT.hh
Normal file
105
src/OpenMesh/Tools/Subdivider/Uniform/MidpointT.hh
Normal file
@@ -0,0 +1,105 @@
|
||||
#pragma once
|
||||
|
||||
#include <OpenMesh/Core/Mesh/BaseKernel.hh>
|
||||
#include <OpenMesh/Tools/Subdivider/Uniform/SubdividerT.hh>
|
||||
#include <OpenMesh/Core/Utils/PropertyManager.hh>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace OpenMesh {
|
||||
namespace Subdivider {
|
||||
namespace Uniform {
|
||||
|
||||
/**
|
||||
* Midpoint subdivision algorithm.
|
||||
*
|
||||
* With every step, the set of vertices is replaced with by the midpoints of all
|
||||
* current edges. Then, two sets of faces are created to set up the new
|
||||
* connectivity: From all midpoints of edges surrounding an original face, a new
|
||||
* face is created. Also, for all midpoints of edges surrounding an original
|
||||
* vertex, a new face is created.
|
||||
*
|
||||
* @note This algorithm ignores the _update_points option.
|
||||
* @note This algorithm is best suited for closed meshes since boundaries tend
|
||||
* to fragment into isolated faces after a few iterations.
|
||||
*/
|
||||
template<typename MeshType, typename RealType = double>
|
||||
class MidpointT : public SubdividerT<MeshType, RealType>
|
||||
{
|
||||
public:
|
||||
typedef RealType real_t;
|
||||
typedef MeshType mesh_t;
|
||||
typedef SubdividerT<MeshType, RealType> parent_t;
|
||||
|
||||
// Inherited constructors
|
||||
MidpointT() : parent_t() {}
|
||||
MidpointT(mesh_t& _m) : parent_t(_m) {}
|
||||
|
||||
const char* name() const { return "midpoint"; }
|
||||
|
||||
protected: // SubdividerT interface
|
||||
bool prepare(mesh_t& _m)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//! Performs one step of Midpoint subdivision.
|
||||
//! @note The _update_points option is ignored
|
||||
bool subdivide(mesh_t& _m, size_t _n, const bool _update_points = true)
|
||||
{
|
||||
PropertyManager<EPropHandleT<typename mesh_t::VertexHandle>, mesh_t> edge_midpoint(_m, "edge_midpoint");
|
||||
PropertyManager<VPropHandleT<bool>, mesh_t> is_original_vertex(_m, "is_original_vertex");
|
||||
|
||||
for (size_t iteration = 0; iteration < _n; ++iteration) {
|
||||
is_original_vertex.set_range(_m.vertices_begin(), _m.vertices_end(), true);
|
||||
// Create vertices on edge midpoints
|
||||
for (typename mesh_t::EdgeIter it = _m.edges_begin(), end = _m.edges_end(); it != end; ++it) {
|
||||
EdgeHandle eh = *it;
|
||||
VertexHandle new_vh = _m.new_vertex(_m.calc_edge_midpoint(eh));
|
||||
edge_midpoint[eh] = new_vh;
|
||||
is_original_vertex[new_vh] = false;
|
||||
}
|
||||
// Create new faces from original faces
|
||||
for (typename mesh_t::FaceIter it = _m.faces_begin(), end = _m.faces_end(); it != end; ++it) {
|
||||
FaceHandle fh = *it;
|
||||
std::vector<typename mesh_t::VertexHandle> new_corners;
|
||||
for (typename mesh_t::FaceEdgeIter it = _m.fe_begin(fh), end = _m.fe_end(fh); it != end; ++it) {
|
||||
EdgeHandle eh = *it;
|
||||
new_corners.push_back(edge_midpoint[eh]);
|
||||
}
|
||||
_m.add_face(new_corners);
|
||||
}
|
||||
// Create new faces from original vertices
|
||||
for (typename mesh_t::VertexIter it = _m.vertices_begin(), end = _m.vertices_end(); it != end; ++it) {
|
||||
VertexHandle vh = *it;
|
||||
if (is_original_vertex[vh]) {
|
||||
if (!_m.is_boundary(vh)) {
|
||||
std::vector<typename mesh_t::VertexHandle> new_corners;
|
||||
for (typename mesh_t::VertexEdgeIter it = _m.ve_begin(vh), end = _m.ve_end(vh); it != end; ++it) {
|
||||
EdgeHandle eh = *it;
|
||||
new_corners.push_back(edge_midpoint[eh]);
|
||||
}
|
||||
std::reverse(new_corners.begin(), new_corners.end());
|
||||
_m.add_face(new_corners);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (typename mesh_t::VertexIter it = _m.vertices_begin(), end = _m.vertices_end(); it != end; ++it) {
|
||||
VertexHandle vh = *it;
|
||||
if (is_original_vertex[vh]) {
|
||||
_m.delete_vertex(vh);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cleanup(mesh_t& _m)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Uniform
|
||||
} // namespace Subdivider
|
||||
} // namespace OpenMesh
|
||||
@@ -95,7 +95,7 @@ namespace Uniform { // BEGIN_NS_UNIFORM
|
||||
*
|
||||
* Clement Courbet - clement.courbet@ecp.fr
|
||||
*/
|
||||
template <typename MeshType, typename RealType = float>
|
||||
template <typename MeshType, typename RealType = double>
|
||||
class ModifiedButterflyT : public SubdividerT<MeshType, RealType>
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -109,7 +109,7 @@ namespace Uniform { // BEGIN_NS_UNIFORM
|
||||
* Clement Courbet - clement.courbet@ecp.fr
|
||||
*/
|
||||
|
||||
template <typename MeshType, typename RealType = float>
|
||||
template <typename MeshType, typename RealType = double>
|
||||
class InterpolatingSqrt3LGT : public SubdividerT< MeshType, RealType >
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -99,7 +99,7 @@ namespace Uniform { // BEGIN_NS_DECIMATER
|
||||
*
|
||||
* L. Kobbelt, <a href="http://www-i8.informatik.rwth-aachen.de/publications/downloads/sqrt3.pdf">"Sqrt(3) subdivision"</a>, Proceedings of SIGGRAPH 2000.
|
||||
*/
|
||||
template <typename MeshType, typename RealType = float>
|
||||
template <typename MeshType, typename RealType = double>
|
||||
class Sqrt3T : public SubdividerT< MeshType, RealType >
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -79,18 +79,17 @@ namespace OpenMesh {
|
||||
namespace Subdivider {
|
||||
namespace Uniform {
|
||||
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
/** Abstract base class for uniform subdivision algorithms.
|
||||
*
|
||||
* A derived class must overload the following functions:
|
||||
* -# name()
|
||||
* -# prepare()
|
||||
* -# subdivide()
|
||||
* -# cleanup()
|
||||
* -# const char* name() const
|
||||
* -# void prepare(MeshType&)
|
||||
* -# void subdivide(MeshType&, size_t, bool)
|
||||
* -# void cleanup(MeshType&)
|
||||
*/
|
||||
template <typename MeshType, typename RealType=float>
|
||||
template <typename MeshType, typename RealType = double>
|
||||
class SubdividerT : private Utils::Noncopyable
|
||||
{
|
||||
public:
|
||||
@@ -104,7 +103,7 @@ public:
|
||||
//@{
|
||||
/// Constructor to be used with interface 2
|
||||
/// \see attach(), operator()(size_t), detach()
|
||||
SubdividerT(void) : attached_(NULL) { }
|
||||
SubdividerT(void) : attached_() { }
|
||||
|
||||
/// Constructor to be used with interface 1 (calls attach())
|
||||
/// \see operator()( MeshType&, size_t )
|
||||
@@ -112,7 +111,7 @@ public:
|
||||
|
||||
//@}
|
||||
|
||||
/// Descructor (calls detach())
|
||||
/// Destructor (calls detach())
|
||||
virtual ~SubdividerT()
|
||||
{ detach(); }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user