00001 #include "geom/world.H"
00002 #include "gtex/util.H"  
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 
00012 
00013 UVdata::UVdata(Bsimplex* s) :
00014    SimplexData(key(), s),
00015    _uv_valid(false),
00016    _calc_type(SIMPLE_CALC),     
00017    _did_subdiv(false),
00018    _mapping(0) 
00019 {
00020    
00021    
00022    
00023    
00024 
00025    
00026    
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       
00037       
00038       
00039       
00040       
00041    }
00042 }
00043 
00044 bool 
00045 UVdata::quad_has_uv(CBface* f) 
00046 {
00047    
00048    
00049 
00050    return (f            &&                   
00051            f->is_quad() &&                   
00052            lookup(f)    &&                   
00053            is_continuous(f->weak_edge())     
00054            );
00055 }
00056 
00057 bool
00058 UVdata::get_uv(CBvert* v, UVpt& uv)
00059 {
00060    if (!v)
00061       return 0;
00062 
00063    
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    
00080    
00081 
00082    
00083    
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    
00116    
00117 
00118    
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    
00130    
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       
00146       
00147       
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 
00159          assert(lookup(faces[i]) != NULL); 
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    
00194 
00195    
00196    if (!(f && v))
00197       return false;
00198 
00199    
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    
00207    
00208    
00209 
00210 
00211 
00212 
00213 
00214 
00215 
00216 
00217 
00218 
00219 
00220 
00221 
00222 
00223    
00224    get_data(f);
00225 
00226    
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    
00257    
00258 
00259    
00260    
00261    
00262    
00263    
00264    
00265    
00266    
00267    
00268 
00269    
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    
00281    
00282 
00283    
00284    
00285    
00286    
00287    
00288    
00289    
00290    
00291    
00292    
00293 
00294    
00295    
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    
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    
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    
00328    
00329 
00330    
00331    
00332    
00333    
00334    
00335    
00336    
00337    
00338    
00339    
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    
00358    
00359 
00360    
00361    
00362    
00363    
00364    
00365    
00366    
00367    
00368    
00369 
00370    if (!(a && b && c && d))
00371       return false;
00372 
00373    
00374    Bedge* e = a->lookup_edge(c);
00375    if (e) {
00376       if (!quad_has_uv(e->f1()))
00377          return 0;
00378 
00379       
00380       Bface* lower = lookup_face(a,b,c);
00381       Bface* upper = lookup_face(a,c,d);
00382 
00383       
00384       if (!(upper && lower))
00385          return 0;
00386 
00387       
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    
00397    e = b->lookup_edge(d);
00398    if (!(e && quad_has_uv(e->f1())))
00399       return 0;
00400 
00401    
00402    Bface* lower = lookup_face(a,b,d);
00403    Bface* upper = lookup_face(b,c,d);
00404 
00405    
00406    if (!(upper && lower))
00407       return 0;
00408 
00409    
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    
00422    
00423    
00424    
00425    
00426    
00427    
00428    
00429    
00430    
00431    
00432 
00433    
00434    
00435    
00436    
00437    
00438    
00439    
00440    
00441    
00442    
00443    
00444 
00445    
00446    UVpt uva, uvb, uvc, uvd;
00447    if (!get_quad_uvs(f, uva, uvb, uvc, uvd))
00448       return false;
00449 
00450    
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    
00463    if (!e)
00464       return 1; 
00465 
00466    Bvert *v1 = e->v1(), *v2 = e->v2();  
00467    Bface *f1 = e->f1(), *f2 = e->f2();  
00468    UVdata* uvd1 = lookup(f1);
00469    UVdata* uvd2 = lookup(f2);
00470    if (!(uvd1 || uvd2)) {
00471       
00472       return 1;
00473    } else if (uvd1 && uvd2) {
00474       
00475       return (
00476          get_uv(v1,f1) == get_uv(v1,f2) &&
00477          get_uv(v2,f1) == get_uv(v2,f2)
00478          );
00479    } else {
00480       
00481       
00482       return !(f1 && f2);
00483    }
00484 }
00485 
00486 int 
00487 UVdata::discontinuity_degree(CBvert* v) 
00488 {
00489    
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    
00502    
00503    
00504    
00505 
00506    if (is_face(simplex())) {
00507       
00508       
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    
00521    
00522    
00523    
00524    
00525    
00526    
00527    
00528    
00529    
00530    
00531    
00532    
00533    
00534    
00535 
00536    
00537    
00538    
00539    
00540    
00541    
00542 
00543 
00544    
00545    
00546    
00547    
00548    
00549    
00550    if (_did_subdiv) {
00551 
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          
00563          
00564          _set(e->subdiv_vertex(), subdiv_uv(e, e->get_face()));
00565       } else {
00566          
00567          
00568          
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          
00580          
00581          _set(v->subdiv_vertex(), subdiv_uv(v, v->get_face()));
00582       } else {
00583          
00584          
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       
00592       
00593       assert(0);
00594    }
00595 
00596    
00597    
00598    return 0;
00599 }
00600 
00601 void
00602 UVdata::set_subdiv_uv(Ledge* e, Lface* f)
00603 {
00604    
00605    
00606    
00607    
00608 
00609    
00610    if (!(e && f))
00611       return;
00612 
00613    
00614    if (!lookup(f)) 
00615       return;
00616 
00617    
00618    assert(f->contains(e));
00619 
00620    
00621 
00622 
00623 
00624 
00625 
00626 
00627 
00628 
00629 
00630 
00631 
00632 
00633 
00634 
00635 
00636 
00637 
00638 
00639 
00640 
00641    
00642    
00643    
00644    f->allocate_subdiv_elements();
00645 
00646    
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    
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    
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    
00672    
00673    
00674    
00675 
00676    
00677    if (!(v && f))
00678       return;
00679 
00680    
00681    if (!lookup(f)) 
00682       return;
00683 
00684    
00685    assert(f->contains(v));
00686 
00687    
00688 
00689 
00690 
00691 
00692 
00693 
00694 
00695 
00696 
00697 
00698 
00699 
00700 
00701    
00702    f->allocate_subdiv_elements();
00703 
00704    
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    
00710    Bface* subf = lookup_face(subv,subva,subvb);
00711 
00712    
00713    if (subf)
00714       set(subv, subf, subdiv_uv(v,f));
00715 }
00716 
00717 
00718 
00719 
00720 #include "subdiv_calc.H"
00721 
00722 
00723 UVpt
00724 operator+(CUVpt& a, CUVpt& b)
00725 {
00726    return UVpt(a[0] + b[0], a[1] + b[1]);
00727 }
00728 
00729 
00730 
00731 
00732 
00733 
00734 class LoopUV : public LoopCalc<UVpt> {
00735  protected:
00736    CBface*    _face; 
00737 
00738  public:
00739    LoopUV(CBface* f) : _face(f) { assert(f); }
00740 
00741    
00742    virtual UVpt get_val(CBvert* v) const { return UVdata::get_uv(v, _face);}
00743 
00744    virtual UVpt centroid(CLvert* v) const;
00745 
00746    
00747    virtual UVpt subdiv_val(CBvert* bv) const;
00748    virtual UVpt subdiv_val(CBedge* be) const;
00749 
00750    
00751    
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        
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        
00772        
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        
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    
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 
00827 
00828 
00829 
00830 
00831 class SimpleUVCalc : public SimpleCalc<UVpt> {
00832  protected:
00833    CBface*    _face; 
00834 
00835  public:
00836    
00837    SimpleUVCalc(CBface* f) : _face(f) { assert(f); }
00838 
00839    
00840    virtual UVpt get_val(CBvert* v) const { return UVdata::get_uv(v, _face);}
00841 
00842    
00843    virtual UVpt subdiv_val(CBvert* bv) const { return get_val(bv); }
00844    virtual UVpt subdiv_val(CBedge* be) const;
00845 
00846    
00847    
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       
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       
00871       
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       
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       
00907     default:
00908       return LoopUV(f).subdiv_val(e);
00909    }
00910 }
00911 
00912