[Plib-users] R: Selecting ssEntity with mouse
Brought to you by:
sjbaker
From: Paolo L. <p.l...@ci...> - 2010-07-28 09:01:23
|
Johannes, sorry for the delay, I answered you at once days ago but my webmail system clearly failed, and I didn't save a copy of that message. Well, basically I wrote you: 1. in place of get_eye_matrices, do simply: sgMat4 mview_mat; glGetFloatv(GL_MODELVIEW_MATRIX, (float *)mview_mat); perhaps is just the same as you did. 2. the meaning of mview_mat is the "camera matrix". If you have already set the SSG camera (by one of the many forms of the setCamera ssgContext's methods) before going picking in your program, you can even simply query the resulting modelview matrix: ssgGetCurrentContext()->getModelviewMatrix( mview_mat ); Hope you will soon be successful with SSG picking. Greetings, Paolo _____ Da: Johannes Strömberg [mailto:joh...@gm...] Inviato: lunedì 26 luglio 2010 16.52 A: Paolo Leoncini Cc: PLIB Users Oggetto: Re: [Plib-users] Selecting ssEntity with mouse 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 |