#include #include #ifdef __APPLE__ #include #else #include "glut.h" #endif GLfloat vertices[] = {-1.0,-1.0,-1.0,1.0,-1.0,-1.0, 1.0,1.0,-1.0, -1.0,1.0,-1.0, -1.0,-1.0,1.0, 1.0,-1.0,1.0, 1.0,1.0,1.0, -1.0,1.0,1.0}; GLfloat colors[] = {0.0,0.0,0.0,1.0,0.0,0.0, 1.0,1.0,0.0, 0.0,1.0,0.0, 0.0,0.0,1.0, 1.0,0.0,1.0, 1.0,1.0,1.0, 0.0,1.0,1.0}; GLubyte cubeIndices[]={0,3,2,1,2,3,7,6,0,4,7,3,1,2,6,5,4,5,6,7,0,1,5,4}; static GLfloat theta[] = {0.0,0.0,0.0}; static GLint axis = 2; // the camera info float eye[3]; float lookat[3]; void display(void) { /* display callback, clear frame buffer and z buffer, rotate cube and draw, swap buffers */ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //glShadeModel(GL_FLAT); // camera transform glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(eye[0], eye[1], eye[2], lookat[0], lookat[1], lookat[2], 0, 1, 0); glTranslatef(0.0, 3.0, 0.0); glRotatef(theta[0], 1.0, 0.0, 0.0); glRotatef(theta[1], 0.0, 1.0, 0.0); glRotatef(theta[2], 0.0, 0.0, 1.0); glColorPointer(3,GL_FLOAT, 0, colors); glDrawElements(GL_QUADS, 24, GL_UNSIGNED_BYTE, cubeIndices); glutSwapBuffers(); } void myReshape(int w, int h) { glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if (w <= h) glOrtho(-4.0, 4.0, -3.0 * (GLfloat) h / (GLfloat) w, 5.0 * (GLfloat) h / (GLfloat) w, -10.0, 10.0); else glOrtho(-4.0 * (GLfloat) w / (GLfloat) h, 4.0 * (GLfloat) w / (GLfloat) h, -3.0, 5.0, -10.0, 10.0); glMatrixMode(GL_MODELVIEW); } void normalize(float v[3]) { float l = v[0]*v[0] + v[1]*v[1] + v[2]*v[2]; l = 1 / (float)sqrt(l); v[0] *= l; v[1] *= l; v[2] *= l; } void crossproduct(float a[3], float b[3], float res[3]) { res[0] = (a[1] * b[2] - a[2] * b[1]); res[1] = (a[2] * b[0] - a[0] * b[2]); res[2] = (a[0] * b[1] - a[1] * b[0]); } float length(float v[3]) { return (float)sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]); } void myGlutIdle(void) { // just keep redrawing the scene over and over glutPostRedisplay(); } // mouse handling functions for the main window // left mouse translates, middle zooms, right rotates // keep track of which button is down and where the last position was int cur_button = -1; int last_x; int last_y; // catch mouse up/down events void myGlutMouse(int button, int state, int x, int y) { if (state == GLUT_DOWN) cur_button = button; else { if (button == cur_button) cur_button = -1; } last_x = x; last_y = y; } // catch mouse move events void myGlutMotion(int x, int y) { // the change in mouse position int dx = x-last_x; int dy = y-last_y; float scale, len, theta; float neye[3], neye2[3]; float f[3], r[3], u[3]; switch(cur_button) { case GLUT_LEFT_BUTTON: // translate f[0] = lookat[0] - eye[0]; f[1] = lookat[1] - eye[1]; f[2] = lookat[2] - eye[2]; u[0] = 0; u[1] = 1; u[2] = 0; // scale the change by how far away we are scale = sqrt(length(f)) * 0.007; crossproduct(f, u, r); crossproduct(r, f, u); normalize(r); normalize(u); eye[0] += -r[0]*dx*scale + u[0]*dy*scale; eye[1] += -r[1]*dx*scale + u[1]*dy*scale; eye[2] += -r[2]*dx*scale + u[2]*dy*scale; lookat[0] += -r[0]*dx*scale + u[0]*dy*scale; lookat[1] += -r[1]*dx*scale + u[1]*dy*scale; lookat[2] += -r[2]*dx*scale + u[2]*dy*scale; break; case GLUT_MIDDLE_BUTTON: // zoom f[0] = lookat[0] - eye[0]; f[1] = lookat[1] - eye[1]; f[2] = lookat[2] - eye[2]; len = length(f); normalize(f); // scale the change by how far away we are len -= sqrt(len)*dx*0.03; eye[0] = lookat[0] - len*f[0]; eye[1] = lookat[1] - len*f[1]; eye[2] = lookat[2] - len*f[2]; // make sure the eye and lookat points are sufficiently far away // push the lookat point forward if it is too close if (len < 1) { printf("lookat move: %f\n", len); lookat[0] = eye[0] + f[0]; lookat[1] = eye[1] + f[1]; lookat[2] = eye[2] + f[2]; } break; case GLUT_RIGHT_BUTTON: // rotate neye[0] = eye[0] - lookat[0]; neye[1] = eye[1] - lookat[1]; neye[2] = eye[2] - lookat[2]; // first rotate in the x/z plane theta = -dx * 0.007; neye2[0] = (float)cos(theta)*neye[0] + (float)sin(theta)*neye[2]; neye2[1] = neye[1]; neye2[2] =-(float)sin(theta)*neye[0] + (float)cos(theta)*neye[2]; // now rotate vertically theta = -dy * 0.007; f[0] = -neye2[0]; f[1] = -neye2[1]; f[2] = -neye2[2]; u[0] = 0; u[1] = 1; u[2] = 0; crossproduct(f, u, r); crossproduct(r, f, u); len = length(f); normalize(f); normalize(u); neye[0] = len * ((float)cos(theta)*f[0] + (float)sin(theta)*u[0]); neye[1] = len * ((float)cos(theta)*f[1] + (float)sin(theta)*u[1]); neye[2] = len * ((float)cos(theta)*f[2] + (float)sin(theta)*u[2]); eye[0] = lookat[0] - neye[0]; eye[1] = lookat[1] - neye[1]; eye[2] = lookat[2] - neye[2]; break; } last_x = x; last_y = y; glutPostRedisplay(); } void main(int argc, char **argv) { /* need both double buffering and z buffer */ glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(500, 500); glutCreateWindow("colorcube"); glutReshapeFunc(myReshape); glutDisplayFunc(display); glutIdleFunc(myGlutIdle); glutMouseFunc(myGlutMouse); glutMotionFunc(myGlutMotion); glEnable(GL_DEPTH_TEST); /* Enable hidden--surface--removal */ glEnableClientState(GL_COLOR_ARRAY); glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3, GL_FLOAT, 0, vertices); glColorPointer(3,GL_FLOAT, 0, colors); glClearColor(1.0,1.0,1.0,1.0); glColor3f(1.0,1.0,1.0); // initialize the camera eye[0] = 1; eye[1] = 1; eye[2] = 1; lookat[0] = 0; lookat[1] = 0; lookat[2] = 0; glutMainLoop(); }