00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00046
00047
00048
00049
00050
00051
00052 #ifndef OPENMESH_SUBDIVIDER_UNIFORM_LOOPT_HH
00053 #define OPENMESH_SUBDIVIDER_UNIFORM_LOOPT_HH
00054
00055
00056
00057
00058 #include <OpenMesh/Core/System/config.hh>
00059 #include <OpenMesh/Tools/Subdivider/Uniform/SubdividerT.hh>
00060 #include <OpenMesh/Core/Utils/vector_cast.hh>
00061
00062 #include <vector>
00063 #if defined(OM_CC_MIPS)
00064 # include <math.h>
00065 #else
00066 # include <cmath>
00067 #endif
00068
00069
00070
00071
00072 namespace OpenMesh {
00073 namespace Subdivider {
00074 namespace Uniform {
00075
00076
00077
00078
00087 template <typename MeshType, typename RealType = float>
00088 class LoopT : public SubdividerT<MeshType, RealType>
00089 {
00090 public:
00091
00092 typedef RealType real_t;
00093 typedef MeshType mesh_t;
00094 typedef SubdividerT< mesh_t, real_t > parent_t;
00095
00096 typedef std::pair< real_t, real_t > weight_t;
00097 typedef std::vector< std::pair<real_t,real_t> > weights_t;
00098
00099 public:
00100
00101
00102 LoopT(void) : parent_t(), _1over8( 1.0/8.0 ), _3over8( 3.0/8.0 )
00103 { init_weights(); }
00104
00105
00106 LoopT( mesh_t& _m ) : parent_t(_m), _1over8( 1.0/8.0 ), _3over8( 3.0/8.0 )
00107 { init_weights(); }
00108
00109
00110 ~LoopT() {}
00111
00112
00113 public:
00114
00115
00116 const char *name() const { return "Uniform Loop"; }
00117
00118
00120 void init_weights(size_t _max_valence=50)
00121 {
00122 weights_.resize(_max_valence);
00123 std::generate(weights_.begin(), weights_.end(), compute_weight());
00124 }
00125
00126
00127 protected:
00128
00129
00130 bool prepare( mesh_t& _m )
00131 {
00132 _m.add_property( vp_pos_ );
00133 _m.add_property( ep_pos_ );
00134 return true;
00135 }
00136
00137
00138 bool cleanup( mesh_t& _m )
00139 {
00140 _m.remove_property( vp_pos_ );
00141 _m.remove_property( ep_pos_ );
00142 return true;
00143 }
00144
00145
00146 bool subdivide( mesh_t& _m, size_t _n)
00147 {
00148 typename mesh_t::FaceIter fit, f_end;
00149 typename mesh_t::EdgeIter eit, e_end;
00150 typename mesh_t::VertexIter vit;
00151
00152
00153 for (size_t i=0; i < _n; ++i)
00154 {
00155
00156 for ( vit = _m.vertices_begin();
00157 vit != _m.vertices_end(); ++vit)
00158 smooth( _m, vit.handle() );
00159
00160
00161
00162 for (eit=_m.edges_begin(); eit != _m.edges_end(); ++eit)
00163 compute_midpoint( _m, eit.handle() );
00164
00165
00166
00167
00168
00169
00170 e_end = _m.edges_end();
00171 for (eit=_m.edges_begin(); eit != e_end; ++eit)
00172 split_edge(_m, eit.handle() );
00173
00174
00175
00176
00177
00178 f_end = _m.faces_end();
00179 for (fit = _m.faces_begin(); fit != f_end; ++fit)
00180 split_face(_m, fit.handle() );
00181
00182
00183
00184 for ( vit = _m.vertices_begin();
00185 vit != _m.vertices_end(); ++vit)
00186 _m.set_point(vit, _m.property( vp_pos_, vit ) );
00187
00188 #if defined(_DEBUG) || defined(DEBUG)
00189
00190 assert( OpenMesh::Utils::MeshCheckerT<mesh_t>(_m).check() );
00191 #endif
00192 }
00193
00194 return true;
00195 }
00196
00197 private:
00198
00201 struct compute_weight
00202 {
00203 compute_weight() : valence(-1) { }
00204 weight_t operator() (void)
00205 {
00206 #if !defined(OM_CC_MIPS)
00207 using std::cos;
00208 #endif
00209
00210
00211
00212
00213 if (++valence)
00214 {
00215 double inv_v = 1.0/double(valence);
00216 double t = (3.0 + 2.0 * cos( 2.0 * M_PI * inv_v) );
00217 double alpha = (40.0 - t * t)/64.0;
00218
00219 return weight_t( 1.0-alpha, inv_v*alpha);
00220 }
00221 return weight_t(0.0, 0.0);
00222 }
00223 int valence;
00224 };
00225
00226 private:
00227
00228 void split_face(mesh_t& _m, const typename mesh_t::FaceHandle& _fh)
00229 {
00230 typename mesh_t::HalfedgeHandle
00231 heh1(_m.halfedge_handle(_fh)),
00232 heh2(_m.next_halfedge_handle(_m.next_halfedge_handle(heh1))),
00233 heh3(_m.next_halfedge_handle(_m.next_halfedge_handle(heh2)));
00234
00235
00236 corner_cutting( _m, heh1 );
00237 corner_cutting( _m, heh2 );
00238 corner_cutting( _m, heh3 );
00239 }
00240
00241
00242 void corner_cutting(mesh_t& _m, const typename mesh_t::HalfedgeHandle& _he)
00243 {
00244
00245 typename mesh_t::HalfedgeHandle
00246 heh1(_he),
00247 heh5(heh1),
00248 heh6(_m.next_halfedge_handle(heh1));
00249
00250
00251 for (; _m.next_halfedge_handle(_m.next_halfedge_handle(heh5)) != heh1;
00252 heh5 = _m.next_halfedge_handle(heh5))
00253 {}
00254
00255 typename mesh_t::VertexHandle
00256 vh1 = _m.to_vertex_handle(heh1),
00257 vh2 = _m.to_vertex_handle(heh5);
00258
00259 typename mesh_t::HalfedgeHandle
00260 heh2(_m.next_halfedge_handle(heh5)),
00261 heh3(_m.new_edge( vh1, vh2)),
00262 heh4(_m.opposite_halfedge_handle(heh3));
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278 typename mesh_t::FaceHandle fh_old(_m.face_handle(heh6));
00279 typename mesh_t::FaceHandle fh_new(_m.new_face());
00280
00281
00282
00283 _m.set_next_halfedge_handle(heh4, heh6);
00284 _m.set_next_halfedge_handle(heh5, heh4);
00285
00286 _m.set_face_handle(heh4, fh_old);
00287 _m.set_face_handle(heh5, fh_old);
00288 _m.set_face_handle(heh6, fh_old);
00289 _m.set_halfedge_handle(fh_old, heh4);
00290
00291
00292 _m.set_next_halfedge_handle(heh1, heh3);
00293 _m.set_next_halfedge_handle(heh3, heh2);
00294
00295 _m.set_face_handle(heh1, fh_new);
00296 _m.set_face_handle(heh2, fh_new);
00297 _m.set_face_handle(heh3, fh_new);
00298
00299 _m.set_halfedge_handle(fh_new, heh1);
00300 }
00301
00302
00303 void split_edge(mesh_t& _m, const typename mesh_t::EdgeHandle& _eh)
00304 {
00305 typename mesh_t::HalfedgeHandle
00306 heh = _m.halfedge_handle(_eh, 0),
00307 opp_heh = _m.halfedge_handle(_eh, 1);
00308
00309 typename mesh_t::HalfedgeHandle new_heh, opp_new_heh, t_heh;
00310 typename mesh_t::VertexHandle vh;
00311 typename mesh_t::VertexHandle vh1(_m.to_vertex_handle(heh));
00312 typename mesh_t::Point zero(0,0,0);
00313
00314
00315 vh = _m.new_vertex( zero );
00316
00317
00318 _m.property( vp_pos_, vh ) = _m.property( ep_pos_, _eh );
00319
00320
00321
00322 if (_m.is_boundary(_eh))
00323 {
00324 for (t_heh = heh;
00325 _m.next_halfedge_handle(t_heh) != opp_heh;
00326 t_heh = _m.opposite_halfedge_handle(_m.next_halfedge_handle(t_heh)))
00327 {}
00328 }
00329 else
00330 {
00331 for (t_heh = _m.next_halfedge_handle(opp_heh);
00332 _m.next_halfedge_handle(t_heh) != opp_heh;
00333 t_heh = _m.next_halfedge_handle(t_heh) )
00334 {}
00335 }
00336
00337 new_heh = _m.new_edge(vh, vh1);
00338 opp_new_heh = _m.opposite_halfedge_handle(new_heh);
00339 _m.set_vertex_handle( heh, vh );
00340
00341 _m.set_next_halfedge_handle(t_heh, opp_new_heh);
00342 _m.set_next_halfedge_handle(new_heh, _m.next_halfedge_handle(heh));
00343 _m.set_next_halfedge_handle(heh, new_heh);
00344 _m.set_next_halfedge_handle(opp_new_heh, opp_heh);
00345
00346 if (_m.face_handle(opp_heh).is_valid())
00347 {
00348 _m.set_face_handle(opp_new_heh, _m.face_handle(opp_heh));
00349 _m.set_halfedge_handle(_m.face_handle(opp_new_heh), opp_new_heh);
00350 }
00351
00352 _m.set_face_handle( new_heh, _m.face_handle(heh) );
00353 _m.set_halfedge_handle( vh, new_heh);
00354 _m.set_halfedge_handle( _m.face_handle(heh), heh );
00355 _m.set_halfedge_handle( vh1, opp_new_heh );
00356
00357
00358 _m.adjust_outgoing_halfedge( vh );
00359 _m.adjust_outgoing_halfedge( vh1 );
00360 }
00361
00362 private:
00363
00364 void compute_midpoint(mesh_t& _m, const typename mesh_t::EdgeHandle& _eh)
00365 {
00366 #define V( X ) vector_cast< typename mesh_t::Normal >( X )
00367 typename mesh_t::HalfedgeHandle heh, opp_heh;
00368
00369 heh = _m.halfedge_handle( _eh, 0);
00370 opp_heh = _m.halfedge_handle( _eh, 1);
00371
00372 typename mesh_t::Point
00373 pos(_m.point(_m.to_vertex_handle(heh)));
00374
00375 pos += V( _m.point(_m.to_vertex_handle(opp_heh)) );
00376
00377
00378 if (_m.is_boundary(_eh) )
00379 {
00380 pos *= 0.5;
00381 }
00382 else
00383 {
00384 pos *= real_t(3.0);
00385 pos += V(_m.point(_m.to_vertex_handle(_m.next_halfedge_handle(heh))));
00386 pos += V(_m.point(_m.to_vertex_handle(_m.next_halfedge_handle(opp_heh))));
00387 pos *= _1over8;
00388 }
00389 _m.property( ep_pos_, _eh ) = pos;
00390 #undef V
00391 }
00392
00393
00394 void smooth(mesh_t& _m, const typename mesh_t::VertexHandle& _vh)
00395 {
00396 typename mesh_t::Point pos(0.0,0.0,0.0);
00397
00398 if (_m.is_boundary(_vh))
00399 {
00400 typename mesh_t::HalfedgeHandle heh, prev_heh;
00401 heh = _m.halfedge_handle( _vh );
00402
00403 if ( heh.is_valid() )
00404 {
00405 assert( _m.is_boundary( _m.edge_handle( heh ) ) );
00406
00407 prev_heh = _m.prev_halfedge_handle( heh );
00408
00409 typename mesh_t::VertexHandle
00410 to_vh = _m.to_vertex_handle( heh ),
00411 from_vh = _m.from_vertex_handle( prev_heh );
00412
00413
00414 pos = _m.point( _vh );
00415 pos *= real_t(6.0);
00416 pos += vector_cast< typename mesh_t::Normal >( _m.point( to_vh ) );
00417 pos += vector_cast< typename mesh_t::Normal >( _m.point( from_vh ) );
00418 pos *= _1over8;
00419
00420 }
00421 else
00422 return;
00423 }
00424 else
00425 {
00426 typedef typename mesh_t::Normal Vec;
00427 typename mesh_t::VertexVertexIter vvit;
00428 size_t valence(0);
00429
00430
00431 for (vvit=_m.vv_iter(_vh); vvit; ++vvit) {
00432 ++valence;
00433 pos += vector_cast< Vec >( _m.point(vvit) );
00434 }
00435 pos *= weights_[valence].second;
00436 pos += weights_[valence].first
00437 * vector_cast<Vec>(_m.point(_vh));
00438 }
00439
00440 _m.property( vp_pos_, _vh ) = pos;
00441 }
00442
00443 private:
00444
00445 OpenMesh::VPropHandleT< typename mesh_t::Point > vp_pos_;
00446 OpenMesh::EPropHandleT< typename mesh_t::Point > ep_pos_;
00447
00448 weights_t weights_;
00449
00450 const real_t _1over8;
00451 const real_t _3over8;
00452
00453 };
00454
00455
00456
00457 }
00458 }
00459 }
00460
00461 #endif // OPENMESH_SUBDIVIDER_UNIFORM_COMPOSITELOOPT_HH defined
00462