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