// GLUT mouse motion handling #include "motion.h" #include "view.h" // Apple's annoying non-standard GL include location #if defined(__APPLE__) || defined(MACOSX) #include #else #include #endif #include #include #include using std::list; // data on button press or drag static struct PressData { enum Event {PRESS,DRAG} event; // was this a press or drag? int button; // which mouse button was pressed? int x, y; // where was our last position? PressData(Event _event, int _button, int _x, int _y) : event(_event), button(_button), x(_x), y(_y) {} } lastPress(PressData::PRESS,0,0,0); // mouse drag delayed by latency // use difference between last x,y and x,y to define a rotation void drag(const PressData &pd) { float dx = pd.x - lastPress.x; //record differences from last position float dy = pd.y - lastPress.y; lastPress.x = pd.x; // update stored position lastPress.y = pd.y; if (lastPress.button == GLUT_LEFT_BUTTON) { // rotate // save current view state float matrix[16]; glGetFloatv(GL_MODELVIEW_MATRIX, matrix); // From the starting state, rotate around axis perpendicular to // mouse motion, where the window x axis is aligned with the 3D // view x axis, while the window y axis is aligned with the 3D // view z axis. Find perpendicular using rule that (y,-x) is // perpendicular to (x,y). Rotation angle is scaled so 1/2 // window width = about 90 degrees glLoadIdentity(); glRotatef(180 * sqrt(dx*dx + dy*dy) / winWidth, dy,dx,0); glMultMatrixf(matrix); } else if (lastPress.button == GLUT_MIDDLE_BUTTON) { // zoom viewDistance -= dy; reshape(winWidth, winHeight); } else if (lastPress.button == GLUT_RIGHT_BUTTON) { // save current view state float matrix[16]; glGetFloatv(GL_MODELVIEW_MATRIX, matrix); // apply translation to head of list glLoadIdentity(); glTranslatef(dx,-dy,0); glMultMatrixf(matrix); } // tell GLUT that something has changed and we must redraw glutPostRedisplay(); } // called when a mouse button is pressed -- schedule delayed callback extern "C" void mousePress(int b, int state, int x, int y) { lastPress = PressData(PressData::PRESS,b,x,y); } // called when the mouse moves -- schedule delayed callback extern "C" void mouseDrag(int x, int y) { drag(PressData(PressData::DRAG,0,x,y)); }