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
> >
> >
>
|