SlideShare a Scribd company logo
Page 1 of 16
main.cpp 12/05/2011 23:06
/****
ELE 8050 - Computer Graphics
Sebastian Krezel (29043024)
Advanced Visualisation / Computer Graphics Course Work 2010/2011
The purpose of the course work is to reinforce your understanding of, and your ability to use,
the OpenGL 3D graphics programming library, and the platform independent utility toolkit (the GLUT).
The coursework task is:
Make an interactive version of ‘the Towers of Hanoi game’ (See next page),
Make the simulation using the OpenGL and GLUT libraries,
and provide an elementary user interface so that the game operated from the keyboard
and visualised interactively from different points of view.
Write a formal report in the software engineering style outlining the key steps in designing and building
the program and discuss enhancements you would like to see added to it.
The basic shapes can be build using standard primitives.
Try and augment the visual appearance by placing the model on a mirrored surface,
possibly add shadows and/or make the material take on a coloured metallic lustre using a reflection map,
and/or or use a surface image map or GPU shader to give the material the appearance of wood.
Provide some animation of the moves and facilitate basic interactivity via the keyboard or mouse.
(e.g. to change the viewpoint and select disks to be moved) You will need to think about your user interface design,
e.g. how is the user going to choose the piece to move.
You can generally find a pre-built version of the GLUT library already installed.
But it may be necessary to build the library from its source code.
You may also need to install a development environment,
Visual Studio can be obtained through the MSDNAA. GNU-C/C++ can be obtained for Window and Unix/Linux platforms,
and XCODE is free if you wish to develop on an Apple Mac
If you wanted to be really really adventurous it should possible to develop a version for an
iPhone or Android smart-phone platform. – using their simulators.
This coursework carries 40% of the total marks for the module:
■ 15% for the report and enhancement suggestions
■ 15% for the code design, layout and annotation
■ 10% for the usability and appearance of the finished program
|===3===| | |
|====2====| | |
|=====1=====| | |
--------------------------------------------------
TOWER OF HANOI
****/
#ifdef WIN32
#include "windows.h"
#else
#define WORD unsigned short
#define DWORD unsigned long
#define LONG long
// Structure - BMP file header
typedef struct tagBITMAPFILEHEADER {
WORD bfType;
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits;
} BITMAPFILEHEADER;
// Structure - BMP Info header
typedef struct tagBITMAPINFOHEADER {
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
} BITMAPINFOHEADER;
#endif
#if __APPLE__
/*
Tested on: Mac OSX 10.6.4
Page 2 of 16
main.cpp 12/05/2011 23:06
XcodeVersion 3.2.4 (64-bit)
Component versions
Xcode IDE: 1708.0
Xcode Core: 1705.0
ToolSupport: 1591.0
Built-In (GPU)
Intel GMA 950:
64MB of Shared System Memory
OenGL ver: 2.1
*/
//Include libraries
#include <stdio.h>
#include <GLUT/glut.h>
#include <iostream>
#include <math.h>
#include <string.h>
#include <ctime>
//PC to MAC bit conversion
unsigned long pc2mac(unsigned long a){
unsigned long b;
b= a & (0x000000ff) << 24;
b |= a & (0x0000ff00) << 8 ;
b |= a & (0x00ff0000) >> 8 ;
b |= a & (0xff000000) >> 24 ;
return b;
}
#else
//Note: Other system has not been tested
#include <GL/glut.h>
#include <GL/gl.h>
#include <GL/glu.h>
#endif
//Read short int from the file
unsigned short readShortInt(FILE *f){
unsigned short a,b;
fread((char*)&a,2,1,f);
b=a&(0x00ff) << 8;
b |= a&(0xff00) >> 8;
return b;
}
//Read long int from the file
unsigned long readLongInt(FILE *f){
unsigned long a,b;
fread((char*)&a,4,1,f);
b= a & (0x000000ff) << 24;
b |= a & (0x0000ff00) << 8 ;
b |= a & (0x00ff0000) >> 8 ;
b |= a & (0xff000000) >> 24 ;
return b;
}
//Loading BMP file - Use in texturing
unsigned char *LoadBmp(char *fn, int *wi, int *hi){
BITMAPFILEHEADER bmfh;
BITMAPINFOHEADER bmih;
WORD bits;
FILE *t24;
unsigned char *lpBitmapBits;
long imagesize,nc;
// read the bitmap
t24=fopen((char *)fn,"rb");
if(t24 == NULL){printf("Could not open input file [%s]n",fn); exit(0);}
readShortInt(t24);
bmfh.bfSize=readLongInt(t24);
readShortInt(t24);
readShortInt(t24);
bmfh.bfOffBits=readLongInt(t24);
fread((char *)&bmih,sizeof(BITMAPINFOHEADER),1,t24);
if(bmih.biClrUsed != 0)nc=bmih.biClrUsed;
else{
bits = bmih.biBitCount;
switch (bits){
case 1: nc=2; break;
case 4: nc=16; break;
case 8: nc=256; break;
default: nc=0; break;
}
}
if(nc > 0) {
Page 3 of 16
main.cpp 12/05/2011 23:06
printf("Cannot handle paletted imagen");
exit(0);
}
imagesize = bmfh.bfSize - bmfh.bfOffBits;
printf("You have to allocate %ld n", imagesize);
lpBitmapBits = (unsigned char *)malloc(imagesize);
if(lpBitmapBits == NULL) {
printf("Cannot allocate memoryn");
fclose(t24);
exit (0);
}
fread((char *)lpBitmapBits,imagesize,1,t24);
fclose(t24);
#if __APPLE__
*wi=pc2mac(bmih.biWidth); *hi=pc2mac(bmih.biHeight);
#else
*wi=bmih.biWidth; *hi=bmih.biHeight;
#endif
return lpBitmapBits;
}
//Use standard namespace
using namespace std;
///////////////////////////////////////////////////////////
// Global variables
//This size fit nice (not hiding the dock )
//on my current resolution 1280 x 800
GLint WindowWidth = 1240; //1280;
GLint WindowHeight = 680; //800;
//to indicate rotate angle (board, light source)
GLfloat rtri = 0.0, Rlight = 0.0, rtrBoard = 0.0;
//Variables used in options (menu)
GLboolean menu_light = false;
GLboolean menu_texture = false;
GLboolean menu_solve = false;
GLboolean menu_restart = false;
GLboolean menu_surface = false;
GLboolean menu_restart_view = false;
GLboolean menu_details = false;
//Indicator of intro animation
GLboolean Gintro = true;
//Used in displaying details
GLint min_steps;
GLint no_steps;
//Time counter
time_t tstart = time(0), tend, tcount;
struct tm *current;
//Buffer for string conversions
char buffer [40];
//Light details
GLfloat fAmbLight[] = { 0.9f, 0.9f, 0.9f, 0.0f };
GLfloat fDiffLight[] = { 1.0f, 1.0f, 1.0f, 0.0f };
GLfloat fSpecLight[] = { 0.9f, 0.9f, 0.9f, 0.0f };
GLfloat lightPos[] = {1.67f, 1.0f,-2.0f, 1.0f };
GLfloat border = 1; // used in light_move()
//Texturing
GLuint nTexture[7];
//Handle information about disk on each peg
GLint *peg_A, *peg_B, *peg_C;
//Game level, number of disk
GLint no_of_disk;
//Camera set up point
GLfloat camera_x = 4.3,
camera_y = 6,
camera_z = 7.25;
//Camera set up point for intro
GLfloat intro_camera_x = -48.5,
intro_camera_y = 20,
intro_camera_z = 7.25;
GLdouble posX, posY, posZ, //Handle mouse position in 3d space
Page 4 of 16
main.cpp 12/05/2011 23:06
ghostX, ghostY; //position of animated disk (ghost disk)
//Approximation of round objects
const GLfloat ROUND = 30;
//Hight from reflective surface
GLfloat HEIGHT = 0.0f;
//Details of the disk movement
GLint from = 0, to = 0;
//Mouse movement
GLfloat moveX = 0.0;
//Quadric - cylinders, spheres
GLUquadricObj *IDquadric;
//Mouse button is holed
bool lbuttonDown = false;
///////////////////////////////////////////////
// Tesselate floor
void drawFloor(void) {
float x, y, d = 1.0;
// Draw ground.
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, nTexture[6]);
glTranslatef(0.0, 0.1, 0.0);
glNormal3f(0,1,0);
// Tesselate floor so lighting looks more reasonable.
for (x=-8; x<=7; x+=d) {
glBegin(GL_QUAD_STRIP);
for (y=-8; y<=8; y+=d) {
glTexCoord2f(x+1, y);
glVertex3f(x+1, 0, y);
glTexCoord2f(x, y);
glVertex3f(x, 0, y);
}
glEnd();
}
glDisable(GL_TEXTURE_2D);
}
///////////////////////////////////////////////////////////
// Check if you win
bool win() {
int count = 0;
//Calculate who many disk you have on peg_C
for(int i = 0; i < no_of_disk; i++) {
if (peg_C[i] == i+1) count += 1;
}
//If all disk are on "C" you win
if (count == no_of_disk) {
return true;
}else return false;
}
///////////////////////////////////////////////////////////
// Initialize game details
void init_hanoi() {
//First clean up
delete [] peg_A;
delete [] peg_B;
delete [] peg_C;
//Allocate tables plus one cell to store index of the top disk
peg_A = new int[no_of_disk + 1];
peg_B = new int[no_of_disk + 1];
peg_C = new int[no_of_disk + 1];
for (int i = 0; i < no_of_disk; i++) {
//Put all disk at the first peg and clear others
peg_A[i] = i+1;
peg_B[i] = 0;
peg_C[i] = 0;
}
//Put the proper flag at the end of the table
peg_A[no_of_disk] = no_of_disk;
peg_B[no_of_disk] = 0;
Page 5 of 16
main.cpp 12/05/2011 23:06
peg_C[no_of_disk] = 0;
//Init variables used in Details
no_steps = 0;
min_steps = pow(2, no_of_disk) - 1;
if (lbuttonDown) tstart = time(0);
}
///////////////////////////////////////////////////////////
// Conversion between window and openGL
// return the correct OpenGL coordinates from mouse coordinates
void GetOGLPos(int x, int y) {
GLint viewport[4];
GLdouble modelview[16];
GLdouble projection[16];
GLfloat winX, winY, winZ;
glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
glGetDoublev(GL_PROJECTION_MATRIX, projection);
glGetIntegerv(GL_VIEWPORT, viewport);
winX = (float)x;
winY = (float)viewport[3] - (float)y;
glReadPixels(x, int(winY), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ);
gluUnProject(winX, winY, winZ, modelview, projection, viewport, &posX, &posY, &posZ);
}
///////////////////////////////////////////////////////////
// Move peg from S-source to D-destination peg
bool move_it(int *S, int *D) {
int S_index, D_index;
//Check if you have disk to be moved
if (S[no_of_disk] == 0) {
return false;
} else {
S_index = S[no_of_disk] - 1;
//Peg is empty so we can put disk on it
if ((D[no_of_disk] == 0)) {
D[0] = S[S_index];
S[S_index] = 0;
S[no_of_disk] -= 1;
D[no_of_disk] += 1;
no_steps +=1; //Count this move
return true;
} else D_index = D[no_of_disk];
//Check if possible to move
if (S[S_index] > D[D_index - 1]) {
D[D_index] = S[S_index];
S[S_index] = 0;
S[no_of_disk] -= 1;
D[no_of_disk] += 1;
no_steps +=1; //Count this move
return true;
} else {
//You cant put bigger on smaller
return false;
}
}
}
///////////////////////////////////////////////////////////
// This function shows game details in the console
// It was used for testing purposes while implementing "solve_it()" function
//
// Example:
//
//
// //Test legal move between A and B Track solving steps:
// if (!move_it(B, C)) { [ 3 ][ 0 ][ 1 ]
// move_it(C,B); [ 0 ][ 0 ][ 2 ]
// console_hanoi(A,B,C); [ 0 ][ 0 ][ 0 ]
// } else console_hanoi(A,B,C); ___________________
// [ 1 ][ 0 ][ 2 ]
//
// currently not used to keep final code clear
Page 6 of 16
main.cpp 12/05/2011 23:06
void console_hanoi (int *A, int *B, int *C) {
cout << "Track solving steps:" << endl;
//For simplicity show it up side down
for (int i = 0; i < no_of_disk + 1; i++) {
if (i == no_of_disk) cout << "___________________" << endl;
//Display flags, number of disk on the peg
cout << "[ " << A[i] << " ]" << "[ " << B[i] << " ]" << "[ " << C[i] << " ]" << endl;
}
cout << endl << endl;
}
///////////////////////////////////////////////////////////
// Function is solving the game
void solve_it(int *A, int *B, int *C) {
//Use iterative solution
//In each case (even,odd), a total of 2n-1 moves are made.
//For an even number of disks:
if (no_of_disk % 2 == 0) {
//make the legal move between pegs A and B
if (!move_it(A,B)) move_it(B,A);
//make the legal move between pegs A and C
if (!move_it(A, C)) move_it(C,A);
//make the legal move between pegs B and C
if (!move_it(B, C)) move_it(C,B);
//For odd number of disk
} else {
//make the legal move between pegs A and C
if (!move_it(A,C)) move_it(C,A);
else {
//If solved just go out from this function
if (win()) return;
}
//make the legal move between pegs A and B
if (!move_it(A,B)) move_it(B,A);
//make the legal move between pegs B and C
if (!move_it(B,C)) move_it(C,B);
}
}
///////////////////////////////////////////////////////////
// Draw "ghost" disk to help track user movement and improve interface
void ghost_disk (GLfloat x, GLfloat y) {
int index;
//GLfloat h = 0; //hight position
GLfloat radius = 0, r_max = 1.1; //declare radius var
GLfloat r_step = 0.9 / no_of_disk; //calculate difference in radius between disks
switch (from) {
case 1:
if (peg_A[no_of_disk] != 0) {
index = peg_A[no_of_disk] -1;
radius = r_max - ((peg_A[index] - 1) * r_step);
radius += 0.01; //Make it a bit bigger then original
}
break;
case 2:
if (peg_B[no_of_disk] != 0) {
index = peg_B[no_of_disk] -1;
radius = r_max - ((peg_B[index] - 1) * r_step);
radius += 0.01; //Make it a bit bigger then original
}
break;
case 3:
if (peg_C[no_of_disk] != 0) {
index = peg_C[no_of_disk] -1;
radius = r_max - ((peg_C[index] - 1) * r_step);
radius += 0.01; //Make it a bit bigger then original
}
break;
default:
break;
}
//Draw the ghost disk with proper radius and place on proper height
glPushMatrix();
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, nTexture[4]);
glRotatef(90, 1.0f, 0.0, 0.0);
glTranslatef(x, 0.0, 0.0);
Page 7 of 16
main.cpp 12/05/2011 23:06
gluCylinder(IDquadric, radius, radius, 0.30f, ROUND, ROUND);
gluDisk(IDquadric, 0.125f, radius, ROUND, ROUND);
//Bottom circle of the disk - not really visible
//so we don't have to draw it
glDisable(GL_TEXTURE_2D);
glPopMatrix();
}
///////////////////////////////////////////////////////////
//Mouse button is clicked/hold...
//defining drag and drop disk movement
void mouse(int button, int state, int x, int y) {
//Use only left mouse button to drag and drop disk
if (button == GLUT_LEFT_BUTTON) {
if (state == GLUT_DOWN) {
lbuttonDown = true;
GetOGLPos(x,y);
//Check what peg you "drag"
if (posX > -4.0 and posX < -1.34 and posY > 0) from = 1; //peg_A
if (posX > -1.3 and posX < 1.32 and posY > 0) from = 2; //peg_B
if (posX > 1.32 and posX < 4 and posY > 0) from = 3; //peg_C
if (win()) {
//Go to next level, Put limit of 13 disk
//It fit nice on pegs
if (no_of_disk < 13) no_of_disk += 1;
//Initialise new level
init_hanoi();
//go back to normal view - stop spinning
rtri = 0;
}
}
else {
lbuttonDown = false;
GetOGLPos(x,y);
//If drop disk on peg A
if (posX > -4.0 and posX < -1.34 and posY > 0) {
to = 1; //peg_A
switch (from) {
case 1:
break;
case 2:
move_it(peg_B, peg_A);
break;
case 3:
move_it(peg_C, peg_A);
break;
}
}
//If drop disk on peg B
if (posX > -1.3 and posX < 1.32 and posY > 0) {
to = 2; //peg_B
switch (from) {
case 1:
move_it(peg_A, peg_B);
break;
case 2:
break;
case 3:
move_it(peg_C, peg_B);
break;
}
}
//If drop disk on peg C
if (posX > 1.32 and posX < 4 and posY > 0) {
to = 3; //peg_C
switch (from) {
case 1:
move_it(peg_A, peg_C);
break;
case 2:
move_it(peg_B, peg_C);
break;
case 3:
break;
}
}
}
}
}
Page 8 of 16
main.cpp 12/05/2011 23:06
///////////////////////////////////////////////////////////
//Mouse motion
void motion(int x, int y) {
//If you hold left button and move mouse
//Update position of the cursor to refresh
//Animation of "ghost disk"
if (lbuttonDown) {
GetOGLPos(x, y);
}
}
///////////////////////////////////////////////////////////
// Defining key action
void processSpecialKeys(int key, int x, int y) {
switch(key) {
case GLUT_KEY_F1:
menu_restart = !menu_restart;
tstart = time(0);
break;
case GLUT_KEY_F2:
//Place disks on start position Before solving
//Avoid infinitive loops in iterative algorithm
menu_restart = true;
menu_solve = !menu_solve;
break;
case GLUT_KEY_F3:
menu_texture = !menu_texture;
break;
case GLUT_KEY_F4:
menu_surface = !menu_surface;
break;
case GLUT_KEY_F5:
menu_light = !menu_light;
break;
case GLUT_KEY_F6:
menu_restart_view = !menu_restart_view;
break;
case GLUT_KEY_F7:
menu_details = !menu_details;
break;
}
}
///////////////////////////////////////////////////////////
// Defining key action
void processNormalKeys(unsigned char key, int x, int y) {
//Light settings
if(key == 'q') lightPos[2] -= 0.25;
if(key == 'a') lightPos[2] += 0.25;
if(key == 'f') lightPos[0] += 0.25;
if(key == 's') lightPos[0] -= 0.25;
if(key == 'e') lightPos[1] += 0.25;
if(key == 'd') lightPos[1] -= 0.25;
//Camera positions
if (key == 'p') camera_z -= 0.25f;
if (key == ';') camera_z += 0.25f;
if (key == 'o')
//Don't go to low
//don't show whats under the board
if (camera_y > 0.5) camera_y -= 0.5f;
if (key == 'l') camera_y += 0.25f;
if (key == 'i') camera_x -= 0.25f;
if (key == 'k') camera_x += 0.25f;
if(key == 27) exit(0);
// Refresh the Window
glutPostRedisplay();
}
///////////////////////////////////////////////////////////////////////////////
// Reset flags as appropriate in response to menu selections
void ProcessMenu(int value) {
switch(value) {
case 1:
menu_restart = !menu_restart;
tstart = time(0);
break;
case 2:
//Place disks on start position Before solving
//Avoid infinitive loops in iterative algorithm
Page 9 of 16
main.cpp 12/05/2011 23:06
menu_restart = true;
menu_solve = !menu_solve;
break;
case 3:
menu_texture = !menu_texture;
break;
case 4:
menu_surface = !menu_surface;
break;
case 5:
menu_light = !menu_light;
break;
case 6:
menu_restart_view = !menu_restart_view;
break;
case 7:
menu_details = !menu_details;
break;
default:
break;
}
glutPostRedisplay();
}
///////////////////////////////////////////////////////////////////////////////
//process submenu - chose number of disk on board
void num_disk(int value) {
no_of_disk = value;
//Initialise with new number
init_hanoi();
tstart = time(0);
glutPostRedisplay();
}
///////////////////////////////////////////////////////////
// Called to clean quadric
void cleanupQuadric(void) {
gluDeleteQuadric(IDquadric);
cout << "cleanupQuadric completed" << endl;
}
///////////////////////////////////////////////////////////
// Called to clean up arrays
void cleanupArrays(void) {
delete [] peg_A;
delete [] peg_B;
delete [] peg_C;
peg_A = NULL;
peg_B = NULL;
peg_C = NULL;
cout << "cleanupArray completed" << endl;
}
///////////////////////////////////////////////////////////
// Called to draw a mirrored surface
void Surface() {
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, nTexture[1]);
glBegin(GL_POLYGON);
glNormal3f(0.0, 1.0, 0.0);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 8.0f, 0.15f,-8.0f); // Top Right Of The Quad (Top)
glTexCoord2f(0.0f, 1.0f); glVertex3f(-8.0f, 0.15f,-8.0f); // Top Left Of The Quad (Top)
glTexCoord2f(0.0f, 0.0f); glVertex3f(-8.0f, 0.15f, 8.0f); // Bottom Left Of The Quad (Top)
glTexCoord2f(1.0f, 0.0f); glVertex3f( 8.0f, 0.15f, 8.0f); // Bottom Right Of The Quad (Top)
glEnd();
glDisable(GL_TEXTURE_2D);
}
///////////////////////////////////////////////////////////
// Called to draw disk
// Depends of parameter type it draws disk with different textures
void draw_disk (GLfloat radius, GLfloat x, GLfloat h, GLboolean type) {
//Rough wood looking disks
//Use two different textures
if (type) {
glPushMatrix();
Page 10 of 16
main.cpp 12/05/2011 23:06
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, nTexture[4]);
glRotatef(90, 1.0f, 0.0, 0.0);
glTranslatef(x, 0.0, -h -0.6);
//Main part of the disk
gluCylinder(IDquadric,radius,radius,0.30f,ROUND, ROUND);
glDisable(GL_TEXTURE_2D);
//Top cover of the disk
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, nTexture[3]);
gluDisk(IDquadric,0.125f,radius,ROUND,ROUND);
//Bottom circle of the disk - not really visible
//so we don't have to draw it
glDisable(GL_TEXTURE_2D);
glPopMatrix();
//Use one texture for drawing
} else {
glPushMatrix();
glRotatef(90, 1.0f, 0.0, 0.0);
glTranslatef(x, 0.0, -h -0.4);
//Main part of the disk
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, nTexture[0]);
gluCylinder(IDquadric,radius,radius,0.30f,ROUND, ROUND);
gluDisk(IDquadric, 0.125f, radius, ROUND, ROUND);
//Bottom not visible
glDisable(GL_TEXTURE_2D);
glPopMatrix();
}
}
///////////////////////////////////////////////////////////
// Called to draw peg
void draw_peg(GLfloat x) {
glEnable(GL_TEXTURE_2D);
if (menu_texture)
glBindTexture(GL_TEXTURE_2D, nTexture[5]);
else
glBindTexture(GL_TEXTURE_2D, nTexture[0]);
glPushMatrix();
glTranslatef(x,0,0);
glRotatef(270.0, 1.0f, 0.0f, 0.0f);
gluCylinder(IDquadric, 0.15f, //base radius
0.1f, //top radius
4.0f, //height
ROUND, //approximation
ROUND //...
);
glTranslatef(0,0,4);
gluSphere(IDquadric,0.1f,ROUND,ROUND);
glPopMatrix();
glDisable(GL_TEXTURE_2D);
}
///////////////////////////////////////////////////////////
// Called to draw game board
void draw_board() {
glEnable(GL_TEXTURE_2D);
if (menu_texture) glBindTexture(GL_TEXTURE_2D, nTexture[5]);
else glBindTexture(GL_TEXTURE_2D, nTexture[0]);
glBegin(GL_QUADS); // Start Drawing Hanoi board
glNormal3f(0.0, 1.0, 0.0); //Use to point proper sides for lighting
glTexCoord2f(1.0f, 1.0f); glVertex3f( 4.0f, 0.15f,-2.0f); // Top Right Of The Quad (Top)
glTexCoord2f(0.0f, 1.0f); glVertex3f(-4.0f, 0.15f,-2.0f); // Top Left Of The Quad (Top)
glTexCoord2f(0.0f, 0.0f); glVertex3f(-4.0f, 0.15f, 2.0f); // Bottom Left Of The Quad (Top)
glTexCoord2f(1.0f, 0.0f); glVertex3f( 4.0f, 0.15f, 2.0f); // Bottom Right Of The Quad (Top)
glNormal3f(0.0, -1.0, 0.0);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 4.0f,-0.15f, 2.0f); // Top Right Of The Quad (Bottom)
glTexCoord2f(0.0f, 1.0f); glVertex3f(-4.0f,-0.15f, 2.0f); // Top Left Of The Quad (Bottom)
glTexCoord2f(0.0f, 0.0f); glVertex3f(-4.0f,-0.15f,-2.0f); // Bottom Left Of The Quad (Bottom)
glTexCoord2f(1.0f, 0.0f); glVertex3f( 4.0f,-0.15f,-2.0f); // Bottom Right Of The Quad (Bottom)
glNormal3f(0.0, 0.0, 1.0);
glTexCoord2f(0.0f, 0.0f); glVertex3f( 4.0f, 0.15f, 2.0f); // Top Right Of The Quad (Front)
Page 11 of 16
main.cpp 12/05/2011 23:06
glTexCoord2f(1.0f, 0.0f); glVertex3f(-4.0f, 0.15f, 2.0f); // Top Left Of The Quad (Front)
glTexCoord2f(1.0f, 1.0f); glVertex3f(-4.0f,-0.15f, 2.0f); // Bottom Left Of The Quad (Front)
glTexCoord2f(0.0f, 1.0f); glVertex3f( 4.0f,-0.15f, 2.0f); // Bottom Right Of The Quad (Front)
glNormal3f(0.0, 0.0, -1.0);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 4.0f,-0.15f,-2.0f); // Bottom Left Of The Quad (Back)
glTexCoord2f(1.0f, 1.0f); glVertex3f(-4.0f,-0.15f,-2.0f); // Bottom Right Of The Quad (Back)
glTexCoord2f(0.0f, 1.0f); glVertex3f(-4.0f, 0.15f,-2.0f); // Top Right Of The Quad (Back)
glTexCoord2f(0.0f, 0.0f); glVertex3f( 4.0f, 0.15f,-2.0f); // Top Left Of The Quad (Back)
glNormal3f(-1.0, 0.0, 0.0);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-4.0f, 0.15f, 2.0f); // Top Right Of The Quad (Left)
glTexCoord2f(1.0f, 0.0f); glVertex3f(-4.0f, 0.15f,-2.0f); // Top Left Of The Quad (Left)
glTexCoord2f(1.0f, 1.0f); glVertex3f(-4.0f,-0.15f,-2.0f); // Bottom Left Of The Quad (Left)
glTexCoord2f(0.0f, 1.0f); glVertex3f(-4.0f,-0.15f, 2.0f); // Bottom Right Of The Quad (Left)
glNormal3f(1.0, 0.0, 0.0);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 4.0f, 0.15f,-2.0f); // Top Right Of The Quad (Right)
glTexCoord2f(1.0f, 1.0f); glVertex3f( 4.0f, 0.15f, 2.0f); // Top Left Of The Quad (Right)
glTexCoord2f(0.0f, 1.0f); glVertex3f( 4.0f,-0.15f, 2.0f); // Bottom Left Of The Quad (Right)
glTexCoord2f(0.0f, 0.0f); glVertex3f( 4.0f,-0.15f,-2.0f); // Bottom Right Of The Quad (Right)
glEnd(); // Done Drawing
glDisable(GL_TEXTURE_2D);
}
///////////////////////////////////////////////////////////
//Functions draws all disks in the game radius depends of numbers
//of disk in the game
void draw_all_disks () {
GLfloat h = 0; //hight position
GLfloat r, r_max = 1.1; //declare radius var
GLfloat r_step = 0.9 / no_of_disk; //calculate difference in radius between disks
for (int i = 0; i < no_of_disk; i++) {
//draw on peg A
if (peg_A[i] != 0) {
//Calculate radius of the disk
r = r_max - ((peg_A[i] - 1) * r_step);
draw_disk (r, -2.5, h, menu_texture);
}
//draw on peg B
if (peg_B[i] != 0) {
//Calculate radius of the disk
r = r_max - ((peg_B[i] - 1) * r_step);
draw_disk (r, 0.0, h, menu_texture);
}
//draw on peg C
if (peg_C[i] != 0) {
//Calculate radius of the disk
r = r_max - ((peg_C[i] - 1) * r_step);
draw_disk (r, 2.5, h, menu_texture);
}
h += 0.3; //Move it up
}
}
///////////////////////////////////////////////////////////
//Function draw light source
//on the scene
void Draw_Light_Source () {
glPushMatrix();
glTranslatef(lightPos[0], lightPos[1], lightPos[2]);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, nTexture[2]);
glPushMatrix();
glRotatef(Rlight, 1.0, 1.0, 1.0);
gluSphere(IDquadric,0.15f,ROUND,ROUND);
glPopMatrix();
glDisable(GL_TEXTURE_2D);
glPopMatrix();
}
//////////////////////////////////////////////////////////////////////////
// To move light stripe slowly
void light_move() {
//Move just on y and z axis
lightPos[1] = 8.5;
lightPos[2] = -15.75;
//Set up range of movement
if (border == 1) {
Page 12 of 16
main.cpp 12/05/2011 23:06
lightPos[0] += 0.1;
if (lightPos[0] > 20.0) border = 0;
} else {
lightPos[0] -= 0.1;
if (lightPos[0] < -20.0) border = 1;
}
}
///////////////////////////////////////////////////////////
//Function combine all objets that have to be draw
void Draw_Hanoi () {
glPushMatrix();
draw_board(); //main board
draw_peg(0); //first stick
draw_peg(-2.5); //second stick
draw_peg(2.5); //third stick
draw_all_disks(); //draw disks
glPopMatrix();
}
///////////////////////////////////////////////////////////////////
//Function calculate camera position for intro animation purpose
bool intro() {
if (intro_camera_x < 3.5) intro_camera_x += 0.8;
//camera_x = -48.5,
if (intro_camera_y > 6) {
intro_camera_y -= 0.15;
return true;
} else return false;
}
///////////////////////////////////////////////////////////////////
//Function Display the text (r,g,b colours) on "viewing plane"
void DrawText(GLint x, GLint y, char* s, GLfloat r, GLfloat g, GLfloat b)
{
int lines;
char* p;
glDisable(GL_LIGHTING); //To get proper colour
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
//Change to Ortho
glOrtho(0.0, glutGet(GLUT_WINDOW_WIDTH),
0.0, glutGet(GLUT_WINDOW_HEIGHT), -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glColor3f(r,g,b);
glRasterPos2i(x, y);
for(p = s, lines = 0; *p; p++) {
if (*p == 'n') {
lines++;
glRasterPos2i(x, y-(lines*18));
}
glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, *p);
}
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glEnable(GL_LIGHTING); //Turn it back
}
///////////////////////////////////////////////////////////
// Called to draw scene
void RenderScene(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glLoadIdentity(); //Re-set the view
glEnable(GL_NORMALIZE);
glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
//If flag is set up show light source
if (menu_light) Draw_Light_Source();
if (!intro())
Page 13 of 16
main.cpp 12/05/2011 23:06
gluLookAt(camera_x, camera_y, camera_z, // look from camera XYZ
0, 0, 0, // look at the origin
0, 1, 0 // positive Y up vector
);
else gluLookAt(intro_camera_x, intro_camera_y, intro_camera_z, 0, 0, 0, 0, 1, 0);
glScaled(1.1, 1.1, 1.1); //Make it a bit bigger
glRotatef(rtri,0.0f,1.0f,0.0f); //Rotate if Win
Draw_Hanoi(); //Draw board with disks
if (menu_surface) HEIGHT = 0.2;
else HEIGHT = 0;
glTranslatef(0.0f, -HEIGHT-0.3, 0.0f); //Place on surface
glEnable(GL_STENCIL_TEST); //Enable using the stencil buffer
glColorMask(0, 0, 0, 0); //Disable drawing colours to the screen
glDisable(GL_DEPTH_TEST); //Disable depth testing
glStencilFunc(GL_ALWAYS, 1, 1); //Make the stencil test always pass
//Make pixels in the stencil buffer be set to 1 when the stencil test passes
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
//Set all of the pixels covered by the floor to be 1 in the stencil buffer
//Draw mirrored plane
if (menu_surface) drawFloor();
else Surface();
glColorMask(1, 1, 1, 1); //Enable drawing colours to the screen
glEnable(GL_DEPTH_TEST); //Enable depth testing
//Make the stencil test pass only when the pixel is 1 in the stencil buffer
glStencilFunc(GL_EQUAL, 1, 1);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); //Make the stencil buffer not change
//Draw Game board, reflected vertically, at all pixels where the stencil buffer is 1
glPushMatrix();
glScalef(1, -1, 1);
glTranslatef(0, HEIGHT, 0);
Draw_Hanoi();
glPopMatrix();
glDisable(GL_STENCIL_TEST); //Disable stencil buffer
//Blend the floor onto the screen
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glColor4f(1, 1, 1, 0.9f);
//Draw mirrored plane
if (menu_surface) drawFloor();
else Surface();
glDisable(GL_BLEND);
//If left button is pressed render move tracking disk
if (lbuttonDown) {
glPushMatrix();
glEnable (GL_BLEND);
glDepthMask (GL_FALSE);
glBlendFunc (GL_SRC_ALPHA, GL_ONE);
//Move if you point the game board
if (posX > -4 && posX < 4) {
if (posZ > -2 && posZ < 2) {
glTranslatef(posX, 1.0, posZ);
glColor4f(1, 1, 1, 0.5f);
ghost_disk(0.0, 4.0);
}
}
glDepthMask (GL_TRUE);
glDisable (GL_BLEND);
glPopMatrix();
}
//If you win display a message
if (win()) {
char tmp[50] = "You Solve it, Click to Next Level";
DrawText((glutGet(GLUT_WINDOW_WIDTH) /2) - 140, glutGet(GLUT_WINDOW_HEIGHT) /2, tmp, 1.0, 1.0, 1.0);
}
//If required display dame details
if (menu_details) {
sprintf(buffer, "Number of disks = %d", no_of_disk);
DrawText(20, glutGet(GLUT_WINDOW_HEIGHT) -30, buffer, 0.56, 0.34, 0.05);
sprintf(buffer, "Minimum to solve = %d", min_steps);
DrawText(20, glutGet(GLUT_WINDOW_HEIGHT) -50, buffer, 0.56, 0.34, 0.05);
sprintf(buffer, "Your moves: %d", no_steps);
DrawText(20, glutGet(GLUT_WINDOW_HEIGHT) -70, buffer, 0.56, 0.34, 0.05);
Page 14 of 16
main.cpp 12/05/2011 23:06
//Display time
current = localtime(&tcount);
sprintf(buffer, "Time: %02d:%02d:%02dn", current->tm_hour, current->tm_min, current->tm_sec);
DrawText(20, glutGet(GLUT_WINDOW_HEIGHT) -90, buffer, 0.56, 0.34, 0.05);
}
glColor3f(1.0, 1.0, 10.0);
glutSwapBuffers();
}
//////////////////////////////////////////////////////////////////////////
// Change viewing volume and viewport. Called when window is resized
void ChangeSize(int w, int h) {
GLfloat fAspect;
// Prevent a divide by zero
if(h == 0) h = 1;
// Set Viewport to window dimensions
glViewport(0, 0, w, h);
fAspect = (GLfloat)w/(GLfloat)h;
// Reset coordinate system
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Produce the perspective projection
gluPerspective(60.0f, fAspect, 1.0, 400.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
///////////////////////////////////////////////////////////
// Called by GLUT library when idle
void TimerFunction(int value) {
//If you show light object it will spin
Rlight +=1.2f;
//If you win current level board will spin until mouse button pressed
if (win()) {
rtri+=1.2f;
menu_solve = false;
lightPos[0] = 0.42;
lightPos[1] = 9.75;
lightPos[2] = -22;
}
//If chose run light movement
if (menu_surface) light_move();
//If chose solve puzzles
if (menu_solve) solve_it(peg_A, peg_B, peg_C);
//If restart level
if (menu_restart) {
init_hanoi();
menu_restart = !menu_restart;
}
//Restart view
if (menu_restart_view) {
camera_x = 4.3;
camera_y = 6;
camera_z = 7.25;
menu_restart_view = !menu_restart_view;
}
if (!win()) tend = time(0);
tcount = difftime(tend, tstart);
//Redraw the scene with new coordinates
glutPostRedisplay();
glutTimerFunc(1,TimerFunction, 1);
}
///////////////////////////////////////////////////////////
// Setting up texture
void SetupTexture (char *name, int nT) {
unsigned char *pix;
GLint w,h;
glBindTexture(GL_TEXTURE_2D, nT);
Page 15 of 16
main.cpp 12/05/2011 23:06
pix = LoadBmp(name,&w,&h);
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, w, h,
0, GL_BGR_EXT, GL_UNSIGNED_BYTE, pix);
free(pix);
pix = NULL;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
}
///////////////////////////////////////////////////////////
// Setup the rendering state
void SetupRC(void) {
char tmp[50];
glShadeModel(GL_SMOOTH); //Enables Smooth Shading
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); //Background
IDquadric=gluNewQuadric(); //Create A Pointer To The Quadric Object
gluQuadricNormals(IDquadric, GLU_SMOOTH); //Create Smooth Normals
gluQuadricTexture(IDquadric, GL_TRUE); //Create Texture Coords
no_of_disk = 3; //Game start level
init_hanoi(); //Initialize data
glClearDepth(1.0f); //Depth Buffer Setup
glEnable(GL_DEPTH_TEST); //Enables Depth Testing
glDepthFunc(GL_LEQUAL); //The Type Of Depth Test To Do
// Set up lighting
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
glMaterialfv(GL_FRONT, GL_SPECULAR, fDiffLight);
glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, 64);
//Set up blending function
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glLightfv(GL_LIGHT0, GL_AMBIENT, fAmbLight);
glLightfv(GL_LIGHT0, GL_DIFFUSE, fDiffLight);
glLightfv(GL_LIGHT0, GL_SPECULAR, fSpecLight);
glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
//Perspective Calculations
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
//Texturing
glEnable(GL_TEXTURE_2D);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glGenTextures(6, nTexture);
//Prepare all textures for use
//To avoid conversion warning use strcpy
strcpy (tmp,"tex1.bmp"); SetupTexture(tmp, nTexture[0]);
strcpy (tmp,"tex2.bmp"); SetupTexture(tmp, nTexture[1]);
strcpy (tmp,"tex3.bmp"); SetupTexture(tmp, nTexture[2]);
strcpy (tmp,"tex4.bmp"); SetupTexture(tmp, nTexture[3]);
strcpy (tmp,"tex5.bmp"); SetupTexture(tmp, nTexture[4]);
strcpy (tmp,"tex6.bmp"); SetupTexture(tmp, nTexture[5]);
strcpy (tmp,"tex7.bmp"); SetupTexture(tmp, nTexture[6]);
//Clean up at exit
atexit(cleanupQuadric);
atexit(cleanupArrays);
}
///////////////////////////////////////////////////////////
// Main program entry point
int main(int argc, char* argv[]) {
GLint sub;
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(WindowWidth, WindowHeight);
glutInitWindowPosition(0, 0); //Place window on left top corner
glutCreateWindow("Tower of Hanoi - Sebastian Krezel - Courswork");
//No of disk - sub menu
sub = glutCreateMenu(num_disk);
glutAddMenuEntry("3", 3);
glutAddMenuEntry("4", 4);
glutAddMenuEntry("5", 5);
glutAddMenuEntry("6", 6);
Page 16 of 16
main.cpp 12/05/2011 23:06
glutAddMenuEntry("7", 7);
glutAddMenuEntry("8", 8);
glutAddMenuEntry("9", 9);
glutAddMenuEntry("10", 10);
glutAddMenuEntry("11", 11);
glutAddMenuEntry("12", 12);
glutAddMenuEntry("13", 13);
//Create the Menu
glutCreateMenu(ProcessMenu);
glutAddMenuEntry("Restart this level" ,1);
glutAddSubMenu("Pick-up no of disk" ,sub);
glutAddMenuEntry("Solve it for me!" ,2);
glutAddMenuEntry("Change Textures" ,3);
glutAddMenuEntry("Change Surface and Light",4);
glutAddMenuEntry("Show Light Opject" ,5);
glutAddMenuEntry("Restart view" ,6);
glutAddMenuEntry("Show details" ,7);
glutAttachMenu(GLUT_RIGHT_BUTTON);
SetupRC();
glutReshapeFunc(ChangeSize);
glutDisplayFunc(RenderScene);
//Keyboard controls
glutKeyboardFunc(processNormalKeys);
glutSpecialFunc(processSpecialKeys);
//Mouse controls
glutMouseFunc(mouse);
glutMotionFunc(motion);
glutTimerFunc(33, TimerFunction, 1);
glutMainLoop();
return 0;
}

