OpenMesh
|
00001 /*===========================================================================*\ 00002 * * 00003 * OpenMesh * 00004 * Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen * 00005 * www.openmesh.org * 00006 * * 00007 *---------------------------------------------------------------------------* 00008 * This file is part of OpenMesh. * 00009 * * 00010 * OpenMesh is free software: you can redistribute it and/or modify * 00011 * it under the terms of the GNU Lesser General Public License as * 00012 * published by the Free Software Foundation, either version 3 of * 00013 * the License, or (at your option) any later version with the * 00014 * following exceptions: * 00015 * * 00016 * If other files instantiate templates or use macros * 00017 * or inline functions from this file, or you compile this file and * 00018 * link it with other files to produce an executable, this file does * 00019 * not by itself cause the resulting executable to be covered by the * 00020 * GNU Lesser General Public License. This exception does not however * 00021 * invalidate any other reasons why the executable file might be * 00022 * covered by the GNU Lesser General Public License. * 00023 * * 00024 * OpenMesh is distributed in the hope that it will be useful, * 00025 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00026 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00027 * GNU Lesser General Public License for more details. * 00028 * * 00029 * You should have received a copy of the GNU LesserGeneral Public * 00030 * License along with OpenMesh. If not, * 00031 * see <http://www.gnu.org/licenses/>. * 00032 * * 00033 \*===========================================================================*/ 00034 00035 /*===========================================================================*\ 00036 * * 00037 * $Revision: 520 $ * 00038 * $Date: 2012-01-20 15:29:31 +0100 (Fr, 20 Jan 2012) $ * 00039 * * 00040 \*===========================================================================*/ 00041 00046 //============================================================================= 00047 // 00048 // CLASS Sqrt3T 00049 // 00050 //============================================================================= 00051 00052 #ifndef OPENMESH_SUBDIVIDER_UNIFORM_SQRT3T_HH 00053 #define OPENMESH_SUBDIVIDER_UNIFORM_SQRT3T_HH 00054 00055 00056 //== INCLUDES ================================================================= 00057 00058 #include <OpenMesh/Core/Mesh/Handles.hh> 00059 #include <OpenMesh/Core/System/config.hh> 00060 #include <OpenMesh/Tools/Subdivider/Uniform/SubdividerT.hh> 00061 #if defined(_DEBUG) || defined(DEBUG) 00062 // Makes life lot easier, when playing/messing around with low-level topology 00063 // changing methods of OpenMesh 00064 # include <OpenMesh/Tools/Utils/MeshCheckerT.hh> 00065 # define ASSERT_CONSISTENCY( T, m ) \ 00066 assert(OpenMesh::Utils::MeshCheckerT<T>(m).check()) 00067 #else 00068 # define ASSERT_CONSISTENCY( T, m ) 00069 #endif 00070 // -------------------- STL 00071 #include <vector> 00072 #if defined(OM_CC_MIPS) 00073 # include <math.h> 00074 #else 00075 # include <cmath> 00076 #endif 00077 00078 00079 //== NAMESPACE ================================================================ 00080 00081 namespace OpenMesh { // BEGIN_NS_OPENMESH 00082 namespace Subdivider { // BEGIN_NS_DECIMATER 00083 namespace Uniform { // BEGIN_NS_DECIMATER 00084 00085 00086 //== CLASS DEFINITION ========================================================= 00087 00088 00095 template <typename MeshType, typename RealType = float> 00096 class Sqrt3T : public SubdividerT< MeshType, RealType > 00097 { 00098 public: 00099 00100 typedef RealType real_t; 00101 typedef MeshType mesh_t; 00102 typedef SubdividerT< mesh_t, real_t > parent_t; 00103 00104 typedef std::pair< real_t, real_t > weight_t; 00105 typedef std::vector< std::pair<real_t,real_t> > weights_t; 00106 00107 public: 00108 00109 00110 Sqrt3T(void) : parent_t(), _1over3( 1.0/3.0 ), _1over27( 1.0/27.0 ) 00111 { init_weights(); } 00112 00113 Sqrt3T(MeshType &_m) : parent_t(_m), _1over3( 1.0/3.0 ), _1over27( 1.0/27.0 ) 00114 { init_weights(); } 00115 00116 virtual ~Sqrt3T() {} 00117 00118 00119 public: 00120 00121 00122 const char *name() const { return "Uniform Sqrt3"; } 00123 00124 00126 void init_weights(size_t _max_valence=50) 00127 { 00128 weights_.resize(_max_valence); 00129 std::generate(weights_.begin(), weights_.end(), compute_weight()); 00130 } 00131 00132 00133 protected: 00134 00135 00136 bool prepare( MeshType& _m ) 00137 { 00138 _m.request_edge_status(); 00139 _m.add_property( vp_pos_ ); 00140 _m.add_property( ep_nv_ ); 00141 _m.add_property( mp_gen_ ); 00142 _m.property( mp_gen_ ) = 0; 00143 00144 return _m.has_edge_status() && vp_pos_.is_valid() 00145 && ep_nv_.is_valid() && mp_gen_.is_valid(); 00146 } 00147 00148 00149 bool cleanup( MeshType& _m ) 00150 { 00151 _m.release_edge_status(); 00152 _m.remove_property( vp_pos_ ); 00153 _m.remove_property( ep_nv_ ); 00154 _m.remove_property( mp_gen_ ); 00155 return true; 00156 } 00157 00158 bool subdivide( MeshType& _m, size_t _n , const bool _update_points = true) 00159 { 00160 00162 00163 typename MeshType::VertexIter vit; 00164 typename MeshType::VertexVertexIter vvit; 00165 typename MeshType::EdgeIter eit; 00166 typename MeshType::FaceIter fit; 00167 typename MeshType::FaceVertexIter fvit; 00168 typename MeshType::VertexHandle vh; 00169 typename MeshType::HalfedgeHandle heh; 00170 typename MeshType::Point pos(0,0,0), zero(0,0,0); 00171 size_t &gen = _m.property( mp_gen_ ); 00172 00173 for (size_t l=0; l<_n; ++l) 00174 { 00175 // tag existing edges 00176 for (eit=_m.edges_begin(); eit != _m.edges_end();++eit) 00177 { 00178 _m.status( eit ).set_tagged( true ); 00179 if ( (gen%2) && _m.is_boundary(eit) ) 00180 compute_new_boundary_points( _m, eit ); // *) creates new vertices 00181 } 00182 00183 // do relaxation of old vertices, but store new pos in property vp_pos_ 00184 00185 for (vit=_m.vertices_begin(); vit!=_m.vertices_end(); ++vit) 00186 { 00187 if ( _m.is_boundary(vit) ) 00188 { 00189 if ( gen%2 ) 00190 { 00191 heh = _m.halfedge_handle(vit); 00192 if (heh.is_valid()) // skip isolated newly inserted vertices *) 00193 { 00194 typename OpenMesh::HalfedgeHandle 00195 prev_heh = _m.prev_halfedge_handle(heh); 00196 00197 assert( _m.is_boundary(heh ) ); 00198 assert( _m.is_boundary(prev_heh) ); 00199 00200 pos = _m.point(_m.to_vertex_handle(heh)); 00201 pos += _m.point(_m.from_vertex_handle(prev_heh)); 00202 pos *= real_t(4.0); 00203 00204 pos += real_t(19.0) * _m.point( vit ); 00205 pos *= _1over27; 00206 00207 _m.property( vp_pos_, vit ) = pos; 00208 } 00209 } 00210 else 00211 _m.property( vp_pos_, vit ) = _m.point( vit ); 00212 } 00213 else 00214 { 00215 size_t valence=0; 00216 00217 pos = zero; 00218 for ( vvit = _m.vv_iter(vit); vvit; ++vvit) 00219 { 00220 pos += _m.point( vvit ); 00221 ++valence; 00222 } 00223 pos *= weights_[ valence ].second; 00224 pos += weights_[ valence ].first * _m.point(vit); 00225 _m.property( vp_pos_, vit ) = pos; 00226 } 00227 } 00228 00229 // insert new vertices, but store pos in vp_pos_ 00230 typename MeshType::FaceIter fend = _m.faces_end(); 00231 for (fit = _m.faces_begin();fit != fend; ++fit) 00232 { 00233 if ( (gen%2) && _m.is_boundary(fit)) 00234 { 00235 boundary_split( _m, fit ); 00236 } 00237 else 00238 { 00239 fvit = _m.fv_iter( fit ); 00240 pos = _m.point( fvit); 00241 pos += _m.point(++fvit); 00242 pos += _m.point(++fvit); 00243 pos *= _1over3; 00244 vh = _m.add_vertex( zero ); 00245 _m.property( vp_pos_, vh ) = pos; 00246 _m.split( fit, vh ); 00247 } 00248 } 00249 00250 // commit new positions (now iterating over all vertices) 00251 for (vit=_m.vertices_begin();vit != _m.vertices_end(); ++vit) 00252 _m.set_point(vit, _m.property( vp_pos_, vit ) ); 00253 00254 // flip old edges 00255 for (eit=_m.edges_begin(); eit != _m.edges_end(); ++eit) 00256 if ( _m.status( eit ).tagged() && !_m.is_boundary( eit ) ) 00257 _m.flip(eit); 00258 00259 // Now we have an consistent mesh! 00260 ASSERT_CONSISTENCY( MeshType, _m ); 00261 00262 // increase generation by one 00263 ++gen; 00264 } 00265 return true; 00266 } 00267 00268 private: 00269 00272 struct compute_weight 00273 { 00274 compute_weight() : valence(-1) { } 00275 weight_t operator() (void) 00276 { 00277 #if !defined(OM_CC_MIPS) 00278 using std::cos; 00279 #endif 00280 if (++valence) 00281 { 00282 real_t alpha = (4.0-2.0*cos(2.0*M_PI / (double)valence))/9.0; 00283 return weight_t( real_t(1)-alpha, alpha/real_t(valence) ); 00284 } 00285 return weight_t(0.0, 0.0); 00286 } 00287 int valence; 00288 }; 00289 00290 private: 00291 00292 // Pre-compute location of new boundary points for odd generations 00293 // and store them in the edge property ep_nv_; 00294 void compute_new_boundary_points( MeshType& _m, 00295 const typename MeshType::EdgeHandle& _eh) 00296 { 00297 assert( _m.is_boundary(_eh) ); 00298 00299 typename MeshType::HalfedgeHandle heh; 00300 typename MeshType::VertexHandle vh1, vh2, vh3, vh4, vhl, vhr; 00301 typename MeshType::Point zero(0,0,0), P1, P2, P3, P4; 00302 00303 /* 00304 // *---------*---------* 00305 // / \ / \ / \ 00306 // / \ / \ / \ 00307 // / \ / \ / \ 00308 // / \ / \ / \ 00309 // *---------*--#---#--*---------* 00310 // 00311 // ^ ^ ^ ^ ^ ^ 00312 // P1 P2 pl pr P3 P4 00313 */ 00314 // get halfedge pointing from P3 to P2 (outer boundary halfedge) 00315 00316 heh = _m.halfedge_handle(_eh, 00317 _m.is_boundary(_m.halfedge_handle(_eh,1))); 00318 00319 assert( _m.is_boundary( _m.next_halfedge_handle( heh ) ) ); 00320 assert( _m.is_boundary( _m.prev_halfedge_handle( heh ) ) ); 00321 00322 vh1 = _m.to_vertex_handle( _m.next_halfedge_handle( heh ) ); 00323 vh2 = _m.to_vertex_handle( heh ); 00324 vh3 = _m.from_vertex_handle( heh ); 00325 vh4 = _m.from_vertex_handle( _m.prev_halfedge_handle( heh )); 00326 00327 P1 = _m.point(vh1); 00328 P2 = _m.point(vh2); 00329 P3 = _m.point(vh3); 00330 P4 = _m.point(vh4); 00331 00332 vhl = _m.add_vertex(zero); 00333 vhr = _m.add_vertex(zero); 00334 00335 _m.property(vp_pos_, vhl ) = (P1 + real_t(16.0f) * P2 + real_t(10.0f) * P3) * _1over27; 00336 _m.property(vp_pos_, vhr ) = ( real_t(10.0f) * P2 + real_t(16.0f) * P3 + P4) * _1over27; 00337 _m.property(ep_nv_, _eh).first = vhl; 00338 _m.property(ep_nv_, _eh).second = vhr; 00339 } 00340 00341 00342 void boundary_split( MeshType& _m, const typename MeshType::FaceHandle& _fh ) 00343 { 00344 assert( _m.is_boundary(_fh) ); 00345 00346 typename MeshType::VertexHandle vhl, vhr; 00347 typename MeshType::FaceEdgeIter fe_it; 00348 typename MeshType::HalfedgeHandle heh; 00349 00350 // find boundary edge 00351 for( fe_it=_m.fe_iter( _fh ); fe_it && !_m.is_boundary( fe_it ); ++fe_it ) {}; 00352 00353 // use precomputed, already inserted but not linked vertices 00354 vhl = _m.property(ep_nv_, fe_it).first; 00355 vhr = _m.property(ep_nv_, fe_it).second; 00356 00357 /* 00358 // *---------*---------* 00359 // / \ / \ / \ 00360 // / \ / \ / \ 00361 // / \ / \ / \ 00362 // / \ / \ / \ 00363 // *---------*--#---#--*---------* 00364 // 00365 // ^ ^ ^ ^ ^ ^ 00366 // P1 P2 pl pr P3 P4 00367 */ 00368 // get halfedge pointing from P2 to P3 (inner boundary halfedge) 00369 00370 heh = _m.halfedge_handle(fe_it, 00371 _m.is_boundary(_m.halfedge_handle(fe_it,0))); 00372 00373 typename MeshType::HalfedgeHandle pl_P3; 00374 00375 // split P2->P3 (heh) in P2->pl (heh) and pl->P3 00376 boundary_split( _m, heh, vhl ); // split edge 00377 pl_P3 = _m.next_halfedge_handle( heh ); // store next halfedge handle 00378 boundary_split( _m, heh ); // split face 00379 00380 // split pl->P3 in pl->pr and pr->P3 00381 boundary_split( _m, pl_P3, vhr ); 00382 boundary_split( _m, pl_P3 ); 00383 00384 assert( _m.is_boundary( vhl ) && _m.halfedge_handle(vhl).is_valid() ); 00385 assert( _m.is_boundary( vhr ) && _m.halfedge_handle(vhr).is_valid() ); 00386 } 00387 00388 void boundary_split(MeshType& _m, 00389 const typename MeshType::HalfedgeHandle& _heh, 00390 const typename MeshType::VertexHandle& _vh) 00391 { 00392 assert( _m.is_boundary( _m.edge_handle(_heh) ) ); 00393 00394 typename MeshType::HalfedgeHandle 00395 heh(_heh), 00396 opp_heh( _m.opposite_halfedge_handle(_heh) ), 00397 new_heh, opp_new_heh; 00398 typename MeshType::VertexHandle to_vh(_m.to_vertex_handle(heh)); 00399 typename MeshType::HalfedgeHandle t_heh; 00400 00401 /* 00402 * P5 00403 * * 00404 * /|\ 00405 * / \ 00406 * / \ 00407 * / \ 00408 * / \ 00409 * /_ heh new \ 00410 * *-----\*-----\*\-----* 00411 * ^ ^ t_heh 00412 * _vh to_vh 00413 * 00414 * P1 P2 P3 P4 00415 */ 00416 // Re-Setting Handles 00417 00418 // find halfedge point from P4 to P3 00419 for(t_heh = heh; 00420 _m.next_halfedge_handle(t_heh) != opp_heh; 00421 t_heh = _m.opposite_halfedge_handle(_m.next_halfedge_handle(t_heh))) 00422 {} 00423 00424 assert( _m.is_boundary( t_heh ) ); 00425 00426 new_heh = _m.new_edge( _vh, to_vh ); 00427 opp_new_heh = _m.opposite_halfedge_handle(new_heh); 00428 00429 // update halfedge connectivity 00430 00431 _m.set_next_halfedge_handle(t_heh, opp_new_heh); // P4-P3 -> P3-P2 00432 // P2-P3 -> P3-P5 00433 _m.set_next_halfedge_handle(new_heh, _m.next_halfedge_handle(heh)); 00434 _m.set_next_halfedge_handle(heh, new_heh); // P1-P2 -> P2-P3 00435 _m.set_next_halfedge_handle(opp_new_heh, opp_heh); // P3-P2 -> P2-P1 00436 00437 // both opposite halfedges point to same face 00438 _m.set_face_handle(opp_new_heh, _m.face_handle(opp_heh)); 00439 00440 // let heh finally point to new inserted vertex 00441 _m.set_vertex_handle(heh, _vh); 00442 00443 // let heh and new_heh point to same face 00444 _m.set_face_handle(new_heh, _m.face_handle(heh)); 00445 00446 // let opp_new_heh be the new outgoing halfedge for to_vh 00447 // (replaces for opp_heh) 00448 _m.set_halfedge_handle( to_vh, opp_new_heh ); 00449 00450 // let opp_heh be the outgoing halfedge for _vh 00451 _m.set_halfedge_handle( _vh, opp_heh ); 00452 } 00453 00454 void boundary_split( MeshType& _m, 00455 const typename MeshType::HalfedgeHandle& _heh) 00456 { 00457 assert( _m.is_boundary( _m.opposite_halfedge_handle( _heh ) ) ); 00458 00459 typename MeshType::HalfedgeHandle 00460 heh(_heh), 00461 n_heh(_m.next_halfedge_handle(heh)); 00462 00463 typename MeshType::VertexHandle 00464 to_vh(_m.to_vertex_handle(heh)); 00465 00466 typename MeshType::HalfedgeHandle 00467 heh2(_m.new_edge(to_vh, 00468 _m.to_vertex_handle(_m.next_halfedge_handle(n_heh)))), 00469 heh3(_m.opposite_halfedge_handle(heh2)); 00470 00471 typename MeshType::FaceHandle 00472 new_fh(_m.new_face()), 00473 fh(_m.face_handle(heh)); 00474 00475 // Relink (half)edges 00476 00477 #define set_next_heh set_next_halfedge_handle 00478 #define next_heh next_halfedge_handle 00479 00480 _m.set_face_handle(heh, new_fh); 00481 _m.set_face_handle(heh2, new_fh); 00482 _m.set_next_heh(heh2, _m.next_heh(_m.next_heh(n_heh))); 00483 _m.set_next_heh(heh, heh2); 00484 _m.set_face_handle( _m.next_heh(heh2), new_fh); 00485 00486 // _m.set_face_handle( _m.next_heh(_m.next_heh(heh2)), new_fh); 00487 00488 _m.set_next_heh(heh3, n_heh); 00489 _m.set_next_heh(_m.next_halfedge_handle(n_heh), heh3); 00490 _m.set_face_handle(heh3, fh); 00491 // _m.set_face_handle(n_heh, fh); 00492 00493 _m.set_halfedge_handle( fh, n_heh); 00494 _m.set_halfedge_handle(new_fh, heh); 00495 00496 #undef set_next_halfedge_handle 00497 #undef next_halfedge_handle 00498 00499 } 00500 00501 private: 00502 00503 weights_t weights_; 00504 OpenMesh::VPropHandleT< typename MeshType::Point > vp_pos_; 00505 OpenMesh::EPropHandleT< std::pair< typename MeshType::VertexHandle, 00506 typename MeshType::VertexHandle> > ep_nv_; 00507 OpenMesh::MPropHandleT< size_t > mp_gen_; 00508 00509 const real_t _1over3; 00510 const real_t _1over27; 00511 }; 00512 00513 00514 //============================================================================= 00515 } // END_NS_UNIFORM 00516 } // END_NS_SUBDIVIDER 00517 } // END_NS_OPENMESH 00518 //============================================================================= 00519 #endif // OPENMESH_SUBDIVIDER_UNIFORM_SQRT3T_HH 00520 //=============================================================================