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

uv_mapping.C

Go to the documentation of this file.
00001 #include "std/support.H" 
00002 #include "glew/glew.H" // XXX - remove when debugging phase is over
00003 
00004 #include "uv_data.H"
00005 #include "uv_mapping.H"
00006 #include "bmesh.H"
00007 #include "std/config.H"
00008 
00009 using namespace mlib;
00010 
00011 /*****************************************************************
00012  * UVMapping
00013  *****************************************************************/
00014 
00015 //XXX -The map dimension should really
00016 //be dynamically determined to optimize
00017 //some binning crtieria
00018 
00019 #define DEBUG_DOT_HEIGHT 200
00020 #define MAPPING_SIZE 100
00021 #define MAPPING_BINS MAPPING_SIZE*MAPPING_SIZE
00022 
00023 #define DEBUG_SIZE (MAPPING_SIZE + DEBUG_DOT_HEIGHT)*MAPPING_SIZE
00024 
00025 /////////////////////////////////////
00026 // Constructor
00027 /////////////////////////////////////
00028 UVMapping::UVMapping(Bface *f) :
00029    _seed_face(f),
00030    _face_cnt(0),
00031    _bin_cnt(0),
00032    _entry_cnt(0),
00033    _use_cnt(0),
00034    _du(-1.0),
00035    _dv(-1.0),
00036    _wrap_u(false),
00037    _wrap_v(false),
00038    _wrap_bad(false),
00039    _virgin_debug_image(0),
00040    _marked_debug_image(0)
00041 {
00042    
00043    int k;
00044 
00045    assert(_seed_face);
00046 
00047    _mapping.clear();
00048    for (k=0 ; k < MAPPING_BINS ; k++) _mapping.add(new ARRAY<Bface*>);
00049 
00050    compute_limits(f);
00051    compute_mapping(f);
00052    compute_wrapping(f);
00053 
00054    //If debug is set, generate texture map
00055    if (Config::get_var_bool("HATCHING_DEBUG_MAPPING",false))
00056       compute_debug_image();
00057 
00058 
00059 }
00060 
00061 /////////////////////////////////////
00062 // Destructor
00063 /////////////////////////////////////
00064 UVMapping::~UVMapping()
00065 {
00066 
00067 
00068    UVdata* uvd;
00069    int k, i, cnt=0;
00070 
00071    //We should be unreferenced if we get here...
00072    assert(!_use_cnt);
00073 
00074    //Remove ourself from the uvdata of binned faces
00075    for (k=0;k<_mapping.num();k++) 
00076       {
00077          for (i=0;i<_mapping[k]->num();i++) 
00078             {
00079                uvd = UVdata::lookup((*_mapping[k])[i]);
00080                assert(uvd);
00081                if (uvd->mapping())
00082                   {
00083                      assert(uvd->mapping()==this);
00084                      uvd->set_mapping(0);
00085                      cnt++;
00086                   }
00087             }
00088       }
00089 
00090    err_mesg(ERR_LEV_WARN,  
00091       "UVMapping::~UVMapping() - Removed from %d faces (should have been %d).",
00092          cnt, _face_cnt);
00093 
00094    for (k=0;k<_mapping.num();k++) delete _mapping[k];
00095    _mapping.clear();
00096 
00097    if (_virgin_debug_image) delete[] _virgin_debug_image;
00098    if (_marked_debug_image) delete[] _marked_debug_image;
00099 
00100 }
00101 
00102 /////////////////////////////////////
00103 // draw_debug()
00104 /////////////////////////////////////
00105 void 
00106 UVMapping::draw_debug() 
00107 {
00108 
00109    int w,h;
00110 
00111    VIEW_SIZE(w,h);         
00112    
00113    // before calling glRasterPos2i(),
00114    // first set up orthographic viewing
00115    // matrix for points in pixel coords:
00116    glMatrixMode(GL_MODELVIEW);
00117    glPushMatrix();
00118    glLoadIdentity();
00119    glMatrixMode(GL_PROJECTION);
00120    glPushMatrix();
00121    glLoadMatrixd(VIEW::peek()->pix_proj().transpose().matrix());
00122 
00123    glRasterPos2i(w-MAPPING_SIZE,0);
00124 
00125    glPushAttrib(GL_ENABLE_BIT);
00126    glDisable(GL_BLEND);
00127 
00128    glDrawPixels(MAPPING_SIZE,MAPPING_SIZE + DEBUG_DOT_HEIGHT,GL_RGB,GL_UNSIGNED_BYTE,_marked_debug_image);
00129 
00130    glPopAttrib();
00131 
00132    glPopMatrix();
00133    glMatrixMode(GL_MODELVIEW);
00134    glPopMatrix();
00135 }
00136 
00137 
00138 /////////////////////////////////////
00139 // compute_debug_image()
00140 /////////////////////////////////////
00141 //
00142 // -Creates a bitmap in which each pixel
00143 //  represents a bin
00144 // -The grey level is scaled to white
00145 //  where binning is maximum
00146 // -Empty bins appear red
00147 //
00148 /////////////////////////////////////
00149 void
00150 UVMapping::compute_debug_image()
00151 {
00152 
00153    err_mesg(ERR_LEV_SPAM, "UVMapping::compute_debug_map()");
00154 
00155    int k, max=0;
00156 
00157    assert(!_virgin_debug_image);
00158    assert(!_marked_debug_image);
00159 
00160    _virgin_debug_image = new unsigned char[3*DEBUG_SIZE];
00161    assert(_virgin_debug_image);
00162    _marked_debug_image = new unsigned char[3*DEBUG_SIZE];
00163    assert(_marked_debug_image);
00164 
00165    assert(_mapping.num() == MAPPING_BINS);
00166 
00167    for (k=0;k<_mapping.num();k++)
00168       if (_mapping[k]->num() > max)
00169          max = _mapping[k]->num();
00170 
00171    //The UV binning part
00172 
00173    GLubyte b;
00174    for (k=0;k<MAPPING_BINS;k++)
00175       {
00176          b = (unsigned char)( (double)(0x88)*
00177                               ( (double)(_mapping[k]->num()) / (double)(max) )  );
00178 
00179          if (b)
00180             {
00181                _virgin_debug_image[3*k  ] = b;
00182                _virgin_debug_image[3*k+1] = b;
00183                _virgin_debug_image[3*k+2] = b;
00184             }
00185          else
00186             {
00187                _virgin_debug_image[3*k  ] = 0;
00188                _virgin_debug_image[3*k+1] = 0x99;
00189                _virgin_debug_image[3*k+2] = 0xFF;
00190             }
00191       }
00192 
00193    //The dot product graph part
00194 
00195    for (k=MAPPING_BINS;k<DEBUG_SIZE;k++)
00196       {
00197          b = (unsigned char)0;
00198 
00199          _virgin_debug_image[3*k  ] = b;
00200          _virgin_debug_image[3*k+1] = b;
00201          _virgin_debug_image[3*k+2] = b;
00202 
00203       }
00204 
00205    int h = int(floor( ( 0.0 + 1.0 ) * (double) DEBUG_DOT_HEIGHT / 2.0 ));
00206    if (h==DEBUG_DOT_HEIGHT) h--;
00207         
00208    for (int u=0; u<MAPPING_SIZE; u++)
00209       {
00210          k = (MAPPING_SIZE + h) * MAPPING_SIZE + u;
00211 
00212          _virgin_debug_image[3*k  ] = 0x90;
00213          _virgin_debug_image[3*k+1] = 0x90;
00214          _virgin_debug_image[3*k+2] = 0x90;
00215       }
00216 
00217    clear_debug_image();
00218 }
00219 /////////////////////////////////////
00220 // clear_debug_image()
00221 /////////////////////////////////////
00222 void
00223 UVMapping::clear_debug_image()
00224 {
00225    static bool cool = Config::get_var_bool("HATCHING_DEBUG_MAPPING",false);
00226    assert(cool);
00227 
00228    for (int i=0; i<3*DEBUG_SIZE; i++)
00229       _marked_debug_image[i] = _virgin_debug_image[i];
00230 }
00231 
00232 /////////////////////////////////////
00233 // debug_dot()
00234 /////////////////////////////////////
00235 void
00236 UVMapping::debug_dot(
00237    double ewe,
00238    double val, 
00239    unsigned char r,
00240    unsigned char g,
00241    unsigned char b)
00242 {
00243    static bool cool = Config::get_var_bool("HATCHING_DEBUG_MAPPING",false);
00244    assert(cool);
00245 
00246    assert(val >= -1.0);
00247    assert(val <=  1.0);
00248    
00249    int u = int(floor( ( ewe - _min_u ) / _du ));
00250    if (u==MAPPING_SIZE) u--;
00251 
00252    int h = int(floor( ( val + 1.0 ) * (double) DEBUG_DOT_HEIGHT / 2.0 ));
00253    if (h==DEBUG_DOT_HEIGHT) h--;
00254 
00255    int k = (MAPPING_SIZE + h) * MAPPING_SIZE + u;
00256 
00257    _marked_debug_image[3*k  ] = r;
00258    _marked_debug_image[3*k+1] = g;
00259    _marked_debug_image[3*k+2] = b;
00260 
00261 }
00262 
00263 /////////////////////////////////////
00264 // compute_limits()
00265 /////////////////////////////////////
00266 void
00267 UVMapping::compute_limits(Bface *f)
00268 {
00269    int k;
00270 
00271    assert(f);
00272    
00273    //There oughta be uv here
00274    UVdata* uvdata = UVdata::lookup(f);
00275    assert(uvdata);
00276 
00277    //And it should not be mapped yet
00278    assert(uvdata->mapping()==0);
00279 
00280    //Init uv limits
00281    _min_u = uvdata->uv(1)[0];
00282    _max_u = uvdata->uv(1)[0];
00283    _min_v = uvdata->uv(1)[1];
00284    _max_v = uvdata->uv(1)[1];
00285 
00286    //Clear the mesh bits
00287    CBface_list& faces = f->mesh()->faces();
00288    for (k=0; k< faces.num(); k++) faces[k]->clear_bit(1);
00289 
00290    //Walk from seed face and fill out uv min/max
00291    recurse(f,&UVMapping::add_limit);
00292 
00293    //Sanity check
00294    assert( _min_u < _max_u );
00295    assert( _min_v < _max_v );
00296 
00297    _span_u = _max_u - _min_u;
00298    _span_v = _max_v - _min_v;
00299         
00300    _du = _span_u/(double)MAPPING_SIZE;
00301    _dv = _span_v/(double)MAPPING_SIZE;
00302 
00303    err_mesg(ERR_LEV_INFO,
00304       "UVMapping::compute_limits() - u_min=%f u_max=%f v_min=%f v_max=%f u_span=%f v_span=%f",
00305          _min_u, _max_u, _min_v, _max_v, _span_u, _span_v);
00306 }
00307 
00308 /////////////////////////////////////
00309 // compute_mapping()
00310 /////////////////////////////////////
00311 void
00312 UVMapping::compute_mapping(Bface *f)
00313 {
00314    int k;
00315 
00316    assert(f);
00317    
00318    //There oughta be uv here
00319    UVdata* uvdata = UVdata::lookup(f);
00320    assert(uvdata);
00321 
00322    //And it better not be mapped yet
00323    assert(uvdata->mapping()==0);
00324 
00325    //Clear mesh bits
00326    CBface_list& faces = f->mesh()->faces();
00327    for (k=0; k< faces.num(); k++) faces[k]->clear_bit(1);
00328 
00329    //Walk from seed face and store faces in region in map
00330    recurse(f,&UVMapping::add_face);
00331 
00332    err_mesg(ERR_LEV_INFO,
00333       "UVMapping::generate_mapping() - %d faces added to mapping (from %d in mesh) using %d entries.",
00334          _face_cnt, faces.num(), _entry_cnt);
00335 
00336    err_mesg(ERR_LEV_INFO,
00337       "UVMapping::generate_mapping() - %d populated bins of possible %d (%d holes).",
00338          _bin_cnt, MAPPING_BINS, MAPPING_BINS-_bin_cnt);
00339 }
00340 
00341 /////////////////////////////////////
00342 // compute_wrapping()
00343 /////////////////////////////////////
00344 void
00345 UVMapping::compute_wrapping(Bface *f)
00346 {
00347    int k;
00348 
00349    assert(f);
00350    
00351    //There oughta be uv here
00352    UVdata* uvdata = UVdata::lookup(f);
00353    assert(uvdata);
00354 
00355    //All your mapping are belong to us!
00356    assert(uvdata->mapping()==this);
00357 
00358    //Clear mesh bits
00359    CBface_list& faces = f->mesh()->faces();
00360    for (k=0; k< faces.num(); k++) faces[k]->clear_bit(1);
00361 
00362    //Walk from seed face and check uv region edges
00363    recurse_wrapping(f);
00364 
00365    if (_wrap_bad)
00366       err_mesg(ERR_LEV_WARN, "UVMapping::compute_mapping() - No wrapping set due to anomolous seam.");
00367    if (_wrap_u)
00368       err_mesg(ERR_LEV_INFO, "UVMapping::compute_mapping() - Wrapping in u at (%f,%f) discontinuity.", _min_u, _max_u);
00369    if (_wrap_v)
00370       err_mesg(ERR_LEV_INFO, "UVMapping::compute_mapping() - Wrapping in v at (%f,%f) discontinuity.", _min_v, _max_v);
00371    if ( (!_wrap_bad) && (!_wrap_u) && (!_wrap_v) )
00372       err_mesg(ERR_LEV_INFO, "UVMapping::compute_mapping() - No wrapping detected.");
00373 
00374 }
00375 
00376 /////////////////////////////////////
00377 // recurse_wrapping()
00378 /////////////////////////////////////
00379 void      
00380 UVMapping::recurse_wrapping(Bface *seed_f)
00381 {           
00382    int k;
00383 
00384    Bface *f;
00385    ARRAY<Bface*> faces;
00386 
00387    assert(seed_f);
00388 
00389    faces.push(seed_f);
00390 
00391    while (faces.num()>0)
00392    {
00393       //Remove face from end of queue
00394       f = faces.pop();
00395 
00396       //Skip if already seen
00397       if (!f->is_set(1))
00398       {
00399          f->set_bit(1);
00400 
00401          //If we get here, then this face *should* have uvdata
00402          //and *should* be allready be mapped to us!
00403          UVdata* uvdata = UVdata::lookup(f);
00404          assert(uvdata);
00405          assert(uvdata->mapping()==this);
00406 
00407          for (k=1; k<=3; k++)
00408          {
00409             Bedge *nxt_e = f->e(k);
00410             assert(nxt_e);
00411             Bface *nxt_f = nxt_e->other_face(f);
00412             if (nxt_f)
00413             {
00414                UVdata *nxt_uvdata = UVdata::lookup(nxt_f);
00415                if (nxt_uvdata)
00416                {
00417                   UVpt uva = uvdata->uv(k);
00418                   UVpt uvb = uvdata->uv((k==3)?(1):(k+1));
00419                   int nxt_k = ( (nxt_f->e1()==nxt_e)?(1):
00420                                 ((nxt_f->e2()==nxt_e)?(2):
00421                                  ((nxt_f->e3()==nxt_e)?(3):(0))));
00422                   assert(nxt_k);
00423                   UVpt nxt_uva = nxt_uvdata->uv(nxt_k);
00424                   UVpt nxt_uvb = nxt_uvdata->uv((nxt_k==3)?(1):(nxt_k+1));
00425 
00426                   //If neighboring face has uv, and the they match
00427                   //we recurse into this next face
00428                   if ((uva==nxt_uvb)&&(uvb==nxt_uva))
00429                   {
00430                      //Stick face on start of queue
00431                      faces.push(nxt_f);
00432                   }
00433                   //But if not, let's see if the other face is
00434                   //part of this mapping. If it is, then we found
00435                   //a seam.  Find the direction (u or v) and if
00436                   //its consistent with the _min_u/_max_u (or v)
00437                   //Then set the wrap flag for u or v appropriately
00438                   //or just turn all wrapping off if something's amiss
00439                   else 
00440                   {
00441                      //Here's a seam!
00442                      if (nxt_uvdata->mapping() == this)
00443                      {               
00444                         //We support 2 kinds of wrapping:
00445                         //-Wrap on a line of constant u (wrap at _min_u,_max_u)
00446                         //-Wrap on a line of constant v (wrap at _min_v,_max_v)
00447                         //If neither is seen, or if the discontinuity isn't
00448                         //at the extrema, we found something anomolous, abort!
00449                         //Note - There can be holes at the seam without problems.
00450 
00451                         if ((uva[0]==uvb[0])&&(nxt_uva[0]==nxt_uvb[0]))
00452                         {
00453                            //This looks like wrapping on a line of const. u
00454                            //Let's make sure the discontinuity is at the extrema
00455 
00456                            if ( (uva[0]==_min_u && nxt_uva[0]==_max_u) ||
00457                                 (uva[0]==_max_u && nxt_uva[0]==_min_u))
00458                            {
00459                               //It's all good
00460                               if (!_wrap_u)
00461                                  {
00462                                     err_mesg(ERR_LEV_SPAM, "UVMapping::recurse_wrapping() - Found a valid wrapping seam in u.");
00463                                     _wrap_u = true;
00464                                  }
00465                            }
00466                            else
00467                            {
00468                               //We aren't at the extrema, so set the bad flag
00469                               //to avoid further checking
00470 
00471                               _wrap_bad = true;
00472                               _wrap_u = false;
00473                               _wrap_v = false;
00474 
00475                               err_mesg(ERR_LEV_WARN,
00476                                  "UVMapping::recurse_wrapping() - Found an INVALID wrapping seam in u: (%f,%f) since u extrema are: (%f,%f)",
00477                                    uva[0], nxt_uva[0], _min_u, _max_u);
00478                               err_mesg(ERR_LEV_WARN, "UVMapping::recurse_wrapping() - Aborting all wrapping.");
00479                            }
00480                         }
00481                         else if ((uva[1]==uvb[1])&&(nxt_uva[1]==nxt_uvb[1]))
00482                         {
00483                            //This looks like wrapping on a line of const. v
00484                            //Let's make sure the discontinuity is at the extrema
00485 
00486                            if ( (uva[1]==_min_v && nxt_uva[1]==_max_v) ||
00487                                 (uva[1]==_max_v && nxt_uva[1]==_min_v))
00488                            {
00489                               //It's all good
00490                               if (!_wrap_v)
00491                               {
00492                                  err_mesg(ERR_LEV_INFO, "UVMapping::recurse_wrapping() - Found a valid wrapping seam in v.");
00493                                  _wrap_v = true;
00494                               }
00495                            }
00496                            else
00497                            {
00498                               //We aren't at the extrema, so set the bad flag
00499                               //to avoid further checking
00500 
00501                               _wrap_bad = true;
00502                               _wrap_u = false;
00503                               _wrap_v = false;
00504                                         
00505                               err_mesg(ERR_LEV_WARN,
00506                                  "UVMapping::recurse_wrapping() - Found an INVALID wrapping seam in v: (%f,%f) since v extrema are: (%f,%f)",
00507                                    uva[1], nxt_uva[1], _min_v, _max_v);
00508                               err_mesg(ERR_LEV_WARN, "UVMapping::recurse_wrapping() - Aborting all wrapping.");
00509                            }
00510                         }
00511                         else
00512                         {
00513                            //One or both edges failed to show constant u or v
00514                            //Abort any further wrapping...
00515 
00516                            _wrap_bad = true;
00517                            _wrap_u = false;
00518                            _wrap_v = false;
00519 
00520                            err_mesg(ERR_LEV_WARN,
00521                               "UVMapping::recurse_wrapping() - Found an INVALID wrapping. The seam wasn't constant in u or v.");
00522                            err_mesg(ERR_LEV_WARN,
00523                               "UVMapping::recurse_wrapping() - Edge #1 (%f,%f)-(%f,%f) Edge #2 (%f,%f)-(%f,%f)",
00524                                  uva[0], uva[1], uvb[0], uvb[1], nxt_uvb[0], nxt_uvb[1], nxt_uva[0], nxt_uva[1]);
00525                            err_mesg(ERR_LEV_WARN,
00526                               "UVMapping::recurse_wrapping() - Aborting all wrapping.");
00527                         }
00528                      }
00529                   }
00530                }
00531             }
00532          }
00533       }
00534    }
00535 }
00536 
00537 /////////////////////////////////////
00538 // recurse()
00539 /////////////////////////////////////
00540 void      
00541 UVMapping::recurse(Bface *seed_f, rec_fun_t fun )
00542 {           
00543    int k;
00544 //   bool done = false;
00545 
00546    Bface*                  f;
00547    ARRAY<Bface*>   faces;
00548 
00549    assert(seed_f);
00550 
00551    faces.push(seed_f);
00552 
00553    while (faces.num()>0)
00554       {
00555          //Remove oldest face from end of queue
00556          f = faces.pop();
00557 
00558          //Skip if already seen
00559          if (!f->is_set(1))
00560             {
00561                f->set_bit(1);
00562 
00563                //If we get here, then this face *should* have uvdata
00564                //and *should* be unmapped
00565                UVdata* uvdata = UVdata::lookup(f);
00566                assert(uvdata);
00567                assert(uvdata->mapping()==0);
00568 
00569                //Do the action (add to map, or update limits, etc.)
00570                (this->*fun)(f);
00571 
00572                for (k=1; k<=3; k++)
00573                   {
00574                      Bedge *nxt_e = f->e(k);
00575                      assert(nxt_e);
00576                      Bface *nxt_f = nxt_e->other_face(f);
00577                      if (nxt_f)
00578                         {
00579                            UVdata *nxt_uvdata = UVdata::lookup(nxt_f);
00580                            if (nxt_uvdata)
00581                               {
00582                                  UVpt uva = uvdata->uv(k);
00583                                  UVpt uvb = uvdata->uv((k==3)?(1):(k+1));
00584                                  int nxt_k = ( (nxt_f->e1()==nxt_e)?(1):
00585                                                ((nxt_f->e2()==nxt_e)?(2):
00586                                                 ((nxt_f->e3()==nxt_e)?(3):(0))));
00587                                  assert(nxt_k);
00588                                  UVpt nxt_uva = nxt_uvdata->uv(nxt_k);
00589                                  UVpt nxt_uvb = nxt_uvdata->uv((nxt_k==3)?(1):(nxt_k+1));
00590 
00591                                  //If neighboring face has uv, and the they match
00592                                  //we recurse into this next face
00593                                  if ((uva==nxt_uvb)&&(uvb==nxt_uva))
00594                                     {
00595                                        //Add to front of queue
00596                                        faces.push(nxt_f);
00597                                     }
00598                                  else {
00599                                     //Nothing
00600                                  }
00601                               }
00602                         }
00603                   }
00604             }
00605       }
00606 }
00607 
00608 /////////////////////////////////////
00609 // add_limits()
00610 /////////////////////////////////////
00611 void 
00612 UVMapping::add_limit(Bface *f)
00613 {
00614    int k;
00615 
00616    assert(f);
00617 
00618    UVdata* uvdata = UVdata::lookup(f);
00619    assert(uvdata);
00620    assert(uvdata->mapping()==0);
00621 
00622 
00623    for (k=1; k<=3; k++)
00624       {
00625          if ( uvdata->uv(k)[0] < _min_u ) 
00626             _min_u = uvdata->uv(k)[0];
00627          if ( uvdata->uv(k)[0] > _max_u ) 
00628             _max_u = uvdata->uv(k)[0];
00629          if ( uvdata->uv(k)[1] < _min_v ) 
00630             _min_v = uvdata->uv(k)[1];
00631          if ( uvdata->uv(k)[1] > _max_v ) 
00632             _max_v = uvdata->uv(k)[1];
00633       }
00634 
00635 }
00636 
00637 
00638 /////////////////////////////////////
00639 // add_face()
00640 /////////////////////////////////////
00641 void
00642 UVMapping::add_face(Bface *f)
00643 {
00644    int k, u, v;
00645    int umax=0, vmax=0;
00646    int umin=MAPPING_SIZE-1, vmin=MAPPING_SIZE-1;
00647    int entry_count = 0;
00648    int bin_count = 0;
00649 
00650    assert(f);
00651 
00652    UVdata* uvdata = UVdata::lookup(f);
00653    assert(uvdata);
00654    assert(uvdata->mapping()==0);
00655 
00656    //Sanity check
00657    for (k=1; k<=3; k++)
00658       {
00659          assert( uvdata->uv(k)[0] <= _max_u );
00660          assert( uvdata->uv(k)[1] <= _max_v );
00661          assert( uvdata->uv(k)[0] >= _min_u );
00662          assert( uvdata->uv(k)[1] >= _min_v );
00663       }
00664 
00665    //Find the square set of u,v bins holding face
00666    for (k=1; k<=3; k++)
00667       {
00668          u = int(floor( (uvdata->uv(k)[0] - _min_u) / _du ));
00669          if (u==MAPPING_SIZE) u--;
00670          v = int(floor( (uvdata->uv(k)[1] - _min_v ) /_dv ));
00671          if (v==MAPPING_SIZE) v--;
00672 
00673          if (u<umin) umin=u;
00674          if (u>umax) umax=u;
00675 
00676          if (v<vmin) vmin=v;
00677          if (v>vmax) vmax=v;
00678       }
00679 
00680    //So escape rounding error that would
00681    //exclude bins that we genuinely intersect
00682    //we puff out the set of bins by 1 on each side
00683 
00684    if (umin>0) umin--;
00685    if (vmin>0) vmin--;
00686    if (umax<MAPPING_SIZE-1) umax++;
00687    if (vmax<MAPPING_SIZE-1) vmax++;
00688 
00689    //Sanity checks
00690    assert(umin>=0);
00691    assert(vmin>=0);
00692 
00693    assert(umax<MAPPING_SIZE);
00694    assert(vmax<MAPPING_SIZE);
00695 
00696    assert(umax>=umin);
00697    assert(vmax>=vmin);
00698 
00699    UVpt_list box;
00700    UVpt_list tri;
00701 
00702    bool isect;
00703 
00704    for (v=vmin; v<=vmax; v++)
00705       {
00706          for (u=umin; u<=umax; u++)
00707             {
00708                isect = false;
00709          
00710                box.clear();
00711                tri.clear();
00712 
00713                box += UVpt( _min_u +     u *_du , _min_v +     v * _dv );
00714                box += UVpt( _min_u + (u+1) *_du , _min_v +     v * _dv );
00715                box += UVpt( _min_u + (u+1) *_du , _min_v + (v+1) * _dv );
00716                box += UVpt( _min_u +     u *_du , _min_v + (v+1) * _dv );
00717 
00718                tri += uvdata->uv1();
00719                tri += uvdata->uv2();
00720                tri += uvdata->uv3();
00721 
00722                //isect if box holds tri or vice versa
00723                if (box.contains(tri)) isect = true;
00724                else if (tri.contains(box)) isect = true;
00725                //or if any edges intersect
00726                else
00727                   {
00728                      for (k=0; k<3; k++)
00729                         {
00730                            if (!isect)
00731                               {
00732                                  if      (intersect(box[0],box[1],tri[k],tri[(k+1)%3])) isect=true;
00733                                  else if (intersect(box[1],box[2],tri[k],tri[(k+1)%3])) isect=true;
00734                                  else if (intersect(box[2],box[3],tri[k],tri[(k+1)%3])) isect=true;
00735                                  else if (intersect(box[3],box[0],tri[k],tri[(k+1)%3])) isect=true;
00736 
00737                               }
00738                         }
00739                   }
00740          
00741                if (isect)
00742                   {
00743                      entry_count++;
00744                      _mapping[u+MAPPING_SIZE*v]->add(f);
00745                      if ( _mapping[u+MAPPING_SIZE*v]->num() == 1 )   bin_count++;
00746                   }
00747       
00748             }
00749       }
00750 
00751    //By definition , a face imust fall somewhere
00752    //within the mapping's bin
00753    assert(entry_count>0);
00754 
00755    uvdata->set_mapping(this);
00756 
00757    //Increment mapped face count
00758    _face_cnt++;
00759 
00760    //Increment map face entry count
00761    _entry_cnt += entry_count;
00762 
00763    //Increment unique bin usage count
00764    _bin_cnt += bin_count;
00765 
00766 
00767 }
00768 
00769 /////////////////////////////////////
00770 // find_face();
00771 /////////////////////////////////////
00772 Bface*   
00773 UVMapping::find_face(CUVpt &uv, Wvec &bc)
00774 {
00775    static bool debug = Config::get_var_bool("HATCHING_DEBUG_MAPPING",false);
00776    
00777    int k,i;
00778 //   double bc1,bc2,bc3;
00779    UVdata* uvdata;
00780    Bface *f;
00781 
00782    int u = int(floor( ( uv[0] - _min_u ) / _du ));
00783    if (u==MAPPING_SIZE) u--;
00784    int v = int(floor( ( uv[1] - _min_v ) / _dv ));
00785    if (v==MAPPING_SIZE) v--;
00786 
00787    i = u+MAPPING_SIZE*v;
00788 
00789    for (k=0; k<_mapping[i]->num(); k++)
00790       {
00791          f = (*_mapping[i])[k];
00792          uvdata = UVdata::lookup(f);
00793          assert(uvdata);
00794 
00795          CUVpt& uv1 = uvdata->uv1();
00796          CUVpt& uv2 = uvdata->uv2();
00797          CUVpt& uv3 = uvdata->uv3();
00798          UVvec uv3_1 = uv3 - uv1;
00799 
00800          double A   = det(uv2 - uv1, uv3_1    );
00801          double bc1 = det(uv2 - uv , uv3 - uv ) / A;
00802 
00803          if ((bc1<0)||(bc1>1)) continue;
00804     
00805          double bc2 = det(uv  - uv1, uv3_1    ) / A;
00806 
00807          if ((bc2<0)||(bc2>1)) continue;
00808       
00809          double bc3 = 1.0 - bc1 - bc2;
00810       
00811          if (bc3>=0)
00812             {
00813                bc = Wvec(bc1,bc2,bc3);
00814 
00815                if (debug)
00816                   {
00817                      _marked_debug_image[3*i  ] = 0xFF;
00818                      _marked_debug_image[3*i+1] = 0x77;
00819                      _marked_debug_image[3*i+2] = 0x77;
00820                   }
00821          
00822                return f;
00823             }
00824 
00825 /*
00826   double A   = 0.5 * det(uvdata->uv2() - uvdata->uv1(), uvdata->uv3() - uvdata->uv1());
00827   double bc1 = 0.5 * det(uvdata->uv2() - uv,            uvdata->uv3() - uv           ) / A;
00828   double bc2 = 0.5 * det(uv            - uvdata->uv1(), uvdata->uv3() - uvdata->uv1()) / A;
00829   double bc3 = 1.0 - bc1 - bc2;
00830 
00831   if ( ((bc1>=0)&&(bc1<=1)) && ((bc2>=0)&&(bc2<=1)) && ((bc3)>=0) )
00832   {
00833   bc = Wvec(bc1,bc2,bc3);
00834 
00835   if (debug)
00836   {
00837   _marked_debug_image[3*i  ] = 0xFF;
00838   _marked_debug_image[3*i+1] = 0x77;
00839   _marked_debug_image[3*i+2] = 0x77;
00840   }
00841          
00842   return f;
00843   }
00844 */      
00845 
00846       }
00847    return 0;
00848 }
00849 
00850 
00851 /////////////////////////////////////
00852 // intersect()
00853 /////////////////////////////////////
00854 bool
00855 UVMapping::intersect(CUVpt &pt1a, CUVpt &pt1b, CUVpt &pt2a, CUVpt &pt2b)
00856 {
00857 
00858    if ((pt1a==pt2a)||(pt1a==pt2b)||(pt1b==pt2a)||(pt1b==pt2b)) return true;
00859 
00860    double c1a = det(pt1b - pt1a, pt2a - pt1a);
00861    double c1b = det(pt1b - pt1a, pt2b - pt1a);
00862    double c2a = det(pt2b - pt2a, pt1a - pt2a);
00863    double c2b = det(pt2b - pt2a, pt1b - pt2a);
00864 
00865 
00866 
00867    if  ( ( ((c1a>=-gEpsZeroMath)&&(c1b<=gEpsZeroMath)) || ((c1a<=gEpsZeroMath)&&(c1b>=-gEpsZeroMath)) ) &&
00868          ( ((c2a>=-gEpsZeroMath)&&(c2b<=gEpsZeroMath)) || ((c2a<=gEpsZeroMath)&&(c2b>=-gEpsZeroMath)) )    )
00869       return true;
00870 
00871    return false;
00872 }
00873 
00874 /////////////////////////////////////
00875 // interpolate()
00876 /////////////////////////////////////
00877 void
00878 UVMapping::interpolate( 
00879    CUVpt &uv1, double frac1, 
00880    CUVpt &uv2, double frac2, 
00881    UVpt &uv )
00882 {
00883 
00884    //Interpolates two uv values using given weights
00885    //and accounting for discontinuity at seams
00886    
00887    //XXX - Not bullet proof.  We check if both points
00888    //are within 25% of span's proximity to opposite
00889    //sides of seam.  If so, the lower value is offset by
00890    //the span, and the final sum is adjusted back into range.
00891    //e.g. Wrap in u, u ranges 0-1, u1=.2, u2=.9, u1->1.2, 
00892    //so ave=1.05, final=0.05
00893 
00894 
00895    double lo;
00896    double hi;
00897 
00898    if (!_wrap_u)
00899       {
00900          uv[0]  = uv1[0]*frac1 + uv2[0]*frac2;
00901       }
00902    else
00903       {
00904          lo = _min_u + 0.25*_span_u;
00905          hi = _max_u - 0.25*_span_u;
00906    
00907          if       ((uv1[0]>hi) && (uv2[0]<lo))
00908             {
00909                uv[0] =           uv1[0]*frac1 + (uv2[0]+_span_u)*frac2;
00910             }
00911          else if  ((uv1[0]<lo) && (uv2[0]>hi))
00912             {
00913                uv[0] = (uv1[0]+_span_u)*frac1 +           uv2[0]*frac2;
00914             }
00915          else
00916             {
00917                uv[0] = uv1[0]*frac1 + uv2[0]*frac2;   
00918             }
00919 
00920          if (uv[0]>_max_u) uv[0] = uv[0] - _span_u;
00921       }
00922    
00923 
00924    if (!_wrap_v)
00925       {
00926          uv[1]  = uv1[1]*frac1 + uv2[1]*frac2;
00927       }
00928    else
00929       {
00930          lo = _min_v + 0.25*_span_v;
00931          hi = _max_v - 0.25*_span_v;
00932    
00933          if       ((uv1[1]>hi) && (uv2[1]<lo))
00934             {
00935                uv[1] =           uv1[1]*frac1 + (uv2[1]+_span_v)*frac2;
00936             }
00937          else if  ((uv1[1]<lo) && (uv2[1]>hi))
00938             {
00939                uv[1] = (uv1[1]+_span_v)*frac1 +           uv2[1]*frac2;
00940             }
00941          else
00942             {
00943                uv[1] = uv1[1]*frac1 + uv2[1]*frac2;   
00944             }
00945 
00946          if (uv[1]>_max_v) uv[1] = uv[1] - _span_v;
00947       }
00948    
00949 
00950 }
00951 
00952 
00953 /////////////////////////////////////
00954 // apply_wrap()
00955 /////////////////////////////////////
00956 //
00957 // -Takes a uv and if u or v are out
00958 //  of bounds and there is wrapping
00959 //  in the respecive direction, the
00960 //  coordinate is moved into range
00961 //
00962 /////////////////////////////////////
00963 
00964 void
00965 UVMapping::apply_wrap( 
00966    UVpt &uv)
00967 {
00968 
00969    if (_wrap_u)
00970       {
00971          if (uv[0]<_min_u)
00972             do
00973                uv[0] += _span_u;
00974             while (uv[0]<_min_u);
00975 
00976          else if (uv[0]>_max_u)
00977             do
00978                uv[0] -= _span_u;
00979             while (uv[0]>_max_u);
00980       }
00981 
00982    if (_wrap_v)
00983       {
00984          if (uv[1]<_min_v)
00985             do
00986                uv[1] += _span_v;
00987             while (uv[1]<_min_v);
00988 
00989          else if (uv[1]>_max_v)
00990             do
00991                uv[1] -= _span_v;
00992             while (uv[1]>_max_v);
00993       }
00994 
00995 }
00996 /* end of file uv_mapping.C */

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