#include "exp004mouse.h" #include "exp004processhits.h" #include "../view/exp004geometry.h" #include "../view/exp004state0.h" #include "../util/check_error.h" #include "../util/pick_convert.h" #include #include /* * A simple alias to make the code more readable. */ #define S exp004state0 void exp004mouse (int button, int state, int x, int y) { if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) { /* * Complete a selection if one was started and not cancelled. */ if (S.selecting == true) { /* * "Specify the array to be used for the returned hit records * with glSelectBuffer () [Redbook]." */ GLuint select_buf[ROWS]; glSelectBuffer (ROWS, select_buf); /* * "Enter selection mode by specifying GL_SELECT with * glRenderMode () [Redbook]." */ glRenderMode (GL_SELECT); /* * "Initialize the name stack using glInitNames () and glPush * Names () [Redbook]." */ glInitNames (); glPushName (0); /* * "Define the viewing volume you want to use for selection. * Usually this is different from the viewing volume you * originally used to draw the scene, so you probably want to * save and then restore the current transformation state with * glPushMatrix () and glPopMatrix () [Redbook]." */ glMatrixMode (GL_PROJECTION); glPushMatrix (); glLoadIdentity (); GLint viewport[4]; glGetIntegerv (GL_VIEWPORT, viewport); /* gluPickMatrix ((GLdouble) x, (GLdouble) (viewport[3] - y), N, N, viewport); */ double c_x = 0.0; double c_y = 0.0; double w = 0.0; double h = 0.0; pick_convert (S.select_x, S.select_y, x, y, &c_x, &c_y, &w, &h); gluPickMatrix (c_x, (GLdouble)viewport[3] - c_y, w, h, viewport); gluOrtho2D(S.ortho.min_x, S.ortho.max_x, S.ortho.min_y, S.ortho.max_y); /* * "Alternately issue primitive drawing commands and commands to * manipulate the name stack so that each primitive of interest * has appropriate names assigned [Redbook]." */ exp004geometry (GL_SELECT); glMatrixMode (GL_PROJECTION); glPopMatrix (); glutSwapBuffers (); /* * "Exit selection mode and process the returned selection data * (the hit records) [Redbook]." */ GLint hits = glRenderMode (GL_RENDER); check_error (__FILE__, __LINE__); /* "process hits from selection mode rendering [Angel,2008]." */ exp004processhits (hits, select_buf); /* "normal render [Angel,2008]." */ glutPostRedisplay (); } } if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) { S.selecting = true; S.select_x = x; S.select_y = y; } return; }