00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "config_builder.h"
00020
00021 template <class PrimType>
00022 INLINE MesherStrip<PrimType>::
00023 MesherStrip(const MesherStrip ©) :
00024 _prims(copy._prims),
00025 _edges(copy._edges),
00026 _verts(copy._verts),
00027 _type(copy._type),
00028 _index(copy._index),
00029 _status(copy._status),
00030 _planar(copy._planar),
00031 _plane_normal(copy._plane_normal),
00032 _plane_offset(copy._plane_offset),
00033 _row_id(copy._row_id)
00034 {
00035 }
00036
00037
00038
00039
00040
00041
00042
00043
00044 template <class PrimType>
00045 INLINE bool MesherStrip<PrimType>::
00046 is_coplanar_with(const MesherStrip &other, float threshold) const {
00047 return (coplanarity(other) <= threshold);
00048 }
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059 template <class PrimType>
00060 INLINE float MesherStrip<PrimType>::
00061 coplanarity(const MesherStrip &other) const {
00062 if (_planar && other._planar) {
00063 return 1.0 - dot(_plane_normal, other._plane_normal);
00064 } else {
00065 return 3.0;
00066 }
00067 }
00068
00069
00070
00071
00072
00073
00074
00075
00076 template <class PrimType>
00077 INLINE int MesherStrip<PrimType>::
00078 type_category() const {
00079 switch (_type) {
00080 case BPT_tri:
00081 return 1;
00082
00083 case BPT_tristrip:
00084 return 2;
00085
00086 case BPT_quad:
00087 case BPT_quadstrip:
00088 return 5;
00089
00090 default:
00091 return 10;
00092 }
00093 }
00094
00095
00096
00097
00098
00099
00100
00101
00102 template <class PrimType>
00103 INLINE void MesherStrip<PrimType>::
00104 rotate_forward() {
00105 _verts.push_back(_verts.front());
00106 _verts.pop_front();
00107 }
00108
00109
00110
00111
00112
00113
00114
00115 template <class PrimType>
00116 INLINE void MesherStrip<PrimType>::
00117 rotate_back() {
00118 _verts.push_front(_verts.back());
00119 _verts.pop_back();
00120 }
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130 template <class PrimType>
00131 INLINE TYPENAME MesherStrip<PrimType>::Edge MesherStrip<PrimType>::
00132 get_head_edge() const {
00133 TYPENAME Verts::const_iterator vi = _verts.begin();
00134 return Edge(_verts.front(), *++vi);
00135 }
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145 template <class PrimType>
00146 INLINE TYPENAME MesherStrip<PrimType>::Edge MesherStrip<PrimType>::
00147 get_tail_edge() const {
00148 TYPENAME Verts::const_reverse_iterator vi = _verts.rbegin();
00149 return Edge(*++vi, _verts.back());
00150 }
00151
00152
00153
00154
00155
00156
00157
00158
00159 template <class PrimType>
00160 INLINE bool MesherStrip<PrimType>::
00161 operator == (const MesherStrip &other) const {
00162 return this == &other;
00163 }
00164
00165
00166
00167
00168
00169
00170 template <class PrimType>
00171 INLINE bool MesherStrip<PrimType>::
00172 operator != (const MesherStrip &other) const {
00173 return !operator == (other);
00174 }
00175
00176
00177
00178
00179
00180
00181 template <class PrimType>
00182 MesherStrip<PrimType>::
00183 MesherStrip(const PrimType &prim, int index, const BuilderBucket &bucket) {
00184 _index = index;
00185 _row_id = 0;
00186 _status = MS_alive;
00187 _origin = MO_unknown;
00188 prim.has_overall_normal();
00189 _type = prim.get_type();
00190
00191
00192
00193 _prims.push_back(prim);
00194
00195 if (_type == BPT_poly) {
00196 switch (prim.get_num_verts()) {
00197 case 3:
00198 _type = BPT_tri;
00199 break;
00200
00201 case 4:
00202 _type = BPT_quad;
00203 break;
00204 }
00205 }
00206
00207 if (_type == BPT_quad) {
00208
00209
00210 _prims.push_back(prim);
00211 }
00212
00213 _planar = false;
00214
00215 if (prim.get_num_verts() >= 3) {
00216
00217 Vertexf p1 = prim.get_vertex(0).get_coord_value(bucket);
00218 Vertexf p2 = prim.get_vertex(1).get_coord_value(bucket);
00219 Vertexf p3 = prim.get_vertex(2).get_coord_value(bucket);
00220 _plane_normal = cross(p1-p2, p2-p3);
00221 float l = length(_plane_normal);
00222
00223 if (l != 0.0f) {
00224 _plane_normal /= l;
00225 _planar = true;
00226 _plane_offset = -dot(_plane_normal, p1);
00227 }
00228 }
00229 }
00230
00231
00232
00233
00234
00235
00236
00237
00238 template <class PrimType>
00239 PrimType MesherStrip<PrimType>::
00240 make_prim(const BuilderBucket &bucket) {
00241 Prim p;
00242 BuilderPrimType dest_type;
00243
00244 switch (_type) {
00245 case BPT_quad:
00246 dest_type = bucket._show_quads ? BPT_poly : BPT_tristrip;
00247 break;
00248
00249 case BPT_tristrip:
00250 case BPT_quadstrip:
00251 dest_type = BPT_tristrip;
00252 break;
00253
00254 case BPT_trifan:
00255 dest_type = BPT_trifan;
00256 break;
00257
00258 default:
00259 dest_type = _type;
00260 }
00261
00262 if (dest_type != BPT_tristrip && dest_type != BPT_trifan) {
00263
00264 p.set_attrib(_prims.front());
00265 TYPENAME Verts::iterator vi;
00266 for (vi = _verts.begin(); vi != _verts.end(); ++vi) {
00267 const Vertex *v = *vi;
00268 nassertr(v != (Vertex *)NULL, p);
00269 p.add_vertex(*v);
00270 }
00271 p.set_type(dest_type);
00272
00273 } else {
00274
00275 convert_to_type(dest_type);
00276 p.set_attrib(_prims.front());
00277
00278 BuilderPrimType type = dest_type;
00279
00280
00281
00282 TYPENAME Verts::iterator vi;
00283 TYPENAME Prims::iterator pi;
00284 pi = _prims.begin();
00285 int count = 0;
00286 for (vi = _verts.begin();
00287 vi != _verts.end() && pi != _prims.end();
00288 ++vi) {
00289 const Vertex *v = *vi;
00290 nassertr(v != (Vertex *)NULL, p);
00291
00292 if (++count >= 3) {
00293
00294
00295
00296 p.add_component(*pi);
00297 ++pi;
00298 }
00299 p.add_vertex(*v);
00300 }
00301
00302 p.set_type(type);
00303
00304
00305
00306 nassertr(vi==_verts.end(), p);
00307 nassertr(pi==_prims.end(), p);
00308 }
00309
00310 return p;
00311 }
00312
00313
00314
00315
00316
00317
00318 template <class PrimType>
00319 void MesherStrip<PrimType>::
00320 measure_sheet(const Edge *edge, int new_row, int &num_prims, int &num_rows,
00321 int first_row_id, int this_row_id, int this_row_distance) {
00322 if (new_row) {
00323
00324
00325 if (_row_id >= first_row_id) {
00326 return;
00327 }
00328 } else {
00329
00330
00331
00332 if (_row_id >= first_row_id && _row_distance <= this_row_distance) {
00333 return;
00334 }
00335 }
00336
00337 num_prims += _prims.size();
00338 if (new_row) {
00339 ++num_rows;
00340 this_row_id = first_row_id + num_rows - 1;
00341 }
00342
00343 _row_id = this_row_id;
00344
00345 TYPENAME Edges::iterator ei;
00346 TYPENAME Edge::Strips::iterator si;
00347
00348 if (_type == BPT_quad) {
00349
00350
00351
00352 const Vertex *a = edge->_a;
00353 const Vertex *b = edge->_b;
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377 for (int secondary = 0; secondary <= 1; secondary++) {
00378
00379
00380
00381 int want_count;
00382 if (secondary) {
00383 want_count = new_row ? 0 : 1;
00384 } else {
00385 want_count = new_row ? 1 : 0;
00386 }
00387
00388 for (ei = _edges.begin(); ei != _edges.end(); ++ei) {
00389 int common_verts =
00390 ((*ei)->_a == a || (*ei)->_a == b) +
00391 ((*ei)->_b == a || (*ei)->_b == b);
00392
00393 if (common_verts == want_count) {
00394
00395
00396
00397
00398 TYPENAME Edge::Strips &strips = (*ei)->_strips;
00399 MesherStrip *mate = NULL;
00400 for (si = strips.begin(); si != strips.end(); ++si) {
00401 if ((*si)->_row_id < first_row_id) {
00402 if (mate==NULL || pick_sheet_mate(**si, *mate)) {
00403 mate = *si;
00404 }
00405 }
00406 }
00407 if (mate!=NULL) {
00408 mate->measure_sheet(*ei, secondary, num_prims, num_rows,
00409 first_row_id, this_row_id,
00410 this_row_distance + secondary);
00411 }
00412 }
00413 }
00414 }
00415
00416 } else {
00417
00418
00419 nassertv(_type != BPT_tri);
00420
00421
00422 nassertv(_type == BPT_tristrip || _type == BPT_quadstrip);
00423
00424
00425
00426
00427 for (ei = _edges.begin(); ei != _edges.end(); ++ei) {
00428 if (!(*ei)->matches(*edge)) {
00429
00430
00431 TYPENAME Edge::Strips &strips = (*ei)->_strips;
00432 MesherStrip *mate = NULL;
00433 for (si = strips.begin(); si != strips.end(); ++si) {
00434 if ((*si)->_row_id < first_row_id) {
00435 if (mate==NULL || pick_sheet_mate(**si, *mate)) {
00436 mate = *si;
00437 }
00438 }
00439 }
00440 if (mate!=NULL) {
00441 mate->measure_sheet(*ei, false, num_prims, num_rows,
00442 first_row_id, this_row_id, this_row_distance);
00443 }
00444 }
00445 }
00446 }
00447 }
00448
00449
00450
00451
00452
00453
00454
00455 template <class PrimType>
00456 void MesherStrip<PrimType>::
00457 cut_sheet(int first_row_id, int do_mate, const BuilderBucket &bucket) {
00458 TYPENAME Edges::iterator ei;
00459 TYPENAME Edge::Strips::iterator si;
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469 typedef plist<MesherStrip *> StripPtrs;
00470 StripPtrs strip_ptrs;
00471
00472 for (ei = _edges.begin(); ei != _edges.end(); ++ei) {
00473 TYPENAME Edge::Strips &strips = (*ei)->_strips;
00474 for (si = strips.begin(); si != strips.end(); ++si) {
00475 if ((*si)->_row_id > _row_id) {
00476
00477 strip_ptrs.push_back(*si);
00478 }
00479 }
00480 }
00481
00482
00483
00484
00485 TYPENAME StripPtrs::iterator spi;
00486 for (spi = strip_ptrs.begin(); spi != strip_ptrs.end(); ++spi) {
00487 if ((*spi)->_status == MS_alive) {
00488 (*spi)->cut_sheet(first_row_id, true, bucket);
00489 }
00490 }
00491
00492
00493 if (do_mate && _status == MS_alive) {
00494
00495 int not_any;
00496 do {
00497 not_any = true;
00498
00499 ei = _edges.begin();
00500 while (ei != _edges.end() && not_any) {
00501 TYPENAME Edge::Strips &strips = (*ei)->_strips;
00502 si = strips.begin();
00503 while (si != strips.end() && not_any) {
00504 if (*si != this && (*si)->_row_id == _row_id) {
00505
00506 not_any = false;
00507 MesherStrip *mate = *si;
00508
00509
00510
00511
00512
00513
00514
00515 mate->cut_sheet(first_row_id, false, bucket);
00516
00517 if (_status == MS_alive && mate->_status == MS_alive) {
00518
00519
00520
00521
00522 mate_pieces(*ei, *this, *mate, bucket);
00523 }
00524 }
00525 if (not_any) {
00526 ++si;
00527 }
00528 }
00529 if (not_any) {
00530 ++ei;
00531 }
00532 }
00533 } while (!not_any);
00534
00535
00536 _row_id = -first_row_id;
00537 }
00538 }
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551 template <class PrimType>
00552 bool MesherStrip<PrimType>::
00553 mate(const BuilderBucket &bucket) {
00554
00555
00556 nassertr(_status == MS_alive, false);
00557
00558 MesherStrip *mate;
00559 Edge *common_edge;
00560
00561 if (!find_ideal_mate(mate, common_edge, bucket)) {
00562
00563 _status = MS_done;
00564
00565 return false;
00566 }
00567
00568 nassertr(!mate->_prims.empty(), false);
00569 nassertr(!mate->_verts.empty(), false);
00570
00571 mate_pieces(common_edge, *this, *mate, bucket);
00572
00573
00574
00575 return true;
00576 }
00577
00578
00579
00580
00581
00582
00583
00584
00585 template <class PrimType>
00586 bool MesherStrip<PrimType>::
00587 find_ideal_mate(MesherStrip *&mate, Edge *&common_edge,
00588 const BuilderBucket &bucket) {
00589 TYPENAME Edges::iterator ei;
00590
00591 mate = NULL;
00592 common_edge = NULL;
00593
00594 for (ei = _edges.begin(); ei != _edges.end(); ++ei) {
00595 TYPENAME Edge::Strips &strips = (*ei)->_strips;
00596 TYPENAME Edge::Strips::iterator si;
00597 for (si = strips.begin(); si != strips.end(); ++si) {
00598 if (*si != this) {
00599 if (mate==NULL || pick_mate(**si, *mate, **ei, *common_edge,
00600 bucket)) {
00601 mate = *si;
00602 common_edge = *ei;
00603 }
00604 }
00605 }
00606 }
00607
00608 return (mate!=NULL);
00609 }
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620 template <class PrimType>
00621 bool MesherStrip<PrimType>::
00622 mate_pieces(Edge *common_edge, MesherStrip &front, MesherStrip &back,
00623 const BuilderBucket &bucket) {
00624 nassertr(front._status == MS_alive, false);
00625 nassertr(back._status == MS_alive, false);
00626 nassertr(&front != &back, false);
00627
00628 bool success = true;
00629
00630
00631 bool remove_sides = true;
00632
00633 bool is_coplanar = front.is_coplanar_with(back, bucket._coplanar_threshold);
00634
00635 if (front._type==BPT_tri && back._type==BPT_tri) {
00636
00637 if (is_coplanar && bucket._retesselate_coplanar &&
00638 front._prims.front() == back._prims.front() &&
00639 convex_quad(common_edge, front, back, bucket)) {
00640
00641
00642
00643 front._type = BPT_quad;
00644
00645
00646
00647 const Vertex *new_vert = back.find_uncommon_vertex(common_edge);
00648
00649
00650
00651
00652 TYPENAME Verts::iterator a = front._verts.begin();
00653 TYPENAME Verts::iterator b = a;
00654 ++b;
00655
00656 if (common_edge->contains_vertex(*a)) {
00657 if (common_edge->contains_vertex(*b)) {
00658
00659 front._verts.insert(b, new_vert);
00660 } else {
00661
00662 front._verts.push_back(new_vert);
00663 }
00664 } else {
00665
00666 ++b;
00667 front._verts.insert(b, new_vert);
00668 }
00669
00670 front._prims.splice(front._prims.end(), back._prims);
00671 back._verts.clear();
00672
00673
00674
00675 remove_sides = false;
00676
00677 } else {
00678
00679 front._type = BPT_tristrip;
00680
00681 const Vertex *new_vert = back.find_uncommon_vertex(common_edge);
00682 front.rotate_to_back(common_edge);
00683
00684 front._verts.push_back(new_vert);
00685 front._prims.splice(front._prims.end(), back._prims);
00686 back._verts.clear();
00687 }
00688
00689 } else if ((front._type==BPT_quad || front._type==BPT_quadstrip) &&
00690 (back._type==BPT_quad || back._type==BPT_quadstrip)) {
00691
00692
00693
00694
00695 success = mate_strips(common_edge, front, back, BPT_quadstrip);
00696
00697 if (!success) {
00698
00699
00700
00701
00702 common_edge->remove(&front);
00703 common_edge->remove(&back);
00704 }
00705
00706 } else {
00707
00708
00709
00710
00711
00712
00713
00714 success = mate_strips(common_edge, front, back, BPT_tristrip);
00715
00716 if (!success) {
00717
00718
00719
00720
00721 success = mate_strips(common_edge, back, front, BPT_tristrip);
00722
00723 if (success) {
00724
00725 front._verts.splice(front._verts.end(), back._verts);
00726 front._prims.splice(front._prims.end(), back._prims);
00727 } else {
00728
00729
00730 common_edge->remove(&front);
00731 common_edge->remove(&back);
00732 }
00733 }
00734 }
00735
00736 if (success) {
00737 front.combine_edges(back, remove_sides);
00738 if (!remove_sides) {
00739
00740
00741 common_edge->remove(&front);
00742 }
00743
00744 nassertr(back._prims.empty(), false);
00745 nassertr(back._verts.empty(), false);
00746
00747
00748 back._status = MS_dead;
00749
00750
00751
00752 front._planar = is_coplanar;
00753 front._origin = MO_mate;
00754 }
00755
00756 return success;
00757 }
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773 template <class PrimType>
00774 bool MesherStrip<PrimType>::
00775 mate_strips(Edge *common_edge, MesherStrip &front, MesherStrip &back,
00776 BuilderPrimType type) {
00777
00778
00779 if (front._type==BPT_tri || front._type==BPT_quad) {
00780 front.rotate_to_back(common_edge);
00781 }
00782 if (back._type==BPT_tri || back._type==BPT_quad) {
00783 back.rotate_to_front(common_edge);
00784 }
00785
00786 bool reverse_front = common_edge->matches(front.get_head_edge());
00787 bool reverse_back = !common_edge->matches(back.get_head_edge());
00788
00789 bool invert_front = false;
00790 bool invert_back = false;
00791
00792 if (reverse_front && front.is_odd()) {
00793
00794
00795
00796 if (!front.can_invert()) {
00797 return false;
00798 }
00799 invert_front = true;
00800 }
00801
00802 if (must_invert(front, back, reverse_back, type)) {
00803 if (!back.can_invert()) {
00804 return false;
00805 }
00806 invert_back = true;
00807 back.invert();
00808 }
00809
00810 if (invert_front) {
00811 front.invert();
00812 }
00813
00814 if (reverse_front) {
00815 reverse(front._verts.begin(), front._verts.end());
00816 reverse(front._prims.begin(), front._prims.end());
00817 }
00818
00819 if (reverse_back) {
00820 reverse(back._verts.begin(), back._verts.end());
00821 reverse(back._prims.begin(), back._prims.end());
00822 }
00823
00824 bool will_reverse = front.would_reverse_tail(type);
00825 bool is_headtotail = (front.get_tail_edge() == back.get_head_edge());
00826 if (will_reverse == is_headtotail) {
00827
00828
00829 if (reverse_back) {
00830 reverse(back._verts.begin(), back._verts.end());
00831 reverse(back._prims.begin(), back._prims.end());
00832 }
00833 if (invert_back) {
00834 back.invert();
00835 }
00836 if (reverse_front) {
00837 reverse(front._verts.begin(), front._verts.end());
00838 reverse(front._prims.begin(), front._prims.end());
00839 }
00840 if (invert_front) {
00841 front.invert();
00842 }
00843 return false;
00844 }
00845
00846 front.convert_to_type(type);
00847 back.convert_to_type(type);
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878 front._verts.pop_back();
00879 front._verts.pop_back();
00880 front._verts.splice(front._verts.end(), back._verts);
00881 front._prims.splice(front._prims.end(), back._prims);
00882
00883 return true;
00884 }
00885
00886
00887
00888
00889
00890
00891
00892
00893 template <class PrimType>
00894 bool MesherStrip<PrimType>::
00895 must_invert(const MesherStrip &front, const MesherStrip &back,
00896 bool will_reverse_back, BuilderPrimType type) {
00897 bool invert = false;
00898
00899 if ((front._type == BPT_quad || front._type == BPT_quadstrip) &&
00900 type == BPT_tristrip) {
00901
00902
00903
00904 } else if (front.is_odd()) {
00905
00906 invert = !invert;
00907 }
00908
00909 if (will_reverse_back) {
00910
00911
00912
00913 if (back.is_odd()) {
00914
00915
00916 invert = !invert;
00917 }
00918 }
00919
00920 return invert;
00921 }
00922
00923
00924
00925
00926
00927
00928
00929
00930 template <class PrimType>
00931 bool MesherStrip<PrimType>::
00932 convex_quad(Edge *common_edge, MesherStrip &front, MesherStrip &back,
00933 const BuilderBucket &bucket) {
00934
00935
00936
00937 const Vertex *a = front.find_uncommon_vertex(common_edge);
00938 const Vertex *b = back.find_uncommon_vertex(common_edge);
00939 nassertr(a!=NULL && b!=NULL, false);
00940
00941 Vertexf a3, b3, c3, d3;
00942 a3 = a->get_coord_value(bucket);
00943 b3 = b->get_coord_value(bucket);
00944
00945 c3 = common_edge->_a->get_coord_value(bucket);
00946 d3 = common_edge->_b->get_coord_value(bucket);
00947
00948
00949
00950
00951
00952 nassertr(front._planar, false);
00953
00954 LVector3f &n = front._plane_normal;
00955 int xi, yi;
00956
00957
00958 if (fabs(n[0]) > fabs(n[1])) {
00959 if (fabs(n[0]) > fabs(n[2])) {
00960 xi = 1;
00961 yi = 2;
00962 } else {
00963 xi = 0;
00964 yi = 1;
00965 }
00966 } else {
00967 if (fabs(n[1]) > fabs(n[2])) {
00968 xi = 0;
00969 yi = 2;
00970 } else {
00971 xi = 0;
00972 yi = 1;
00973 }
00974 }
00975
00976 LVecBase2f a2, b2, c2, d2;
00977 a2.set(a3[xi], a3[yi]);
00978 b2.set(b3[xi], b3[yi]);
00979 c2.set(c3[xi], c3[yi]);
00980 d2.set(d3[xi], d3[yi]);
00981
00982
00983
00984
00985
00986
00987
00988
00989 double A = (b2[1] - a2[1]);
00990 double B = (a2[0] - b2[0]);
00991 double C = -(A*b2[0] + B*b2[1]);
00992
00993
00994
00995
00996
00997
00998 double t = - ((A*c2[0] + B*c2[1]) + C) / (A*(d2[0]-c2[0]) + B*(d2[1]-c2[1]));
00999
01000
01001 return (0.0 <= t && t <= 1.0);
01002 }
01003
01004
01005
01006
01007
01008
01009 template <class PrimType>
01010 int MesherStrip<PrimType>::
01011 count_neighbors() const {
01012 int count = 0;
01013 TYPENAME Edges::const_iterator ei;
01014
01015 for (ei = _edges.begin(); ei != _edges.end(); ++ei) {
01016 count += (*ei)->_strips.size();
01017 }
01018 return count;
01019 }
01020
01021
01022
01023
01024
01025
01026 template <class PrimType>
01027 ostream &MesherStrip<PrimType>::
01028 show_neighbors(ostream &out) const {
01029 TYPENAME Edges::const_iterator ei;
01030 TYPENAME Edge::Strips::const_iterator si;
01031
01032 for (ei = _edges.begin(); ei != _edges.end(); ++ei) {
01033 for (si = (*ei)->_strips.begin();
01034 si != (*ei)->_strips.end();
01035 ++si) {
01036 out << " " << (*si)->_index;
01037 }
01038 }
01039 return out;
01040 }
01041
01042
01043
01044
01045
01046
01047
01048 template <class PrimType>
01049 const TYPENAME MesherStrip<PrimType>::Vertex *MesherStrip<PrimType>::
01050 find_uncommon_vertex(const Edge *edge) const {
01051 const Vertex *a = edge->_a;
01052 const Vertex *b = edge->_b;
01053
01054 TYPENAME Edges::const_iterator ei;
01055 for (ei = _edges.begin(); ei != _edges.end(); ++ei) {
01056 Edge *e = (*ei);
01057
01058 if (e->_a != a && e->_a != b) {
01059 return e->_a;
01060 } else if (e->_b != a && e->_b != b) {
01061 return e->_b;
01062 }
01063 }
01064
01065 return NULL;
01066 }
01067
01068
01069
01070
01071
01072
01073
01074
01075 template <class PrimType>
01076 const TYPENAME MesherStrip<PrimType>::Edge *MesherStrip<PrimType>::
01077 find_opposite_edge(const Vertex *vertex) const {
01078 TYPENAME Edges::const_iterator ei;
01079 for (ei = _edges.begin(); ei != _edges.end(); ++ei) {
01080 Edge *e = (*ei);
01081 if (!e->contains_vertex(vertex)) {
01082 return e;
01083 }
01084 }
01085
01086 return NULL;
01087 }
01088
01089
01090
01091
01092
01093
01094
01095
01096 template <class PrimType>
01097 const TYPENAME MesherStrip<PrimType>::Edge *MesherStrip<PrimType>::
01098 find_opposite_edge(const Edge *edge) const {
01099 const Vertex *a = edge->_a;
01100 const Vertex *b = edge->_b;
01101
01102 TYPENAME Edges::const_iterator ei;
01103 for (ei = _edges.begin(); ei != _edges.end(); ++ei) {
01104 Edge *e = (*ei);
01105 if (!e->contains_vertex(a) && !e->contains_vertex(b)) {
01106 return e;
01107 }
01108 }
01109
01110 return NULL;
01111 }
01112
01113
01114
01115
01116
01117
01118
01119
01120 template <class PrimType>
01121 const TYPENAME MesherStrip<PrimType>::Edge *MesherStrip<PrimType>::
01122 find_adjacent_edge(const Edge *edge) const {
01123 const Vertex *a = edge->_a;
01124 const Vertex *b = edge->_b;
01125
01126 TYPENAME Edges::const_iterator ei;
01127 for (ei = _edges.begin(); ei != _edges.end(); ++ei) {
01128 Edge *e = (*ei);
01129 if (e->contains_vertex(a) != e->contains_vertex(b)) {
01130 return e;
01131 }
01132 }
01133
01134 return NULL;
01135 }
01136
01137
01138
01139
01140
01141
01142
01143 template <class PrimType>
01144 void MesherStrip<PrimType>::
01145 rotate_to_front(const Edge *edge) {
01146 const Vertex *a = edge->_a;
01147 const Vertex *b = edge->_b;
01148
01149
01150 if (_verts.front() == a || _verts.front() == b) {
01151 TYPENAME Verts::iterator vi = _verts.begin();
01152 ++vi;
01153 if (*vi == a || *vi == b) {
01154
01155 return;
01156 }
01157
01158
01159 rotate_back();
01160
01161 } else {
01162
01163 int num_verts = _verts.size();
01164 while (_verts.front() != a && _verts.front() != b) {
01165
01166 num_verts--;
01167 nassertv(num_verts > 0);
01168 rotate_forward();
01169 }
01170 }
01171
01172
01173 TYPENAME Verts::iterator vi = _verts.begin();
01174 ++vi;
01175 nassertv(*vi == a || *vi == b);
01176 }
01177
01178
01179
01180
01181
01182
01183
01184 template <class PrimType>
01185 void MesherStrip<PrimType>::
01186 rotate_to_back(const Edge *edge) {
01187 const Vertex *a = edge->_a;
01188 const Vertex *b = edge->_b;
01189
01190
01191 if (_verts.back() == a || _verts.back() == b) {
01192 TYPENAME Verts::reverse_iterator vi = _verts.rbegin();
01193 ++vi;
01194 if (*vi == a || *vi == b) {
01195
01196 return;
01197 }
01198
01199
01200 rotate_forward();
01201
01202 } else {
01203
01204 int num_verts = _verts.size();
01205 while (_verts.back() != a && _verts.back() != b) {
01206
01207 num_verts--;
01208 nassertv(num_verts > 0);
01209 rotate_back();
01210 }
01211 }
01212
01213
01214 TYPENAME Verts::reverse_iterator vi = _verts.rbegin();
01215 ++vi;
01216 nassertv(*vi == a || *vi == b);
01217 }
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227 template <class PrimType>
01228 bool MesherStrip<PrimType>::
01229 can_invert() const {
01230 return (_type==BPT_quadstrip || _type==BPT_quad);
01231 }
01232
01233
01234
01235
01236
01237
01238
01239
01240 template <class PrimType>
01241 bool MesherStrip<PrimType>::
01242 invert() {
01243 if (!can_invert()) {
01244 return false;
01245 }
01246 TYPENAME Verts::iterator vi, vi2;
01247 vi = _verts.begin();
01248 while (vi != _verts.end()) {
01249 vi2 = vi;
01250 ++vi2;
01251 nassertr(vi2 != _verts.end(), false);
01252
01253
01254 const Vertex *t = *vi2;
01255 *vi2 = *vi;
01256 *vi = t;
01257
01258
01259 vi = vi2;
01260 ++vi;
01261 }
01262 return true;
01263 }
01264
01265
01266
01267
01268
01269
01270
01271 template <class PrimType>
01272 bool MesherStrip<PrimType>::
01273 is_odd() const {
01274 if (_type==BPT_quadstrip || _type==BPT_quad) {
01275
01276
01277 return (_verts.size()%4 == 0);
01278 } else {
01279
01280
01281 return (_verts.size()%2 == 1);
01282 }
01283 }
01284
01285
01286
01287
01288
01289
01290
01291 template <class PrimType>
01292 bool MesherStrip<PrimType>::
01293 would_reverse_tail(BuilderPrimType wantType) const {
01294 bool reverse = false;
01295
01296 if (_type==wantType) {
01297 return false;
01298 }
01299 if (wantType==BPT_tristrip) {
01300 switch (_type) {
01301 case BPT_tri:
01302 case BPT_tristrip:
01303 break;
01304
01305 case BPT_quad:
01306 case BPT_quadstrip:
01307
01308
01309 reverse = (_verts.size()%4==0);
01310 break;
01311
01312 default:
01313 builder_cat.fatal() << "Invalid conversion!\n";
01314 abort();
01315 break;
01316 }
01317
01318 } else if (wantType==BPT_quadstrip) {
01319 switch (_type) {
01320 case BPT_quad:
01321 case BPT_quadstrip:
01322 break;
01323
01324 case BPT_tri:
01325 case BPT_tristrip:
01326
01327
01328 default:
01329 builder_cat.fatal() << "Invalid conversion!\n";
01330 abort();
01331 break;
01332 }
01333 }
01334
01335 return reverse;
01336 }
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346 template <class PrimType>
01347 void MesherStrip<PrimType>::
01348 convert_to_type(BuilderPrimType wantType) {
01349 TYPENAME Verts::iterator vi, vi2;
01350 int even;
01351
01352 if (_type==wantType) {
01353 return;
01354 }
01355 if (wantType==BPT_tristrip) {
01356 switch (_type) {
01357 case BPT_tri:
01358 case BPT_tristrip:
01359 break;
01360
01361 case BPT_quad:
01362 case BPT_quadstrip:
01363
01364
01365
01366 vi = _verts.begin();
01367 even = 0;
01368 while (vi != _verts.end()) {
01369 vi2 = vi;
01370 ++vi2;
01371 nassertv(vi2 != _verts.end());
01372
01373
01374 if (even) {
01375 const Vertex *t = *vi2;
01376 *vi2 = *vi;
01377 *vi = t;
01378 }
01379
01380
01381 vi = vi2;
01382 ++vi;
01383 even = !even;
01384 }
01385 break;
01386
01387 default:
01388 builder_cat.fatal() << "Invalid conversion!\n";
01389 abort();
01390 }
01391
01392 } else if (wantType==BPT_quadstrip) {
01393 switch (_type) {
01394 case BPT_quad:
01395 case BPT_quadstrip:
01396 break;
01397
01398 case BPT_tri:
01399 case BPT_tristrip:
01400
01401
01402 default:
01403 builder_cat.fatal() << "Invalid conversion!\n";
01404 abort();
01405 }
01406 }
01407
01408 _type = wantType;
01409 }
01410
01411
01412
01413
01414
01415
01416
01417
01418 template <class PrimType>
01419 void MesherStrip<PrimType>::
01420 combine_edges(MesherStrip<PrimType> &other, int removeSides) {
01421 TYPENAME Edges::iterator ei;
01422 for (ei = other._edges.begin(); ei != other._edges.end(); ++ei) {
01423 (*ei)->change_strip(&other, this);
01424 }
01425
01426 _edges.splice(_edges.end(), other._edges);
01427
01428 if (removeSides) {
01429
01430
01431 Edge head = get_head_edge();
01432 Edge tail = get_tail_edge();
01433
01434 if (!is_odd()) {
01435
01436
01437 tail = Edge(tail._b, tail._a);
01438 }
01439
01440 Edges junk_edges;
01441
01442 TYPENAME Edges::iterator next_ei;
01443 ei = _edges.begin();
01444 while (ei != _edges.end()) {
01445 next_ei = ei;
01446 ++next_ei;
01447
01448
01449 if (!(**ei == head) && !(**ei == tail)) {
01450
01451
01452
01453 junk_edges.splice(junk_edges.end(), _edges, ei);
01454 }
01455 ei = next_ei;
01456 }
01457
01458
01459 for (ei = junk_edges.begin(); ei != junk_edges.end(); ++ei) {
01460 (*ei)->remove(this);
01461 }
01462 }
01463 }
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473 template <class PrimType>
01474 void MesherStrip<PrimType>::
01475 remove_all_edges() {
01476
01477
01478 Edges junk_edges;
01479 junk_edges.splice(junk_edges.end(), _edges);
01480
01481
01482 TYPENAME Edges::iterator ei;
01483 for (ei = junk_edges.begin(); ei != junk_edges.end(); ++ei) {
01484 (*ei)->remove(this);
01485 }
01486 }
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496 template <class PrimType>
01497 bool MesherStrip<PrimType>::
01498 pick_mate(const MesherStrip &a_strip, const MesherStrip &b_strip,
01499 const Edge &a_edge, const Edge &b_edge,
01500 const BuilderBucket &bucket) const {
01501
01502
01503
01504
01505
01506 int a_cat = a_strip.type_category();
01507 int b_cat = b_strip.type_category();
01508 if (a_cat != b_cat) {
01509 int me_cat = type_category();
01510 return abs(a_cat - me_cat) < abs(b_cat - me_cat);
01511 }
01512
01513
01514
01515 if (_type == BPT_tri && a_strip._type == BPT_tri &&
01516 b_strip._type == BPT_tri) {
01517
01518
01519
01520
01521
01522
01523
01524 double a_coplanar = coplanarity(a_strip);
01525 double b_coplanar = coplanarity(b_strip);
01526 double coplanar_diff = a_coplanar - b_coplanar;
01527
01528 double a_length = a_edge.compute_length(bucket);
01529 double b_length = b_edge.compute_length(bucket);
01530 double length_diff = (a_length - b_length) / (a_length + b_length);
01531
01532
01533 double sum = 4.0 * coplanar_diff - 1.0 * length_diff;
01534 return sum < 0;
01535 }
01536
01537
01538 if (a_strip._prims.size() != b_strip._prims.size()) {
01539 return a_strip._prims.size() < b_strip._prims.size();
01540 }
01541
01542
01543 return a_strip.count_neighbors() < b_strip.count_neighbors();
01544 }
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554
01555 template <class PrimType>
01556 bool MesherStrip<PrimType>::
01557 pick_sheet_mate(const MesherStrip &a_strip, const MesherStrip &b_strip) const {
01558
01559 if (_planar && a_strip._planar && b_strip._planar) {
01560 float a_diff = dot(_plane_normal, a_strip._plane_normal);
01561 float b_diff = dot(_plane_normal, b_strip._plane_normal);
01562
01563 if (fabs(a_diff - b_diff) > 0.0001f) {
01564 return a_diff > b_diff;
01565 }
01566 }
01567
01568
01569 int a_cat = a_strip.type_category();
01570 int b_cat = b_strip.type_category();
01571 if (a_cat != b_cat) {
01572 int me_cat = type_category();
01573 return abs(a_cat - me_cat) < abs(b_cat - me_cat);
01574 }
01575
01576
01577 return false;
01578 }
01579
01580
01581
01582
01583
01584
01585 template <class PrimType>
01586 ostream &MesherStrip<PrimType>::
01587 output(ostream &out) const {
01588 switch (_status) {
01589 case MS_alive:
01590 break;
01591
01592 case MS_dead:
01593 out << "Dead ";
01594 break;
01595
01596 case MS_done:
01597 out << "Done ";
01598 break;
01599
01600 default:
01601 out << "Unknown status ";
01602 }
01603
01604 switch (_type) {
01605 case BPT_tri:
01606 out << "Tri";
01607 break;
01608
01609 case BPT_quad:
01610 out << "Quad";
01611 break;
01612
01613 case BPT_tristrip:
01614 out << "TriStrip";
01615 break;
01616
01617 case BPT_trifan:
01618 out << "TriFan";
01619 break;
01620
01621 case BPT_quadstrip:
01622 out << "QuadStrip";
01623 break;
01624
01625 default:
01626 out << "Unknown";
01627 }
01628
01629 if (_planar) {
01630 out << " (planar)";
01631 }
01632
01633 out << " " << _index << " [";
01634
01635 TYPENAME Verts::const_iterator vi;
01636 for (vi = _verts.begin(); vi != _verts.end(); vi++) {
01637 out << " " << **vi;
01638 }
01639 out << " ]: " << _prims.size()
01640 << " prims, " << count_neighbors() << " neighbors";
01641
01642 show_neighbors(out);
01643
01644 out << " edges";
01645 TYPENAME Edges::const_iterator ei;
01646 for (ei = _edges.begin(); ei != _edges.end(); ei++) {
01647 out << " " << (void *)(*ei);
01648 }
01649
01650 return out << ".";
01651 }
01652