00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
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
00052
00053
00054
00055
00056
00057
00058
00059
00060 namespace vcg
00061 {
00062 namespace tri
00063 {
00064
00065
00066
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
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
00084 const MeshType & Mesh() const {return m;}
00085 MeshType & Mesh() {return m;}
00086
00087
00088 TextureOptimizer(MeshType &_m):m(_m),isFixed(_m.vert){
00089 assert(m.HasPerVertexTexture());
00090 }
00091
00092
00093 virtual void TargetCurrentGeometry()=0;
00094
00095
00096 virtual ScalarType Iterate()=0;
00097
00098
00099 virtual void IterateBlind()=0;
00100
00101
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
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
00119 ~TextureOptimizer(){
00120 isFixed.Stop();
00121 };
00122
00123
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
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
00140 void FixVertex(const VertexType *v, bool fix=true){
00141 isFixed[v]=(fix)?1:0;
00142 }
00143
00144
00145 };
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171 template<class MESH_TYPE>
00172 class AreaPreservingTextureOptimizer:public TextureOptimizer<MESH_TYPE>{
00173 public:
00174
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;
00185
00186
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
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
00218
00219
00220
00221
00222 void SetTheta(int _theta){
00223 theta=_theta;
00224 }
00225
00226 int GetTheta(){
00227 return theta;
00228 }
00229
00230 void IterateBlind(){
00231
00232 Iterate();
00233 }
00234
00235 ScalarType Iterate(){
00236
00237 ScalarType max;
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;
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,
00269 mA= data[f][3]/area2 * scale,
00270 e = m0*((b-a)*(b-a)+c*c) + m1*(b*b+c*c) + m2*a*a,
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
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288 dx=
00289
00290 pow(M1,theta-1)
00291 *(px*(M1+ theta*M2) - 2.0*qx*M1),
00292 dy=
00293
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
00301
00302 sum[f->V(i)]+= ( (v1-v0) * gx + (v2-v0) * gy ) * data[f][3];
00303 }
00304 }
00305 max=0;
00306 speed=0.001;
00307 for (VertexIterator v=Super::m.vert.begin(); v!=Super::m.vert.end(); v++)
00308 if ( !Super::isFixed[v] )
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
00317 }
00318 return max;
00319 #undef v0
00320 #undef v1
00321 #undef v2
00322
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
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
00350
00351
00352
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
00373
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
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
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
00411
00412
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++)
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 } }
00452
00453 #endif // __VCGLIB__TEXTCOOORD_OPTIMIZATION