textcoord_optimization.h
Go to the documentation of this file.
00001 /****************************************************************************
00002 * VCGLib                                                            o o     *
00003 * Visual and Computer Graphics Library                            o     o   *
00004 *                                                                _   O  _   *
00005 * Copyright(C) 2004                                                \/)\/    *
00006 * Visual Computing Lab                                            /\/|      *
00007 * ISTI - Italian National Research Council                           |      *
00008 *                                                                    \      *
00009 * All rights reserved.                                                      *
00010 *                                                                           *
00011 * This program is free software; you can redistribute it and/or modify      *   
00012 * it under the terms of the GNU General Public License as published by      *
00013 * the Free Software Foundation; either version 2 of the License, or         *
00014 * (at your option) any later version.                                       *
00015 *                                                                           *
00016 * This program is distributed in the hope that it will be useful,           *
00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of            *
00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
00019 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt)          *
00020 * for more details.                                                         *
00021 *                                                                           *
00022 ****************************************************************************/
00023 /****************************************************************************
00024   History
00025   
00026 $Log: not supported by cvs2svn $
00027 Revision 1.6  2007/02/02 04:11:00  tarini
00028 added parameter theta (from conformal to equiareal) to AreaPresTextureOptimizer.
00029 Improved feature lists (comments).
00030 
00031 Revision 1.5  2007/02/02 01:39:58  tarini
00032 added three general-utility global functions for texture coordinates: SmoothTextureCoords, IsFoldFree, MarkFolds (see descriptions)
00033 
00034 Revision 1.4  2007/02/02 01:23:47  tarini
00035 added a few general comments on AreaPreserving optimizer, recapping optimizer features.
00036 
00037 Revision 1.3  2007/02/02 01:18:15  tarini
00038 First version: general virtual class for texture optimizers. A subclass for area preservation.
00039 
00040 
00041 ****************************************************************************/
00042 
00043 #ifndef __VCGLIB__TEXTCOOORD_OPTIMIZATION
00044 #define __VCGLIB__TEXTCOOORD_OPTIMIZATION
00045 
00046 #include <vcg/container/simple_temporary_data.h>
00047 
00048 
00049 /*
00050 
00051 SINGLE PATCH TEXTURE OPTIMIZATIONS
00052 
00053 A set of classes to perform optimizations of disk->disk parametrization.
00054 
00055 Requires texture coords to be defined per vertex (replicate seams).
00056 
00057 */
00058 
00059 
00060 namespace vcg
00061 {
00062 namespace tri
00063 {
00064 
00065 
00066 /* Base class for all Texture Optimizers*/
00067 template<class MESH_TYPE> 
00068 class TextureOptimizer{
00069 protected:
00070   MESH_TYPE &m;
00071   SimpleTempData<typename MESH_TYPE::VertContainer, int > isFixed;
00072 public:
00073   
00074   /* Tpyes */
00075   typedef MESH_TYPE MeshType;
00076   typedef typename MESH_TYPE::VertexIterator VertexIterator;
00077   typedef typename MESH_TYPE::FaceIterator FaceIterator;
00078   typedef typename MESH_TYPE::VertexType VertexType;
00079   typedef typename MESH_TYPE::FaceType FaceType;
00080   typedef typename MESH_TYPE::ScalarType ScalarType;
00081   
00082   
00083   /* Access functions */
00084   const MeshType & Mesh() const {return m;}
00085   MeshType & Mesh() {return m;}
00086    
00087   /* Constructior */
00088   TextureOptimizer(MeshType &_m):m(_m),isFixed(_m.vert){
00089     assert(m.HasPerVertexTexture());
00090   }
00091   
00092   // initializes on current geometry 
00093   virtual void TargetCurrentGeometry()=0;
00094   
00095   // performs an interation. Returns largest movement.
00096   virtual ScalarType Iterate()=0;
00097   
00098   // performs an iteration (faster, but it does not tell how close it is to stopping)
00099   virtual void IterateBlind()=0;
00100   
00101   // performs <steps> iteration
00102   virtual ScalarType IterateN(int step){
00103     for (int i=0; i<step-1; i++) {
00104       this->IterateBlind();
00105     }
00106     if (step>1) return this->Iterate(); else return 0;
00107   }
00108  
00109   // performs iterations until convergence.
00110   bool IterateUntilConvergence(ScalarType threshold=0.0001, int maxite=5000){
00111     int i;
00112     while (Iterate()>threshold) {
00113       if (i++>maxite) return false;
00114     }
00115     return true;
00116   }
00117   
00118   // desctuctor: free temporary field
00119   ~TextureOptimizer(){
00120     isFixed.Stop();
00121   };
00122   
00123   // set the current border as fixed (forced to stay in position during text optimization)
00124   void SetBorderAsFixed(){
00125     isFixed.Start();
00126     for (VertexIterator v=m.vert.begin(); v!=m.vert.end(); v++) {
00127                   isFixed[v]=(v->IsB())?1:0; 
00128           }  
00129   }
00130   
00131   // everything moves, no vertex must fixed during texture optimization)
00132   void SetNothingAsFixed(){
00133     isFixed.Start();
00134     for (VertexIterator v=m.vert.begin(); v!=m.vert.end(); v++) {
00135                   isFixed[v]=0; 
00136           }  
00137   }
00138   
00139   // fix a given vertex
00140   void FixVertex(const VertexType *v, bool fix=true){
00141     isFixed[v]=(fix)?1:0;
00142   }
00143   
00144   
00145 };
00146 
00147 
00148 
00149 /*
00150 AREA PRESERVING TEXTURE OPTIMIZATION
00151 
00152 as in: Degener, P., Meseth, J., Klein, R. 
00153        "An adaptable surface parameterization method."
00154        Proc. of the 12th International Meshing oundtable, 201–213 [2003].
00155 
00156 Features:
00157   
00158 :) - Balances angle and area distortions (best results!).
00159 :) - Can choose how to balance area and angle preservation (see SetTheta)
00160        theta=0 -> pure conformal (use MIPS instead!)
00161        theta=3 -> good balance between area and angle preservation
00162        theta>3 -> care more about area than about angles
00163 :( - Slowest method.
00164 :( - Requires a fixed boundary, else expands forever in texture space (unless theta=0).
00165 :( - Diverges in presence of flipped faces (unless theta=0).
00166 :( - Requires a speed parameter to be set. 
00167        Speed too large => when close, bounces back and forth around minimum, w/o getting any closer.
00168        Lower speed => longer convercence times
00169 */
00170 
00171 template<class MESH_TYPE> 
00172 class AreaPreservingTextureOptimizer:public TextureOptimizer<MESH_TYPE>{
00173 public:
00174   /* Types */
00175   typedef MESH_TYPE MeshType;
00176   typedef typename MESH_TYPE::VertexIterator VertexIterator;
00177   typedef typename MESH_TYPE::FaceIterator FaceIterator;
00178   typedef typename MESH_TYPE::VertexType VertexType;
00179   typedef typename MESH_TYPE::FaceType FaceType;
00180   typedef typename MESH_TYPE::ScalarType ScalarType;
00181   
00182 
00183 private:
00184   typedef TextureOptimizer<MESH_TYPE> Super; // superclass (commodity)
00185   
00186   // extra data per face: [0..3] -> cotangents. [4] -> area*2
00187   SimpleTempData<typename MESH_TYPE::FaceContainer, Point4<ScalarType> > data;
00188   SimpleTempData<typename MESH_TYPE::VertContainer, Point2<ScalarType> > sum;
00189   
00190   ScalarType totArea;
00191   ScalarType speed;
00192   
00193   int theta;
00194   
00195 public:
00196    
00197   // constructor and destructor
00198   AreaPreservingTextureOptimizer(MeshType &_m):Super(_m),data(_m.face),sum(_m.vert){
00199     speed=0.001;
00200     theta=3;
00201   }
00202   
00203   ~AreaPreservingTextureOptimizer(){
00204     data.Stop();
00205     sum.Stop();
00206     Super::isFixed.Stop();
00207   }
00208   
00209   void SetSpeed(ScalarType _speed){
00210     speed=_speed;
00211   }
00212 
00213   ScalarType GetSpeed(){
00214     return speed;
00215   }
00216   
00217   // sets the parameter theta:
00218   // good parameters are in 1..3
00219   //  0 = converge to pure conformal, ignore area preservation
00220   //  3 = good balance between area and conformal
00221   // >3 = area more important, angle preservation less important
00222   void SetTheta(int _theta){
00223     theta=_theta;
00224   }
00225 
00226   int GetTheta(){
00227     return theta;
00228   }
00229   
00230   void IterateBlind(){
00231     /* todo: do as iterate, but without */ 
00232     Iterate();
00233   }
00234   
00235   ScalarType Iterate(){
00236     
00237     ScalarType max; // max displacement
00238     
00239     #define v0 (f->V0(i)->T().P())
00240     #define v1 (f->V1(i)->T().P())
00241     #define v2 (f->V2(i)->T().P())
00242           for (VertexIterator v=Super::m.vert.begin(); v!=Super::m.vert.end(); v++) {
00243                   sum[v].SetZero();
00244           }
00245 
00246           ScalarType tot_proj_area=0;
00247           for (FaceIterator f=Super::m.face.begin(); f!=Super::m.face.end(); f++) {
00248                   int i=0;
00249                   double area2 = ((v1-v0) ^ (v2-v0));
00250                   tot_proj_area+=area2;
00251           }
00252 
00253           double scale= 1.0; //tot_proj_area / tot_area ;
00254 
00255           for (FaceIterator f=Super::m.face.begin(); f!=Super::m.face.end(); f++) {
00256                   int i=0; ScalarType area2 = ((v1-v0) ^ (v2-v0));
00257                   for (i=0; i<3; i++){
00258                           ScalarType 
00259                                   a = (v1-v0).Norm(),
00260                                   b =  ((v1-v0) * (v2-v0))/a,
00261                             c = area2 / a,
00262                             
00263                                   m0= data[f][i] / area2,
00264                                   m1= data[f][(i+1)%3] / area2,
00265                                   m2= data[f][(i+2)%3] / area2,
00266                                   
00267                                   mx= (b-a)/area2,
00268                                   my= c/area2, // 1.0/a
00269                                   mA= data[f][3]/area2 * scale,
00270                                   e = m0*((b-a)*(b-a)+c*c) + m1*(b*b+c*c) + m2*a*a, // as obvious
00271                                   M1= mA + 1.0/mA,
00272                                   M2= mA - 1.0/mA,
00273                                   px= e*my,
00274                                   py=-e*mx,
00275                                   qx= m1*b+ m2*a,
00276                                   qy= m1*c,
00277 
00278                                   /* linear weightings
00279 
00280                                   dx= (OMEGA) * (my * M2) + 
00281                                       (1-OMEGA) * ( px - 2.0*qx),
00282                                   dy= (OMEGA) * (-mx * M2) + 
00283                                       (1-OMEGA) * ( py - 2.0*qy),*/
00284                                 
00285                                   // exponential weighting
00286                                   // 2d gradient
00287                                 
00288                                   dx=// M1
00289                                          //*M1 // ^ theta-1 
00290                                          pow(M1,theta-1)
00291                                          *(px*(M1+ theta*M2) - 2.0*qx*M1), 
00292                                   dy=// M1
00293                                            //*M1 // ^ theta-1 
00294                                            pow(M1,theta-1)
00295                                            *(py*(M1+ theta*M2) - 2.0*qy*M1), 
00296 
00297                                   gy= dy/c,
00298                                   gx= (dx - gy*b) / a;
00299 
00300                                   // 3d gradient
00301 
00302                             sum[f->V(i)]+= ( (v1-v0) * gx + (v2-v0) * gy ) * data[f][3]; 
00303                   }
00304           }
00305         max=0; // max displacement      
00306         speed=0.001;
00307           for (VertexIterator v=Super::m.vert.begin(); v!=Super::m.vert.end(); v++) 
00308     if (  !Super::isFixed[v] ) //if (!v->IsB()) 
00309     {
00310       ScalarType n=sum[v].Norm();
00311                   if ( n > 1 ) { sum[v]/=n; n=1.0;}
00312                   if ( n*speed<=0.1 ); {
00313                     v->T().P()-=(sum[v] * speed ) ;
00314                     if (max<n) max=n;
00315       }
00316                   //else rejected++;
00317         }
00318         return max;
00319         #undef v0
00320     #undef v1 
00321     #undef v2 
00322         //printf("rejected %d\n",rejected);
00323   }
00324   
00325   void TargetCurrentGeometry(){
00326     
00327     Super::isFixed.Start();
00328     data.Start();
00329     sum.Start();
00330     
00331           totArea=0;
00332           for (FaceIterator f=Super::m.face.begin(); f!=Super::m.face.end(); f++) {
00333                   double area2 =        ((f->V(1)->P() - f->V(0)->P() )^(f->V(2)->P() - f->V(0)->P() )).Norm();
00334                   totArea+=area2;
00335                   //if (  Super::isFixed[f->V1(0)] )
00336                   for (int i=0; i<3; i++){
00337                           data[f][i]=(
00338                                 (f->V1(i)->P() - f->V0(i)->P() )*(f->V2(i)->P() - f->V0(i)->P() )
00339                           )/area2;
00340                           data[f][3]=area2;
00341                   }
00342           }
00343   }
00344   
00345 };
00346 
00347 
00348 
00349 /* texture coords general utility functions */
00350 /*++++++++++++++++++++++++++++++++++++++++++*/
00351 
00352 // returns false if any fold is present (faster than MarkFolds)
00353 template<class MESH_TYPE>
00354 bool IsFoldFree(MESH_TYPE &m){
00355   
00356   assert(m.HasPerVertexTexture());
00357   
00358   typedef typename MESH_TYPE::VertexType::TextureType::PointType PointType;
00359   typedef typename MESH_TYPE::VertexType::TextureType::PointType::ScalarType ScalarType;
00360   
00361   ScalarType lastsign=0;
00362   for (typename MESH_TYPE::FaceIterator f=m.face.begin(); f!=m.face.end(); f++){
00363     ScalarType sign=((f->V(1)->T().P()-f->V(0)->T().P()) ^ (f->V(2)->T().P()-f->V(0)->T().P()));
00364     if (sign!=0) {
00365       if (sign*lastsign<0) return false;
00366       lastsign=sign;
00367     }
00368   }
00369   return true;
00370 }
00371 
00372 // detects and marks folded faces, by setting their quality to 0 (or 1 otherwise)
00373 // returns number of folded faces
00374 template<class MESH_TYPE>
00375 int MarkFolds(MESH_TYPE &m){
00376   
00377   assert(m.HasPerVertexTexture());
00378   assert(m.HasPerFaceQuality());
00379   
00380   typedef typename MESH_TYPE::VertexType::TextureType::PointType PointType;
00381   typedef typename MESH_TYPE::VertexType::TextureType::PointType::ScalarType ScalarType;
00382   
00383   SimpleTempData<typename MESH_TYPE::FaceContainer, short> sign(m.face);
00384   sign.Start(0);
00385   
00386   // first pass, determine predominant sign
00387   int npos=0, nneg=0;
00388   ScalarType lastsign=0;
00389   for (typename MESH_TYPE::FaceIterator f=m.face.begin(); f!=m.face.end(); f++){
00390     ScalarType fsign=((f->V(1)->T().P()-f->V(0)->T().P()) ^ (f->V(2)->T().P()-f->V(0)->T().P()));
00391     if (fsign<0) { sign[f]=-1;  nneg++; }
00392     if (fsign>0) { sign[f]=+1; npos++; }
00393   }
00394   
00395   // second pass, detect folded faces
00396   int res=0;
00397   short gsign= (nneg>npos)?-1:+1;
00398   for (typename MESH_TYPE::FaceIterator f=m.face.begin(); f!=m.face.end(); f++){
00399     if (sign[f]*gsign<0){
00400       res++;
00401       f->Q()=0;
00402     } else f->Q()=1;
00403   }
00404   
00405   sign.Stop();
00406   
00407   return res;
00408 }
00409 
00410 // Smooths texture coords.
00411 // (can be useful to remove folds, 
00412 //  e.g. these created when obtaining tecture coordinates after projections)
00413 template<class MESH_TYPE>
00414 void SmoothTextureCoords(MESH_TYPE &m){
00415   
00416   assert(m.HasPerVertexTexture());
00417   
00418   typedef typename MESH_TYPE::VertexType::TextureType::PointType PointType;
00419   
00420   SimpleTempData<typename MESH_TYPE::VertContainer, int> div(m.vert);
00421   SimpleTempData<typename MESH_TYPE::VertContainer, PointType > sum(m.vert);
00422   
00423   div.Start();
00424   sum.Start();
00425   
00426         for (typename MESH_TYPE::VertexIterator v=m.vert.begin(); v!=m.vert.end(); v++) {
00427                 sum[v].SetZero();
00428     div[v]=0;
00429         }
00430 
00431         for (typename MESH_TYPE::FaceIterator f=m.face.begin(); f!=m.face.end(); f++){
00432                 div[f->V(0)] +=2; sum[f->V(0)] += f->V(2)->T().P(); sum[f->V(0)] += f->V(1)->T().P();
00433                 div[f->V(1)] +=2; sum[f->V(1)] += f->V(0)->T().P(); sum[f->V(1)] += f->V(2)->T().P();
00434                 div[f->V(2)] +=2; sum[f->V(2)] += f->V(1)->T().P(); sum[f->V(2)] += f->V(0)->T().P();
00435         }
00436 
00437         for (typename MESH_TYPE::VertexIterator v=m.vert.begin(); v!=m.vert.end(); v++) // if (!v->IsB()) 
00438   {
00439                 if (v->div>0) {
00440                         v->T().P() = sum[v]/div[v];
00441                 }
00442         }
00443         
00444         div.Stop();
00445   sum.Stop();
00446 
00447 }
00448 
00449 
00450 
00451 }       }       // End namespace vcg::tri
00452 
00453 #endif //  __VCGLIB__TEXTCOOORD_OPTIMIZATION


shape_reconstruction
Author(s): Roberto Martín-Martín
autogenerated on Sat Jun 8 2019 18:37:18