Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

tri_strip.C

Go to the documentation of this file.
00001 /**********************************************************************
00002  * tri_strip.C:
00003  **********************************************************************/
00004 #include "bmesh.H"
00005 #include "mesh_global.H"        // for debugging (selecting bad faces)
00006 #include "stripcb.H"
00007 
00008 // Values used in finding triangle strips.
00009 //
00010 // A face is "claimed" when it has been added to a strip.
00011 //
00012 // A face is "marked" during TriStrip::backup_strip(), below,
00013 // during a traversal that "backs up" over a sequence of faces
00014 // before adding them to a new strip.
00015 //
00016 // (Initially all face flags should be cleared to 0.)
00017 //
00018 static const uchar CLEARED_FLAG = 0;
00019 static const uchar MARKED_FLAG  = 1;
00020 static const uchar CLAIMED_FLAG = 2;
00021 
00022 inline bool
00023 is_cleared(Bface* f)
00024 {
00025    return f->flag() == CLEARED_FLAG;
00026 }
00027 
00028 inline bool
00029 is_marked(Bface* f)
00030 {
00031    return f->flag() == MARKED_FLAG;
00032 }
00033 
00034 inline bool
00035 is_claimed(Bface* f)
00036 {
00037    return f->flag() == CLAIMED_FLAG;
00038 }
00039 
00040 inline void
00041 mark_face(Bface* f)
00042 {
00043    f->set_flag(MARKED_FLAG);
00044 }
00045 
00046 inline void
00047 claim_face(Bface* f)
00048 {
00049    f->set_flag(CLAIMED_FLAG);
00050 }
00051 
00052 /**********************************************************************
00053  * TriStrip:
00054  **********************************************************************/
00055 Bface*
00056 TriStrip::backup_strip(Bface* f, Bvert*& a) 
00057 {
00058    // we'd like to draw a triangle strip starting at the 
00059    // given triangle and proceeding "forward." but to get 
00060    // the most bang for the buck, we'll first "backup" over 
00061    // as many triangles as possible to find a starting place 
00062    // from which we can generate a longer strip.
00063 
00064    assert(!f->flag());
00065 
00066    mark_face(f);
00067 
00068    Bface* ret = f;
00069    Bvert* b   = f->next_vert_ccw(a);
00070    Bvert* c   = f->next_vert_ccw(b);
00071    Bedge* e;
00072 
00073    int i = 0;
00074    while((e = f->edge_from_vert((i%2) ? b : a)) &&
00075          e->consistent_orientation()            &&
00076          e->is_crossable()                      &&
00077          (f = e->other_face(f))                 &&
00078          is_cleared(f)) {
00079       mark_face(f);
00080       ret = f;
00081       Bvert* d = f->other_vertex(a,b);
00082       c = b;
00083       b = a;
00084       a = d;
00085       i++;
00086    }
00087 
00088    _orientation = ((i%2) != 0);
00089 
00090    return ret;
00091 }
00092 
00093 bool
00094 TriStrip::build(
00095    Bface* start,        // build a new strip starting here.
00096    Bface_list& stack    // used to build nearby parallel strips
00097    )
00098 {
00099    // a set flag means this face is already in a TriStrip
00100    assert(!start->flag());
00101 
00102    // start fresh
00103    reset();
00104 
00105    // repeat 1st vertex if needed
00106    if (!start->orient_strip())
00107       start->orient_strip(start->v1());
00108 
00109    // get the starting vert. i.e., the strip will
00110    // continue onto the next face across the edge
00111    // opposite this vertex.
00112    Bvert *a = start->orient_strip(), *b, *c;
00113 
00114    // squash and stretch
00115    start = backup_strip(start,a);
00116 
00117    if (!start) {
00118       // should never happen, but can happen
00119       // if there are inconsistently oriented faces
00120       err_msg("TriStrip::build: error: backup_strip() failed");
00121       err_msg("*** check mesh for inconsistently oriented faces ***");
00122 
00123       return 0;
00124    }
00125 
00126    // claim it
00127    claim_face(start);
00128 
00129    // record direction of strip on 1st face:
00130    start->orient_strip(a);
00131 
00132    // faces alternate CCW / CW
00133    if (_orientation) {
00134       c = start->next_vert_ccw(a);
00135       b = start->next_vert_ccw(c);
00136    } else {
00137       b = start->next_vert_ccw(a);
00138       c = start->next_vert_ccw(b);
00139    }
00140 
00141    add(a,start);
00142    add(b,start);
00143    add(c,start);
00144 
00145    Bface* opp;
00146    if ((opp = start->opposite_face(b)) && is_cleared(opp) &&
00147       opp->patch() == start->patch()) {
00148       opp->orient_strip(_orientation ? a : c);
00149       stack += opp;
00150    }
00151 
00152    int i=_orientation;
00153    Bface* cur = start;
00154    while ((cur = cur->next_strip_face()) && !is_claimed(cur)) {
00155       claim_face(cur);
00156       i++;
00157       a = b;
00158       b = c;
00159       c = cur->other_vertex(a,b);
00160       cur->orient_strip(a);
00161 
00162       if ((opp = cur->opposite_face(b)) && is_cleared(opp) &&
00163           opp->patch() == start->patch()) {
00164          opp->orient_strip(i % 2 ? a : c);
00165          stack += opp;
00166       }
00167 
00168       add(c,cur);
00169    }
00170 
00171    return 1;
00172 }
00173 
00174 void
00175 TriStrip::get_strips(
00176    Bface* start,
00177    ARRAY<TriStrip*>& strips
00178    ) 
00179 {
00180    // if starting face was visited already, stop
00181    if (!is_cleared(start))
00182       return;
00183 
00184    // stack is used to record faces adjacent to
00185    // the current strip, in order to build additional
00186    // strips that align with the current one
00187    static Bface_list stack(1024);
00188    stack.clear();
00189    stack += start;
00190 
00191    BMESH* mesh = start->mesh();
00192 
00193    while (!stack.empty()) {
00194       start = stack.pop();
00195       if (is_cleared(start)) {
00196          TriStrip* strip = mesh->new_tri_strip();
00197          strip->build(start, stack);
00198          strips += strip;
00199       }
00200    }
00201 }
00202 
00203 void
00204 TriStrip::draw(StripCB* cb)
00205 {
00206    // check for empty strip before doing work:
00207    if (empty())
00208       return;
00209 
00210    // XXX -
00211    //   Temporary check to see if it ever happens (10/2003):
00212    if (!BMESH::show_secondary_faces() && _faces.has_any_secondary()) {
00213       err_msg("TriStrip::draw: warning: %d/%d secondary faces",
00214               _faces.num_secondary(), _faces.num());
00215       MeshGlobal::select(_faces.secondary_faces());
00216    }
00217 
00218    cb->begin_faces(this);
00219 
00220    // repeat 1st vertex if strip is
00221    // negatively oriented:
00222    if (_orientation)
00223       cb->faceCB(_verts[0], _faces[0]); // good thing it's not empty
00224 
00225    for (int i=0; i<_verts.num(); i++)
00226       cb->faceCB(_verts[i], _faces[i]);
00227 
00228    cb->end_faces(this);
00229 }
00230 
00231 /* end of file tri_strip.C */

Generated on Mon Sep 18 11:39:34 2006 for jot by  doxygen 1.4.4