00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "builderMisc.h"
00020 #include "mesherStrip.h"
00021 #include "mesherFanMaker.h"
00022 #include "config_builder.h"
00023
00024 #include <algorithm>
00025
00026 template <class PrimType>
00027 MesherTempl<PrimType>::
00028 MesherTempl(BuilderBucket *bucket) {
00029 _bucket = bucket;
00030 _stripIndex = 0;
00031 _next_strip = _done.end();
00032 }
00033
00034 template <class PrimType>
00035 int MesherTempl<PrimType>::
00036 add_prim(const Prim &prim, MesherStripOrigin origin) {
00037 if (!prim.is_valid()) {
00038 return false;
00039 }
00040
00041
00042 Strip temp_strip(prim, _stripIndex++, *_bucket);
00043 Strips &list = choose_strip_list(temp_strip);
00044 list.push_back(temp_strip);
00045 Strip &strip = list.back();
00046 strip._origin = origin;
00047
00048 int i;
00049 int num_verts = prim.get_num_verts();
00050
00051 const Vertex **vptrs = (const Vertex **)alloca(num_verts * sizeof(Vertex *));
00052 EdgePtrs **eptrs = (EdgePtrs **)alloca(num_verts * sizeof(EdgePtrs *));
00053
00054
00055 for (i = 0; i < num_verts; i++) {
00056 TYPENAME Verts::iterator n =
00057 _verts.insert(Verts::value_type(prim.get_vertex(i), EdgePtrs())).first;
00058 vptrs[i] = &(*n).first;
00059 eptrs[i] = &(*n).second;
00060
00061 strip._verts.push_back(vptrs[i]);
00062 }
00063
00064
00065 if (prim.get_type() == BPT_tri || prim.get_type() == BPT_quad) {
00066
00067
00068
00069
00070
00071
00072 for (i = 0; i < num_verts; i++) {
00073
00074
00075
00076 Edge inner(vptrs[i], vptrs[(i+1) % num_verts]);
00077 Edge outer(vptrs[(i+1) % num_verts], vptrs[i]);
00078
00079
00080 Edge &inner_ref = (Edge &)*_edges.insert(inner).first;
00081 Edge &outer_ref = (Edge &)*_edges.insert(outer).first;
00082
00083
00084 inner_ref._opposite = &outer_ref;
00085 outer_ref._opposite = &inner_ref;
00086
00087
00088 strip._edges.push_back(&inner_ref);
00089
00090
00091 outer_ref._strips.push_back(&strip);
00092
00093
00094
00095 eptrs[i]->insert(&outer_ref);
00096 eptrs[(i+1) % num_verts]->insert(&outer_ref);
00097 }
00098 }
00099 return true;
00100 }
00101
00102
00103 template <class PrimType>
00104 void MesherTempl<PrimType>::
00105 mesh() {
00106 if (_bucket->_consider_fans) {
00107 find_fans();
00108 }
00109
00110
00111 if (_bucket->_retesselate_coplanar) {
00112 make_quads();
00113 }
00114
00115
00116 meshList(_tris);
00117
00118 if (_bucket->_show_quads) {
00119
00120 TYPENAME Strips::iterator si;
00121 for (si = _quads.begin(); si != _quads.end(); ++si) {
00122 if ((*si)._status == MS_alive) {
00123 (*si)._status = MS_done;
00124 }
00125 }
00126 for (si = _strips.begin(); si != _strips.end(); ++si) {
00127 if ((*si)._status == MS_alive) {
00128 (*si)._status = MS_done;
00129 }
00130 }
00131 }
00132
00133
00134 build_sheets();
00135
00136
00137 meshList(_quads);
00138
00139
00140 meshList(_strips);
00141
00142
00143 _next_strip = _done.begin();
00144 }
00145
00146
00147 template <class PrimType>
00148 PrimType MesherTempl<PrimType>::
00149 getPrim() {
00150 if (_next_strip == _done.end()) {
00151
00152 finalize();
00153 return Prim();
00154 }
00155
00156 Strip &strip = (*_next_strip++);
00157 BuilderPrimType orig_type = strip._type;
00158 Prim prim = strip.make_prim(*_bucket);
00159
00160 if (_bucket->_show_tstrips) {
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170 if (_colors.empty()) {
00171
00172 _colors.push_back(Colorf(0.85, 0.85, 0.85, 1.0));
00173 }
00174
00175 ushort i1, i2;
00176 Colorf color1, color2;;
00177
00178 switch (prim.get_type()) {
00179 case BPT_tristrip:
00180 case BPT_trifan:
00181 make_random_color(color2);
00182 color1 = (color2 * 0.8);
00183 i1 = _colors.size();
00184 i2 = i1+1;
00185 _colors.push_back(color1);
00186 _colors.push_back(color2);
00187 break;
00188
00189 default:
00190
00191 i1 = i2 = 0;
00192 }
00193
00194
00195
00196
00197 int num_components = prim.get_num_components();
00198 if (num_components > 0) {
00199 prim.get_component(0).set_color_value(&_colors[0], i1);
00200 for (int i = 1; i < num_components; i++) {
00201 prim.get_component(i).set_color_value(&_colors[0], i2);
00202 }
00203 } else {
00204 prim.set_color_value(&_colors[0], i1);
00205 }
00206
00207 } else if (_bucket->_show_qsheets) {
00208
00209
00210
00211
00212 if (_colors.empty()) {
00213
00214 _colors.push_back(Colorf(0.85, 0.85, 0.85, 1.0));
00215 }
00216
00217
00218 ushort i1 = 0;
00219 if (strip._row_id < 0) {
00220
00221 ColorSheetMap::iterator ci = _color_sheets.find(strip._row_id);
00222
00223 if (ci == _color_sheets.end()) {
00224 Colorf color1;
00225 make_random_color(color1);
00226 i1 = _colors.size();
00227 _colors.push_back(color1);
00228 _color_sheets[strip._row_id] = i1;
00229 } else {
00230 i1 = (*ci).second;
00231 }
00232 }
00233
00234
00235
00236 int num_verts = prim.get_num_verts();
00237 for (int i = 0; i < num_verts; i++) {
00238 prim.get_vertex(i).set_color_value(&_colors[0], i1);
00239 }
00240
00241 } else if (_bucket->_show_quads) {
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253 if (_colors.empty()) {
00254
00255 _colors.push_back(Colorf(0.85, 0.85, 0.85, 1.0));
00256 _colors.push_back(Colorf(0.0, 0.0, 0.75, 1.0));
00257 _colors.push_back(Colorf(0.4, 0.4, 0.8, 1.0));
00258 _colors.push_back(Colorf(0.6, 0.6, 1.0, 1.0));
00259 _colors.push_back(Colorf(0.2, 0.8, 0.2, 1.0));
00260 }
00261
00262 ushort i1;
00263 Colorf color1;
00264 if (strip._origin == MO_user) {
00265 i1 = 0;
00266 } else if (strip._origin == MO_firstquad) {
00267 i1 = 1;
00268 } else if (strip._origin == MO_fanpoly) {
00269 i1 = 4;
00270 } else {
00271 switch (orig_type) {
00272 case BPT_quad:
00273 i1 = 2;
00274 break;
00275
00276 case BPT_quadstrip:
00277 i1 = 3;
00278 break;
00279
00280 case BPT_tristrip:
00281 make_random_color(color1);
00282
00283 if (color1[0] < color1[1]) {
00284 float t = color1[0];
00285 color1[0] = color1[1];
00286 color1[1] = t;
00287 }
00288 color1[2] = color1[1];
00289 i1 = _colors.size();
00290 _colors.push_back(color1);
00291 break;
00292
00293 case BPT_trifan:
00294 make_random_color(color1);
00295
00296 if (color1[0] > color1[1]) {
00297 float t = color1[0];
00298 color1[0] = color1[1];
00299 color1[1] = t;
00300 }
00301 color1[2] = color1[0];
00302 i1 = _colors.size();
00303 _colors.push_back(color1);
00304 break;
00305
00306 default:
00307 i1 = 0;
00308 }
00309 }
00310
00311
00312
00313 int num_verts = prim.get_num_verts();
00314 for (int i = 0; i < num_verts; i++) {
00315 prim.get_vertex(i).set_color_value(&_colors[0], i1);
00316 }
00317 }
00318
00319 return prim;
00320 }
00321
00322
00323 template <class PrimType>
00324 void MesherTempl<PrimType>::
00325 finalize() {
00326 if (!_colors.empty()) {
00327
00328 PTA_Colorf colors=PTA_Colorf::empty_array(_colors.size());
00329 for (int i = 0; i < (int)_colors.size(); i++) {
00330 colors[i] = _colors[i];
00331 }
00332 _bucket->set_colors(colors);
00333
00334 _colors.clear();
00335 _color_sheets.clear();
00336 }
00337 }
00338
00339
00340
00341 template <class PrimType>
00342 void MesherTempl<PrimType>::
00343 show(ostream &out) {
00344
00345
00346
00347
00348
00349 out << _verts.size() << " verts:\n";
00350 TYPENAME Verts::const_iterator vi;
00351
00352 for (vi = _verts.begin(); vi != _verts.end(); ++vi) {
00353 const Vertex &v = (*vi).first;
00354 const EdgePtrs &edges = (*vi).second;
00355 out << v << " shares " << count_vert_edges(edges) << " edges:\n";
00356 TYPENAME EdgePtrs::const_iterator ei;
00357 for (ei = edges.begin(); ei != edges.end(); ++ei) {
00358 if (!(*ei)->_strips.empty() || !(*ei)->_opposite->_strips.empty()) {
00359 out << " " << **ei << "\n";
00360 }
00361 }
00362 }
00363
00364 TYPENAME Strips::const_iterator si;
00365 out << _tris.size() << " tris:\n";
00366 for (si = _tris.begin(); si != _tris.end(); ++si) {
00367 out << (*si) << "\n";
00368 }
00369
00370 out << _quads.size() << " quads:\n";
00371 for (si = _quads.begin(); si != _quads.end(); ++si) {
00372 out << (*si) << "\n";
00373 }
00374
00375 out << _strips.size() << " strips:\n";
00376 for (si = _strips.begin(); si != _strips.end(); ++si) {
00377 out << (*si) << "\n";
00378 }
00379 }
00380
00381
00382 template <class PrimType>
00383 int MesherTempl<PrimType>::
00384 count_vert_edges(const EdgePtrs &edges) const {
00385 int count = 0;
00386 TYPENAME EdgePtrs::const_iterator ei;
00387 for (ei = edges.begin(); ei != edges.end(); ++ei) {
00388 count += (!(*ei)->_strips.empty() || !(*ei)->_opposite->_strips.empty());
00389 }
00390 return count;
00391 }
00392
00393 template <class PrimType>
00394 plist<TYPENAME MesherTempl<PrimType>::Strip> &MesherTempl<PrimType>::
00395 choose_strip_list(const Strip &strip) {
00396 switch (strip._status) {
00397 case MS_done:
00398 return _done;
00399
00400 case MS_dead:
00401 return _dead;
00402
00403 case MS_alive:
00404 switch (strip._type) {
00405 case BPT_tri:
00406 return _tris;
00407
00408 case BPT_quad:
00409 return _quads;
00410
00411 default:
00412 return _strips;
00413 }
00414
00415 default:
00416 builder_cat.fatal() << "Invalid strip status!\n";
00417 abort();
00418 }
00419
00420 return _strips;
00421 }
00422
00423
00424 template <class PrimType>
00425 void MesherTempl<PrimType>::
00426 build_sheets() {
00427 int first_row_id = 1;
00428
00429
00430 Strips pre_sheeted;
00431 pre_sheeted.splice(pre_sheeted.end(), _quads);
00432
00433 while (!pre_sheeted.empty()) {
00434
00435
00436 TYPENAME Strips::iterator best = pre_sheeted.begin();
00437
00438
00439
00440
00441 if ((*best)._row_id >= 0 &&
00442 (*best)._status == MS_alive &&
00443 !(*best)._edges.empty()) {
00444
00445
00446
00447
00448 const Edge *edge_a = (*best)._edges.front();
00449 const Edge *edge_b = (*best).find_adjacent_edge(edge_a);
00450
00451 int num_prims_a = 0;
00452 int num_rows_a = 0;
00453 int first_row_id_a = first_row_id;
00454 (*best).measure_sheet(edge_a, true, num_prims_a, num_rows_a,
00455 first_row_id_a, 0, 0);
00456 first_row_id += num_rows_a;
00457 double avg_length_a = (double)num_prims_a / (double)num_rows_a;
00458
00459 int num_prims_b = 0;
00460 int num_rows_b = 0;
00461 int first_row_id_b = first_row_id;
00462 double avg_length_b;
00463 if (edge_b != NULL) {
00464 (*best).measure_sheet(edge_b, true, num_prims_b, num_rows_b,
00465 first_row_id_b, 0, 0);
00466 first_row_id += num_rows_b;
00467 avg_length_b = (double)num_prims_b / (double)num_rows_b;
00468 }
00469
00470
00471 if (edge_b != NULL && avg_length_b >= avg_length_a) {
00472
00473 (*best).cut_sheet(first_row_id_b, true, *_bucket);
00474
00475 } else {
00476
00477
00478
00479
00480
00481 num_prims_a = 0;
00482 num_rows_a = 0;
00483 first_row_id_a = first_row_id;
00484 (*best).measure_sheet(edge_a, true, num_prims_a, num_rows_a,
00485 first_row_id_a, 0, 0);
00486 first_row_id += num_rows_a;
00487
00488
00489 (*best).cut_sheet(first_row_id_a, true, *_bucket);
00490 }
00491 }
00492
00493
00494
00495 Strips &list = choose_strip_list(*best);
00496 list.splice(list.end(), pre_sheeted, best);
00497 }
00498 }
00499
00500
00501 template <class PrimType>
00502 void MesherTempl<PrimType>::
00503 find_fans() {
00504 #ifdef SUPPORT_FANS
00505 pvector<Prim> unrolled_tris;
00506
00507
00508
00509
00510 TYPENAME Verts::iterator vi;
00511
00512 for (vi = _verts.begin(); vi != _verts.end(); ++vi) {
00513 EdgePtrs &edges = (*vi).second;
00514
00515
00516
00517
00518
00519
00520
00521 if (edges.size() > 6) {
00522 const Vertex &v = (*vi).first;
00523
00524
00525 typedef pvector<FanMaker> FanMakers;
00526
00527 FanMakers fans;
00528
00529 TYPENAME EdgePtrs::iterator ei;
00530 TYPENAME Edge::Strips::iterator si;
00531 for (ei = edges.begin(); ei != edges.end(); ++ei) {
00532 for (si = (*ei)->_strips.begin();
00533 si != (*ei)->_strips.end();
00534 ++si) {
00535 Strip *strip = *si;
00536 if (strip->_type == BPT_tri) {
00537 fans.push_back(FanMaker(&v, strip, this));
00538 }
00539 }
00540 }
00541
00542
00543 sort(fans.begin(), fans.end());
00544 fans.erase(unique(fans.begin(), fans.end()),
00545 fans.end());
00546
00547 TYPENAME FanMakers::iterator fi, fi2;
00548
00549
00550 int joined_any;
00551 do {
00552 joined_any = false;
00553 for (fi = fans.begin(); fi != fans.end(); ++fi) {
00554 if (!(*fi).is_empty()) {
00555 fi2 = fi;
00556 for (++fi2; fi2 != fans.end(); ++fi2) {
00557 if (!(*fi2).is_empty()) {
00558 joined_any = (*fi).join(*fi2);
00559 }
00560 }
00561 }
00562 }
00563 } while (joined_any);
00564
00565 for (fi = fans.begin(); fi != fans.end(); ++fi) {
00566 if ((*fi).is_valid()) {
00567 (*fi).build(unrolled_tris);
00568 }
00569 }
00570 }
00571 }
00572
00573
00574
00575
00576
00577
00578 TYPENAME pvector<Prim>::iterator ti;
00579 for (ti = unrolled_tris.begin(); ti != unrolled_tris.end(); ++ti) {
00580 add_prim(*ti);
00581 }
00582 #endif
00583 }
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594 template <class PrimType>
00595 void MesherTempl<PrimType>::
00596 make_quads() {
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608 typedef pair<Strip *, Strip *> Pair;
00609 typedef pair<Pair, Edge *> Matched;
00610 typedef pvector<Matched> SoulMates;
00611
00612 SoulMates soulmates;
00613
00614 Strip *tri, *mate, *mate2;
00615 Edge *common_edge, *common_edge2;
00616
00617 TYPENAME Strips::iterator si;
00618 for (si = _tris.begin(); si != _tris.end(); ++si) {
00619 tri = &(*si);
00620
00621 if (tri->_status == MS_alive) {
00622 if (tri->find_ideal_mate(mate, common_edge, *_bucket)) {
00623
00624 if (mate->_type == BPT_tri && mate->_status == MS_alive &&
00625 mate->find_ideal_mate(mate2, common_edge2, *_bucket) &&
00626 mate2 == tri) {
00627
00628 soulmates.push_back(Matched(Pair(tri, mate), common_edge));
00629
00630 tri->_status = MS_paired;
00631 mate->_status = MS_paired;
00632 }
00633 }
00634 }
00635 }
00636
00637
00638
00639 TYPENAME SoulMates::iterator mi;
00640 for (mi = soulmates.begin(); mi != soulmates.end(); ++mi) {
00641 tri = (*mi).first.first;
00642 mate = (*mi).first.second;
00643 common_edge = (*mi).second;
00644
00645 nassertv(tri->_status == MS_paired);
00646 nassertv(mate->_status == MS_paired);
00647 tri->_status = MS_alive;
00648 mate->_status = MS_alive;
00649
00650 Strip::mate_pieces(common_edge, *tri, *mate, *_bucket);
00651 tri->_origin = MO_firstquad;
00652 }
00653
00654
00655 TYPENAME Strips::iterator next;
00656 si = _tris.begin();
00657 while (si != _tris.end()) {
00658 next = si;
00659 ++next;
00660
00661 Strips &list = choose_strip_list(*si);
00662 if (&list != &_tris) {
00663 list.splice(list.end(), _tris, si);
00664 }
00665
00666 si = next;
00667 }
00668 }
00669
00670 template <class PrimType>
00671 void MesherTempl<PrimType>::
00672 meshList(Strips &strips) {
00673 while (!strips.empty()) {
00674
00675
00676 TYPENAME Strips::iterator best = strips.begin();
00677
00678 if ((*best)._status == MS_alive) {
00679 (*best).mate(*_bucket);
00680 }
00681
00682
00683
00684
00685 Strips &list = choose_strip_list(*best);
00686 list.splice(list.end(), strips, best);
00687 }
00688 }