Re: [Plib-users] Selecting ssEntity with mouse
Brought to you by:
sjbaker
From: <p.l...@ci...> - 2010-07-26 15:30:09
|
Scrive Johannes Strömberg <joh...@gm...>: > 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. as far as I know sgMat4 and OpenGL matrices are laid out in memory the same way assuming you put translations in sgMat4[3][*], and the forst three rows are the rotation part. So you could try this: sgMat4 mview_mat; glGetFloatv(GL_MODELVIEW_MATRIX, (float *)mview_mat); as far as it compiles, it shoud work. Another way to get it is to call: sgMat4 mview_mat; ssgGetCurrentContext()->getModelviewMatrix( mview_mat ); assuming you have ever set the camera till there (i.e. through a call to ssgGetCurrentContext()->setCamera()). Perhaps your solution is correct too, but I'm lazy to think to row- or colum-major order every time, sorry. Paolo > /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 > > > > > |