Dimitris,=20
> -----Messaggio originale-----
> Da: pli...@li...=20
> [mailto:pli...@li...] Per conto=20
> di Dimitris Mexis
> Inviato: luned=EC 23 luglio 2007 23.42
> A: pli...@li...
> Oggetto: [Plib-users] Help for code that is not documented=20
> and is confusing
>
> [...]
>
> OR has anyone achieved to point and click an object ?
This code works for picking an SSG node in a GLUT-based app (Project2d3d =
and
getPickedLeaf functions reported below):
glutMouseFunc( mouseclick );
...
void mouseclick( int button, int state, int x, int y )
{
if ( button =3D=3D GLUT_LEFT_BUTTON && !state ) { // pick only when =
the
left button is pressed
float x3, y3, z3;
if ( Project2d3d ( x, y, x3, y3, z3 ) ) {
sgVec3 pick_pnt =3D {x3, y3, z3}; // pack them into a
sgVec3 for use in getPickedLeaf
ulSetError( UL_DEBUG, "picking point (%f,%f,%f)",
x3, y3, z3 );
ssgEntityBinding *ebind =3D getPickedLeaf( pick_pnt,
scene );
if ( ebind ) { // really picked a node
// picked_entity is what the name says,
ssgEntity *picked_entity =3D *(ebind->entity);
// ebind->entity is a ssgEntity**, so setting it as ssgEntity* is handy =
and
more SSG-ish
// *(ebind->nameOrPath) is its path along
the scene graph, useful as far as it could not be unique!
// make use of them ...
}
}
}
}
ssgEntityBinding *getPickedEntity( sgVec3 center, ssgBranch *scene )
//
// this function gets
// - a 3D 'picked' point in the scene (typically returned by the =
Project2d3d
function),
// - a scene graph root pointer,
// and returns a pointer to ssgEntityBinding, which actually holds a
(entity,path) pair for the picked node.
// 'path' is useful when one wants the path to walk from the root to =
reach
that node, and it is not unique
// (remember, it's a scene *graph*, not necessarily a tree, so a node =
could
have in general more than one parent)
//
{
sgVec3 test_vec, cam_center, up =3D {0,0,1};
sgMat4 inv_cam_mat, cam_mat, _OpenGL2ssg;
extern sgMat4 _ssgOpenGLAxisSwapMatrix; // defined in ssg.cxx
// back to SSG coordinate system
sgTransposeNegateMat4( _OpenGL2ssg, _ssgOpenGLAxisSwapMatrix );
ssgGetModelviewMatrix ( inv_cam_mat );
sgPostMultMat4( inv_cam_mat, _OpenGL2ssg );
// cam_mat is finally the current SSG camera
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 );
// inv_cam_mat is reused here with a different meaning - it is now
the inverse of cam_mat
sgTransposeNegateMat4( inv_cam_mat, cam_mat );
sgSetVec3( test_vec, 0, 1, 0 );
static ssgLeaf *leaf; // its pointer must live outside the function
call
ssgHit *results, *hit;
int num_hits =3D ssgLOS ( scene, test_vec, inv_cam_mat, &results ) ;
if ( num_hits > 0 ) {
float min_dst =3D -1000000.0f ;
for ( int i =3D 0 ; i < num_hits ; i++ ) {
ssgHit *h =3D &results [ i ] ;
float dst =3D - h->plane[3] / h->plane[1];
if ( dst > 0 && dst < fabs(min_dst) ) {
min_dst =3D dst;
leaf =3D h->leaf;
hit =3D h;
}
}
if ( min_dst > 0 ) {
static ssgEntityBinding ebind;
static char path_string[1023], *name;
strcpy( path_string, "" );
// ssgHit give us the node path for free, let's
export it in string form
for ( int i =3D 0; i < hit->getNumPathEntries(); i++ )
{
strcat( path_string, "/" );
strcat( path_string,
(name=3Dhit->getPathEntry(i)->getName()) ? name : "" );
}
ebind.entity =3D (ssgEntity**)&leaf;
ebind.nameOrPath =3D path_string;
return &ebind;
}
}
return NULL;
}
// Project2d3d is the function which will transform 2d into 3d =
coordinates:
int Project2d3d ( int x2, int y2, 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 =3D viewport[3] - y2 ;
/* Update the Modelview and Projectionmatrix */
glMatrixMode ( GL_MODELVIEW ) ; ssgLoadModelviewMatrix () ;
glMatrixMode ( GL_PROJECTION ) ; ssgLoadProjectionMatrix () ;
/* Use GL power to find the depth of the projection */
GLfloat z2 ;
glReadPixels ( x2, y2gl, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &z2 ) ;
if ( z2 >=3D 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 =3D gluUnProject ( x2, y2gl, z2, modvmatrix, projmatrix,
viewport, &dx, &dy, &dz ) ;
x3 =3D dx ;
y3 =3D dy ;
z3 =3D dz ;
return retcode;
}
> Crying for help...
> Dimitris
>=20
> Thank you
Don't cry. Just ask.
Greetings,
Paolo Leoncini
|