git-svn-id: http://www.openmesh.org/svnrepo/OpenMesh/trunk@83 fdac6126-5c0c-442c-9429-916003d36597
299 lines
9.8 KiB
C++
299 lines
9.8 KiB
C++
//=============================================================================
|
||
//
|
||
// 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$
|
||
// $Date$
|
||
//
|
||
//=============================================================================
|
||
|
||
/** \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
|
||
//=============================================================================
|