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: 362 $ * 00038 * $Date: 2011-01-26 10:21:12 +0100 (Mi, 26 Jan 2011) $ * 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 00159 bool subdivide( MeshType& _m, size_t _n ) 00160 { 00161 typename MeshType::VertexIter vit; 00162 typename MeshType::VertexVertexIter vvit; 00163 typename MeshType::EdgeIter eit; 00164 typename MeshType::FaceIter fit; 00165 typename MeshType::FaceVertexIter fvit; 00166 typename MeshType::VertexHandle vh; 00167 typename MeshType::HalfedgeHandle heh; 00168 typename MeshType::Point pos(0,0,0), zero(0,0,0); 00169 size_t &gen = _m.property( mp_gen_ ); 00170 00171 for (size_t l=0; l<_n; ++l) 00172 { 00173 // tag existing edges 00174 for (eit=_m.edges_begin(); eit != _m.edges_end();++eit) 00175 { 00176 _m.status( eit ).set_tagged( true ); 00177 if ( (gen%2) && _m.is_boundary(eit) ) 00178 compute_new_boundary_points( _m, eit ); // *) creates new vertices 00179 } 00180 00181 // do relaxation of old vertices, but store new pos in property vp_pos_ 00182 00183 for (vit=_m.vertices_begin(); vit!=_m.vertices_end(); ++vit) 00184 { 00185 if ( _m.is_boundary(vit) ) 00186 { 00187 if ( gen%2 ) 00188 { 00189 heh = _m.halfedge_handle(vit); 00190 if (heh.is_valid()) // skip isolated newly inserted vertices *) 00191 { 00192 typename OpenMesh::HalfedgeHandle 00193 prev_heh = _m.prev_halfedge_handle(heh); 00194 00195 assert( _m.is_boundary(heh ) ); 00196 assert( _m.is_boundary(prev_heh) ); 00197 00198 pos = _m.point(_m.to_vertex_handle(heh)); 00199 pos += _m.point(_m.from_vertex_handle(prev_heh)); 00200 pos *= real_t(4.0); 00201 00202 pos += real_t(19.0) * _m.point( vit ); 00203 pos *= _1over27; 00204 00205 _m.property( vp_pos_, vit ) = pos; 00206 } 00207 } 00208 else 00209 _m.property( vp_pos_, vit ) = _m.point( vit ); 00210 } 00211 else 00212 { 00213 size_t valence=0; 00214 00215 pos = zero; 00216 for ( vvit = _m.vv_iter(vit); vvit; ++vvit) 00217 { 00218 pos += _m.point( vvit ); 00219 ++valence; 00220 } 00221 pos *= weights_[ valence ].second; 00222 pos += weights_[ valence ].first * _m.point(vit); 00223 _m.property( vp_pos_, vit ) = pos; 00224 } 00225 } 00226 00227 // insert new vertices, but store pos in vp_pos_ 00228 typename MeshType::FaceIter fend = _m.faces_end(); 00229 for (fit = _m.faces_begin();fit != fend; ++fit) 00230 { 00231 if ( (gen%2) && _m.is_boundary(fit)) 00232 { 00233 boundary_split( _m, fit ); 00234 } 00235 else 00236 { 00237 fvit = _m.fv_iter( fit ); 00238 pos = _m.point( fvit); 00239 pos += _m.point(++fvit); 00240 pos += _m.point(++fvit); 00241 pos *= _1over3; 00242 vh = _m.add_vertex( zero ); 00243 _m.property( vp_pos_, vh ) = pos; 00244 _m.split( fit, vh ); 00245 } 00246 } 00247 00248 // commit new positions (now iterating over all vertices) 00249 for (vit=_m.vertices_begin();vit != _m.vertices_end(); ++vit) 00250 _m.set_point(vit, _m.property( vp_pos_, vit ) ); 00251 00252 // flip old edges 00253 for (eit=_m.edges_begin(); eit != _m.edges_end(); ++eit) 00254 if ( _m.status( eit ).tagged() && !_m.is_boundary( eit ) ) 00255 _m.flip(eit); 00256 00257 // Now we have an consistent mesh! 00258 ASSERT_CONSISTENCY( MeshType, _m ); 00259 00260 // increase generation by one 00261 ++gen; 00262 } 00263 return true; 00264 } 00265 00266 private: 00267 00270 struct compute_weight 00271 { 00272 compute_weight() : valence(-1) { } 00273 weight_t operator() (void) 00274 { 00275 #if !defined(OM_CC_MIPS) 00276 using std::cos; 00277 #endif 00278 if (++valence) 00279 { 00280 real_t alpha = (4.0-2.0*cos(2.0*M_PI / (double)valence))/9.0; 00281 return weight_t( real_t(1)-alpha, alpha/real_t(valence) ); 00282 } 00283 return weight_t(0.0, 0.0); 00284 } 00285 int valence; 00286 }; 00287 00288 private: 00289 00290 // Pre-compute location of new boundary points for odd generations 00291 // and store them in the edge property ep_nv_; 00292 void compute_new_boundary_points( MeshType& _m, 00293 const typename MeshType::EdgeHandle& _eh) 00294 { 00295 assert( _m.is_boundary(_eh) ); 00296 00297 typename MeshType::HalfedgeHandle heh; 00298 typename MeshType::VertexHandle vh1, vh2, vh3, vh4, vhl, vhr; 00299 typename MeshType::Point zero(0,0,0), P1, P2, P3, P4; 00300 00301 /* 00302 // *---------*---------* 00303 // / \ / \ / \ 00304 // / \ / \ / \ 00305 // / \ / \ / \ 00306 // / \ / \ / \ 00307 // *---------*--#---#--*---------* 00308 // 00309 // ^ ^ ^ ^ ^ ^ 00310 // P1 P2 pl pr P3 P4 00311 */ 00312 // get halfedge pointing from P3 to P2 (outer boundary halfedge) 00313 00314 heh = _m.halfedge_handle(_eh, 00315 _m.is_boundary(_m.halfedge_handle(_eh,1))); 00316 00317 assert( _m.is_boundary( _m.next_halfedge_handle( heh ) ) ); 00318 assert( _m.is_boundary( _m.prev_halfedge_handle( heh ) ) ); 00319 00320 vh1 = _m.to_vertex_handle( _m.next_halfedge_handle( heh ) ); 00321 vh2 = _m.to_vertex_handle( heh ); 00322 vh3 = _m.from_vertex_handle( heh ); 00323 vh4 = _m.from_vertex_handle( _m.prev_halfedge_handle( heh )); 00324 00325 P1 = _m.point(vh1); 00326 P2 = _m.point(vh2); 00327 P3 = _m.point(vh3); 00328 P4 = _m.point(vh4); 00329 00330 vhl = _m.add_vertex(zero); 00331 vhr = _m.add_vertex(zero); 00332 00333 _m.property(vp_pos_, vhl ) = (P1 + real_t(16.0f) * P2 + real_t(10.0f) * P3) * _1over27; 00334 _m.property(vp_pos_, vhr ) = ( real_t(10.0f) * P2 + real_t(16.0f) * P3 + P4) * _1over27; 00335 _m.property(ep_nv_, _eh).first = vhl; 00336 _m.property(ep_nv_, _eh).second = vhr; 00337 } 00338 00339 00340 void boundary_split( MeshType& _m, const typename MeshType::FaceHandle& _fh ) 00341 { 00342 assert( _m.is_boundary(_fh) ); 00343 00344 typename MeshType::VertexHandle vhl, vhr; 00345 typename MeshType::FaceEdgeIter fe_it; 00346 typename MeshType::HalfedgeHandle heh; 00347 00348 // find boundary edge 00349 for( fe_it=_m.fe_iter( _fh ); fe_it && !_m.is_boundary( fe_it ); ++fe_it ) {}; 00350 00351 // use precomputed, already inserted but not linked vertices 00352 vhl = _m.property(ep_nv_, fe_it).first; 00353 vhr = _m.property(ep_nv_, fe_it).second; 00354 00355 /* 00356 // *---------*---------* 00357 // / \ / \ / \ 00358 // / \ / \ / \ 00359 // / \ / \ / \ 00360 // / \ / \ / \ 00361 // *---------*--#---#--*---------* 00362 // 00363 // ^ ^ ^ ^ ^ ^ 00364 // P1 P2 pl pr P3 P4 00365 */ 00366 // get halfedge pointing from P2 to P3 (inner boundary halfedge) 00367 00368 heh = _m.halfedge_handle(fe_it, 00369 _m.is_boundary(_m.halfedge_handle(fe_it,0))); 00370 00371 typename MeshType::HalfedgeHandle pl_P3; 00372 00373 // split P2->P3 (heh) in P2->pl (heh) and pl->P3 00374 boundary_split( _m, heh, vhl ); // split edge 00375 pl_P3 = _m.next_halfedge_handle( heh ); // store next halfedge handle 00376 boundary_split( _m, heh ); // split face 00377 00378 // split pl->P3 in pl->pr and pr->P3 00379 boundary_split( _m, pl_P3, vhr ); 00380 boundary_split( _m, pl_P3 ); 00381 00382 assert( _m.is_boundary( vhl ) && _m.halfedge_handle(vhl).is_valid() ); 00383 assert( _m.is_boundary( vhr ) && _m.halfedge_handle(vhr).is_valid() ); 00384 } 00385 00386 void boundary_split(MeshType& _m, 00387 const typename MeshType::HalfedgeHandle& _heh, 00388 const typename MeshType::VertexHandle& _vh) 00389 { 00390 assert( _m.is_boundary( _m.edge_handle(_heh) ) ); 00391 00392 typename MeshType::HalfedgeHandle 00393 heh(_heh), 00394 opp_heh( _m.opposite_halfedge_handle(_heh) ), 00395 new_heh, opp_new_heh; 00396 typename MeshType::VertexHandle to_vh(_m.to_vertex_handle(heh)); 00397 typename MeshType::HalfedgeHandle t_heh; 00398 00399 /* 00400 * P5 00401 * * 00402 * /|\ 00403 * / \ 00404 * / \ 00405 * / \ 00406 * / \ 00407 * /_ heh new \ 00408 * *-----\*-----\*\-----* 00409 * ^ ^ t_heh 00410 * _vh to_vh 00411 * 00412 * P1 P2 P3 P4 00413 */ 00414 // Re-Setting Handles 00415 00416 // find halfedge point from P4 to P3 00417 for(t_heh = heh; 00418 _m.next_halfedge_handle(t_heh) != opp_heh; 00419 t_heh = _m.opposite_halfedge_handle(_m.next_halfedge_handle(t_heh))) 00420 {} 00421 00422 assert( _m.is_boundary( t_heh ) ); 00423 00424 new_heh = _m.new_edge( _vh, to_vh ); 00425 opp_new_heh = _m.opposite_halfedge_handle(new_heh); 00426 00427 // update halfedge connectivity 00428 00429 _m.set_next_halfedge_handle(t_heh, opp_new_heh); // P4-P3 -> P3-P2 00430 // P2-P3 -> P3-P5 00431 _m.set_next_halfedge_handle(new_heh, _m.next_halfedge_handle(heh)); 00432 _m.set_next_halfedge_handle(heh, new_heh); // P1-P2 -> P2-P3 00433 _m.set_next_halfedge_handle(opp_new_heh, opp_heh); // P3-P2 -> P2-P1 00434 00435 // both opposite halfedges point to same face 00436 _m.set_face_handle(opp_new_heh, _m.face_handle(opp_heh)); 00437 00438 // let heh finally point to new inserted vertex 00439 _m.set_vertex_handle(heh, _vh); 00440 00441 // let heh and new_heh point to same face 00442 _m.set_face_handle(new_heh, _m.face_handle(heh)); 00443 00444 // let opp_new_heh be the new outgoing halfedge for to_vh 00445 // (replaces for opp_heh) 00446 _m.set_halfedge_handle( to_vh, opp_new_heh ); 00447 00448 // let opp_heh be the outgoing halfedge for _vh 00449 _m.set_halfedge_handle( _vh, opp_heh ); 00450 } 00451 00452 void boundary_split( MeshType& _m, 00453 const typename MeshType::HalfedgeHandle& _heh) 00454 { 00455 assert( _m.is_boundary( _m.opposite_halfedge_handle( _heh ) ) ); 00456 00457 typename MeshType::HalfedgeHandle 00458 heh(_heh), 00459 n_heh(_m.next_halfedge_handle(heh)); 00460 00461 typename MeshType::VertexHandle 00462 to_vh(_m.to_vertex_handle(heh)); 00463 00464 typename MeshType::HalfedgeHandle 00465 heh2(_m.new_edge(to_vh, 00466 _m.to_vertex_handle(_m.next_halfedge_handle(n_heh)))), 00467 heh3(_m.opposite_halfedge_handle(heh2)); 00468 00469 typename MeshType::FaceHandle 00470 new_fh(_m.new_face()), 00471 fh(_m.face_handle(heh)); 00472 00473 // Relink (half)edges 00474 00475 #define set_next_heh set_next_halfedge_handle 00476 #define next_heh next_halfedge_handle 00477 00478 _m.set_face_handle(heh, new_fh); 00479 _m.set_face_handle(heh2, new_fh); 00480 _m.set_next_heh(heh2, _m.next_heh(_m.next_heh(n_heh))); 00481 _m.set_next_heh(heh, heh2); 00482 _m.set_face_handle( _m.next_heh(heh2), new_fh); 00483 00484 // _m.set_face_handle( _m.next_heh(_m.next_heh(heh2)), new_fh); 00485 00486 _m.set_next_heh(heh3, n_heh); 00487 _m.set_next_heh(_m.next_halfedge_handle(n_heh), heh3); 00488 _m.set_face_handle(heh3, fh); 00489 // _m.set_face_handle(n_heh, fh); 00490 00491 _m.set_halfedge_handle( fh, n_heh); 00492 _m.set_halfedge_handle(new_fh, heh); 00493 00494 #undef set_next_halfedge_handle 00495 #undef next_halfedge_handle 00496 00497 } 00498 00499 private: 00500 00501 weights_t weights_; 00502 OpenMesh::VPropHandleT< typename MeshType::Point > vp_pos_; 00503 OpenMesh::EPropHandleT< std::pair< typename MeshType::VertexHandle, 00504 typename MeshType::VertexHandle> > ep_nv_; 00505 OpenMesh::MPropHandleT< size_t > mp_gen_; 00506 00507 const real_t _1over3; 00508 const real_t _1over27; 00509 }; 00510 00511 00512 //============================================================================= 00513 } // END_NS_UNIFORM 00514 } // END_NS_SUBDIVIDER 00515 } // END_NS_OPENMESH 00516 //============================================================================= 00517 #endif // OPENMESH_SUBDIVIDER_UNIFORM_SQRT3T_HH 00518 //=============================================================================