More Related Content

Similar to main.pdf java programming practice for programs (20)

PPT
Intro to Computer Graphics.ppt
adil104135
 
PPT
opengl.ppt
Subiksha57
 
PPTX
Chapter02 graphics-programming
Mohammed Romi
 
PPTX
3 CG_U1_P2_PPT_3 OpenGL.pptx
ssuser255bf1
 
PDF
Computer Graphics Report
Koshy Geoji
 
PPT
openGL basics for sample program (1).ppt
HIMANKMISHRA2
 
PPT
openGL basics for sample program.ppt
HIMANKMISHRA2
 
PPT
Game Engine Design: Anatomy of a game engine
xarawig871
 
PPTX
Computer Graphics Project on Sinking Ship using OpenGL
Sharath Raj
 
PDF
CG mini project
Mohammed Dawood
 
PPT
Opengl (1)
ch samaram
 
PPTX
Opengl presentation
elnaqah
 
PPT
Computer Graphics involves technology to access. The Process transforms and p...
ErNandiniDharne
 
PDF
AN INTERNSHIP REPORT ON AIRPLANE GAME MANAGEMENT SYSTEM PROJECT REPORT.
Kamal Acharya
 
PPT
Drawing Figures
Ghaffar Khan
 
PPTX
OpenGL Introduction
Jayant Mukherjee
 
