visshader.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.9  2005/11/12 06:47:18  cignoni
00028 Added Enhancement, removed type warnings,
00029 started to refactor code in order to remove the unnecessary generality of the class.
00030 
00031 Revision 1.8  2004/09/28 09:45:17  cignoni
00032 Added MapFalseColor
00033 
00034 Revision 1.7  2004/09/16 14:23:57  ponchio
00035 fixed gcc template compatibility issues.
00036 
00037 Revision 1.6  2004/09/10 14:02:20  cignoni
00038 Added Cone directions
00039 
00040 Revision 1.5  2004/09/09 22:59:21  cignoni
00041 Removed many small warnings
00042 
00043 Revision 1.4  2004/09/09 22:37:48  cignoni
00044 Integrated lost modifications...
00045 
00046 Revision 1.3  2004/09/09 14:35:54  ponchio
00047 Various changes for gcc compatibility
00048 
00049 Revision 1.2  2004/07/11 22:13:30  cignoni
00050 Added GPL comments
00051 
00052 
00053 ****************************************************************************/
00054 
00055 #ifndef __VCG_MESH_VISIBILITY
00056 #define __VCG_MESH_VISIBILITY
00057 
00058 #include <stdlib.h>
00059 
00060 #include <bitset>
00061 #include <vcg/math/matrix44.h>
00062 #include <wrap/gl/math.h>
00063 #include "simplepic.h"
00064 #include <vcg/math/gen_normal.h>
00065 
00066 namespace vcg {
00067   // Base Class che definisce le varie interfaccie;
00068 template <class MESH_TYPE, int MAXVIS=2048> class VisShader 
00069 {
00070         public :
00071                 enum {VisMax=MAXVIS};
00072         VisShader(MESH_TYPE &me):m(me)
00073         {
00074                         CullFlag= false;
00075                         IsClosedFlag = false;
00076                         ZTWIST=1e-3;
00077       SplitNum=1;
00078                         
00079                         CameraViewing=false;
00080         }
00081 
00082                 typedef Point3<typename MESH_TYPE::ScalarType> Point3x;
00083 
00084     typedef typename MESH_TYPE::CoordType CoordType;
00085     typedef typename MESH_TYPE::ScalarType ScalarType;
00086                 typedef typename MESH_TYPE::VertexType  VertexType;
00087     typedef typename MESH_TYPE::VertexPointer  VertexPointer;
00088     typedef typename MESH_TYPE::VertexIterator VertexIterator;
00089     typedef typename MESH_TYPE::FaceIterator   FaceIterator;
00090     typedef typename MESH_TYPE::FaceType   FaceType;
00091         typedef Matrix44<ScalarType> Matrix44x;
00092         typedef Box3<ScalarType> Box3x;
00093 
00094 // The Basic Data the mesh and its wrapper;
00095         MESH_TYPE &m;
00096 
00097   std::vector<MESH_TYPE *> OMV;  // Occluder Mesh Vector;
00098 
00099 // la visibilita' e' in float, per ogni entita' 
00100 // 1 significa che e' totalmente visibile per una data direzione.
00101 
00102         std::vector<float> VV;
00103         std::vector< Point3x > VN;                               // Vettore delle normali che ho usato per calcolare la mask e i float in W;
00104 
00105          // User defined parameters and flags
00106          bool IsClosedFlag;
00107          float ZTWIST;
00108          bool CullFlag;   // Enable the frustum culling. Useful when the splitting value is larger than 2 
00109          int SplitNum;
00110          protected:
00111          bool CameraViewing;
00112          //Camera<ScalarType> Cam;
00113          public: 
00114 
00115 /********************************************************/
00116 // Generic functions with Specialized code for every subclass
00117          virtual void MapVisibility(float Gamma=1, float LowPass=0, float HighPass=1,float Scale=1.0)=0;
00118    //virtual void ApplyLightingEnvironment(std::vector<float> &W, float Gamma);
00119          
00120          virtual int GLAccumPixel(      std::vector<int> &PixSeen)=0;
00121          
00122          virtual bool ReadVisibility(const char * /*filename*/){assert( 0); return false;}
00123          virtual bool WriteVisibility(const char * /*filename*/){assert( 0); return false;}
00124 
00125 /********************************************************/
00126 // Generic functions with same code for every subclass
00127 
00128         void Clear() {          
00129         fill(VV.begin(),VV.end(),0); }
00130 
00131         void InitGL() 
00132                 {
00133                   glPushAttrib(GL_COLOR_BUFFER_BIT );
00134       ::glClearColor (1.0, 1.0, 1.0, 0.0);
00135                         glMatrixMode (GL_PROJECTION);                           
00136                         glPushMatrix();
00137                         glMatrixMode (GL_MODELVIEW);    
00138                         glPushMatrix();
00139                 }
00140 
00141         void RestoreGL()
00142                 {
00143                         glMatrixMode (GL_PROJECTION);                           
00144                         glPopMatrix();
00145                         glMatrixMode (GL_MODELVIEW);    
00146                         glPopMatrix();
00147                         glPopAttrib();
00148                 }
00149 
00150 
00151 /*
00152  Funzione principale di conversione in visibilita'
00153  Dati i due vettori PixSeen e PixNotSeen che indicano per ogni entita' (vertice o faccia) 
00154  quanti sono, rispettivamente,  i pixel visibili e occlusi,
00155  questa funzione calcola un valore float per ogni entita' che indica quanto  e' visibile lungo una data direzione camera 
00156  == 1 significa completamente visibile
00157  == 0 significa completamente occluso.
00158 
00159 */
00160         void AddPixelCount(std::vector<float> &_VV, const std::vector<int> &PixSeen)
00161                 {
00162                 assert(_VV.size()==PixSeen.size());
00163                         for(unsigned int i=0;i<PixSeen.size();++i)
00164                                 if(PixSeen[i]>0) _VV[i]+= 1;
00165                 }
00166  
00167 
00168  //void SetVisibilityMask(std::vector< std::bitset<MAXVIS> > &_VM, const std::vector<int> &PixSeen, const int dir)
00169         //      {
00170         //      assert(_VM.size()==PixSeen.size());
00171         //              for(int i=0;i<PixSeen.size();++i)
00172         //                      if(PixSeen[i]>0) _VM[i][dir]=true;
00173         //      }
00174 
00175 /*******************************
00176 Funzioni ad alto livello che computano le Visibility Mask per varie distribuzioni di direzioni
00177 
00178 
00179 *******************************/
00180 
00181 // Funzione Generica 
00182 // Calcola l'occlusion in base all'insieme VN di direzioni.
00183 
00184 void Compute( CallBack *cb)
00185 {
00186   //cb(buf.format("Start to compute %i dir\n",VN.size()));
00187         InitGL();
00188   int t00=clock();
00189         VV.resize(m.vert.size());
00190   std::vector<int> PixSeen(VV.size(),0);
00191         int TotRay=0,HitRay=0;
00192         for(unsigned int i=0;i<VN.size();++i)
00193                 {
00194       int t0=clock(); 
00195                         fill(PixSeen.begin(),PixSeen.end(),0);
00196       int added=SplittedRendering(VN[i], PixSeen,cb);   
00197                   AddPixelCount(VV,PixSeen);
00198       int t1=clock();
00199       HitRay+=added;
00200       TotRay+=VV.size();
00201       printf("%3i/%i : %i msec -- TotRays %i, HitRays %i, ray/sec %3.1fk \n ",i,VN.size(),t1-t0,TotRay,HitRay,float(TotRay)/(clock()-t00));
00202                 }
00203   
00204   printf("Tot Time %i msec TotRays %i, HitRays %i, ray/sec %3.1fk \n ",clock()-t00,TotRay,HitRay,float(TotRay)/(clock()-t00));
00205         RestoreGL();
00206 }
00207 
00208 void ComputeHalf(int nn, Point3x &dir, CallBack *cb)
00209 {
00210         std::string buf;
00211         
00212         VN.clear();
00213         std::vector<Point3x> nvt;
00214         assert(0 && "This is only my guess (to compile). (Ponchio)");
00215         assert(0 && "Was: GenNormal(nn*2, nvt);");
00216         GenNormal<ScalarType>::Uniform(nn*2,nvt);
00217         for(int i=0;i<nvt.size();++i)
00218                 if(dir*nvt[i]>0) VN.push_back(nvt[i]);
00219  
00220         printf("Asked %i normal, got %i normals\n",nn,VN.size());
00221   Compute(cb); 
00222 }
00223 
00224 void ComputeUniformCone(int nn, std::vector<Point3x> &vv, ScalarType AngleRad, Point3x &ConeDir, CallBack *cb)
00225 {
00226         VN.clear();
00227   GenNormal<ScalarType>::UniformCone(nn,VN,AngleRad,ConeDir);
00228   typename std::vector<Point3x>::iterator vi;
00229   for(vi=VN.begin();vi!=VN.end();++vi) 
00230     vv.push_back(*vi); 
00231   
00232         char buf[256];
00233         sprintf(buf,"Asked %i normal, got %i normals\n",nn,VN.size());
00234   cb(buf);
00235   Compute(cb); 
00236 }
00237 void ComputeUniform(int nn, std::vector<Point3x> &vv, CallBack *cb)
00238 {
00239         VN.clear();
00240   GenNormal<ScalarType>::Uniform(nn,VN);
00241   typename std::vector<Point3x>::iterator vi;
00242   for(vi=VN.begin();vi!=VN.end();++vi) 
00243     vv.push_back(*vi); 
00244   
00245         char buf[256];
00246         sprintf(buf,"Asked %i normal, got %i normals\n",nn,VN.size());
00247   cb(buf);
00248   Compute(cb); 
00249 }
00250 
00251 void ComputeSingle(Point3x &dir, std::vector<Point3x> &vv,CallBack *cb)
00252 {
00253         VN.clear();
00254         VN.push_back(dir);
00255   vv.push_back(dir);
00256         printf("Computing one direction (%f %f %f)\n",dir[0],dir[1],dir[2]);
00257   Compute(cb); 
00258 }
00259 
00260 /**********************************************************/
00261 
00262 int SplittedRendering(Point3x &ViewDir, std::vector<int> &PixSeen, CallBack *cb=DummyCallBack)
00263 {
00264   int tt=0;
00265   int i,j;
00266   for(i=0;i<SplitNum;++i)
00267     for(j=0;j<SplitNum;++j){
00268         SetupOrthoViewMatrix(ViewDir, i,j,SplitNum);
00269               tt+=GLAccumPixel(PixSeen);
00270     }
00271     return tt;
00272 }
00273 
00274 // Compute a rotation matrix that bring Axis parallel to Z. 
00275 void GenMatrix(Matrix44d &a, Point3d Axis, double angle)
00276 {
00277         const double eps=1e-3;
00278         Point3d RotAx   = Axis ^ Point3d(0,0,1);
00279   double RotAngle = Angle(Axis,Point3d(0,0,1));
00280 
00281   if(math::Abs(RotAx.Norm())<eps) { // in questo caso Axis e' collineare con l'asse z
00282                         RotAx=Axis ^ Point3d(0,1,0);
00283       double RotAngle = Angle(Axis,Point3d(0,1,0));
00284                 }
00285   
00286   //printf("Rotating around (%5.3f %5.3f %5.3f) %5.3f\n",RotAx[0],RotAx[1],RotAx[2],RotAngle);
00287   RotAx.Normalize();
00288   a.SetRotate(RotAngle,RotAx);
00289         //Matrix44d rr;
00290   //rr.SetRotate(-angle, Point3d(0,0,1));
00291         //a=rr*a;
00292 }
00293 
00294 
00295 // Genera la matrice di proj e model nel caso di un rendering ortogonale.
00296 // subx e suby indicano la sottoparte che si vuole
00297 void SetupOrthoViewMatrix(Point3x &ViewDir, int subx, int suby,int LocSplit)
00298 {
00299         glMatrixMode (GL_PROJECTION);                           
00300         glLoadIdentity (); 
00301   float dlt=2.0f/LocSplit;
00302 
00303   glOrtho(-1+subx*dlt, -1+(subx+1)*dlt, -1+suby*dlt, -1+(suby+1)*dlt,-2,2);
00304         glMatrixMode (GL_MODELVIEW);    
00305         glLoadIdentity ();  
00306         Matrix44d rot;
00307         Point3d qq; qq.Import(ViewDir);
00308         GenMatrix(rot,qq,0);
00309   glMultMatrix(rot);
00310         double d=2.0/m.bbox.Diag();
00311   glScalef(d,d,d);
00312         glTranslate(-m.bbox.Center());
00313 }
00314 
00315 void ComputeSingleDirection(Point3x BaseDir, std::vector<int> &PixSeen, CallBack *cb=DummyCallBack)
00316 {
00317         int t0=clock();
00318         std::string buf;
00319  
00320         int added=SplittedRendering(BaseDir, PixSeen,cb);       
00321   int t1=clock();
00322         printf("ComputeSingleDir %i msec\n",t1-t0);
00323 }
00324 
00325 void ComputeAverageVisibilityDirection()
00326 {
00327         int i,j;
00328         VD.resize(VM.size());
00329         for(j=0;j<VM.size();++j)
00330                 {
00331                         Point3x &nn=VD[j];
00332                         nn=Point3x(0,0,0);
00333                         bitset<VisMax> &msk=VM[j];
00334                                 for(i=0;i<VN.size();++i)
00335                                     if(msk[i]) nn+=VN[i];
00336                 }
00337                 for(j=0;j<VM.size();++j)
00338                          VD[j].Normalize();
00339                 
00340 }
00341 
00342 // calcola un LightingEnvironment direzionale, cioe'un vettore di pesi per l'insieme di normali 
00343 // corrente tale che 
00344 // mette a 1 tutti i vettori che sono entro un angolo DegAngle1 
00345 // a 0 tutti quelli oltre DegAngle2 e
00346 // sfuma linearmente nel mezzo. 
00347 void DirectionalLightingEnvironment(std::vector<float> &LE, Point3x dir, ScalarType DegAngle1, ScalarType DegAngle2)
00348 {
00349         LE.clear();
00350         LE.resize(VN.size(),0);
00351         int i;
00352         for(i=0;i<VN.size();++i)
00353                 {
00354                         ScalarType a=ToDeg(Angle(dir,VN[i]));
00355                         if(a<DegAngle1) { LE[i]=1; continue; }
00356                         if(a>DegAngle2) { LE[i]=0; continue; }
00357                         LE[i] = 1.0-(a-DegAngle1)/(DegAngle2-DegAngle1);
00358 
00359                 }
00360         // last step normalize the weights;
00361         ScalarType sum=0;
00362         for(i=0;i<VN.size();++i)
00363                 sum+=LE[i];
00364         for(i=0;i<VN.size();++i)
00365                 LE[i]/=sum;
00366 }
00367 
00368 
00369 };
00370 /***************************************************************************/
00371 /***************************************************************************/
00372 /***************************************************************************/
00373 
00374 template <class MESH_TYPE> class VertexVisShader : public VisShader<MESH_TYPE>
00375 {
00376         public :
00377 
00378         // Function Members
00379         VertexVisShader(MESH_TYPE &me):VisShader<MESH_TYPE>(me)
00380         {
00381      // la mesh DEVE avere colore per vertice
00382                         if(! HasPerVertexColor(m)) assert(0);
00383         }
00384 
00385         void Init()  {          VV.resize(m.vert.size()); }
00386         void Compute(int nn);
00387 
00388 void DrawFill (MESH_TYPE &mm)
00389 {
00390   static GLuint dl=0;
00391   if(mm.face.empty())
00392   { AMesh::VertexIterator vi;
00393     glBegin(GL_POINTS);
00394     for(vi=mm.vert.begin();vi!=mm.vert.end();++vi)
00395       {
00396         if(ColorFlag) glColor((*vi).C()); 
00397         glVertex((*vi).P());
00398       }
00399     glEnd();
00400   }
00401   else
00402   {
00403     glBegin(GL_TRIANGLES);
00404     FaceIterator fi;
00405     for(fi=mm.face.begin();fi!=mm.face.end();++fi)
00406     {
00407       glVertex((*fi).V(0)->P());
00408       glVertex((*fi).V(1)->P());
00409       glVertex((*fi).V(2)->P());
00410     }
00411     glEnd();
00412   }
00413 }
00414 
00415 /***************************************************************************/
00416 
00417 //VertexVisibility
00418 // Funzione Principale restituisce per ogni entita' quanti px si vedono o no.
00419 
00420 int GLAccumPixel(       std::vector<int> &PixSeen)
00421 {
00422         SimplePic<float> snapZ;
00423         SimplePic<Color4b> snapC;
00424 
00425   glClearColor(Color4b::Black);
00426         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00427         glPushAttrib(GL_CURRENT_BIT | GL_ENABLE_BIT | GL_LIGHTING_BIT | GL_POLYGON_BIT );
00428         glDisable(GL_LIGHTING); 
00429         glDepthRange(0.0f,1.0f);
00430         glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
00431         glDepthMask(GL_TRUE);
00432         glDrawBuffer(GL_BACK);
00433         glReadBuffer(GL_BACK);
00434         
00436   glDepthRange(2.0*ZTWIST,1.0f);
00437   if(IsClosedFlag) glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE);
00438         glEnable(GL_CULL_FACE);
00439         glCullFace(GL_BACK);
00440         glColor(Color4b::Red);
00441         DrawFill(m);
00442   
00443   if(!IsClosedFlag) {
00444       glCullFace(GL_FRONT);
00445             glColor(Color4b::Black);
00446             DrawFill(m);
00447       snapC.OpenGLSnap();
00448   }
00449     
00450         int cnt=0;
00451         snapZ.OpenGLSnap(GL_DEPTH_COMPONENT);
00452         
00453   glDepthRange(0,1.0f-2.0*ZTWIST);
00454   double MM[16];
00455         glGetDoublev(GL_MODELVIEW_MATRIX,MM);
00456         double MP[16];
00457   glGetDoublev(GL_PROJECTION_MATRIX,MP);
00458         int VP[4];
00459         glGetIntegerv(GL_VIEWPORT,VP);
00460         double tx,ty,tz;
00461   
00462         for(unsigned int i=0;i<m.vert.size();++i)
00463         {
00464                 gluProject(m.vert[i].P()[0],m.vert[i].P()[1],m.vert[i].P()[2],
00465                         MM,MP,VP,
00466                         &tx,&ty,&tz);
00467     int col=1;
00468                     
00469     if(tx>=0 && tx<snapZ.sx && ty>=0 && ty<snapZ.sy)
00470     {
00471                     int txi=floor(tx),tyi=floor(ty);
00472                     float sd=snapZ.Pix(tx,ty);
00473                 if(!IsClosedFlag) {
00474           col = max( max(snapC.Pix(txi+0,tyi+0)[0],snapC.Pix(txi+1,tyi+0)[0]),
00475                                                            max(snapC.Pix(txi+0,tyi+1)[0],snapC.Pix(txi+1,tyi+1)[0]));
00476                     
00477         // col=snapC.Pix(txi+0,tyi+0)[0];
00478         }
00479         if(col!=0 && tz<sd) {
00480                             PixSeen[i]++;
00481                             cnt++;
00482                     }
00483             }
00484   }
00485         glPopAttrib();
00486 //printf("Seen %i vertexes on %i\n",cnt,m.vert.size());
00487 return cnt;
00488 }
00489 
00490 void SmoothVisibility(bool Enhance=false)
00491 {
00492         FaceIterator fi;
00493         std::vector<float> VV2;
00494         std::vector<int> VC(VV.size(),1);
00495         VV2=VV;
00496         for(fi=m.face.begin();fi!=m.face.end();++fi)
00497                 for(int i=0;i<3;++i)
00498                 {
00499                         VV2[(*fi).V(i)-&*m.vert.begin()] += VV[(*fi).V1(i)-&*m.vert.begin()];
00500                         ++VC[(*fi).V(i)-&*m.vert.begin()];
00501                 }
00502 
00503  if(!Enhance)
00504           for(unsigned int i=0;i<VV2.size();++i)
00505                 VV[i]=VV2[i]/VC[i];
00506  else
00507           for(unsigned int i=0;i<VV2.size();++i)
00508                     VV[i]=VV[i]+ (VV[i]-VV2[i]/VC[i])*.5;
00509 }
00510 
00511 
00512 void MapFalseColor()
00513 {
00514   float minv=*min_element(VV.begin(),VV.end());
00515         float maxv=*max_element(VV.begin(),VV.end());
00516         printf("Visibility Range %f %f\n", minv,maxv);
00517   MapFalseColor(minv, maxv);
00518 }
00519 
00520 void MapFalseColor(float minv, float maxv)
00521 {
00522         VertexIterator vi;
00523         for(vi=m.vert.begin();vi!=m.vert.end();++vi){
00524                             float gval=(VV[vi-m.vert.begin()]-minv)/(maxv-minv);
00525           math::Clamp(gval,0.0f,1.0f);
00526                                   (*vi).C().ColorRamp(1.0,0.0,gval);
00527         }
00528 }
00529 
00530 /*
00531 The visibility is mapped in [0..1]
00532 then clamped to [low,high]
00533 this value is mapped again in [0.1] and gamma corrected;
00534 and at the end is scaled for 'Scale'
00535 */
00536 
00537 void MapVisibility(float Gamma=1, float LowPass=0, float HighPass=1, float Scale= 1.0)
00538 {
00539         float minv=*min_element(VV.begin(),VV.end());
00540         float maxv=*max_element(VV.begin(),VV.end());
00541         printf("Visibility Range %f %f\n", minv,maxv);
00542 
00543         VertexIterator vi;
00544                         for(vi=m.vert.begin();vi!=m.vert.end();++vi){
00545                                 float gval=(VV[vi-m.vert.begin()]-minv)/(maxv-minv);
00546                                 if(gval<LowPass) gval=LowPass;
00547                                 if(gval>HighPass) gval=HighPass;
00548                                 (*vi).C().SetGrayShade(Scale*pow((gval-LowPass)/(HighPass-LowPass),Gamma));
00549                         }
00550 }
00551 
00552 //void ApplyLightingEnvironment(std::vector<float> &W, float Gamma=1)
00553 //      {
00554 //              assert(W.size()==VN.size());
00555 //              MESH_TYPE::VertexIterator vi;
00556 //      
00557 //              for(vi=m.vert.begin();vi!=m.vert.end();++vi)
00558 //              {
00559 //              float gray=0;
00560 //              bitset<VisMax> &msk=VM[vi-m.vert.begin()];
00561 //                      for(int i=0;i<VN.size();++i)
00562 //                              if(msk[i]) gray+=W[i];
00563 //                      
00564 //                      (*vi).C().SetGrayShade(gray);
00565 //              }
00566 //      }
00567 
00568 };
00569 
00570 
00571 
00572 }
00573 #endif // __VCG_MESH_VISIBILITY


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