pick.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 #ifndef __PICK______H
00025 #define __PICK______H
00026 
00027 #include <vector>
00028 #include <algorithm>
00029 namespace vcg{
00030 
00031 template <class MESH_TYPE>
00032 class GLPickTri
00033 {
00034   typedef typename MESH_TYPE::ScalarType ScalarType;
00035   typedef typename MESH_TYPE::CoordType CoordType;
00036   typedef typename MESH_TYPE::FaceIterator FaceIterator;
00037   typedef typename MESH_TYPE::VertexIterator VertexIterator;
00038   typedef typename MESH_TYPE::FacePointer  FacePointer;
00039   typedef typename MESH_TYPE::VertexPointer  VertexPointer;
00040   typedef typename MESH_TYPE::VertexType  VertexType;
00041 
00042 private:
00043 
00044  static CoordType Proj(const Eigen::Matrix<ScalarType,4,4> &M, const ScalarType * viewport, const CoordType &p)
00045   {
00046     const ScalarType vx=viewport[0];
00047     const ScalarType vy=viewport[1];
00048     const ScalarType vw2=viewport[2]/ScalarType(2.0);
00049     const ScalarType vh2=viewport[3]/ScalarType(2.0);
00050     Eigen::Matrix<ScalarType,4,1> vp(p[0],p[1],p[2],ScalarType(1.0));
00051     Eigen::Matrix<ScalarType,4,1> vpp = M*vp;
00052     Eigen::Matrix<ScalarType,4,1> ndc = vpp/vpp[3];
00053 
00054     CoordType sc(
00055         vw2*ndc[0] + vx+vw2,
00056         vh2*ndc[1] + vy+vh2,
00057         ndc[2]
00058         );
00059 
00060     return sc;
00061   }
00062 
00063   static void FillProjectedVector(MESH_TYPE &m, std::vector<CoordType> &pVec, const Eigen::Matrix<ScalarType,4,4> &M, const ScalarType * viewportF)
00064   {
00065     pVec.resize(m.vert.size());
00066     for(size_t i=0;i<m.vert.size();++i) if(!m.vert[i].IsD())
00067     {
00068       pVec[i] = Proj(M, viewportF,CoordType::Construct(m.vert[i].P()));
00069     }
00070   }
00071 
00072   static void glGetMatrixAndViewport(Eigen::Matrix<ScalarType,4,4> &M, ScalarType *viewportF)
00073   {
00074     Eigen::Matrix4d mp,mm;
00075 
00076     GLint viewport[4];
00077     glGetIntegerv(GL_VIEWPORT,viewport);
00078     for(int i=0;i<4;++i) viewportF[i]=viewport[i];
00079 
00080     glGetDoublev(GL_PROJECTION_MATRIX, mp.data());
00081     glGetDoublev(GL_MODELVIEW_MATRIX,  mm.data());
00082 
00083     M = (mp*mm).cast<ScalarType>();
00084   }
00085 
00086   // compute a bbox in Device Coordinate (with the z without the near far normalization and ranged in -1 1)
00087   static Box3<ScalarType> ComputeDCBox(int x, int y, int width, int height)
00088   {
00089     Box3<ScalarType> bb;
00090     bb.SetNull();
00091     bb.Add(CoordType(x-width/ScalarType(2.0),y-height/ScalarType(2.0),ScalarType(-1.0)));
00092     bb.Add(CoordType(x+width/ScalarType(2.0),y+height/ScalarType(2.0), ScalarType(1.0)));
00093     return bb;
00094   }
00095 
00096 public:
00097 
00098   static bool PickClosestFace(int x, int y, MESH_TYPE &m, FacePointer &fp,int width=4, int height=4)
00099   {
00100     Eigen::Matrix<ScalarType,4,4> M;
00101     ScalarType viewportF[4];
00102     glGetMatrixAndViewport(M,viewportF);
00103     Box3<ScalarType> reg=ComputeDCBox(x,y,width,height);
00104 
00105     ScalarType bzmin = std::numeric_limits<ScalarType>::max();
00106     fp=0;
00107     for(size_t i=0;i<m.face.size();++i) if(!m.face[i].IsD())
00108     {
00109       CoordType bary = vcg::Barycenter(m.face[i]);
00110       CoordType bz = Proj(M, viewportF,bary);
00111 
00112       if(bz[2]<bzmin && reg.IsIn(bz))
00113       {
00114         bzmin=bz[2];
00115         fp = &m.face[i];
00116       }
00117     }
00118     return fp!=0;
00119   }
00120 
00121   static bool PickClosestVert(int x, int y, MESH_TYPE &m, VertexPointer &vp,int width=4, int height=4)
00122   {
00123     Eigen::Matrix<ScalarType,4,4> M;
00124     ScalarType viewportF[4];
00125     glGetMatrixAndViewport(M,viewportF);
00126     ScalarType bzmin = std::numeric_limits<ScalarType>::max();
00127     vp=0;
00128 
00129     Box3<ScalarType> reg=ComputeDCBox(x,y,width,height);
00130 
00131     for(size_t i=0;i<m.vert.size();++i) if(!m.vert[i].IsD())
00132     {
00133       CoordType bz = Proj(M, viewportF,m.vert[i].P());
00134       if(bz[2]<bzmin && reg.IsIn(bz))
00135       {
00136         bzmin=bz[2];
00137         vp = &m.vert[i];
00138       }
00139     }
00140     return vp!=0;
00141   }
00142 
00143   static int PickVert(int x, int y, MESH_TYPE &m, std::vector<VertexPointer> &result, int width=4, int height=4)
00144    {
00145      result.clear();
00146      static Eigen::Matrix<ScalarType,4,4> lastM;
00147      static MESH_TYPE *lastm=0;
00148      static std::vector<CoordType> pVec;
00149 
00150      Eigen::Matrix<ScalarType,4,4> M;
00151      ScalarType viewportF[4];
00152      glGetMatrixAndViewport(M,viewportF);
00153 
00154      Box3<ScalarType> reg =ComputeDCBox(x,y,width,height);
00155 
00156      if(M!=lastM || &m != lastm)
00157      {
00158        FillProjectedVector(m,pVec,M,viewportF);
00159        lastM = M;
00160        lastm = &m;
00161      }
00162 
00163      for(size_t i=0;i<m.vert.size();++i) if(!m.vert[i].IsD())
00164      {
00165        if(reg.IsIn(pVec[i]))
00166          result.push_back(&m.vert[i]);
00167      }
00168      return result.size();
00169    }
00170 
00171   static int PickFace(int x, int y, MESH_TYPE &m, std::vector<FacePointer> &result, int width=4, int height=4)
00172   {
00173     static Eigen::Matrix<ScalarType,4,4> lastM;
00174     static MESH_TYPE *lastm=0;
00175     static std::vector<CoordType> pVec;
00176 
00177     ScalarType viewportF[4];
00178     Eigen::Matrix<ScalarType,4,4> M;
00179     glGetMatrixAndViewport(M,viewportF);
00180     result.clear();
00181     Box3<ScalarType> reg;
00182     reg.Add(CoordType(x-width/ScalarType(2.0),y-height/ScalarType(2.0),ScalarType(-1.0)));
00183     reg.Add(CoordType(x+width/ScalarType(2.0),y+height/ScalarType(2.0),ScalarType(1.0)));
00184 
00185     if(M!=lastM || &m != lastm)
00186     {
00187       FillProjectedVector(m,pVec,M,viewportF);
00188       lastM = M;
00189       lastm = &m;
00190     }
00191 
00192     for(size_t i=0;i<m.face.size();++i) if(!m.face[i].IsD())
00193     {
00194       const CoordType &p0 = pVec[tri::Index(m,m.face[i].V(0))];
00195       const CoordType &p1 = pVec[tri::Index(m,m.face[i].V(1))];
00196       const CoordType &p2 = pVec[tri::Index(m,m.face[i].V(2))];
00197       if( (p0[2]>-1.0f) && (p1[2]>-1.0f) && (p2[2]>-1.0f) && IntersectionTriangleBox(reg,p0,p1,p2))
00198         result.push_back(&m.face[i]);
00199     }
00200     return result.size();
00201   }
00202 
00203   // Same of above but it also assumes that you want only visible faces.
00204   // Visibility is computed according to the current depth buffer.
00205   static int PickVisibleFace(int x, int y, MESH_TYPE &m, std::vector<FacePointer> &resultZ, int width=4, int height=4)
00206   {
00207     ScalarType vp[4];
00208     Eigen::Matrix<ScalarType,4,4> M;
00209     glGetMatrixAndViewport(M,vp);
00210 
00211     int screenW = (int)(vp[2]-vp[0]);
00212     int screenH = (int)(vp[3]-vp[1]);
00213 
00214     GL_TYPE_NM<Scalarm>::ScalarType *buffer = new GL_TYPE_NM<Scalarm>::ScalarType[screenW*screenH];
00215 
00216     //I'm not sure glReadPixels can accept GL_DOUBLE tag
00217     //GLenum err = glGetError();
00218     glReadPixels(vp[0],vp[1],vp[2],vp[3],GL_DEPTH_COMPONENT,GL_TYPE_NM<Scalarm>::SCALAR(),buffer);
00219     //err = glGetError();
00220     std::vector<FacePointer> result;
00221     PickFace(x,y,m,result,width,height);
00222     ScalarType LocalEpsilon(0.001);
00223     for(size_t i =0;i<result.size();++i)
00224     {
00225       CoordType p = Proj(M,vp,CoordType::Construct(Barycenter(*(result[i])))) ;
00226       if(p[0] >=0 && p[0]<screenW && p[1] >=0 && p[1]<screenH)
00227       {
00228         ScalarType bufZ(buffer[int(p[0])+int(p[1])*screenW]);
00229         //qDebug("face %i txyz (%f %f %f)  bufz %f",i,tx,ty,tz,bufZ);
00230         if(bufZ + LocalEpsilon >= ScalarType(p[2]+1.0)/2.0)
00231           resultZ.push_back(result[i]);
00232       }
00233     }
00234 
00235     delete [] buffer;
00236     return resultZ.size();
00237   }
00238 
00239 
00240 
00241  // Same of above but it also assumes that you want only visible faces.
00242  // Visibility is computed according to the current depth buffer.
00243     static int OldPickFaceVisible(int x, int y, MESH_TYPE &m, std::vector<FacePointer> &resultZ, int width=4, int height=4, bool sorted=true)
00244     {
00245         // First step
00246 
00247         double mm[16];
00248         double mp[16];
00249         GLint vp[4];
00250         glGetIntegerv(GL_VIEWPORT,vp);
00251         glGetDoublev(GL_MODELVIEW_MATRIX ,mm);
00252         glGetDoublev(GL_PROJECTION_MATRIX ,mp);
00253         int screenW =           vp[2]-vp[0];
00254         int screenH =           vp[3]-vp[1];
00255 
00256 
00257         GL_TYPE_NM<Scalarm>::ScalarType *buffer = new GL_TYPE_NM<Scalarm>::ScalarType[screenW*screenH];
00258 
00259         //I'm not sure glReadPixels can accept GL_DOUBLE tag
00260         //GLenum err = glGetError();
00261         glReadPixels(vp[0],vp[1],vp[2],vp[3],GL_DEPTH_COMPONENT,GL_TYPE_NM<Scalarm>::SCALAR(),buffer);
00262         //err = glGetError();
00263 
00264         std::vector<FacePointer> result;
00265         OldPickFace(x,y,m,result,width,height,sorted);
00266         ScalarType LocalEpsilon(0.001);
00267         for(size_t i =0;i<result.size();++i)
00268         {
00269             CoordType v=Barycenter(*(result[i]));
00270             GLdouble tx,ty,tz;
00271             gluProject(v.X(),v.Y(),v.Z(), mm,mp,vp, &tx,&ty,&tz);
00272             if(tx >=0 && tx<screenW && ty >=0 && ty<screenH)
00273             {
00274                     ScalarType bufZ(buffer[int(tx)+int(ty)*screenW]);
00275                     //qDebug("face %i txyz (%f %f %f)  bufz %f",i,tx,ty,tz,bufZ);
00276                     if(bufZ + LocalEpsilon >= tz)
00277                                 resultZ.push_back(result[i]);
00278             }
00279         }
00280 
00281         delete [] buffer;
00282         return resultZ.size();
00283     }
00284 
00285 
00286     static int OldPickFace(int x, int y, MESH_TYPE &m, std::vector<FacePointer> &result, int width=4, int height=4,bool sorted=true)
00287       {
00288           result.clear();
00289       if(width==0 ||height==0) return 0;
00290           long hits;
00291           int sz=m.face.size()*5;
00292           GLuint *selectBuf =new GLuint[sz];
00293           //  static unsigned int selectBuf[16384];
00294           glSelectBuffer(sz, selectBuf);
00295           glRenderMode(GL_SELECT);
00296           glInitNames();
00297 
00298           /* Because LoadName() won't work with no names on the stack */
00299           glPushName(-1);
00300           double mp[16];
00301 
00302           GLint viewport[4];
00303           glGetIntegerv(GL_VIEWPORT,viewport);
00304           glMatrixMode(GL_PROJECTION);
00305           glGetDoublev(GL_PROJECTION_MATRIX ,mp);
00306           glPushMatrix();
00307           glLoadIdentity();
00308           //gluPickMatrix(x, viewport[3]-y, 4, 4, viewport);
00309           gluPickMatrix(x, y, width, height, viewport);
00310           glMultMatrixd(mp);
00311 
00312           glMatrixMode(GL_MODELVIEW);
00313           glPushMatrix();
00314           int fcnt=0;
00315           FaceIterator fi;
00316           for(fi=m.face.begin();fi!=m.face.end();++fi)
00317           {
00318               if(!(*fi).IsD())
00319               {
00320                   glLoadName(fcnt);
00321                   glBegin(GL_TRIANGLES);
00322                       glVertex( (*fi).V(0)->P() );
00323                       glVertex( (*fi).V(1)->P() );
00324                       glVertex( (*fi).V(2)->P() );
00325                   glEnd();
00326               }
00327         fcnt++; // the counter should advance even for deleted faces!
00328           }
00329 
00330           glPopMatrix();
00331           glMatrixMode(GL_PROJECTION);
00332           glPopMatrix();
00333           glMatrixMode(GL_MODELVIEW);
00334           hits = glRenderMode(GL_RENDER);
00335           //xstring buf;
00336           //if (hits <= 0)     return 0;
00337           std::vector< std::pair<double,unsigned int> > H;
00338           for(long ii=0;ii<hits;ii++){
00339               //TRACE("%ui %ui %ui %ui\n",selectBuf[ii*4],selectBuf[ii*4+1],selectBuf[ii*4+2],selectBuf[ii*4+3]);
00340               H.push_back( std::pair<double,unsigned int>(selectBuf[ii*4+1]/4294967295.0,selectBuf[ii*4+3]));
00341           }
00342           if(sorted)
00343         std::sort(H.begin(),H.end());
00344           //  if(H.size()>0) TRACE("\n Closest is %i\n",H[0].second);
00345           result.resize(H.size());
00346           for(long ii=0;ii<hits;ii++){
00347               FaceIterator fi=m.face.begin();
00348               advance(fi ,H[ii].second);
00349               result[ii]=&*fi;
00350           }
00351 
00352           delete [] selectBuf;
00353           return result.size();
00354       }
00355 
00356     static int OldPickVert(int x, int y, MESH_TYPE &m, std::vector<VertexPointer> &result, int width=4, int height=4,bool sorted=true)
00357     {
00358         result.clear();
00359         if(width==0 ||height==0) return 0;
00360         long hits;
00361         int sz=m.vert.size()*5;
00362         GLuint *selectBuf =new GLuint[sz];
00363         glSelectBuffer(sz, selectBuf);
00364         glRenderMode(GL_SELECT);
00365         glInitNames();
00366 
00367         /* Because LoadName() won't work with no names on the stack */
00368         glPushName(-1);
00369         double mp[16];
00370 
00371         GLint viewport[4];
00372         glGetIntegerv(GL_VIEWPORT,viewport);
00373         glMatrixMode(GL_PROJECTION);
00374         glGetDoublev(GL_PROJECTION_MATRIX ,mp);
00375         glPushMatrix();
00376         glLoadIdentity();
00377         gluPickMatrix(x, y, width, height, viewport);
00378         glMultMatrixd(mp);
00379 
00380         glMatrixMode(GL_MODELVIEW);
00381         glPushMatrix();
00382         int vcnt=0;
00383         VertexIterator vi;
00384         for(vi=m.vert.begin();vi!=m.vert.end();++vi)
00385         {
00386           if(!(*vi).IsD())
00387           {
00388             glLoadName(vcnt);
00389             glBegin(GL_POINTS);
00390               glVertex( (*vi).P() );
00391             glEnd();
00392           }
00393           vcnt++; // the counter should advance even for deleted faces!
00394         }
00395 
00396         glPopMatrix();
00397         glMatrixMode(GL_PROJECTION);
00398         glPopMatrix();
00399         glMatrixMode(GL_MODELVIEW);
00400         hits = glRenderMode(GL_RENDER);
00401         std::vector< std::pair<double,unsigned int> > H;
00402         for(long ii=0;ii<hits;ii++){
00403           H.push_back( std::pair<double,unsigned int>(selectBuf[ii*4+1]/4294967295.0,selectBuf[ii*4+3]));
00404         }
00405         if(sorted)
00406           std::sort(H.begin(),H.end());
00407         result.resize(H.size());
00408         for(long ii=0;ii<hits;ii++){
00409           VertexIterator vi=m.vert.begin();
00410           advance(vi ,H[ii].second);
00411           result[ii]=&*vi;
00412         }
00413 
00414         delete [] selectBuf;
00415         return result.size();
00416     }
00417 
00418 };
00419 
00420 }
00421 
00422 #endif


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