/* unproject.c selecting (picking) a 3D object */ /* press left mouse button to select object */ #include #include #include #include #include /* fixed display list for this example */ typedef float vec[3]; typedef struct {vec coord; vec color;} points; static int width = 500; static int height = 500; static int selected = -1; static points display_list[4] = { { 0.4, 0.4, -1.0, 1.0, 0.0, 0.0}, { -0.4, -0.4, -1.0, 0.0, 0.0, 1.0}, { 40.0, -40.0, -100.0, 1.0, 1.0, 0.0}, {-40.0, 40.0, -100.0, 0.0, 1.0, 0.0}}; static void printstring(float x, float y, char *string); static void display(void); static void reshape(int w, int h); static GLdouble dist(GLdouble a1x, GLdouble a1y, GLdouble a1z, GLdouble a2x, GLdouble a2y, GLdouble a2z, GLdouble a3x, GLdouble a3y, GLdouble a3z); static void mouse(int button, int state, int x, int y) ; static void printstring(float x, float y, char *string) { int len, i; glPushMatrix(); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0.0, (GLfloat)width, 0.0, (GLfloat)height); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glRasterPos2f(x, y); len = (int) strlen(string); for (i = 0; i < len; i++) glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, string[i]); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective (45.0, (GLfloat) width/(GLfloat) height, 1.0, 100.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glPopMatrix(); } /* end printstring */ static void display(void) { char redstr[50]; int i; glClear(GL_COLOR_BUFFER_BIT); glPointSize(10.0); glBegin(GL_POINTS); for(i=0; i<4; i++) /* loop through display list */ { if(i==selected) glColor3f(1.0, 1.0, 1.0); else glColor3f(display_list[i].color[0], display_list[i].color[1], display_list[i].color[2]); glVertex3f(display_list[i].coord[0], display_list[i].coord[1], display_list[i].coord[2]); } glEnd(); glColor3f(1.0, 1.0, 1.0); /* label points */ sprintf(redstr, "(%f,%f,%f)\n", display_list[0].coord[0], display_list[0].coord[1], display_list[0].coord[2]); printstring(300.0, 480.0, redstr); sprintf(redstr, "(%f,%f,%f)\n", display_list[1].coord[0], display_list[1].coord[1], display_list[1].coord[2]); printstring( 20.0, 10.0, redstr); sprintf(redstr, "(%f,%f,%f)\n", display_list[2].coord[0], display_list[2].coord[1], display_list[2].coord[2]); printstring(260.0, 10.0, redstr); sprintf(redstr, "(%f,%f,%f)\n", display_list[3].coord[0], display_list[3].coord[1], display_list[3].coord[2]); printstring( 20.0, 480.0, redstr); glFlush(); } static void reshape(int w, int h) { glViewport (0, 0, w, h); width = w; height = h; glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective (45.0, (GLfloat) w/(GLfloat) h, 1.0, 100.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } static GLdouble dist(GLdouble a1x, GLdouble a1y, GLdouble a1z, GLdouble a2x, GLdouble a2y, GLdouble a2z, GLdouble a3x, GLdouble a3y, GLdouble a3z) { GLdouble d, ax, ay, az, bx, by, bz, cx, cy, cz; ax = a2x-a1x; ay = a2y-a1y; az = a2z-a1z; bx = a1x-a3x; by = a1y-a3y; bz = a1z-a3z; cx = ay*bz-az*by; cy = ax*bz-az*bx; cz = ax*by-ay*bx; d = sqrt(cx*cx+cy*cy+cz*cz)/sqrt(ax*ax+ay*ay+az*az); return d; } static void mouse(int button, int state, int x, int y) { int i; GLint viewport[4]; GLdouble mvmatrix[16], projmatrix[16]; GLint realy; /* OpenGL y coordinate position */ GLdouble wx0, wy0, wz0; /* returned world x, y, z coords */ GLdouble wx1, wy1, wz1; /* returned world x, y, z coords */ GLdouble close, d; if(button==GLUT_LEFT_BUTTON && state == GLUT_DOWN) { glGetIntegerv (GL_VIEWPORT, viewport); glGetDoublev (GL_MODELVIEW_MATRIX, mvmatrix); glGetDoublev (GL_PROJECTION_MATRIX, projmatrix); /* note viewport[3] is height of window in pixels */ realy = viewport[3] - (GLint) y - 1; printf ("Coordinates at cursor are (%4d, %4d)\n", x, realy); gluUnProject((GLdouble) x, (GLdouble) realy, 0.0, mvmatrix, projmatrix, viewport, &wx0, &wy0, &wz0); printf ("World coords at z=0.0 are (%f, %f, %f)\n", wx0, wy0, wz0); gluUnProject((GLdouble) x, (GLdouble) realy, 1.0, mvmatrix, projmatrix, viewport, &wx1, &wy1, &wz1); printf ("World coords at z=1.0 are (%f, %f, %f)\n", wx1, wy1, wz1); selected = -1; close = 10000.0; for(i=0; i<4; i++) { d = dist(wx0, wy0, wz0, wx1, wy1, wz1, (double)display_list[i].coord[0], (double)display_list[i].coord[1], (double)display_list[i].coord[2]); printf("distance, d to point %d is %g\n", i, d); if(d0.5) selected = -1; /* not close enough */ glutPostRedisplay(); } } int main(int argc, char* argv[]) { glutInit(&argc, argv); glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); glutInitWindowSize (width, height); glutInitWindowPosition (100, 100); glutCreateWindow (argv[0]); glutDisplayFunc(display); glutReshapeFunc(reshape); glutMouseFunc(mouse); glutMainLoop(); return 0; }