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

lmesh.C

Go to the documentation of this file.
00001 /**********************************************************************
00002  * lmesh.C
00003  **********************************************************************/
00004 #include "disp/ray.H"
00005 #include "disp/colors.H"
00006 #include "geom/world.H"   // XXX - for debugging
00007 #include "mlib/statistics.H"
00008 #include "std/config.H"
00009 #include "lpatch.H"
00010 
00011 using namespace mlib;
00012 
00013 // add LMESH to decoder hash table:
00014 /*
00015 // XXX - Moved this to bmesh.C
00016 // to work around a static initialization
00017 // order problem with BMESHobs not having
00018 // its static members available before
00019 // the LMESH constructor is called.
00020 static class DECODERS {
00021 public:
00022 DECODERS() {
00023 DECODER_ADD(LMESH);
00024 }
00025 } DECODERS_static;
00026 */
00027 
00028 LMESH::LMESH(int num_v, int num_e, int num_f) :
00029    BMESH(num_v, num_e, num_f),
00030    _parent_mesh(0),
00031    _cur_mesh(0),     // XXX - see comment below
00032    _subdiv_mesh(0),
00033    _subdiv_level(0),
00034    _loc_calc(new HybridLoc),    // use hybrid rules by default
00035    _color_calc(new LoopColor)   // for colors we're not so choosy
00036 {
00037    // Some compilers complain if 'this' is used in
00038    // member variable initialization section above
00039    _cur_mesh = this;
00040    _lmesh_tags = NULL;            // non-static tags
00041 }
00042 
00043 LMESH::~LMESH()
00044 {
00045    delete_elements();
00046    delete _loc_calc;
00047    delete _color_calc;
00048 }
00049 
00050 void
00051 LMESH::set_subdiv_loc_calc(SubdivLocCalc* c)
00052 {
00053    // Delete the old one:
00054    delete _loc_calc;
00055 
00056    // Store the new one:
00057    _loc_calc = c;
00058 
00059    // Mark all vertices "dirty" to force recomputation
00060    // next time the mesh is used for anything:
00061    mark_all_dirty();
00062 
00063    // If there is a subdivision mesh already allocated,
00064    // change its subdiv_loc too:
00065    if (_subdiv_mesh)
00066       _subdiv_mesh->set_subdiv_loc_calc(c->dup());
00067 
00068    // For control meshes only -- make sure display lists are
00069    // invalidated so we can see the results of the change!
00070    if (is_control_mesh())
00071       changed(RENDERING_CHANGED);
00072 }
00073 
00074 void
00075 LMESH::set_subdiv_color_calc(SubdivColorCalc* c)
00076 {
00077    // Delete the old one:
00078    delete _color_calc;
00079 
00080    // Store the new one:
00081    _color_calc = c;
00082 
00083    // Mark all vertices "dirty" to force recomputation
00084    // next time the mesh is used for anything:
00085    mark_all_dirty();
00086 
00087    // If there is a subdivision mesh already allocated,
00088    // change its subdiv_loc too:
00089    if (_subdiv_mesh)
00090       _subdiv_mesh->set_subdiv_color_calc(c->dup());
00091 
00092    // For control meshes only -- make sure display lists are
00093    // invalidated so we can see the results of the change!
00094    if (is_control_mesh())
00095       changed(RENDERING_CHANGED);
00096 
00097    // XXX - this copied code (see set_subdiv_loc_calc())
00098    // is sub-optimal
00099 }
00100 
00101 void
00102 LMESH::set_geom(GEOM *geom)
00103 {
00104    BMESH::set_geom(geom);
00105    if (_subdiv_mesh)
00106       _subdiv_mesh->set_geom(geom);
00107 }
00108 
00109 int
00110 LMESH::draw(CVIEWptr &v)
00111 {
00112    // Only called on control mesh...
00113    assert(is_control_mesh());
00114 
00115    // Update subdivision if needed (down to current level):
00116    update();
00117 
00118    // BMESH functionality handles it...
00119    return BMESH::draw(v);
00120 }
00121 
00122 double
00123 LMESH::area() const
00124 {
00125    // if current subdivision mesh is not this
00126    // (i.e., this is the control mesh),
00127    // make sure subdivision is up-to-date
00128    // then forward call to current mesh:
00129 
00130    ((LMESH*)this)->update();
00131 
00132    return _cur_mesh->BMESH::area();
00133 }
00134 
00135 double
00136 LMESH::volume() const
00137 {
00138    // if current subdivision mesh is not this
00139    // (i.e., this is the control mesh),
00140    // make sure subdivision is up-to-date
00141    // then forward call to current mesh:
00142 
00143    ((LMESH*)this)->update();
00144 
00145    return _cur_mesh->BMESH::volume();
00146 }
00147 
00148 void
00149 LMESH::clear_creases()
00150 {
00151    // handle corners
00152    int count = 0;
00153    for (int i=0; i<nverts(); i++) {
00154       if (lv(i)->corner_value()) {
00155          lv(i)->set_corner(0);
00156          count++;
00157       }
00158    }
00159    if (count)
00160       changed(RENDERING_CHANGED);
00161 
00162    err_msg("LMESH::clear_creases: cleared %d corners", count);
00163 
00164    // take care of creases...
00165    BMESH::clear_creases();
00166 }
00167 
00168 
00169 Patch*
00170 LMESH::new_patch()
00171 {
00172    Patch* ret = new Lpatch(this);
00173 
00174    _patches += ret;
00175    if (is_control_mesh())
00176       _drawables += ret;
00177    return ret;
00178 }
00179 
00180 
00181 Bedge*
00182 LMESH::new_edge(Bvert* u, Bvert* v) const
00183 {
00184    return new Ledge((Lvert*)u, (Lvert*)v);
00185 }
00186 
00187 Bvert*
00188 LMESH::new_vert(CWpt& p) const
00189 {
00190    return new Lvert(p);
00191 }
00192 
00193 Bface*
00194 LMESH::new_face(
00195    Bvert* u,
00196    Bvert* v,
00197    Bvert* w,
00198    Bedge* e,
00199    Bedge* f,
00200    Bedge* g) const
00201 {
00202    return new Lface((Lvert*)u, (Lvert*)v, (Lvert*)w,
00203                     (Ledge*)e, (Ledge*)f, (Ledge*)g);
00204 }
00205 
00206 int
00207 LMESH::remove_vertex(Bvert* bv)
00208 {
00209    assert(bv && bv->mesh() == this);
00210    Lvert* v = (Lvert*)bv;
00211 
00212    // Get it out of the dirty list
00213    rem_dirty_vert(v);
00214 
00215    // And make damn sure it stays out
00216    v->set_bit(Lvert::DEAD_BIT);
00217 
00218    return BMESH::remove_vertex(v);
00219 }
00220 
00221 int
00222 LMESH::remove_edge(Bedge* be)
00223 {
00224    // Need to delete edge's subdiv elements
00225    // first, before the edge is detached
00226    // and loses its connectivity info
00227 
00228    assert(be && be->mesh() == this);
00229    Ledge* e = (Ledge*)be;
00230 
00231    e->delete_subdiv_elements();
00232    return BMESH::remove_edge(e);
00233 }
00234 
00235 int
00236 LMESH::remove_face(Bface* bf)
00237 {
00238    // Need to delete face's subdiv elements
00239    // first, before the face is detached
00240    // and loses its connectivity info
00241 
00242    assert(bf && bf->mesh() == this);
00243    Lface* f = (Lface*)bf;
00244 
00245    f->delete_subdiv_elements();
00246    return BMESH::remove_face(f);
00247 }
00248 
00249 Bvert*
00250 LMESH::add_vertex(Bvert* v)
00251 {
00252    if (BMESH::add_vertex(v))
00253       add_dirty_vert((Lvert*)v);
00254    return v;
00255 }
00256 
00257 Bvert*
00258 LMESH::add_vertex(CWpt& p)
00259 {
00260    // following line triggers LMESH::add_vertex(Bvert*)
00261    // which adds the dirty vert:
00262    return BMESH::add_vertex(p);
00263 }
00264 
00265 BMESH&
00266 LMESH::operator =(CBMESH& m)
00267 {
00268    return BMESH::operator=(m);
00269 }
00270 
00271 BMESH&
00272 LMESH::operator =(CLMESH& m)
00273 {
00274    // Replace this mesh with identical copy of m:
00275    BMESH::operator=((CBMESH&)m);
00276 
00277    // Also copy corner information
00278    for (int k=0; k<nverts(); k++) {
00279       if (m.lv(k)->corner_value() > 0)
00280          lv(k)->set_corner(m.lv(k)->corner_value());
00281    }
00282 
00283    return *this;
00284 }
00285 
00286 BMESH&
00287 LMESH::operator =(BODY& b)
00288 {
00289    BMESH::operator=(b); return *((BMESH*)this);
00290 }
00291 
00292 int
00293 LMESH::write_patches(ostream& os) const
00294 {
00295    return control_mesh()->BMESH::write_patches(os);
00296 }
00297 
00298 void
00299 LMESH::changed(change_t change)
00300 {
00301    BMESH::changed(change);
00302 //    if (_subdiv_mesh)
00303 //       _subdiv_mesh->changed(change);
00304 
00305    // notify subdiv meshes
00306    for (LMESH* m = _subdiv_mesh; m; m = m->_subdiv_mesh)
00307       m->BMESH::changed(change);
00308 
00309    // ensure control mesh knows to invalidate display lists etc.
00310    // (if this *is* the control mesh, the first line took care of it)
00311    if (!is_control_mesh())
00312       control_mesh()->BMESH::changed(RENDERING_CHANGED);
00313 /*
00314    return;
00315 
00316    switch(change) {
00317     case RENDERING_CHANGED:
00318       if (!is_control_mesh())
00319          control_mesh()->changed(change);
00320     case NO_CHANGE:
00321       break;
00322     case TOPOLOGY_CHANGED:
00323     case PATCHES_CHANGED:
00324     case TRIANGULATION_CHANGED:
00325     case VERT_POSITIONS_CHANGED:
00326     case VERT_COLORS_CHANGED:
00327     case CREASES_CHANGED:
00328       if (_subdiv_mesh)                              // if subdiv mesh, 
00329          _subdiv_mesh->changed(change);              //   pass it down.
00330       else if (!is_control_mesh())                   // else, invalidate display 
00331          control_mesh()->changed(RENDERING_CHANGED); //   lists in ctrl mesh
00332    }
00333 */
00334 }
00335 
00336 int
00337 LMESH::size() const
00338 {
00339    // Return the approximate memory used for this mesh.
00340 
00341    // The extra 4 bytes per vertex, edge, etc. is for the
00342    // pointer in the corresponding list (_verts, _edges, etc.).
00343    // For each Bvert we also count the expected number of Bedge*
00344    // pointers in the adjacency list.
00345 
00346    return (
00347       (nverts()   * (sizeof(Lvert)  + 6*sizeof(Bedge*) + 4)) +
00348       (nedges()   * (sizeof(Ledge)  + 4)) +
00349       (nfaces()   * (sizeof(Lface)  + 8)) +     // each face is in two lists
00350       (npatches() * (sizeof(Lpatch) + 4)) +
00351       sizeof(LMESH)
00352       );
00353 }
00354 void
00355 LMESH::print() const
00356 {
00357    BMESH::print();
00358    err_msg("\tsubdiv level: %d", _subdiv_level);
00359 }
00360 
00361 int
00362 LMESH::intersect(
00363    RAYhit   &r,
00364    CWtransf &m,
00365    Wpt      &nearpt,
00366    Wvec     &n,
00367    double   &d,
00368    double   &d2d,
00369    XYpt     &uvc
00370    ) const
00371 {
00372    // if current subdivision mesh is not this
00373    // (i.e., this is the control mesh),
00374    // make sure subdivision is up-to-date
00375    // then forward call to current mesh:
00376 
00377    ((LMESH*)this)->update();
00378 
00379    return _cur_mesh->BMESH::intersect(r,m,nearpt,n,d,d2d,uvc);
00380 }
00381 
00382 void
00383 LMESH::transform(CWtransf &xform, CMOD& mod)
00384 {
00385    // Apply the transform to this mesh:
00386    BMESH::transform(xform, mod);
00387 
00388    // It used to be that we could just apply the transform at the
00389    // control mesh level, knowing that the effect was propagated to
00390    // finer subdivision levels thru the normal subdivision
00391    // process. But now subdivision meshes have been generalized to
00392    // include portions that do not come from the next coarser level
00393    // in the hierarchy. So to be on the safe side we apply the
00394    // transformation at all levels, recursively:
00395    if (_subdiv_mesh)
00396       _subdiv_mesh->transform(xform, mod);
00397 }
00398 
00399 void
00400 LMESH::_merge(BMESH* bm)
00401 {
00402    // merge the given mesh into this one.
00403 
00404    // error checking was done before this protected method was called.
00405    // so this convenient upcast is safe:
00406    LMESH* m = (LMESH*)bm;
00407 
00408    // merge subdivision meshes (recursively) first. but if this one
00409    // has fewer levels of subdivision, truncate the other one to the
00410    // same number of levels.
00411    if (_subdiv_mesh && m->_subdiv_mesh)
00412       _subdiv_mesh->_merge(m->_subdiv_mesh);
00413    else
00414       m->delete_subdiv_mesh(); // ensure it has no finer level meshes
00415 
00416    // Get the dirty vertices from m and put them into this
00417    // mesh's dirty list:
00418    m->_dirty_verts.clear_bits(Lvert::DIRTY_VERT_LIST_BIT);
00419    while (!m->_dirty_verts.empty())
00420       add_dirty_vert((Lvert*)m->_dirty_verts.pop());
00421 
00422    // this concludes the LMESH-specific aspect of the merge
00423    // method. now just continue with the normal merge...
00424    BMESH::_merge(bm);
00425 }
00426 
00427 const BBOX&
00428 LMESH::get_bb()
00429 {
00430    // if current subdivision mesh is not this
00431    // (i.e., this is the control mesh),
00432    // make sure subdivision is up-to-date
00433    // then forward call to current mesh:
00434 
00435    update();
00436 
00437    return _cur_mesh->BMESH::get_bb();
00438 }
00439 
00440 // Helper function used below in allocate_adjacent_child_faces():
00441 inline void
00442 allocate_child_faces(Lface* f)
00443 {
00444    if (f && f->subdiv_dirty())
00445       f->allocate_subdiv_elements();
00446 }
00447 
00448 // Helper function used below in update_sub(Ledge* e):
00449 inline void
00450 allocate_adjacent_child_faces(Ledge* e)
00451 {
00452    if (!e) return;
00453 
00454    allocate_child_faces(e->lf(1));
00455    allocate_child_faces(e->lf(2));
00456    if (e->is_multi()) {
00457       CBface_list& faces = *e->adj();
00458       for (int i=0; i<faces.num(); i++) {
00459          allocate_child_faces((Lface*)faces[i]);
00460       }
00461    }
00462 }
00463 
00464 // Helper function used below in update_sub(Lvert* v)
00465 inline void
00466 update_sub(Ledge* e, bool do_faces=true)
00467 {
00468    if (!e) return;
00469 
00470    // Allocate subdiv elements for the edge and try to
00471    // assign the subdiv vert location:
00472    e->update_subdivision();
00473 
00474    // Ensure adjacent subdiv faces are allocated:
00475    if (do_faces) {
00476       allocate_adjacent_child_faces(e);
00477    }
00478 }
00479 
00480 // Helper function used below in LMESH::allocate_subdiv_mesh():
00481 inline void
00482 update_sub(Lvert* v, bool do_edges=true)
00483 {
00484    if (!v) return;
00485 
00486    
00487    // Allocate subdiv vert and assign the subdiv location:
00488    v->update_subdivision();
00489 
00490    // Visit all adjacent edges and faces...
00491    if (do_edges) {
00492       for (int j=0; j<v->degree(); j++)
00493          update_sub(v->le(j));
00494    }
00495 }
00496 
00497 bool
00498 LMESH::allocate_subdiv_mesh()
00499 {
00500    // Allocate the next-level subdivision mesh itself.
00501    // (NOT any vertices, edges or faces).
00502 
00503    if (_subdiv_mesh)
00504       return 1; // It was easy
00505 
00506    // Actually have to do it:
00507    _subdiv_mesh = new LMESH(
00508       nverts()     + nedges(),       // number of vertices
00509       2*nedges() + 3*nfaces(),       // number of edges
00510       4*nfaces()                     // number of faces
00511       );
00512 
00513    if (!_subdiv_mesh) {
00514       // System error - can't allocate memory.
00515       err_ret( "LMESH::allocate_subdiv_mesh: can't allocate subdiv mesh");
00516       return 0; // Failure. (Might also try exit(1) here.)
00517    }
00518 
00519    // Inherited stuff:
00520    _subdiv_mesh->_type = _type;
00521    _subdiv_mesh->_geom = _geom;
00522    _subdiv_mesh->set_parent(this);
00523    _subdiv_mesh->set_subdiv_loc_calc(_loc_calc->dup());
00524    _subdiv_mesh->set_subdiv_color_calc(_color_calc->dup());
00525 
00526    // Tell observers the subdivision mesh was allocated:
00527    BMESHobs::broadcast_subdiv_gen(this);
00528 
00529    return 1; // success
00530 }
00531 
00532 const char*
00533 face_type(Bface* f)
00534 {
00535    if (!f)                      return "NULL ";
00536    else if (f->is_primary())    return "primary ";
00537    else                         return "secondary ";
00538 }
00539 
00540 inline void
00541 check(Ledge* e)
00542 {
00543    if (!e) {
00544       cerr << "null edge" << endl;
00545       return;
00546    }
00547    if (e->subdiv_mask() == Ledge::REGULAR_SMOOTH_EDGE && e->nfaces() < 2) {
00548       cerr << "bad edge found." << endl;
00549       cerr << "  faces: "
00550            << face_type(e->f1())
00551            << face_type(e->f2());
00552       if (e->adj()) {
00553          CBface_list& adj = *e->adj();
00554          for (int i=0; i<adj.num(); i++)
00555             cerr << face_type(adj[i]);
00556       }
00557       cerr << endl;
00558       WORLD::show(e->v1()->loc(), e->v2()->loc());
00559       e->mask_changed();
00560       e->set_mask();
00561    }
00562 }
00563 
00564 inline void
00565 debug_check_verts(Cstr_ptr& msg, CBvert_list& verts, CBvert_list& dirty_verts)
00566 {
00567    Bvert_list A = verts.filter(BitSetSimplexFilter(Lvert::DIRTY_VERT_LIST_BIT));
00568    if (!dirty_verts.contains_all(A)) {
00569       Bvert_list bad = A.minus(dirty_verts);
00570       cerr << msg << ": found " << bad.num()
00571            << " vertices missing from dirty list" << endl;
00572       WORLD::show_pts(bad.pts(), 8, Color::red);
00573    }
00574    Bvert_list B = verts.filter(BitClearSimplexFilter(Lvert::DIRTY_VERT_LIST_BIT));
00575    if (dirty_verts.contains_any(B)) {
00576       Bvert_list bad = dirty_verts.minus(B);
00577       cerr << msg << ": found " << bad.num()
00578            << " unexpected vertices in dirty list" << endl;
00579       WORLD::show_pts(bad.pts(), 8, Color::blue);
00580    }
00581 }
00582 
00583 inline str_ptr
00584 get_name(LMESH* m)
00585 {
00586    return (m && m->geom()) ? m->geom()->name() :
00587       (m ? "null geom" : "null mesh");
00588 }
00589 
00590 bool
00591 LMESH::update_subdivision(int level)
00592 {
00593    // Allocate subdivision meshes and mesh elements, and compute
00594    // subdivision positions (and optionally colors) down to the
00595    // given number of levels.
00596    //
00597    // "Level" is relative to this mesh.
00598    // I.e., level 1 means 1 level down from this one.
00599 
00600    // Returns 'true' if anything happened.
00601    bool ret = !_dirty_verts.empty();
00602 
00603    // Before going any further, make sure this mesh is up to
00604    // date.  You see, this mesh may have just been generated by
00605    // its parent.  And it may contain vertices whose locations
00606    // have not yet been computed, because the vertex or edge in
00607    // the parent mesh that would have computed the subdivision
00608    // location deferred to some observer that said it was going
00609    // to "handle" it. But that observer (e.g. a Bsurface) may not
00610    // have actually handled it yet, preferring to wait for the
00611    // update request which is going out now:
00612    BMESHobs::broadcast_update_request(this);
00613 
00614    // If level <= 0 there is nothing to do.
00615    // If can't allocate subdiv mesh, give up:
00616    if (level <= 0 || !allocate_subdiv_mesh()) {
00617       if (cur_mesh() == this)
00618          return false;
00619       control_mesh()->set_cur_mesh(this);
00620       return true;
00621    }
00622 
00623    // Debugging:
00624    static bool debug = Config::get_var_bool("DEBUG_SUBDIVISION",false);
00625    static uint fnum = 0;
00626    if (debug && ret) {
00627       if (fnum != VIEW::stamp()) {
00628          fnum = VIEW::stamp();
00629          cerr << "******** frame " << fnum << " ********" << endl;
00630       }
00631       if (level > 0 && ret) {
00632          err_adv(debug, "%s: level %d updating subdiv mesh",
00633                  **get_name(this), _subdiv_level);
00634       }
00635    }
00636    err_adv(ret && debug,
00637            "level %d to level %d: %d faces, updating %d of %d vertices using %s",
00638            subdiv_level(),
00639            level,
00640            _faces.num(),
00641            _dirty_verts.num(),
00642            _verts.num(),
00643            **_loc_calc->name());
00644 
00645    // Q: How do we know which mesh elements to visit to tell them
00646    //    to generate and update their subdivision elements?
00647    // A: Well, we could just visit them all.
00648    // Q: NO, that would be too slow!!! Instead we choose this
00649    //    convoluted method: Vertices that haven't updated their
00650    //    subdivision vertices are in the "dirty" list. Edges and
00651    //    faces that haven't updated their subdivision elements
00652    //    don't have a dirty list to get into, but they are always
00653    //    adjacent to at least one dirty vertex. So we visit all the
00654    //    dirty vertices and tell them and their adjacent edges and
00655    //    faces to allocate their subdivision elements.
00656 
00657    if (debug && ret) {
00658       err_adv(0, "level %d: %d faces, updating %d of %d vertices using %s",
00659               subdiv_level(),
00660               _faces.num(),
00661               _dirty_verts.num(),
00662               _verts.num(),
00663               **_loc_calc->name());
00664       debug_check_verts("  before", _verts, _dirty_verts);
00665    }
00666    while (!_dirty_verts.empty()) {
00667       Lvert* v = (Lvert*)_dirty_verts.pop();
00668       v->clear_bit(Lvert::DIRTY_VERT_LIST_BIT);
00669       // See inline helper function update_sub(Lvert* v) above
00670       update_sub(v);
00671    }
00672    if (debug && ret) {
00673       debug_check_verts("  after", _verts, _dirty_verts);
00674    }
00675 
00676    if (0 && ret && debug)
00677       _subdiv_mesh->print();
00678 
00679    ret = _subdiv_mesh->update_subdivision(level-1) || ret;
00680 
00681    if (ret && is_control_mesh())
00682       changed(RENDERING_CHANGED);
00683    return ret;
00684 }
00685 
00686 inline void
00687 update_verts(CBvert_list& verts)
00688 {
00689    // helper for LMESH::update_subdivision(CBface_list& faces)
00690    for (int i=0; i<verts.num(); i++)
00691       ((Lvert*)verts[i])->update_subdivision();
00692 }
00693 
00694 inline void
00695 update_edges(CBedge_list& edges)
00696 {
00697    // helper for LMESH::update_subdivision(CBface_list& faces)
00698    for (int i=0; i<edges.num(); i++)
00699       ((Ledge*)edges[i])->update_subdivision();
00700 }
00701 
00702 inline void
00703 update_faces(CBface_list& faces, bool debug)
00704 {
00705    // helper for LMESH::update_subdivision(CBface_list& faces)
00706 
00707    err_adv(debug, "updating verts");
00708    update_verts(faces.get_verts());
00709 
00710    err_adv(debug, "updating edges");
00711    update_edges(faces.get_edges());
00712 
00713    err_adv(debug, "updating faces");
00714    for (int i=0; i<faces.num(); i++)
00715       allocate_child_faces((Lface*)faces[i]);
00716 }
00717 
00718 bool
00719 LMESH::update_subdivision(CBface_list& faces, int k)
00720 {
00721    static bool debug = Config::get_var_bool("DEBUG_BFACE_LIST_SUBDIVISION",false);
00722 
00723    if (debug) {
00724       cerr << "LMESH::update_subdivision: " << faces.num()
00725            << " faces to level "<< k << endl;
00726    }
00727 
00728    if (k  < 0)
00729       return false;
00730 
00731    if (faces.empty())
00732       return true;
00733 
00734    LMESH* m = LMESH::upcast(faces.mesh());
00735    if (!m) {
00736       err_adv(debug, "  error: non-LMESH");
00737       return false;
00738    }
00739 
00740    // Ensure mesh is up-to-date wrt controllers
00741    BMESHobs::broadcast_update_request(m);
00742 
00743    if (k == 0)
00744       return true;
00745 
00746    // generate lext-level mesh if needed
00747    if (!m->allocate_subdiv_mesh()) {
00748       err_adv(debug, "  error: can't allocate subdiv mesh");
00749       return false;
00750    }
00751 
00752    // update subdivision for the one-ring, 1-level down
00753    update_faces(faces.one_ring_faces(), debug);
00754    update_faces(faces.secondary_faces(), debug);
00755 
00756    assert(m->subdiv_mesh());
00757    m->subdiv_mesh()->changed(VERT_POSITIONS_CHANGED);
00758 
00759    // then recurse
00760    return update_subdivision(get_subdiv_faces(faces,1), k-1);
00761 }
00762 
00763 void
00764 LMESH::subdivide_in_place()
00765 {
00766    if (is_control_mesh()) {
00767 
00768       // produce the subdivision mesh
00769       refine();
00770 
00771       // copy it for safety
00772       // (blowing us away blows it away)
00773       LMESHptr sub = new LMESH;
00774       *sub = *_subdiv_mesh;
00775 
00776       // now blow us away and replace
00777       // with copy of subdivision mesh
00778       *this = *sub;
00779    } else
00780       err_msg("LMESH::subdivide_in_place: error: this not control mesh");
00781 }
00782 
00783 void
00784 LMESH::delete_subdiv_mesh()
00785 {
00786    // Notify observers that it's gonna happen
00787    BMESHobs::broadcast_sub_delete(this);
00788 
00789    if (is_control_mesh() && _subdiv_mesh) {
00790       int k;
00791       for (k = 0; k < nfaces(); k++)
00792          lf(k)->delete_subdiv_elements();
00793       for(k = 0; k < nedges(); k++)
00794          le(k)->delete_subdiv_elements();
00795       for(k = 0; k < nverts(); k++)
00796          lv(k)->delete_subdiv_vert();
00797       for(k = 0; k < _patches.num(); k++)
00798          ((Lpatch*)_patches[k])->clear_subdiv_strips(1);
00799    }
00800    if (is_control_mesh())
00801       set_cur_mesh(this);
00802    _subdiv_mesh = 0;    // deletes _subdiv_mesh thru ref-counting
00803 }
00804 
00805 void
00806 LMESH::delete_elements()
00807 {
00808    delete_subdiv_mesh();
00809    BMESH::delete_elements();
00810 }
00811 
00812 void
00813 LMESH::set_cur_mesh(LMESH* cur)
00814 {
00815    if (is_control_mesh()) {
00816       if (_cur_mesh != cur) {
00817          bool coi = is_center_of_interest(_cur_mesh);
00818          _cur_mesh = cur;
00819          if (coi)
00820             set_center_of_interest(_cur_mesh);
00821          changed(RENDERING_CHANGED);
00822       }
00823    } else
00824       err_msg("LMESH::set_cur_mesh: error: called on non-control mesh");
00825 }
00826 
00827 void
00828 LMESH::refine()
00829 {
00830    // Called on control mesh.
00831    //
00832    // Effect is to assign:
00833    //   _cur_mesh = _cur_mesh->subdiv_mesh()
00834 
00835    if (!is_control_mesh())
00836       return;
00837 
00838    if (is_control_mesh()) {
00839 
00840       int new_level = _cur_mesh->subdiv_level() + 1;
00841 
00842       // do it:
00843       update_subdivision(new_level);
00844    }
00845 }
00846 
00847 void
00848 LMESH::unrefine()
00849 {
00850    if (is_control_mesh() && _cur_mesh != this) {
00851       set_cur_mesh(_cur_mesh->_parent_mesh);
00852       while (edit_level() > cur_level())
00853          dec_edit_level();
00854    }
00855 }
00856 
00857 void
00858 LMESH::inc_edit_level()
00859 {
00860    int prev_edit_level = edit_level();
00861 
00862    control_mesh()->BMESH::inc_edit_level();
00863    if (is_control_mesh() && cur_level() < edit_level())
00864       update_subdivision(edit_level()); // calls changed()
00865    else
00866       control_mesh()->changed(RENDERING_CHANGED);
00867 
00868    MeshGlobal::edit_level_changed(control_mesh(),
00869                                   prev_edit_level,
00870                                   control_mesh()->edit_level());
00871 }
00872 
00873 void
00874 LMESH::dec_edit_level()
00875 {
00876    int prev_edit_level = edit_level();
00877 
00878    control_mesh()->BMESH::dec_edit_level();
00879    control_mesh()->changed(RENDERING_CHANGED);
00880 
00881    MeshGlobal::edit_level_changed(control_mesh(),
00882                                   prev_edit_level,
00883                                   control_mesh()->edit_level());
00884 }
00885 
00886 bool
00887 LMESH::set_edit_level(int level)
00888 {
00889    // XXX make sure it doesnt go
00890    // past current subdiv level ?
00891    // ... john
00892                 
00893    while (level > edit_level())
00894       control_mesh()->inc_edit_level();
00895    while (level < edit_level())
00896       control_mesh()->dec_edit_level();
00897         
00898    return true;
00899 }
00900 
00901 void
00902 LMESH::mark_all_dirty()
00903 {
00904    int i;
00905    for (i=0; i<nverts(); i++)
00906       lv(i)->mark_dirty(Lvert::SUBDIV_LOC_VALID_BIT);
00907    for (i=0; i<nedges(); i++)
00908       le(i)->clear_bit(Ledge::SUBDIV_LOC_VALID_BIT);
00909    if (_subdiv_mesh)
00910       _subdiv_mesh->mark_all_dirty();
00911 }
00912 
00913 void
00914 LMESH::fit(ARRAY<Lvert*>& verts, bool do_gauss_seidel)
00915 {
00916    static bool debug = Config::get_var_bool("DEBUG_LMESH_FIT",false);
00917    static bool move_along_normal =
00918       Config::get_var_bool("FITTING_MOVE_ALONG_NORMAL",false);
00919 
00920    if (verts.empty())
00921       return;
00922 
00923    // calculate the bounding box of the vertices
00924    BBOX box;
00925    int i;
00926    for (i=0; i<verts.num(); i++)
00927       box.update(verts[i]->loc());
00928 
00929    double max_err = box.dim().length() * 1e-5;
00930 
00931    int n = verts.num();
00932 
00933    // get original control point locations
00934    ARRAY<Wpt> C(n);   // original control points
00935    ARRAY<Wpt> L(n);   // current limit points
00936    for (i=0; i<n; i++) {
00937       C += verts[i]->loc();
00938       L += Wpt::Origin();
00939    }
00940 
00941    if(debug) {
00942       cerr << "LMESH::fit- fitting " << n << " vertices"<<endl;
00943       cerr << "Max_err = " << max_err <<endl;
00944    }
00945 
00946    // do 50 iterations...
00947    double prev_err = 0;
00948    ARRAY<double> errors;
00949    for (int k=0; k<50; k++) {
00950 
00951       errors.clear();
00952 
00953       double err = 0;
00954 
00955       if (do_gauss_seidel) {
00956 
00957          // Gauss-Seidel iteration: use updated values from the
00958          // current iteration as they are computed...
00959          for (int j=0; j<n; j++) {
00960             // don't need that L[] array...
00961             Wpt limit;
00962             verts[j]->limit_loc(limit);
00963             Wvec delt = C[j] - limit;
00964             errors+=delt.length();
00965             err += delt.length();
00966             if(move_along_normal)
00967                delt = delt*verts[j]->norm()*verts[j]->norm();
00968             verts[j]->offset_loc(delt);
00969          }
00970 
00971       } else {
00972          // compute the new offsets from the offsets computed in the
00973          // previous iteration
00974          int j;
00975          for (j=0; j<n; j++)
00976             verts[j]->limit_loc(L[j]);
00977 
00978          for (j=0; j<n; j++) {
00979             Wvec delt = C[j] - L[j];
00980 
00981             err += delt.length();
00982             errors+=delt.length();
00983             if(move_along_normal)
00984                delt = delt*verts[j]->norm()*verts[j]->norm();
00985             verts[j]->offset_loc(delt);
00986          }
00987       }
00988       // compute the average error:
00989       err /= n;
00990 
00991       double avg,std_d,max,min;
00992       if (debug) {
00993          if (prev_err != 0) {
00994             err_msg("Iter %d: avg error: %f, reduction: %f",
00995                     k, err, err/prev_err);
00996             statistics(errors,true,&avg,&std_d,&max,&min);
00997          } else {
00998             err_msg("Iter %d: avg error: %f", k, err);
00999             statistics(errors,true,&avg,&std_d,&max,&min);
01000          }
01001       } else
01002          statistics(errors,false,&avg,&std_d,&max,&min);
01003 
01004       prev_err = err;
01005 
01006       if (max < max_err) {
01007          if(debug) cerr << "Terminating at " << k <<" th iterations"<<endl;
01008          return;
01009       }
01010    }
01011 }
01012 
01013 inline void
01014 add_p(Lvert* v, Bvert_list& vp, Bedge_list& ep)
01015 {
01016    // Helper method used below in get_parents();
01017    // Given an Lvert, add its parent simplex to the
01018    // appropriate list depending on whether the parent
01019    // is an Lvert or Ledge.
01020 
01021    assert(v);
01022 
01023    Bsimplex* p = v->parent();
01024    if (!p)
01025       return;
01026    if (is_vert(p))
01027       vp += (Bvert*)p;
01028    else if (is_edge(p))
01029       ep += (Bedge*)p;
01030    else
01031       assert(0);
01032 }
01033 
01034 inline void
01035 get_parents(CBvert_list& verts, Bvert_list& vp, Bedge_list& ep)
01036 {
01037    // Helper method used below in get_parents();
01038    // from the given list of vertices, return the parent
01039    // simplices in two lists: one of Lverts, one of Ledges.
01040 
01041    if (verts.empty())
01042       return;
01043 
01044    assert(LMESH::isa(verts.mesh()));
01045 
01046    for (int i=0; i<verts.num(); i++)
01047       add_p((Lvert*)verts[i], vp, ep);
01048 }
01049 
01050 inline void
01051 clear_face_flags(CBvert_list& verts)
01052 {
01053    // Helper method used below in get_parents();
01054    // clear flags of faces adjacent to the given vertices,
01055    // including faces that are not stricly adjacent, but
01056    // that are part of a quad that contains the vertex.
01057 
01058    Bface_list star;
01059    for (int i=0; i<verts.num(); i++) {
01060       verts[i]->get_q_faces(star);
01061       star.clear_flags();
01062    }
01063 }
01064 
01065 inline void
01066 try_append(Bface_list& A, Bface* f)
01067 {
01068    // Helper method used below in try_append();
01069 
01070    if (f && !f->flag()) {
01071       f->set_flag();
01072       A += f;
01073    }
01074 }
01075 
01076 inline void
01077 try_append(Bface_list& A, CBface_list& B)
01078 {
01079    // Helper method used below in get_q_faces();
01080    // append faces from list B to list A, provided
01081    // the face flag is clear. Set the flag after
01082    // appending.
01083 
01084    for (int i=0; i<B.num(); i++)
01085       try_append(A, B[i]);
01086 }
01087 
01088 inline Bface_list
01089 get_q_faces(CBvert_list& verts)
01090 {
01091    // Helper method used below in get_parents();
01092    // return all faces adjacent to the given vertices,
01093    // including faces that are not stricly adjacent, but
01094    // that are part of a quad that contains the vertex.
01095 
01096    Bface_list ret, star;
01097    for (int i=0; i<verts.num(); i++) {
01098       verts[i]->get_q_faces(star);
01099       try_append(ret, star);
01100    }
01101    return ret;
01102 }
01103 
01104 Bvert_list
01105 LMESH::get_subdiv_inputs(CBvert_list& verts)
01106 {
01107    static bool debug = Config::get_var_bool("DEBUG_LMESH_SUBDIV_INPUTS",false);
01108 
01109    // Given a set of vertices from the same LMESH, return
01110    // the vertices of the parent LMESH that affect the
01111    // subdivision locations of the given vertices.
01112 
01113    // Require verts share common LMESH
01114    // XXX - could relax this, provided we test each Bvert
01115    //       to ensure it is really an Lvert.
01116    if (!isa(verts.mesh()))
01117       return Bvert_list();
01118 
01119    // Get direct parent vertices and edges
01120    Bvert_list vp;       // vertex parents
01121    Bedge_list ep;       // edge parents
01122    get_parents(verts, vp, ep);
01123 
01124    err_adv(debug, "%d verts: parents: %d verts, %d edges",
01125            verts.num(), vp.num(), ep.num());
01126 
01127    // Clear flags of all adjacent faces
01128    clear_face_flags(vp);
01129    ep.clear_flag02();
01130 
01131    // Put all adjacent faces into a list
01132    Bface_list faces = get_q_faces(vp);
01133    err_adv(debug, "parent faces from verts: %d", faces.num());
01134    try_append(faces, ep.get_primary_faces());
01135    err_adv(debug, "parent faces from edges too: %d", faces.num());
01136 
01137    // Pull out the vertices:
01138    return faces.get_verts();
01139 }
01140 
01141 void
01142 LMESH::send_update_notification()
01143 {
01144    // Send controllers a message to do their mesh modifications
01145    // now:
01146    BMESH::send_update_notification();
01147 
01148    // If that did anything, subdivision meshes may be out of
01149    // date. Update them if needed:
01150    update();
01151 }
01152 
01153 inline LMESHptr
01154 bmesh_to_lmesh(BMESHptr mesh)
01155 {
01156    // If the given mesh is an LMESH, return it.
01157    // Otherwise allocate a new LMESH, copy the data
01158    // from the given mesh, and return the LMESH.
01159 
01160    if (!mesh) return 0;
01161    LMESHptr ret = LMESH::upcast(&*mesh);
01162    if (!ret) {
01163       ret = new LMESH;
01164       *ret = *mesh;
01165    }
01166    return ret;
01167 }
01168 
01169 LMESHptr
01170 LMESH::read_jot_stream(istream& in)
01171 {
01172    // Convenience method to read a mesh from a given stream
01173    // and return it as an LMESH:
01174 
01175    return bmesh_to_lmesh(BMESH::read_jot_stream(in));
01176 }
01177 
01178 LMESHptr
01179 LMESH::read_jot_file(char* filename)
01180 {
01181    // Convenience method to read a mesh from a given stream
01182    // and return it as an LMESH:
01183 
01184    return bmesh_to_lmesh(BMESH::read_jot_file(filename));
01185 }
01186 
01187 CTAGlist &
01188 LMESH::tags() const
01189 {
01190    return BMESH::tags();
01191 }
01192 
01193 // end of file lmesh.C

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