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

uv_data.C

Go to the documentation of this file.
00001 #include "geom/world.H"
00002 #include "gtex/util.H"  // XXX - remove after done debugging
00003 #include "std/config.H"
00004 #include "mesh/uv_data.H"
00005 
00006 using namespace mlib;
00007 
00008 static bool debug = Config::get_var_bool("DEBUG_UV_DATA",false);
00009 
00010 /*****************************************************************
00011  * UVdata
00012  *****************************************************************/
00013 UVdata::UVdata(Bsimplex* s) :
00014    SimplexData(key(), s),
00015    _uv_valid(false),
00016    _calc_type(SIMPLE_CALC),     // default: simple subdiv scheme
00017    _did_subdiv(false),
00018    _mapping(0) 
00019 {
00020    // The constructor is called (internally) only when the given
00021    // simplex does not already have a UVdata associated with it.
00022    //
00023    // UVdata gets looked-up by its classname.
00024 
00025    // For face data, slather UVdatas all over the
00026    // vertices and edges:
00027    if (is_face(s)) {
00028       Bface* f = (Bface*)s;
00029       get_data(f->v1());
00030       get_data(f->v2());
00031       get_data(f->v3());
00032       get_data(f->e1());
00033       get_data(f->e2());
00034       get_data(f->e3());
00035 
00036       // XXX - 
00037       //   If the UVdata is created on a pre-existing face
00038       //   that has already generated its subdivision
00039       //   elements, then currently the UVdatas won't be
00040       //   created on those subdivision elements ...
00041    }
00042 }
00043 
00044 bool 
00045 UVdata::quad_has_uv(CBface* f) 
00046 {
00047    // Simple check to see if the given Bface is a quad and
00048    // has continous uv-coordinates
00049 
00050    return (f            &&                   // non-null
00051            f->is_quad() &&                   // is a quad
00052            lookup(f)    &&                   // has UV-data
00053            is_continuous(f->weak_edge())     // UV is continuous in quad
00054            );
00055 }
00056 
00057 bool
00058 UVdata::get_uv(CBvert* v, UVpt& uv)
00059 {
00060    if (!v)
00061       return 0;
00062 
00063    // Try the lightweight way first:
00064    UVdata* uvd = lookup(v);
00065    if (uvd && uvd->_uv_valid) {
00066       uv = uvd->_uv;
00067       return 1;
00068    }
00069 
00070    if (!is_continuous(v))
00071       return 0;
00072 
00073    return get_uv(v, v->get_face(), uv);
00074 }
00075 
00076 bool
00077 UVdata::get_uv(CBvert* v, CBface* f, UVpt& uv) 
00078 {
00079    // Extract uv-coords for a Bvert on a Bface,
00080    // checking for errors.
00081 
00082    // An error occurs if v or f are nil, or f does not contain
00083    // v, or there are no uv-coords assigned to v or f.
00084 
00085    UVdata* uvd = lookup(v);
00086    if (uvd && uvd->_uv_valid) {
00087       uv = uvd->_uv;
00088       return true;
00089    }
00090    if (f && f->contains(v) && has_uv(f)) {
00091       uv =  f->tex_coord(v);
00092       return true;
00093    }
00094    return false;
00095 }
00096 
00097 UVpt 
00098 UVdata::get_uv(CBvert* v, CBface* f) 
00099 {
00100    UVpt ret;
00101    if (!get_uv(v, f, ret) && debug) {
00102       if (!f) {
00103          err_msg("UVdata::get_uv: error: null face");
00104       } else {
00105          err_msg("UVdata::get_uv: error, showing triangle");
00106          GtexUtil::show_tris(Bface_list((Bface*)f));
00107       }
00108    }
00109    return ret;
00110 }
00111 
00112 CUVpt& 
00113 UVdata::uv(CBvert* v) const 
00114 {
00115    // Non-static method that is safe to call on a UVdata
00116    // associated w/ a face.
00117 
00118    // Prefer a uv-coord stored explicitly on the vertex:
00119    UVdata* uvd = lookup(v);
00120    if (uvd && uvd->_uv_valid)
00121       return uvd->_uv;
00122    else
00123       return face()->tex_coord(v);
00124 }
00125 
00126 bool
00127 UVdata::set(Bvert* v, CUVpt& uv) 
00128 {
00129    // If uv-coords around v are continuous, then assign a new
00130    // value at v and return true. Otherwise return false.
00131 
00132    if (!(v && is_continuous(v)))
00133       return 0;
00134    _set(v, uv);
00135    return 1;
00136 }
00137 
00138 void
00139 UVdata::split(Bvert* v)
00140 {
00141    if (!v) return;
00142 
00143    UVdata* uvd = lookup(v);
00144    if (uvd && uvd->_uv_valid) {
00145       // If uvd->_uv_valid is true, we must set it to false
00146       // and then push the old uv coord onto all the
00147       // neighboring faces.
00148       Bface_list faces = v->get_all_faces();
00149       for (int i=0; i<faces.num(); i++) {
00150          if (lookup(faces[i]) == NULL) {
00151             if (debug) {
00152                err_msg("UVdata::split: continous vert next to non-uv face!");
00153                GtexUtil::show_tris(Bface_list(faces[i]));
00154                WORLD::show(v->loc(), 6, Color::red);
00155             }
00156             continue;
00157          }
00158 //         get_data(faces[i]);
00159          assert(lookup(faces[i]) != NULL); // must be, right?
00160          faces[i]->tex_coord(v) = uvd->_uv;
00161       }
00162       uvd->_uv_valid = false;
00163    }
00164 }
00165 
00166 void
00167 UVdata::split(CBvert_list& verts)
00168 {
00169    for (int i=0; i<verts.num(); i++)
00170       UVdata::split(verts[i]);
00171 }
00172 
00173 void
00174 UVdata::split_chain(Bvert_list chain)
00175 {
00176    split(chain);
00177    for (Bvert_list next; get_subdiv_chain(chain, 1, next); chain = next)
00178       split(next);
00179 }
00180 
00181 void
00182 UVdata::split(CEdgeStrip& strip)
00183 {
00184    ARRAY<Bvert_list> chains;
00185    strip.get_chains(chains);
00186    for (int i=0; i<chains.num(); i++)
00187       split_chain(chains[i]);
00188 }
00189 
00190 bool
00191 UVdata::set(Bvert* v, Bface* f, CUVpt& uv)
00192 {
00193    // Set uv-coords on a face for a given vertex
00194 
00195    // Doesn't hurt to be careful:
00196    if (!(f && v))
00197       return false;
00198 
00199    // Sometimes they toy with us:
00200    if (!f->contains(v)) {
00201       err_msg("UVdata::set: Error: face doesn't contain given vertex");
00202       return false;
00203    }
00204 
00205    split(v);
00206    // We are setting the uv-coord per face for this vertex. So if
00207    // there was previously an assignment of continuous uv at the
00208    // given vertex, we must clear that away.
00209 //    UVdata* uvd = lookup(v);
00210 //    if (uvd && uvd->_uv_valid) {
00211 //       // If uvd->_uv_valid is true, we must set it to false
00212 //       // and then push the old uv coord onto all the
00213 //       // neighboring faces.
00214 //       Bface_list faces = v->get_all_faces();
00215 //       for (int i=0; i<faces.num(); i++) {
00216 //          get_data(faces[i]);
00217 // //         assert(lookup(faces[i]) != NULL); // must be, right?
00218 //          faces[i]->tex_coord(v) = uvd->_uv;
00219 //       }
00220 //       uvd->_uv_valid = false;
00221 //    }
00222 
00223    // Make sure UVdata is there
00224    get_data(f);
00225 
00226    // Set the per-face uv-coords:
00227    f->tex_coord(v) = uv;
00228 
00229    return true;
00230 }
00231 
00232 bool 
00233 UVdata::offset_uv(Bvert* v, CUVvec& delt)
00234 {
00235    UVpt cur;
00236    if (!get_uv(v, cur))
00237       return 0;
00238    return set(v, cur + delt);
00239 }
00240 
00241 bool
00242 UVdata::offset_uv(Bvert* v, Bface* f, CUVvec& delt)
00243 {
00244    UVpt cur;
00245    if (!get_uv(v, f, cur))
00246       return 0;
00247    return set(v, f, cur + delt);
00248 }
00249 
00250 bool 
00251 UVdata::set(
00252    Bvert*   a, Bvert*   b, Bvert*   c,
00253    CUVpt& uva, CUVpt& uvb, CUVpt& uvc
00254    )
00255 {
00256    // Set uv-coords on a face
00257    // (provided the 3 CCW verts define one):
00258 
00259    //                 c                               
00260    //                /|                                
00261    //              /  |                                
00262    //            /    |                                
00263    //          /      |                                
00264    //        /        |                                
00265    //      /          |                                
00266    //    a ---------- b                                
00267    //
00268 
00269    // First try to get the face
00270    Bface* f = lookup_face(a,b,c);
00271    return f ? set(f, a, b, c, uva, uvb, uvc) : false;
00272 }
00273 
00274 bool 
00275 UVdata::set(
00276    Bvert*   a, Bvert*   b, Bvert*   c, Bvert*   d,
00277    CUVpt& uva, CUVpt& uvb, CUVpt& uvc, CUVpt& uvd
00278    )
00279 {
00280    // Set uv-coords on a quad
00281    // (provided the 4 CCW verts define one):
00282 
00283    //    d ---------- c                               
00284    //    |            |                                
00285    //    |            |                                
00286    //    |            |                                
00287    //    |            |                                
00288    //    |            |                                
00289    //    |            |                                
00290    //    a ---------- b                                
00291    //
00292    // We'll try the diagonal both ways before giving up...
00293 
00294    // First try to get the two faces assuming the diagonal
00295    // runs from a to c:
00296    Bface* lower = lookup_face(a,b,c);
00297    Bface* upper = lookup_face(a,c,d);
00298 
00299    if (upper && lower) {
00300       set(lower, a, b, c, uva, uvb, uvc);
00301       set(upper, a, c, d, uva, uvc, uvd);
00302       return true;
00303    }
00304 
00305    // If that didn't work try it the other way:
00306    lower = lookup_face(a,b,d);
00307    upper = lookup_face(b,c,d);
00308 
00309    if (upper && lower) {
00310       set(lower, a, b, d, uva, uvb, uvd);
00311       set(upper, b, c, d, uvb, uvc, uvd);
00312       return true;
00313    }
00314 
00315    // We didn't want to do it anyway
00316    return false;
00317 }
00318 
00319 bool 
00320 UVdata::get_quad_uvs(
00321    CBface* f,
00322    UVpt& uva,
00323    UVpt& uvb,
00324    UVpt& uvc,
00325    UVpt& uvd)
00326 {
00327    // Pull out the uv-coordinates (in standard quad order)
00328    // from the given Bface that is supposedly a quad.
00329 
00330    //    d ---------- c                               
00331    //    |          / |                                
00332    //    |        /   |                                
00333    //    |      /     |                                
00334    //    |    /       |                                
00335    //    |  /         |                                
00336    //    |/           |                                
00337    //    a ---------- b                                
00338    //
00339    //   STANDARD QUAD ORDER
00340 
00341    Bvert *a=0, *b=0, *c=0, *d=0;
00342    return (f && f->get_quad_verts(a, b, c, d) &&
00343            get_quad_uvs(a,b,c,d,uva,uvb,uvc,uvd));
00344 }
00345 
00346 bool 
00347 UVdata::get_quad_uvs(
00348    CBvert* a,
00349    CBvert* b,
00350    CBvert* c,
00351    CBvert* d,
00352    UVpt& uva,
00353    UVpt& uvb,
00354    UVpt& uvc,
00355    UVpt& uvd)
00356 {
00357    // Pull out the uv-coordinates from the 4 given vertices
00358    // that supposedly form a quad.
00359 
00360    //    d ---------- c                               
00361    //    |            |                                
00362    //    |            |                                
00363    //    |            |                                
00364    //    |            |                                
00365    //    |            |                                
00366    //    |            |                                
00367    //    a ---------- b                                
00368    //
00369 
00370    if (!(a && b && c && d))
00371       return false;
00372 
00373    // Try the diagonal running NE:
00374    Bedge* e = a->lookup_edge(c);
00375    if (e) {
00376       if (!quad_has_uv(e->f1()))
00377          return 0;
00378 
00379       // Get the two faces, trying the diagonal running NE
00380       Bface* lower = lookup_face(a,b,c);
00381       Bface* upper = lookup_face(a,c,d);
00382 
00383       // Should never fail, but check anyway:
00384       if (!(upper && lower))
00385          return 0;
00386 
00387       // Get the data and return happy
00388       uva = get_uv(a, lower);
00389       uvb = get_uv(b, lower);
00390       uvc = get_uv(c, lower);
00391       uvd = get_uv(d, upper);
00392 
00393       return 1;
00394    }
00395 
00396    // Try the diagonal the other way:
00397    e = b->lookup_edge(d);
00398    if (!(e && quad_has_uv(e->f1())))
00399       return 0;
00400 
00401    // Get the two faces, trying the diagonal running NE
00402    Bface* lower = lookup_face(a,b,d);
00403    Bface* upper = lookup_face(b,c,d);
00404 
00405    // Should never fail, but check anyway:
00406    if (!(upper && lower))
00407       return 0;
00408 
00409    // Get the data and return happy
00410    uva = get_uv(a, lower);
00411    uvb = get_uv(b, lower);
00412    uvc = get_uv(c, upper);
00413    uvd = get_uv(d, upper);
00414 
00415    return 1;
00416 }
00417 
00418 bool
00419 UVdata::quad_interp_texcoord(CBface* f, CUVpt& uv, UVpt& ret)
00420 {
00421    // For the given quad, use bilinear interpolation on the
00422    // UV coordinates at the quad vertices to map the given
00423    // UV coordinate (WRT the quad) to a UV coordinate. I.e.,
00424    // the 'UV' coordinate in this case can vary from (0,0)
00425    // in the lower left corner of the quad (see below) to
00426    // (1,1) in the upper right.
00427    //
00428    // For this to succeed, the given Bface must be a quad,
00429    // there must be texture coordinates defined at the 4
00430    // quad vertices, and there can be no UV-discontinuity
00431    // along the quad diagonal.
00432 
00433    //
00434    //    d ---------- c                               
00435    //    |          / |                                
00436    //    |        /   |                                
00437    //    |      /     |                                
00438    //    |    /       |                                
00439    //    |  /         |                                
00440    //    |/           |                                
00441    //    a ---------- b                                
00442    //
00443    //   STANDARD QUAD ORDER
00444 
00445    // Get the uv-coords at the four corners:
00446    UVpt uva, uvb, uvc, uvd;
00447    if (!get_quad_uvs(f, uva, uvb, uvc, uvd))
00448       return false;
00449 
00450    // Do bilinear interpolation
00451    UVvec x0 = uvb - uva;
00452    UVvec x1 = uvc - uvd;
00453    UVvec y0 = uvd - uva;
00454    ret = uva + x0*uv[0] + y0*uv[1] + (x1 - x0)*(uv[0]*uv[1]);
00455 
00456    return true;
00457 }
00458 
00459 bool
00460 UVdata::is_continuous(CBedge* e) 
00461 {
00462    // Check for uv discontinuity across the edge
00463    if (!e)
00464       return 1; // no edge -- whatever
00465 
00466    Bvert *v1 = e->v1(), *v2 = e->v2();  // Should always exist
00467    Bface *f1 = e->f1(), *f2 = e->f2();  // Either might be null
00468    UVdata* uvd1 = lookup(f1);
00469    UVdata* uvd2 = lookup(f2);
00470    if (!(uvd1 || uvd2)) {
00471       // no uv coords at all -- no discontinuity
00472       return 1;
00473    } else if (uvd1 && uvd2) {
00474       // uv on both sides -- continuous iff they agree:
00475       return (
00476          get_uv(v1,f1) == get_uv(v1,f2) &&
00477          get_uv(v2,f1) == get_uv(v2,f2)
00478          );
00479    } else {
00480       // uv on one side but not the other -- discontinuity
00481       // (but only if both faces are present)
00482       return !(f1 && f2);
00483    }
00484 }
00485 
00486 int 
00487 UVdata::discontinuity_degree(CBvert* v) 
00488 {
00489    // Gives the number of UV-discontinous edges adjacent to v:
00490 
00491    int ret = 0;
00492    for (int i=0; i<v->degree(); i++)
00493       if (!is_continuous(v->e(i)))
00494          ret++;
00495    return ret;
00496 }
00497 
00498 void
00499 UVdata::notify_subdiv_gen() 
00500 {
00501    // Called right after new subdivision elements have been
00502    // generated by the simplex upon which this UVdata is
00503    // stored. Now is the time to generate UVdata on the
00504    // newly created subdivision elements.
00505 
00506    if (is_face(simplex())) {
00507       // Propagate data to the 4 subdivision faces.
00508       // That also puts it on the subdivision verts and edges.
00509       Lface* f = (Lface*) simplex();
00510       get_data(f->subdiv_face1());
00511       get_data(f->subdiv_face2());
00512       get_data(f->subdiv_face3());
00513       get_data(f->subdiv_face_center());
00514    }
00515 }
00516 
00517 bool
00518 UVdata::handle_subdiv_calc()
00519 {
00520    // Some of you may have been wondering why anyone would
00521    // need UVdata on an edge. The whole reason is to pick up
00522    // this here callback, which is generated when it is time
00523    // to recompute subdivision values for an edge or vertex.
00524    // (I.e., this is also why you need UVdata on a vertex).
00525    //
00526    // XXX - Currently we aren't keeping track of when
00527    //       subdivision uv-coords need to be recomputed. We
00528    //       just get this callback whenever subdivision
00529    //       *locations* need to be recomputed. So the wrong
00530    //       thing happens if you change the uv-coords of the
00531    //       control mesh but not the vertex locations or
00532    //       connectivity. And if you change the vertex
00533    //       locations but not the uv-coords the latter get
00534    //       recomputed even though they don't need to be.
00535 
00536    // XXX - even worser: working on a deadline, we're changing
00537    //  mesh connectivity at arbitrary subdivision levels
00538    //  (not previously done), and that's leading to an assertion
00539    //  failure in subdiv_uv(Bedge*, Bface*) below...
00540    //  needs to get fixed (later)
00541    //   lem - 1/6/2002
00542 //   return 0;
00543 
00544    // Don't compute it more than once.  Current policy is uv
00545    // coords are assigned but not later edited or changed ever.
00546    // Why? Because with mesh connectivity edits happening at
00547    // arbitrary levels of subdivision, we don't want parent
00548    // elements forcing inappropriate uv values on elements at
00549    // current level. -- lem 12/29/2004; same deadline :(
00550    if (_did_subdiv) {
00551 //      return false;
00552    }
00553    _did_subdiv = true;
00554 
00555    if (is_edge(simplex())) {
00556       Ledge* e = (Ledge*) simplex();
00557 
00558       if ( !e->get_face() )
00559          return false;
00560 
00561       if (is_continuous(e)) {
00562          // Set a single uv-coord on the subdivision vertex
00563          // to be used regardless of the face containing it.
00564          _set(e->subdiv_vertex(), subdiv_uv(e, e->get_face()));
00565       } else {
00566          // Compute 2 separate subdiv uv-coords, set each one
00567          // on the 3 sub-faces on each side of the edge.
00568          // (If a face is missing or has no uv-coords it's a no-op).
00569          set_subdiv_uv(e, (Lface*)e->f1());
00570          set_subdiv_uv(e, (Lface*)e->f2());
00571       }
00572    } else if (is_vert(simplex())) {
00573       Lvert* v = (Lvert*) simplex();
00574 
00575       if ( !v->get_face() )
00576          return false;
00577 
00578       if (is_continuous(v)) {
00579          // Set a single uv-coord on the subdivision vertex
00580          // to be used regardless of the face containing it.
00581          _set(v->subdiv_vertex(), subdiv_uv(v, v->get_face()));
00582       } else {
00583          // Compute and set a separate uv-coord for each face
00584          // surrounding the subdiv vert:
00585          Bface_list faces;
00586          v->get_faces(faces);
00587          for (int i=0; i<faces.num(); i++)
00588             set_subdiv_uv(v, (Lface*)faces[i]);
00589       }
00590    } else {
00591       // We get here if this UVdata is on a Bface or a null simplex.
00592       // Neither should ever happen.
00593       assert(0);
00594    }
00595 
00596    // Returning 0 means we are not overriding the normal
00597    // subdivision calculation.
00598    return 0;
00599 }
00600 
00601 void
00602 UVdata::set_subdiv_uv(Ledge* e, Lface* f)
00603 {
00604    // Compute the uv-coords for the subdivision vertex of
00605    // the given edge e and set them on the 3 subdivision
00606    // faces generated by the given face f, which is adjacent
00607    // to e. (See ASCII diagram below).
00608 
00609    // Don't deal w/ null pointers
00610    if (!(e && f))
00611       return;
00612 
00613    // Do nothing if f has no uv-coords
00614    if (!lookup(f)) 
00615       return;
00616 
00617    // Don't put up with silliness
00618    assert(f->contains(e));
00619 
00620    /*      
00621    //
00622    //   e runs vertically from subv1 to subv2,
00623    //   f is on the right, producing 4 sub-faces. 
00624    // 
00625    //       subv1              
00626    //           | \            
00627    //           |   \ subva    
00628    //           | f1 /\        
00629    //           |  /  | \      
00630    //      subv |/  f2|   \                 
00631    //           | \   |  /     
00632    //           |   \ |/       
00633    //           | f3 / subvb   
00634    //           |  /           
00635    //           |/             
00636    //       subv2
00637    //                                                       
00638    //
00639    // We want to compute the uv-coords for e's subdivision vertex,
00640    // then set that uv-coord on the 3 sub-faces shown (f1, f2, f3).
00641    */   
00642    
00643    // Ensure subdiv elements exist:
00644    f->allocate_subdiv_elements();
00645 
00646    // Get the needed subdivision vertices
00647    Bvert* subv  = e->subdiv_vertex();
00648    Bvert* subv1 = e->lv(1)->subdiv_vertex();
00649    Bvert* subv2 = e->lv(2)->subdiv_vertex();
00650    Bvert* subva = ((Ledge*)f->other_edge(e->v1(),e))->subdiv_vertex();
00651    Bvert* subvb = ((Ledge*)f->other_edge(e->v2(),e))->subdiv_vertex();
00652 
00653    // Get the 3 sub-faces (CCW order is not relevant):
00654    Bface* f1 = lookup_face(subv1,subv,subva);
00655    Bface* f2 = lookup_face(subva,subv,subvb);
00656    Bface* f3 = lookup_face(subv2,subv,subvb);
00657 
00658    // Set the same uv-coords on the 3 faces
00659    CUVpt& uv = subdiv_uv(e, f);
00660    if (f1)
00661       set(subv, f1, uv);
00662    if (f2)
00663       set(subv, f2, uv);
00664    if (f3)
00665       set(subv, f3, uv);
00666 }
00667 
00668 void
00669 UVdata::set_subdiv_uv(Lvert* v, Lface* f)
00670 {
00671    // Compute the subdivision uv-coords for the given vertex
00672    // which belongs to the given face. Then assign those
00673    // uv-coords to the subdivison vertex of v on the
00674    // corresponding subdivision face of f.
00675 
00676    // Don't deal w/ null pointers
00677    if (!(v && f))
00678       return;
00679 
00680    // Do nothing if f has no uv-coords
00681    if (!lookup(f)) 
00682       return;
00683 
00684    // Don't put up with silliness
00685    assert(f->contains(v));
00686 
00687    /*******************************************************
00688    //                                                  
00689    //                      /\                          
00690    //                    /   \                         
00691    //                  /      \                        
00692    //          subvb /- - - - -\                       
00693    //              /  \      /  \                      
00694    //            /     \   /     \                     
00695    //          /  subf  \/        \                    
00696    //     subv --------------------                    
00697    //               subva                              
00698    //
00699    *******************************************************/
00700 
00701    // Ensure subdiv elements exist:
00702    f->allocate_subdiv_elements();
00703 
00704    // Get the needed subdivision vertices
00705    Bvert* subv  = v->subdiv_vertex();
00706    Bvert* subva = ((Ledge*)f->edge_from_vert(v))->subdiv_vertex();
00707    Bvert* subvb = ((Ledge*)f->edge_before_vert(v))->subdiv_vertex();
00708 
00709    // Get the sub-face:
00710    Bface* subf = lookup_face(subv,subva,subvb);
00711 
00712    // Set the uv-coord for the sub-vert on the sub-face:
00713    if (subf)
00714       set(subv, subf, subdiv_uv(v,f));
00715 }
00716 
00717 /*****************************************************************
00718  * Computing subdivision uv-coords
00719  *****************************************************************/
00720 #include "subdiv_calc.H"
00721 
00722 // Need this operator defined to instantiate LoopCalc<UVpt> below:
00723 UVpt
00724 operator+(CUVpt& a, CUVpt& b)
00725 {
00726    return UVpt(a[0] + b[0], a[1] + b[1]);
00727 }
00728 
00729 /*****************************************************************
00730  * LoopUV
00731  *
00732  *      Calculates subdivision values of uv-coordinates
00733  *****************************************************************/
00734 class LoopUV : public LoopCalc<UVpt> {
00735  protected:
00736    CBface*    _face; // Used in get_val() to lookup correct uv
00737 
00738  public:
00739    LoopUV(CBface* f) : _face(f) { assert(f); }
00740 
00741    //******** VALUE ACCESSORS ********
00742    virtual UVpt get_val(CBvert* v) const { return UVdata::get_uv(v, _face);}
00743 
00744    virtual UVpt centroid(CLvert* v) const;
00745 
00746    //******** SUBDIVISION CALCULATION ********
00747    virtual UVpt subdiv_val(CBvert* bv) const;
00748    virtual UVpt subdiv_val(CBedge* be) const;
00749 
00750    //******** GETTING MORE LIKE IT ********
00751    // we don't do duping
00752    virtual SubdivCalc<UVpt> *dup() const { return 0; }
00753 };
00754 
00755 UVpt
00756 LoopUV::centroid(CLvert* v) const
00757 {
00758    assert(v);
00759 
00760    switch (UVdata::discontinuity_degree(v)) {
00761     case 0:
00762     {
00763        // No discontinuity:
00764        UVpt ret;
00765        for (int i=0; i<v->degree(); i++)
00766           ret += UVdata::get_uv(v->nbr(i), v->e(i)->get_face());
00767        return ret / v->degree();
00768     }
00769     case 2:
00770     {
00771        // Find the 2 discontinuity edges and get the uv values of
00772        // their opposite vertices that agree with the current vertex.
00773        CUVpt& uv = UVdata::get_uv(v,_face);
00774        UVpt ret;
00775        for (int i=0; i<v->degree(); i++) {
00776           Bedge* e = v->e(i);
00777           if (!UVdata::is_continuous(e)) {
00778              if (UVdata::lookup(e->f1()) && UVdata::get_uv(v,e->f1()) == uv)
00779                 ret += UVdata::get_uv(v->nbr(i), e->f1());
00780              else if (UVdata::lookup(e->f2()) &&
00781                       UVdata::get_uv(v,e->f2()) == uv)
00782                 ret += UVdata::get_uv(v->nbr(i), e->f2());
00783              else
00784                 assert(0);
00785           }
00786        }
00787        return ret/2;
00788     }
00789     default:
00790        // Treat as a corner vertex
00791        return UVdata::get_uv(v, _face);
00792    }
00793 }
00794 
00795 UVpt
00796 LoopUV::subdiv_val(CBvert* bv) const 
00797 {
00798    assert(bv);
00799 
00800    // XXX - has to be an Lvert
00801    Lvert* v = (Lvert*)bv;
00802    switch (UVdata::discontinuity_degree(v)) {
00803     case 0:     return smooth_subdiv_val(v);
00804     case 2:     return crease_subdiv_val(v);
00805     default:    return get_val(v);
00806    }
00807 }
00808 
00809 UVpt
00810 LoopUV::subdiv_val(CBedge* e) const 
00811 {
00812    assert(e);
00813 
00814    if (UVdata::is_continuous(e)) {
00815       return (
00816          (get_val(e->v1()) + get_val(e->v2()))*3.0 +
00817          UVdata::get_uv(e->opposite_vert1(), e->f1()) +
00818          UVdata::get_uv(e->opposite_vert2(), e->f2())
00819          )/8.0;
00820    } else {
00821       return (get_val(e->v1()) + get_val(e->v2()))/2.0;
00822    }
00823 }
00824 
00825 /*****************************************************************
00826  * SimpleUVCalc:
00827  *
00828  *      Calculates subdivision values of uv-coordinates via simple
00829  *      scheme.
00830  *****************************************************************/
00831 class SimpleUVCalc : public SimpleCalc<UVpt> {
00832  protected:
00833    CBface*    _face; // Used in get_val() to lookup correct uv
00834 
00835  public:
00836    //******** MANAGERS ********
00837    SimpleUVCalc(CBface* f) : _face(f) { assert(f); }
00838 
00839    //******** VALUE ACCESSORS ********
00840    virtual UVpt get_val(CBvert* v) const { return UVdata::get_uv(v, _face);}
00841 
00842    //******** SUBDIVISION CALCULATION ********
00843    virtual UVpt subdiv_val(CBvert* bv) const { return get_val(bv); }
00844    virtual UVpt subdiv_val(CBedge* be) const;
00845 
00846    //******** GETTING MORE LIKE IT ********
00847    // we don't do duping
00848    virtual SubdivCalc<UVpt> *dup() const { return 0; }
00849 };
00850 
00851 UVpt
00852 SimpleUVCalc::subdiv_val(CBedge* e) const 
00853 {
00854    assert(e);
00855 
00856    if (e->is_weak()) {
00857 
00858       // For quad diagonals we actually average the 4 quad points:
00859 
00860       Bface* f1 = e->f1();
00861       Bface* f2 = e->f2();
00862 
00863       if (debug && !UVdata::is_continuous(e)) {
00864          cerr << "SimpleUVCalc::subdiv_val: found discontinuous weak edge "
00865               << "at level " << e->mesh()->subdiv_level() << endl;
00866          WORLD::show(e->v1()->loc(), e->v2()->loc(), 4);
00867          return UVpt::Origin();
00868       }
00869 
00870       // Many assumptions should hold:
00871       //assert(UVdata::is_continuous(e));
00872       assert(f1 && f1->is_quad() &&
00873              f2 && f2->is_quad() && f1->quad_partner() == f2);
00874       assert(_face == f1 || _face == f2);
00875 
00876       return (
00877          UVdata::get_uv(f1->v1(), f1) +
00878          UVdata::get_uv(f1->v2(), f1) +
00879          UVdata::get_uv(f1->v3(), f1) +
00880          UVdata::get_uv(f1->quad_vert(), f2))/4.0;
00881    } else {
00882       return (get_val(e->v1()) + get_val(e->v2()))/2.0;
00883    }
00884 }
00885 
00886 UVpt
00887 UVdata::subdiv_uv(CBvert* v, CBface* f) const
00888 {
00889    switch(_calc_type) {
00890     case SIMPLE_CALC:   return SimpleUVCalc(f).subdiv_val(v);
00891     case HYBRID_CALC:     
00892       err_msg("UVdata::subdiv_uv: Hybrid scheme not implemented for UV");
00893       // No break - it drops down to the default clause:
00894     default:
00895       return LoopUV(f).subdiv_val(v);
00896    }
00897 }
00898 
00899 UVpt
00900 UVdata::subdiv_uv(CBedge* e, CBface* f) const
00901 {
00902    switch(_calc_type) {
00903     case SIMPLE_CALC:   return SimpleUVCalc(f).subdiv_val(e);
00904     case HYBRID_CALC:     
00905       err_msg("UVdata::subdiv_uv: Hybrid scheme not implemented for UV");
00906       // No break - it drops down to the default clause:
00907     default:
00908       return LoopUV(f).subdiv_val(e);
00909    }
00910 }
00911 
00912 /* end of file uv_data.C */

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