PDA

View Full Version : Picking in 3D - plz help



beautiful world
05-29-2002, 11:18 AM
Hi ..
I am trying to draw a cube and then change its color when clicked on it....
(I got the code from picksquares.c and cube.c examples of the red book)

Selection and picking seem to be working fine as the hit is being recognized. The cube also gets drawn properly in render mode but not in select mode....The window becomes blank in select mode,(i.e when I click on it).
I dont understand what I am missing in the select mode.....

Here is my code :

#include <stdlib.h>
#include <stdio.h>
#include <glut.h>

void init(void)
{
glClearColor (0.0, 0.0, 0.0, 0.0);
glShadeModel (GL_FLAT);
}


void drawSquares(GLenum mode)
{
static GLuint i=1;

if (mode == GL_SELECT)
glPushName (i);
glColor3f ((GLfloat) i/2.0, (GLfloat) i/
20.0, (GLfloat) i/100.0);
glutWireCube(1.0);

i++;

}


void proces****s (GLint hits, GLuint buffer[])
{
unsigned int i;
GLuint names, *ptr;
FILE *fp;

fp = fopen ("/Users/..../.../outfile","a");
fprintf (fp,"hits = %d\n", hits);
ptr = (GLuint *) buffer;
for (i = 0; i < hits; i++) { /* for each hit */
names = *ptr;
ptr++;
ptr++;
ptr++;
}

fclose(fp);
}


#define BUFSIZE 512

void pickSquares(int button, int state, int x, int y)
{
GLuint selectBuf[BUFSIZE];
GLint hits;
GLint viewport[4];

if (button != GLUT_LEFT_BUTTON &#0124; &#0124; state != GLUT_DOWN)
return;

glGetIntegerv (GL_VIEWPORT, viewport);

glSelectBuffer (BUFSIZE, selectBuf);
glRenderMode (GL_SELECT);

glInitNames();
glPushName(0);

glMatrixMode (GL_PROJECTION);
glPushMatrix ();
glLoadIdentity ();
/* create 5x5 pixel picking region near cursor location */
gluPickMatrix ((GLdouble) x, (GLdouble) (viewport[3] - y),
5.0, 5.0, viewport);
glFrustum( -1.0, 1.0, -1.0, 1.0, 1.5, 15.0 );
// gluOrtho2D (0.0, 3.0, 0.0, 3.0);
drawSquares (GL_SELECT);

glMatrixMode (GL_PROJECTION);
glPopMatrix ();
glFlush ();

hits = glRenderMode (GL_RENDER);
proces****s (hits, selectBuf);
glutPostRedisplay();

}

void display(void)
{

glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity ();

drawSquares (GL_RENDER);
glFlush();
}

void reshape(int w, int h)
{
glViewport(0, 0, (GLsizei)w, (GLsizei) h); // 4th step
glMatrixMode(GL_PROJECTION); //Now deal with projection matrix
glLoadIdentity(); // Set the projection matrix to identity and multiply this identity
glFrustum( -1.0, 1.0, -1.0, 1.0, 1.5, 20.0 );
// gluOrtho2D (0.0, 3.0, 0.0, 3.0); // matrix with the orthomatrix
glMatrixMode(GL_MODELVIEW); // prepare for projecting our actual object... - we now deal with Modelview Matrix
glLoadIdentity(); // All set for putting an object in..
}


/* Main Loop */
int main(int argc, char** argv)
{

glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize (400, 400);
glutInitWindowPosition (100, 100);
glutCreateWindow (argv[0]);
init ();
glutReshapeFunc (reshape);
glutDisplayFunc(display);
glutMouseFunc (pickSquares);
glutMainLoop();
return 0;
}

Thanx in advance....

mikael_aronsson
05-29-2002, 01:04 PM
Hi !

You setup the correct matrices in reshape(), the problem is that whhen you do the picking you change this with gluPickMatrix(), so when you then call glutPostRedisplay() you are using the incorrect matrices, you need to restore theese the same way as you do in reshape() after the piccking is done.

Mikael

beautiful world
05-30-2002, 10:39 AM
Hi...
Its not very clear to me as to what I am supposed to do to restore the matrices ?? I modified my code a lil bit with your suggestions, and now, the cube doesn't disappear, but it becomes smaller when I click on it.. and then remains constant on further clicks.....the color changes on every click though.. I think the size is changing becoz of the glLookAt() , but I dont understand why.....

I have one more question - Is the Projection matrix modified becoz of the gluPickMatrix ??

this is my new code :
I am pasting only the drawSquares and pickSquares functions here as I made changes only in these two methods....

void drawSquares(GLenum mode)
{
static GLuint i=1;

glMatrixMode (GL_MODELVIEW);
gluLookAt (0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

if (mode == GL_SELECT)
glPushName (i);

glColor3f ((GLfloat) i/2.0, (GLfloat) i/20.0, (GLfloat) i/100.0);
glutWireCube(1.0);

i++;

}


#define BUFSIZE 512

void pickSquares(int button, int state, int x, int y)
{
GLuint selectBuf[BUFSIZE];
GLint hits;
GLint viewport[4];

if (button != GLUT_LEFT_BUTTON &#0124; &#0124; state != GLUT_DOWN)
return;

glGetIntegerv (GL_VIEWPORT, viewport);

glSelectBuffer (BUFSIZE, selectBuf);
glRenderMode (GL_SELECT);

glInitNames();
glPushName(0);

glMatrixMode (GL_PROJECTION);
glPushMatrix ();
glLoadIdentity ();

gluPickMatrix ((GLdouble) x, (GLdouble) (viewport[3] - y),
5.0, 5.0, viewport);

glFrustum( -1.0, 1.0, -1.0, 1.0, 1.5, 20.0 );
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

glClear(GL_COLOR_BUFFER_BIT);

drawSquares (GL_SELECT);

glMatrixMode (GL_PROJECTION);
glPopMatrix ();
glFlush ();

hits = glRenderMode (GL_RENDER);
proces****s (hits, selectBuf);
glutPostRedisplay();

}

Thanx....