00001
00002
00003
00004 #include "std/config.H"
00005 #include "mesh/mi.H"
00006 #include "mesh/lmesh.H"
00007
00008 using namespace mlib;
00009
00010 double
00011 loop_alpha(int n)
00012 {
00013
00014
00015 static bool do_warren = Config::get_var_bool("DO_WARREN",false);
00016 if (do_warren)
00017 return 5.0/3*n;
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 static double _alpha[] = {
00028 1, 1, 1.282051, 2.333333,
00029 4.258065, 6.891565, 10.000000, 13.397789,
00030 16.957691, 20.598919, 24.272687, 27.950704,
00031 31.617293, 35.264345, 38.888210, 42.487807,
00032 46.063495, 49.616397, 53.148004, 56.659946,
00033 60.153856, 63.631303, 67.093752, 70.542553,
00034 73.978934, 77.404006, 80.818773, 84.224136,
00035 87.620905, 91.009809, 94.391503, 97.766576
00036 };
00037 if (n<2) {
00038 err_msg("loop_alpha: bad index %d", n);
00039 return 1;
00040 } else if (n >= 32) {
00041
00042 double b = 5.0/8.0 - sqr(3.0 + 2.0*cos(2*M_PI/n))/64.0;
00043 return n*(1-b)/b;
00044 } else {
00045 return _alpha[n];
00046 }
00047 }
00048
00049 Lvert::~Lvert()
00050 {
00051 if (is_edge(_parent)) {
00052 ((Ledge*)_parent)->subdiv_vert_deleted();
00053 } else if (is_vert(_parent)) {
00054 ((Lvert*)_parent)->subdiv_vert_deleted();
00055 }
00056
00057 delete_subdiv_vert();
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067 if (_mesh) {
00068 while (degree() > 0)
00069 _mesh->remove_edge(_adj.last());
00070 }
00071 }
00072
00073 void
00074 Lvert::subdiv_vert_deleted()
00075 {
00076
00077 _subdiv_vertex = 0;
00078
00079 clear_bit(SUBDIV_LOC_VALID_BIT);
00080 clear_bit(SUBDIV_COLOR_VALID_BIT);
00081 clear_bit(SUBDIV_CORNER_VALID_BIT);
00082 }
00083
00084 Bsimplex*
00085 Lvert::ctrl_element() const
00086 {
00087 if (!_parent)
00088 return (Bsimplex*)this;
00089 if (is_vert(_parent))
00090 return ((Lvert*)_parent)->ctrl_element();
00091 if (is_edge(_parent))
00092 return ((Ledge*)_parent)->ctrl_element();
00093 if (is_face(_parent))
00094 return ((Lface*)_parent)->control_face();
00095 return 0;
00096 }
00097
00098 Lvert*
00099 Lvert::subdiv_vert(int level)
00100 {
00101
00102
00103
00104 if (level < 0)
00105 return 0;
00106 if (level == 0)
00107 return this;
00108 return _subdiv_vertex ? _subdiv_vertex->subdiv_vert(level-1) : 0;
00109 }
00110
00111 Lvert*
00112 Lvert::parent_vert(int rel_level) const
00113 {
00114
00115
00116
00117 Lvert* v = (Lvert*)this;
00118 for (int i=0; v && i<rel_level; i++) {
00119 Bsimplex* p = v->parent();
00120 if (!is_vert(p))
00121 return 0;
00122 v = (Lvert*)p;
00123 }
00124
00125 return v;
00126 }
00127
00128 Lvert*
00129 Lvert::cur_subdiv_vert()
00130 {
00131
00132
00133 return _mesh ? subdiv_vert(_mesh->rel_cur_level()) : 0;
00134 }
00135
00136
00137
00138
00139 Lvert*
00140 Lvert::allocate_subdiv_vert()
00141 {
00142
00143
00144 if (is_set(SUBDIV_ALLOCATED_BIT))
00145 return _subdiv_vertex;
00146 set_bit(SUBDIV_ALLOCATED_BIT);
00147
00148 assert(!_subdiv_vertex);
00149
00150 LMESH* submesh = lmesh()->subdiv_mesh();
00151 assert(submesh);
00152 _subdiv_vertex = (Lvert*)submesh->add_vertex(_loc); assert(_subdiv_vertex);
00153
00154 _subdiv_vertex->set_parent(this);
00155
00156
00157 if (_data_list)
00158 _data_list->notify_subdiv_gen();
00159
00160 return _subdiv_vertex;
00161 }
00162
00163 void
00164 Lvert::set_subdiv_vert(Lvert* subv)
00165 {
00166 if (is_set(SUBDIV_ALLOCATED_BIT)) {
00167 err_msg("Lvert::set_subdiv_vert: already set");
00168 return;
00169 }
00170 assert(!_subdiv_vertex);
00171
00172 set_bit(SUBDIV_ALLOCATED_BIT);
00173 _subdiv_vertex = subv;
00174 if (subv) {
00175 assert(!subv->parent());
00176 assert(lmesh()->subdiv_mesh() == subv->mesh());
00177 subv->set_parent(this);
00178 }
00179
00180
00181 if (_data_list)
00182 _data_list->notify_subdiv_gen();
00183 }
00184
00185 void
00186 Lvert::delete_subdiv_vert()
00187 {
00188
00189
00190 if (!is_set(SUBDIV_ALLOCATED_BIT))
00191 return;
00192 clear_bit(SUBDIV_ALLOCATED_BIT);
00193
00194 if (_subdiv_vertex) {
00195 _subdiv_vertex->mesh()->remove_vertex(_subdiv_vertex);
00196 mark_dirty();
00197 }
00198 }
00199
00200 Lvert*
00201 Lvert::update_subdivision()
00202 {
00203
00204 allocate_subdiv_vert();
00205 if (!_subdiv_vertex) {
00206
00207
00208 return 0;
00209 }
00210
00211
00212
00213
00214
00215 if (is_clear(SUBDIV_CORNER_VALID_BIT)) {
00216 set_bit(SUBDIV_CORNER_VALID_BIT);
00217 _subdiv_vertex->set_corner((_corner > 0) ? _corner - 1 : 0);
00218 }
00219
00220
00221 if (is_clear(SUBDIV_COLOR_VALID_BIT)) {
00222 set_bit(SUBDIV_COLOR_VALID_BIT);
00223 if (has_color())
00224 _subdiv_vertex->set_color(lmesh()->subdiv_color(this));
00225 }
00226
00227
00228 if (is_clear(SUBDIV_LOC_VALID_BIT)) {
00229 set_bit(SUBDIV_LOC_VALID_BIT);
00230
00231
00232 if (!(_data_list && _data_list->handle_subdiv_calc())) {
00233 if (corner_value() > 0)
00234 _subdiv_vertex->set_loc(loc());
00235 else
00236 _subdiv_vertex->set_subdiv_base_loc(lmesh()->subdiv_loc(this));
00237 }
00238 }
00239
00240
00241 return _subdiv_vertex;
00242 }
00243
00244 void
00245 Lvert::set_offset(double d)
00246 {
00247 if (!_parent) {
00248 err_msg("Lvert::set_offset: error: called on control vert");
00249 } else if (_offset != d) {
00250 _offset = d;
00251 set_loc(detail_loc_from_parent());
00252 }
00253 }
00254
00255 Wpt
00256 Lvert::smooth_loc_from_parent() const
00257 {
00258
00259
00260
00261
00262 if (!_parent)
00263 return loc();
00264 assert(lmesh() && lmesh()->parent_mesh());
00265 if (is_vert(_parent))
00266 return lmesh()->parent_mesh()->subdiv_loc((Lvert*)_parent);
00267 if (is_edge(_parent))
00268 return lmesh()->parent_mesh()->subdiv_loc((Ledge*)_parent);
00269 assert(0);
00270 return Wpt::Origin();
00271 }
00272
00273 Wpt
00274 Lvert::detail_loc_from_parent() const
00275 {
00276
00277
00278 assert(_parent);
00279
00280 return smooth_loc_from_parent() + get_norm(_parent)*_offset;
00281 }
00282
00283 void
00284 Lvert::set_subdiv_base_loc(CWpt& base_loc)
00285 {
00286
00287
00288
00289
00290
00291
00292
00293
00294 if (_offset == 0 || !_parent) {
00295 set_loc(base_loc);
00296 } else {
00297 set_loc(base_loc + get_norm(_parent)*_offset);
00298 }
00299 }
00300
00301 void
00302 Lvert::fit_subdiv_offset(CWpt& detail_loc)
00303 {
00304
00305
00306
00307 if (!_parent) {
00308 set_loc(detail_loc);
00309 } else {
00310 set_offset( (detail_loc - smooth_loc_from_parent()) * get_norm(_parent) );
00311 }
00312 }
00313
00314 Wpt&
00315 Lvert::limit_loc(Wpt& ret) const
00316 {
00317 return (ret = lmesh()->limit_loc(this));
00318 }
00319
00320 Wvec&
00321 Lvert::loop_normal(Wvec& ret) const
00322 {
00323 return (ret = LoopLoc().limit_normal(this));
00324 }
00325
00326 CWpt&
00327 Lvert::displaced_loc(LocCalc* c)
00328 {
00329 static double a = Config::get_var_dbl("VOL_PRESERVE_ALPHA", 0.5,true);
00330
00331 if (!is_set(DISPLACED_LOC_VALID)) {
00332
00333 _displaced_loc = interp(c->subdiv_val(this), _loc, 1 + a);
00334 set_bit(DISPLACED_LOC_VALID);
00335 }
00336 return _displaced_loc;
00337 }
00338
00339 void
00340 Lvert::mark_dirty(int bit)
00341 {
00342 if (!is_set(DEAD_BIT)) {
00343 clear_bit(bit);
00344 lmesh()->add_dirty_vert(this);
00345 }
00346 }
00347
00348 void
00349 Lvert::crease_changed()
00350 {
00351 Bvert::crease_changed();
00352
00353 mask_changed();
00354 }
00355
00356 void
00357 Lvert::degree_changed()
00358 {
00359 Bvert::degree_changed();
00360
00361 mask_changed();
00362 }
00363
00364 void
00365 Lvert::mask_changed()
00366 {
00367 clear_bit(MASK_VALID_BIT);
00368 subdiv_loc_changed();
00369 subdiv_color_changed();
00370
00371
00372
00373
00374
00375
00376
00377
00378 for (int k = 0; k < degree(); k++) {
00379 if (e(k)->is_set(Ledge::MASK_VALID_BIT))
00380 le(k)->mask_changed();
00381 }
00382 }
00383
00384 void
00385 Lvert::geometry_changed()
00386 {
00387 subdiv_loc_changed();
00388 Bvert::geometry_changed();
00389 }
00390
00391 void
00392 Lvert::normal_changed()
00393 {
00394 subdiv_loc_changed();
00395 Bvert::normal_changed();
00396 }
00397
00398 void
00399 Lvert::color_changed()
00400 {
00401 subdiv_color_changed();
00402 Bvert::color_changed();
00403
00404 for (int k = 0; k < degree(); k++)
00405 le(k)->color_changed();
00406 }
00407
00408 void
00409 Lvert::set_corner(unsigned short c)
00410 {
00411 if (_corner != c) {
00412 _corner = c;
00413 clear_bit(SUBDIV_CORNER_VALID_BIT);
00414 mask_changed();
00415 }
00416 }
00417
00418 void
00419 Lvert::set_mask()
00420 {
00421 set_bit(MASK_VALID_BIT);
00422
00423 static Bedge_list pedges;
00424 get_manifold_edges(pedges);
00425
00426
00427
00428
00429 if (_corner || pedges.num() < 2) {
00430 _mask = CORNER_VERTEX;
00431 return;
00432 }
00433
00434
00435
00436
00437
00438 int s = pedges.num_satisfy(PolylineEdgeFilter());
00439 if (s > 0) {
00440 _mask = ((s == 2) ? REGULAR_CREASE_VERTEX : CORNER_VERTEX);
00441 return;
00442 }
00443
00444
00445
00446 for (int k=0; k<pedges.num(); k++)
00447 if (pedges[k]->is_crease() || pedges[k]->is_border())
00448 s++;
00449
00450
00451 _mask = ((s == 0) ? SMOOTH_VERTEX :
00452 (s == 1) ? DART_VERTEX :
00453 (s == 2) ? REGULAR_CREASE_VERTEX :
00454 CORNER_VERTEX);
00455 }
00456
00457