OpenMesh
Loading...
Searching...
No Matches
ModifiedButterFlyT.hh File Reference

The modified butterfly scheme of Denis Zorin, Peter Schröder and Wim Sweldens, ``Interpolating subdivision for meshes with arbitrary topology,'' in Proceedings of SIGGRAPH 1996, ACM SIGGRAPH, 1996, pp. More...

#include <OpenMesh/Tools/Subdivider/Uniform/SubdividerT.hh>
#include <OpenMesh/Core/Utils/vector_cast.hh>
#include <OpenMesh/Core/Utils/Property.hh>
#include <vector>
#include <cmath>
Include dependency graph for ModifiedButterFlyT.hh:

Go to the source code of this file.

Functions

mesh_t::FaceHandle fh_old (_m.face_handle(heh6))
mesh_t::FaceHandle fh_new (_m.new_face())
_m set_next_halfedge_handle (heh4, heh6)
_m set_next_halfedge_handle (heh5, heh4)
_m set_face_handle (heh4, fh_old)
_m set_face_handle (heh5, fh_old)
_m set_face_handle (heh6, fh_old)
_m set_halfedge_handle (fh_old, heh4)
_m set_next_halfedge_handle (heh1, heh3)
_m set_next_halfedge_handle (heh3, heh2)
_m set_face_handle (heh1, fh_new)
_m set_face_handle (heh2, fh_new)
_m set_face_handle (heh3, fh_new)
_m set_halfedge_handle (fh_new, heh1)
void split_edge (mesh_t &_m, const typename mesh_t::EdgeHandle &_eh)

Detailed Description

The modified butterfly scheme of Denis Zorin, Peter Schröder and Wim Sweldens, ``Interpolating subdivision for meshes with arbitrary topology,'' in Proceedings of SIGGRAPH 1996, ACM SIGGRAPH, 1996, pp.

189-192.

Clement Courbet - cleme.nosp@m.nt.c.nosp@m.ourbe.nosp@m.t@ec.nosp@m.p.fr */


CLASS ModifiedButterflyT


-----------------— STL

== NAMESPACE ================================================================

