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