First checkin for OpenMesh 2.0
git-svn-id: http://www.openmesh.org/svnrepo/OpenMesh/trunk@2 fdac6126-5c0c-442c-9429-916003d36597
This commit is contained in:
17
Tools/Subdivider/Uniform/ACGMakefile
Normal file
17
Tools/Subdivider/Uniform/ACGMakefile
Normal file
@@ -0,0 +1,17 @@
|
||||
#== SYSTEM PART -- DON'T TOUCH ==============================================
|
||||
include $(ACGMAKE)/Config
|
||||
#==============================================================================
|
||||
|
||||
|
||||
SUBDIRS = $(call find-subdirs)
|
||||
|
||||
PACKAGES :=
|
||||
|
||||
PROJ_LIBS :=
|
||||
|
||||
MODULES := cxxlib
|
||||
|
||||
|
||||
#== SYSTEM PART -- DON'T TOUCH ==============================================
|
||||
include $(ACGMAKE)/Rules
|
||||
#==============================================================================
|
||||
17
Tools/Subdivider/Uniform/Composite/ACGMakefile
Normal file
17
Tools/Subdivider/Uniform/Composite/ACGMakefile
Normal file
@@ -0,0 +1,17 @@
|
||||
#== SYSTEM PART -- DON'T TOUCH ==============================================
|
||||
include $(ACGMAKE)/Config
|
||||
#==============================================================================
|
||||
|
||||
|
||||
SUBDIRS = $(call find-subdirs)
|
||||
|
||||
PACKAGES :=
|
||||
|
||||
PROJ_LIBS :=
|
||||
|
||||
MODULES := cxxlib
|
||||
|
||||
|
||||
#== SYSTEM PART -- DON'T TOUCH ==============================================
|
||||
include $(ACGMAKE)/Rules
|
||||
#==============================================================================
|
||||
1310
Tools/Subdivider/Uniform/Composite/CompositeT.cc
Normal file
1310
Tools/Subdivider/Uniform/Composite/CompositeT.cc
Normal file
File diff suppressed because it is too large
Load Diff
233
Tools/Subdivider/Uniform/Composite/CompositeT.hh
Normal file
233
Tools/Subdivider/Uniform/Composite/CompositeT.hh
Normal file
@@ -0,0 +1,233 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// OpenMesh
|
||||
// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen
|
||||
// www.openmesh.org
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// License
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation, version 2.1.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Revision: 1802 $
|
||||
// $Date: 2008-05-19 11:55:07 +0200 (Mo, 19. Mai 2008) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
/** \file Uniform/Composite/CompositeT.hh
|
||||
|
||||
*/
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// CLASS CompositeT
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef OPENMESH_SUBDIVIDER_UNIFORM_COMPOSITE_HH
|
||||
#define OPENMESH_SUBDIVIDER_UNIFORM_COMPOSITE_HH
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
// --------------------
|
||||
#include <OpenMesh/Tools/Subdivider/Uniform/SubdividerT.hh>
|
||||
|
||||
//== NAMESPACE ================================================================
|
||||
|
||||
namespace OpenMesh { // BEGIN_NS_OPENMESH
|
||||
namespace Subdivider { // BEGIN_NS_DECIMATER
|
||||
namespace Uniform { // BEGIN_NS_UNIFORM
|
||||
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
/** This class provides the composite subdivision rules for the uniform case.
|
||||
*
|
||||
* To create a subdivider derive from this class and overload the functions
|
||||
* name() and apply_rules(). In the latter one call the wanted rules.
|
||||
*
|
||||
* For details on the composite scheme refer to
|
||||
* - <a
|
||||
* href="http://cm.bell-labs.com/who/poswald/sqrt3.pdf">P. Oswald,
|
||||
* P. Schroeder "Composite primal/dual sqrt(3)-subdivision schemes",
|
||||
* CAGD 20, 3, 2003, 135--164</a>
|
||||
|
||||
* \note Not all rules are implemented!
|
||||
* \see class Adaptive::CompositeT
|
||||
*/
|
||||
template <typename MeshType, typename RealType=float >
|
||||
class CompositeT : public SubdividerT< MeshType, RealType >
|
||||
{
|
||||
public:
|
||||
|
||||
typedef RealType real_t;
|
||||
typedef MeshType mesh_t;
|
||||
typedef SubdividerT< mesh_t, real_t > parent_t;
|
||||
|
||||
public:
|
||||
|
||||
CompositeT(void) : parent_t(), p_mesh_(NULL) {}
|
||||
CompositeT(MeshType& _mesh) : parent_t(_mesh), p_mesh_(NULL) {};
|
||||
virtual ~CompositeT() { }
|
||||
|
||||
public: // inherited interface
|
||||
|
||||
virtual const char *name( void ) const = 0;
|
||||
|
||||
protected: // inherited interface
|
||||
|
||||
bool prepare( MeshType& _m );
|
||||
|
||||
bool subdivide( MeshType& _m, size_t _n )
|
||||
{
|
||||
assert( p_mesh_ == &_m );
|
||||
|
||||
while(_n--)
|
||||
{
|
||||
apply_rules();
|
||||
commit(_m);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef NDEBUG
|
||||
bool cleanup( MeshType& )
|
||||
#else
|
||||
bool cleanup( MeshType& _m )
|
||||
#endif
|
||||
{
|
||||
assert( p_mesh_ == &_m );
|
||||
p_mesh_=NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/// Assemble here the rule sequence, by calling the constructor
|
||||
/// of the wanted rules.
|
||||
virtual void apply_rules(void) = 0;
|
||||
|
||||
protected:
|
||||
|
||||
/// Move vertices to new positions after the rules have been applied
|
||||
/// to the mesh (called by subdivide()).
|
||||
void commit( MeshType &_m)
|
||||
{
|
||||
typename MeshType::VertexIter v_it;
|
||||
|
||||
for (v_it=_m.vertices_begin(); v_it != _m.vertices_end(); ++v_it)
|
||||
_m.set_point(v_it.handle(), _m.data(v_it).position());
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
|
||||
/// Abstract base class for coefficient functions
|
||||
struct Coeff
|
||||
{
|
||||
virtual ~Coeff() { }
|
||||
virtual double operator() (size_t _valence) = 0;
|
||||
};
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
typedef typename MeshType::Scalar scalar_t;
|
||||
typedef typename MeshType::VertexHandle VertexHandle;
|
||||
typedef typename MeshType::FaceHandle FaceHandle;
|
||||
typedef typename MeshType::EdgeHandle EdgeHandle;
|
||||
typedef typename MeshType::HalfedgeHandle HalfedgeHandle;
|
||||
|
||||
/// \name Uniform composite subdivision rules
|
||||
//@{
|
||||
|
||||
|
||||
void Tvv3(); ///< Split Face, using Vertex information (1-3 split)
|
||||
void Tvv4(); ///< Split Face, using Vertex information (1-4 split)
|
||||
void Tfv(); ///< Split Face, using Face Information
|
||||
|
||||
void FF(); ///< Face to face averaging.
|
||||
void FFc(Coeff& _coeff); ///< Weighted face to face averaging.
|
||||
void FFc(scalar_t _c); ///< Weighted face to face averaging.
|
||||
|
||||
void FV(); ///< Face to vertex averaging.
|
||||
void FVc(Coeff& _coeff); ///< Weighted face to vertex Averaging with flaps
|
||||
void FVc(scalar_t _c); ///< Weighted face to vertex Averaging with flaps
|
||||
|
||||
void FE(); ///< Face to edge averaging.
|
||||
|
||||
void VF(); ///< Vertex to Face Averaging.
|
||||
void VFa(Coeff& _coeff); ///< Vertex to Face Averaging, weighted.
|
||||
void VFa(scalar_t _alpha); ///< Vertex to Face Averaging, weighted.
|
||||
|
||||
void VV(); ///< Vertex to vertex averaging.
|
||||
void VVc(Coeff& _coeff); ///< Vertex to vertex averaging, weighted.
|
||||
void VVc(scalar_t _c); ///< Vertex to vertex averaging, weighted.
|
||||
|
||||
void VE(); ///< VE Step (Vertex to Edge Averaging)
|
||||
|
||||
|
||||
void VdE(); ///< Vertex to edge averaging, using diamond of edges.
|
||||
void VdEc(scalar_t _c); ///< Weighted vertex to edge averaging, using diamond of edges
|
||||
|
||||
/// Weigthed vertex to edge averaging, using diamond of edges for
|
||||
/// irregular vertices.
|
||||
void VdEg(Coeff& _coeff);
|
||||
/// Weigthed vertex to edge averaging, using diamond of edges for
|
||||
/// irregular vertices.
|
||||
void VdEg(scalar_t _gamma);
|
||||
|
||||
void EF(); ///< Edge to face averaging.
|
||||
|
||||
void EV(); ///< Edge to vertex averaging.
|
||||
void EVc(Coeff& _coeff); ///< Weighted edge to vertex averaging.
|
||||
void EVc(scalar_t _c); ///< Weighted edge to vertex averaging.
|
||||
|
||||
void EdE(); ///< Edge to edge averaging w/ flap rule.
|
||||
void EdEc(scalar_t _c); ///< Weighted edge to edge averaging w/ flap rule.
|
||||
|
||||
|
||||
//@}
|
||||
|
||||
void corner_cutting(HalfedgeHandle _heh);
|
||||
|
||||
VertexHandle split_edge(HalfedgeHandle _heh);
|
||||
|
||||
private:
|
||||
|
||||
MeshType* p_mesh_;
|
||||
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
} // END_NS_UNIFORM
|
||||
} // END_NS_SUBDIVIDER
|
||||
} // END_NS_OPENMESH
|
||||
//=============================================================================
|
||||
#if defined(OM_INCLUDE_TEMPLATES) && !defined(OPENMESH_SUBDIVIDER_UNIFORM_COMPOSITE_CC)
|
||||
#define OPENMESH_SUBDIVIDER_TEMPLATES
|
||||
#include "CompositeT.cc"
|
||||
#endif
|
||||
//=============================================================================
|
||||
#endif // COMPOSITET_HH defined
|
||||
//=============================================================================
|
||||
|
||||
150
Tools/Subdivider/Uniform/Composite/CompositeTraits.hh
Normal file
150
Tools/Subdivider/Uniform/Composite/CompositeTraits.hh
Normal file
@@ -0,0 +1,150 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// OpenMesh
|
||||
// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen
|
||||
// www.openmesh.org
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// License
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation, version 2.1.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Revision: 1802 $
|
||||
// $Date: 2008-05-19 11:55:07 +0200 (Mo, 19. Mai 2008) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
/** \file Uniform/Composite/CompositeTraits.hh
|
||||
Mesh traits for uniform composite subdivision.
|
||||
*/
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// CLASS Traits
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef OPENMESH_SUBDIVIDER_UNIFORM_COMPOSITETRAITS_HH
|
||||
#define OPENMESH_SUBDIVIDER_UNIFORM_COMPOSITETRAITS_HH
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
//#include "Config.hh"
|
||||
// --------------------
|
||||
#include <OpenMesh/Core/Mesh/Traits.hh>
|
||||
#include <OpenMesh/Core/Mesh/Attributes.hh>
|
||||
|
||||
|
||||
//== NAMESPACE ================================================================
|
||||
|
||||
namespace OpenMesh { // BEGIN_NS_OPENMESH
|
||||
namespace Subdivider { // BEGIN_NS_DECIMATER
|
||||
namespace Uniform { // BEGIN_NS_UNIFORM
|
||||
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
|
||||
/** Uniform Composite Subdivision framework.
|
||||
*/
|
||||
|
||||
struct CompositeTraits : public OpenMesh::DefaultTraits
|
||||
{
|
||||
FaceAttributes( OpenMesh::Attributes::Normal );
|
||||
|
||||
VertexAttributes( OpenMesh::Attributes::Normal );
|
||||
|
||||
//HalfedgeAttributes( OpenMesh::Attributes::PrevHalfedge );
|
||||
|
||||
FaceTraits
|
||||
{
|
||||
private:
|
||||
typedef typename Refs::HalfedgeHandle HalfedgeHandle;
|
||||
typedef typename Refs::Scalar Scalar;
|
||||
typedef typename Refs::Point Point;
|
||||
HalfedgeHandle red_halfedge_handle_;
|
||||
unsigned int generation_;
|
||||
bool red_;
|
||||
Scalar quality_;
|
||||
Point midpoint_;
|
||||
Point position_;
|
||||
|
||||
public:
|
||||
const unsigned int& generation() { return generation_; }
|
||||
void set_generation(const unsigned int& _g) { generation_ = _g; }
|
||||
void inc_generation() { ++generation_; }
|
||||
void set_red() { red_ = 1; }
|
||||
void set_green() {red_ = 0; }
|
||||
bool is_red() { return red_; }
|
||||
bool is_green() { return !red_; }
|
||||
void set_red_halfedge_handle(HalfedgeHandle& _heh)
|
||||
{ red_halfedge_handle_ = _heh; }
|
||||
HalfedgeHandle& red_halfedge_handle() { return red_halfedge_handle_; }
|
||||
void set_quality(Scalar& _q) { quality_ = _q; }
|
||||
Scalar& quality() { return quality_; }
|
||||
const Point& midpoint() const { return midpoint_; }
|
||||
void set_midpoint(const Point& _p) { midpoint_ = _p; }
|
||||
const Point& position() const { return position_; }
|
||||
void set_position(const Point& _p) { position_ = _p; }
|
||||
};
|
||||
|
||||
EdgeTraits
|
||||
{
|
||||
private:
|
||||
typedef typename Refs::Point Point;
|
||||
typedef typename Refs::Scalar Scalar;
|
||||
Point midpoint_;
|
||||
Scalar length_;
|
||||
Point position_;
|
||||
public:
|
||||
const Point& midpoint() const { return midpoint_; }
|
||||
void set_midpoint(const Point& _vh) { midpoint_ = _vh; }
|
||||
const Scalar& length() const { return length_; }
|
||||
void set_length(const Scalar& _s) { length_ = _s; }
|
||||
const Point& position() const { return position_; }
|
||||
void set_position(const Point& _p) { position_ = _p; }
|
||||
};
|
||||
|
||||
VertexTraits
|
||||
{
|
||||
private:
|
||||
typedef typename Refs::Point Point;
|
||||
Point new_pos_;
|
||||
Point orig_pos_;
|
||||
Point position_;
|
||||
unsigned int generation_;
|
||||
public:
|
||||
const Point& new_pos() const { return new_pos_; }
|
||||
void set_new_pos(const Point& _p) { new_pos_ = _p; }
|
||||
const unsigned int& generation() const { return generation_; }
|
||||
void set_generation(const unsigned int& _i) { generation_ = _i; }
|
||||
const Point& orig_pos() const { return orig_pos_; }
|
||||
void set_orig_pos(const Point& _p) { orig_pos_ = _p; }
|
||||
const Point& position() const { return position_; }
|
||||
void set_position(const Point& _p) { position_ = _p; }
|
||||
};
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
} // END_NS_UNIFORM
|
||||
} // END_NS_SUBDIVIDER
|
||||
} // END_NS_OPENMESH
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_SUBDIVIDER_UNIFORM_COMPOSITETRAITS_HH defined
|
||||
//=============================================================================
|
||||
|
||||
139
Tools/Subdivider/Uniform/CompositeLoopT.hh
Normal file
139
Tools/Subdivider/Uniform/CompositeLoopT.hh
Normal file
@@ -0,0 +1,139 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// OpenMesh
|
||||
// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen
|
||||
// www.openmesh.org
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// License
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation, version 2.1.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Revision: 1802 $
|
||||
// $Date: 2008-05-19 11:55:07 +0200 (Mo, 19. Mai 2008) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
/** \file CompositeLoopT.hh
|
||||
|
||||
*/
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// CLASS LoopT
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef OPENMESH_SUBDIVIDER_UNIFORM_COMPOSITELOOPT_HH
|
||||
#define OPENMESH_SUBDIVIDER_UNIFORM_COMPOSITELOOPT_HH
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
#include "Composite/CompositeT.hh"
|
||||
#include "Composite/CompositeTraits.hh"
|
||||
|
||||
|
||||
//== NAMESPACE ================================================================
|
||||
|
||||
namespace OpenMesh { // BEGIN_NS_OPENMESH
|
||||
namespace Subdivider { // BEGIN_NS_DECIMATER
|
||||
namespace Uniform { // BEGIN_NS_DECIMATER
|
||||
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
/** Uniform composite Loop subdivision algorithm
|
||||
*/
|
||||
template <class MeshType, class RealType=float>
|
||||
class CompositeLoopT : public CompositeT<MeshType, RealType>
|
||||
{
|
||||
public:
|
||||
|
||||
typedef CompositeT<MeshType, RealType> Inherited;
|
||||
|
||||
public:
|
||||
|
||||
CompositeLoopT() : Inherited() {};
|
||||
CompositeLoopT(MeshType& _mesh) : Inherited(_mesh) {};
|
||||
~CompositeLoopT() {}
|
||||
|
||||
public:
|
||||
|
||||
const char *name() const { return "Uniform Composite Loop"; }
|
||||
|
||||
protected: // inherited interface
|
||||
|
||||
void apply_rules(void)
|
||||
{
|
||||
Inherited::Tvv4();
|
||||
Inherited::VdE();
|
||||
Inherited::EVc(coeffs_);
|
||||
Inherited::VdE();
|
||||
Inherited::EVc(coeffs_);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
typedef typename Inherited::Coeff Coeff;
|
||||
|
||||
|
||||
/** Helper struct
|
||||
* \internal
|
||||
*/
|
||||
struct EVCoeff : public Coeff
|
||||
{
|
||||
EVCoeff() : Coeff() { init(50); }
|
||||
|
||||
void init(size_t _max_valence)
|
||||
{
|
||||
weights_.resize(_max_valence);
|
||||
std::generate(weights_.begin(),
|
||||
weights_.end(), compute_weight() );
|
||||
}
|
||||
|
||||
double operator()(size_t _valence) { return weights_[_valence]; }
|
||||
|
||||
/// \internal
|
||||
struct compute_weight
|
||||
{
|
||||
compute_weight() : val_(0) { }
|
||||
|
||||
double operator()(void) // Loop weights for non-boundary vertices
|
||||
{
|
||||
// 1 3 2 * pi
|
||||
// - * ( --- + cos ( ------- ) )<29> - 1.0
|
||||
// 2 2 valence
|
||||
double f1 = 1.5 + cos(2.0*M_PI/val_++);
|
||||
return 0.5 * f1 * f1 - 1.0;
|
||||
}
|
||||
size_t val_;
|
||||
|
||||
};
|
||||
|
||||
std::vector<double> weights_;
|
||||
} coeffs_;
|
||||
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
} // END_NS_UNIFORM
|
||||
} // END_NS_SUBDIVIDER
|
||||
} // END_NS_OPENMESH
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_SUBDIVIDER_UNIFORM_COMPOSITELOOPT_HH defined
|
||||
//=============================================================================
|
||||
135
Tools/Subdivider/Uniform/CompositeSqrt3T.hh
Normal file
135
Tools/Subdivider/Uniform/CompositeSqrt3T.hh
Normal file
@@ -0,0 +1,135 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// OpenMesh
|
||||
// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen
|
||||
// www.openmesh.org
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// License
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation, version 2.1.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Revision: 1802 $
|
||||
// $Date: 2008-05-19 11:55:07 +0200 (Mo, 19. Mai 2008) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
/** \file CompositeSqrt3T.hh
|
||||
|
||||
*/
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// CLASS SQRT3T
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef OPENMESH_SUBDIVIDER_UNIFORM_COMPOSITESQRT3T_HH
|
||||
#define OPENMESH_SUBDIVIDER_UNIFORM_COMPOSITESQRT3T_HH
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
#include "Composite/CompositeT.hh"
|
||||
#include "Composite/CompositeTraits.hh"
|
||||
|
||||
|
||||
//== NAMESPACE ================================================================
|
||||
|
||||
namespace OpenMesh { // BEGIN_NS_OPENMESH
|
||||
namespace Subdivider { // BEGIN_NS_DECIMATER
|
||||
namespace Uniform { // BEGIN_NS_UNIFORM
|
||||
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
/** Uniform composite sqrt(3) subdivision algorithm
|
||||
*/
|
||||
template <typename MeshType, typename RealType=float>
|
||||
class CompositeSqrt3T : public CompositeT<MeshType, RealType>
|
||||
{
|
||||
public:
|
||||
|
||||
typedef CompositeT<MeshType, RealType> Inherited;
|
||||
|
||||
public:
|
||||
|
||||
CompositeSqrt3T() : Inherited() {};
|
||||
CompositeSqrt3T(MeshType& _mesh) : Inherited(_mesh) {};
|
||||
~CompositeSqrt3T() {}
|
||||
|
||||
public:
|
||||
|
||||
const char *name() const { return "Uniform Composite Sqrt3"; }
|
||||
|
||||
protected: // inherited interface
|
||||
|
||||
void apply_rules(void)
|
||||
{
|
||||
Inherited::Tvv3();
|
||||
Inherited::VF();
|
||||
Inherited::FF();
|
||||
Inherited::FVc(coeffs_);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
typedef typename Inherited::Coeff Coeff;
|
||||
|
||||
/** Helper class
|
||||
* \internal
|
||||
*/
|
||||
struct FVCoeff : public Coeff
|
||||
{
|
||||
FVCoeff() : Coeff() { init(50); }
|
||||
|
||||
void init(size_t _max_valence)
|
||||
{
|
||||
weights_.resize(_max_valence);
|
||||
std::generate(weights_.begin(),
|
||||
weights_.end(), compute_weight() );
|
||||
}
|
||||
|
||||
double operator()(size_t _valence) { return weights_[_valence]; }
|
||||
|
||||
/** \internal
|
||||
*/
|
||||
struct compute_weight
|
||||
{
|
||||
compute_weight() : val_(0) { }
|
||||
|
||||
double operator()(void) // sqrt(3) weights for non-boundary vertices
|
||||
{
|
||||
return 2.0/3.0 * (cos(2.0*M_PI/val_++)+1.0);
|
||||
}
|
||||
size_t val_;
|
||||
};
|
||||
|
||||
std::vector<double> weights_;
|
||||
|
||||
} coeffs_;
|
||||
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
} // END_NS_UNIFORM
|
||||
} // END_NS_SUBDIVIDER
|
||||
} // END_NS_OPENMESH
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_SUBDIVIDER_UNIFORM_COMPOSITESQRT3T_HH defined
|
||||
//=============================================================================
|
||||
451
Tools/Subdivider/Uniform/LoopT.hh
Normal file
451
Tools/Subdivider/Uniform/LoopT.hh
Normal file
@@ -0,0 +1,451 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// OpenMesh
|
||||
// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen
|
||||
// www.openmesh.org
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// License
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation, version 2.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Revision: 1802 $
|
||||
// $Date: 2008-05-19 11:55:07 +0200 (Mo, 19. Mai 2008) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
/** \file LoopT.hh
|
||||
|
||||
*/
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// CLASS LoopT
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef OPENMESH_SUBDIVIDER_UNIFORM_LOOPT_HH
|
||||
#define OPENMESH_SUBDIVIDER_UNIFORM_LOOPT_HH
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
#include <OpenMesh/Core/System/config.hh>
|
||||
#include <OpenMesh/Tools/Subdivider/Uniform/SubdividerT.hh>
|
||||
#include <OpenMesh/Core/Utils/vector_cast.hh>
|
||||
// -------------------- STL
|
||||
#include <vector>
|
||||
#if defined(OM_CC_MIPS)
|
||||
# include <math.h>
|
||||
#else
|
||||
# include <cmath>
|
||||
#endif
|
||||
|
||||
|
||||
//== NAMESPACE ================================================================
|
||||
|
||||
namespace OpenMesh { // BEGIN_NS_OPENMESH
|
||||
namespace Subdivider { // BEGIN_NS_DECIMATER
|
||||
namespace Uniform { // BEGIN_NS_DECIMATER
|
||||
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
/** %Uniform Loop subdivision algorithm.
|
||||
*
|
||||
* Implementation as described in
|
||||
*
|
||||
* C. T. Loop, "Smooth Subdivision Surfaces Based on Triangles",
|
||||
* M.S. Thesis, Department of Mathematics, University of Utah, August 1987.
|
||||
*
|
||||
*/
|
||||
template <typename MeshType, typename RealType = float>
|
||||
class LoopT : public SubdividerT<MeshType, RealType>
|
||||
{
|
||||
public:
|
||||
|
||||
typedef RealType real_t;
|
||||
typedef MeshType mesh_t;
|
||||
typedef SubdividerT< mesh_t, real_t > parent_t;
|
||||
|
||||
typedef std::pair< real_t, real_t > weight_t;
|
||||
typedef std::vector< std::pair<real_t,real_t> > weights_t;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
LoopT(void) : parent_t(), _1over8( 1.0/8.0 ), _3over8( 3.0/8.0 )
|
||||
{ init_weights(); }
|
||||
|
||||
|
||||
LoopT( mesh_t& _m ) : parent_t(_m), _1over8( 1.0/8.0 ), _3over8( 3.0/8.0 )
|
||||
{ init_weights(); }
|
||||
|
||||
|
||||
~LoopT() {}
|
||||
|
||||
|
||||
public:
|
||||
|
||||
|
||||
const char *name() const { return "Uniform Loop"; }
|
||||
|
||||
|
||||
/// Pre-compute weights
|
||||
void init_weights(size_t _max_valence=50)
|
||||
{
|
||||
weights_.resize(_max_valence);
|
||||
std::generate(weights_.begin(), weights_.end(), compute_weight());
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
bool prepare( mesh_t& _m )
|
||||
{
|
||||
_m.add_property( vp_pos_ );
|
||||
_m.add_property( ep_pos_ );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool cleanup( mesh_t& _m )
|
||||
{
|
||||
_m.remove_property( vp_pos_ );
|
||||
_m.remove_property( ep_pos_ );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool subdivide( mesh_t& _m, size_t _n)
|
||||
{
|
||||
typename mesh_t::FaceIter fit, f_end;
|
||||
typename mesh_t::EdgeIter eit, e_end;
|
||||
typename mesh_t::VertexIter vit;
|
||||
|
||||
// Do _n subdivisions
|
||||
for (size_t i=0; i < _n; ++i)
|
||||
{
|
||||
// compute new positions for old vertices
|
||||
for ( vit = _m.vertices_begin();
|
||||
vit != _m.vertices_end(); ++vit)
|
||||
smooth( _m, vit.handle() );
|
||||
|
||||
|
||||
// Compute position for new vertices and store them in the edge property
|
||||
for (eit=_m.edges_begin(); eit != _m.edges_end(); ++eit)
|
||||
compute_midpoint( _m, eit.handle() );
|
||||
|
||||
|
||||
// Split each edge at midpoint and store precomputed positions (stored in
|
||||
// edge property ep_pos_) in the vertex property vp_pos_;
|
||||
|
||||
// Attention! Creating new edges, hence make sure the loop ends correctly.
|
||||
e_end = _m.edges_end();
|
||||
for (eit=_m.edges_begin(); eit != e_end; ++eit)
|
||||
split_edge(_m, eit.handle() );
|
||||
|
||||
|
||||
// Commit changes in topology and reconsitute consistency
|
||||
|
||||
// Attention! Creating new faces, hence make sure the loop ends correctly.
|
||||
f_end = _m.faces_end();
|
||||
for (fit = _m.faces_begin(); fit != f_end; ++fit)
|
||||
split_face(_m, fit.handle() );
|
||||
|
||||
|
||||
// Commit changes in geometry
|
||||
for ( vit = _m.vertices_begin();
|
||||
vit != _m.vertices_end(); ++vit)
|
||||
_m.set_point(vit, _m.property( vp_pos_, vit ) );
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUG)
|
||||
// Now we have an consistent mesh!
|
||||
assert( OpenMesh::Utils::MeshCheckerT<mesh_t>(_m).check() );
|
||||
#endif
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
/// Helper functor to compute weights for Loop-subdivision
|
||||
/// \internal
|
||||
struct compute_weight
|
||||
{
|
||||
compute_weight() : valence(-1) { }
|
||||
weight_t operator() (void)
|
||||
{
|
||||
#if !defined(OM_CC_MIPS)
|
||||
using std::cos;
|
||||
#endif
|
||||
// 1
|
||||
// alpha(n) = ---- * (40 - ( 3 + 2 cos( 2 Pi / n ) )<29> )
|
||||
// 64
|
||||
|
||||
if (++valence)
|
||||
{
|
||||
double inv_v = 1.0/double(valence);
|
||||
double t = (3.0 + 2.0 * cos( 2.0 * M_PI * inv_v) );
|
||||
double alpha = (40.0 - t * t)/64.0;
|
||||
|
||||
return weight_t( 1.0-alpha, inv_v*alpha);
|
||||
}
|
||||
return weight_t(0.0, 0.0);
|
||||
}
|
||||
int valence;
|
||||
};
|
||||
|
||||
private: // topological modifiers
|
||||
|
||||
void split_face(mesh_t& _m, const typename mesh_t::FaceHandle& _fh)
|
||||
{
|
||||
typename mesh_t::HalfedgeHandle
|
||||
heh1(_m.halfedge_handle(_fh)),
|
||||
heh2(_m.next_halfedge_handle(_m.next_halfedge_handle(heh1))),
|
||||
heh3(_m.next_halfedge_handle(_m.next_halfedge_handle(heh2)));
|
||||
|
||||
// Cutting off every corner of the 6_gon
|
||||
corner_cutting( _m, heh1 );
|
||||
corner_cutting( _m, heh2 );
|
||||
corner_cutting( _m, heh3 );
|
||||
}
|
||||
|
||||
|
||||
void corner_cutting(mesh_t& _m, const typename mesh_t::HalfedgeHandle& _he)
|
||||
{
|
||||
// Define Halfedge Handles
|
||||
typename mesh_t::HalfedgeHandle
|
||||
heh1(_he),
|
||||
heh5(heh1),
|
||||
heh6(_m.next_halfedge_handle(heh1));
|
||||
|
||||
// Cycle around the polygon to find correct Halfedge
|
||||
for (; _m.next_halfedge_handle(_m.next_halfedge_handle(heh5)) != heh1;
|
||||
heh5 = _m.next_halfedge_handle(heh5))
|
||||
{}
|
||||
|
||||
typename mesh_t::VertexHandle
|
||||
vh1 = _m.to_vertex_handle(heh1),
|
||||
vh2 = _m.to_vertex_handle(heh5);
|
||||
|
||||
typename mesh_t::HalfedgeHandle
|
||||
heh2(_m.next_halfedge_handle(heh5)),
|
||||
heh3(_m.new_edge( vh1, vh2)),
|
||||
heh4(_m.opposite_halfedge_handle(heh3));
|
||||
|
||||
/* Intermediate result
|
||||
*
|
||||
* *
|
||||
* 5 /|\
|
||||
* /_ \
|
||||
* vh2> * *
|
||||
* /|\3 |\
|
||||
* /_ \|4 \
|
||||
* *----\*----\*
|
||||
* 1 ^ 6
|
||||
* vh1 (adjust_outgoing halfedge!)
|
||||
*/
|
||||
|
||||
// Old and new Face
|
||||
typename mesh_t::FaceHandle fh_old(_m.face_handle(heh6));
|
||||
typename mesh_t::FaceHandle fh_new(_m.new_face());
|
||||
|
||||
|
||||
// Re-Set Handles around old Face
|
||||
_m.set_next_halfedge_handle(heh4, heh6);
|
||||
_m.set_next_halfedge_handle(heh5, heh4);
|
||||
|
||||
_m.set_face_handle(heh4, fh_old);
|
||||
_m.set_face_handle(heh5, fh_old);
|
||||
_m.set_face_handle(heh6, fh_old);
|
||||
_m.set_halfedge_handle(fh_old, heh4);
|
||||
|
||||
// Re-Set Handles around new Face
|
||||
_m.set_next_halfedge_handle(heh1, heh3);
|
||||
_m.set_next_halfedge_handle(heh3, heh2);
|
||||
|
||||
_m.set_face_handle(heh1, fh_new);
|
||||
_m.set_face_handle(heh2, fh_new);
|
||||
_m.set_face_handle(heh3, fh_new);
|
||||
|
||||
_m.set_halfedge_handle(fh_new, heh1);
|
||||
}
|
||||
|
||||
|
||||
void split_edge(mesh_t& _m, const typename mesh_t::EdgeHandle& _eh)
|
||||
{
|
||||
typename mesh_t::HalfedgeHandle
|
||||
heh = _m.halfedge_handle(_eh, 0),
|
||||
opp_heh = _m.halfedge_handle(_eh, 1);
|
||||
|
||||
typename mesh_t::HalfedgeHandle new_heh, opp_new_heh, t_heh;
|
||||
typename mesh_t::VertexHandle vh;
|
||||
typename mesh_t::VertexHandle vh1(_m.to_vertex_handle(heh));
|
||||
typename mesh_t::Point zero(0,0,0);
|
||||
|
||||
// new vertex
|
||||
vh = _m.new_vertex( zero );
|
||||
|
||||
// memorize position, will be set later
|
||||
_m.property( vp_pos_, vh ) = _m.property( ep_pos_, _eh );
|
||||
|
||||
|
||||
// Re-link mesh entities
|
||||
if (_m.is_boundary(_eh))
|
||||
{
|
||||
for (t_heh = heh;
|
||||
_m.next_halfedge_handle(t_heh) != opp_heh;
|
||||
t_heh = _m.opposite_halfedge_handle(_m.next_halfedge_handle(t_heh)))
|
||||
{}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (t_heh = _m.next_halfedge_handle(opp_heh);
|
||||
_m.next_halfedge_handle(t_heh) != opp_heh;
|
||||
t_heh = _m.next_halfedge_handle(t_heh) )
|
||||
{}
|
||||
}
|
||||
|
||||
new_heh = _m.new_edge(vh, vh1);
|
||||
opp_new_heh = _m.opposite_halfedge_handle(new_heh);
|
||||
_m.set_vertex_handle( heh, vh );
|
||||
|
||||
_m.set_next_halfedge_handle(t_heh, opp_new_heh);
|
||||
_m.set_next_halfedge_handle(new_heh, _m.next_halfedge_handle(heh));
|
||||
_m.set_next_halfedge_handle(heh, new_heh);
|
||||
_m.set_next_halfedge_handle(opp_new_heh, opp_heh);
|
||||
|
||||
if (_m.face_handle(opp_heh).is_valid())
|
||||
{
|
||||
_m.set_face_handle(opp_new_heh, _m.face_handle(opp_heh));
|
||||
_m.set_halfedge_handle(_m.face_handle(opp_new_heh), opp_new_heh);
|
||||
}
|
||||
|
||||
_m.set_face_handle( new_heh, _m.face_handle(heh) );
|
||||
_m.set_halfedge_handle( vh, new_heh);
|
||||
_m.set_halfedge_handle( _m.face_handle(heh), heh );
|
||||
_m.set_halfedge_handle( vh1, opp_new_heh );
|
||||
|
||||
// Never forget this, when playing with the topology
|
||||
_m.adjust_outgoing_halfedge( vh );
|
||||
_m.adjust_outgoing_halfedge( vh1 );
|
||||
}
|
||||
|
||||
private: // geometry helper
|
||||
|
||||
void compute_midpoint(mesh_t& _m, const typename mesh_t::EdgeHandle& _eh)
|
||||
{
|
||||
#define V( X ) vector_cast< typename mesh_t::Normal >( X )
|
||||
typename mesh_t::HalfedgeHandle heh, opp_heh;
|
||||
|
||||
heh = _m.halfedge_handle( _eh, 0);
|
||||
opp_heh = _m.halfedge_handle( _eh, 1);
|
||||
|
||||
typename mesh_t::Point
|
||||
pos(_m.point(_m.to_vertex_handle(heh)));
|
||||
|
||||
pos += V( _m.point(_m.to_vertex_handle(opp_heh)) );
|
||||
|
||||
// boundary edge: just average vertex positions
|
||||
if (_m.is_boundary(_eh) )
|
||||
{
|
||||
pos *= 0.5;
|
||||
}
|
||||
else // inner edge: add neighbouring Vertices to sum
|
||||
{
|
||||
pos *= real_t(3.0);
|
||||
pos += V(_m.point(_m.to_vertex_handle(_m.next_halfedge_handle(heh))));
|
||||
pos += V(_m.point(_m.to_vertex_handle(_m.next_halfedge_handle(opp_heh))));
|
||||
pos *= _1over8;
|
||||
}
|
||||
_m.property( ep_pos_, _eh ) = pos;
|
||||
#undef V
|
||||
}
|
||||
|
||||
|
||||
void smooth(mesh_t& _m, const typename mesh_t::VertexHandle& _vh)
|
||||
{
|
||||
typename mesh_t::Point pos(0.0,0.0,0.0);
|
||||
|
||||
if (_m.is_boundary(_vh)) // if boundary: Point 1-6-1
|
||||
{
|
||||
typename mesh_t::HalfedgeHandle heh, prev_heh;
|
||||
heh = _m.halfedge_handle( _vh );
|
||||
|
||||
if ( heh.is_valid() )
|
||||
{
|
||||
assert( _m.is_boundary( _m.edge_handle( heh ) ) );
|
||||
|
||||
prev_heh = _m.prev_halfedge_handle( heh );
|
||||
|
||||
typename mesh_t::VertexHandle
|
||||
to_vh = _m.to_vertex_handle( heh ),
|
||||
from_vh = _m.from_vertex_handle( prev_heh );
|
||||
|
||||
// ( v_l + 6 v + v_r ) / 8
|
||||
pos = _m.point( _vh );
|
||||
pos *= real_t(6.0);
|
||||
pos += vector_cast< typename mesh_t::Normal >( _m.point( to_vh ) );
|
||||
pos += vector_cast< typename mesh_t::Normal >( _m.point( from_vh ) );
|
||||
pos *= _1over8;
|
||||
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
else // inner vertex: (1-a) * p + a/n * Sum q, q in one-ring of p
|
||||
{
|
||||
typedef typename mesh_t::Normal Vec;
|
||||
typename mesh_t::VertexVertexIter vvit;
|
||||
size_t valence(0);
|
||||
|
||||
// Calculate Valence and sum up neighbour points
|
||||
for (vvit=_m.vv_iter(_vh); vvit; ++vvit) {
|
||||
++valence;
|
||||
pos += vector_cast< Vec >( _m.point(vvit) );
|
||||
}
|
||||
pos *= weights_[valence].second; // alpha(n)/n * Sum q, q in one-ring of p
|
||||
pos += weights_[valence].first
|
||||
* vector_cast<Vec>(_m.point(_vh)); // + (1-a)*p
|
||||
}
|
||||
|
||||
_m.property( vp_pos_, _vh ) = pos;
|
||||
}
|
||||
|
||||
private: // data
|
||||
|
||||
OpenMesh::VPropHandleT< typename mesh_t::Point > vp_pos_;
|
||||
OpenMesh::EPropHandleT< typename mesh_t::Point > ep_pos_;
|
||||
|
||||
weights_t weights_;
|
||||
|
||||
const real_t _1over8;
|
||||
const real_t _3over8;
|
||||
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
} // END_NS_UNIFORM
|
||||
} // END_NS_SUBDIVIDER
|
||||
} // END_NS_OPENMESH
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_SUBDIVIDER_UNIFORM_COMPOSITELOOPT_HH defined
|
||||
//=============================================================================
|
||||
507
Tools/Subdivider/Uniform/Sqrt3T.hh
Normal file
507
Tools/Subdivider/Uniform/Sqrt3T.hh
Normal file
@@ -0,0 +1,507 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// OpenMesh
|
||||
// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen
|
||||
// www.openmesh.org
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// License
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation, version 2.1.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Revision: 4083 $
|
||||
// $Date: 2008-12-29 15:29:38 +0100 (Mo, 29. Dez 2008) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
/** \file Sqrt3T.hh
|
||||
|
||||
*/
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// CLASS Sqrt3T
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef OPENMESH_SUBDIVIDER_UNIFORM_SQRT3T_HH
|
||||
#define OPENMESH_SUBDIVIDER_UNIFORM_SQRT3T_HH
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
#include <OpenMesh/Core/Mesh/Handles.hh>
|
||||
#include <OpenMesh/Core/System/config.hh>
|
||||
#include <OpenMesh/Tools/Subdivider/Uniform/SubdividerT.hh>
|
||||
#if defined(_DEBUG) || defined(DEBUG)
|
||||
// Makes life lot easier, when playing/messing around with low-level topology
|
||||
// changing methods of OpenMesh
|
||||
# include <OpenMesh/Tools/Utils/MeshCheckerT.hh>
|
||||
# define ASSERT_CONSISTENCY( T, m ) \
|
||||
assert(OpenMesh::Utils::MeshCheckerT<T>(m).check())
|
||||
#else
|
||||
# define ASSERT_CONSISTENCY( T, m )
|
||||
#endif
|
||||
// -------------------- STL
|
||||
#include <vector>
|
||||
#if defined(OM_CC_MIPS)
|
||||
# include <math.h>
|
||||
#else
|
||||
# include <cmath>
|
||||
#endif
|
||||
|
||||
|
||||
//== NAMESPACE ================================================================
|
||||
|
||||
namespace OpenMesh { // BEGIN_NS_OPENMESH
|
||||
namespace Subdivider { // BEGIN_NS_DECIMATER
|
||||
namespace Uniform { // BEGIN_NS_DECIMATER
|
||||
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
|
||||
/** %Uniform Sqrt3 subdivision algorithm
|
||||
*
|
||||
* Implementation as described in
|
||||
*
|
||||
* L. Kobbelt, <a href="http://www-i8.informatik.rwth-aachen.de/publications/downloads/sqrt3.pdf">"Sqrt(3) subdivision"</a>, Proceedings of SIGGRAPH 2000.
|
||||
*/
|
||||
template <typename MeshType, typename RealType = float>
|
||||
class Sqrt3T : public SubdividerT< MeshType, RealType >
|
||||
{
|
||||
public:
|
||||
|
||||
typedef RealType real_t;
|
||||
typedef MeshType mesh_t;
|
||||
typedef SubdividerT< mesh_t, real_t > parent_t;
|
||||
|
||||
typedef std::pair< real_t, real_t > weight_t;
|
||||
typedef std::vector< std::pair<real_t,real_t> > weights_t;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
Sqrt3T(void) : parent_t(), _1over3( 1.0/3.0 ), _1over27( 1.0/27.0 )
|
||||
{ init_weights(); }
|
||||
|
||||
Sqrt3T(MeshType &_m) : parent_t(_m), _1over3( 1.0/3.0 ), _1over27( 1.0/27.0 )
|
||||
{ init_weights(); }
|
||||
|
||||
virtual ~Sqrt3T() {}
|
||||
|
||||
|
||||
public:
|
||||
|
||||
|
||||
const char *name() const { return "Uniform Sqrt3"; }
|
||||
|
||||
|
||||
/// Pre-compute weights
|
||||
void init_weights(size_t _max_valence=50)
|
||||
{
|
||||
weights_.resize(_max_valence);
|
||||
std::generate(weights_.begin(), weights_.end(), compute_weight());
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
bool prepare( MeshType& _m )
|
||||
{
|
||||
_m.request_edge_status();
|
||||
_m.add_property( vp_pos_ );
|
||||
_m.add_property( ep_nv_ );
|
||||
_m.add_property( mp_gen_ );
|
||||
_m.property( mp_gen_ ) = 0;
|
||||
|
||||
return _m.has_edge_status() && vp_pos_.is_valid()
|
||||
&& ep_nv_.is_valid() && mp_gen_.is_valid();
|
||||
}
|
||||
|
||||
|
||||
bool cleanup( MeshType& _m )
|
||||
{
|
||||
_m.release_edge_status();
|
||||
_m.remove_property( vp_pos_ );
|
||||
_m.remove_property( ep_nv_ );
|
||||
_m.remove_property( mp_gen_ );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool subdivide( MeshType& _m, size_t _n )
|
||||
{
|
||||
typename MeshType::VertexIter vit;
|
||||
typename MeshType::VertexVertexIter vvit;
|
||||
typename MeshType::EdgeIter eit;
|
||||
typename MeshType::FaceIter fit;
|
||||
typename MeshType::FaceVertexIter fvit;
|
||||
typename MeshType::VertexHandle vh;
|
||||
typename MeshType::HalfedgeHandle heh;
|
||||
typename MeshType::Point pos(0,0,0), zero(0,0,0);
|
||||
size_t &gen = _m.property( mp_gen_ );
|
||||
|
||||
for (size_t l=0; l<_n; ++l)
|
||||
{
|
||||
// tag existing edges
|
||||
for (eit=_m.edges_begin(); eit != _m.edges_end();++eit)
|
||||
{
|
||||
_m.status( eit ).set_tagged( true );
|
||||
if ( (gen%2) && _m.is_boundary(eit) )
|
||||
compute_new_boundary_points( _m, eit ); // *) creates new vertices
|
||||
}
|
||||
|
||||
// do relaxation of old vertices, but store new pos in property vp_pos_
|
||||
|
||||
for (vit=_m.vertices_begin(); vit!=_m.vertices_end(); ++vit)
|
||||
{
|
||||
if ( _m.is_boundary(vit) )
|
||||
{
|
||||
if ( gen%2 )
|
||||
{
|
||||
heh = _m.halfedge_handle(vit);
|
||||
if (heh.is_valid()) // skip isolated newly inserted vertices *)
|
||||
{
|
||||
typename OpenMesh::HalfedgeHandle
|
||||
prev_heh = _m.prev_halfedge_handle(heh);
|
||||
|
||||
assert( _m.is_boundary(heh ) );
|
||||
assert( _m.is_boundary(prev_heh) );
|
||||
|
||||
pos = _m.point(_m.to_vertex_handle(heh));
|
||||
pos += _m.point(_m.from_vertex_handle(prev_heh));
|
||||
pos *= real_t(4.0);
|
||||
|
||||
pos += real_t(19.0) * _m.point( vit );
|
||||
pos *= _1over27;
|
||||
|
||||
_m.property( vp_pos_, vit ) = pos;
|
||||
}
|
||||
}
|
||||
else
|
||||
_m.property( vp_pos_, vit ) = _m.point( vit );
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t valence=0;
|
||||
|
||||
pos = zero;
|
||||
for ( vvit = _m.vv_iter(vit); vvit; ++vvit)
|
||||
{
|
||||
pos += _m.point( vvit );
|
||||
++valence;
|
||||
}
|
||||
pos *= weights_[ valence ].second;
|
||||
pos += weights_[ valence ].first * _m.point(vit);
|
||||
_m.property( vp_pos_, vit ) = pos;
|
||||
}
|
||||
}
|
||||
|
||||
// insert new vertices, but store pos in vp_pos_
|
||||
typename MeshType::FaceIter fend = _m.faces_end();
|
||||
for (fit = _m.faces_begin();fit != fend; ++fit)
|
||||
{
|
||||
if ( (gen%2) && _m.is_boundary(fit))
|
||||
{
|
||||
boundary_split( _m, fit );
|
||||
}
|
||||
else
|
||||
{
|
||||
fvit = _m.fv_iter( fit );
|
||||
pos = _m.point( fvit);
|
||||
pos += _m.point(++fvit);
|
||||
pos += _m.point(++fvit);
|
||||
pos *= _1over3;
|
||||
vh = _m.add_vertex( zero );
|
||||
_m.property( vp_pos_, vh ) = pos;
|
||||
_m.split( fit, vh );
|
||||
}
|
||||
}
|
||||
|
||||
// commit new positions (now iterating over all vertices)
|
||||
for (vit=_m.vertices_begin();vit != _m.vertices_end(); ++vit)
|
||||
_m.set_point(vit, _m.property( vp_pos_, vit ) );
|
||||
|
||||
// flip old edges
|
||||
for (eit=_m.edges_begin(); eit != _m.edges_end(); ++eit)
|
||||
if ( _m.status( eit ).tagged() && !_m.is_boundary( eit ) )
|
||||
_m.flip(eit);
|
||||
|
||||
// Now we have an consistent mesh!
|
||||
ASSERT_CONSISTENCY( MeshType, _m );
|
||||
|
||||
// increase generation by one
|
||||
++gen;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
/// Helper functor to compute weights for sqrt(3)-subdivision
|
||||
/// \internal
|
||||
struct compute_weight
|
||||
{
|
||||
compute_weight() : valence(-1) { }
|
||||
weight_t operator() (void)
|
||||
{
|
||||
#if !defined(OM_CC_MIPS)
|
||||
using std::cos;
|
||||
#endif
|
||||
if (++valence)
|
||||
{
|
||||
real_t alpha = (4.0-2.0*cos(2.0*M_PI / (double)valence))/9.0;
|
||||
return weight_t( real_t(1)-alpha, alpha/real_t(valence) );
|
||||
}
|
||||
return weight_t(0.0, 0.0);
|
||||
}
|
||||
int valence;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
// Pre-compute location of new boundary points for odd generations
|
||||
// and store them in the edge property ep_nv_;
|
||||
void compute_new_boundary_points( MeshType& _m,
|
||||
const typename MeshType::EdgeHandle& _eh)
|
||||
{
|
||||
assert( _m.is_boundary(_eh) );
|
||||
|
||||
typename MeshType::HalfedgeHandle heh;
|
||||
typename MeshType::VertexHandle vh1, vh2, vh3, vh4, vhl, vhr;
|
||||
typename MeshType::Point zero(0,0,0), P1, P2, P3, P4;
|
||||
|
||||
/*
|
||||
// *---------*---------*
|
||||
// / \ / \ / \
|
||||
// / \ / \ / \
|
||||
// / \ / \ / \
|
||||
// / \ / \ / \
|
||||
// *---------*--#---#--*---------*
|
||||
//
|
||||
// ^ ^ ^ ^ ^ ^
|
||||
// P1 P2 pl pr P3 P4
|
||||
*/
|
||||
// get halfedge pointing from P3 to P2 (outer boundary halfedge)
|
||||
|
||||
heh = _m.halfedge_handle(_eh,
|
||||
_m.is_boundary(_m.halfedge_handle(_eh,1)));
|
||||
|
||||
assert( _m.is_boundary( _m.next_halfedge_handle( heh ) ) );
|
||||
assert( _m.is_boundary( _m.prev_halfedge_handle( heh ) ) );
|
||||
|
||||
vh1 = _m.to_vertex_handle( _m.next_halfedge_handle( heh ) );
|
||||
vh2 = _m.to_vertex_handle( heh );
|
||||
vh3 = _m.from_vertex_handle( heh );
|
||||
vh4 = _m.from_vertex_handle( _m.prev_halfedge_handle( heh ));
|
||||
|
||||
P1 = _m.point(vh1);
|
||||
P2 = _m.point(vh2);
|
||||
P3 = _m.point(vh3);
|
||||
P4 = _m.point(vh4);
|
||||
|
||||
vhl = _m.add_vertex(zero);
|
||||
vhr = _m.add_vertex(zero);
|
||||
|
||||
_m.property(vp_pos_, vhl ) = (P1 + 16.0f*P2 + 10.0f*P3) * _1over27;
|
||||
_m.property(vp_pos_, vhr ) = (10.0f*P2 + 16.0f*P3 + P4) * _1over27;
|
||||
_m.property(ep_nv_, _eh).first = vhl;
|
||||
_m.property(ep_nv_, _eh).second = vhr;
|
||||
}
|
||||
|
||||
|
||||
void boundary_split( MeshType& _m, const typename MeshType::FaceHandle& _fh )
|
||||
{
|
||||
assert( _m.is_boundary(_fh) );
|
||||
|
||||
typename MeshType::VertexHandle vhl, vhr;
|
||||
typename MeshType::FaceEdgeIter fe_it;
|
||||
typename MeshType::HalfedgeHandle heh;
|
||||
|
||||
// find boundary edge
|
||||
for( fe_it=_m.fe_iter( _fh ); fe_it && !_m.is_boundary( fe_it ); ++fe_it );
|
||||
|
||||
// use precomputed, already inserted but not linked vertices
|
||||
vhl = _m.property(ep_nv_, fe_it).first;
|
||||
vhr = _m.property(ep_nv_, fe_it).second;
|
||||
|
||||
/*
|
||||
// *---------*---------*
|
||||
// / \ / \ / \
|
||||
// / \ / \ / \
|
||||
// / \ / \ / \
|
||||
// / \ / \ / \
|
||||
// *---------*--#---#--*---------*
|
||||
//
|
||||
// ^ ^ ^ ^ ^ ^
|
||||
// P1 P2 pl pr P3 P4
|
||||
*/
|
||||
// get halfedge pointing from P2 to P3 (inner boundary halfedge)
|
||||
|
||||
heh = _m.halfedge_handle(fe_it,
|
||||
_m.is_boundary(_m.halfedge_handle(fe_it,0)));
|
||||
|
||||
typename MeshType::HalfedgeHandle pl_P3;
|
||||
|
||||
// split P2->P3 (heh) in P2->pl (heh) and pl->P3
|
||||
boundary_split( _m, heh, vhl ); // split edge
|
||||
pl_P3 = _m.next_halfedge_handle( heh ); // store next halfedge handle
|
||||
boundary_split( _m, heh ); // split face
|
||||
|
||||
// split pl->P3 in pl->pr and pr->P3
|
||||
boundary_split( _m, pl_P3, vhr );
|
||||
boundary_split( _m, pl_P3 );
|
||||
|
||||
assert( _m.is_boundary( vhl ) && _m.halfedge_handle(vhl).is_valid() );
|
||||
assert( _m.is_boundary( vhr ) && _m.halfedge_handle(vhr).is_valid() );
|
||||
}
|
||||
|
||||
void boundary_split(MeshType& _m,
|
||||
const typename MeshType::HalfedgeHandle& _heh,
|
||||
const typename MeshType::VertexHandle& _vh)
|
||||
{
|
||||
assert( _m.is_boundary( _m.edge_handle(_heh) ) );
|
||||
|
||||
typename MeshType::HalfedgeHandle
|
||||
heh(_heh),
|
||||
opp_heh( _m.opposite_halfedge_handle(_heh) ),
|
||||
new_heh, opp_new_heh;
|
||||
typename MeshType::VertexHandle to_vh(_m.to_vertex_handle(heh));
|
||||
typename MeshType::HalfedgeHandle t_heh;
|
||||
|
||||
/*
|
||||
* P5
|
||||
* *
|
||||
* /|\
|
||||
* / \
|
||||
* / \
|
||||
* / \
|
||||
* / \
|
||||
* /_ heh new \
|
||||
* *-----\*-----\*\-----*
|
||||
* ^ ^ t_heh
|
||||
* _vh to_vh
|
||||
*
|
||||
* P1 P2 P3 P4
|
||||
*/
|
||||
// Re-Setting Handles
|
||||
|
||||
// find halfedge point from P4 to P3
|
||||
for(t_heh = heh;
|
||||
_m.next_halfedge_handle(t_heh) != opp_heh;
|
||||
t_heh = _m.opposite_halfedge_handle(_m.next_halfedge_handle(t_heh)))
|
||||
{}
|
||||
|
||||
assert( _m.is_boundary( t_heh ) );
|
||||
|
||||
new_heh = _m.new_edge( _vh, to_vh );
|
||||
opp_new_heh = _m.opposite_halfedge_handle(new_heh);
|
||||
|
||||
// update halfedge connectivity
|
||||
|
||||
_m.set_next_halfedge_handle(t_heh, opp_new_heh); // P4-P3 -> P3-P2
|
||||
// P2-P3 -> P3-P5
|
||||
_m.set_next_halfedge_handle(new_heh, _m.next_halfedge_handle(heh));
|
||||
_m.set_next_halfedge_handle(heh, new_heh); // P1-P2 -> P2-P3
|
||||
_m.set_next_halfedge_handle(opp_new_heh, opp_heh); // P3-P2 -> P2-P1
|
||||
|
||||
// both opposite halfedges point to same face
|
||||
_m.set_face_handle(opp_new_heh, _m.face_handle(opp_heh));
|
||||
|
||||
// let heh finally point to new inserted vertex
|
||||
_m.set_vertex_handle(heh, _vh);
|
||||
|
||||
// let heh and new_heh point to same face
|
||||
_m.set_face_handle(new_heh, _m.face_handle(heh));
|
||||
|
||||
// let opp_new_heh be the new outgoing halfedge for to_vh
|
||||
// (replaces for opp_heh)
|
||||
_m.set_halfedge_handle( to_vh, opp_new_heh );
|
||||
|
||||
// let opp_heh be the outgoing halfedge for _vh
|
||||
_m.set_halfedge_handle( _vh, opp_heh );
|
||||
}
|
||||
|
||||
void boundary_split( MeshType& _m,
|
||||
const typename MeshType::HalfedgeHandle& _heh)
|
||||
{
|
||||
assert( _m.is_boundary( _m.opposite_halfedge_handle( _heh ) ) );
|
||||
|
||||
typename MeshType::HalfedgeHandle
|
||||
heh(_heh),
|
||||
n_heh(_m.next_halfedge_handle(heh));
|
||||
|
||||
typename MeshType::VertexHandle
|
||||
to_vh(_m.to_vertex_handle(heh));
|
||||
|
||||
typename MeshType::HalfedgeHandle
|
||||
heh2(_m.new_edge(to_vh,
|
||||
_m.to_vertex_handle(_m.next_halfedge_handle(n_heh)))),
|
||||
heh3(_m.opposite_halfedge_handle(heh2));
|
||||
|
||||
typename MeshType::FaceHandle
|
||||
new_fh(_m.new_face()),
|
||||
fh(_m.face_handle(heh));
|
||||
|
||||
// Relink (half)edges
|
||||
|
||||
#define set_next_heh set_next_halfedge_handle
|
||||
#define next_heh next_halfedge_handle
|
||||
|
||||
_m.set_face_handle(heh, new_fh);
|
||||
_m.set_face_handle(heh2, new_fh);
|
||||
_m.set_next_heh(heh2, _m.next_heh(_m.next_heh(n_heh)));
|
||||
_m.set_next_heh(heh, heh2);
|
||||
_m.set_face_handle( _m.next_heh(heh2), new_fh);
|
||||
|
||||
// _m.set_face_handle( _m.next_heh(_m.next_heh(heh2)), new_fh);
|
||||
|
||||
_m.set_next_heh(heh3, n_heh);
|
||||
_m.set_next_heh(_m.next_halfedge_handle(n_heh), heh3);
|
||||
_m.set_face_handle(heh3, fh);
|
||||
// _m.set_face_handle(n_heh, fh);
|
||||
|
||||
_m.set_halfedge_handle( fh, n_heh);
|
||||
_m.set_halfedge_handle(new_fh, heh);
|
||||
|
||||
#undef set_next_halfedge_handle
|
||||
#undef next_halfedge_handle
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
weights_t weights_;
|
||||
OpenMesh::VPropHandleT< typename MeshType::Point > vp_pos_;
|
||||
OpenMesh::EPropHandleT< std::pair< typename MeshType::VertexHandle,
|
||||
typename MeshType::VertexHandle> > ep_nv_;
|
||||
OpenMesh::MPropHandleT< size_t > mp_gen_;
|
||||
|
||||
const real_t _1over3;
|
||||
const real_t _1over27;
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
} // END_NS_UNIFORM
|
||||
} // END_NS_SUBDIVIDER
|
||||
} // END_NS_OPENMESH
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_SUBDIVIDER_UNIFORM_SQRT3T_HH
|
||||
//=============================================================================
|
||||
179
Tools/Subdivider/Uniform/SubdividerT.hh
Normal file
179
Tools/Subdivider/Uniform/SubdividerT.hh
Normal file
@@ -0,0 +1,179 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// OpenMesh
|
||||
// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen
|
||||
// www.openmesh.org
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// License
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation, version 2.1.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Revision: 1802 $
|
||||
// $Date: 2008-05-19 11:55:07 +0200 (Mo, 19. Mai 2008) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
/** \file SubdividerT.hh
|
||||
|
||||
*/
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// CLASS SubdividerT
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef OPENMESH_SUBDIVIDER_UNIFORM_SUDIVIDERT_HH
|
||||
#define OPENMESH_SUBDIVIDER_UNIFORM_SUDIVIDERT_HH
|
||||
|
||||
//== INCLUDE ==================================================================
|
||||
|
||||
#include <OpenMesh/Core/System/config.hh>
|
||||
#include <OpenMesh/Core/Utils/Noncopyable.hh>
|
||||
#if defined(_DEBUG) || defined(DEBUG)
|
||||
// Makes life lot easier, when playing/messing around with low-level topology
|
||||
// changing methods of OpenMesh
|
||||
# include <OpenMesh/Tools/Utils/MeshCheckerT.hh>
|
||||
# define ASSERT_CONSISTENCY( T, m ) \
|
||||
assert(OpenMesh::Utils::MeshCheckerT<T>(m).check())
|
||||
#else
|
||||
# define ASSERT_CONSISTENCY( T, m )
|
||||
#endif
|
||||
|
||||
//== NAMESPACE ================================================================
|
||||
|
||||
namespace OpenMesh {
|
||||
namespace Subdivider {
|
||||
namespace Uniform {
|
||||
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
/** Abstract base class for uniform subdivision algorithms.
|
||||
*
|
||||
* A derived class must overload the following functions:
|
||||
* -# name()
|
||||
* -# prepare()
|
||||
* -# subdivide()
|
||||
* -# cleanup()
|
||||
*/
|
||||
template <typename MeshType, typename RealType=float>
|
||||
class SubdividerT : private Utils::Noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
typedef MeshType mesh_t;
|
||||
typedef RealType real_t;
|
||||
|
||||
public:
|
||||
|
||||
/// \name Constructors
|
||||
//@{
|
||||
/// Constructor to be used with interface 2
|
||||
/// \see attach(), operator()(size_t), detach()
|
||||
SubdividerT(void) : attached_(NULL) { }
|
||||
|
||||
/// Constructor to be used with interface 1 (calls attach())
|
||||
/// \see operator()( MeshType&, size_t )
|
||||
SubdividerT( MeshType &_m ) : attached_(NULL) { attach(_m); }
|
||||
|
||||
//@}
|
||||
|
||||
/// Descructor (calls detach())
|
||||
virtual ~SubdividerT()
|
||||
{ detach(); }
|
||||
|
||||
/// Return name of subdivision algorithm
|
||||
virtual const char *name( void ) const = 0;
|
||||
|
||||
|
||||
public: /// \name Interface 1
|
||||
|
||||
//@{
|
||||
/// Subdivide the mesh \c _m \c _n times.
|
||||
/// \see SubdividerT(MeshType&)
|
||||
bool operator () ( MeshType& _m, size_t _n )
|
||||
{
|
||||
return prepare(_m) && subdivide( _m, _n ) && cleanup( _m );
|
||||
}
|
||||
//@}
|
||||
|
||||
public: /// \name Interface 2
|
||||
//@{
|
||||
/// Attach mesh \c _m to self
|
||||
/// \see SubdividerT(), operator()(size_t), detach()
|
||||
bool attach( MeshType& _m )
|
||||
{
|
||||
if ( attached_ == &_m )
|
||||
return true;
|
||||
|
||||
detach();
|
||||
if (prepare( _m ))
|
||||
{
|
||||
attached_ = &_m;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Subdivide the attached \c _n times.
|
||||
/// \see SubdividerT(), attach(), detach()
|
||||
bool operator()( size_t _n )
|
||||
{
|
||||
return attached_ ? subdivide( *attached_, _n ) : false;
|
||||
}
|
||||
|
||||
/// Detach an eventually attached mesh.
|
||||
/// \see SubdividerT(), attach(), operator()(size_t)
|
||||
void detach(void)
|
||||
{
|
||||
if ( attached_ )
|
||||
{
|
||||
cleanup( *attached_ );
|
||||
attached_ = NULL;
|
||||
}
|
||||
}
|
||||
//@}
|
||||
|
||||
protected:
|
||||
|
||||
/// \name Overload theses methods
|
||||
//@{
|
||||
/// Prepare mesh, e.g. add properties
|
||||
virtual bool prepare( MeshType& _m ) = 0;
|
||||
|
||||
/// Subdivide mesh \c _m \c _n times
|
||||
virtual bool subdivide( MeshType& _m, size_t _n ) = 0;
|
||||
|
||||
/// Cleanup mesh after usage, e.g. remove added properties
|
||||
virtual bool cleanup( MeshType& _m ) = 0;
|
||||
//@}
|
||||
|
||||
private:
|
||||
|
||||
MeshType *attached_;
|
||||
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
} // namespace Uniform
|
||||
} // namespace Subdivider
|
||||
} // namespace OpenMesh
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_SUBDIVIDER_UNIFORM_SUBDIVIDERT_HH
|
||||
//=============================================================================
|
||||
Reference in New Issue
Block a user