Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

panda/src/builder/mesherStrip.I

Go to the documentation of this file.
00001 // Filename: mesherStrip.I
00002 // Created by:  drose (16Sep97)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 
00019 #include "config_builder.h"
00020 
00021 template <class PrimType>
00022 INLINE MesherStrip<PrimType>::
00023 MesherStrip(const MesherStrip &copy) :
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 //     Function: MesherStrip::is_coplanar_with
00040 //       Access: Public
00041 //  Description: Returns true if the strip and the other strip are
00042 //               coplanar.
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 //     Function: MesherStrip::coplanarity
00052 //       Access: Public
00053 //  Description: Returns the degree to which the two strips are
00054 //               coplanar.  0.0 is exactly coplanar; numbers somewhat
00055 //               larger than zero indicate less coplanar.  1.0 is
00056 //               at right angles; 2.0 is exactly backfacing.  If
00057 //               either strip is not itself planar, 3.0 is returned.
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 //     Function: MesherStrip::type_category
00071 //       Access: Public
00072 //  Description: Returns an integer which gives a heuristic about the
00073 //               similarity of different strip types.  In general,
00074 //               closer numbers are more similar.
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 //     Function: MesherStrip::rotate_forward
00098 //       Access: Public
00099 //  Description: Rotates a triangle or quad by bringing its second
00100 //               vertex to the front.
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 //     Function: MesherStrip::rotate_back
00111 //       Access: Public
00112 //  Description: Rotates a triangle or quad by bringing its second
00113 //               vertex to the front.
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 //     Function: MesherStrip::get_head_edge
00125 //       Access: Public
00126 //  Description: Returns an Edge which represents the leading edge in
00127 //               the quadstrip or tristrip.  This Edge will not have
00128 //               pointer equality with any shared Edge.
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 //     Function: MesherStrip::get_tail_edge
00140 //       Access: Public
00141 //  Description: Returns an Edge which represents the trailing edge in
00142 //               the quadstrip or tristrip.  This Edge will not have
00143 //               pointer equality with any shared Edge.
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 //     Function: MesherStrip::operator ==
00154 //       Access: Public
00155 //  Description: Defines equality for strips.  This actually tests
00156 //               only pointer equality; it's used only when removing a
00157 //               strip from the list.
00158 ////////////////////////////////////////////////////////////////////
00159 template <class PrimType>
00160 INLINE bool MesherStrip<PrimType>::
00161 operator == (const MesherStrip &other) const {
00162   return this == &other;
00163 }
00164 
00165 ////////////////////////////////////////////////////////////////////
00166 //     Function: MesherStrip::operator !=
00167 //       Access: Public
00168 //  Description:
00169 ////////////////////////////////////////////////////////////////////
00170 template <class PrimType>
00171 INLINE bool MesherStrip<PrimType>::
00172 operator != (const MesherStrip &other) const {
00173   return !operator == (other);
00174 }
00175 
00176 ////////////////////////////////////////////////////////////////////
00177 //     Function: MesherStrip::Constructor
00178 //       Access: Public
00179 //  Description:
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();  // Force the prim to update its overall flags.
00189   _type = prim.get_type();
00190 
00191   // We save only the prim's overall properties in the _prims
00192   // array.  The vertices get re-added later by Mesher::add_prim().
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     // A quad has two internal triangles; we therefore push the prim
00209     // properties twice.
00210     _prims.push_back(prim);
00211   }
00212 
00213   _planar = false;
00214 
00215   if (prim.get_num_verts() >= 3) {
00216     // However, we will examine the vertices to determine the plane equation.
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 //     Function: MesherStrip::make_prim
00234 //       Access: Public
00235 //  Description: Creates a PrimType element corresponding to the strip
00236 //               represented by this node.
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     // The easy case: a simple primitive.
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     // The harder case: a tristrip of some kind.
00275     convert_to_type(dest_type);
00276     p.set_attrib(_prims.front());
00277 
00278     BuilderPrimType type = dest_type;
00279 
00280     // Now store all the vertices, as well as each individual
00281     // triangle's attributes.
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         // Beginning with the third vertex, we increment pi.  Thus, the
00294         // first two vertices stand alone, then each vertex beginning
00295         // with the third completes a triangle.
00296         p.add_component(*pi);
00297         ++pi;
00298       }
00299       p.add_vertex(*v);
00300     }
00301 
00302     p.set_type(type);
00303 
00304     // If either of these fail, there weren't num_prims + 2 vertices in
00305     // the tristrip!
00306     nassertr(vi==_verts.end(), p);
00307     nassertr(pi==_prims.end(), p);
00308   }
00309 
00310   return p;
00311 }
00312 
00313 ////////////////////////////////////////////////////////////////////
00314 //     Function: MesherStrip::measure_sheet
00315 //       Access: Public
00316 //  Description:
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     // If we would create a new row by stepping here, we won't stay if
00324     // there was any other row already defined here.
00325     if (_row_id >= first_row_id) {
00326       return;
00327     }
00328   } else {
00329     // On the other hand, if this is a continuation of the current
00330     // row, we'll stay if the other row had to travel farther to get
00331     // here.
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     // If this is a quad, it has four neighbors: two in the direction
00350     // we are testing, and two in an orthagonal direction.
00351 
00352     const Vertex *a = edge->_a;
00353     const Vertex *b = edge->_b;
00354 
00355     // We use these vertices to differentiate the edges that run in
00356     // our primary direction from those in the secondary direction.
00357     // For each edge, we count the number of vertices that the edge
00358     // shares with our starting edge.  There are then three cases:
00359 
00360     // (a) The edge shares two vertices.  It is the direction we came
00361     // from; forget it.
00362 
00363     // (b) The edge shares one vertex.  It is at right angles to our
00364     // starting edge.  This is the primary direction if new_row is
00365     // true, and the secondary direction if new_row is false.
00366 
00367     // (c) The edge shares no vertices.  It is directly opposite our
00368     // starting edge.  This is the primary direction if new_row is
00369     // false, and the secondary direction if new_row is true.
00370 
00371 
00372     // Here's a silly little for loop that executes the following code
00373     // twice: once with secondary == 0, and once with secondary == 1.
00374     // This is because we want to find all the primary edges first,
00375     // and then all the secondary edges.
00376 
00377     for (int secondary = 0; secondary <= 1; secondary++) {
00378       // How many common vertices are we looking for this pass (see
00379       // above)?
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           // Here's the edge.  Look at all its connections.  Hopefully,
00395           // there will only be one besides ourselves, but there may be
00396           // more.  Pick the best.
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     // Otherwise, this is not a quad.  It's certainly not a triangle,
00418     // because we've built all the single triangles already.
00419     nassertv(_type != BPT_tri);
00420 
00421     // Therefore, it must be a tristrip or quadstrip.
00422     nassertv(_type == BPT_tristrip || _type == BPT_quadstrip);
00423 
00424     // Since it's a strip, it only has two neighbors: the one we came
00425     // from, and the other one.  Find the other one.
00426 
00427     for (ei = _edges.begin(); ei != _edges.end(); ++ei) {
00428       if (!(*ei)->matches(*edge)) {
00429         // Here's the edge.  Same drill as above.
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 //     Function: MesherStrip::cut_sheet
00452 //       Access: Public
00453 //  Description:
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   // First, start the process going on any neighbors that belong to a
00462   // later row.  (We must do these first, because we'll change our
00463   // neighbor list when we start to mate.)
00464 
00465   // We need to build a temporary list of neighbors first, because
00466   // calling cut_sheet() recursively will start things mating, and
00467   // could damage our edge list.
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         // Here's a different row in the sheet!
00477         strip_ptrs.push_back(*si);
00478       }
00479     }
00480   }
00481 
00482   // Now walk the temporary list and do some damage.  We pass do_mate
00483   // = true to each of these neighbors, because as far as we know,
00484   // they're the first nodes of a particular row.
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     // Now mate like a bunny until we don't have any more eligible mates.
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             // Here's one!
00506             not_any = false;
00507             MesherStrip *mate = *si;
00508 
00509             // We also recurse on these guys so they can spread the
00510             // word to their own neighbors.  This time we don't need
00511             // to build a temporary list, because we'll be restarting
00512             // from the beginning of our edge list after we do this.
00513             // We also pass do_mate = false to these guys because
00514             // we're the ones doing the mating here.
00515             mate->cut_sheet(first_row_id, false, bucket);
00516 
00517             if (_status == MS_alive && mate->_status == MS_alive) {
00518               // Now mate.  This will either succeed or fail.  It ought
00519               // to succeed, but if it doesn't, no harm done; it will
00520               // simply remove the common edge and return.  We'll go
00521               // around again and not encounter this neighbor next time.
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     // All done.  Mark this one as down for the count.
00536     _row_id = -first_row_id;
00537   }
00538 }
00539 
00540 
00541 
00542 
00543 ////////////////////////////////////////////////////////////////////
00544 //     Function: MesherStrip::mate
00545 //       Access: Public
00546 //  Description: Finds a neighboring strip and joins up with it to
00547 //               make a larger strip.  Returns true if mating was
00548 //               successful or at least possible, false if the strip
00549 //               has no neighbors.
00550 ////////////////////////////////////////////////////////////////////
00551 template <class PrimType>
00552 bool MesherStrip<PrimType>::
00553 mate(const BuilderBucket &bucket) {
00554   // We must walk through the list of our neighbors and choose our
00555   // best mate.
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     // We have no more eligible neighbors.  Call us done.
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   // Whether the mate failed or not, the strip still (probably) has
00574   // other neighbors to consider.  Return true regardless.
00575   return true;
00576 }
00577 
00578 ////////////////////////////////////////////////////////////////////
00579 //     Function: MesherStrip::find_ideal_mate
00580 //       Access: Public
00581 //  Description: Searches our neighbors for the most suitable mate.
00582 //               Returns true if one is found, false if we have no
00583 //               neighbors.
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 //     Function: MesherStrip::mate_pieces
00616 //       Access: Public, Static
00617 //  Description: Connects two pieces of arbitrary type, if possible.
00618 //               Returns true if successful, false if failure.
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   // remove_sides tracks whether we want to remove all but the leading
00630   // edges of the newly joined piece if we succeed.
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       // If we're joining two equivalent coplanar triangles, call it a
00642       // quad.
00643       front._type = BPT_quad;
00644 
00645       // We add one additional vertex for the new triangle, the one
00646       // vertex we didn't already share.
00647       const Vertex *new_vert = back.find_uncommon_vertex(common_edge);
00648 
00649       // Now we just need to find the right place to insert it.  It
00650       // belongs in the middle of the common edge, i.e. after the first
00651       // vertex that is on the common edge and before the second vertex.
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           // It goes between a and b.
00659           front._verts.insert(b, new_vert);
00660         } else {
00661           // It goes at the end.
00662           front._verts.push_back(new_vert);
00663         }
00664       } else {
00665         // It goes between b and c.
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       // We leave all four surrounding edges for now, since the quad
00674       // might still be joined up in any direction.
00675       remove_sides = false;
00676 
00677     } else {
00678       // Otherwise, connect the two tris into a tristrip.
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     // Joining two quads, two quadstrips, or a quad and a quadstrip.
00692     // This makes another quadstrip.
00693 
00694     // We expect this to succeed every time with quadstrips.
00695     success = mate_strips(common_edge, front, back, BPT_quadstrip);
00696 
00697     if (!success) {
00698       // Although it might fail in rare circumstances (specifically,
00699       // if the two strips we attempted to join were backfacing to
00700       // each other).  If so, remove the adjoining edge so these two
00701       // don't get tried again.
00702       common_edge->remove(&front);
00703       common_edge->remove(&back);
00704     }
00705 
00706   } else {
00707 
00708     // Otherwise.  This might be two tristrips, a quad and a tristrip,
00709     // a triangle and a quad, a triangle and a tristrip, a triangle
00710     // and a quadstrip, or a tristrip and a quadstrip.  In any case,
00711     // we'll end up with a tristrip.
00712 
00713     // This might fail if the tristrips don't match polarity.
00714     success = mate_strips(common_edge, front, back, BPT_tristrip);
00715 
00716     if (!success) {
00717       // If it does fail, we'll try reversing the connection.  This
00718       // makes sense if we are joining a tri or tristrip to a quad or
00719       // quadstrip, which might fail in one direction but succeed in
00720       // the other.
00721       success = mate_strips(common_edge, back, front, BPT_tristrip);
00722 
00723       if (success) {
00724         // Yay!  Now return all the stuff to front.
00725         front._verts.splice(front._verts.end(), back._verts);
00726         front._prims.splice(front._prims.end(), back._prims);
00727       } else {
00728         // A miserable failure.  Never try to join these two again.
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       // If we didn't want to remove the side edges, at least remove
00740       // the join edge, which is now internal.
00741       common_edge->remove(&front);
00742     }
00743 
00744     nassertr(back._prims.empty(), false);
00745     nassertr(back._verts.empty(), false);
00746 
00747     // Strip back is no more.
00748     back._status = MS_dead;
00749 
00750     // The result is planar if and only if we joined two coplanar
00751     // pieces.
00752     front._planar = is_coplanar;
00753     front._origin = MO_mate;
00754   }
00755 
00756   return success;
00757 }
00758 
00759 
00760 ////////////////////////////////////////////////////////////////////
00761 //     Function: MesherStrip::mate_strips
00762 //       Access: Public, Static
00763 //  Description: Stitches two strips together, producing in "front" a
00764 //               new strip of the indicated type (quadstrip or
00765 //               tristrip).  The front strip stores the result, and
00766 //               the back strip is emptied on success.
00767 //
00768 //               Returns true if successful, false if failure
00769 //               (generally because of incorrect polarity of
00770 //               tristrips), in which case nothing has changed (or at
00771 //               least, not much).
00772 ////////////////////////////////////////////////////////////////////
00773 template <class PrimType>
00774 bool MesherStrip<PrimType>::
00775 mate_strips(Edge *common_edge, MesherStrip &front, MesherStrip &back,
00776             BuilderPrimType type) {
00777   // If we start with a quad or tri, rotate the vertices around so we
00778   // start with the common edge.
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     // If we're going to reverse the front strip, we have to be
00794     // careful.  This will also reverse the facing direction if it has
00795     // an odd number of prims.
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     // Instead of crapping out, for now we'll just recover and carry on.
00828     //    builder_cat.info() << "Recovering from attempt to join backfacing strips.\n";
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   if (! (front.get_tail_edge() == back.get_head_edge()) ) {
00851     builder_cat.error()
00852          << "\nFailure, trying to connect " << front
00853          << "\nto " << back
00854          << "\nreverse_front = " << reverse_front
00855          << " reverse_back = " << reverse_back
00856          << " invert_front = " << invert_front
00857          << "\n";
00858     Edges::iterator ei;
00859 
00860     nout << "\nFront edges:\n";
00861     for (ei = front._edges.begin(); ei != front._edges.end(); ++ei) {
00862       nout << **ei << "\n";
00863     }
00864 
00865     nout << "\nBack edges:\n";
00866     for (ei = back._edges.begin(); ei != back._edges.end(); ++ei) {
00867       nout << **ei << "\n";
00868     }
00869   }
00870   */
00871 
00872   // If this assertion fails, we were misinformed about our ability to
00873   // join these two strips.  Either the must_invert() call returned the
00874   // incorrect value, or our edge-detection logic failed and we
00875   // attempted to join two oppositely-facing strips.
00876   //nassertr(front.get_tail_edge() == back.get_head_edge(), false);
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 //     Function: MesherStrip::must_invert
00888 //       Access: Public, Static
00889 //  Description: Returns false if the strips can be mated as they
00890 //               currently are.  Returns true if the back strip must
00891 //               be inverted first.
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     // If we'll be converting from quads to tris, the tail edge of the
00902     // front strip will always be even.
00903 
00904   } else if (front.is_odd()) {
00905     // Otherwise, we have to flip if the tail edge is odd.
00906     invert = !invert;
00907   }
00908 
00909   if (will_reverse_back) {
00910     // With the back strip, we don't care about what will happen to
00911     // its tail edge when we convert it, but we do care what happens
00912     // to its front edge if we reverse it.
00913     if (back.is_odd()) {
00914       // Specifically, the front edge will be reversed when the strip
00915       // is reversed only if the strip is odd.
00916       invert = !invert;
00917     }
00918   }
00919 
00920   return invert;
00921 }
00922 
00923 ////////////////////////////////////////////////////////////////////
00924 //     Function: MesherStrip::convex_quad
00925 //       Access: Public, Static
00926 //  Description: Returns true if the quad that would be formed by
00927 //               connecting coplanar tris front and back along
00928 //               common_edge is convex, false otherwise.
00929 ////////////////////////////////////////////////////////////////////
00930 template <class PrimType>
00931 bool MesherStrip<PrimType>::
00932 convex_quad(Edge *common_edge, MesherStrip &front, MesherStrip &back,
00933             const BuilderBucket &bucket) {
00934   // Find the edge from the apex of one triangle to the apex of the
00935   // other.  This is the "other" diagonal of the quad-to-be, other
00936   // than the common_edge.
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   // Project both edges into the 2-d axis plane most nearly
00949   // perpendicular to the normal.  We're assuming both tris have the
00950   // same normal.
00951 
00952   nassertr(front._planar, false);
00953 
00954   LVector3f &n = front._plane_normal;
00955   int xi, yi;
00956 
00957   // Find the largest dimension of the normal.
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   // Now (c2-d2) is the common edge, and (a2-b2) is the new edge.  The
00983   // quad is convex iff (c2-d2) intersects (a2-b2).  We actually only
00984   // need to test whether (c2-d2) intersects the infinite line passing
00985   // through (a2-b2).
00986 
00987   // The equation for the infinite line containing (a2-b2):
00988   // Ax + By + C = 0
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   // The parametric equations for the line segment (c2-d2):
00994   // x = c2[0] + (d2[0]-c2[0])t
00995   // y = c2[1] + (d2[1]-c2[1])t
00996 
00997   // Solved for t:
00998   double t = - ((A*c2[0] + B*c2[1]) + C) / (A*(d2[0]-c2[0]) + B*(d2[1]-c2[1]));
00999 
01000   // Now the lines intersect if t is in [0, 1].
01001   return (0.0 <= t && t <= 1.0);
01002 }
01003 
01004 ////////////////////////////////////////////////////////////////////
01005 //     Function: MesherStrip::count_neighbors
01006 //       Access: Public
01007 //  Description: Returns the number of neighbors the strip shares.
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 //     Function: MesherStrip::show_neighbors
01023 //       Access: Public
01024 //  Description: Writes all the neighbor indexes to the ostream.
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 //     Function: MesherStrip::find_uncommon_vertex
01044 //       Access: Public
01045 //  Description: Returns the first vertex found that is not shared by
01046 //               the given edge.
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 //     Function: MesherStrip::find_opposite_edge
01070 //       Access: Public
01071 //  Description: Returns the first edge found that does not contain
01072 //               the given vertex.  In a tri, this will be the edge
01073 //               opposite the given vertex.
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 //     Function: MesherStrip::find_opposite_edge
01091 //       Access: Public
01092 //  Description: Returns the first edge found that shares no vertices
01093 //               with the given edge.  In a quad, this will be the
01094 //               edge opposite the given edge.
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 //     Function: MesherStrip::find_adjacent_edge
01115 //       Access: Public
01116 //  Description: Returns the first edge found that shares exactly one
01117 //               vertex with the given edge.  In a quad, this will be
01118 //               one of two edges adjacent to the given edge.
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 //     Function: MesherStrip::rotate_to_front
01139 //       Access: Public
01140 //  Description: Rotates a triangle or quad so that the given edge is
01141 //               first in the vertex list.
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   // See if we're already there.
01150   if (_verts.front() == a || _verts.front() == b) {
01151     TYPENAME Verts::iterator vi = _verts.begin();
01152     ++vi;
01153     if (*vi == a || *vi == b) {
01154       // Yes!
01155       return;
01156     }
01157 
01158     // No, we must be right on the line.  Roll back one.
01159     rotate_back();
01160 
01161   } else {
01162     // Roll forward until it comes into view.
01163     int num_verts = _verts.size();
01164     while (_verts.front() != a && _verts.front() != b) {
01165       // Make sure either vertex exists.
01166       num_verts--;
01167       nassertv(num_verts > 0);
01168       rotate_forward();
01169     }
01170   }
01171 
01172   // Now make sure the edge actually exists.
01173   TYPENAME Verts::iterator vi = _verts.begin();
01174   ++vi;
01175   nassertv(*vi == a || *vi == b);
01176 }
01177 
01178 ////////////////////////////////////////////////////////////////////
01179 //     Function: MesherStrip::rotate_to_back
01180 //       Access: Public
01181 //  Description: Rotates a triangle or quad so that the given edge is
01182 //               last in the vertex list.
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   // See if we're already there.
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       // Yes!
01196       return;
01197     }
01198 
01199     // No, we must be right on the line.  Roll forward one.
01200     rotate_forward();
01201 
01202   } else {
01203     // Roll backward until it comes into view.
01204     int num_verts = _verts.size();
01205     while (_verts.back() != a && _verts.back() != b) {
01206       // Make sure either vertex exists.
01207       num_verts--;
01208       nassertv(num_verts > 0);
01209       rotate_back();
01210     }
01211   }
01212 
01213   // Now make sure the edge actually exists.
01214   TYPENAME Verts::reverse_iterator vi = _verts.rbegin();
01215   ++vi;
01216   nassertv(*vi == a || *vi == b);
01217 }
01218 
01219 
01220 ////////////////////////////////////////////////////////////////////
01221 //     Function: MesherStrip::can_invert
01222 //       Access: Public
01223 //  Description: Returns true if the strip can be inverted (reverse
01224 //               its facing direction).  Generally, this is true for
01225 //               quadstrips and false for tristrips.
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 //     Function: MesherStrip::invert
01235 //       Access: Public
01236 //  Description: Reverses the facing of a quadstrip by reversing pairs
01237 //               of vertices.  Returns true if successful, false if
01238 //               failure (for instance, on a tristrip).
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     // Exchange vi and vi2
01254     const Vertex *t = *vi2;
01255     *vi2 = *vi;
01256     *vi = t;
01257 
01258     // Increment
01259     vi = vi2;
01260     ++vi;
01261   }
01262   return true;
01263 }
01264 
01265 ////////////////////////////////////////////////////////////////////
01266 //     Function: MesherStrip::is_odd
01267 //       Access: Public
01268 //  Description: Returns true if the tristrip or quadstrip contains an
01269 //               odd number of pieces.
01270 ////////////////////////////////////////////////////////////////////
01271 template <class PrimType>
01272 bool MesherStrip<PrimType>::
01273 is_odd() const {
01274   if (_type==BPT_quadstrip || _type==BPT_quad) {
01275     // If a quadstrip has a multiple of four vertices, it has an
01276     // odd number of quads.
01277     return (_verts.size()%4 == 0);
01278   } else {
01279     // If a tristrip has an odd number of vertices, it has an odd
01280     // number of tris.
01281     return (_verts.size()%2 == 1);
01282   }
01283 }
01284 
01285 ////////////////////////////////////////////////////////////////////
01286 //     Function: MesherStrip::would_reverse_tail
01287 //       Access: Public
01288 //  Description: Returns true if convert_to_type() would reverse the
01289 //               tail edge of the given strip, false otherwise.
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       // When we convert a quadstrip to a tristrip, we reverse the
01308       // tail edge if we have a multiple of four verts.
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       // We don't convert tristrips to quadstrips; fall through.
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 //     Function: MesherStrip::convert_to_type
01341 //       Access: Public
01342 //  Description: Converts the MesherStrip from whatever form it
01343 //               is--triangle, quad, or quadstrip--into a tristrip or
01344 //               quadstrip.
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       // To convert from quad/quadstrip to tristrip, we reverse every other
01364       // pair of vertices.
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         // vi and vi2 are a pair.  Should we reverse them?
01374         if (even) {
01375           const Vertex *t = *vi2;
01376           *vi2 = *vi;
01377           *vi = t;
01378         }
01379 
01380         // Increment
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       // We don't convert tristrips to quadstrips; fall through.
01401 
01402     default:
01403       builder_cat.fatal() << "Invalid conversion!\n";
01404       abort();
01405     }
01406   }
01407 
01408   _type = wantType;
01409 }
01410 
01411 ////////////////////////////////////////////////////////////////////
01412 //     Function: MesherStrip::combine_edges
01413 //       Access: Public
01414 //  Description: Removes the edges from the given strip and appends
01415 //               them to our own.  If removeSides is true, then
01416 //               removes all the edges except the head and the tail.
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     // Identify the head and tail edges so we can remove everything
01430     // else.
01431     Edge head = get_head_edge();
01432     Edge tail = get_tail_edge();
01433 
01434     if (!is_odd()) {
01435       // If the strip is odd, its true tail edge is the inverse of its
01436       // actual edge.
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       // Is this edge to be saved or is it fodder?
01449       if (!(**ei == head) && !(**ei == tail)) {
01450         // Fodder!  But we can't remove it right away, because this
01451         // will upset the current list; instead, we'll splice it to
01452         // junk_edges.
01453         junk_edges.splice(junk_edges.end(), _edges, ei);
01454       }
01455       ei = next_ei;
01456     }
01457 
01458     // Now we can safely remove all the to-be-junked edges.
01459     for (ei = junk_edges.begin(); ei != junk_edges.end(); ++ei) {
01460       (*ei)->remove(this);
01461     }
01462   }
01463 }
01464 
01465 
01466 ////////////////////////////////////////////////////////////////////
01467 //     Function: MesherStrip::remove_all_edges
01468 //       Access: Public
01469 //  Description: Removes all active edges from the strip.  This
01470 //               effectively renders it ineligible to mate with
01471 //               anything else.
01472 ////////////////////////////////////////////////////////////////////
01473 template <class PrimType>
01474 void MesherStrip<PrimType>::
01475 remove_all_edges() {
01476   // First, move all the edges to a safe place so we can traverse the
01477   // list without it changing on us.
01478   Edges junk_edges;
01479   junk_edges.splice(junk_edges.end(), _edges);
01480 
01481   // Now we can safely remove all the to-be-junked edges.
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 //     Function: MesherStrip::pick_mate
01490 //       Access: Public
01491 //  Description: Defines an ordering to select neighbors to mate with.
01492 //               This compares strip a with strip b and returns true
01493 //               if strip a is the preferable choice, false if strip
01494 //               b.
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   // First, try to avoid polluting quads, quadstrips, and tristrips
01502   // with arbitrary triangles.  When we mate a tri or tristrip to a
01503   // quadstrip, we end up with a tristrip that may be less versatile
01504   // than the original quadstrip.  Better to avoid this if we can.
01505   // Try to choose a mate that more closely matches our own type.
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   // Now, if we're connecting two tris, try to connect them up so they
01514   // make good quads.
01515   if (_type == BPT_tri && a_strip._type == BPT_tri &&
01516       b_strip._type == BPT_tri) {
01517 
01518     // This will depend on both coplanarity and edge length.  We can't
01519     // use just one or the other, because some tris are nearly
01520     // isosceles, and some have more than one coplanar neighbor.
01521     // Hopefully the combination of both factors will zero us in on
01522     // the correct neighbor first.
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     // These weights were chosen empirically to yield fairly good results.
01533     double sum = 4.0 * coplanar_diff - 1.0 * length_diff;
01534     return sum < 0;
01535   }
01536 
01537   // Then, get the smallest strip.
01538   if (a_strip._prims.size() != b_strip._prims.size()) {
01539     return a_strip._prims.size() < b_strip._prims.size();
01540   }
01541 
01542   // Finally, get the strip with the fewest neighbors.
01543   return a_strip.count_neighbors() < b_strip.count_neighbors();
01544 }
01545 
01546 ////////////////////////////////////////////////////////////////////
01547 //     Function: MesherStrip::pick_sheet_mate
01548 //       Access: Public
01549 //  Description: Defines an ordering to select neighbors to follow
01550 //               when measuring out a quadsheet.  This is only called
01551 //               when three or more prims share a single edge, which
01552 //               should be rarely--generally only when coplanar polys
01553 //               are going on.
01554 ////////////////////////////////////////////////////////////////////
01555 template <class PrimType>
01556 bool MesherStrip<PrimType>::
01557 pick_sheet_mate(const MesherStrip &a_strip, const MesherStrip &b_strip) const {
01558   // First, try to get the poly which is closest to our own normal.
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   // Then, pick the one that's most like our own type.
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   // Oh, just pick any old one.
01577   return false;
01578 }
01579 
01580 ////////////////////////////////////////////////////////////////////
01581 //     Function: MesherStrip::output
01582 //       Access: Public
01583 //  Description: Formats the vertex for output in some sensible way.
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 

Generated on Fri May 2 00:34:50 2003 for Panda by doxygen1.3