namespace OpenMesh { // BEGIN_NS_OPENMESH namespace Subdivider { // BEGIN_NS_DECIMATER namespace Uniform { // BEGIN_NS_UNIFORM

== CLASS DEFINITION =========================================================

/** Modified Butterfly subdivision algorithm

Implementation of the modified butterfly scheme of Denis Zorin, Peter Schröder and Wim Sweldens, ``Interpolating subdivision for meshes with arbitrary topology,'' in Proceedings of SIGGRAPH 1996, ACM SIGGRAPH, 1996, pp. 189-192.

Clement Courbet - cleme.nosp@m.nt.c.nosp@m.ourbe.nosp@m.t@ec.nosp@m.p.fr */ template <typename MeshType, typename RealType = double> class ModifiedButterflyT : public SubdividerT<MeshType, RealType> { public:

typedef RealType real_t; typedef MeshType mesh_t; typedef SubdividerT< mesh_t, real_t > parent_t;

typedef std::vector< std::vector<real_t> > weights_t; typedef std::vector<real_t> weight_t;

public:

ModifiedButterflyT() : parent_t() { init_weights(); }

explicit ModifiedButterflyT( mesh_t& _m) : parent_t(_m) { init_weights(); }

~ModifiedButterflyT() {}

public:

const char *name() const override { return "Uniform Spectral"; }

/ Pre-compute weights void init_weights(size_t _max_valence=30) { weights.resize(_max_valence);

special case: K==3, K==4 weights[3].resize(4); weights[3][0] = real_t(5.0)/12; weights[3][1] = real_t(-1.0)/12; weights[3][2] = real_t(-1.0)/12; weights[3][3] = real_t(3.0)/4;

weights[4].resize(5); weights[4][0] = real_t(3.0)/8; weights[4][1] = 0; weights[4][2] = real_t(-1.0)/8; weights[4][3] = 0; weights[4][4] = real_t(3.0)/4;

for(unsigned int K = 5; K<_max_valence; ++K) { weights[K].resize(K+1); s(j) = ( 1/4 + cos(2*pi*j/K) + 1/2 * cos(4*pi*j/K) )/K double invK = 1.0/static_cast<double>(K); real_t sum = 0; for(unsigned int j=0; j<K; ++j) { weights[K][j] = static_cast<real_t>((0.25 + cos(2.0*M_PI*static_cast<double>(j)*invK) + 0.5*cos(4.0*M_PI*static_cast<double>(j)*invK))*invK); sum += weights[K][j]; } weights[K][K] = static_cast<real_t>(1.0) - sum; } }

protected:

bool prepare( mesh_t& <em>m ) override { _m.add_property( vp_pos ); m.add_property( ep_pos ); return true; }

bool cleanup( mesh_t& <em>m ) override { _m.remove_property( vp_pos ); m.remove_property( ep_pos ); return true; }

bool subdivide( MeshType& _m, size_t _n , const bool _update_points = true) override {

/TODO:Implement fixed positions

Compute the maximal vertex valence in the mesh unsigned int maxValence = 0; for ( auto vertex : _m.vertices() ) { maxValence = std::max(maxValence,_m.valence(vertex)); }

We pre initialized with 30. If it's larger, we update the weights if (maxValence >= 30) { init_weights( maxValence + 1 ); }

Do n subdivisions for (size_t i=0; i < _n; ++i) {

This is an interpolating scheme, old vertices remain the same. for ( auto vh : _m.vertices()) _m.property( vp_pos, vh ) = _m.point(vh);

Compute position for new vertices and store them in the edge property for (auto eh : _m.edges()) compute_midpoint( _m, eh);

Split each edge at midpoint and store precomputed positions (stored in edge property ep_pos_) in the vertex property vp_pos_;

Attention! Creating new edges, hence make sure the loop ends correctly. for (auto eh : _m.edges()) split_edge(_m, eh );

Commit changes in topology and reconsitute consistency

Attention! Creating new faces, hence make sure the loop ends correctly. for (auto fh : _m.faces()) split_face(_m, fh );

Commit changes in geometry for ( auto vh : m.vertices()) _m.set_point(vh, _m.property( vp_pos, vh ) );

}

return true;

}

private: // topological modifiers

void split_face(mesh_t& _m, const typename mesh_t::FaceHandle& _fh) { typename mesh_t::HalfedgeHandle heh1(_m.halfedge_handle(_fh)), heh2(_m.next_halfedge_handle(_m.next_halfedge_handle(heh1))), heh3(_m.next_halfedge_handle(_m.next_halfedge_handle(heh2)));

Cutting off every corner of the 6_gon corner_cutting( _m, heh1 ); corner_cutting( _m, heh2 ); corner_cutting( _m, heh3 ); }

void corner_cutting(mesh_t& _m, const typename mesh_t::HalfedgeHandle& _he) { Define Halfedge Handles typename mesh_t::HalfedgeHandle heh1(_he), heh5(heh1), heh6(_m.next_halfedge_handle(heh1));

Cycle around the polygon to find correct Halfedge for (; _m.next_halfedge_handle(_m.next_halfedge_handle(heh5)) != heh1; heh5 = _m.next_halfedge_handle(heh5)) {}

typename mesh_t::VertexHandle vh1 = _m.to_vertex_handle(heh1), vh2 = _m.to_vertex_handle(heh5);

typename mesh_t::HalfedgeHandle heh2(_m.next_halfedge_handle(heh5)), heh3(_m.new_edge( vh1, vh2)), heh4(_m.opposite_halfedge_handle(heh3));

/* Intermediate result

          *
       5 /|\
        /_  \
  vh2> *     *
      /|\3   |\
     /_  \|4   \
    *----\*----\*
        1 ^   6
          vh1 (adjust_outgoing halfedge!)

Project OpenMesh, ©  Visual Computing Institute, RWTH Aachen. Documentation generated using doxygen .