PDF
Opengl4 quick reference card
Adrien Wattez
 
PDF
OpenGL 4.4 Reference Card
The Khronos Group Inc.
 
DOCX
Lab Practices and Works Documentation / Report on Computer Graphics
Rup Chowdhury
 
PDF
Graphics Programming OpenGL & GLUT in Code::Blocks
Budditha Hettige
 
Intro to Computer Graphics.ppt
adil104135
 
opengl.ppt
Subiksha57
 
Chapter02 graphics-programming
Mohammed Romi
 
3 CG_U1_P2_PPT_3 OpenGL.pptx
ssuser255bf1
 
Computer Graphics Report
Koshy Geoji
 
openGL basics for sample program (1).ppt
HIMANKMISHRA2
 
openGL basics for sample program.ppt
HIMANKMISHRA2
 
Game Engine Design: Anatomy of a game engine
xarawig871
 
Computer Graphics Project on Sinking Ship using OpenGL
Sharath Raj
 
CG mini project
Mohammed Dawood
 
Opengl (1)
ch samaram
 
Opengl presentation
elnaqah
 
Computer Graphics involves technology to access. The Process transforms and p...
ErNandiniDharne
 
AN INTERNSHIP REPORT ON AIRPLANE GAME MANAGEMENT SYSTEM PROJECT REPORT.
Kamal Acharya
 
