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