opengl_demo.cpp
/* opengl_demo.cpp
Ryan Pickelsimer
3/16/15
Computer Graphics
This program demonstrates several features of OpenGL including shapes, coloring, motion, lighting, text, and fog.
*/
#include <iostream>
#include <stdlib.h> // needed for "exit" function
#include <Windows.h>
#include <GL\glew.h>
#include <GL\freeglut.h>
#include "Stages.h"
using namespace std;
// Rotation angle for polygons
float rot_angle = 30.0f;
// used in drawScene()
Stages stage;
int draw_test = 0;
/**************************************************************************************/
/* Camera Controls */
/**************************************************************************************/
// for moving camera
float deltaAngle = 0.0f;
float deltaMove = 0.0f;
float deltaStrafe = 0.0f;
// factor to translate left and right
float strafe = 0.0f;
// angle of rotation for the camera direction
float angle = 0.0f;
// actual vector representing the camera's direction
float lx = 0.0f, lz = -1.0f;
// XZ position of the camera
float x = 0.0f, z = 5.0f;
void computeCameraPos(float deltaMove) {
x += deltaMove * lx * 0.1f;
z += deltaMove * lz * 0.1f;
}
void computeCameraDir(float deltaAngle) {
angle += deltaAngle;
lx = sin(angle);
lz = -cos(angle);
}
void computeStrafe(float deltaStrafe) {
strafe += deltaStrafe;
}
/***********************************************************************************************/
/* Keyboard Controls */
/***********************************************************************************************/
// ESC
void handleKeypress(unsigned char key,
int x, int y) { //The current mouse coordinates
switch (key) {
case 27: //ESC key
exit(0);
break;
case 32: //space bar
draw_test += 1;
break;
}
}
// Camera UP, DOWN, ZOOM IN, ZOOM OUT
void handleSpecialKeypress(int key, int xx, int yy) {
switch (key) {
case GLUT_KEY_LEFT: deltaAngle = -0.005f; break;
case GLUT_KEY_RIGHT: deltaAngle = 0.005f; break;
case GLUT_KEY_UP: deltaMove = 0.5f; break;
case GLUT_KEY_DOWN: deltaMove = -0.5f; break;
case GLUT_KEY_F1: deltaStrafe = 0.25f; break;
case GLUT_KEY_F2: deltaStrafe = -0.25f; break;
}
}
// Stop when key is released
void releaseKey(int key, int x, int y) {
switch (key) {
case GLUT_KEY_LEFT:
case GLUT_KEY_RIGHT: deltaAngle = 0.0f; break;
case GLUT_KEY_UP:
case GLUT_KEY_DOWN: deltaMove = 0; break;
case GLUT_KEY_F1:
case GLUT_KEY_F2: deltaStrafe = 0.0; break;
}
}
/***********************************************************************************************/
/* Update */
/***********************************************************************************************/
void update(int value) {
//increase rotation angle by 2 degrees
rot_angle += 2.0f;
if (rot_angle > 360) {
rot_angle -= 360;
}
// update camera
if (deltaMove)
computeCameraPos(deltaMove);
if (deltaAngle)
computeCameraDir(deltaAngle);
if (deltaStrafe)
computeStrafe(deltaStrafe);
glutPostRedisplay(); //tells Glut that scene has changed and needs to redraw
glutTimerFunc(25, update, 0); //call update again 25 milliseconds, 0 refers to the param value
}
/*********************************************************************************************/
/* Console Window */
/*********************************************************************************************/
//Move console window and display demo controls
void initConsoleWindow() {
// Set console window to top left corner // User32.lib; User32.dll -> need this for .exe file?
HWND consoleWindow = GetConsoleWindow();
SetWindowPos(consoleWindow, 0,
0, // X pos
0, // Y pos
100, 200, SWP_NOSIZE | SWP_NOZORDER);
// Display demo controls in console window
cout << "CONTROLS" << endl << "--------" << endl;
cout << "\nSPACE BAR: Next";
cout << "\n\nLEFT ARROW: Move camera left";
cout << "\nRIGHT ARROW: Move camera right"; // add strafe left strafe right
cout << "\nUP ARROW: Zoom in";
cout << "\nDOWN ARROW: Zoom out";
cout << "\nF1: Strafe left";
cout << "\nF2: Strafe right";
cout << "\n\nESC: Quit";
cout << endl << endl;
// Five second countdown before demo starts
int timer = 5;
while (timer > -1)
{
cout << "\rPlease wait... " << timer;
timer -= 1;
Sleep(1000);
}
}
/***********************************************************************************************/
/* GLUT window resize */
/***********************************************************************************************/
//Called when the window is resized
void handleResize(int w, int h) {
//Tell OpenGl how to convert from coordinates to pixel values
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION); //Switch to setting the camera perspective --> allows transformations and animation, etc.
//Only used in resizing window
//Set the camera perspective
glLoadIdentity(); //Reset the camera
gluPerspective(45.0, //The camera angle
(double)w / (double)h, //The width-to-height ratio
1.0, //The near z clipping coordinate --> don't draw things closer than 1 unit to eye
200.0); //The far z clipping coordinate --> don't draw things further than 200 units from eye
}
/*********************************************************************************************/
/* Draw */
/*********************************************************************************************/
//Draws the 3D scene
void drawScene() {
//Clear information from last draw
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW); //Switch to the standard drawing perspective
glLoadIdentity(); //Reset the drawing perspective
//glRotatef(-_cameraAngle, 0.0f, 1.0f, 0.0f); //Tip: rotate scene opposite direction instead of change camera angle
// Set the camera
gluLookAt(x, 1.0f, z,
x + lx, 1.0f, z + lz,
0.0f, 1.0f, 0.0f);
glTranslatef(strafe, 1.0f, 0.0f); // adjustment for more centered viewing and strafe control
if (draw_test > -1 && draw_test < 3) { // 0 - 2
stage.pentagon(rot_angle);
stage.text("Next: Space Bar", 350, 100);
if (draw_test >0 && draw_test < 3) { // 1 - 2
stage.trapezoid(rot_angle);
if (draw_test > 1 && draw_test < 3) { // 2
//Set background color
glClearColor(0.7f, 0.9f, 1.0f, 1.0f);
stage.triangle(rot_angle);
}
}
}
if (draw_test > 2 && draw_test < 5) { // 3 - 4 cube
stage.cube(rot_angle);
if (draw_test == 4) { // 4 fog
glEnable(GL_FOG); //enable the fog
stage.fog();
stage.text("Zoom in and out with the up and down keys to see the fog effect!", 150, 100);
}
}
if (draw_test == 5) { // 5 Lighting
glDisable(GL_FOG); //disable the fog
glEnable(GL_LIGHTING); //Enable lighting
glEnable(GL_LIGHT0); //Enable light #0
glEnable(GL_LIGHT1); //Enable light #1
glEnable(GL_NORMALIZE); //Automatically normalize normals
stage.lighting(rot_angle);
stage.text("Lighting", 370, 100);
}
if (draw_test > 5) { // 6 End
//Set background color
glClearColor(1.0f, 1.0, 1.0, 1.0f);
stage.text("Fin", 395, 300);
}
glutSwapBuffers();
}
/*************************************************************************************************/
/* Main */
/*************************************************************************************************/
int main(int argc, char** argv) {
// Move console window and display demo controls
initConsoleWindow();
//Initialize GLUT
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
//Set window size
glutInitWindowSize(800, 600);
//Set Window position to center of screen
glutInitWindowPosition((glutGet(GLUT_SCREEN_WIDTH) - 800) / 2,
(glutGet(GLUT_SCREEN_HEIGHT) - 600) / 2);
//Create the window
glutCreateWindow("MR. GLUT - Rpickelsimer");
//Makes 3D drawing work when something is in front of something else.
glEnable(GL_DEPTH_TEST);
//Enable color
glEnable(GL_COLOR_MATERIAL);
//Set handler functions for drawing, keypresses, and window resizes
glutDisplayFunc(drawScene);
glutKeyboardFunc(handleKeypress);
glutSpecialFunc(handleSpecialKeypress);
glutIgnoreKeyRepeat(1);
glutSpecialUpFunc(releaseKey);
glutReshapeFunc(handleResize);
//Call update again 25 milliseconds after program starts
glutTimerFunc(25, update, 0);
//Start the main loop.
glutMainLoop();
return 0;
}