Drawing Figures
Ghaffar Khan
 
OpenGL Introduction
Jayant Mukherjee
 
Opengl4 quick reference card
Adrien Wattez
 
OpenGL 4.4 Reference Card
The Khronos Group Inc.
 
Lab Practices and Works Documentation / Report on Computer Graphics
Rup Chowdhury
 
Graphics Programming OpenGL & GLUT in Code::Blocks
Budditha Hettige
 

More from RavinderKSingla (20)

PPTX
aiineducation-part2.pptx It is on artificial intelligence
RavinderKSingla
 
PDF
AI-edication-impact.pdf It is on artificial intelligence
RavinderKSingla
 
PDF
document.pdf It is on artificial intelligence
RavinderKSingla
 
PDF
201811-AI-in-Higher-Education-TLH.pdf the role of AI
RavinderKSingla
 
PDF
IF10937.pdf education with AI role to play
RavinderKSingla
 
PDF
artificial-intelligence-in-higher-education.pdf
RavinderKSingla
 
PDF
Becker_Artificial_Intelligence_in_Education.pdf
RavinderKSingla
 
PDF
ten_facts_about_artificial_intelligence_0.pdf
RavinderKSingla
 
PPTX
Artificial-Intelligence-Academic-Integrity-Participant-Slides.pptx
RavinderKSingla
 
PDF
cs notes for the syudents of computer science
RavinderKSingla
 
PDF
computer graphic and multimedia for the students of MCA
RavinderKSingla
 
PDF
Lecture for the students of CS for interactive graphical techniques
RavinderKSingla
 
PDF
interactive computer graphics for the students of computer science
RavinderKSingla
 
PDF
InTech-Utilising_virtual_environments_to_research_ways_to_improve_manipulatio...
RavinderKSingla
 
DOC
sdlc-Lecture2.doc System analsysis and design
RavinderKSingla
 
DOC
Information Systems, Design and MIS(MS-07).doc
RavinderKSingla
 
PDF
codeblocks-instructions.pdf
RavinderKSingla
 
PDF
Software_Engineering__8th_Ed.pdf
RavinderKSingla
 
PDF
glu1_3.pdf
RavinderKSingla
 
PDF
OpenGL_Programming_Guide.pdf
RavinderKSingla
 
aiineducation-part2.pptx It is on artificial intelligence
RavinderKSingla
 
AI-edication-impact.pdf It is on artificial intelligence
RavinderKSingla
 
document.pdf It is on artificial intelligence
RavinderKSingla
 
201811-AI-in-Higher-Education-TLH.pdf the role of AI
RavinderKSingla
 
IF10937.pdf education with AI role to play
RavinderKSingla
 
artificial-intelligence-in-higher-education.pdf
RavinderKSingla
 
Becker_Artificial_Intelligence_in_Education.pdf
RavinderKSingla
 
ten_facts_about_artificial_intelligence_0.pdf
RavinderKSingla
 
Artificial-Intelligence-Academic-Integrity-Participant-Slides.pptx
RavinderKSingla
 
cs notes for the syudents of computer science
RavinderKSingla
 
computer graphic and multimedia for the students of MCA
RavinderKSingla
 
Lecture for the students of CS for interactive graphical techniques
RavinderKSingla
 
interactive computer graphics for the students of computer science
RavinderKSingla
 
InTech-Utilising_virtual_environments_to_research_ways_to_improve_manipulatio...
RavinderKSingla
 
sdlc-Lecture2.doc System analsysis and design
RavinderKSingla
 
Information Systems, Design and MIS(MS-07).doc
RavinderKSingla
 
codeblocks-instructions.pdf
RavinderKSingla
 
Software_Engineering__8th_Ed.pdf
RavinderKSingla
 
glu1_3.pdf
RavinderKSingla
 
OpenGL_Programming_Guide.pdf
RavinderKSingla
 
Ad

Recently uploaded (20)

PPTX
1.13=Symphytum=1st Term---------------------1st.pptx
zk7304860098
 
PPTX
4 Team Skills under Employability Skills
bonophool banerjee
 
PDF
Mini Cultivator For Multipurpose Farming.pdf
ssuser77b53b
 
PDF
Soft skills for resume and resume match with job description.pdf
worksmart2718
 
PPT
E-MAIL ETIQUETTE_for_business_profes.ppt
WaheedZahran3
 
DOCX
Guidance and counselling program service docx
HockeyApuyaAnion
 
PPTX
Lea 300 Industrial security concept.pptx midterm.pptx
AnthonyLota1
 
PPTX
The Advanced LinkedIn Strategies July 2025
Bruce Bennett
 
PDF
The Impact of Alpha Kappa Alpha on Economic Leadership.pdf
Jennifer Jacques
 
PDF
¡Únete al equipo de Oxigent! Empresa comprometida con la sostenibilidad y la ...
TechMeetups
 
PPTX
Plant Hormones (GAs, CK, ABA, Ethylene and 3rd Groups of Plant Hormones) .......
7300511143
 
PPTX
The LinkedIn for Your Job Search July 2025
Bruce Bennett
 
PPTX
Introduction-to-Data-Flow-Diagrams-DFDs.pptx
bineethbaby2005
 
DOCX
LESSON PLAN FOR COT 2 Nail Care 23-24.docx
JessaMosNoromor
 
PPTX
Enhanced_Career_Guidance_Presentation.pptx
truefollower1
 
PDF
Where Skills Meet Private Job Opportunities – Formwalaa.in
Reeshna Prajeesh
 
PPTX
文凭复刻澳洲电子毕业证阳光海岸大学成绩单USC录取通知书
Taqyea
 
PPTX
Enhanced_Dengue_Safety_Campaign_Singapore_2025_with_Animations.pptx
TrisTan609606
 
PPTX
High Entropy Aaaaaaaaaaaaaaaaalloys.pptx
eltohamym057
 
PDF
Opportunities in Tunnelling in India 2025_Sample Slides.pdf
VikasSingh28809
 
1.13=Symphytum=1st Term---------------------1st.pptx
zk7304860098
 
4 Team Skills under Employability Skills
bonophool banerjee
 
Mini Cultivator For Multipurpose Farming.pdf
ssuser77b53b
 
Soft skills for resume and resume match with job description.pdf
worksmart2718
 
E-MAIL ETIQUETTE_for_business_profes.ppt
WaheedZahran3
 
Guidance and counselling program service docx
HockeyApuyaAnion
 
Lea 300 Industrial security concept.pptx midterm.pptx
AnthonyLota1
 
The Advanced LinkedIn Strategies July 2025
Bruce Bennett
 
The Impact of Alpha Kappa Alpha on Economic Leadership.pdf
Jennifer Jacques
 
¡Únete al equipo de Oxigent! Empresa comprometida con la sostenibilidad y la ...
TechMeetups
 
Plant Hormones (GAs, CK, ABA, Ethylene and 3rd Groups of Plant Hormones) .......
7300511143
 
The LinkedIn for Your Job Search July 2025
Bruce Bennett
 
Introduction-to-Data-Flow-Diagrams-DFDs.pptx
bineethbaby2005
 
LESSON PLAN FOR COT 2 Nail Care 23-24.docx
JessaMosNoromor
 
Enhanced_Career_Guidance_Presentation.pptx
truefollower1
 
Where Skills Meet Private Job Opportunities – Formwalaa.in
Reeshna Prajeesh
 
文凭复刻澳洲电子毕业证阳光海岸大学成绩单USC录取通知书
Taqyea
 
Enhanced_Dengue_Safety_Campaign_Singapore_2025_with_Animations.pptx
TrisTan609606
 
High Entropy Aaaaaaaaaaaaaaaaalloys.pptx
eltohamym057
 
Opportunities in Tunnelling in India 2025_Sample Slides.pdf
VikasSingh28809
 
Ad

