Re: [Plib-users] Selecting ssEntity with mouse
Brought to you by:
sjbaker
From: Johannes S. <joh...@gm...> - 2010-07-26 14:52:03
|
Hello Paolo, Thanks a lot for the code. I get it to build and it picks objects from the screen but not the correct ones and not allways so some part of the code is wrong. I implemented your get_eye_matrices as follows: void get_eye_matrices( int eye, sgMat4 proj_mat, sgMat4 mview_mat ) { GLdouble modelview[16]; glGetDoublev(GL_MODELVIEW_MATRIX, modelview); for (int i = 0; i < 4; i++) { for(int j = 0; j < 4; j++) { mview_mat[i][j] = modelview[i*4+j]; } } } but I am not sure it is correct. /Johannes On Fri, Jul 23, 2010 at 11:06 AM, Paolo Leoncini <p.l...@ci...> wrote: > *Johannes,* > ** > *here is what I do:* > > > float z2, x3, y3, z3; > > if ( Project2d3d ( x, y, z2, x3, y3, z3 ) ) { > > sgVec3 pick_pnt = {x3, y3, z3}; > > ulSetError( UL_DEBUG, "picking point (%f,%f,%f)", x3, y3, z3 ); > > sgMat4 mview_mat; > > extern void get_eye_matrices( int eye, sgMat4 proj_mat, sgMat4 > mview_mat ); > > get_eye_matrices( 0, NULL, mview_mat ); // my way of doing > glGetDoublev(GL_MODELVIEW_MATRIX, mview_mat) > > ssgEntityBinding *ebind = getPickedLeaf( z2, pick_pnt, mview_mat, > scene ); > > } > > > > *x, y are mouse coord, e.g. those arguments of the mouse button press GLUT > callback.* > > *Project2d3d maps 2D's x,y to 3D's x3,y3,z3, and is listed below (borrowed > from a past post):* > > > > // Project2d3d is the function which will transform 2d into 3d coordinates: > > int > Project2d3d ( int x2, int y2, float& z2, float& x3, float& y3, float& z3 ) > > { > > GLint viewport[4] ; > > GLdouble modvmatrix[16], projmatrix[16] ; > > glGetIntegerv ( GL_VIEWPORT, viewport ) ; > > /* OpenGL y starts at lower left, X/Windows y starts at top left */ > > GLdouble y2gl = viewport[3] - y2 ; > > /* Use GL power to find the depth of the projection */ > > glReadPixels ( x2, y2gl, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &z2 ) ; > > if ( z2 >= 1 ) return 0; > > /* Some more GL magic. Get the projection and modelview matrices */ > > glGetDoublev ( GL_MODELVIEW_MATRIX, modvmatrix ) ; > > glGetDoublev ( GL_PROJECTION_MATRIX, projmatrix ) ; > > GLdouble dx, dy, dz ; > > /* convert screen coords to object coords. */ > > int retcode = gluUnProject ( x2, y2gl, z2, modvmatrix, projmatrix, > viewport, &dx, &dy, &dz ) ; > > x3 = dx ; > > y3 = dy ; > > z3 = dz ; > > return retcode; > > } > > > > *getPickedLeaf actually intersects a screen-inward ray with the scene > graph content, and return the outmost leaf along the SSG coord system's > z-axis.* > > > > ssgEntityBinding *getPickedLeaf( float zmin, sgVec3 center, sgMat4 > inv_cam_mat, ssgBranch *scene ) > > { > > sgVec3 test_vec, cam_center, up = {0,0,1}; > > sgMat4 cam_mat, _OpenGL2ssg; > > extern sgMat4 _ssgOpenGLAxisSwapMatrix; // defined in ssg.cxx > > // back to SSG coordinate system > > sgTransposeNegateMat4( _OpenGL2ssg, _ssgOpenGLAxisSwapMatrix ); > > sgPostMultMat4( inv_cam_mat, _OpenGL2ssg ); > > sgTransposeNegateMat4( cam_mat, inv_cam_mat ); > > // rotate the world so to put the 'center' point at the center of the > scene > > sgCopyVec3( cam_center, cam_mat[3] ); > > sgMakeLookAtMat4( cam_mat, cam_center, center, up ); > > sgTransposeNegateMat4( inv_cam_mat, cam_mat ); > > sgSetVec3( test_vec, 0, 1, 0 ); > > static ssgLeaf *leaf; // its pointer goes outside > > ssgHit *results, *hit; > > int num_hits = ssgLOS ( scene, test_vec, inv_cam_mat, &results ) ; > > if ( num_hits > 0 ) { > > ulSetError( UL_DEBUG, "hits %d", num_hits ); > > float min_dst; bool done = false; leaf = NULL; > > for ( int i = 0 ; i < num_hits ; i++ ) { > > ssgHit *h = &results [ i ] ; > > float dst = - h->plane[3] / h->plane[1]; > > ulSetError( UL_DEBUG, "\tdst %f, zmin %f, min_dst %f", dst, > zmin, min_dst ); > > if ( dst > 0 && (!done || dst < min_dst) ) { > > done = true; > > min_dst = dst; > > leaf = h->leaf; > > hit = h; > > ulSetError( UL_DEBUG, "\t\thit %d, leaf '%s', min_dst %f", > hit, leaf->getName(), min_dst ); > > } > > } > > // normally at this point one could return the ssgLeaf * 'leaf', > yet I need the path-to-node string so I fill & return a ssgEntityBinding > > if ( leaf != NULL ) { > > static ssgEntityBinding ebind; > > static char path_string[1023], *name; > > strcpy( path_string, "" ); > > hit->addPath( leaf ); // doesn't include the hit leaf itself, > but we need it > > for ( int i = 0; i < hit->getNumPathEntries(); i++ ) { > > strcat( path_string, "/" ); > > strcat( path_string, > (name=hit->getPathEntry(i)->getName()) ? name : "" ); > > } > > ebind.entity = (ssgEntity**)&leaf; > > ebind.nameOrPath = ulStrDup( path_string ); > > return &ebind; > > } > > } > > return NULL; > > } > > > > *I hope the code would get compiled with little effort and finally will > work.* > > *Greetings,* > > *Paolo Leoncini* > > > ------------------------------ > *Da:* Johannes Strömberg [mailto:joh...@gm...] > *Inviato:* venerdì 23 luglio 2010 10.34 > *A:* pli...@li... > *Oggetto:* [Plib-users] Selecting ssEntity with mouse > > Hello, > > I need a way of selecting an object on screen using the mouse. > > How do I convert mouse input to something that I can use with my scene and > how do I find what is under the mouse? > > /Johannes > > |