/*===========================================================================*\ * * * OpenMesh * * Copyright (c) 2001-2015, RWTH-Aachen University * * Department for Computer Graphics and Multimedia * * All rights reserved. * * www.openmesh.org * * * *---------------------------------------------------------------------------* * This file is part of OpenMesh. * *---------------------------------------------------------------------------* * * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * * * 1. Redistributions of source code must retain the above copyright notice, * * this list of conditions and the following disclaimer. * * * * 2. Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * * * 3. Neither the name of the copyright holder nor the names of its * * contributors may be used to endorse or promote products derived from * * this software without specific prior written permission. * * * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER * * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * /*===========================================================================*\ /*===========================================================================*\ * * * $Revision$ * * $Date$ * * * \*===========================================================================*/ //============================================================================= // // CLASS RuleInterfaceT // //============================================================================= #ifndef OPENMESH_SUBDIVIDER_ADAPTIVE_RULEINTERFACET_HH #define OPENMESH_SUBDIVIDER_ADAPTIVE_RULEINTERFACET_HH //== INCLUDES ================================================================= #include #include //== NAMESPACE ================================================================ namespace OpenMesh { // BEGIN_NS_OPENMESH namespace Subdivider { // BEGIN_NS_SUBDIVIDER namespace Adaptive { // BEGIN_NS_ADAPTIVE //== FORWARDS ================================================================= template class CompositeT; template class RuleInterfaceT; //== CLASS DEFINITION ========================================================= // ---------------------------------------------------------------------------- /** Handle template for adaptive composite subdividion rules * \internal * * Use typed handle of a rule, e.g. Tvv3::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; \ public: \ const char *type() const { return #classname; } \ typedef classname Self; \ typedef RuleHandleT< Self > Handle // ---------------------------------------------------------------------------- /** Base class for adaptive composite subdivision rules * \see class CompositeT */ template class RuleInterfaceT { public: typedef M Mesh; typedef RuleInterfaceT 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 face_vector; face_vector.clear(); if (_target_state > 1) { for (fe_it = mesh_.fe_iter(_fh); fe_it.is_valid(); ++fe_it) { eh = *fe_it; prev_rule()->raise(eh, _target_state - 1); } for (fv_it = mesh_.fv_iter(_fh); fv_it.is_valid(); ++fv_it) { vh = *fv_it; 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 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.is_valid(); ++voh_it) { halfedge_vector.push_back(*voh_it); } 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.is_valid(); ++voh_it) { halfedge_vector.push_back(*voh_it); } 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; 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 //=============================================================================