Skip to content

Instantly share code, notes, and snippets.

@aleks-mariusz
Last active August 29, 2015 14:00
Show Gist options
  • Save aleks-mariusz/34ac97891fcf53db1e62 to your computer and use it in GitHub Desktop.
Save aleks-mariusz/34ac97891fcf53db1e62 to your computer and use it in GitHub Desktop.
May 2 2001 - Another sample of coursework i did for a class on OpenGL using C++ (circa 2001). Neither of these i can say i know like the back of my hand, but at least one can say i'm familiar with the fundamental concepts :-) I definitely had a new found appreciation after this piece for experts on either!
/*
** Alex Koralewski
** 0019480
** Assignment 4
**
** Written with a 2-button mouse in mind when dealing with menu requirement.
**
** Please note, due to linked list usage, the vertex/edge/triangle linked lists
** store the information backwards from what was read; therefore, the normal
** vectors are negated to compensate.
*/
#include <stdlib.h> // for various C goodies
#include <iostream.h> // for c++ i/o
#include <fstream.h> // for file manipulation
#include <math.h> // for mathematical functions (sqrt comes to mind)
#include <assert.h> // for assert()
#include <gl/glut.h> // for all gl_ glu_ and glut_ functions
#define XOFFSET 50 // window offset from left of screen
#define YOFFSET 50 // window offset from top of screen
#define WINDOW_WIDTH 500 // window width
#define WINDOW_HEIGHT 500 // window height
#define IMAGE_WIDTH 64
#define IMAGE_HEIGHT 64
#define LEG1_X -1 // first leg of cycle
#define LEG1_Z -4
#define LEG2_X 3 // second leg of cycle
#define LEG2_Z -3
#define LEG3_X 1 // starting leg of cycle
#define LEG3_Z 4
// menu identifiers
#define MENU_DEFAULT_VIEW 1
#define MENU_NO_HSR 4
#define MENU_HSR 5
#define MENU_SHADE_FLAT 8
#define MENU_SHADE_TVN 9
#define MENU_SHADE_AVN 10
#define MENU_LIGHT_SPOT 16
#define MENU_LIGHT_POINT 17
#define MENU_NO_FOG 32
#define MENU_FOG_LINEAR 33
#define MENU_FOG_EXP 34
#define MENU_FOG_EXP2 35
#define MENU_QUIT 64
#define SHADE_FLAT 128
#define SHADE_AVG_VERTEX 129
#define SHADE_TRUE_VERTEX 130
#define NUM_VERTEX 3 // number of vertexes a triangle SHOULD have!
#define ROLL_SPEED 0.0030 // this is a weird number found through experimentation,
// that controls the speed of rolling, higher == faster
// 0.002 rolls fairly fast on my AMD 1.333 GHZ cpu,
// adjust for your CPU accordingly..
struct triangleNode; // forward declaration of triangleNode to be used in triangleNodeList
struct triangleNodeList { // will contains a list of triangles that belong to a vertex or edge
triangleNode *triangle;
triangleNodeList *nxt;
};
struct vertexNode { // vertex data will be loaded into this linked list of vertexes
GLfloat x;
GLfloat y;
GLfloat z;
// the average-normal vector subcomponents for this vertex
GLfloat normalX;
GLfloat normalY;
GLfloat normalZ;
triangleNodeList *myTriangles;
vertexNode *nxt;
};
struct edgeNode { // edge data will be calculated based on vertex data loaded
vertexNode *vertex0;
vertexNode *vertex1;
triangleNodeList *myTriangles;
edgeNode *nxt;
};
struct triangleNode { // triangle information will be interpolated based on vertex/edge data
vertexNode *vertex0;
vertexNode *vertex1;
vertexNode *vertex2;
// the normal vector subcomponents for this triangle
GLfloat normalX;
GLfloat normalY;
GLfloat normalZ;
triangleNode *nxt;
};
vertexNode *enteredVertexes = NULL; //linked list containing vertexes loaded (initially empty)
edgeNode *enteredEdges = NULL; //linked list containing edges calculated
triangleNode *enteredTriangles = NULL; //linked list containing triangles interpolated
//from vertex data
static GLfloat myMatrix[16]; //viewing matrix that will be used to HSR algorithm
GLubyte Image[IMAGE_HEIGHT][IMAGE_WIDTH][4];
GLuint Texture;
GLfloat noMaterialMatrix[] = {0, 0, 0, 1};
GLfloat floorMaterialMatrix[] = {0, 1, 0};
GLfloat sphereMaterialMatrix[] = {1, 0.84, 0};
GLfloat fogColor[] = {0.7, 0.7, 0.7, 0.5};
static GLfloat transX, transY, transZ, //amount to translate sphere
startX, startZ, //starting position of leg component
theta, rotateX, rotateZ, //amount to rotate sphere & on what axis
vRefPtX, vRefPtY, vRefPtZ, //reference point viewing coordinates
viewingX, viewingY, viewingZ; //transformable viewing coordinates
//state variables
static GLint hasStarted, // if prog has been started
isStopped, // if sphere is not rolling
useHSR, // whether to use hidden surface removal
useShading, // whether to use shading at all
vertexMode, // which vertex normals to use, actual or averaged
useSpotLight,// whether to use a spot light or not
fogMode, // type of fog
legOfCycle; // which leg of the trip the sphere is on
void varInit() {
// initialize variables at beginning of program
glClearColor(0.529, 0.807, 0.92, 0.0);
transX = LEG3_X, transY = 1.0, transZ = LEG3_Z,
startX = LEG3_X, startZ = LEG3_Z,
vRefPtX = 7, vRefPtY = 3,vRefPtZ = -10,
theta = 0, rotateX = 0,rotateZ = 0;
hasStarted = 0, isStopped = 1,useHSR = 0,
vertexMode = SHADE_FLAT,
useShading = 1, useSpotLight = 0, legOfCycle = 1;
glEnable(GL_DEPTH_TEST);
}
void setLightCutOff() {
if (useSpotLight)
glLightf(GL_LIGHT1, GL_SPOT_CUTOFF, 20);
else
glLightf(GL_LIGHT1, GL_SPOT_CUTOFF, 180);
}
void lightsInit() {
GLfloat globalAmbience[] = {1.0, 1.0, 1.0, 1};
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, globalAmbience);
glEnable(GL_LIGHT0);
GLfloat light1Ambience[] = {0.0, 0.0, 0.0, 1};
GLfloat light1Diffuse[] = {1.0, 1.0, 1.0, 1};
GLfloat light1Specular[] = {1.0, 1.0, 1.0, 1};
GLfloat light1Position[] = {-14.0, 12.0, -3.0, 1};
GLfloat light1Direction[] = {8, -12, -1};
glLightfv(GL_LIGHT1, GL_AMBIENT, light1Ambience);
glLightfv(GL_LIGHT1, GL_DIFFUSE, light1Diffuse);
glLightfv(GL_LIGHT1, GL_SPECULAR, light1Specular);
glLightfv(GL_LIGHT1, GL_POSITION, light1Position);
glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, light1Direction);
glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, 2.0);
glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, 0.01);
glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, 0.001);
glLightf(GL_LIGHT1, GL_SPOT_EXPONENT, 5);
setLightCutOff();
glEnable(GL_LIGHT1);
}
void imageInit(void) {
int i, j, c;
/* --- generate checkerboard image to the image array ---*/
for (i = 0; i < IMAGE_HEIGHT; i++)
for (j = 0; j < IMAGE_HEIGHT; j++)
{
c = (((i & 0x8) == 0) ^ ((j & 0x8) == 0));
if (c == 1) /* white */
{
c = 255;
Image[i][j][0] = (GLubyte) c;
Image[i][j][1] = (GLubyte) c;
Image[i][j][2] = (GLubyte) c;
}
else /* green */
{
Image[i][j][0] = (GLubyte) 0;
Image[i][j][1] = (GLubyte) 150;
Image[i][j][2] = (GLubyte) 0;
}
Image[i][j][3] = (GLubyte) 255;
}
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glGenTextures(1, &Texture);
glBindTexture(GL_TEXTURE_2D, Texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, IMAGE_WIDTH, IMAGE_HEIGHT,
0, GL_RGBA, GL_UNSIGNED_BYTE, Image);
} /* end function */
// calculate the dot product of two vectors, given by their components
inline GLdouble calcDotProduct(GLdouble x1, GLdouble y1, GLdouble z1,
GLdouble x2, GLdouble y2, GLdouble z2) {
return ((x1 * x2) + (y1 * y2) + (z1 * z2));
}
void resetFog() {
glFogi(GL_FOG_MODE, fogMode);
glFogf(GL_FOG_START, 0.1);
glFogf(GL_FOG_END, 18.0);
glFogf(GL_FOG_DENSITY, 0.09);
glFogfv(GL_FOG_COLOR, fogColor);
}
// draw the sphere onto the screen
void drawSphere() {
glColor3f(1.0, 0.84, 0.0); // specify color of line/triangles to draw
if (useShading) {
glEnable(GL_LIGHTING); // enable lighting on this object
glEnable(GL_CULL_FACE); // enable culling of faces (to not draw uncessary ones)
glFrontFace(GL_CW); // set the face ordering to be clockwise (read top comments)
glCullFace(GL_BACK); // set to cull back facing triangles
glMaterialf(GL_FRONT, GL_SHININESS, 125);
glMaterialfv(GL_FRONT, GL_AMBIENT, noMaterialMatrix);
glMaterialfv(GL_FRONT, GL_DIFFUSE, sphereMaterialMatrix);
glMaterialfv(GL_FRONT, GL_SPECULAR, sphereMaterialMatrix);
glMaterialfv(GL_FRONT, GL_EMISSION, noMaterialMatrix);
glMaterialf(GL_FRONT, GL_SHININESS, 125);
triangleNode *currTriangle = enteredTriangles;
glBegin(GL_TRIANGLES);
if (vertexMode == SHADE_FLAT) {
while (currTriangle != NULL) {
// here we specify one normal for the entire triangle
glNormal3f(currTriangle->normalX,
currTriangle->normalY,
currTriangle->normalZ);
glVertex3f(currTriangle->vertex0->x,
currTriangle->vertex0->y,
currTriangle->vertex0->z);
glVertex3f(currTriangle->vertex1->x,
currTriangle->vertex1->y,
currTriangle->vertex1->z);
glVertex3f(currTriangle->vertex2->x,
currTriangle->vertex2->y,
currTriangle->vertex2->z);
currTriangle = currTriangle->nxt;
}
} else if (vertexMode == SHADE_AVG_VERTEX) {
while (currTriangle != NULL) {
// here we specify an averaged vertex normal for each vertex
glNormal3f(currTriangle->vertex0->normalX,
currTriangle->vertex0->normalY,
currTriangle->vertex0->normalZ);
glVertex3f(currTriangle->vertex0->x,
currTriangle->vertex0->y,
currTriangle->vertex0->z);
glNormal3f(currTriangle->vertex1->normalX,
currTriangle->vertex1->normalY,
currTriangle->vertex1->normalZ);
glVertex3f(currTriangle->vertex1->x,
currTriangle->vertex1->y,
currTriangle->vertex1->z);
glNormal3f(currTriangle->vertex2->normalX,
currTriangle->vertex2->normalY,
currTriangle->vertex2->normalZ);
glVertex3f(currTriangle->vertex2->x,
currTriangle->vertex2->y,
currTriangle->vertex2->z);
currTriangle = currTriangle->nxt;
}
} else if (vertexMode == SHADE_TRUE_VERTEX) {
while (currTriangle != NULL) {
// here we specify the true triangle normal for each vertex
glNormal3f(currTriangle->normalX,
currTriangle->normalY,
currTriangle->normalZ);
glVertex3f(currTriangle->vertex0->x,
currTriangle->vertex0->y,
currTriangle->vertex0->z);
glNormal3f(currTriangle->normalX,
currTriangle->normalY,
currTriangle->normalZ);
glVertex3f(currTriangle->vertex1->x,
currTriangle->vertex1->y,
currTriangle->vertex1->z);
glNormal3f(currTriangle->normalX,
currTriangle->normalY,
currTriangle->normalZ);
glVertex3f(currTriangle->vertex2->x,
currTriangle->vertex2->y,
currTriangle->vertex2->z);
currTriangle = currTriangle->nxt;
}
}
glEnd ();
glDisable(GL_CULL_FACE);
glDisable(GL_LIGHTING);
} else { // we're drawing wireframe
edgeNode *currEdge = enteredEdges; // use the entered edge list
glBegin(GL_LINES);
while (currEdge != NULL) { // loop through all edges
// if using Hidden Surface Removal, and neither of the edge's triangles are visible..
// note the negated normals, read top comments for more information
if (useHSR && calcDotProduct(-currEdge->myTriangles->triangle->normalX,
-currEdge->myTriangles->triangle->normalY,
-currEdge->myTriangles->triangle->normalZ,
viewingX, viewingY, viewingZ) >= 0 &&
calcDotProduct(-currEdge->myTriangles->nxt->triangle->normalX,
-currEdge->myTriangles->nxt->triangle->normalY,
-currEdge->myTriangles->nxt->triangle->normalZ,
viewingX, viewingY, viewingZ) >= 0) {
currEdge = currEdge->nxt; // traverse to the next edge..
continue; // and skip the drawing draw
} else { // draw all wireframes
// draw the line for the current edge based on its two vertexes
glVertex3f(currEdge->vertex0->x, currEdge->vertex0->y, currEdge->vertex0->z);
glVertex3f(currEdge->vertex1->x, currEdge->vertex1->y, currEdge->vertex1->z);
currEdge = currEdge->nxt; // linked list traversal
}
} // done drawing all edges
glEnd();
}
}
void setupRotationParams(GLfloat x1, GLfloat z1, GLfloat x2, GLfloat z2, GLint legOfCycle) {
// modify the state variables that determine the amount to rotate, translate and on which vector
GLfloat moveX = (x2 - x1) * ROLL_SPEED, // sphere moved this amount on this iteration
moveZ = (z2 - z1) * ROLL_SPEED;
transX += moveX, transZ += moveZ;// add the moved amount to the current amount
GLfloat distance = sqrt (moveX * moveX + moveZ * moveZ); // determine distance
if (legOfCycle == 3) distance = -distance; // negate distance if back at starting point
theta += distance * 180 / 3.14; // determine angle of rotation based on distance moved
if (theta >= 360) theta -= 360; // if theta overflow, correct
rotateX = 1.0 / (x2 - x1); // determine rotational axis vector
rotateZ = -1.0 / (z2 - z1);
glutPostRedisplay(); // re-draw
}
void animateRotatingSphere() {
// sphere has rolled passed limits of the first leg
if (transX < LEG1_X && transZ < LEG1_Z && legOfCycle == 1) {
legOfCycle = 2;
startX = transX;
startZ = transZ;
}
// sphere has rolled passed limits of second leg
else if (transX > LEG2_X && transZ > LEG2_Z && legOfCycle == 2) {
legOfCycle = 3;
startX = transX;
startZ = transZ;
}
// sphere has rolled passed limits of last leg
else if (transX < LEG3_X && transZ > LEG3_Z && legOfCycle == 3) {
legOfCycle = 1;
startX = transX;
startZ = transZ;
}
// modify rolling parameters depending on which leg we're in
switch (legOfCycle) {
case 1:
setupRotationParams(startX, startZ, LEG1_X, LEG1_Z, legOfCycle); break;
case 2:
setupRotationParams(startX, startZ, LEG2_X, LEG2_Z, legOfCycle); break;
case 3:
setupRotationParams(startX, startZ, LEG3_X, LEG3_Z, legOfCycle); break;
}
}
void startRolling() {
// start the rolling of the sphere
isStopped = 0;
if (hasStarted)
glutIdleFunc(animateRotatingSphere);
}
void menuMainHandler(int id) {
// handles main menu items
if (id == MENU_DEFAULT_VIEW) {
vRefPtX = 7.0;
vRefPtY = 3.0;
vRefPtZ = -10.0;
} else if (id == MENU_QUIT)
exit (0);
glutPostRedisplay(); // explicitly re-draw!
if (isStopped) startRolling();
}
void menuWireFrameHandler(int id) {
useShading = 0;
if (id == MENU_NO_HSR) useHSR = 0;
else if (id == MENU_HSR) useHSR = 1;
glutPostRedisplay(); // explicitly re-draw!
if (isStopped) startRolling();
}
void menuShadingSmoothHandler(int id) {
useShading = 1;
glShadeModel(GL_SMOOTH);
if (id == MENU_SHADE_TVN)
vertexMode = SHADE_TRUE_VERTEX;
else if (id == MENU_SHADE_AVN)
vertexMode = SHADE_AVG_VERTEX;
glutPostRedisplay(); // explicitly re-draw!
if (isStopped) startRolling();
}
void menuShadingHandler(int id) {
useShading = 1;
glShadeModel(GL_FLAT);
if (id == MENU_SHADE_FLAT)
vertexMode = SHADE_FLAT;
glutPostRedisplay(); // explicitly re-draw!
if (isStopped) startRolling();
}
void menuLightingHandler(int id) {
if (id == MENU_LIGHT_SPOT) {
useSpotLight = 1;
} else if (id == MENU_LIGHT_POINT)
useSpotLight = 0;
setLightCutOff();
glutPostRedisplay(); // explicitly re-draw!
if (isStopped) startRolling();
}
void menuFogHandler(int id) {
if (id == MENU_NO_FOG) glDisable (GL_FOG);
else if (id == MENU_FOG_LINEAR) fogMode = GL_LINEAR;
else if (id == MENU_FOG_EXP) fogMode = GL_EXP;
else if (id == MENU_FOG_EXP2) fogMode = GL_EXP2;
if (id == MENU_FOG_LINEAR || id == MENU_FOG_EXP || id == MENU_FOG_EXP2) {
glEnable(GL_FOG);
resetFog();
}
glutPostRedisplay(); // explicitly re-draw!
if (isStopped) startRolling();
}
void menuInit() {
// sets up menu definitions
int menuWireFrame = glutCreateMenu(menuWireFrameHandler);
glutAddMenuEntry("without hidden edge removal",MENU_NO_HSR);
glutAddMenuEntry("with hidden edge removal", MENU_HSR);
int menuShadingSmooth = glutCreateMenu(menuShadingSmoothHandler);
glutAddMenuEntry("True Vertex Normals", MENU_SHADE_TVN);
glutAddMenuEntry("Averaged Vertex Normals", MENU_SHADE_AVN);
int menuShading = glutCreateMenu(menuShadingHandler);
glutAddMenuEntry("Flat Shading", MENU_SHADE_FLAT);
glutAddSubMenu("Smooth Shading", menuShadingSmooth);
int menuLighting = glutCreateMenu(menuLightingHandler);
glutAddMenuEntry("Spot Light", MENU_LIGHT_SPOT);
glutAddMenuEntry("Point Source Light", MENU_LIGHT_POINT);
int menuFog = glutCreateMenu (menuFogHandler);
glutAddMenuEntry("No Fog", MENU_NO_FOG);
glutAddMenuEntry("Linear Fog", MENU_FOG_LINEAR);
glutAddMenuEntry("Exponential Fog", MENU_FOG_EXP);
glutAddMenuEntry("Exponential Squared Fog", MENU_FOG_EXP2);
glutCreateMenu(menuMainHandler);
glutAddMenuEntry("Default View Point", MENU_DEFAULT_VIEW);
glutAddSubMenu("Wire Frame", menuWireFrame);
glutAddSubMenu("Fog Options", menuFog);
glutAddSubMenu("Shading", menuShading);
glutAddSubMenu("Lighting", menuLighting);
glutAddMenuEntry("Quit", MENU_QUIT);
glutAttachMenu(GLUT_LEFT_BUTTON);
}
void display() {
// draws the sphere
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
if (useHSR) { // only perform these calculations if we're using HSR.
glLoadIdentity();
glRotatef(theta, rotateX, 0, rotateZ);
glGetFloatv(GL_MODELVIEW_MATRIX, myMatrix);
GLfloat tempX, tempY, tempZ;
viewingX = vRefPtX; viewingY = vRefPtY; viewingZ = vRefPtZ;
// manually multiply this matrix
tempX = viewingX * myMatrix[0] + viewingY * myMatrix[1] + viewingZ * myMatrix[2];
tempY = viewingX * myMatrix[4] + viewingY * myMatrix[5] + viewingZ * myMatrix[6];
tempZ = viewingX * myMatrix[8] + viewingY * myMatrix[9] + viewingZ * myMatrix[10];
viewingX = tempX; viewingY = tempY; viewingZ = tempZ;
}
glLoadIdentity(); // load identity matrix
gluLookAt(vRefPtX,vRefPtY,vRefPtZ,0,0,0,0,1,0); // setup viewing
// draw green plane
setLightCutOff();
glEnable(GL_LIGHTING);
glEnable(GL_TEXTURE_2D);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glBindTexture(GL_TEXTURE_2D, Texture);
glMaterialfv(GL_FRONT, GL_AMBIENT, noMaterialMatrix);
glMaterialfv(GL_FRONT, GL_SPECULAR, noMaterialMatrix);
glMaterialfv(GL_FRONT, GL_DIFFUSE, floorMaterialMatrix);
glMaterialfv(GL_FRONT, GL_EMISSION, noMaterialMatrix);
glMaterialf(GL_FRONT, GL_SHININESS, 0);
glNormal3f(0.0, 1.0, 0.0); // set normal of ground
glBegin(GL_QUADS);
glColor3f (0, 1, 0);
glTexCoord2f(0, 0); glVertex4i(5,0,8,1);
glTexCoord2f(0, 3); glVertex4i(5,0,-4,1);
glTexCoord2f(2.5, 3.0); glVertex4i(-5,0,-4,1);
glTexCoord2f(2.5, 0); glVertex4i(-5,0,8,1);
glEnd();
glDisable(GL_TEXTURE_2D);
glDisable(GL_LIGHTING);
glBegin(GL_LINES);
glColor3f(1, 0, 0); glVertex4f(0, 0.01, 0, 1); glVertex4f(10, 0.01, 0, 1); // red x-axis
glColor3f(1, 0, 1); glVertex4f(0, 10, 0, 1); glVertex4f(0, 0, 0, 1); // magenta y-axis
glColor3f(0, 0, 1); glVertex4f(0, 0.01, 0, 1); glVertex4f(0, 0.01, 10, 1); // blue z-axis
glEnd();
glTranslatef(transX, transY, transZ); // modify matrix for translation
glRotatef(theta, rotateX, 0, rotateZ); // modify matrix for rotation
drawSphere(); // draw our wonderful sphere
glFlush(); // flush system so everything gets drawn
glutSwapBuffers(); // switch to other buffer (we're using double buffering)
}
void myKeyHandler(unsigned char key, int mouseX, int mouseY) {
// start the rolling
if (key == 'S' || key == 's') {
hasStarted = 1; startRolling();
}
// handle navigation keys
else if (key == 'X') vRefPtX += 1; else if (key == 'x') vRefPtX -= 1;
else if (key == 'Y') vRefPtY += 1; else if (key == 'y') vRefPtY -= 1;
else if (key == 'Z') vRefPtZ += 1; else if (key == 'z') vRefPtZ -= 1;
// exit program
else if (key == 'Q' || key == 'q') exit(0);
glutPostRedisplay(); // re-draw
}
void myMouseHandler(int button, int state, int x, int y) {
// pause the rolling of the sphere (if rolling has been started)
if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN && hasStarted) {
if (isStopped) {
startRolling();
} else {
isStopped = 1;
glutIdleFunc(NULL);
}
}
}
void myReshape(int w, int h) {
// called when first drawn and when window is resized, moved, etc.
glViewport(0,0,(GLsizei) w, (GLsizei) h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective (50.0, (GLfloat) w/(GLfloat) h, 0.1, 25.0);
glMatrixMode(GL_MODELVIEW);
}
void loadSphere(const char* filename) {
ifstream infile; infile.open(filename);
if (infile.fail()) {
cout << "Error, cannot open file " << filename << endl;
exit(0);
}
int numVertexes; // will be entered from file
int numTriangles; // will be entered from file
GLfloat length; // will be entered from file
/* part of hash code, see below
#define HASHSIZE 24000
int hashtable[HASHSIZE];
int hashkey;
for (hashkey=0; hashkey < HASHSIZE; hashkey++) {
hashtable[hashkey] = 0;
}
*/
vertexNode *currVertex, *newVertex, tempVertex[NUM_VERTEX];
edgeNode *currEdge, *newEdge, *tempEdge;
triangleNode *currTriangle;
triangleNodeList *currTriangleList;
// read in number of triangles and loop through each triangle.
for (infile >> numTriangles; numTriangles > 0; numTriangles--) {
// create a new triangle
currTriangle = new triangleNode;
infile >> numVertexes; // how many vertexes does this triangle have?
assert(numVertexes == NUM_VERTEX); // it should be 3!!
for (;numVertexes > 0; numVertexes--) {
infile >> tempVertex[numVertexes-1].x // read each coordinate..
>> tempVertex[numVertexes-1].y // into the array..
>> tempVertex[numVertexes-1].z; // for the current vertex..
tempVertex[numVertexes-1].nxt = NULL; // being processed.
// linear search through the already-entered-vertex-list
currVertex = enteredVertexes;
while (currVertex != NULL)
// check to see if the current vertex was already entered
if ((currVertex->x == tempVertex[numVertexes-1].x) &&
(currVertex->y == tempVertex[numVertexes-1].y) &&
(currVertex->z == tempVertex[numVertexes-1].z)) {
// if it was found, save it's location in the temporary vertex array
tempVertex[numVertexes-1].nxt = currVertex;
currVertex = NULL; // and exit the loops.
} else
currVertex = currVertex->nxt; // otherwise try next entered vertex
/* the following is the hash code that just DIDN'T want to work properly!!
// reset hash key to 0
hashkey = 0;
// add positive integer x contribution
if (tempVertex[numVertexes-1].x < 0)
hashkey += int(-(tempVertex[numVertexes-1].x*10000));
else
hashkey += int(tempVertex[numVertexes-1].x*10000);
// add positive integer y contribution
if (tempVertex[numVertexes-1].y < 0)
hashkey += int(-(tempVertex[numVertexes-1].y*100000));
else
hashkey += int(tempVertex[numVertexes-1].y*100000);
// add positive integer z contribution
if (tempVertex[numVertexes-1].z < 0)
hashkey += int(-(tempVertex[numVertexes-1].z*1000000));
else
hashkey += int(tempVertex[numVertexes-1].z*1000000);
hashkey = hashkey % 23997;
// if we ended up NOT finding the current vertex in the hashtable...
if (hashtable[hashkey] == 0) {
hashtable[hashkey] = 1;
// the stuff below would be here.
}
*/
if (tempVertex[numVertexes-1].nxt == NULL) {
// create a new vertex node and set its values to the current vertex
newVertex = new vertexNode;
newVertex->x = tempVertex[numVertexes-1].x;
newVertex->y = tempVertex[numVertexes-1].y;
newVertex->z = tempVertex[numVertexes-1].z;
newVertex->myTriangles = NULL;
// add this vertex to [the beginning of] the list of entered vertexes
newVertex->nxt = enteredVertexes;
enteredVertexes = newVertex;
// remember this new vertex's location in the temporary vertex array
tempVertex[numVertexes-1].nxt = newVertex;
}
} // done processing all vertexes of the current triangle
// process the first two vertex's edge..
// set up traversal through the already-entered-edge-list
tempEdge = NULL; currEdge = enteredEdges;
while (currEdge != NULL)
// check to see if this vertex pair already has been entered
if (((currEdge->vertex0->x == tempVertex[0].nxt->x) && (currEdge->vertex0->y ==
tempVertex[0].nxt->y) && (currEdge->vertex0->z == tempVertex[0].nxt->z) &&
(currEdge->vertex1->x == tempVertex[1].nxt->x) && (currEdge->vertex1->y ==
tempVertex[1].nxt->y) && (currEdge->vertex1->z == tempVertex[1].nxt->z)) ||
((currEdge->vertex0->x == tempVertex[1].nxt->x) && (currEdge->vertex0->y ==
tempVertex[1].nxt->y) && (currEdge->vertex0->z == tempVertex[1].nxt->z) &&
(currEdge->vertex1->x == tempVertex[0].nxt->x) && (currEdge->vertex1->y ==
tempVertex[0].nxt->y) && (currEdge->vertex1->z == tempVertex[0].nxt->z))) {
// it has? then save it and end traversal
tempEdge = currEdge; currEdge = NULL;
} else
currEdge = currEdge->nxt; // otherwise proceed to next edge in list
// edge has not been found, creating new one, setting values, adding to list
if (tempEdge == NULL) {
newEdge = new edgeNode; newEdge->myTriangles = NULL;
newEdge->vertex0 = tempVertex[0].nxt; newEdge->vertex1 = tempVertex[1].nxt;
newEdge->nxt = enteredEdges; enteredEdges = newEdge;
tempEdge = newEdge;
}
// updating the edge's triangle-children list
currTriangleList = new triangleNodeList; currTriangleList->nxt = tempEdge->myTriangles;
currTriangleList->triangle = currTriangle; tempEdge->myTriangles = currTriangleList;
// process the second two vertex's edge..
// set up traversal through the already-entered-edge-list
tempEdge = NULL; currEdge = enteredEdges;
while (currEdge != NULL)
// check to see if this vertex pair already has been entered
if (((currEdge->vertex1->x == tempVertex[1].nxt->x) && (currEdge->vertex1->y ==
tempVertex[1].nxt->y) && (currEdge->vertex1->z == tempVertex[1].nxt->z) &&
(currEdge->vertex0->x == tempVertex[2].nxt->x) && (currEdge->vertex0->y ==
tempVertex[2].nxt->y) && (currEdge->vertex0->z == tempVertex[2].nxt->z)) ||
((currEdge->vertex1->x == tempVertex[2].nxt->x) && (currEdge->vertex1->y ==
tempVertex[2].nxt->y) && (currEdge->vertex1->z == tempVertex[2].nxt->z) &&
(currEdge->vertex0->x == tempVertex[1].nxt->x) && (currEdge->vertex0->y ==
tempVertex[1].nxt->y) && (currEdge->vertex0->z == tempVertex[1].nxt->z))) {
// it has? then save it and end traversal
tempEdge = currEdge; currEdge = NULL;
} else
currEdge = currEdge->nxt; // otherwise proceed to next edge in list
// edge has not been found, creating new one, setting values, adding to list
if (tempEdge == NULL) {
newEdge = new edgeNode; newEdge->myTriangles = NULL;
newEdge->vertex1 = tempVertex[1].nxt; newEdge->vertex0 = tempVertex[2].nxt;
newEdge->nxt = enteredEdges; enteredEdges = newEdge;
tempEdge = newEdge;
}
// updating the edge's triangle-children list
currTriangleList = new triangleNodeList; currTriangleList->nxt = tempEdge->myTriangles;
currTriangleList->triangle = currTriangle; tempEdge->myTriangles = currTriangleList;
// process the last two vertex's edge..
// set up traversal through the already-entered-edge-list
tempEdge = NULL; currEdge = enteredEdges;
while (currEdge != NULL)
// check to see if this vertex pair already has been entered
if (((currEdge->vertex0->x == tempVertex[0].nxt->x) && (currEdge->vertex0->y ==
tempVertex[0].nxt->y) && (currEdge->vertex0->z == tempVertex[0].nxt->z) &&
(currEdge->vertex1->x == tempVertex[2].nxt->x) && (currEdge->vertex1->y ==
tempVertex[2].nxt->y) && (currEdge->vertex1->z == tempVertex[2].nxt->z)) ||
((currEdge->vertex0->x == tempVertex[2].nxt->x) && (currEdge->vertex0->y ==
tempVertex[2].nxt->y) && (currEdge->vertex0->z == tempVertex[2].nxt->z) &&
(currEdge->vertex1->x == tempVertex[0].nxt->x) && (currEdge->vertex1->y ==
tempVertex[0].nxt->y) && (currEdge->vertex1->z == tempVertex[0].nxt->z))) {
// it has? then save it and end traversal
tempEdge = currEdge; currEdge = NULL;
} else
currEdge = currEdge->nxt; // otherwise proceed to next edge in list
// edge has not been found, creating new one, setting values, adding to list
if (tempEdge == NULL) {
newEdge = new edgeNode; newEdge->myTriangles = NULL;
newEdge->vertex0 = tempVertex[0].nxt; newEdge->vertex1 = tempVertex[2].nxt;
newEdge->nxt = enteredEdges; enteredEdges = newEdge;
tempEdge = newEdge;
}
// updating the edge's triangle-children list
currTriangleList = new triangleNodeList; currTriangleList->nxt = tempEdge->myTriangles;
currTriangleList->triangle = currTriangle; tempEdge->myTriangles = currTriangleList;
// back to triangles:
// set triangle's vertexes, and update each vertex's triangle children list
currTriangle->vertex0 = tempVertex[0].nxt;
currTriangleList = new triangleNodeList;
currTriangleList->nxt = currTriangle->vertex0->myTriangles;
currTriangleList->triangle = currTriangle;
currTriangle->vertex0->myTriangles = currTriangleList;
currTriangle->vertex1 = tempVertex[1].nxt;
currTriangleList = new triangleNodeList;
currTriangleList->nxt = currTriangle->vertex1->myTriangles;
currTriangleList->triangle = currTriangle;
currTriangle->vertex1->myTriangles = currTriangleList;
currTriangle->vertex2 = tempVertex[2].nxt;
currTriangleList = new triangleNodeList;
currTriangleList->nxt = currTriangle->vertex2->myTriangles;
currTriangleList->triangle = currTriangle;
currTriangle->vertex2->myTriangles = currTriangleList;
// and add it to the entered-triangle list
currTriangle->nxt = enteredTriangles;
enteredTriangles = currTriangle;
// calculate normal for the triangle
currTriangle->normalX = (currTriangle->vertex1->y - currTriangle->vertex0->y) *
(currTriangle->vertex2->z - currTriangle->vertex0->z) -
(currTriangle->vertex1->z - currTriangle->vertex0->z) *
(currTriangle->vertex2->y - currTriangle->vertex0->y);
currTriangle->normalY = (currTriangle->vertex1->z - currTriangle->vertex0->z) *
(currTriangle->vertex2->x - currTriangle->vertex0->x) -
(currTriangle->vertex1->x - currTriangle->vertex0->x) *
(currTriangle->vertex2->z - currTriangle->vertex0->z);
currTriangle->normalZ = (currTriangle->vertex1->x - currTriangle->vertex0->x) *
(currTriangle->vertex2->y - currTriangle->vertex0->y) -
(currTriangle->vertex1->y - currTriangle->vertex0->y) *
(currTriangle->vertex2->x - currTriangle->vertex0->x);
length = -(sqrt(currTriangle->normalX * currTriangle->normalX +
currTriangle->normalY * currTriangle->normalY +
currTriangle->normalZ * currTriangle->normalZ));
// store normal
currTriangle->normalX /= length;
currTriangle->normalY /= length;
currTriangle->normalZ /= length;
} // done processing all triangles
// calculating average vertex normals
GLfloat tempX, tempY, tempZ, vectorLength;
currVertex = enteredVertexes;
while (currVertex != NULL) {
tempX = 0, tempY = 0, tempZ = 0;
currTriangleList = currVertex->myTriangles;
while (currTriangleList != NULL) {
tempX += currTriangleList->triangle->normalX;
tempY += currTriangleList->triangle->normalY;
tempZ += currTriangleList->triangle->normalZ;
currTriangleList = currTriangleList->nxt;
}
vectorLength = sqrt(tempX*tempX+tempY*tempY+tempZ*tempZ);
currVertex->normalX = tempX/vectorLength;
currVertex->normalY = tempY/vectorLength;
currVertex->normalZ = tempZ/vectorLength;
currVertex = currVertex->nxt;
}
}
void main(int argc, char **argv) {
glutInit(&argc,argv);
if (argc < 2) {
cout << "Requires one argument, which file to open" << endl;
exit(0);
}
glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH | GLUT_RGB);
// position & draw the right window size w/ title
glutInitWindowPosition(XOFFSET, YOFFSET);
glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT);
glutCreateWindow("CS653 Assignment 4");
glutReshapeFunc(myReshape); // set up reshape method
glutDisplayFunc(display); // set our display method
glutIdleFunc(NULL); // initially the program does not roll
glutKeyboardFunc(myKeyHandler); // set keyboard handler
glutMouseFunc(myMouseHandler); // set mouse handler
loadSphere(argv[1]); // load the sphere and perform sphere calculations
varInit(); // initiate our variables
menuInit(); // setup our menus
imageInit(); // setup texture mapping for floor
lightsInit(); // setup lights position, intensity, type, etc..
glutMainLoop(); // let her loose!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment