First checkin for OpenMesh 2.0
git-svn-id: http://www.openmesh.org/svnrepo/OpenMesh/trunk@2 fdac6126-5c0c-442c-9429-916003d36597
This commit is contained in:
17
Tools/Subdivider/ACGMakefile
Normal file
17
Tools/Subdivider/ACGMakefile
Normal file
@@ -0,0 +1,17 @@
|
||||
#== SYSTEM PART -- DON'T TOUCH ==============================================
|
||||
include $(ACGMAKE)/Config
|
||||
#==============================================================================
|
||||
|
||||
|
||||
SUBDIRS = $(call find-subdirs)
|
||||
|
||||
PACKAGES :=
|
||||
|
||||
PROJ_LIBS :=
|
||||
|
||||
MODULES := cxxlib
|
||||
|
||||
|
||||
#== SYSTEM PART -- DON'T TOUCH ==============================================
|
||||
include $(ACGMAKE)/Rules
|
||||
#==============================================================================
|
||||
17
Tools/Subdivider/Adaptive/ACGMakefile
Normal file
17
Tools/Subdivider/Adaptive/ACGMakefile
Normal file
@@ -0,0 +1,17 @@
|
||||
#== SYSTEM PART -- DON'T TOUCH ==============================================
|
||||
include $(ACGMAKE)/Config
|
||||
#==============================================================================
|
||||
|
||||
|
||||
SUBDIRS = $(call find-subdirs)
|
||||
|
||||
PACKAGES := qt glut opengl x11 math
|
||||
|
||||
PROJ_LIBS = OpenMesh/Core
|
||||
|
||||
MODULES := moc cxx
|
||||
|
||||
|
||||
#== SYSTEM PART -- DON'T TOUCH ==============================================
|
||||
include $(ACGMAKE)/Rules
|
||||
#==============================================================================
|
||||
17
Tools/Subdivider/Adaptive/Composite/ACGMakefile
Normal file
17
Tools/Subdivider/Adaptive/Composite/ACGMakefile
Normal file
@@ -0,0 +1,17 @@
|
||||
#== SYSTEM PART -- DON'T TOUCH ==============================================
|
||||
include $(ACGMAKE)/Config
|
||||
#==============================================================================
|
||||
|
||||
|
||||
SUBDIRS =
|
||||
|
||||
PACKAGES := math
|
||||
|
||||
PROJ_LIBS = OpenMesh/Core
|
||||
|
||||
MODULES := cxx
|
||||
|
||||
|
||||
#== SYSTEM PART -- DON'T TOUCH ==============================================
|
||||
include $(ACGMAKE)/Rules
|
||||
#==============================================================================
|
||||
307
Tools/Subdivider/Adaptive/Composite/CompositeT.cc
Normal file
307
Tools/Subdivider/Adaptive/Composite/CompositeT.cc
Normal file
@@ -0,0 +1,307 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// OpenMesh
|
||||
// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen
|
||||
// www.openmesh.org
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// License
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation, version 2.1.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Revision: 1802 $
|
||||
// $Date: 2008-05-19 11:55:07 +0200 (Mo, 19. Mai 2008) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
/** \file Adaptive/Composite/CompositeT.cc
|
||||
|
||||
*/
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// CLASS CompositeT - IMPLEMENTATION
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#define OPENMESH_SUBDIVIDER_ADAPTIVE_COMPOSITET_CC
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
#include <OpenMesh/Core/System/config.hh>
|
||||
#include <OpenMesh/Core/System/omstream.hh>
|
||||
#include <OpenMesh/Tools/Subdivider/Adaptive/Composite/CompositeT.hh>
|
||||
#include <OpenMesh/Tools/Subdivider/Adaptive/Composite/RuleInterfaceT.hh>
|
||||
|
||||
|
||||
//== NAMESPACE ================================================================
|
||||
|
||||
namespace OpenMesh { // BEGIN_NS_OPENMESH
|
||||
namespace Subdivider { // BEGIN_NS_DECIMATER
|
||||
namespace Adaptive { // BEGIN_NS_UNIFORM
|
||||
|
||||
|
||||
//== IMPLEMENTATION ==========================================================
|
||||
|
||||
|
||||
template<class M>
|
||||
bool
|
||||
CompositeT<M> ::
|
||||
initialize( void )
|
||||
{
|
||||
typename Mesh::VertexIter v_it;
|
||||
typename Mesh::FaceIter f_it;
|
||||
typename Mesh::EdgeIter e_it;
|
||||
const typename Mesh::Point zero_point(0.0, 0.0, 0.0);
|
||||
|
||||
// ---------------------------------------- Init Vertices
|
||||
for (v_it = mesh_.vertices_begin(); v_it != mesh_.vertices_end(); ++v_it)
|
||||
{
|
||||
mesh_.data(v_it).set_state(0);
|
||||
mesh_.data(v_it).set_final();
|
||||
mesh_.data(v_it).set_position(0, mesh_.point(v_it.handle()));
|
||||
}
|
||||
|
||||
// ---------------------------------------- Init Faces
|
||||
for (f_it = mesh_.faces_begin(); f_it != mesh_.faces_end(); ++f_it)
|
||||
{
|
||||
mesh_.data(f_it).set_state(0);
|
||||
mesh_.data(f_it).set_final();
|
||||
mesh_.data(f_it).set_position(0, zero_point);
|
||||
}
|
||||
|
||||
// ---------------------------------------- Init Edges
|
||||
for (e_it = mesh_.edges_begin(); e_it != mesh_.edges_end(); ++e_it)
|
||||
{
|
||||
mesh_.data(e_it).set_state(0);
|
||||
mesh_.data(e_it).set_final();
|
||||
mesh_.data(e_it).set_position(0, zero_point);
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------- Init Rules
|
||||
|
||||
int n_subdiv_rules_ = 0;
|
||||
|
||||
|
||||
// look for subdivision rule(s)
|
||||
for (size_t i=0; i < n_rules(); ++i) {
|
||||
|
||||
if (rule_sequence_[i]->type()[0] == 'T' ||
|
||||
rule_sequence_[i]->type()[0] == 't')
|
||||
{
|
||||
++n_subdiv_rules_;
|
||||
subdiv_rule_ = rule_sequence_[i];
|
||||
subdiv_type_ = rule_sequence_[i]->subdiv_type();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// check for correct number of subdivision rules
|
||||
assert(n_subdiv_rules_ == 1);
|
||||
|
||||
if (n_subdiv_rules_ != 1)
|
||||
{
|
||||
std::cerr << "Error! More than one subdivision rules not allowed!\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
// check for subdivision type
|
||||
assert(subdiv_type_ == 3 || subdiv_type_ == 4);
|
||||
|
||||
if (subdiv_type_ != 3 && subdiv_type_ != 4)
|
||||
{
|
||||
::omerr() << "Error! Unknown subdivision type in sequence!" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// set pointer to last rule
|
||||
// first_rule_ = rule_sequence_.front();
|
||||
// last_rule_ = rule_sequence_.back(); //[n_rules() - 1];
|
||||
|
||||
// set numbers and previous rule
|
||||
for (size_t i = 0; i < n_rules(); ++i)
|
||||
{
|
||||
rule_sequence_[i]->set_subdiv_type(subdiv_type_);
|
||||
rule_sequence_[i]->set_n_rules(n_rules());
|
||||
rule_sequence_[i]->set_number(i);
|
||||
rule_sequence_[i]->set_prev_rule(rule_sequence_[(i+n_rules()-1)%n_rules()]);
|
||||
rule_sequence_[i]->set_subdiv_rule(subdiv_rule_);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
#define MOBJ mesh_.deref
|
||||
#define TVH to_vertex_handle
|
||||
#define HEH halfedge_handle
|
||||
#define NHEH next_halfedge_handle
|
||||
#define PHEH prev_halfedge_handle
|
||||
#define OHEH opposite_halfedge_handle
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
template<class M>
|
||||
void CompositeT<M>::refine(typename Mesh::FaceHandle& _fh)
|
||||
{
|
||||
std::vector<typename Mesh::HalfedgeHandle> hh_vector;
|
||||
|
||||
// -------------------- calculate new level for faces and vertices
|
||||
int new_face_level =
|
||||
t_rule()->number() + 1 +
|
||||
((int)floor((float)(mesh_.data(_fh).state() - t_rule()->number() - 1)/n_rules()) + 1) * n_rules();
|
||||
|
||||
int new_vertex_level =
|
||||
new_face_level + l_rule()->number() - t_rule()->number();
|
||||
|
||||
// -------------------- store old vertices
|
||||
// !!! only triangle meshes supported!
|
||||
typename Mesh::VertexHandle vh[3];
|
||||
|
||||
vh[0] = mesh_.TVH(mesh_.HEH(_fh));
|
||||
vh[1] = mesh_.TVH(mesh_.NHEH(mesh_.HEH(_fh)));
|
||||
vh[2] = mesh_.TVH(mesh_.PHEH(mesh_.HEH(_fh)));
|
||||
|
||||
// save handles to incoming halfedges for getting the new vertices
|
||||
// after subdivision (1-4 split)
|
||||
if (subdiv_type_ == 4)
|
||||
{
|
||||
hh_vector.clear();
|
||||
|
||||
// green face
|
||||
if (mesh_.data(_fh).final())
|
||||
{
|
||||
typename Mesh::FaceHalfedgeIter fh_it(mesh_.fh_iter(_fh));
|
||||
|
||||
for (; fh_it; ++fh_it)
|
||||
{
|
||||
hh_vector.push_back(mesh_.PHEH(mesh_.OHEH(fh_it.handle())));
|
||||
}
|
||||
}
|
||||
|
||||
// red face
|
||||
else
|
||||
{
|
||||
|
||||
typename Mesh::HalfedgeHandle red_hh(mesh_.data(_fh).red_halfedge());
|
||||
|
||||
hh_vector.push_back(mesh_.PHEH(mesh_.OHEH(mesh_.NHEH(red_hh))));
|
||||
hh_vector.push_back(mesh_.PHEH(mesh_.OHEH(mesh_.PHEH(mesh_.OHEH(red_hh)))));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// -------------------- Average rule before topo rule?
|
||||
if (t_rule()->number() > 0)
|
||||
t_rule()->prev_rule()->raise(_fh, new_face_level-1);
|
||||
|
||||
// -------------------- Apply topological operator first
|
||||
t_rule()->raise(_fh, new_face_level);
|
||||
|
||||
#if 0 // original code
|
||||
assert(MOBJ(_fh).state() >=
|
||||
subdiv_rule_->number()+1+(int) (MOBJ(_fh).state()/n_rules())*n_rules());
|
||||
#else // improved code (use % operation and avoid floating point division)
|
||||
assert( mesh_.data(_fh).state() >= ( t_rule()->number()+1+generation(_fh) ) );
|
||||
#endif
|
||||
|
||||
// raise new vertices to final levels
|
||||
if (subdiv_type_ == 3)
|
||||
{
|
||||
typename Mesh::VertexHandle new_vh(mesh_.TVH(mesh_.NHEH(mesh_.HEH(_fh))));
|
||||
|
||||
// raise new vertex to final level
|
||||
l_rule()->raise(new_vh, new_vertex_level);
|
||||
}
|
||||
|
||||
if (subdiv_type_ == 4)
|
||||
{
|
||||
typename Mesh::HalfedgeHandle hh;
|
||||
typename Mesh::VertexHandle new_vh;
|
||||
|
||||
while (!hh_vector.empty()) {
|
||||
|
||||
hh = hh_vector.back();
|
||||
hh_vector.pop_back();
|
||||
|
||||
// get new vertex
|
||||
new_vh = mesh_.TVH(mesh_.NHEH(hh));
|
||||
|
||||
// raise new vertex to final level
|
||||
l_rule()->raise(new_vh, new_vertex_level);
|
||||
}
|
||||
}
|
||||
|
||||
// raise old vertices to final position
|
||||
l_rule()->raise(vh[0], new_vertex_level);
|
||||
l_rule()->raise(vh[1], new_vertex_level);
|
||||
l_rule()->raise(vh[2], new_vertex_level);
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
template<class M>
|
||||
void CompositeT<M>::refine(typename Mesh::VertexHandle& _vh)
|
||||
{
|
||||
// calculate next final level for vertex
|
||||
int new_vertex_state = generation(_vh) + l_rule()->number() + 1;
|
||||
|
||||
assert( new_vertex_state == mesh_.data(_vh).state()+1 );
|
||||
|
||||
// raise vertex to final position
|
||||
l_rule()->raise(_vh, new_vertex_state);
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
template <class M>
|
||||
std::string CompositeT<M>::rules_as_string(const std::string& _sep) const
|
||||
{
|
||||
std::string seq;
|
||||
typename RuleSequence::const_iterator it = rule_sequence_.begin();
|
||||
|
||||
if ( it != rule_sequence_.end() )
|
||||
{
|
||||
seq = (*it)->type();
|
||||
for (++it; it != rule_sequence_.end(); ++it )
|
||||
{
|
||||
seq += _sep;
|
||||
seq += (*it)->type();
|
||||
}
|
||||
}
|
||||
return seq;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
#undef MOBJ
|
||||
#undef TVH
|
||||
#undef HEH
|
||||
#undef NHEH
|
||||
#undef PHEH
|
||||
#undef OHEH
|
||||
//=============================================================================
|
||||
} // END_NS_ADAPTIVE
|
||||
} // END_NS_SUBDIVIDER
|
||||
} // END_NS_OPENMESH
|
||||
//=============================================================================
|
||||
298
Tools/Subdivider/Adaptive/Composite/CompositeT.hh
Normal file
298
Tools/Subdivider/Adaptive/Composite/CompositeT.hh
Normal file
@@ -0,0 +1,298 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// OpenMesh
|
||||
// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen
|
||||
// www.openmesh.org
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// License
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation, version 2.1.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Revision: 1802 $
|
||||
// $Date: 2008-05-19 11:55:07 +0200 (Mo, 19. Mai 2008) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
/** \file Adaptive/Composite/CompositeT.hh
|
||||
|
||||
*/
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// CLASS CompositeT
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef OPENMESH_SUBDIVIDER_ADAPTIVE_COMPOSITET_HH
|
||||
#define OPENMESH_SUBDIVIDER_ADAPTIVE_COMPOSITET_HH
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
#include <OpenMesh/Core/System/config.hh>
|
||||
#include <OpenMesh/Tools/Subdivider/Adaptive/Composite/CompositeTraits.hh>
|
||||
// --------------------
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
|
||||
//== NAMESPACE ================================================================
|
||||
|
||||
namespace OpenMesh { // BEGIN_NS_OPENMESH
|
||||
namespace Subdivider { // BEGIN_NS_SUBDIVIDER
|
||||
namespace Adaptive { // BEGIN_NS_ADAPTIVE
|
||||
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
|
||||
template <typename R> struct RuleHandleT;
|
||||
template <typename M> class RuleInterfaceT;
|
||||
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
/** Adaptive Composite Subdivision framework.
|
||||
*
|
||||
* The adaptive composite subdivision framework is based on the work
|
||||
* done by P. Oswald and P. Schroeder. This framework elevates the
|
||||
* uniform case of the composite scheme to the adaptive
|
||||
* setting.
|
||||
*
|
||||
* For details on the composite scheme refer to
|
||||
* - <a
|
||||
* href="http://cm.bell-labs.com/who/poswald/sqrt3.pdf">P. Oswald,
|
||||
* P. Schroeder "Composite primal/dual sqrt(3)-subdivision schemes",
|
||||
* CAGD 20, 3, 2003, 135--164</a>
|
||||
*
|
||||
* For details on the transition from uniform to adaptive composite
|
||||
* subdivision please refer to
|
||||
* - <a
|
||||
* href="http://www.eg.org/EG/DL/PE/OPENSG03/04sovakar.pdf>A. von Studnitz,
|
||||
* A. Sovakar, L. Kobbelt "API Design for Adaptive Subdivision
|
||||
* Schemes" OpenSG Symposium 2003</a>
|
||||
*
|
||||
* In the composite scheme a subdivision operator is created by
|
||||
* combining smaller "atomic" rules. Depending on the selection and
|
||||
* ordering of the operator many known subdivision schemes can be
|
||||
* created.
|
||||
*
|
||||
* Every rule inherits from RuleInterfaceT and is represented out of
|
||||
* the subdivider object by a RuleHandleT (as usual within
|
||||
* %OpenMesh). You can add rules using the CompositeT::add()
|
||||
* functions. The correct order of adding the rules is very
|
||||
* important, and furthermore not all rules get along with each other
|
||||
* very well. (Please read the given literature, especially the
|
||||
* paper by Oswald and Schr<68>der.)
|
||||
*
|
||||
* To use a composite subdivider first define a rule sequence
|
||||
* describing the order of execution of the rules. In the order the
|
||||
* rules habe been added they will be executed. E.g. the rules given
|
||||
* in operator notation have to added from right to left.
|
||||
*
|
||||
* After the rule sequence has been defined the subdivider has to be
|
||||
* intialized using CompositeT::initialize(). If everything went well,
|
||||
* use CompositeT::refine() to subdivide locally a face or vertex.
|
||||
*
|
||||
* \note Not all (topological) operators have been implemented!
|
||||
* \note Only triangle meshes are supported.
|
||||
* \note The rule sequence must begin with a topological operator.
|
||||
*
|
||||
* \see RuleInterfaceT, RuleHandleT
|
||||
*
|
||||
*/
|
||||
template <typename M> class CompositeT
|
||||
{
|
||||
public:
|
||||
|
||||
typedef RuleInterfaceT<M> Rule;
|
||||
typedef M Mesh;
|
||||
typedef std::vector<Rule*> RuleSequence;
|
||||
|
||||
typedef typename M::VertexHandle VH;
|
||||
typedef typename M::FaceHandle FH;
|
||||
typedef typename M::EdgeHandle EH;
|
||||
typedef typename M::HalfedgeHandle HH;
|
||||
|
||||
public:
|
||||
|
||||
/// Constructor
|
||||
CompositeT(Mesh& _mesh)
|
||||
: subdiv_type_(0),
|
||||
subdiv_rule_(NULL), /*first_rule_(NULL), last_rule_(NULL),*/ mesh_(_mesh)
|
||||
{ }
|
||||
|
||||
///
|
||||
virtual ~CompositeT()
|
||||
{ cleanup(); }
|
||||
|
||||
|
||||
/// Reset \c self to state after the default constructor except of
|
||||
/// the mesh.
|
||||
void cleanup(void)
|
||||
{
|
||||
subdiv_type_ = 0;
|
||||
subdiv_rule_ = NULL;
|
||||
|
||||
std::for_each(rule_sequence_.begin(),
|
||||
rule_sequence_.end(), DeleteRule() );
|
||||
rule_sequence_.clear();
|
||||
}
|
||||
|
||||
|
||||
/// Initialize faces, edges, vertices, and rules
|
||||
bool initialize(void);
|
||||
|
||||
|
||||
/// Refine one face.
|
||||
void refine(typename Mesh::FaceHandle& _fh);
|
||||
|
||||
|
||||
/// Raise one vertex to next final level.
|
||||
void refine(typename Mesh::VertexHandle& _vh);
|
||||
|
||||
|
||||
/// Return subdivision split type (3 for 1-to-3 split, 4 for 1-to-4 split).
|
||||
int subdiv_type() { return subdiv_type_; }
|
||||
|
||||
|
||||
// Return subdivision rule.
|
||||
const Rule& subdiv_rule() const { return *subdiv_rule_; }
|
||||
|
||||
public:
|
||||
|
||||
/// \name Managing composite rules
|
||||
//*@
|
||||
|
||||
/** Add new rule to rule sequence by passing the type of the wanted
|
||||
* rule as template argument to the method.
|
||||
* \return Valid handle on success. Else it is invalid.
|
||||
*/
|
||||
template < typename R >
|
||||
RuleHandleT<R> add()
|
||||
{
|
||||
size_t idx = rule_sequence_.size();
|
||||
rule_sequence_.push_back( new R( mesh_ ) );
|
||||
return RuleHandleT<R>( (idx < rule_sequence_.size()) ? idx : -1 );
|
||||
}
|
||||
|
||||
/** Add new rule to rule sequence by passing an appropriate handle
|
||||
* to the method.
|
||||
* \return Valid handle on success. Else it is invalid.
|
||||
*/
|
||||
template < typename R >
|
||||
RuleHandleT<R>& add( RuleHandleT<R>& _rh )
|
||||
{
|
||||
return _rh = add< R >();
|
||||
}
|
||||
|
||||
/** Get rule in the rule sequence by a handle.
|
||||
*
|
||||
* \return The wanted rule if the handle is valid. The return value
|
||||
* is undefined if the handle is invalid!
|
||||
*/
|
||||
template < typename R >
|
||||
typename RuleHandleT<R>::Rule& rule( const RuleHandleT<R>& _rh )
|
||||
{
|
||||
typedef typename RuleHandleT<R>::Rule rule_t;
|
||||
assert( _rh.is_valid() );
|
||||
return *dynamic_cast<rule_t*>(rule_sequence_[ _rh.idx() ]);
|
||||
}
|
||||
|
||||
|
||||
/** Get rule (interface) by index
|
||||
*
|
||||
* \return The wanted rule if the handle is valid. The return value
|
||||
* is undefined if the handle is invalid!
|
||||
*/
|
||||
RuleInterfaceT<M>& rule( size_t _idx )
|
||||
{
|
||||
assert( _idx < n_rules() );
|
||||
return *rule_sequence_[ _idx ];
|
||||
}
|
||||
|
||||
/// Number of rules in the rule sequence
|
||||
size_t n_rules() const { return rule_sequence_.size(); }
|
||||
|
||||
/// Return the sequence as string
|
||||
std::string rules_as_string(const std::string& _sep= " * ") const;
|
||||
|
||||
//@}
|
||||
|
||||
protected:
|
||||
|
||||
/// The rule sequence
|
||||
const RuleSequence& rules() const { return rule_sequence_; }
|
||||
|
||||
protected: // helper
|
||||
|
||||
// get current generation from state
|
||||
state_t generation(state_t _s) { return _s-(_s % n_rules()); }
|
||||
state_t generation( VH _vh ) { return generation(mesh_.data(_vh).state()); }
|
||||
state_t generation( EH _eh ) { return generation(mesh_.data(_eh).state()); }
|
||||
state_t generation( FH _fh ) { return generation(mesh_.data(_fh).state()); }
|
||||
|
||||
private:
|
||||
|
||||
// short cuts
|
||||
Rule* t_rule() { return subdiv_rule_; }
|
||||
Rule* f_rule() { return rule_sequence_.front(); }
|
||||
Rule* l_rule() { return rule_sequence_.back(); }
|
||||
|
||||
private:
|
||||
|
||||
//
|
||||
RuleSequence rule_sequence_;
|
||||
|
||||
// Split type
|
||||
int subdiv_type_;
|
||||
|
||||
Rule *subdiv_rule_;
|
||||
// Rule *first_rule_;
|
||||
// Rule *last_rule_;
|
||||
|
||||
//
|
||||
Mesh &mesh_;
|
||||
|
||||
private: // helper
|
||||
|
||||
#ifndef DOXY_IGNORE_THIS
|
||||
struct DeleteRule { void operator()( Rule* _r ) { delete _r; } };
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
CompositeT( const CompositeT& );
|
||||
CompositeT& operator = ( const CompositeT );
|
||||
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
} // END_NS_ADAPTIVE
|
||||
} // END_NS_SUBDIVIDER
|
||||
} // END_NS_OPENMESH
|
||||
//=============================================================================
|
||||
#if defined(OM_INCLUDE_TEMPLATES) && !defined(OPENMESH_SUBDIVIDER_ADAPTIVE_COMPOSITET_CC)
|
||||
# define OPENMESH_SUBDIVIDER_TEMPLATES
|
||||
# include "CompositeT.cc"
|
||||
#endif
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_SUBDIVIDER_ADAPTIVE_COMPOSITET_HH defined
|
||||
//=============================================================================
|
||||
247
Tools/Subdivider/Adaptive/Composite/CompositeTraits.hh
Normal file
247
Tools/Subdivider/Adaptive/Composite/CompositeTraits.hh
Normal file
@@ -0,0 +1,247 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// OpenMesh
|
||||
// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen
|
||||
// www.openmesh.org
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// License
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation, version 2.1.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Revision: 1802 $
|
||||
// $Date: 2008-05-19 11:55:07 +0200 (Mo, 19. Mai 2008) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
/** \file Subdivider/Adaptive/Composite/CompositeTraits.hh
|
||||
Mesh traits for adaptive composite subdivider.
|
||||
*/
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// CLASS Traits
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef OPENMESH_SUBDIVIDER_ADAPTIVE_COMPOSITETRAITS_HH
|
||||
#define OPENMESH_SUBDIVIDER_ADAPTIVE_COMPOSITETRAITS_HH
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
#include <map>
|
||||
#include <OpenMesh/Core/Mesh/Traits.hh>
|
||||
|
||||
//== NAMESPACE ================================================================
|
||||
|
||||
namespace OpenMesh { // BEGIN_NS_OPENMESH
|
||||
namespace Subdivider { // BEGIN_NS_DECIMATER
|
||||
namespace Adaptive { // BEGIN_NS_UNIFORM
|
||||
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
/** Adaptive Composite Subdivision framework.
|
||||
*/
|
||||
|
||||
// typedef unsigned short state_t;
|
||||
// const state_t mask_final = 1 << ((sizeof(state_t)*8)-1);
|
||||
// const state_t mask_state = ~mask_final;
|
||||
|
||||
/** Mesh traits for adaptive composite subdivision
|
||||
*/
|
||||
struct CompositeTraits : public OpenMesh::DefaultTraits
|
||||
{
|
||||
typedef int state_t; ///< External representation for intermediate state
|
||||
typedef bool final_t; ///< External representation for final flag
|
||||
|
||||
|
||||
/// Storage type for intermediate states and the final flag of a mesh entity.
|
||||
struct State
|
||||
{
|
||||
int state : 31;
|
||||
unsigned final : 1;
|
||||
};
|
||||
|
||||
// ---------------------------------------- attributes
|
||||
|
||||
// add face normals
|
||||
FaceAttributes( OpenMesh::Attributes::Normal );
|
||||
|
||||
// add vertex normals
|
||||
VertexAttributes( OpenMesh::Attributes::Normal );
|
||||
|
||||
// add previous halfedge handle
|
||||
HalfedgeAttributes( OpenMesh::Attributes::PrevHalfedge );
|
||||
|
||||
// ---------------------------------------- items
|
||||
|
||||
FaceTraits
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
typedef typename Refs::Point Point;
|
||||
typedef typename Refs::HalfedgeHandle HalfedgeHandle;
|
||||
typedef std::map<state_t, Point> PositionHistory;
|
||||
|
||||
State state_;
|
||||
HalfedgeHandle red_halfedge_;
|
||||
|
||||
PositionHistory pos_map_;
|
||||
|
||||
public:
|
||||
|
||||
// face state
|
||||
state_t state() const { return state_t(state_.state); }
|
||||
void set_state(const state_t _s) { state_.state = _s; }
|
||||
void inc_state() { ++state_.state; }
|
||||
|
||||
// face not final if divided (loop) or edge not flipped (sqrt(3))
|
||||
final_t final() const { return final_t(state_.final); }
|
||||
void set_final() { state_.final = true; }
|
||||
void set_not_final() { state_.final = false; }
|
||||
|
||||
// halfedge of dividing edge (red-green triangulation)
|
||||
const HalfedgeHandle& red_halfedge() const { return red_halfedge_; }
|
||||
void set_red_halfedge(const HalfedgeHandle& _h) { red_halfedge_ = _h; }
|
||||
|
||||
// position of face, depending on generation _i.
|
||||
void set_position(const int& _i, const Point& _p) { pos_map_[_i] = _p; }
|
||||
const Point position(const int& _i) {
|
||||
if (pos_map_.find(_i) != pos_map_.end())
|
||||
return pos_map_[_i];
|
||||
else {
|
||||
|
||||
if (_i <= 0) {
|
||||
return Point(0.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
return position(_i - 1);
|
||||
}
|
||||
}
|
||||
}; // end class FaceTraits
|
||||
|
||||
|
||||
EdgeTraits
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
typedef typename Refs::Point Point;
|
||||
typedef std::map<state_t, Point> PositionHistory;
|
||||
|
||||
State state_;
|
||||
PositionHistory pos_map_;
|
||||
|
||||
public:
|
||||
|
||||
typedef typename Refs::Scalar Scalar;
|
||||
|
||||
// Scalar weight_;
|
||||
|
||||
// state of edge
|
||||
state_t state() const { return state_t(state_.state); }
|
||||
void set_state(const state_t _s) { state_.state = _s; }
|
||||
void inc_state() { ++state_.state; }
|
||||
|
||||
// edge not final if dividing face (Loop) or edge not flipped (SQRT(3))
|
||||
final_t final() const { return final_t(state_.final); }
|
||||
void set_final() { state_.final = true; }
|
||||
void set_not_final() { state_.final = false; }
|
||||
|
||||
// position of edge, depending on generation _i.
|
||||
void set_position(const int& _i, const Point& _p) { pos_map_[_i] = _p; }
|
||||
|
||||
const Point position(const int& _i) {
|
||||
|
||||
if (pos_map_.find(_i) != pos_map_.end())
|
||||
return pos_map_[_i];
|
||||
else
|
||||
{
|
||||
if (_i <= 0)
|
||||
{
|
||||
const Point zero_point(0.0, 0.0, 0.0);
|
||||
return zero_point;
|
||||
}
|
||||
|
||||
return position(_i - 1);
|
||||
}
|
||||
}
|
||||
}; // end class EdgeTraits
|
||||
|
||||
|
||||
VertexTraits
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
typedef typename Refs::Point Point;
|
||||
typedef std::map<state_t, Point> PositionHistory;
|
||||
|
||||
State state_;
|
||||
PositionHistory pos_map_;
|
||||
|
||||
public:
|
||||
|
||||
// state of vertex
|
||||
state_t state() const { return state_.state; }
|
||||
void set_state(const state_t _s) { state_.state = _s; }
|
||||
void inc_state() { ++state_.state; }
|
||||
|
||||
|
||||
// usually not needed by loop or sqrt(3)
|
||||
final_t final() const { return state_.final; }
|
||||
void set_final() { state_.final = true; }
|
||||
void set_not_final() { state_.final = false; }
|
||||
|
||||
// position of vertex, depending on generation _i. (not for display)
|
||||
void set_position(const int& _i, const Point& _p) { pos_map_[_i] = _p; }
|
||||
const Point position(const int& _i) {
|
||||
|
||||
if (pos_map_.find(_i) != pos_map_.end())
|
||||
|
||||
return pos_map_[_i];
|
||||
|
||||
else {
|
||||
|
||||
if (_i <= 0) {
|
||||
|
||||
const Point zero_point(0.0, 0.0, 0.0);
|
||||
return zero_point;
|
||||
}
|
||||
|
||||
return position(_i - 1);
|
||||
}
|
||||
}
|
||||
}; // end class VertexTraits
|
||||
}; // end class CompositeTraits
|
||||
|
||||
|
||||
// export items to namespace to maintain compatibility
|
||||
typedef CompositeTraits::state_t state_t;
|
||||
typedef CompositeTraits::final_t final_t;
|
||||
typedef CompositeTraits::State State;
|
||||
|
||||
//=============================================================================
|
||||
} // END_NS_ADAPTIVE
|
||||
} // END_NS_SUBDIVIDER
|
||||
} // END_NS_OPENMESH
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_SUBDIVIDER_ADAPTIVE_COMPOSITETRAITS_HH defined
|
||||
//=============================================================================
|
||||
389
Tools/Subdivider/Adaptive/Composite/RuleInterfaceT.hh
Normal file
389
Tools/Subdivider/Adaptive/Composite/RuleInterfaceT.hh
Normal file
@@ -0,0 +1,389 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// OpenMesh
|
||||
// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen
|
||||
// www.openmesh.org
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// License
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation, version 2.1.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Revision: 1802 $
|
||||
// $Date: 2008-05-19 11:55:07 +0200 (Mo, 19. Mai 2008) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// CLASS RuleInterfaceT
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef OPENMESH_SUBDIVIDER_ADAPTIVE_RULEINTERFACET_HH
|
||||
#define OPENMESH_SUBDIVIDER_ADAPTIVE_RULEINTERFACET_HH
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
#include <string>
|
||||
#include <OpenMesh/Tools/Subdivider/Adaptive/Composite/CompositeTraits.hh>
|
||||
|
||||
//== NAMESPACE ================================================================
|
||||
|
||||
namespace OpenMesh { // BEGIN_NS_OPENMESH
|
||||
namespace Subdivider { // BEGIN_NS_SUBDIVIDER
|
||||
namespace Adaptive { // BEGIN_NS_ADAPTIVE
|
||||
|
||||
|
||||
//== FORWARDS =================================================================
|
||||
|
||||
template <typename M> class CompositeT;
|
||||
template <typename M> class RuleInterfaceT;
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/** Handle template for adaptive composite subdividion rules
|
||||
* \internal
|
||||
*
|
||||
* Use typed handle of a rule, e.g. Tvv3<MyMesh>::Handle.
|
||||
*/
|
||||
template < typename R >
|
||||
struct RuleHandleT : public BaseHandle
|
||||
{
|
||||
explicit RuleHandleT(int _idx=-1) : BaseHandle(_idx) {}
|
||||
typedef R Rule;
|
||||
|
||||
operator bool() const { return is_valid(); }
|
||||
|
||||
};
|
||||
|
||||
/** Defines the method type() (RuleInterfaceT::type()) and the
|
||||
* typedefs Self and Handle.
|
||||
*/
|
||||
#define COMPOSITE_RULE( classname, mesh_type ) \
|
||||
protected:\
|
||||
friend class CompositeT<mesh_type>; \
|
||||
public: \
|
||||
const char *type() const { return #classname; } \
|
||||
typedef classname<mesh_type> Self; \
|
||||
typedef RuleHandleT< Self > Handle
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Base class for adaptive composite subdivision rules
|
||||
* \see class CompositeT
|
||||
*/
|
||||
template <typename M> class RuleInterfaceT
|
||||
{
|
||||
public:
|
||||
|
||||
typedef M Mesh;
|
||||
typedef RuleInterfaceT<M> Self;
|
||||
typedef RuleHandleT< Self > Rule;
|
||||
|
||||
typedef typename M::Scalar scalar_t;
|
||||
|
||||
protected:
|
||||
|
||||
/// Default constructor
|
||||
RuleInterfaceT(Mesh& _mesh) : mesh_(_mesh) {};
|
||||
|
||||
public:
|
||||
|
||||
/// Destructor
|
||||
virtual ~RuleInterfaceT() {};
|
||||
|
||||
|
||||
/// Returns the name of the rule.
|
||||
/// Use define COMPOSITE_RULE to overload this function in a derived class.
|
||||
virtual const char *type() const = 0;
|
||||
|
||||
public:
|
||||
|
||||
/// \name Raise item
|
||||
//@{
|
||||
/// Raise item to target state \c _target_state.
|
||||
virtual void raise(typename M::FaceHandle& _fh, state_t _target_state)
|
||||
{
|
||||
if (mesh_.data(_fh).state() < _target_state) {
|
||||
update(_fh, _target_state);
|
||||
mesh_.data(_fh).inc_state();
|
||||
}
|
||||
}
|
||||
|
||||
virtual void raise(typename M::EdgeHandle& _eh, state_t _target_state)
|
||||
{
|
||||
if (mesh_.data(_eh).state() < _target_state) {
|
||||
update(_eh, _target_state);
|
||||
mesh_.data(_eh).inc_state();
|
||||
}
|
||||
}
|
||||
|
||||
virtual void raise(typename M::VertexHandle& _vh, state_t _target_state)
|
||||
{
|
||||
if (mesh_.data(_vh).state() < _target_state) {
|
||||
update(_vh, _target_state);
|
||||
mesh_.data(_vh).inc_state();
|
||||
}
|
||||
}
|
||||
//@}
|
||||
|
||||
void update(typename M::FaceHandle& _fh, state_t _target_state)
|
||||
{
|
||||
typename M::FaceHandle opp_fh;
|
||||
|
||||
while (mesh_.data(_fh).state() < _target_state - 1) {
|
||||
prev_rule()->raise(_fh, _target_state - 1);
|
||||
}
|
||||
|
||||
// Don't use unflipped / unfinal faces!!!
|
||||
if (subdiv_type() == 3) {
|
||||
|
||||
if (mesh_.face_handle(mesh_.opposite_halfedge_handle(mesh_.halfedge_handle(_fh))).is_valid()) {
|
||||
|
||||
while (!mesh_.data(_fh).final()) {
|
||||
|
||||
opp_fh = mesh_.face_handle(mesh_.opposite_halfedge_handle(mesh_.halfedge_handle(_fh)));
|
||||
|
||||
assert (mesh_.data(_fh).state() >=
|
||||
mesh_.data(opp_fh).state());
|
||||
|
||||
// different states: raise other face
|
||||
if (mesh_.data(_fh).state() > mesh_.data(opp_fh).state()){
|
||||
|
||||
// raise opposite face
|
||||
prev_rule()->raise(opp_fh, _target_state - 1);
|
||||
}
|
||||
|
||||
else {
|
||||
|
||||
// equal states
|
||||
|
||||
// flip edge
|
||||
// typename M::EdgeHandle eh(mesh_.edge_handle(mesh_.halfedge_handle(_fh)));
|
||||
|
||||
// if (mesh_.is_flip_ok(eh)) {
|
||||
|
||||
// std::cout << "Flipping Edge...\n";
|
||||
|
||||
// mesh_.flip(eh);
|
||||
|
||||
// mesh_.data(_fh).set_final();
|
||||
// mesh_.data(opp_fh).set_final();
|
||||
// }
|
||||
|
||||
// else {
|
||||
|
||||
// std::cout << "Flip not okay.\n";
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
|
||||
// mesh_.data(_fh).set_final();
|
||||
}
|
||||
|
||||
// std::cout << "Raising Face to Level "
|
||||
// << _target_state
|
||||
// << " with "
|
||||
// << type()
|
||||
// << ".\n";
|
||||
|
||||
}
|
||||
|
||||
assert( subdiv_type() != 4 ||
|
||||
mesh_.data(_fh).final() ||
|
||||
_target_state%n_rules() == (subdiv_rule()->number() + 1)%n_rules() );
|
||||
|
||||
typename M::FaceEdgeIter fe_it;
|
||||
typename M::FaceVertexIter fv_it;
|
||||
typename M::EdgeHandle eh;
|
||||
typename M::VertexHandle vh;
|
||||
|
||||
std::vector<typename M::FaceHandle> face_vector;
|
||||
face_vector.clear();
|
||||
|
||||
if (_target_state > 1) {
|
||||
|
||||
for (fe_it = mesh_.fe_iter(_fh); fe_it; ++fe_it) {
|
||||
|
||||
eh = fe_it.handle();
|
||||
prev_rule()->raise(eh, _target_state - 1);
|
||||
}
|
||||
|
||||
for (fv_it = mesh_.fv_iter(_fh); fv_it; ++fv_it) {
|
||||
|
||||
vh = fv_it.handle();
|
||||
prev_rule()->raise(vh, _target_state - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void update(typename M::EdgeHandle& _eh, state_t _target_state)
|
||||
{
|
||||
state_t state(mesh_.data(_eh).state());
|
||||
|
||||
// raise edge to correct state
|
||||
if (state + 1 < _target_state && _target_state > 0) {
|
||||
|
||||
prev_rule()->raise(_eh, _target_state - 1);
|
||||
}
|
||||
|
||||
typename M::VertexHandle vh;
|
||||
typename M::FaceHandle fh;
|
||||
|
||||
if (_target_state > 1)
|
||||
{
|
||||
vh = mesh_.to_vertex_handle(mesh_.halfedge_handle(_eh, 0));
|
||||
prev_rule()->raise(vh, _target_state - 1);
|
||||
|
||||
vh = mesh_.to_vertex_handle(mesh_.halfedge_handle(_eh, 1));
|
||||
prev_rule()->raise(vh, _target_state - 1);
|
||||
|
||||
fh = mesh_.face_handle(mesh_.halfedge_handle(_eh, 0));
|
||||
if (fh.is_valid())
|
||||
prev_rule()->raise(fh, _target_state - 1);
|
||||
|
||||
fh = mesh_.face_handle(mesh_.halfedge_handle(_eh, 1));
|
||||
if (fh.is_valid())
|
||||
prev_rule()->raise(fh, _target_state - 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void update(typename M::VertexHandle& _vh, state_t _target_state) {
|
||||
|
||||
state_t state(mesh_.data(_vh).state());
|
||||
|
||||
// raise vertex to correct state
|
||||
if (state + 1 < _target_state)
|
||||
{
|
||||
prev_rule()->raise(_vh, _target_state - 1);
|
||||
}
|
||||
|
||||
std::vector<typename M::HalfedgeHandle> halfedge_vector;
|
||||
halfedge_vector.clear();
|
||||
|
||||
typename M::VertexOHalfedgeIter voh_it;
|
||||
typename M::EdgeHandle eh;
|
||||
typename M::FaceHandle fh;
|
||||
|
||||
if (_target_state > 1)
|
||||
{
|
||||
|
||||
for (voh_it = mesh_.voh_iter(_vh); voh_it; ++voh_it) {
|
||||
halfedge_vector.push_back(voh_it.handle());
|
||||
}
|
||||
|
||||
while ( !halfedge_vector.empty() ) {
|
||||
eh = mesh_.edge_handle(halfedge_vector.back());
|
||||
halfedge_vector.pop_back();
|
||||
|
||||
prev_rule()->raise(eh, _target_state - 1);
|
||||
}
|
||||
|
||||
for (voh_it = mesh_.voh_iter(_vh); voh_it; ++voh_it) {
|
||||
halfedge_vector.push_back(voh_it.handle());
|
||||
}
|
||||
|
||||
while ( !halfedge_vector.empty() ) {
|
||||
fh = mesh_.face_handle(halfedge_vector.back());
|
||||
halfedge_vector.pop_back();
|
||||
|
||||
if (fh.is_valid())
|
||||
prev_rule()->raise(fh, _target_state - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
|
||||
/// Type of split operation, if it is a topological operator
|
||||
int subdiv_type() const { return subdiv_type_; }
|
||||
|
||||
|
||||
/// Position in rule sequence
|
||||
int number() const { return number_; }
|
||||
|
||||
/// \name Parameterization of rule
|
||||
//@{
|
||||
|
||||
/// Set coefficient - ignored by non-parameterized rules.
|
||||
virtual void set_coeff( scalar_t _coeff ) { coeff_ = _coeff; }
|
||||
|
||||
/// Get coefficient - ignored by non-parameterized rules.
|
||||
scalar_t coeff() const { return coeff_; }
|
||||
|
||||
//@}
|
||||
|
||||
protected:
|
||||
|
||||
void set_prev_rule(Self*& _p) { prev_rule_ = _p; }
|
||||
Self* prev_rule() { return prev_rule_; }
|
||||
|
||||
void set_subdiv_rule(Self*& _n) { subdiv_rule_ = _n; }
|
||||
Self* subdiv_rule() { return subdiv_rule_; }
|
||||
|
||||
void set_number(int _n) { number_ = _n; }
|
||||
|
||||
void set_n_rules(int _n) { n_rules_ = _n; }
|
||||
int n_rules() { return n_rules_; }
|
||||
|
||||
void set_subdiv_type(int _n)
|
||||
{ assert(_n == 3 || _n == 4); subdiv_type_ = _n; }
|
||||
|
||||
friend class CompositeT<M>;
|
||||
|
||||
protected:
|
||||
|
||||
Mesh& mesh_;
|
||||
|
||||
private:
|
||||
|
||||
Self* prev_rule_;
|
||||
Self* subdiv_rule_;
|
||||
|
||||
int subdiv_type_;
|
||||
int number_;
|
||||
int n_rules_;
|
||||
|
||||
scalar_t coeff_;
|
||||
|
||||
private: // Noncopyable
|
||||
|
||||
RuleInterfaceT(const RuleInterfaceT&);
|
||||
RuleInterfaceT& operator=(const RuleInterfaceT&);
|
||||
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
} // END_NS_ADAPTIVE
|
||||
} // END_NS_SUBDIVIDER
|
||||
} // END_NS_OPENMESH
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_SUBDIVIDER_ADAPTIVE_RULEINTERFACET_HH defined
|
||||
//=============================================================================
|
||||
|
||||
2015
Tools/Subdivider/Adaptive/Composite/RulesT.cc
Normal file
2015
Tools/Subdivider/Adaptive/Composite/RulesT.cc
Normal file
File diff suppressed because it is too large
Load Diff
525
Tools/Subdivider/Adaptive/Composite/RulesT.hh
Normal file
525
Tools/Subdivider/Adaptive/Composite/RulesT.hh
Normal file
@@ -0,0 +1,525 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// OpenMesh
|
||||
// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen
|
||||
// www.openmesh.org
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// License
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation, version 2.1.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Revision: 1802 $
|
||||
// $Date: 2008-05-19 11:55:07 +0200 (Mo, 19. Mai 2008) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
/** \file RulesT.hh
|
||||
|
||||
*/
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Composite Subdivision and Averaging Rules
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef OPENMESH_SUBDIVIDER_ADAPTIVE_RULEST_HH
|
||||
#define OPENMESH_SUBDIVIDER_ADAPTIVE_RULEST_HH
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
#include <OpenMesh/Core/System/config.hh>
|
||||
#include <OpenMesh/Tools/Subdivider/Adaptive/Composite/RuleInterfaceT.hh>
|
||||
// -------------------- STL
|
||||
#include <vector>
|
||||
|
||||
|
||||
#if defined(OM_CC_MIPS) // avoid warnings
|
||||
# define MIPS_WARN_WA( Item ) \
|
||||
void raise(typename M:: ## Item ## Handle &_h, state_t _target_state ) \
|
||||
{ Inherited::raise(_h, _target_state); }
|
||||
#else
|
||||
# define MIPS_WARN_WA( Item )
|
||||
#endif
|
||||
|
||||
//== NAMESPACE ================================================================
|
||||
|
||||
namespace OpenMesh { // BEGIN_NS_OPENMESH
|
||||
namespace Subdivider { // BEGIN_NS_SUBDIVIDER
|
||||
namespace Adaptive { // BEGIN_NS_ADAPTIVE
|
||||
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
/** Adaptive Composite Subdivision framework.
|
||||
*/
|
||||
|
||||
|
||||
//=============================================================================
|
||||
|
||||
/** Topological composite rule Tvv,3 doing a 1-3 split of a face.
|
||||
*/
|
||||
template <class M> class Tvv3 : public RuleInterfaceT<M>
|
||||
{
|
||||
COMPOSITE_RULE( Tvv3, M );
|
||||
private:
|
||||
typedef RuleInterfaceT<M> Base;
|
||||
|
||||
public:
|
||||
|
||||
typedef RuleInterfaceT<M> Inherited;
|
||||
|
||||
Tvv3(M& _mesh) : Inherited(_mesh) { Base::set_subdiv_type(3); };
|
||||
|
||||
void raise(typename M::FaceHandle& _fh, state_t _target_state);
|
||||
void raise(typename M::VertexHandle& _vh, state_t _target_state);
|
||||
MIPS_WARN_WA(Edge); // avoid warning
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
|
||||
|
||||
/** Topological composite rule Tvv,4 doing a 1-4 split of a face
|
||||
*/
|
||||
template <class M> class Tvv4 : public RuleInterfaceT<M>
|
||||
{
|
||||
COMPOSITE_RULE( Tvv4, M );
|
||||
|
||||
private:
|
||||
typedef RuleInterfaceT<M> Base;
|
||||
public:
|
||||
typedef typename M::HalfedgeHandle HEH;
|
||||
typedef typename M::VertexHandle VH;
|
||||
|
||||
typedef RuleInterfaceT<M> Inherited;
|
||||
|
||||
Tvv4(M& _mesh) : Inherited(_mesh) { Base::set_subdiv_type(4); };
|
||||
|
||||
void raise(typename M::FaceHandle& _fh, state_t _target_state);
|
||||
void raise(typename M::VertexHandle& _vh, state_t _target_state);
|
||||
void raise(typename M::EdgeHandle& _eh, state_t _target_state);
|
||||
|
||||
private:
|
||||
|
||||
void split_edge(HEH& _hh, VH& _vh, state_t _target_state);
|
||||
void check_edge(const typename M::HalfedgeHandle& _hh,
|
||||
state_t _target_state);
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
|
||||
|
||||
/** Composite rule VF
|
||||
*/
|
||||
template <class M> class VF : public RuleInterfaceT<M>
|
||||
{
|
||||
COMPOSITE_RULE( VF, M );
|
||||
private:
|
||||
typedef RuleInterfaceT<M> Base;
|
||||
|
||||
public:
|
||||
typedef RuleInterfaceT<M> Inherited;
|
||||
|
||||
VF(M& _mesh) : Inherited(_mesh) {}
|
||||
|
||||
void raise(typename M::FaceHandle& _fh, state_t _target_state);
|
||||
MIPS_WARN_WA(Edge);
|
||||
MIPS_WARN_WA(Vertex);
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
|
||||
|
||||
/** Composite rule FF
|
||||
*/
|
||||
template <class M> class FF : public RuleInterfaceT<M>
|
||||
{
|
||||
COMPOSITE_RULE( FF, M );
|
||||
private:
|
||||
typedef RuleInterfaceT<M> Base;
|
||||
|
||||
public:
|
||||
typedef RuleInterfaceT<M> Inherited;
|
||||
|
||||
FF(M& _mesh) : Inherited(_mesh) {}
|
||||
|
||||
void raise(typename M::FaceHandle& _fh, state_t _target_state);
|
||||
MIPS_WARN_WA(Vertex); // avoid warning
|
||||
MIPS_WARN_WA(Edge ); // avoid warning
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
|
||||
|
||||
/** Composite rule FFc
|
||||
*/
|
||||
template <class M> class FFc : public RuleInterfaceT<M>
|
||||
{
|
||||
COMPOSITE_RULE( FFc, M );
|
||||
private:
|
||||
typedef RuleInterfaceT<M> Base;
|
||||
|
||||
public:
|
||||
typedef RuleInterfaceT<M> Inherited;
|
||||
|
||||
FFc(M& _mesh) : Inherited(_mesh) {}
|
||||
|
||||
void raise(typename M::FaceHandle& _fh, state_t _target_state);
|
||||
MIPS_WARN_WA(Vertex); // avoid warning
|
||||
MIPS_WARN_WA(Edge ); // avoid warning
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
|
||||
|
||||
/** Composite rule FV
|
||||
*/
|
||||
template <class M> class FV : public RuleInterfaceT<M>
|
||||
{
|
||||
COMPOSITE_RULE( FV, M );
|
||||
private:
|
||||
typedef RuleInterfaceT<M> Base;
|
||||
|
||||
public:
|
||||
typedef RuleInterfaceT<M> Inherited;
|
||||
|
||||
FV(M& _mesh) : Inherited(_mesh) {}
|
||||
|
||||
void raise(typename M::VertexHandle& _vh, state_t _target_state);
|
||||
MIPS_WARN_WA(Face); // avoid warning
|
||||
MIPS_WARN_WA(Edge); // avoid warning
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
|
||||
|
||||
/** Composite rule FVc
|
||||
*/
|
||||
template <class M> class FVc : public RuleInterfaceT<M>
|
||||
{
|
||||
COMPOSITE_RULE( FVc, M );
|
||||
private:
|
||||
typedef RuleInterfaceT<M> Base;
|
||||
|
||||
public:
|
||||
typedef RuleInterfaceT<M> Inherited;
|
||||
|
||||
FVc(M& _mesh) : Inherited(_mesh) { init_coeffs(50); }
|
||||
|
||||
void raise(typename M::VertexHandle& _vh, state_t _target_state);
|
||||
MIPS_WARN_WA(Face); // avoid warning
|
||||
MIPS_WARN_WA(Edge); // avoid warning
|
||||
|
||||
static void init_coeffs(size_t _max_valence);
|
||||
static const std::vector<double>& coeffs() { return coeffs_; }
|
||||
|
||||
double coeff( size_t _valence )
|
||||
{
|
||||
assert(_valence < coeffs_.size());
|
||||
return coeffs_[_valence];
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
static std::vector<double> coeffs_;
|
||||
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
|
||||
|
||||
/** Composite rule VV
|
||||
*/
|
||||
template <class M> class VV : public RuleInterfaceT<M>
|
||||
{
|
||||
COMPOSITE_RULE( VV, M );
|
||||
private:
|
||||
typedef RuleInterfaceT<M> Base;
|
||||
|
||||
public:
|
||||
|
||||
typedef RuleInterfaceT<M> Inherited;
|
||||
|
||||
VV(M& _mesh) : Inherited(_mesh) {}
|
||||
|
||||
void raise(typename M::VertexHandle& _vh, state_t _target_state);
|
||||
MIPS_WARN_WA(Face); // avoid warning
|
||||
MIPS_WARN_WA(Edge); // avoid warning
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
|
||||
|
||||
/** Composite rule VVc
|
||||
*/
|
||||
template <class M> class VVc : public RuleInterfaceT<M>
|
||||
{
|
||||
COMPOSITE_RULE( VVc, M );
|
||||
private:
|
||||
typedef RuleInterfaceT<M> Base;
|
||||
|
||||
public:
|
||||
typedef RuleInterfaceT<M> Inherited;
|
||||
|
||||
VVc(M& _mesh) : Inherited(_mesh) {}
|
||||
|
||||
void raise(typename M::VertexHandle& _vh, state_t _target_state);
|
||||
MIPS_WARN_WA(Face); // avoid warning
|
||||
MIPS_WARN_WA(Edge); // avoid warning
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
|
||||
|
||||
/** Composite rule VE
|
||||
*/
|
||||
template <class M> class VE : public RuleInterfaceT<M>
|
||||
{
|
||||
COMPOSITE_RULE( VE, M );
|
||||
private:
|
||||
typedef RuleInterfaceT<M> Base;
|
||||
|
||||
public:
|
||||
typedef RuleInterfaceT<M> Inherited;
|
||||
|
||||
VE(M& _mesh) : Inherited(_mesh) {}
|
||||
|
||||
void raise(typename M::EdgeHandle& _eh, state_t _target_state);
|
||||
MIPS_WARN_WA(Face ); // avoid warning
|
||||
MIPS_WARN_WA(Vertex); // avoid warning
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
|
||||
|
||||
/** Composite rule VdE
|
||||
*/
|
||||
template <class M> class VdE : public RuleInterfaceT<M>
|
||||
{
|
||||
COMPOSITE_RULE( VdE, M );
|
||||
private:
|
||||
typedef RuleInterfaceT<M> Base;
|
||||
|
||||
public:
|
||||
typedef RuleInterfaceT<M> Inherited;
|
||||
|
||||
VdE(M& _mesh) : Inherited(_mesh) {}
|
||||
|
||||
void raise(typename M::EdgeHandle& _eh, state_t _target_state);
|
||||
MIPS_WARN_WA(Face ); // avoid warning
|
||||
MIPS_WARN_WA(Vertex); // avoid warning
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
|
||||
|
||||
/** Composite rule VdEc
|
||||
*/
|
||||
template <class M> class VdEc : public RuleInterfaceT<M>
|
||||
{
|
||||
COMPOSITE_RULE( VdEc, M );
|
||||
private:
|
||||
typedef RuleInterfaceT<M> Base;
|
||||
|
||||
public:
|
||||
typedef RuleInterfaceT<M> Inherited;
|
||||
|
||||
VdEc(M& _mesh) : Inherited(_mesh) {}
|
||||
|
||||
void raise(typename M::EdgeHandle& _eh, state_t _target_state);
|
||||
MIPS_WARN_WA(Face ); // avoid warning
|
||||
MIPS_WARN_WA(Vertex); // avoid warning
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
|
||||
|
||||
/** Composite rule EV
|
||||
*/
|
||||
template <class M> class EV : public RuleInterfaceT<M>
|
||||
{
|
||||
COMPOSITE_RULE( EV, M );
|
||||
private:
|
||||
typedef RuleInterfaceT<M> Base;
|
||||
|
||||
public:
|
||||
typedef RuleInterfaceT<M> Inherited;
|
||||
|
||||
EV(M& _mesh) : Inherited(_mesh) {}
|
||||
|
||||
void raise(typename M::VertexHandle& _vh, state_t _target_state);
|
||||
MIPS_WARN_WA(Face); // avoid warning
|
||||
MIPS_WARN_WA(Edge); // avoid warning
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
|
||||
|
||||
/** Composite rule EVc
|
||||
*/
|
||||
template <class M> class EVc : public RuleInterfaceT<M>
|
||||
{
|
||||
COMPOSITE_RULE( EVc, M );
|
||||
private:
|
||||
typedef RuleInterfaceT<M> Base;
|
||||
|
||||
public:
|
||||
|
||||
typedef RuleInterfaceT<M> Inherited;
|
||||
|
||||
EVc(M& _mesh) : Inherited(_mesh) { init_coeffs(50); }
|
||||
|
||||
void raise(typename M::VertexHandle& _vh, state_t _target_state);
|
||||
MIPS_WARN_WA(Face); // avoid warning
|
||||
MIPS_WARN_WA(Edge); // avoid warning
|
||||
|
||||
static void init_coeffs(size_t _max_valence);
|
||||
static const std::vector<double>& coeffs() { return coeffs_; }
|
||||
|
||||
double coeff( size_t _valence )
|
||||
{
|
||||
assert(_valence < coeffs_.size());
|
||||
return coeffs_[_valence];
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
static std::vector<double> coeffs_;
|
||||
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
|
||||
|
||||
/** Composite rule EF
|
||||
*/
|
||||
template <class M> class EF : public RuleInterfaceT<M>
|
||||
{
|
||||
COMPOSITE_RULE( EF, M );
|
||||
private:
|
||||
typedef RuleInterfaceT<M> Base;
|
||||
|
||||
public:
|
||||
typedef RuleInterfaceT<M> Inherited;
|
||||
|
||||
EF(M& _mesh) : Inherited(_mesh) {}
|
||||
|
||||
void raise(typename M::FaceHandle& _fh, state_t _target_state);
|
||||
MIPS_WARN_WA(Edge ); // avoid warning
|
||||
MIPS_WARN_WA(Vertex); // avoid warning
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
|
||||
|
||||
/** Composite rule FE
|
||||
*/
|
||||
template <class M> class FE : public RuleInterfaceT<M>
|
||||
{
|
||||
COMPOSITE_RULE( FE, M );
|
||||
private:
|
||||
typedef RuleInterfaceT<M> Base;
|
||||
|
||||
public:
|
||||
typedef RuleInterfaceT<M> Inherited;
|
||||
|
||||
FE(M& _mesh) : Inherited(_mesh) {}
|
||||
|
||||
void raise(typename M::EdgeHandle& _eh, state_t _target_state);
|
||||
MIPS_WARN_WA(Face ); // avoid warning
|
||||
MIPS_WARN_WA(Vertex); // avoid warning
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
|
||||
|
||||
/** Composite rule EdE
|
||||
*/
|
||||
template <class M> class EdE : public RuleInterfaceT<M>
|
||||
{
|
||||
COMPOSITE_RULE( EdE, M );
|
||||
private:
|
||||
typedef RuleInterfaceT<M> Base;
|
||||
|
||||
public:
|
||||
typedef RuleInterfaceT<M> Inherited;
|
||||
|
||||
EdE(M& _mesh) : Inherited(_mesh) {}
|
||||
|
||||
void raise(typename M::EdgeHandle& _eh, state_t _target_state);
|
||||
MIPS_WARN_WA(Face ); // avoid warning
|
||||
MIPS_WARN_WA(Vertex); // avoid warning
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
|
||||
|
||||
/** Composite rule EdEc
|
||||
*/
|
||||
template <class M> class EdEc : public RuleInterfaceT<M>
|
||||
{
|
||||
COMPOSITE_RULE( EdEc, M );
|
||||
private:
|
||||
typedef RuleInterfaceT<M> Base;
|
||||
|
||||
public:
|
||||
typedef RuleInterfaceT<M> Inherited;
|
||||
|
||||
EdEc(M& _mesh) : Inherited(_mesh) {}
|
||||
|
||||
void raise(typename M::EdgeHandle& _eh, state_t _target_state);
|
||||
MIPS_WARN_WA(Face ); // avoid warning
|
||||
MIPS_WARN_WA(Vertex); // avoid warning
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#undef MIPS_WARN_WA
|
||||
|
||||
//=============================================================================
|
||||
} // END_NS_ADAPTIVE
|
||||
} // END_NS_SUBDIVIDER
|
||||
} // END_NS_OPENMESH
|
||||
//=============================================================================
|
||||
#if defined(OM_INCLUDE_TEMPLATES) && !defined(OPENMESH_SUBDIVIDER_ADAPTIVE_RULEST_CC)
|
||||
# define OPENMESH_SUBDIVIDER_TEMPLATES
|
||||
# include "RulesT.cc"
|
||||
#endif
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_SUBDIVIDER_ADAPTIVE_RULEST_HH defined
|
||||
//=============================================================================
|
||||
|
||||
237
Tools/Subdivider/Adaptive/Composite/Traits.hh
Normal file
237
Tools/Subdivider/Adaptive/Composite/Traits.hh
Normal file
@@ -0,0 +1,237 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// OpenMesh
|
||||
// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen
|
||||
// www.openmesh.org
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// License
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation, version 2.1.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Revision: 1802 $
|
||||
// $Date: 2008-05-19 11:55:07 +0200 (Mo, 19. Mai 2008) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
/** \file Traits.hh
|
||||
|
||||
*/
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// CLASS Traits
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef OPENMESH_SUBDIVIDER_ADAPTIVE_TRAITS_HH
|
||||
#define OPENMESH_SUBDIVIDER_ADAPTIVE_TRAITS_HH
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
#include <map>
|
||||
#include <OpenMesh/Core/Mesh/Types/TriMesh_ArrayKernelT.hh>
|
||||
|
||||
//== NAMESPACE ================================================================
|
||||
|
||||
namespace OpenMesh { // BEGIN_NS_OPENMESH
|
||||
namespace Subdivider { // BEGIN_NS_DECIMATER
|
||||
namespace Adaptive { // BEGIN_NS_UNIFORM
|
||||
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
/** Adaptive Composite Subdivision framework.
|
||||
*/
|
||||
|
||||
// typedef unsigned short state_t;
|
||||
// const state_t mask_final = 1 << ((sizeof(state_t)*8)-1);
|
||||
// const state_t mask_state = ~mask_final;
|
||||
|
||||
typedef int state_t;
|
||||
typedef bool final_t;
|
||||
|
||||
struct State
|
||||
{
|
||||
int state : 31;
|
||||
unsigned final : 1;
|
||||
};
|
||||
|
||||
struct Traits : public OpenMesh::DefaultTraits
|
||||
{
|
||||
|
||||
// add face normals
|
||||
FaceAttributes( OpenMesh::Attributes::Normal );
|
||||
|
||||
// add vertex normals
|
||||
VertexAttributes( OpenMesh::Attributes::Normal );
|
||||
|
||||
// add previous halfedge handle
|
||||
HalfedgeAttributes( OpenMesh::Attributes::PrevHalfedge );
|
||||
|
||||
FaceTraits
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
typedef typename Refs::Point Point;
|
||||
typedef typename Refs::HalfedgeHandle HalfedgeHandle;
|
||||
typedef std::map<state_t, Point> PositionHistory;
|
||||
|
||||
State state_;
|
||||
HalfedgeHandle red_halfedge_;
|
||||
|
||||
PositionHistory pos_map_;
|
||||
|
||||
public:
|
||||
|
||||
// face state
|
||||
state_t state() const { return state_t(state_.state); }
|
||||
void set_state(const state_t _s) { state_.state = _s; }
|
||||
void inc_state() { ++state_.state; }
|
||||
|
||||
// face not final if divided (loop) or edge not flipped (sqrt(3))
|
||||
final_t final() const { return final_t(state_.final); }
|
||||
void set_final() { state_.final = true; }
|
||||
void set_not_final() { state_.final = false; }
|
||||
|
||||
// halfedge of dividing edge (red-green triangulation)
|
||||
const HalfedgeHandle& red_halfedge() const { return red_halfedge_; }
|
||||
void set_red_halfedge(const HalfedgeHandle& _h) { red_halfedge_ = _h; }
|
||||
|
||||
// position of face, depending on generation _i.
|
||||
void set_position(const int& _i, const Point& _p) { pos_map_[_i] = _p; }
|
||||
const Point position(const int& _i) {
|
||||
if (pos_map_.find(_i) != pos_map_.end())
|
||||
return pos_map_[_i];
|
||||
else {
|
||||
|
||||
if (_i <= 0) {
|
||||
const Point zero_point(0.0, 0.0, 0.0);
|
||||
return zero_point;
|
||||
}
|
||||
|
||||
return position(_i - 1);
|
||||
}
|
||||
}
|
||||
}; // end class FaceTraits
|
||||
|
||||
|
||||
EdgeTraits
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
typedef typename Refs::Point Point;
|
||||
typedef std::map<state_t, Point> PositionHistory;
|
||||
|
||||
State state_;
|
||||
PositionHistory pos_map_;
|
||||
|
||||
public:
|
||||
|
||||
typedef typename Refs::Scalar Scalar;
|
||||
|
||||
// Scalar weight_;
|
||||
|
||||
// state of edge
|
||||
state_t state() const { return state_t(state_.state); }
|
||||
void set_state(const state_t _s) { state_.state = _s; }
|
||||
void inc_state() { ++state_.state; }
|
||||
|
||||
// edge not final if dividing face (Loop) or edge not flipped (SQRT(3))
|
||||
final_t final() const { return final_t(state_.final); }
|
||||
void set_final() { state_.final = true; }
|
||||
void set_not_final() { state_.final = false; }
|
||||
|
||||
// position of edge, depending on generation _i.
|
||||
void set_position(const int& _i, const Point& _p) { pos_map_[_i] = _p; }
|
||||
const Point position(const int& _i) {
|
||||
|
||||
if (pos_map_.find(_i) != pos_map_.end())
|
||||
{
|
||||
return pos_map_[_i];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_i <= 0)
|
||||
{
|
||||
const Point zero_point(0.0, 0.0, 0.0);
|
||||
return zero_point;
|
||||
}
|
||||
|
||||
return position(_i - 1);
|
||||
}
|
||||
}
|
||||
}; // end class EdgeTraits
|
||||
|
||||
|
||||
VertexTraits
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
typedef typename Refs::Point Point;
|
||||
typedef std::map<state_t, Point> PositionHistory;
|
||||
|
||||
State state_;
|
||||
|
||||
PositionHistory pos_map_;
|
||||
|
||||
public:
|
||||
|
||||
// state of vertex
|
||||
state_t state() const { return state_.state; }
|
||||
void set_state(const state_t _s) { state_.state = _s; }
|
||||
void inc_state() { ++state_.state; }
|
||||
|
||||
|
||||
// usually not needed by loop or sqrt(3)
|
||||
final_t final() const { return state_.final; }
|
||||
void set_final() { state_.final = true; }
|
||||
void set_not_final() { state_.final = false; }
|
||||
|
||||
// position of vertex, depending on generation _i. (not for display)
|
||||
void set_position(const int& _i, const Point& _p) { pos_map_[_i] = _p; }
|
||||
const Point position(const int& _i) {
|
||||
|
||||
if (pos_map_.find(_i) != pos_map_.end())
|
||||
|
||||
return pos_map_[_i];
|
||||
|
||||
else {
|
||||
|
||||
if (_i <= 0) {
|
||||
|
||||
const Point zero_point(0.0, 0.0, 0.0);
|
||||
return zero_point;
|
||||
}
|
||||
|
||||
return position(_i - 1);
|
||||
}
|
||||
}
|
||||
}; // end class VertexTraits
|
||||
}; // end class Traits
|
||||
|
||||
//=============================================================================
|
||||
} // END_NS_ADAPTIVE
|
||||
} // END_NS_SUBDIVIDER
|
||||
} // END_NS_OPENMESH
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_SUBDIVIDER_ADAPTIVE_TRAITS_HH defined
|
||||
//=============================================================================
|
||||
17
Tools/Subdivider/Uniform/ACGMakefile
Normal file
17
Tools/Subdivider/Uniform/ACGMakefile
Normal file
@@ -0,0 +1,17 @@
|
||||
#== SYSTEM PART -- DON'T TOUCH ==============================================
|
||||
include $(ACGMAKE)/Config
|
||||
#==============================================================================
|
||||
|
||||
|
||||
SUBDIRS = $(call find-subdirs)
|
||||
|
||||
PACKAGES :=
|
||||
|
||||
PROJ_LIBS :=
|
||||
|
||||
MODULES := cxxlib
|
||||
|
||||
|
||||
#== SYSTEM PART -- DON'T TOUCH ==============================================
|
||||
include $(ACGMAKE)/Rules
|
||||
#==============================================================================
|
||||
17
Tools/Subdivider/Uniform/Composite/ACGMakefile
Normal file
17
Tools/Subdivider/Uniform/Composite/ACGMakefile
Normal file
@@ -0,0 +1,17 @@
|
||||
#== SYSTEM PART -- DON'T TOUCH ==============================================
|
||||
include $(ACGMAKE)/Config
|
||||
#==============================================================================
|
||||
|
||||
|
||||
SUBDIRS = $(call find-subdirs)
|
||||
|
||||
PACKAGES :=
|
||||
|
||||
PROJ_LIBS :=
|
||||
|
||||
MODULES := cxxlib
|
||||
|
||||
|
||||
#== SYSTEM PART -- DON'T TOUCH ==============================================
|
||||
include $(ACGMAKE)/Rules
|
||||
#==============================================================================
|
||||
1310
Tools/Subdivider/Uniform/Composite/CompositeT.cc
Normal file
1310
Tools/Subdivider/Uniform/Composite/CompositeT.cc
Normal file
File diff suppressed because it is too large
Load Diff
233
Tools/Subdivider/Uniform/Composite/CompositeT.hh
Normal file
233
Tools/Subdivider/Uniform/Composite/CompositeT.hh
Normal file
@@ -0,0 +1,233 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// OpenMesh
|
||||
// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen
|
||||
// www.openmesh.org
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// License
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation, version 2.1.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Revision: 1802 $
|
||||
// $Date: 2008-05-19 11:55:07 +0200 (Mo, 19. Mai 2008) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
/** \file Uniform/Composite/CompositeT.hh
|
||||
|
||||
*/
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// CLASS CompositeT
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef OPENMESH_SUBDIVIDER_UNIFORM_COMPOSITE_HH
|
||||
#define OPENMESH_SUBDIVIDER_UNIFORM_COMPOSITE_HH
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
// --------------------
|
||||
#include <OpenMesh/Tools/Subdivider/Uniform/SubdividerT.hh>
|
||||
|
||||
//== NAMESPACE ================================================================
|
||||
|
||||
namespace OpenMesh { // BEGIN_NS_OPENMESH
|
||||
namespace Subdivider { // BEGIN_NS_DECIMATER
|
||||
namespace Uniform { // BEGIN_NS_UNIFORM
|
||||
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
/** This class provides the composite subdivision rules for the uniform case.
|
||||
*
|
||||
* To create a subdivider derive from this class and overload the functions
|
||||
* name() and apply_rules(). In the latter one call the wanted rules.
|
||||
*
|
||||
* For details on the composite scheme refer to
|
||||
* - <a
|
||||
* href="http://cm.bell-labs.com/who/poswald/sqrt3.pdf">P. Oswald,
|
||||
* P. Schroeder "Composite primal/dual sqrt(3)-subdivision schemes",
|
||||
* CAGD 20, 3, 2003, 135--164</a>
|
||||
|
||||
* \note Not all rules are implemented!
|
||||
* \see class Adaptive::CompositeT
|
||||
*/
|
||||
template <typename MeshType, typename RealType=float >
|
||||
class CompositeT : public SubdividerT< MeshType, RealType >
|
||||
{
|
||||
public:
|
||||
|
||||
typedef RealType real_t;
|
||||
typedef MeshType mesh_t;
|
||||
typedef SubdividerT< mesh_t, real_t > parent_t;
|
||||
|
||||
public:
|
||||
|
||||
CompositeT(void) : parent_t(), p_mesh_(NULL) {}
|
||||
CompositeT(MeshType& _mesh) : parent_t(_mesh), p_mesh_(NULL) {};
|
||||
virtual ~CompositeT() { }
|
||||
|
||||
public: // inherited interface
|
||||
|
||||
virtual const char *name( void ) const = 0;
|
||||
|
||||
protected: // inherited interface
|
||||
|
||||
bool prepare( MeshType& _m );
|
||||
|
||||
bool subdivide( MeshType& _m, size_t _n )
|
||||
{
|
||||
assert( p_mesh_ == &_m );
|
||||
|
||||
while(_n--)
|
||||
{
|
||||
apply_rules();
|
||||
commit(_m);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef NDEBUG
|
||||
bool cleanup( MeshType& )
|
||||
#else
|
||||
bool cleanup( MeshType& _m )
|
||||
#endif
|
||||
{
|
||||
assert( p_mesh_ == &_m );
|
||||
p_mesh_=NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/// Assemble here the rule sequence, by calling the constructor
|
||||
/// of the wanted rules.
|
||||
virtual void apply_rules(void) = 0;
|
||||
|
||||
protected:
|
||||
|
||||
/// Move vertices to new positions after the rules have been applied
|
||||
/// to the mesh (called by subdivide()).
|
||||
void commit( MeshType &_m)
|
||||
{
|
||||
typename MeshType::VertexIter v_it;
|
||||
|
||||
for (v_it=_m.vertices_begin(); v_it != _m.vertices_end(); ++v_it)
|
||||
_m.set_point(v_it.handle(), _m.data(v_it).position());
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
|
||||
/// Abstract base class for coefficient functions
|
||||
struct Coeff
|
||||
{
|
||||
virtual ~Coeff() { }
|
||||
virtual double operator() (size_t _valence) = 0;
|
||||
};
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
typedef typename MeshType::Scalar scalar_t;
|
||||
typedef typename MeshType::VertexHandle VertexHandle;
|
||||
typedef typename MeshType::FaceHandle FaceHandle;
|
||||
typedef typename MeshType::EdgeHandle EdgeHandle;
|
||||
typedef typename MeshType::HalfedgeHandle HalfedgeHandle;
|
||||
|
||||
/// \name Uniform composite subdivision rules
|
||||
//@{
|
||||
|
||||
|
||||
void Tvv3(); ///< Split Face, using Vertex information (1-3 split)
|
||||
void Tvv4(); ///< Split Face, using Vertex information (1-4 split)
|
||||
void Tfv(); ///< Split Face, using Face Information
|
||||
|
||||
void FF(); ///< Face to face averaging.
|
||||
void FFc(Coeff& _coeff); ///< Weighted face to face averaging.
|
||||
void FFc(scalar_t _c); ///< Weighted face to face averaging.
|
||||
|
||||
void FV(); ///< Face to vertex averaging.
|
||||
void FVc(Coeff& _coeff); ///< Weighted face to vertex Averaging with flaps
|
||||
void FVc(scalar_t _c); ///< Weighted face to vertex Averaging with flaps
|
||||
|
||||
void FE(); ///< Face to edge averaging.
|
||||
|
||||
void VF(); ///< Vertex to Face Averaging.
|
||||
void VFa(Coeff& _coeff); ///< Vertex to Face Averaging, weighted.
|
||||
void VFa(scalar_t _alpha); ///< Vertex to Face Averaging, weighted.
|
||||
|
||||
void VV(); ///< Vertex to vertex averaging.
|
||||
void VVc(Coeff& _coeff); ///< Vertex to vertex averaging, weighted.
|
||||
void VVc(scalar_t _c); ///< Vertex to vertex averaging, weighted.
|
||||
|
||||
void VE(); ///< VE Step (Vertex to Edge Averaging)
|
||||
|
||||
|
||||
void VdE(); ///< Vertex to edge averaging, using diamond of edges.
|
||||
void VdEc(scalar_t _c); ///< Weighted vertex to edge averaging, using diamond of edges
|
||||
|
||||
/// Weigthed vertex to edge averaging, using diamond of edges for
|
||||
/// irregular vertices.
|
||||
void VdEg(Coeff& _coeff);
|
||||
/// Weigthed vertex to edge averaging, using diamond of edges for
|
||||
/// irregular vertices.
|
||||
void VdEg(scalar_t _gamma);
|
||||
|
||||
void EF(); ///< Edge to face averaging.
|
||||
|
||||
void EV(); ///< Edge to vertex averaging.
|
||||
void EVc(Coeff& _coeff); ///< Weighted edge to vertex averaging.
|
||||
void EVc(scalar_t _c); ///< Weighted edge to vertex averaging.
|
||||
|
||||
void EdE(); ///< Edge to edge averaging w/ flap rule.
|
||||
void EdEc(scalar_t _c); ///< Weighted edge to edge averaging w/ flap rule.
|
||||
|
||||
|
||||
//@}
|
||||
|
||||
void corner_cutting(HalfedgeHandle _heh);
|
||||
|
||||
VertexHandle split_edge(HalfedgeHandle _heh);
|
||||
|
||||
private:
|
||||
|
||||
MeshType* p_mesh_;
|
||||
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
} // END_NS_UNIFORM
|
||||
} // END_NS_SUBDIVIDER
|
||||
} // END_NS_OPENMESH
|
||||
//=============================================================================
|
||||
#if defined(OM_INCLUDE_TEMPLATES) && !defined(OPENMESH_SUBDIVIDER_UNIFORM_COMPOSITE_CC)
|
||||
#define OPENMESH_SUBDIVIDER_TEMPLATES
|
||||
#include "CompositeT.cc"
|
||||
#endif
|
||||
//=============================================================================
|
||||
#endif // COMPOSITET_HH defined
|
||||
//=============================================================================
|
||||
|
||||
150
Tools/Subdivider/Uniform/Composite/CompositeTraits.hh
Normal file
150
Tools/Subdivider/Uniform/Composite/CompositeTraits.hh
Normal file
@@ -0,0 +1,150 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// OpenMesh
|
||||
// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen
|
||||
// www.openmesh.org
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// License
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation, version 2.1.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Revision: 1802 $
|
||||
// $Date: 2008-05-19 11:55:07 +0200 (Mo, 19. Mai 2008) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
/** \file Uniform/Composite/CompositeTraits.hh
|
||||
Mesh traits for uniform composite subdivision.
|
||||
*/
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// CLASS Traits
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef OPENMESH_SUBDIVIDER_UNIFORM_COMPOSITETRAITS_HH
|
||||
#define OPENMESH_SUBDIVIDER_UNIFORM_COMPOSITETRAITS_HH
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
//#include "Config.hh"
|
||||
// --------------------
|
||||
#include <OpenMesh/Core/Mesh/Traits.hh>
|
||||
#include <OpenMesh/Core/Mesh/Attributes.hh>
|
||||
|
||||
|
||||
//== NAMESPACE ================================================================
|
||||
|
||||
namespace OpenMesh { // BEGIN_NS_OPENMESH
|
||||
namespace Subdivider { // BEGIN_NS_DECIMATER
|
||||
namespace Uniform { // BEGIN_NS_UNIFORM
|
||||
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
|
||||
/** Uniform Composite Subdivision framework.
|
||||
*/
|
||||
|
||||
struct CompositeTraits : public OpenMesh::DefaultTraits
|
||||
{
|
||||
FaceAttributes( OpenMesh::Attributes::Normal );
|
||||
|
||||
VertexAttributes( OpenMesh::Attributes::Normal );
|
||||
|
||||
//HalfedgeAttributes( OpenMesh::Attributes::PrevHalfedge );
|
||||
|
||||
FaceTraits
|
||||
{
|
||||
private:
|
||||
typedef typename Refs::HalfedgeHandle HalfedgeHandle;
|
||||
typedef typename Refs::Scalar Scalar;
|
||||
typedef typename Refs::Point Point;
|
||||
HalfedgeHandle red_halfedge_handle_;
|
||||
unsigned int generation_;
|
||||
bool red_;
|
||||
Scalar quality_;
|
||||
Point midpoint_;
|
||||
Point position_;
|
||||
|
||||
public:
|
||||
const unsigned int& generation() { return generation_; }
|
||||
void set_generation(const unsigned int& _g) { generation_ = _g; }
|
||||
void inc_generation() { ++generation_; }
|
||||
void set_red() { red_ = 1; }
|
||||
void set_green() {red_ = 0; }
|
||||
bool is_red() { return red_; }
|
||||
bool is_green() { return !red_; }
|
||||
void set_red_halfedge_handle(HalfedgeHandle& _heh)
|
||||
{ red_halfedge_handle_ = _heh; }
|
||||
HalfedgeHandle& red_halfedge_handle() { return red_halfedge_handle_; }
|
||||
void set_quality(Scalar& _q) { quality_ = _q; }
|
||||
Scalar& quality() { return quality_; }
|
||||
const Point& midpoint() const { return midpoint_; }
|
||||
void set_midpoint(const Point& _p) { midpoint_ = _p; }
|
||||
const Point& position() const { return position_; }
|
||||
void set_position(const Point& _p) { position_ = _p; }
|
||||
};
|
||||
|
||||
EdgeTraits
|
||||
{
|
||||
private:
|
||||
typedef typename Refs::Point Point;
|
||||
typedef typename Refs::Scalar Scalar;
|
||||
Point midpoint_;
|
||||
Scalar length_;
|
||||
Point position_;
|
||||
public:
|
||||
const Point& midpoint() const { return midpoint_; }
|
||||
void set_midpoint(const Point& _vh) { midpoint_ = _vh; }
|
||||
const Scalar& length() const { return length_; }
|
||||
void set_length(const Scalar& _s) { length_ = _s; }
|
||||
const Point& position() const { return position_; }
|
||||
void set_position(const Point& _p) { position_ = _p; }
|
||||
};
|
||||
|
||||
VertexTraits
|
||||
{
|
||||
private:
|
||||
typedef typename Refs::Point Point;
|
||||
Point new_pos_;
|
||||
Point orig_pos_;
|
||||
Point position_;
|
||||
unsigned int generation_;
|
||||
public:
|
||||
const Point& new_pos() const { return new_pos_; }
|
||||
void set_new_pos(const Point& _p) { new_pos_ = _p; }
|
||||
const unsigned int& generation() const { return generation_; }
|
||||
void set_generation(const unsigned int& _i) { generation_ = _i; }
|
||||
const Point& orig_pos() const { return orig_pos_; }
|
||||
void set_orig_pos(const Point& _p) { orig_pos_ = _p; }
|
||||
const Point& position() const { return position_; }
|
||||
void set_position(const Point& _p) { position_ = _p; }
|
||||
};
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
} // END_NS_UNIFORM
|
||||
} // END_NS_SUBDIVIDER
|
||||
} // END_NS_OPENMESH
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_SUBDIVIDER_UNIFORM_COMPOSITETRAITS_HH defined
|
||||
//=============================================================================
|
||||
|
||||
139
Tools/Subdivider/Uniform/CompositeLoopT.hh
Normal file
139
Tools/Subdivider/Uniform/CompositeLoopT.hh
Normal file
@@ -0,0 +1,139 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// OpenMesh
|
||||
// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen
|
||||
// www.openmesh.org
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// License
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation, version 2.1.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Revision: 1802 $
|
||||
// $Date: 2008-05-19 11:55:07 +0200 (Mo, 19. Mai 2008) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
/** \file CompositeLoopT.hh
|
||||
|
||||
*/
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// CLASS LoopT
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef OPENMESH_SUBDIVIDER_UNIFORM_COMPOSITELOOPT_HH
|
||||
#define OPENMESH_SUBDIVIDER_UNIFORM_COMPOSITELOOPT_HH
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
#include "Composite/CompositeT.hh"
|
||||
#include "Composite/CompositeTraits.hh"
|
||||
|
||||
|
||||
//== NAMESPACE ================================================================
|
||||
|
||||
namespace OpenMesh { // BEGIN_NS_OPENMESH
|
||||
namespace Subdivider { // BEGIN_NS_DECIMATER
|
||||
namespace Uniform { // BEGIN_NS_DECIMATER
|
||||
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
/** Uniform composite Loop subdivision algorithm
|
||||
*/
|
||||
template <class MeshType, class RealType=float>
|
||||
class CompositeLoopT : public CompositeT<MeshType, RealType>
|
||||
{
|
||||
public:
|
||||
|
||||
typedef CompositeT<MeshType, RealType> Inherited;
|
||||
|
||||
public:
|
||||
|
||||
CompositeLoopT() : Inherited() {};
|
||||
CompositeLoopT(MeshType& _mesh) : Inherited(_mesh) {};
|
||||
~CompositeLoopT() {}
|
||||
|
||||
public:
|
||||
|
||||
const char *name() const { return "Uniform Composite Loop"; }
|
||||
|
||||
protected: // inherited interface
|
||||
|
||||
void apply_rules(void)
|
||||
{
|
||||
Inherited::Tvv4();
|
||||
Inherited::VdE();
|
||||
Inherited::EVc(coeffs_);
|
||||
Inherited::VdE();
|
||||
Inherited::EVc(coeffs_);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
typedef typename Inherited::Coeff Coeff;
|
||||
|
||||
|
||||
/** Helper struct
|
||||
* \internal
|
||||
*/
|
||||
struct EVCoeff : public Coeff
|
||||
{
|
||||
EVCoeff() : Coeff() { init(50); }
|
||||
|
||||
void init(size_t _max_valence)
|
||||
{
|
||||
weights_.resize(_max_valence);
|
||||
std::generate(weights_.begin(),
|
||||
weights_.end(), compute_weight() );
|
||||
}
|
||||
|
||||
double operator()(size_t _valence) { return weights_[_valence]; }
|
||||
|
||||
/// \internal
|
||||
struct compute_weight
|
||||
{
|
||||
compute_weight() : val_(0) { }
|
||||
|
||||
double operator()(void) // Loop weights for non-boundary vertices
|
||||
{
|
||||
// 1 3 2 * pi
|
||||
// - * ( --- + cos ( ------- ) )<29> - 1.0
|
||||
// 2 2 valence
|
||||
double f1 = 1.5 + cos(2.0*M_PI/val_++);
|
||||
return 0.5 * f1 * f1 - 1.0;
|
||||
}
|
||||
size_t val_;
|
||||
|
||||
};
|
||||
|
||||
std::vector<double> weights_;
|
||||
} coeffs_;
|
||||
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
} // END_NS_UNIFORM
|
||||
} // END_NS_SUBDIVIDER
|
||||
} // END_NS_OPENMESH
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_SUBDIVIDER_UNIFORM_COMPOSITELOOPT_HH defined
|
||||
//=============================================================================
|
||||
135
Tools/Subdivider/Uniform/CompositeSqrt3T.hh
Normal file
135
Tools/Subdivider/Uniform/CompositeSqrt3T.hh
Normal file
@@ -0,0 +1,135 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// OpenMesh
|
||||
// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen
|
||||
// www.openmesh.org
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// License
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation, version 2.1.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Revision: 1802 $
|
||||
// $Date: 2008-05-19 11:55:07 +0200 (Mo, 19. Mai 2008) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
/** \file CompositeSqrt3T.hh
|
||||
|
||||
*/
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// CLASS SQRT3T
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef OPENMESH_SUBDIVIDER_UNIFORM_COMPOSITESQRT3T_HH
|
||||
#define OPENMESH_SUBDIVIDER_UNIFORM_COMPOSITESQRT3T_HH
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
#include "Composite/CompositeT.hh"
|
||||
#include "Composite/CompositeTraits.hh"
|
||||
|
||||
|
||||
//== NAMESPACE ================================================================
|
||||
|
||||
namespace OpenMesh { // BEGIN_NS_OPENMESH
|
||||
namespace Subdivider { // BEGIN_NS_DECIMATER
|
||||
namespace Uniform { // BEGIN_NS_UNIFORM
|
||||
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
/** Uniform composite sqrt(3) subdivision algorithm
|
||||
*/
|
||||
template <typename MeshType, typename RealType=float>
|
||||
class CompositeSqrt3T : public CompositeT<MeshType, RealType>
|
||||
{
|
||||
public:
|
||||
|
||||
typedef CompositeT<MeshType, RealType> Inherited;
|
||||
|
||||
public:
|
||||
|
||||
CompositeSqrt3T() : Inherited() {};
|
||||
CompositeSqrt3T(MeshType& _mesh) : Inherited(_mesh) {};
|
||||
~CompositeSqrt3T() {}
|
||||
|
||||
public:
|
||||
|
||||
const char *name() const { return "Uniform Composite Sqrt3"; }
|
||||
|
||||
protected: // inherited interface
|
||||
|
||||
void apply_rules(void)
|
||||
{
|
||||
Inherited::Tvv3();
|
||||
Inherited::VF();
|
||||
Inherited::FF();
|
||||
Inherited::FVc(coeffs_);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
typedef typename Inherited::Coeff Coeff;
|
||||
|
||||
/** Helper class
|
||||
* \internal
|
||||
*/
|
||||
struct FVCoeff : public Coeff
|
||||
{
|
||||
FVCoeff() : Coeff() { init(50); }
|
||||
|
||||
void init(size_t _max_valence)
|
||||
{
|
||||
weights_.resize(_max_valence);
|
||||
std::generate(weights_.begin(),
|
||||
weights_.end(), compute_weight() );
|
||||
}
|
||||
|
||||
double operator()(size_t _valence) { return weights_[_valence]; }
|
||||
|
||||
/** \internal
|
||||
*/
|
||||
struct compute_weight
|
||||
{
|
||||
compute_weight() : val_(0) { }
|
||||
|
||||
double operator()(void) // sqrt(3) weights for non-boundary vertices
|
||||
{
|
||||
return 2.0/3.0 * (cos(2.0*M_PI/val_++)+1.0);
|
||||
}
|
||||
size_t val_;
|
||||
};
|
||||
|
||||
std::vector<double> weights_;
|
||||
|
||||
} coeffs_;
|
||||
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
} // END_NS_UNIFORM
|
||||
} // END_NS_SUBDIVIDER
|
||||
} // END_NS_OPENMESH
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_SUBDIVIDER_UNIFORM_COMPOSITESQRT3T_HH defined
|
||||
//=============================================================================
|
||||
451
Tools/Subdivider/Uniform/LoopT.hh
Normal file
451
Tools/Subdivider/Uniform/LoopT.hh
Normal file
@@ -0,0 +1,451 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// OpenMesh
|
||||
// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen
|
||||
// www.openmesh.org
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// License
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation, version 2.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Revision: 1802 $
|
||||
// $Date: 2008-05-19 11:55:07 +0200 (Mo, 19. Mai 2008) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
/** \file LoopT.hh
|
||||
|
||||
*/
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// CLASS LoopT
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef OPENMESH_SUBDIVIDER_UNIFORM_LOOPT_HH
|
||||
#define OPENMESH_SUBDIVIDER_UNIFORM_LOOPT_HH
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
#include <OpenMesh/Core/System/config.hh>
|
||||
#include <OpenMesh/Tools/Subdivider/Uniform/SubdividerT.hh>
|
||||
#include <OpenMesh/Core/Utils/vector_cast.hh>
|
||||
// -------------------- STL
|
||||
#include <vector>
|
||||
#if defined(OM_CC_MIPS)
|
||||
# include <math.h>
|
||||
#else
|
||||
# include <cmath>
|
||||
#endif
|
||||
|
||||
|
||||
//== NAMESPACE ================================================================
|
||||
|
||||
namespace OpenMesh { // BEGIN_NS_OPENMESH
|
||||
namespace Subdivider { // BEGIN_NS_DECIMATER
|
||||
namespace Uniform { // BEGIN_NS_DECIMATER
|
||||
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
/** %Uniform Loop subdivision algorithm.
|
||||
*
|
||||
* Implementation as described in
|
||||
*
|
||||
* C. T. Loop, "Smooth Subdivision Surfaces Based on Triangles",
|
||||
* M.S. Thesis, Department of Mathematics, University of Utah, August 1987.
|
||||
*
|
||||
*/
|
||||
template <typename MeshType, typename RealType = float>
|
||||
class LoopT : public SubdividerT<MeshType, RealType>
|
||||
{
|
||||
public:
|
||||
|
||||
typedef RealType real_t;
|
||||
typedef MeshType mesh_t;
|
||||
typedef SubdividerT< mesh_t, real_t > parent_t;
|
||||
|
||||
typedef std::pair< real_t, real_t > weight_t;
|
||||
typedef std::vector< std::pair<real_t,real_t> > weights_t;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
LoopT(void) : parent_t(), _1over8( 1.0/8.0 ), _3over8( 3.0/8.0 )
|
||||
{ init_weights(); }
|
||||
|
||||
|
||||
LoopT( mesh_t& _m ) : parent_t(_m), _1over8( 1.0/8.0 ), _3over8( 3.0/8.0 )
|
||||
{ init_weights(); }
|
||||
|
||||
|
||||
~LoopT() {}
|
||||
|
||||
|
||||
public:
|
||||
|
||||
|
||||
const char *name() const { return "Uniform Loop"; }
|
||||
|
||||
|
||||
/// Pre-compute weights
|
||||
void init_weights(size_t _max_valence=50)
|
||||
{
|
||||
weights_.resize(_max_valence);
|
||||
std::generate(weights_.begin(), weights_.end(), compute_weight());
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
bool prepare( mesh_t& _m )
|
||||
{
|
||||
_m.add_property( vp_pos_ );
|
||||
_m.add_property( ep_pos_ );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool cleanup( mesh_t& _m )
|
||||
{
|
||||
_m.remove_property( vp_pos_ );
|
||||
_m.remove_property( ep_pos_ );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool subdivide( mesh_t& _m, size_t _n)
|
||||
{
|
||||
typename mesh_t::FaceIter fit, f_end;
|
||||
typename mesh_t::EdgeIter eit, e_end;
|
||||
typename mesh_t::VertexIter vit;
|
||||
|
||||
// Do _n subdivisions
|
||||
for (size_t i=0; i < _n; ++i)
|
||||
{
|
||||
// compute new positions for old vertices
|
||||
for ( vit = _m.vertices_begin();
|
||||
vit != _m.vertices_end(); ++vit)
|
||||
smooth( _m, vit.handle() );
|
||||
|
||||
|
||||
// Compute position for new vertices and store them in the edge property
|
||||
for (eit=_m.edges_begin(); eit != _m.edges_end(); ++eit)
|
||||
compute_midpoint( _m, eit.handle() );
|
||||
|
||||
|
||||
// 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.
|
||||
e_end = _m.edges_end();
|
||||
for (eit=_m.edges_begin(); eit != e_end; ++eit)
|
||||
split_edge(_m, eit.handle() );
|
||||
|
||||
|
||||
// Commit changes in topology and reconsitute consistency
|
||||
|
||||
// Attention! Creating new faces, hence make sure the loop ends correctly.
|
||||
f_end = _m.faces_end();
|
||||
for (fit = _m.faces_begin(); fit != f_end; ++fit)
|
||||
split_face(_m, fit.handle() );
|
||||
|
||||
|
||||
// Commit changes in geometry
|
||||
for ( vit = _m.vertices_begin();
|
||||
vit != _m.vertices_end(); ++vit)
|
||||
_m.set_point(vit, _m.property( vp_pos_, vit ) );
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUG)
|
||||
// Now we have an consistent mesh!
|
||||
assert( OpenMesh::Utils::MeshCheckerT<mesh_t>(_m).check() );
|
||||
#endif
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
/// Helper functor to compute weights for Loop-subdivision
|
||||
/// \internal
|
||||
struct compute_weight
|
||||
{
|
||||
compute_weight() : valence(-1) { }
|
||||
weight_t operator() (void)
|
||||
{
|
||||
#if !defined(OM_CC_MIPS)
|
||||
using std::cos;
|
||||
#endif
|
||||
// 1
|
||||
// alpha(n) = ---- * (40 - ( 3 + 2 cos( 2 Pi / n ) )<29> )
|
||||
// 64
|
||||
|
||||
if (++valence)
|
||||
{
|
||||
double inv_v = 1.0/double(valence);
|
||||
double t = (3.0 + 2.0 * cos( 2.0 * M_PI * inv_v) );
|
||||
double alpha = (40.0 - t * t)/64.0;
|
||||
|
||||
return weight_t( 1.0-alpha, inv_v*alpha);
|
||||
}
|
||||
return weight_t(0.0, 0.0);
|
||||
}
|
||||
int valence;
|
||||
};
|
||||
|
||||
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!)
|
||||
*/
|
||||
|
||||
// Old and new Face
|
||||
typename mesh_t::FaceHandle fh_old(_m.face_handle(heh6));
|
||||
typename mesh_t::FaceHandle fh_new(_m.new_face());
|
||||
|
||||
|
||||
// Re-Set Handles around old 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);
|
||||
|
||||
// Re-Set Handles around new Face
|
||||
_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)
|
||||
{
|
||||
typename mesh_t::HalfedgeHandle
|
||||
heh = _m.halfedge_handle(_eh, 0),
|
||||
opp_heh = _m.halfedge_handle(_eh, 1);
|
||||
|
||||
typename mesh_t::HalfedgeHandle new_heh, opp_new_heh, t_heh;
|
||||
typename mesh_t::VertexHandle vh;
|
||||
typename mesh_t::VertexHandle vh1(_m.to_vertex_handle(heh));
|
||||
typename mesh_t::Point zero(0,0,0);
|
||||
|
||||
// new vertex
|
||||
vh = _m.new_vertex( zero );
|
||||
|
||||
// memorize position, will be set later
|
||||
_m.property( vp_pos_, vh ) = _m.property( ep_pos_, _eh );
|
||||
|
||||
|
||||
// Re-link mesh entities
|
||||
if (_m.is_boundary(_eh))
|
||||
{
|
||||
for (t_heh = heh;
|
||||
_m.next_halfedge_handle(t_heh) != opp_heh;
|
||||
t_heh = _m.opposite_halfedge_handle(_m.next_halfedge_handle(t_heh)))
|
||||
{}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (t_heh = _m.next_halfedge_handle(opp_heh);
|
||||
_m.next_halfedge_handle(t_heh) != opp_heh;
|
||||
t_heh = _m.next_halfedge_handle(t_heh) )
|
||||
{}
|
||||
}
|
||||
|
||||
new_heh = _m.new_edge(vh, vh1);
|
||||
opp_new_heh = _m.opposite_halfedge_handle(new_heh);
|
||||
_m.set_vertex_handle( heh, vh );
|
||||
|
||||
_m.set_next_halfedge_handle(t_heh, opp_new_heh);
|
||||
_m.set_next_halfedge_handle(new_heh, _m.next_halfedge_handle(heh));
|
||||
_m.set_next_halfedge_handle(heh, new_heh);
|
||||
_m.set_next_halfedge_handle(opp_new_heh, opp_heh);
|
||||
|
||||
if (_m.face_handle(opp_heh).is_valid())
|
||||
{
|
||||
_m.set_face_handle(opp_new_heh, _m.face_handle(opp_heh));
|
||||
_m.set_halfedge_handle(_m.face_handle(opp_new_heh), opp_new_heh);
|
||||
}
|
||||
|
||||
_m.set_face_handle( new_heh, _m.face_handle(heh) );
|
||||
_m.set_halfedge_handle( vh, new_heh);
|
||||
_m.set_halfedge_handle( _m.face_handle(heh), heh );
|
||||
_m.set_halfedge_handle( vh1, opp_new_heh );
|
||||
|
||||
// Never forget this, when playing with the topology
|
||||
_m.adjust_outgoing_halfedge( vh );
|
||||
_m.adjust_outgoing_halfedge( vh1 );
|
||||
}
|
||||
|
||||
private: // geometry helper
|
||||
|
||||
void compute_midpoint(mesh_t& _m, const typename mesh_t::EdgeHandle& _eh)
|
||||
{
|
||||
#define V( X ) vector_cast< typename mesh_t::Normal >( X )
|
||||
typename mesh_t::HalfedgeHandle heh, opp_heh;
|
||||
|
||||
heh = _m.halfedge_handle( _eh, 0);
|
||||
opp_heh = _m.halfedge_handle( _eh, 1);
|
||||
|
||||
typename mesh_t::Point
|
||||
pos(_m.point(_m.to_vertex_handle(heh)));
|
||||
|
||||
pos += V( _m.point(_m.to_vertex_handle(opp_heh)) );
|
||||
|
||||
// boundary edge: just average vertex positions
|
||||
if (_m.is_boundary(_eh) )
|
||||
{
|
||||
pos *= 0.5;
|
||||
}
|
||||
else // inner edge: add neighbouring Vertices to sum
|
||||
{
|
||||
pos *= real_t(3.0);
|
||||
pos += V(_m.point(_m.to_vertex_handle(_m.next_halfedge_handle(heh))));
|
||||
pos += V(_m.point(_m.to_vertex_handle(_m.next_halfedge_handle(opp_heh))));
|
||||
pos *= _1over8;
|
||||
}
|
||||
_m.property( ep_pos_, _eh ) = pos;
|
||||
#undef V
|
||||
}
|
||||
|
||||
|
||||
void smooth(mesh_t& _m, const typename mesh_t::VertexHandle& _vh)
|
||||
{
|
||||
typename mesh_t::Point pos(0.0,0.0,0.0);
|
||||
|
||||
if (_m.is_boundary(_vh)) // if boundary: Point 1-6-1
|
||||
{
|
||||
typename mesh_t::HalfedgeHandle heh, prev_heh;
|
||||
heh = _m.halfedge_handle( _vh );
|
||||
|
||||
if ( heh.is_valid() )
|
||||
{
|
||||
assert( _m.is_boundary( _m.edge_handle( heh ) ) );
|
||||
|
||||
prev_heh = _m.prev_halfedge_handle( heh );
|
||||
|
||||
typename mesh_t::VertexHandle
|
||||
to_vh = _m.to_vertex_handle( heh ),
|
||||
from_vh = _m.from_vertex_handle( prev_heh );
|
||||
|
||||
// ( v_l + 6 v + v_r ) / 8
|
||||
pos = _m.point( _vh );
|
||||
pos *= real_t(6.0);
|
||||
pos += vector_cast< typename mesh_t::Normal >( _m.point( to_vh ) );
|
||||
pos += vector_cast< typename mesh_t::Normal >( _m.point( from_vh ) );
|
||||
pos *= _1over8;
|
||||
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
else // inner vertex: (1-a) * p + a/n * Sum q, q in one-ring of p
|
||||
{
|
||||
typedef typename mesh_t::Normal Vec;
|
||||
typename mesh_t::VertexVertexIter vvit;
|
||||
size_t valence(0);
|
||||
|
||||
// Calculate Valence and sum up neighbour points
|
||||
for (vvit=_m.vv_iter(_vh); vvit; ++vvit) {
|
||||
++valence;
|
||||
pos += vector_cast< Vec >( _m.point(vvit) );
|
||||
}
|
||||
pos *= weights_[valence].second; // alpha(n)/n * Sum q, q in one-ring of p
|
||||
pos += weights_[valence].first
|
||||
* vector_cast<Vec>(_m.point(_vh)); // + (1-a)*p
|
||||
}
|
||||
|
||||
_m.property( vp_pos_, _vh ) = pos;
|
||||
}
|
||||
|
||||
private: // data
|
||||
|
||||
OpenMesh::VPropHandleT< typename mesh_t::Point > vp_pos_;
|
||||
OpenMesh::EPropHandleT< typename mesh_t::Point > ep_pos_;
|
||||
|
||||
weights_t weights_;
|
||||
|
||||
const real_t _1over8;
|
||||
const real_t _3over8;
|
||||
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
} // END_NS_UNIFORM
|
||||
} // END_NS_SUBDIVIDER
|
||||
} // END_NS_OPENMESH
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_SUBDIVIDER_UNIFORM_COMPOSITELOOPT_HH defined
|
||||
//=============================================================================
|
||||
507
Tools/Subdivider/Uniform/Sqrt3T.hh
Normal file
507
Tools/Subdivider/Uniform/Sqrt3T.hh
Normal file
@@ -0,0 +1,507 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// OpenMesh
|
||||
// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen
|
||||
// www.openmesh.org
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// License
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation, version 2.1.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Revision: 4083 $
|
||||
// $Date: 2008-12-29 15:29:38 +0100 (Mo, 29. Dez 2008) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
/** \file Sqrt3T.hh
|
||||
|
||||
*/
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// CLASS Sqrt3T
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef OPENMESH_SUBDIVIDER_UNIFORM_SQRT3T_HH
|
||||
#define OPENMESH_SUBDIVIDER_UNIFORM_SQRT3T_HH
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
#include <OpenMesh/Core/Mesh/Handles.hh>
|
||||
#include <OpenMesh/Core/System/config.hh>
|
||||
#include <OpenMesh/Tools/Subdivider/Uniform/SubdividerT.hh>
|
||||
#if defined(_DEBUG) || defined(DEBUG)
|
||||
// Makes life lot easier, when playing/messing around with low-level topology
|
||||
// changing methods of OpenMesh
|
||||
# include <OpenMesh/Tools/Utils/MeshCheckerT.hh>
|
||||
# define ASSERT_CONSISTENCY( T, m ) \
|
||||
assert(OpenMesh::Utils::MeshCheckerT<T>(m).check())
|
||||
#else
|
||||
# define ASSERT_CONSISTENCY( T, m )
|
||||
#endif
|
||||
// -------------------- STL
|
||||
#include <vector>
|
||||
#if defined(OM_CC_MIPS)
|
||||
# include <math.h>
|
||||
#else
|
||||
# include <cmath>
|
||||
#endif
|
||||
|
||||
|
||||
//== NAMESPACE ================================================================
|
||||
|
||||
namespace OpenMesh { // BEGIN_NS_OPENMESH
|
||||
namespace Subdivider { // BEGIN_NS_DECIMATER
|
||||
namespace Uniform { // BEGIN_NS_DECIMATER
|
||||
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
|
||||
/** %Uniform Sqrt3 subdivision algorithm
|
||||
*
|
||||
* Implementation as described in
|
||||
*
|
||||
* 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>
|
||||
class Sqrt3T : public SubdividerT< MeshType, RealType >
|
||||
{
|
||||
public:
|
||||
|
||||
typedef RealType real_t;
|
||||
typedef MeshType mesh_t;
|
||||
typedef SubdividerT< mesh_t, real_t > parent_t;
|
||||
|
||||
typedef std::pair< real_t, real_t > weight_t;
|
||||
typedef std::vector< std::pair<real_t,real_t> > weights_t;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
Sqrt3T(void) : parent_t(), _1over3( 1.0/3.0 ), _1over27( 1.0/27.0 )
|
||||
{ init_weights(); }
|
||||
|
||||
Sqrt3T(MeshType &_m) : parent_t(_m), _1over3( 1.0/3.0 ), _1over27( 1.0/27.0 )
|
||||
{ init_weights(); }
|
||||
|
||||
virtual ~Sqrt3T() {}
|
||||
|
||||
|
||||
public:
|
||||
|
||||
|
||||
const char *name() const { return "Uniform Sqrt3"; }
|
||||
|
||||
|
||||
/// Pre-compute weights
|
||||
void init_weights(size_t _max_valence=50)
|
||||
{
|
||||
weights_.resize(_max_valence);
|
||||
std::generate(weights_.begin(), weights_.end(), compute_weight());
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
bool prepare( MeshType& _m )
|
||||
{
|
||||
_m.request_edge_status();
|
||||
_m.add_property( vp_pos_ );
|
||||
_m.add_property( ep_nv_ );
|
||||
_m.add_property( mp_gen_ );
|
||||
_m.property( mp_gen_ ) = 0;
|
||||
|
||||
return _m.has_edge_status() && vp_pos_.is_valid()
|
||||
&& ep_nv_.is_valid() && mp_gen_.is_valid();
|
||||
}
|
||||
|
||||
|
||||
bool cleanup( MeshType& _m )
|
||||
{
|
||||
_m.release_edge_status();
|
||||
_m.remove_property( vp_pos_ );
|
||||
_m.remove_property( ep_nv_ );
|
||||
_m.remove_property( mp_gen_ );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool subdivide( MeshType& _m, size_t _n )
|
||||
{
|
||||
typename MeshType::VertexIter vit;
|
||||
typename MeshType::VertexVertexIter vvit;
|
||||
typename MeshType::EdgeIter eit;
|
||||
typename MeshType::FaceIter fit;
|
||||
typename MeshType::FaceVertexIter fvit;
|
||||
typename MeshType::VertexHandle vh;
|
||||
typename MeshType::HalfedgeHandle heh;
|
||||
typename MeshType::Point pos(0,0,0), zero(0,0,0);
|
||||
size_t &gen = _m.property( mp_gen_ );
|
||||
|
||||
for (size_t l=0; l<_n; ++l)
|
||||
{
|
||||
// tag existing edges
|
||||
for (eit=_m.edges_begin(); eit != _m.edges_end();++eit)
|
||||
{
|
||||
_m.status( eit ).set_tagged( true );
|
||||
if ( (gen%2) && _m.is_boundary(eit) )
|
||||
compute_new_boundary_points( _m, eit ); // *) creates new vertices
|
||||
}
|
||||
|
||||
// do relaxation of old vertices, but store new pos in property vp_pos_
|
||||
|
||||
for (vit=_m.vertices_begin(); vit!=_m.vertices_end(); ++vit)
|
||||
{
|
||||
if ( _m.is_boundary(vit) )
|
||||
{
|
||||
if ( gen%2 )
|
||||
{
|
||||
heh = _m.halfedge_handle(vit);
|
||||
if (heh.is_valid()) // skip isolated newly inserted vertices *)
|
||||
{
|
||||
typename OpenMesh::HalfedgeHandle
|
||||
prev_heh = _m.prev_halfedge_handle(heh);
|
||||
|
||||
assert( _m.is_boundary(heh ) );
|
||||
assert( _m.is_boundary(prev_heh) );
|
||||
|
||||
pos = _m.point(_m.to_vertex_handle(heh));
|
||||
pos += _m.point(_m.from_vertex_handle(prev_heh));
|
||||
pos *= real_t(4.0);
|
||||
|
||||
pos += real_t(19.0) * _m.point( vit );
|
||||
pos *= _1over27;
|
||||
|
||||
_m.property( vp_pos_, vit ) = pos;
|
||||
}
|
||||
}
|
||||
else
|
||||
_m.property( vp_pos_, vit ) = _m.point( vit );
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t valence=0;
|
||||
|
||||
pos = zero;
|
||||
for ( vvit = _m.vv_iter(vit); vvit; ++vvit)
|
||||
{
|
||||
pos += _m.point( vvit );
|
||||
++valence;
|
||||
}
|
||||
pos *= weights_[ valence ].second;
|
||||
pos += weights_[ valence ].first * _m.point(vit);
|
||||
_m.property( vp_pos_, vit ) = pos;
|
||||
}
|
||||
}
|
||||
|
||||
// insert new vertices, but store pos in vp_pos_
|
||||
typename MeshType::FaceIter fend = _m.faces_end();
|
||||
for (fit = _m.faces_begin();fit != fend; ++fit)
|
||||
{
|
||||
if ( (gen%2) && _m.is_boundary(fit))
|
||||
{
|
||||
boundary_split( _m, fit );
|
||||
}
|
||||
else
|
||||
{
|
||||
fvit = _m.fv_iter( fit );
|
||||
pos = _m.point( fvit);
|
||||
pos += _m.point(++fvit);
|
||||
pos += _m.point(++fvit);
|
||||
pos *= _1over3;
|
||||
vh = _m.add_vertex( zero );
|
||||
_m.property( vp_pos_, vh ) = pos;
|
||||
_m.split( fit, vh );
|
||||
}
|
||||
}
|
||||
|
||||
// commit new positions (now iterating over all vertices)
|
||||
for (vit=_m.vertices_begin();vit != _m.vertices_end(); ++vit)
|
||||
_m.set_point(vit, _m.property( vp_pos_, vit ) );
|
||||
|
||||
// flip old edges
|
||||
for (eit=_m.edges_begin(); eit != _m.edges_end(); ++eit)
|
||||
if ( _m.status( eit ).tagged() && !_m.is_boundary( eit ) )
|
||||
_m.flip(eit);
|
||||
|
||||
// Now we have an consistent mesh!
|
||||
ASSERT_CONSISTENCY( MeshType, _m );
|
||||
|
||||
// increase generation by one
|
||||
++gen;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
/// Helper functor to compute weights for sqrt(3)-subdivision
|
||||
/// \internal
|
||||
struct compute_weight
|
||||
{
|
||||
compute_weight() : valence(-1) { }
|
||||
weight_t operator() (void)
|
||||
{
|
||||
#if !defined(OM_CC_MIPS)
|
||||
using std::cos;
|
||||
#endif
|
||||
if (++valence)
|
||||
{
|
||||
real_t alpha = (4.0-2.0*cos(2.0*M_PI / (double)valence))/9.0;
|
||||
return weight_t( real_t(1)-alpha, alpha/real_t(valence) );
|
||||
}
|
||||
return weight_t(0.0, 0.0);
|
||||
}
|
||||
int valence;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
// Pre-compute location of new boundary points for odd generations
|
||||
// and store them in the edge property ep_nv_;
|
||||
void compute_new_boundary_points( MeshType& _m,
|
||||
const typename MeshType::EdgeHandle& _eh)
|
||||
{
|
||||
assert( _m.is_boundary(_eh) );
|
||||
|
||||
typename MeshType::HalfedgeHandle heh;
|
||||
typename MeshType::VertexHandle vh1, vh2, vh3, vh4, vhl, vhr;
|
||||
typename MeshType::Point zero(0,0,0), P1, P2, P3, P4;
|
||||
|
||||
/*
|
||||
// *---------*---------*
|
||||
// / \ / \ / \
|
||||
// / \ / \ / \
|
||||
// / \ / \ / \
|
||||
// / \ / \ / \
|
||||
// *---------*--#---#--*---------*
|
||||
//
|
||||
// ^ ^ ^ ^ ^ ^
|
||||
// P1 P2 pl pr P3 P4
|
||||
*/
|
||||
// get halfedge pointing from P3 to P2 (outer boundary halfedge)
|
||||
|
||||
heh = _m.halfedge_handle(_eh,
|
||||
_m.is_boundary(_m.halfedge_handle(_eh,1)));
|
||||
|
||||
assert( _m.is_boundary( _m.next_halfedge_handle( heh ) ) );
|
||||
assert( _m.is_boundary( _m.prev_halfedge_handle( heh ) ) );
|
||||
|
||||
vh1 = _m.to_vertex_handle( _m.next_halfedge_handle( heh ) );
|
||||
vh2 = _m.to_vertex_handle( heh );
|
||||
vh3 = _m.from_vertex_handle( heh );
|
||||
vh4 = _m.from_vertex_handle( _m.prev_halfedge_handle( heh ));
|
||||
|
||||
P1 = _m.point(vh1);
|
||||
P2 = _m.point(vh2);
|
||||
P3 = _m.point(vh3);
|
||||
P4 = _m.point(vh4);
|
||||
|
||||
vhl = _m.add_vertex(zero);
|
||||
vhr = _m.add_vertex(zero);
|
||||
|
||||
_m.property(vp_pos_, vhl ) = (P1 + 16.0f*P2 + 10.0f*P3) * _1over27;
|
||||
_m.property(vp_pos_, vhr ) = (10.0f*P2 + 16.0f*P3 + P4) * _1over27;
|
||||
_m.property(ep_nv_, _eh).first = vhl;
|
||||
_m.property(ep_nv_, _eh).second = vhr;
|
||||
}
|
||||
|
||||
|
||||
void boundary_split( MeshType& _m, const typename MeshType::FaceHandle& _fh )
|
||||
{
|
||||
assert( _m.is_boundary(_fh) );
|
||||
|
||||
typename MeshType::VertexHandle vhl, vhr;
|
||||
typename MeshType::FaceEdgeIter fe_it;
|
||||
typename MeshType::HalfedgeHandle heh;
|
||||
|
||||
// find boundary edge
|
||||
for( fe_it=_m.fe_iter( _fh ); fe_it && !_m.is_boundary( fe_it ); ++fe_it );
|
||||
|
||||
// use precomputed, already inserted but not linked vertices
|
||||
vhl = _m.property(ep_nv_, fe_it).first;
|
||||
vhr = _m.property(ep_nv_, fe_it).second;
|
||||
|
||||
/*
|
||||
// *---------*---------*
|
||||
// / \ / \ / \
|
||||
// / \ / \ / \
|
||||
// / \ / \ / \
|
||||
// / \ / \ / \
|
||||
// *---------*--#---#--*---------*
|
||||
//
|
||||
// ^ ^ ^ ^ ^ ^
|
||||
// P1 P2 pl pr P3 P4
|
||||
*/
|
||||
// get halfedge pointing from P2 to P3 (inner boundary halfedge)
|
||||
|
||||
heh = _m.halfedge_handle(fe_it,
|
||||
_m.is_boundary(_m.halfedge_handle(fe_it,0)));
|
||||
|
||||
typename MeshType::HalfedgeHandle pl_P3;
|
||||
|
||||
// split P2->P3 (heh) in P2->pl (heh) and pl->P3
|
||||
boundary_split( _m, heh, vhl ); // split edge
|
||||
pl_P3 = _m.next_halfedge_handle( heh ); // store next halfedge handle
|
||||
boundary_split( _m, heh ); // split face
|
||||
|
||||
// split pl->P3 in pl->pr and pr->P3
|
||||
boundary_split( _m, pl_P3, vhr );
|
||||
boundary_split( _m, pl_P3 );
|
||||
|
||||
assert( _m.is_boundary( vhl ) && _m.halfedge_handle(vhl).is_valid() );
|
||||
assert( _m.is_boundary( vhr ) && _m.halfedge_handle(vhr).is_valid() );
|
||||
}
|
||||
|
||||
void boundary_split(MeshType& _m,
|
||||
const typename MeshType::HalfedgeHandle& _heh,
|
||||
const typename MeshType::VertexHandle& _vh)
|
||||
{
|
||||
assert( _m.is_boundary( _m.edge_handle(_heh) ) );
|
||||
|
||||
typename MeshType::HalfedgeHandle
|
||||
heh(_heh),
|
||||
opp_heh( _m.opposite_halfedge_handle(_heh) ),
|
||||
new_heh, opp_new_heh;
|
||||
typename MeshType::VertexHandle to_vh(_m.to_vertex_handle(heh));
|
||||
typename MeshType::HalfedgeHandle t_heh;
|
||||
|
||||
/*
|
||||
* P5
|
||||
* *
|
||||
* /|\
|
||||
* / \
|
||||
* / \
|
||||
* / \
|
||||
* / \
|
||||
* /_ heh new \
|
||||
* *-----\*-----\*\-----*
|
||||
* ^ ^ t_heh
|
||||
* _vh to_vh
|
||||
*
|
||||
* P1 P2 P3 P4
|
||||
*/
|
||||
// Re-Setting Handles
|
||||
|
||||
// find halfedge point from P4 to P3
|
||||
for(t_heh = heh;
|
||||
_m.next_halfedge_handle(t_heh) != opp_heh;
|
||||
t_heh = _m.opposite_halfedge_handle(_m.next_halfedge_handle(t_heh)))
|
||||
{}
|
||||
|
||||
assert( _m.is_boundary( t_heh ) );
|
||||
|
||||
new_heh = _m.new_edge( _vh, to_vh );
|
||||
opp_new_heh = _m.opposite_halfedge_handle(new_heh);
|
||||
|
||||
// update halfedge connectivity
|
||||
|
||||
_m.set_next_halfedge_handle(t_heh, opp_new_heh); // P4-P3 -> P3-P2
|
||||
// P2-P3 -> P3-P5
|
||||
_m.set_next_halfedge_handle(new_heh, _m.next_halfedge_handle(heh));
|
||||
_m.set_next_halfedge_handle(heh, new_heh); // P1-P2 -> P2-P3
|
||||
_m.set_next_halfedge_handle(opp_new_heh, opp_heh); // P3-P2 -> P2-P1
|
||||
|
||||
// both opposite halfedges point to same face
|
||||
_m.set_face_handle(opp_new_heh, _m.face_handle(opp_heh));
|
||||
|
||||
// let heh finally point to new inserted vertex
|
||||
_m.set_vertex_handle(heh, _vh);
|
||||
|
||||
// let heh and new_heh point to same face
|
||||
_m.set_face_handle(new_heh, _m.face_handle(heh));
|
||||
|
||||
// let opp_new_heh be the new outgoing halfedge for to_vh
|
||||
// (replaces for opp_heh)
|
||||
_m.set_halfedge_handle( to_vh, opp_new_heh );
|
||||
|
||||
// let opp_heh be the outgoing halfedge for _vh
|
||||
_m.set_halfedge_handle( _vh, opp_heh );
|
||||
}
|
||||
|
||||
void boundary_split( MeshType& _m,
|
||||
const typename MeshType::HalfedgeHandle& _heh)
|
||||
{
|
||||
assert( _m.is_boundary( _m.opposite_halfedge_handle( _heh ) ) );
|
||||
|
||||
typename MeshType::HalfedgeHandle
|
||||
heh(_heh),
|
||||
n_heh(_m.next_halfedge_handle(heh));
|
||||
|
||||
typename MeshType::VertexHandle
|
||||
to_vh(_m.to_vertex_handle(heh));
|
||||
|
||||
typename MeshType::HalfedgeHandle
|
||||
heh2(_m.new_edge(to_vh,
|
||||
_m.to_vertex_handle(_m.next_halfedge_handle(n_heh)))),
|
||||
heh3(_m.opposite_halfedge_handle(heh2));
|
||||
|
||||
typename MeshType::FaceHandle
|
||||
new_fh(_m.new_face()),
|
||||
fh(_m.face_handle(heh));
|
||||
|
||||
// Relink (half)edges
|
||||
|
||||
#define set_next_heh set_next_halfedge_handle
|
||||
#define next_heh next_halfedge_handle
|
||||
|
||||
_m.set_face_handle(heh, new_fh);
|
||||
_m.set_face_handle(heh2, new_fh);
|
||||
_m.set_next_heh(heh2, _m.next_heh(_m.next_heh(n_heh)));
|
||||
_m.set_next_heh(heh, heh2);
|
||||
_m.set_face_handle( _m.next_heh(heh2), new_fh);
|
||||
|
||||
// _m.set_face_handle( _m.next_heh(_m.next_heh(heh2)), new_fh);
|
||||
|
||||
_m.set_next_heh(heh3, n_heh);
|
||||
_m.set_next_heh(_m.next_halfedge_handle(n_heh), heh3);
|
||||
_m.set_face_handle(heh3, fh);
|
||||
// _m.set_face_handle(n_heh, fh);
|
||||
|
||||
_m.set_halfedge_handle( fh, n_heh);
|
||||
_m.set_halfedge_handle(new_fh, heh);
|
||||
|
||||
#undef set_next_halfedge_handle
|
||||
#undef next_halfedge_handle
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
weights_t weights_;
|
||||
OpenMesh::VPropHandleT< typename MeshType::Point > vp_pos_;
|
||||
OpenMesh::EPropHandleT< std::pair< typename MeshType::VertexHandle,
|
||||
typename MeshType::VertexHandle> > ep_nv_;
|
||||
OpenMesh::MPropHandleT< size_t > mp_gen_;
|
||||
|
||||
const real_t _1over3;
|
||||
const real_t _1over27;
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
} // END_NS_UNIFORM
|
||||
} // END_NS_SUBDIVIDER
|
||||
} // END_NS_OPENMESH
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_SUBDIVIDER_UNIFORM_SQRT3T_HH
|
||||
//=============================================================================
|
||||
179
Tools/Subdivider/Uniform/SubdividerT.hh
Normal file
179
Tools/Subdivider/Uniform/SubdividerT.hh
Normal file
@@ -0,0 +1,179 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// OpenMesh
|
||||
// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen
|
||||
// www.openmesh.org
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// License
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation, version 2.1.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Revision: 1802 $
|
||||
// $Date: 2008-05-19 11:55:07 +0200 (Mo, 19. Mai 2008) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
/** \file SubdividerT.hh
|
||||
|
||||
*/
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// CLASS SubdividerT
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef OPENMESH_SUBDIVIDER_UNIFORM_SUDIVIDERT_HH
|
||||
#define OPENMESH_SUBDIVIDER_UNIFORM_SUDIVIDERT_HH
|
||||
|
||||
//== INCLUDE ==================================================================
|
||||
|
||||
#include <OpenMesh/Core/System/config.hh>
|
||||
#include <OpenMesh/Core/Utils/Noncopyable.hh>
|
||||
#if defined(_DEBUG) || defined(DEBUG)
|
||||
// Makes life lot easier, when playing/messing around with low-level topology
|
||||
// changing methods of OpenMesh
|
||||
# include <OpenMesh/Tools/Utils/MeshCheckerT.hh>
|
||||
# define ASSERT_CONSISTENCY( T, m ) \
|
||||
assert(OpenMesh::Utils::MeshCheckerT<T>(m).check())
|
||||
#else
|
||||
# define ASSERT_CONSISTENCY( T, m )
|
||||
#endif
|
||||
|
||||
//== NAMESPACE ================================================================
|
||||
|
||||
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()
|
||||
*/
|
||||
template <typename MeshType, typename RealType=float>
|
||||
class SubdividerT : private Utils::Noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
typedef MeshType mesh_t;
|
||||
typedef RealType real_t;
|
||||
|
||||
public:
|
||||
|
||||
/// \name Constructors
|
||||
//@{
|
||||
/// Constructor to be used with interface 2
|
||||
/// \see attach(), operator()(size_t), detach()
|
||||
SubdividerT(void) : attached_(NULL) { }
|
||||
|
||||
/// Constructor to be used with interface 1 (calls attach())
|
||||
/// \see operator()( MeshType&, size_t )
|
||||
SubdividerT( MeshType &_m ) : attached_(NULL) { attach(_m); }
|
||||
|
||||
//@}
|
||||
|
||||
/// Descructor (calls detach())
|
||||
virtual ~SubdividerT()
|
||||
{ detach(); }
|
||||
|
||||
/// Return name of subdivision algorithm
|
||||
virtual const char *name( void ) const = 0;
|
||||
|
||||
|
||||
public: /// \name Interface 1
|
||||
|
||||
//@{
|
||||
/// Subdivide the mesh \c _m \c _n times.
|
||||
/// \see SubdividerT(MeshType&)
|
||||
bool operator () ( MeshType& _m, size_t _n )
|
||||
{
|
||||
return prepare(_m) && subdivide( _m, _n ) && cleanup( _m );
|
||||
}
|
||||
//@}
|
||||
|
||||
public: /// \name Interface 2
|
||||
//@{
|
||||
/// Attach mesh \c _m to self
|
||||
/// \see SubdividerT(), operator()(size_t), detach()
|
||||
bool attach( MeshType& _m )
|
||||
{
|
||||
if ( attached_ == &_m )
|
||||
return true;
|
||||
|
||||
detach();
|
||||
if (prepare( _m ))
|
||||
{
|
||||
attached_ = &_m;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Subdivide the attached \c _n times.
|
||||
/// \see SubdividerT(), attach(), detach()
|
||||
bool operator()( size_t _n )
|
||||
{
|
||||
return attached_ ? subdivide( *attached_, _n ) : false;
|
||||
}
|
||||
|
||||
/// Detach an eventually attached mesh.
|
||||
/// \see SubdividerT(), attach(), operator()(size_t)
|
||||
void detach(void)
|
||||
{
|
||||
if ( attached_ )
|
||||
{
|
||||
cleanup( *attached_ );
|
||||
attached_ = NULL;
|
||||
}
|
||||
}
|
||||
//@}
|
||||
|
||||
protected:
|
||||
|
||||
/// \name Overload theses methods
|
||||
//@{
|
||||
/// Prepare mesh, e.g. add properties
|
||||
virtual bool prepare( MeshType& _m ) = 0;
|
||||
|
||||
/// Subdivide mesh \c _m \c _n times
|
||||
virtual bool subdivide( MeshType& _m, size_t _n ) = 0;
|
||||
|
||||
/// Cleanup mesh after usage, e.g. remove added properties
|
||||
virtual bool cleanup( MeshType& _m ) = 0;
|
||||
//@}
|
||||
|
||||
private:
|
||||
|
||||
MeshType *attached_;
|
||||
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
} // namespace Uniform
|
||||
} // namespace Subdivider
|
||||
} // namespace OpenMesh
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_SUBDIVIDER_UNIFORM_SUBDIVIDERT_HH
|
||||
//=============================================================================
|
||||
Reference in New Issue
Block a user