From adfa6dde129de07c2e70eb51d8adde46c453943a Mon Sep 17 00:00:00 2001 From: cignoni Date: Mon, 7 Apr 2014 12:32:21 +0000 Subject: [PATCH] Added PickVertSW to offer an alternative for selection for hw that does not support opengl selection --- wrap/gl/pick.h | 498 +++++++++++++++++++++++++++---------------------- 1 file changed, 273 insertions(+), 225 deletions(-) diff --git a/wrap/gl/pick.h b/wrap/gl/pick.h index 796e6a6f..5e89ca16 100644 --- a/wrap/gl/pick.h +++ b/wrap/gl/pick.h @@ -8,7 +8,7 @@ * \ * * All rights reserved. * * * -* This program is free software; you can redistribute it and/or modify * +* This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * @@ -40,7 +40,7 @@ namespace vcg{ template class GLPickTri { - typedef typename MESH_TYPE::FaceIterator FaceIterator; + typedef typename MESH_TYPE::FaceIterator FaceIterator; typedef typename MESH_TYPE::VertexIterator VertexIterator; typedef typename MESH_TYPE::FacePointer FacePointer; typedef typename MESH_TYPE::VertexPointer VertexPointer; @@ -48,18 +48,66 @@ class GLPickTri public: - static bool PickNearestFace(int x, int y, MESH_TYPE &m, FacePointer &fi,int width=4, int height=4) - { - std::vector result; - int val=PickFace(x,y,m,result,width,height); - if(val!=0) - { - fi=result[0]; - return true; - } - fi=NULL; - return false; - } + static bool PickNearestFace(int x, int y, MESH_TYPE &m, FacePointer &fi,int width=4, int height=4) + { + std::vector result; + int val=PickFace(x,y,m,result,width,height); + if(val!=0) + { + fi=result[0]; + return true; + } + fi=NULL; + return false; + } + + static Point3f Proj(const Eigen::Matrix4f &M, const float * viewport, Point3f &p) + { + const float vx=viewport[0]; + const float vy=viewport[1]; + const float vw2=viewport[2]/2.0f; + const float vh2=viewport[3]/2.0f; + Eigen::Vector4f vp(p[0],p[1],p[2],1.0f); + Eigen::Vector4f vpp = M*vp; + Eigen::Vector4f ndc = vpp/vpp[3]; + + Point3f sc( + vw2*ndc[0] + vx+vw2, + vh2*ndc[1] + vy+vh2, + ndc[2] + ); + + return sc; + } + + static int PickVertSW(int x, int y, MESH_TYPE &m, std::vector &result, int width=4, int height=4,bool sorted=true) + { + result.clear(); + Eigen::Matrix4d mp,mm; + Eigen::Matrix4f M; + GLint viewport[4]; + Box2f reg; + reg.Add(Point2f(x-width/2.0f,y-height/2.0f)); + reg.Add(Point2f(x+width/2.0f,y+height/2.0f)); + glGetIntegerv(GL_VIEWPORT,viewport); + float viewportF[4]; + for(int i=0;i<4;++i) viewportF[i]=viewport[i]; + + glGetDoublev(GL_PROJECTION_MATRIX ,mp.data()); + glGetDoublev(GL_MODELVIEW_MATRIX,mm.data()); + M = (mp*mm).cast(); + for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)if(!vi->IsD()) + { + Point3f pp = Proj(M,viewportF,vi->P()); + if(pp[0]reg.max[0]) continue; + if(pp[1]reg.max[1]) continue; + result.push_back(&*vi); + } + return result.size(); + } + static int PickVert(int x, int y, MESH_TYPE &m, std::vector &result, int width=4, int height=4,bool sorted=true) { result.clear(); @@ -121,115 +169,115 @@ public: delete [] selectBuf; return result.size(); } - - static int PickFace(int x, int y, MESH_TYPE &m, std::vector &result, int width=4, int height=4,bool sorted=true) - { - result.clear(); - if(width==0 ||height==0) return 0; - long hits; - int sz=m.face.size()*5; - GLuint *selectBuf =new GLuint[sz]; - // static unsigned int selectBuf[16384]; - glSelectBuffer(sz, selectBuf); - glRenderMode(GL_SELECT); - glInitNames(); - /* Because LoadName() won't work with no names on the stack */ - glPushName(-1); - double mp[16]; + static int PickFace(int x, int y, MESH_TYPE &m, std::vector &result, int width=4, int height=4,bool sorted=true) + { + result.clear(); + if(width==0 ||height==0) return 0; + long hits; + int sz=m.face.size()*5; + GLuint *selectBuf =new GLuint[sz]; + // static unsigned int selectBuf[16384]; + glSelectBuffer(sz, selectBuf); + glRenderMode(GL_SELECT); + glInitNames(); - GLint viewport[4]; - glGetIntegerv(GL_VIEWPORT,viewport); - glMatrixMode(GL_PROJECTION); - glGetDoublev(GL_PROJECTION_MATRIX ,mp); - glPushMatrix(); - glLoadIdentity(); - //gluPickMatrix(x, viewport[3]-y, 4, 4, viewport); - gluPickMatrix(x, y, width, height, viewport); - glMultMatrixd(mp); + /* Because LoadName() won't work with no names on the stack */ + glPushName(-1); + double mp[16]; - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - int fcnt=0; - FaceIterator fi; - for(fi=m.face.begin();fi!=m.face.end();++fi) - { - if(!(*fi).IsD()) - { - glLoadName(fcnt); - glBegin(GL_TRIANGLES); - glVertex( (*fi).V(0)->P() ); - glVertex( (*fi).V(1)->P() ); - glVertex( (*fi).V(2)->P() ); - glEnd(); - } - fcnt++; // the counter should advance even for deleted faces! - } + GLint viewport[4]; + glGetIntegerv(GL_VIEWPORT,viewport); + glMatrixMode(GL_PROJECTION); + glGetDoublev(GL_PROJECTION_MATRIX ,mp); + glPushMatrix(); + glLoadIdentity(); + //gluPickMatrix(x, viewport[3]-y, 4, 4, viewport); + gluPickMatrix(x, y, width, height, viewport); + glMultMatrixd(mp); - glPopMatrix(); - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - hits = glRenderMode(GL_RENDER); - //xstring buf; - //if (hits <= 0) return 0; - std::vector< std::pair > H; - for(long ii=0;ii(selectBuf[ii*4+1]/4294967295.0,selectBuf[ii*4+3])); - } - if(sorted) + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + int fcnt=0; + FaceIterator fi; + for(fi=m.face.begin();fi!=m.face.end();++fi) + { + if(!(*fi).IsD()) + { + glLoadName(fcnt); + glBegin(GL_TRIANGLES); + glVertex( (*fi).V(0)->P() ); + glVertex( (*fi).V(1)->P() ); + glVertex( (*fi).V(2)->P() ); + glEnd(); + } + fcnt++; // the counter should advance even for deleted faces! + } + + glPopMatrix(); + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + hits = glRenderMode(GL_RENDER); + //xstring buf; + //if (hits <= 0) return 0; + std::vector< std::pair > H; + for(long ii=0;ii(selectBuf[ii*4+1]/4294967295.0,selectBuf[ii*4+3])); + } + if(sorted) std::sort(H.begin(),H.end()); - // if(H.size()>0) TRACE("\n Closest is %i\n",H[0].second); - result.resize(H.size()); - for(long ii=0;ii0) TRACE("\n Closest is %i\n",H[0].second); + result.resize(H.size()); + for(long ii=0;ii &resultZ, int width=4, int height=4, bool sorted=true) - { - // First step - - double mm[16]; - double mp[16]; - GLint vp[4]; - glGetIntegerv(GL_VIEWPORT,vp); - glGetDoublev(GL_MODELVIEW_MATRIX ,mm); - glGetDoublev(GL_PROJECTION_MATRIX ,mp); - int screenW = vp[2]-vp[0]; - int screenH = vp[3]-vp[1]; - - GLfloat *buffer = new GLfloat[screenW*screenH]; - glReadPixels(vp[0],vp[1],vp[2],vp[3],GL_DEPTH_COMPONENT,GL_FLOAT,buffer); - - std::vector result; - PickFace(x,y,m,result,width,height,sorted); - float LocalEpsilon = 0.001f; + // Visibility is computed according to the current depth buffer. + static int PickFaceVisible(int x, int y, MESH_TYPE &m, std::vector &resultZ, int width=4, int height=4, bool sorted=true) + { + // First step + + double mm[16]; + double mp[16]; + GLint vp[4]; + glGetIntegerv(GL_VIEWPORT,vp); + glGetDoublev(GL_MODELVIEW_MATRIX ,mm); + glGetDoublev(GL_PROJECTION_MATRIX ,mp); + int screenW = vp[2]-vp[0]; + int screenH = vp[3]-vp[1]; + + GLfloat *buffer = new GLfloat[screenW*screenH]; + glReadPixels(vp[0],vp[1],vp[2],vp[3],GL_DEPTH_COMPONENT,GL_FLOAT,buffer); + + std::vector result; + PickFace(x,y,m,result,width,height,sorted); + float LocalEpsilon = 0.001f; for(size_t i =0;i=0 && tx=0 && ty= tz) - resultZ.push_back(result[i]); - } - } - - delete [] buffer; - return resultZ.size(); - } + { + typename VertexType::CoordType v=Barycenter(*(result[i])); + GLdouble tx,ty,tz; + gluProject(v.X(),v.Y(),v.Z(), mm,mp,vp, &tx,&ty,&tz); + if(tx >=0 && tx=0 && ty= tz) + resultZ.push_back(result[i]); + } + } + + delete [] buffer; + return resultZ.size(); + } }; @@ -238,9 +286,9 @@ public: template class GLPickTetra { - typedef typename TETRA_MESH_TYPE::TetraIterator TetraIterator; - typedef typename TETRA_MESH_TYPE::TetraPointer TetraPointer; - typedef typename TETRA_MESH_TYPE::VertexType VertexType; + typedef typename TETRA_MESH_TYPE::TetraIterator TetraIterator; + typedef typename TETRA_MESH_TYPE::TetraPointer TetraPointer; + typedef typename TETRA_MESH_TYPE::VertexType VertexType; public: static bool PickNearestTetra(int x, int y,TETRA_MESH_TYPE &m, TetraIterator &ti,int width=4, int height=4) @@ -250,10 +298,10 @@ static bool PickNearestTetra(int x, int y,TETRA_MESH_TYPE &m, TetraIterator &ti, if(val!=0) { ti=result[0]; - return true; + return true; } ti=0; - return false; + return false; } @@ -262,79 +310,79 @@ class Tetra; static int PickTetra(int x, int y, TETRA_MESH_TYPE &m, std::vector &result, int width=4, int height=4) { - result.clear(); - long hits; + result.clear(); + long hits; int sz=m.tetra.size()*5; - unsigned int *selectBuf =new unsigned int[sz]; - // static unsigned int selectBuf[16384]; + unsigned int *selectBuf =new unsigned int[sz]; + // static unsigned int selectBuf[16384]; glSelectBuffer(sz, selectBuf); glRenderMode(GL_SELECT); glInitNames(); /* Because LoadName() won't work with no names on the stack */ glPushName(-1); - double mp[16]; - + double mp[16]; + int viewport[4]; glGetIntegerv(GL_VIEWPORT,viewport); - glMatrixMode(GL_PROJECTION); - glGetDoublev(GL_PROJECTION_MATRIX ,mp); - glPushMatrix(); + glMatrixMode(GL_PROJECTION); + glGetDoublev(GL_PROJECTION_MATRIX ,mp); + glPushMatrix(); glLoadIdentity(); //gluPickMatrix(x, viewport[3]-y, 4, 4, viewport); gluPickMatrix(x, y, width, height, viewport); - glMultMatrixd(mp); + glMultMatrixd(mp); - glMatrixMode(GL_MODELVIEW); + glMatrixMode(GL_MODELVIEW); glPushMatrix(); - int tetracnt=0; - TetraIterator ti; - for(ti=m.tetra.begin();ti!=m.tetra.end();++ti) - { - if(!(*ti).IsD()) - { - glLoadName(tetracnt); - glBegin(GL_TRIANGLES); - for (int face=0;face<4;face++) - { - //glLoadName(tetracnt); - VertexType *v0=ti->V(Tetra::VofF(face,0)); - VertexType *v1=ti->V(Tetra::VofF(face,1)); - VertexType *v2=ti->V(Tetra::VofF(face,2)); - glVertex(v0->P()); - glVertex(v1->P()); - glVertex(v2->P()); - - } - glEnd(); - tetracnt++; - } - - } + int tetracnt=0; + TetraIterator ti; + for(ti=m.tetra.begin();ti!=m.tetra.end();++ti) + { + if(!(*ti).IsD()) + { + glLoadName(tetracnt); + glBegin(GL_TRIANGLES); + for (int face=0;face<4;face++) + { + //glLoadName(tetracnt); + VertexType *v0=ti->V(Tetra::VofF(face,0)); + VertexType *v1=ti->V(Tetra::VofF(face,1)); + VertexType *v2=ti->V(Tetra::VofF(face,2)); + glVertex(v0->P()); + glVertex(v1->P()); + glVertex(v2->P()); + + } + glEnd(); + tetracnt++; + } + + } glPopMatrix(); glMatrixMode(GL_PROJECTION); - glPopMatrix(); + glPopMatrix(); glMatrixMode(GL_MODELVIEW); hits = glRenderMode(GL_RENDER); - //xstring buf; - //if (hits <= 0) return 0; - std::vector< std::pair > H; - int ii; - for(ii=0;ii(selectBuf[ii*4+1]/4294967295.0,selectBuf[ii*4+3])); - } - std::sort(H.begin(),H.end()); + //xstring buf; + //if (hits <= 0) return 0; + std::vector< std::pair > H; + int ii; + for(ii=0;ii(selectBuf[ii*4+1]/4294967295.0,selectBuf[ii*4+3])); + } + std::sort(H.begin(),H.end()); // if(H.size()>0) TRACE("\n Closest is %i\n",H[0].second); result.resize(H.size()); - for(ii=0;ii > &result, int width=4, int height=4) { - result.clear(); - long hits; + result.clear(); + long hits; int sz=(m.tetra.size()*4)*5; - unsigned int *selectBuf =new unsigned int[sz]; - // static unsigned int selectBuf[16384]; + unsigned int *selectBuf =new unsigned int[sz]; + // static unsigned int selectBuf[16384]; glSelectBuffer(sz, selectBuf); glRenderMode(GL_SELECT); glInitNames(); /* Because LoadName() won't work with no names on the stack */ glPushName(-1); - double mp[16]; - + double mp[16]; + int viewport[4]; glGetIntegerv(GL_VIEWPORT,viewport); - glMatrixMode(GL_PROJECTION); - glGetDoublev(GL_PROJECTION_MATRIX ,mp); - glPushMatrix(); + glMatrixMode(GL_PROJECTION); + glGetDoublev(GL_PROJECTION_MATRIX ,mp); + glPushMatrix(); glLoadIdentity(); //gluPickMatrix(x, viewport[3]-y, 4, 4, viewport); gluPickMatrix(x, y, width, height, viewport); - glMultMatrixd(mp); - glMatrixMode(GL_MODELVIEW); + glMultMatrixd(mp); + glMatrixMode(GL_MODELVIEW); glPushMatrix(); - int tetracnt=0; - TetraIterator ti; - VertexType *v0; - VertexType *v1; - VertexType *v2; - int face; - for(ti=m.tetra.begin();ti!=m.tetra.end();++ti) - { - if(!(*ti).IsD()) - { - for (face=0;face<4;face++){ - v0=ti->V(Tetra::VofF(face,0)); - v1=ti->V(Tetra::VofF(face,1)); - v2=ti->V(Tetra::VofF(face,2)); - glLoadName(tetracnt); - glBegin(GL_TRIANGLES); - glVertex(v0->P()); - glVertex(v1->P()); - glVertex(v2->P()); - glEnd(); - tetracnt++; - } - } - } + int tetracnt=0; + TetraIterator ti; + VertexType *v0; + VertexType *v1; + VertexType *v2; + int face; + for(ti=m.tetra.begin();ti!=m.tetra.end();++ti) + { + if(!(*ti).IsD()) + { + for (face=0;face<4;face++){ + v0=ti->V(Tetra::VofF(face,0)); + v1=ti->V(Tetra::VofF(face,1)); + v2=ti->V(Tetra::VofF(face,2)); + glLoadName(tetracnt); + glBegin(GL_TRIANGLES); + glVertex(v0->P()); + glVertex(v1->P()); + glVertex(v2->P()); + glEnd(); + tetracnt++; + } + } + } glPopMatrix(); glMatrixMode(GL_PROJECTION); - glPopMatrix(); + glPopMatrix(); glMatrixMode(GL_MODELVIEW); hits = glRenderMode(GL_RENDER); - //xstring buf; - //if (hits <= 0) return 0; - std::vector< std::pair > H; - int ii; - for(ii=0;ii(selectBuf[ii*4+1]/4294967295.0,selectBuf[ii*4+3])); - } - std::sort(H.begin(),H.end()); + //xstring buf; + //if (hits <= 0) return 0; + std::vector< std::pair > H; + int ii; + for(ii=0;ii(selectBuf[ii*4+1]/4294967295.0,selectBuf[ii*4+3])); + } + std::sort(H.begin(),H.end()); // if(H.size()>0) TRACE("\n Closest is %i\n",H[0].second); result.resize(H.size()); - for(ii=0;ii(&*ti,index%4); - } - - delete [] selectBuf; + for(ii=0;ii(&*ti,index%4); + } + + delete [] selectBuf; return result.size(); }