main.pdf java programming practice for programs

  • 1. Page 1 of 16 main.cpp 12/05/2011 23:06 /**** ELE 8050 - Computer Graphics Sebastian Krezel (29043024) Advanced Visualisation / Computer Graphics Course Work 2010/2011 The purpose of the course work is to reinforce your understanding of, and your ability to use, the OpenGL 3D graphics programming library, and the platform independent utility toolkit (the GLUT). The coursework task is: Make an interactive version of ‘the Towers of Hanoi game’ (See next page), Make the simulation using the OpenGL and GLUT libraries, and provide an elementary user interface so that the game operated from the keyboard and visualised interactively from different points of view. Write a formal report in the software engineering style outlining the key steps in designing and building the program and discuss enhancements you would like to see added to it. The basic shapes can be build using standard primitives. Try and augment the visual appearance by placing the model on a mirrored surface, possibly add shadows and/or make the material take on a coloured metallic lustre using a reflection map, and/or or use a surface image map or GPU shader to give the material the appearance of wood. Provide some animation of the moves and facilitate basic interactivity via the keyboard or mouse. (e.g. to change the viewpoint and select disks to be moved) You will need to think about your user interface design, e.g. how is the user going to choose the piece to move. You can generally find a pre-built version of the GLUT library already installed. But it may be necessary to build the library from its source code. You may also need to install a development environment, Visual Studio can be obtained through the MSDNAA. GNU-C/C++ can be obtained for Window and Unix/Linux platforms, and XCODE is free if you wish to develop on an Apple Mac If you wanted to be really really adventurous it should possible to develop a version for an iPhone or Android smart-phone platform. – using their simulators. This coursework carries 40% of the total marks for the module: ■ 15% for the report and enhancement suggestions ■ 15% for the code design, layout and annotation ■ 10% for the usability and appearance of the finished program |===3===| | | |====2====| | | |=====1=====| | | -------------------------------------------------- TOWER OF HANOI ****/ #ifdef WIN32 #include "windows.h" #else #define WORD unsigned short #define DWORD unsigned long #define LONG long // Structure - BMP file header typedef struct tagBITMAPFILEHEADER { WORD bfType; DWORD bfSize; WORD bfReserved1; WORD bfReserved2; DWORD bfOffBits; } BITMAPFILEHEADER; // Structure - BMP Info header typedef struct tagBITMAPINFOHEADER { DWORD biSize; LONG biWidth; LONG biHeight; WORD biPlanes; WORD biBitCount; DWORD biCompression; DWORD biSizeImage; LONG biXPelsPerMeter; LONG biYPelsPerMeter; DWORD biClrUsed; DWORD biClrImportant; } BITMAPINFOHEADER; #endif #if __APPLE__ /* Tested on: Mac OSX 10.6.4
  • 2. Page 2 of 16 main.cpp 12/05/2011 23:06 XcodeVersion 3.2.4 (64-bit) Component versions Xcode IDE: 1708.0 Xcode Core: 1705.0 ToolSupport: 1591.0 Built-In (GPU) Intel GMA 950: 64MB of Shared System Memory OenGL ver: 2.1 */ //Include libraries #include <stdio.h> #include <GLUT/glut.h> #include <iostream> #include <math.h> #include <string.h> #include <ctime> //PC to MAC bit conversion unsigned long pc2mac(unsigned long a){ unsigned long b; b= a & (0x000000ff) << 24; b |= a & (0x0000ff00) << 8 ; b |= a & (0x00ff0000) >> 8 ; b |= a & (0xff000000) >> 24 ; return b; } #else //Note: Other system has not been tested #include <GL/glut.h> #include <GL/gl.h> #include <GL/glu.h> #endif //Read short int from the file unsigned short readShortInt(FILE *f){ unsigned short a,b; fread((char*)&a,2,1,f); b=a&(0x00ff) << 8; b |= a&(0xff00) >> 8; return b; } //Read long int from the file unsigned long readLongInt(FILE *f){ unsigned long a,b; fread((char*)&a,4,1,f); b= a & (0x000000ff) << 24; b |= a & (0x0000ff00) << 8 ; b |= a & (0x00ff0000) >> 8 ; b |= a & (0xff000000) >> 24 ; return b; } //Loading BMP file - Use in texturing unsigned char *LoadBmp(char *fn, int *wi, int *hi){ BITMAPFILEHEADER bmfh; BITMAPINFOHEADER bmih; WORD bits; FILE *t24; unsigned char *lpBitmapBits; long imagesize,nc; // read the bitmap t24=fopen((char *)fn,"rb"); if(t24 == NULL){printf("Could not open input file [%s]n",fn); exit(0);} readShortInt(t24); bmfh.bfSize=readLongInt(t24); readShortInt(t24); readShortInt(t24); bmfh.bfOffBits=readLongInt(t24); fread((char *)&bmih,sizeof(BITMAPINFOHEADER),1,t24); if(bmih.biClrUsed != 0)nc=bmih.biClrUsed; else{ bits = bmih.biBitCount; switch (bits){ case 1: nc=2; break; case 4: nc=16; break; case 8: nc=256; break; default: nc=0; break; } } if(nc > 0) {
  • 3. Page 3 of 16 main.cpp 12/05/2011 23:06 printf("Cannot handle paletted imagen"); exit(0); } imagesize = bmfh.bfSize - bmfh.bfOffBits; printf("You have to allocate %ld n", imagesize); lpBitmapBits = (unsigned char *)malloc(imagesize); if(lpBitmapBits == NULL) { printf("Cannot allocate memoryn"); fclose(t24); exit (0); } fread((char *)lpBitmapBits,imagesize,1,t24); fclose(t24); #if __APPLE__ *wi=pc2mac(bmih.biWidth); *hi=pc2mac(bmih.biHeight); #else *wi=bmih.biWidth; *hi=bmih.biHeight; #endif return lpBitmapBits; } //Use standard namespace using namespace std; /////////////////////////////////////////////////////////// // Global variables //This size fit nice (not hiding the dock ) //on my current resolution 1280 x 800 GLint WindowWidth = 1240; //1280; GLint WindowHeight = 680; //800; //to indicate rotate angle (board, light source) GLfloat rtri = 0.0, Rlight = 0.0, rtrBoard = 0.0; //Variables used in options (menu) GLboolean menu_light = false; GLboolean menu_texture = false; GLboolean menu_solve = false; GLboolean menu_restart = false; GLboolean menu_surface = false; GLboolean menu_restart_view = false; GLboolean menu_details = false; //Indicator of intro animation GLboolean Gintro = true; //Used in displaying details GLint min_steps; GLint no_steps; //Time counter time_t tstart = time(0), tend, tcount; struct tm *current; //Buffer for string conversions char buffer [40]; //Light details GLfloat fAmbLight[] = { 0.9f, 0.9f, 0.9f, 0.0f }; GLfloat fDiffLight[] = { 1.0f, 1.0f, 1.0f, 0.0f }; GLfloat fSpecLight[] = { 0.9f, 0.9f, 0.9f, 0.0f }; GLfloat lightPos[] = {1.67f, 1.0f,-2.0f, 1.0f }; GLfloat border = 1; // used in light_move() //Texturing GLuint nTexture[7]; //Handle information about disk on each peg GLint *peg_A, *peg_B, *peg_C; //Game level, number of disk GLint no_of_disk; //Camera set up point GLfloat camera_x = 4.3, camera_y = 6, camera_z = 7.25; //Camera set up point for intro GLfloat intro_camera_x = -48.5, intro_camera_y = 20, intro_camera_z = 7.25; GLdouble posX, posY, posZ, //Handle mouse position in 3d space
  • 4. Page 4 of 16 main.cpp 12/05/2011 23:06 ghostX, ghostY; //position of animated disk (ghost disk) //Approximation of round objects const GLfloat ROUND = 30; //Hight from reflective surface GLfloat HEIGHT = 0.0f; //Details of the disk movement GLint from = 0, to = 0; //Mouse movement GLfloat moveX = 0.0; //Quadric - cylinders, spheres GLUquadricObj *IDquadric; //Mouse button is holed bool lbuttonDown = false; /////////////////////////////////////////////// // Tesselate floor void drawFloor(void) { float x, y, d = 1.0; // Draw ground. glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, nTexture[6]); glTranslatef(0.0, 0.1, 0.0); glNormal3f(0,1,0); // Tesselate floor so lighting looks more reasonable. for (x=-8; x<=7; x+=d) { glBegin(GL_QUAD_STRIP); for (y=-8; y<=8; y+=d) { glTexCoord2f(x+1, y); glVertex3f(x+1, 0, y); glTexCoord2f(x, y); glVertex3f(x, 0, y); } glEnd(); } glDisable(GL_TEXTURE_2D); } /////////////////////////////////////////////////////////// // Check if you win bool win() { int count = 0; //Calculate who many disk you have on peg_C for(int i = 0; i < no_of_disk; i++) { if (peg_C[i] == i+1) count += 1; } //If all disk are on "C" you win if (count == no_of_disk) { return true; }else return false; } /////////////////////////////////////////////////////////// // Initialize game details void init_hanoi() { //First clean up delete [] peg_A; delete [] peg_B; delete [] peg_C; //Allocate tables plus one cell to store index of the top disk peg_A = new int[no_of_disk + 1]; peg_B = new int[no_of_disk + 1]; peg_C = new int[no_of_disk + 1]; for (int i = 0; i < no_of_disk; i++) { //Put all disk at the first peg and clear others peg_A[i] = i+1; peg_B[i] = 0; peg_C[i] = 0; } //Put the proper flag at the end of the table peg_A[no_of_disk] = no_of_disk; peg_B[no_of_disk] = 0;
  • 5. Page 5 of 16 main.cpp 12/05/2011 23:06 peg_C[no_of_disk] = 0; //Init variables used in Details no_steps = 0; min_steps = pow(2, no_of_disk) - 1; if (lbuttonDown) tstart = time(0); } /////////////////////////////////////////////////////////// // Conversion between window and openGL // return the correct OpenGL coordinates from mouse coordinates void GetOGLPos(int x, int y) { GLint viewport[4]; GLdouble modelview[16]; GLdouble projection[16]; GLfloat winX, winY, winZ; glGetDoublev(GL_MODELVIEW_MATRIX, modelview); glGetDoublev(GL_PROJECTION_MATRIX, projection); glGetIntegerv(GL_VIEWPORT, viewport); winX = (float)x; winY = (float)viewport[3] - (float)y; glReadPixels(x, int(winY), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ); gluUnProject(winX, winY, winZ, modelview, projection, viewport, &posX, &posY, &posZ); } /////////////////////////////////////////////////////////// // Move peg from S-source to D-destination peg bool move_it(int *S, int *D) { int S_index, D_index; //Check if you have disk to be moved if (S[no_of_disk] == 0) { return false; } else { S_index = S[no_of_disk] - 1; //Peg is empty so we can put disk on it if ((D[no_of_disk] == 0)) { D[0] = S[S_index]; S[S_index] = 0; S[no_of_disk] -= 1; D[no_of_disk] += 1; no_steps +=1; //Count this move return true; } else D_index = D[no_of_disk]; //Check if possible to move if (S[S_index] > D[D_index - 1]) { D[D_index] = S[S_index]; S[S_index] = 0; S[no_of_disk] -= 1; D[no_of_disk] += 1; no_steps +=1; //Count this move return true; } else { //You cant put bigger on smaller return false; } } } /////////////////////////////////////////////////////////// // This function shows game details in the console // It was used for testing purposes while implementing "solve_it()" function // // Example: // // // //Test legal move between A and B Track solving steps: // if (!move_it(B, C)) { [ 3 ][ 0 ][ 1 ] // move_it(C,B); [ 0 ][ 0 ][ 2 ] // console_hanoi(A,B,C); [ 0 ][ 0 ][ 0 ] // } else console_hanoi(A,B,C); ___________________ // [ 1 ][ 0 ][ 2 ] // // currently not used to keep final code clear
  • 6. Page 6 of 16 main.cpp 12/05/2011 23:06 void console_hanoi (int *A, int *B, int *C) { cout << "Track solving steps:" << endl; //For simplicity show it up side down for (int i = 0; i < no_of_disk + 1; i++) { if (i == no_of_disk) cout << "___________________" << endl; //Display flags, number of disk on the peg cout << "[ " << A[i] << " ]" << "[ " << B[i] << " ]" << "[ " << C[i] << " ]" << endl; } cout << endl << endl; } /////////////////////////////////////////////////////////// // Function is solving the game void solve_it(int *A, int *B, int *C) { //Use iterative solution //In each case (even,odd), a total of 2n-1 moves are made. //For an even number of disks: if (no_of_disk % 2 == 0) { //make the legal move between pegs A and B if (!move_it(A,B)) move_it(B,A); //make the legal move between pegs A and C if (!move_it(A, C)) move_it(C,A); //make the legal move between pegs B and C if (!move_it(B, C)) move_it(C,B); //For odd number of disk } else { //make the legal move between pegs A and C if (!move_it(A,C)) move_it(C,A); else { //If solved just go out from this function if (win()) return; } //make the legal move between pegs A and B if (!move_it(A,B)) move_it(B,A); //make the legal move between pegs B and C if (!move_it(B,C)) move_it(C,B); } } /////////////////////////////////////////////////////////// // Draw "ghost" disk to help track user movement and improve interface void ghost_disk (GLfloat x, GLfloat y) { int index; //GLfloat h = 0; //hight position GLfloat radius = 0, r_max = 1.1; //declare radius var GLfloat r_step = 0.9 / no_of_disk; //calculate difference in radius between disks switch (from) { case 1: if (peg_A[no_of_disk] != 0) { index = peg_A[no_of_disk] -1; radius = r_max - ((peg_A[index] - 1) * r_step); radius += 0.01; //Make it a bit bigger then original } break; case 2: if (peg_B[no_of_disk] != 0) { index = peg_B[no_of_disk] -1; radius = r_max - ((peg_B[index] - 1) * r_step); radius += 0.01; //Make it a bit bigger then original } break; case 3: if (peg_C[no_of_disk] != 0) { index = peg_C[no_of_disk] -1; radius = r_max - ((peg_C[index] - 1) * r_step); radius += 0.01; //Make it a bit bigger then original } break; default: break; } //Draw the ghost disk with proper radius and place on proper height glPushMatrix(); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, nTexture[4]); glRotatef(90, 1.0f, 0.0, 0.0); glTranslatef(x, 0.0, 0.0);
  • 7. Page 7 of 16 main.cpp 12/05/2011 23:06 gluCylinder(IDquadric, radius, radius, 0.30f, ROUND, ROUND); gluDisk(IDquadric, 0.125f, radius, ROUND, ROUND); //Bottom circle of the disk - not really visible //so we don't have to draw it glDisable(GL_TEXTURE_2D); glPopMatrix(); } /////////////////////////////////////////////////////////// //Mouse button is clicked/hold... //defining drag and drop disk movement void mouse(int button, int state, int x, int y) { //Use only left mouse button to drag and drop disk if (button == GLUT_LEFT_BUTTON) { if (state == GLUT_DOWN) { lbuttonDown = true; GetOGLPos(x,y); //Check what peg you "drag" if (posX > -4.0 and posX < -1.34 and posY > 0) from = 1; //peg_A if (posX > -1.3 and posX < 1.32 and posY > 0) from = 2; //peg_B if (posX > 1.32 and posX < 4 and posY > 0) from = 3; //peg_C if (win()) { //Go to next level, Put limit of 13 disk //It fit nice on pegs if (no_of_disk < 13) no_of_disk += 1; //Initialise new level init_hanoi(); //go back to normal view - stop spinning rtri = 0; } } else { lbuttonDown = false; GetOGLPos(x,y); //If drop disk on peg A if (posX > -4.0 and posX < -1.34 and posY > 0) { to = 1; //peg_A switch (from) { case 1: break; case 2: move_it(peg_B, peg_A); break; case 3: move_it(peg_C, peg_A); break; } } //If drop disk on peg B if (posX > -1.3 and posX < 1.32 and posY > 0) { to = 2; //peg_B switch (from) { case 1: move_it(peg_A, peg_B); break; case 2: break; case 3: move_it(peg_C, peg_B); break; } } //If drop disk on peg C if (posX > 1.32 and posX < 4 and posY > 0) { to = 3; //peg_C switch (from) { case 1: move_it(peg_A, peg_C); break; case 2: move_it(peg_B, peg_C); break; case 3: break; } } } } }
  • 8. Page 8 of 16 main.cpp 12/05/2011 23:06 /////////////////////////////////////////////////////////// //Mouse motion void motion(int x, int y) { //If you hold left button and move mouse //Update position of the cursor to refresh //Animation of "ghost disk" if (lbuttonDown) { GetOGLPos(x, y); } } /////////////////////////////////////////////////////////// // Defining key action void processSpecialKeys(int key, int x, int y) { switch(key) { case GLUT_KEY_F1: menu_restart = !menu_restart; tstart = time(0); break; case GLUT_KEY_F2: //Place disks on start position Before solving //Avoid infinitive loops in iterative algorithm menu_restart = true; menu_solve = !menu_solve; break; case GLUT_KEY_F3: menu_texture = !menu_texture; break; case GLUT_KEY_F4: menu_surface = !menu_surface; break; case GLUT_KEY_F5: menu_light = !menu_light; break; case GLUT_KEY_F6: menu_restart_view = !menu_restart_view; break; case GLUT_KEY_F7: menu_details = !menu_details; break; } } /////////////////////////////////////////////////////////// // Defining key action void processNormalKeys(unsigned char key, int x, int y) { //Light settings if(key == 'q') lightPos[2] -= 0.25; if(key == 'a') lightPos[2] += 0.25; if(key == 'f') lightPos[0] += 0.25; if(key == 's') lightPos[0] -= 0.25; if(key == 'e') lightPos[1] += 0.25; if(key == 'd') lightPos[1] -= 0.25; //Camera positions if (key == 'p') camera_z -= 0.25f; if (key == ';') camera_z += 0.25f; if (key == 'o') //Don't go to low //don't show whats under the board if (camera_y > 0.5) camera_y -= 0.5f; if (key == 'l') camera_y += 0.25f; if (key == 'i') camera_x -= 0.25f; if (key == 'k') camera_x += 0.25f; if(key == 27) exit(0); // Refresh the Window glutPostRedisplay(); } /////////////////////////////////////////////////////////////////////////////// // Reset flags as appropriate in response to menu selections void ProcessMenu(int value) { switch(value) { case 1: menu_restart = !menu_restart; tstart = time(0); break; case 2: //Place disks on start position Before solving //Avoid infinitive loops in iterative algorithm
  • 9. Page 9 of 16 main.cpp 12/05/2011 23:06 menu_restart = true; menu_solve = !menu_solve; break; case 3: menu_texture = !menu_texture; break; case 4: menu_surface = !menu_surface; break; case 5: menu_light = !menu_light; break; case 6: menu_restart_view = !menu_restart_view; break; case 7: menu_details = !menu_details; break; default: break; } glutPostRedisplay(); } /////////////////////////////////////////////////////////////////////////////// //process submenu - chose number of disk on board void num_disk(int value) { no_of_disk = value; //Initialise with new number init_hanoi(); tstart = time(0); glutPostRedisplay(); } /////////////////////////////////////////////////////////// // Called to clean quadric void cleanupQuadric(void) { gluDeleteQuadric(IDquadric); cout << "cleanupQuadric completed" << endl; } /////////////////////////////////////////////////////////// // Called to clean up arrays void cleanupArrays(void) { delete [] peg_A; delete [] peg_B; delete [] peg_C; peg_A = NULL; peg_B = NULL; peg_C = NULL; cout << "cleanupArray completed" << endl; } /////////////////////////////////////////////////////////// // Called to draw a mirrored surface void Surface() { glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, nTexture[1]); glBegin(GL_POLYGON); glNormal3f(0.0, 1.0, 0.0); glTexCoord2f(1.0f, 1.0f); glVertex3f( 8.0f, 0.15f,-8.0f); // Top Right Of The Quad (Top) glTexCoord2f(0.0f, 1.0f); glVertex3f(-8.0f, 0.15f,-8.0f); // Top Left Of The Quad (Top) glTexCoord2f(0.0f, 0.0f); glVertex3f(-8.0f, 0.15f, 8.0f); // Bottom Left Of The Quad (Top) glTexCoord2f(1.0f, 0.0f); glVertex3f( 8.0f, 0.15f, 8.0f); // Bottom Right Of The Quad (Top) glEnd(); glDisable(GL_TEXTURE_2D); } /////////////////////////////////////////////////////////// // Called to draw disk // Depends of parameter type it draws disk with different textures void draw_disk (GLfloat radius, GLfloat x, GLfloat h, GLboolean type) { //Rough wood looking disks //Use two different textures if (type) { glPushMatrix();
  • 10. Page 10 of 16 main.cpp 12/05/2011 23:06 glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, nTexture[4]); glRotatef(90, 1.0f, 0.0, 0.0); glTranslatef(x, 0.0, -h -0.6); //Main part of the disk gluCylinder(IDquadric,radius,radius,0.30f,ROUND, ROUND); glDisable(GL_TEXTURE_2D); //Top cover of the disk glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, nTexture[3]); gluDisk(IDquadric,0.125f,radius,ROUND,ROUND); //Bottom circle of the disk - not really visible //so we don't have to draw it glDisable(GL_TEXTURE_2D); glPopMatrix(); //Use one texture for drawing } else { glPushMatrix(); glRotatef(90, 1.0f, 0.0, 0.0); glTranslatef(x, 0.0, -h -0.4); //Main part of the disk glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, nTexture[0]); gluCylinder(IDquadric,radius,radius,0.30f,ROUND, ROUND); gluDisk(IDquadric, 0.125f, radius, ROUND, ROUND); //Bottom not visible glDisable(GL_TEXTURE_2D); glPopMatrix(); } } /////////////////////////////////////////////////////////// // Called to draw peg void draw_peg(GLfloat x) { glEnable(GL_TEXTURE_2D); if (menu_texture) glBindTexture(GL_TEXTURE_2D, nTexture[5]); else glBindTexture(GL_TEXTURE_2D, nTexture[0]); glPushMatrix(); glTranslatef(x,0,0); glRotatef(270.0, 1.0f, 0.0f, 0.0f); gluCylinder(IDquadric, 0.15f, //base radius 0.1f, //top radius 4.0f, //height ROUND, //approximation ROUND //... ); glTranslatef(0,0,4); gluSphere(IDquadric,0.1f,ROUND,ROUND); glPopMatrix(); glDisable(GL_TEXTURE_2D); } /////////////////////////////////////////////////////////// // Called to draw game board void draw_board() { glEnable(GL_TEXTURE_2D); if (menu_texture) glBindTexture(GL_TEXTURE_2D, nTexture[5]); else glBindTexture(GL_TEXTURE_2D, nTexture[0]); glBegin(GL_QUADS); // Start Drawing Hanoi board glNormal3f(0.0, 1.0, 0.0); //Use to point proper sides for lighting glTexCoord2f(1.0f, 1.0f); glVertex3f( 4.0f, 0.15f,-2.0f); // Top Right Of The Quad (Top) glTexCoord2f(0.0f, 1.0f); glVertex3f(-4.0f, 0.15f,-2.0f); // Top Left Of The Quad (Top) glTexCoord2f(0.0f, 0.0f); glVertex3f(-4.0f, 0.15f, 2.0f); // Bottom Left Of The Quad (Top) glTexCoord2f(1.0f, 0.0f); glVertex3f( 4.0f, 0.15f, 2.0f); // Bottom Right Of The Quad (Top) glNormal3f(0.0, -1.0, 0.0); glTexCoord2f(1.0f, 1.0f); glVertex3f( 4.0f,-0.15f, 2.0f); // Top Right Of The Quad (Bottom) glTexCoord2f(0.0f, 1.0f); glVertex3f(-4.0f,-0.15f, 2.0f); // Top Left Of The Quad (Bottom) glTexCoord2f(0.0f, 0.0f); glVertex3f(-4.0f,-0.15f,-2.0f); // Bottom Left Of The Quad (Bottom) glTexCoord2f(1.0f, 0.0f); glVertex3f( 4.0f,-0.15f,-2.0f); // Bottom Right Of The Quad (Bottom) glNormal3f(0.0, 0.0, 1.0); glTexCoord2f(0.0f, 0.0f); glVertex3f( 4.0f, 0.15f, 2.0f); // Top Right Of The Quad (Front)
  • 11. Page 11 of 16 main.cpp 12/05/2011 23:06 glTexCoord2f(1.0f, 0.0f); glVertex3f(-4.0f, 0.15f, 2.0f); // Top Left Of The Quad (Front) glTexCoord2f(1.0f, 1.0f); glVertex3f(-4.0f,-0.15f, 2.0f); // Bottom Left Of The Quad (Front) glTexCoord2f(0.0f, 1.0f); glVertex3f( 4.0f,-0.15f, 2.0f); // Bottom Right Of The Quad (Front) glNormal3f(0.0, 0.0, -1.0); glTexCoord2f(1.0f, 0.0f); glVertex3f( 4.0f,-0.15f,-2.0f); // Bottom Left Of The Quad (Back) glTexCoord2f(1.0f, 1.0f); glVertex3f(-4.0f,-0.15f,-2.0f); // Bottom Right Of The Quad (Back) glTexCoord2f(0.0f, 1.0f); glVertex3f(-4.0f, 0.15f,-2.0f); // Top Right Of The Quad (Back) glTexCoord2f(0.0f, 0.0f); glVertex3f( 4.0f, 0.15f,-2.0f); // Top Left Of The Quad (Back) glNormal3f(-1.0, 0.0, 0.0); glTexCoord2f(0.0f, 0.0f); glVertex3f(-4.0f, 0.15f, 2.0f); // Top Right Of The Quad (Left) glTexCoord2f(1.0f, 0.0f); glVertex3f(-4.0f, 0.15f,-2.0f); // Top Left Of The Quad (Left) glTexCoord2f(1.0f, 1.0f); glVertex3f(-4.0f,-0.15f,-2.0f); // Bottom Left Of The Quad (Left) glTexCoord2f(0.0f, 1.0f); glVertex3f(-4.0f,-0.15f, 2.0f); // Bottom Right Of The Quad (Left) glNormal3f(1.0, 0.0, 0.0); glTexCoord2f(1.0f, 0.0f); glVertex3f( 4.0f, 0.15f,-2.0f); // Top Right Of The Quad (Right) glTexCoord2f(1.0f, 1.0f); glVertex3f( 4.0f, 0.15f, 2.0f); // Top Left Of The Quad (Right) glTexCoord2f(0.0f, 1.0f); glVertex3f( 4.0f,-0.15f, 2.0f); // Bottom Left Of The Quad (Right) glTexCoord2f(0.0f, 0.0f); glVertex3f( 4.0f,-0.15f,-2.0f); // Bottom Right Of The Quad (Right) glEnd(); // Done Drawing glDisable(GL_TEXTURE_2D); } /////////////////////////////////////////////////////////// //Functions draws all disks in the game radius depends of numbers //of disk in the game void draw_all_disks () { GLfloat h = 0; //hight position GLfloat r, r_max = 1.1; //declare radius var GLfloat r_step = 0.9 / no_of_disk; //calculate difference in radius between disks for (int i = 0; i < no_of_disk; i++) { //draw on peg A if (peg_A[i] != 0) { //Calculate radius of the disk r = r_max - ((peg_A[i] - 1) * r_step); draw_disk (r, -2.5, h, menu_texture); } //draw on peg B if (peg_B[i] != 0) { //Calculate radius of the disk r = r_max - ((peg_B[i] - 1) * r_step); draw_disk (r, 0.0, h, menu_texture); } //draw on peg C if (peg_C[i] != 0) { //Calculate radius of the disk r = r_max - ((peg_C[i] - 1) * r_step); draw_disk (r, 2.5, h, menu_texture); } h += 0.3; //Move it up } } /////////////////////////////////////////////////////////// //Function draw light source //on the scene void Draw_Light_Source () { glPushMatrix(); glTranslatef(lightPos[0], lightPos[1], lightPos[2]); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, nTexture[2]); glPushMatrix(); glRotatef(Rlight, 1.0, 1.0, 1.0); gluSphere(IDquadric,0.15f,ROUND,ROUND); glPopMatrix(); glDisable(GL_TEXTURE_2D); glPopMatrix(); } ////////////////////////////////////////////////////////////////////////// // To move light stripe slowly void light_move() { //Move just on y and z axis lightPos[1] = 8.5; lightPos[2] = -15.75; //Set up range of movement if (border == 1) {
  • 12. Page 12 of 16 main.cpp 12/05/2011 23:06 lightPos[0] += 0.1; if (lightPos[0] > 20.0) border = 0; } else { lightPos[0] -= 0.1; if (lightPos[0] < -20.0) border = 1; } } /////////////////////////////////////////////////////////// //Function combine all objets that have to be draw void Draw_Hanoi () { glPushMatrix(); draw_board(); //main board draw_peg(0); //first stick draw_peg(-2.5); //second stick draw_peg(2.5); //third stick draw_all_disks(); //draw disks glPopMatrix(); } /////////////////////////////////////////////////////////////////// //Function calculate camera position for intro animation purpose bool intro() { if (intro_camera_x < 3.5) intro_camera_x += 0.8; //camera_x = -48.5, if (intro_camera_y > 6) { intro_camera_y -= 0.15; return true; } else return false; } /////////////////////////////////////////////////////////////////// //Function Display the text (r,g,b colours) on "viewing plane" void DrawText(GLint x, GLint y, char* s, GLfloat r, GLfloat g, GLfloat b) { int lines; char* p; glDisable(GL_LIGHTING); //To get proper colour glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); //Change to Ortho glOrtho(0.0, glutGet(GLUT_WINDOW_WIDTH), 0.0, glutGet(GLUT_WINDOW_HEIGHT), -1.0, 1.0); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glColor3f(r,g,b); glRasterPos2i(x, y); for(p = s, lines = 0; *p; p++) { if (*p == 'n') { lines++; glRasterPos2i(x, y-(lines*18)); } glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, *p); } glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glEnable(GL_LIGHTING); //Turn it back } /////////////////////////////////////////////////////////// // Called to draw scene void RenderScene(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glLoadIdentity(); //Re-set the view glEnable(GL_NORMALIZE); glLightfv(GL_LIGHT0, GL_POSITION, lightPos); //If flag is set up show light source if (menu_light) Draw_Light_Source(); if (!intro())
  • 13. Page 13 of 16 main.cpp 12/05/2011 23:06 gluLookAt(camera_x, camera_y, camera_z, // look from camera XYZ 0, 0, 0, // look at the origin 0, 1, 0 // positive Y up vector ); else gluLookAt(intro_camera_x, intro_camera_y, intro_camera_z, 0, 0, 0, 0, 1, 0); glScaled(1.1, 1.1, 1.1); //Make it a bit bigger glRotatef(rtri,0.0f,1.0f,0.0f); //Rotate if Win Draw_Hanoi(); //Draw board with disks if (menu_surface) HEIGHT = 0.2; else HEIGHT = 0; glTranslatef(0.0f, -HEIGHT-0.3, 0.0f); //Place on surface glEnable(GL_STENCIL_TEST); //Enable using the stencil buffer glColorMask(0, 0, 0, 0); //Disable drawing colours to the screen glDisable(GL_DEPTH_TEST); //Disable depth testing glStencilFunc(GL_ALWAYS, 1, 1); //Make the stencil test always pass //Make pixels in the stencil buffer be set to 1 when the stencil test passes glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); //Set all of the pixels covered by the floor to be 1 in the stencil buffer //Draw mirrored plane if (menu_surface) drawFloor(); else Surface(); glColorMask(1, 1, 1, 1); //Enable drawing colours to the screen glEnable(GL_DEPTH_TEST); //Enable depth testing //Make the stencil test pass only when the pixel is 1 in the stencil buffer glStencilFunc(GL_EQUAL, 1, 1); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); //Make the stencil buffer not change //Draw Game board, reflected vertically, at all pixels where the stencil buffer is 1 glPushMatrix(); glScalef(1, -1, 1); glTranslatef(0, HEIGHT, 0); Draw_Hanoi(); glPopMatrix(); glDisable(GL_STENCIL_TEST); //Disable stencil buffer //Blend the floor onto the screen glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); glColor4f(1, 1, 1, 0.9f); //Draw mirrored plane if (menu_surface) drawFloor(); else Surface(); glDisable(GL_BLEND); //If left button is pressed render move tracking disk if (lbuttonDown) { glPushMatrix(); glEnable (GL_BLEND); glDepthMask (GL_FALSE); glBlendFunc (GL_SRC_ALPHA, GL_ONE); //Move if you point the game board if (posX > -4 && posX < 4) { if (posZ > -2 && posZ < 2) { glTranslatef(posX, 1.0, posZ); glColor4f(1, 1, 1, 0.5f); ghost_disk(0.0, 4.0); } } glDepthMask (GL_TRUE); glDisable (GL_BLEND); glPopMatrix(); } //If you win display a message if (win()) { char tmp[50] = "You Solve it, Click to Next Level"; DrawText((glutGet(GLUT_WINDOW_WIDTH) /2) - 140, glutGet(GLUT_WINDOW_HEIGHT) /2, tmp, 1.0, 1.0, 1.0); } //If required display dame details if (menu_details) { sprintf(buffer, "Number of disks = %d", no_of_disk); DrawText(20, glutGet(GLUT_WINDOW_HEIGHT) -30, buffer, 0.56, 0.34, 0.05); sprintf(buffer, "Minimum to solve = %d", min_steps); DrawText(20, glutGet(GLUT_WINDOW_HEIGHT) -50, buffer, 0.56, 0.34, 0.05); sprintf(buffer, "Your moves: %d", no_steps); DrawText(20, glutGet(GLUT_WINDOW_HEIGHT) -70, buffer, 0.56, 0.34, 0.05);
  • 14. Page 14 of 16 main.cpp 12/05/2011 23:06 //Display time current = localtime(&tcount); sprintf(buffer, "Time: %02d:%02d:%02dn", current->tm_hour, current->tm_min, current->tm_sec); DrawText(20, glutGet(GLUT_WINDOW_HEIGHT) -90, buffer, 0.56, 0.34, 0.05); } glColor3f(1.0, 1.0, 10.0); glutSwapBuffers(); } ////////////////////////////////////////////////////////////////////////// // Change viewing volume and viewport. Called when window is resized void ChangeSize(int w, int h) { GLfloat fAspect; // Prevent a divide by zero if(h == 0) h = 1; // Set Viewport to window dimensions glViewport(0, 0, w, h); fAspect = (GLfloat)w/(GLfloat)h; // Reset coordinate system glMatrixMode(GL_PROJECTION); glLoadIdentity(); // Produce the perspective projection gluPerspective(60.0f, fAspect, 1.0, 400.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } /////////////////////////////////////////////////////////// // Called by GLUT library when idle void TimerFunction(int value) { //If you show light object it will spin Rlight +=1.2f; //If you win current level board will spin until mouse button pressed if (win()) { rtri+=1.2f; menu_solve = false; lightPos[0] = 0.42; lightPos[1] = 9.75; lightPos[2] = -22; } //If chose run light movement if (menu_surface) light_move(); //If chose solve puzzles if (menu_solve) solve_it(peg_A, peg_B, peg_C); //If restart level if (menu_restart) { init_hanoi(); menu_restart = !menu_restart; } //Restart view if (menu_restart_view) { camera_x = 4.3; camera_y = 6; camera_z = 7.25; menu_restart_view = !menu_restart_view; } if (!win()) tend = time(0); tcount = difftime(tend, tstart); //Redraw the scene with new coordinates glutPostRedisplay(); glutTimerFunc(1,TimerFunction, 1); } /////////////////////////////////////////////////////////// // Setting up texture void SetupTexture (char *name, int nT) { unsigned char *pix; GLint w,h; glBindTexture(GL_TEXTURE_2D, nT);
  • 15. Page 15 of 16 main.cpp 12/05/2011 23:06 pix = LoadBmp(name,&w,&h); glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, pix); free(pix); pix = NULL; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); } /////////////////////////////////////////////////////////// // Setup the rendering state void SetupRC(void) { char tmp[50]; glShadeModel(GL_SMOOTH); //Enables Smooth Shading glClearColor(0.0f, 0.0f, 0.0f, 0.0f); //Background IDquadric=gluNewQuadric(); //Create A Pointer To The Quadric Object gluQuadricNormals(IDquadric, GLU_SMOOTH); //Create Smooth Normals gluQuadricTexture(IDquadric, GL_TRUE); //Create Texture Coords no_of_disk = 3; //Game start level init_hanoi(); //Initialize data glClearDepth(1.0f); //Depth Buffer Setup glEnable(GL_DEPTH_TEST); //Enables Depth Testing glDepthFunc(GL_LEQUAL); //The Type Of Depth Test To Do // Set up lighting glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_COLOR_MATERIAL); glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); glMaterialfv(GL_FRONT, GL_SPECULAR, fDiffLight); glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, 64); //Set up blending function glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glLightfv(GL_LIGHT0, GL_AMBIENT, fAmbLight); glLightfv(GL_LIGHT0, GL_DIFFUSE, fDiffLight); glLightfv(GL_LIGHT0, GL_SPECULAR, fSpecLight); glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); //Perspective Calculations glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); //Texturing glEnable(GL_TEXTURE_2D); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glGenTextures(6, nTexture); //Prepare all textures for use //To avoid conversion warning use strcpy strcpy (tmp,"tex1.bmp"); SetupTexture(tmp, nTexture[0]); strcpy (tmp,"tex2.bmp"); SetupTexture(tmp, nTexture[1]); strcpy (tmp,"tex3.bmp"); SetupTexture(tmp, nTexture[2]); strcpy (tmp,"tex4.bmp"); SetupTexture(tmp, nTexture[3]); strcpy (tmp,"tex5.bmp"); SetupTexture(tmp, nTexture[4]); strcpy (tmp,"tex6.bmp"); SetupTexture(tmp, nTexture[5]); strcpy (tmp,"tex7.bmp"); SetupTexture(tmp, nTexture[6]); //Clean up at exit atexit(cleanupQuadric); atexit(cleanupArrays); } /////////////////////////////////////////////////////////// // Main program entry point int main(int argc, char* argv[]) { GLint sub; glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH); glutInitWindowSize(WindowWidth, WindowHeight); glutInitWindowPosition(0, 0); //Place window on left top corner glutCreateWindow("Tower of Hanoi - Sebastian Krezel - Courswork"); //No of disk - sub menu sub = glutCreateMenu(num_disk); glutAddMenuEntry("3", 3); glutAddMenuEntry("4", 4); glutAddMenuEntry("5", 5); glutAddMenuEntry("6", 6);
  • 16. Page 16 of 16 main.cpp 12/05/2011 23:06 glutAddMenuEntry("7", 7); glutAddMenuEntry("8", 8); glutAddMenuEntry("9", 9); glutAddMenuEntry("10", 10); glutAddMenuEntry("11", 11); glutAddMenuEntry("12", 12); glutAddMenuEntry("13", 13); //Create the Menu glutCreateMenu(ProcessMenu); glutAddMenuEntry("Restart this level" ,1); glutAddSubMenu("Pick-up no of disk" ,sub); glutAddMenuEntry("Solve it for me!" ,2); glutAddMenuEntry("Change Textures" ,3); glutAddMenuEntry("Change Surface and Light",4); glutAddMenuEntry("Show Light Opject" ,5); glutAddMenuEntry("Restart view" ,6); glutAddMenuEntry("Show details" ,7); glutAttachMenu(GLUT_RIGHT_BUTTON); SetupRC(); glutReshapeFunc(ChangeSize); glutDisplayFunc(RenderScene); //Keyboard controls glutKeyboardFunc(processNormalKeys); glutSpecialFunc(processSpecialKeys); //Mouse controls glutMouseFunc(mouse); glutMotionFunc(motion); glutTimerFunc(33, TimerFunction, 1); glutMainLoop(); return 0; }