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:
Jan Möbius
2009-02-06 13:37:46 +00:00
parent c3321ebdd9
commit 97f515985d
417 changed files with 76182 additions and 0 deletions

View 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
#==============================================================================

View 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
#==============================================================================

View 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
#==============================================================================

View 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
//=============================================================================

View 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
//=============================================================================

View 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
//=============================================================================

View 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
//=============================================================================

File diff suppressed because it is too large Load Diff

View 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
//=============================================================================

View 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
//=============================================================================

View 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
#==============================================================================

View 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
#==============================================================================

File diff suppressed because it is too large Load Diff

View 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
//=============================================================================

View 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
//=============================================================================

View 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
//=============================================================================

View 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
//=============================================================================

View 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
//=============================================================================

View 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
//=============================================================================

View 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
//=============================================================================