#include #include #include #include #include // Screen Size int width = 400; int height = 400; // Frame Timer Data int frames = 0; int ttime = glutGet(GLUT_ELAPSED_TIME); int tdiff = 0; // Box Motion Data int size = 50; float conv = 3.14159 / 180.0; float rotate = 0; float ang = 60.0; float vel = 150.0; float px = width / 2.0; float py = height / 2.0; // Color Data int color = 0; int numcolor = 12; float cx = width / (float)numcolor; float cy = height / (float)numcolor; // Cube data structures GLfloat boxpts [][3] = {{-1, -1, -1}, {-1, -1, 1}, {-1, 1, 1}, {-1, 1, -1}, {1, 1, -1}, {1, -1, -1}, {1, -1, 1}, {1, 1, 1}}; int boxfaces [][4] = {{0, 1, 2, 3}, {7, 6, 5, 4}, {4, 3, 2, 7}, {2, 1, 6, 7}, {3, 4, 5, 0}, {1, 0, 5, 6}}; GLfloat boxnrms [][3] = {{-1, 0, 0}, {1, 0, 0}, {0, 1, 0}, {0, 0, 1}, {0, 0, -1}, {0, -1, 0}}; // Rainbow GLfloat rainbowcol [][3] = {{1, 0, 1}, {0.5, 0, 1}, {0, 0, 1}, {0, 0.5, 1}, {0, 1, 1}, {0, 1, 0.5}, {0, 1, 0}, {0.5, 1, 0}, {1, 1, 0}, {1, 0.5, 0}, {1, 0, 0}, {1, 0, 0.5}}; // Lighting parameters GLfloat ambient[] = {0.1, 0.1, 0.1, 1.0}; GLfloat diffuse[] = {0.9, 0.9, 0.9, 1.0}; GLfloat specular[] = {1.0, 1.0, 1.0, 1.0}; GLfloat position[] = {200.0, 200.0, 400.0, 1.0}; GLfloat lmodel_ambient[] = {0.2, 0.2, 0.2, 1.0}; GLfloat local_view[] = {0.0}; GLfloat *rainbow4fv (int color, GLfloat alpha) { static GLfloat col[4]; col[0] = rainbowcol[color][0]; col[1] = rainbowcol[color][1]; col[2] = rainbowcol[color][2]; col[3] = alpha; return col; } GLfloat *rainbow3fv (int color) { static GLfloat col[3]; col[0] = rainbowcol[color][0]; col[1] = rainbowcol[color][1]; col[2] = rainbowcol[color][2]; return col; } void timer_update () { tdiff = glutGet(GLUT_ELAPSED_TIME) - ttime; ttime = glutGet(GLUT_ELAPSED_TIME); } int timer_diff () { return tdiff; } void drawcube (int x, int y, int z, int size) { int w = size / 2.0; // Position cube glTranslatef(px, py, 0); glRotatef(rotate, 1, 0, 0); glRotatef(rotate, 0, 1, 0); glRotatef(rotate, 0, 0, 1); glScaled(w, w, w); rotate = fmodf(rotate + (30.0 * (timer_diff() / 1000.0)), 360); // Setup material for cube glMaterialfv(GL_FRONT, GL_AMBIENT, rainbow4fv(color, 1.0)); glMaterialfv(GL_FRONT, GL_DIFFUSE, rainbow4fv(color, 1.0)); // Draw Cube glBegin(GL_QUADS); glColor3fv(rainbow3fv(color)); for (int i = 0; i < 6; i++) { glNormal3fv(boxnrms[i]); for (int j = 0; j < 4; j ++) glVertex3fv(boxpts[boxfaces[i][j]]); } glEnd(); } void draw () { float tdiff; // Clear buffers glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Reset model viewport glMatrixMode(GL_MODELVIEW); glLoadIdentity(); // Draw the square drawcube(px, py, 0, size); // Update the timer timer_update(); tdiff = timer_diff() / 1000.0; // Move the square px += sin(conv * ang) * vel * tdiff; py += cos(conv * ang) * vel * tdiff; // Wrap bounce off walls if (px > width && (ang > 0 && ang < 180)) ang = 360 - ang; if (px < 0 && (ang > 180 && ang < 360)) ang = 360 - ang; if (py > height && (ang < 90 || ang > 270)) ang = fmodf(540 - ang, 360); if (py < 0 && (ang > 90 && ang < 270)) ang = fmodf(540 - ang, 360); // Draw color hot spots glLoadIdentity(); glTranslatef(0, 0, 100); for (int i = 0; i < numcolor; i++) { glBegin(GL_QUADS); glColor4fv(rainbow4fv(i, 0.8)); glMaterialfv(GL_FRONT, GL_AMBIENT, rainbow4fv(i, 0.8)); glMaterialfv(GL_FRONT, GL_DIFFUSE, rainbow4fv(i, 0.8)); glVertex3f(cx * i, height - cy, 0); glVertex3f(cx * (i + 1), height - cy, 0); glVertex3f(cx * (i + 1), height, 0); glVertex3f(cx * i, height, 0); glEnd(); } // Put buffer on screen glutSwapBuffers(); // Record each frame frames++; } void keys (unsigned char key, int x, int y) { GLboolean btmp; switch (key) { case 'q': case 27: exit(0); break; // Toggle blending case 'b': glGetBooleanv(GL_BLEND, &btmp); if (btmp) glDisable(GL_BLEND); else glEnable(GL_BLEND); break; // Display the frame rate case 'f': printf("fps: %lf\n", frames / (float)glutGet(GLUT_ELAPSED_TIME) * 1000.0); break; // Stop the box case 's': vel = 0; break; // Slow down box case '-': case '_': vel -= 5; break; // Speed up box case '+': case '=': vel += 5; break; // Toggle Lighting case 'l': glGetBooleanv(GL_LIGHTING, &btmp); if (btmp) glDisable(GL_LIGHTING); else glEnable(GL_LIGHTING); break; }; } void mouse (int btn, int state, int x, int y) { y = height - y; if (btn == GLUT_LEFT_BUTTON) { if (state == GLUT_DOWN) { if (y > height - cy) { color = (int)(x / (float)cx); } } } else if (btn == GLUT_RIGHT_BUTTON) { if (state == GLUT_DOWN) { color = ++color % numcolor; } } else { // Middle button } } int main (int argc, char **argv) { // Setup OpenGL glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH); glutInitWindowSize(width, height); glutCreateWindow("Tutorial 2"); // Setup callbacks glutDisplayFunc(draw); glutIdleFunc(draw); glutKeyboardFunc(keys); glutMouseFunc(mouse); // Setup viewport glMatrixMode(GL_PROJECTION); glOrtho(0, width, 0, height, -1000, 1000); // Enable depth testing glEnable(GL_DEPTH_TEST); // Enable blending glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); // Enable lighting glEnable(GL_NORMALIZE); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glLightfv(GL_LIGHT0, GL_AMBIENT, ambient); glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse); glLightfv(GL_LIGHT0, GL_SPECULAR, specular); glLightfv(GL_LIGHT0, GL_POSITION, position); glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient); glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, local_view); // Enable Backface culling glCullFace(GL_BACK); glEnable(GL_CULL_FACE); // Change background color glClearColor(1, 1, 1, 1); // Give control to OpenGL glutMainLoop(); return 0; }