Files
GTSchoolShit/CS4451/proj2/cs4451_a2.cpp
2025-06-07 01:59:34 -04:00

893 lines
23 KiB
C++

/* cs4451_a2.cpp */
/*
* Jose Caban
* gtg184g
* proj2
*/
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <assert.h>
#ifdef _OS_LINUX_
#include <GL/gl.h>
#include <GL/glu.h>
#endif
//Windows only needs glut.h care of SGI ;)
#include <GL/glut.h>
#define VPD_MIN 200
#define VPD_DEFAULT 800
#define VPD_MAX 1024
enum MENU { MENU_SWITCH_SHADING=0,
MENU_ZOOM_IN,
MENU_ZOOM_OUT,
MENU_POINTS,
MENU_LINES,
MENU_TRIANGLES,
MENU_SWITCH_LIGHT,
MENU_SWITCH_CULLING,
MENU_TURN_OFF_CULLING,
MENU_TURN_ON_CULLING,
MENU_RESET_MODELVIEW
};
#define TWOPI (2.0 * M_PI)
///////////////////////////////////////////////////////////////////
//Define the Normal type
typedef struct SNormal {
GLfloat i;
GLfloat j;
GLfloat k;
} SNormal;
typedef struct SPoint {
GLfloat x;
GLfloat y;
GLfloat z;
} SPoint;
//Define the Vertex type for use in keeping track of Vertices
typedef struct SVertex {
SNormal normal;
GLfloat x;
GLfloat y;
GLfloat z;
} SVertex;
//Define the Data structure that will hold all the vertices
typedef struct SVertexList {
SVertex* vertices;
int length;
} SVertexList;
//Define a Triangle (a1,a2,a3 are indices to the SVertexList
typedef struct STriangle {
SNormal normal;
GLint a1,a2,a3;
} STriangle;
typedef struct STriangleList {
STriangle* triangles;
GLint length;
} STriangleList;
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////
// Globals
SVertexList vertexList;
STriangleList triList;
GLfloat currModelTransform[16];
GLint wid; /* GLUT window id */
GLint vpd = VPD_DEFAULT; /* (square) viewport dimensions */
GLuint triangleScene; /* display list ID */
GLuint gouraudID; /* gouraud display list ID */
GLuint flatID; /* flat display list ID */
GLfloat angle1 = 0; /* angles used in animation */
GLfloat angle2 = 0;
GLfloat dangle1 = 0.57;
GLfloat dangle2 = 0.71;
GLdouble viewDist = 8.0; /* Changes the view distance view */
GLuint cullMode = GL_BACK;
GLboolean worldLight = GL_TRUE;
///////////////////////////////////////////////////////
///////////////////////////////////////////////////////
//Functions
/*
* Input scanner
*/
void scanInput(GLvoid);
/*
* Initialize the Light Source
*/
GLvoid init_lightsource ( GLvoid )
{
GLfloat light_ambient[] = { .1, .1, .1, 1.0 };
GLfloat light_diffuse[] = { .9, .9, .9, 1.0 };
GLfloat light_specular[] = { 0, 0, 0, 1.0 };
GLfloat light_position[] = { 2.0, 2.0, 2.0, 0.0 };
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glLightf(GL_LIGHT0,GL_CONSTANT_ATTENUATION,1.0);
glLightf(GL_LIGHT0,GL_LINEAR_ATTENUATION,0.0);
glLightf(GL_LIGHT0,GL_QUADRATIC_ATTENUATION,0.0);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
}
GLvoid set_material_properties ( GLfloat r, GLfloat g, GLfloat b )
{
GLfloat mat_specular[4] = { 0.0, 0.0, 0.0, 1.0 };
GLfloat mat_ambient_and_diffuse[4] = { 0.5, 0.5, 0.5, 1.0 };
GLfloat mat_shininess[1] = { 0.0 };
mat_specular[0] = mat_ambient_and_diffuse[0] = r;
mat_specular[1] = mat_ambient_and_diffuse[1] = g;
mat_specular[2] = mat_ambient_and_diffuse[2] = b;
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mat_ambient_and_diffuse);
}
inline void cross(SNormal& dest, SVertex& a, SVertex& b) {
dest.i = ( (a.y*b.z) - (a.z*b.y) ); //i
dest.j = ( (a.z*b.x) - (a.x*b.z) ); //j
dest.k = ( (a.x*b.y) - (a.y*b.x) ); //k
}
/*
* Initialize the scene
*
*/
GLuint init_flat_scene ( )
{
GLuint sceneList = glGenLists(1);
SNormal tempNormal;
SVertex a1, a2, a3;
glNewList(sceneList,GL_COMPILE);
glBegin(GL_TRIANGLES);
for (int i = 0; i < triList.length; i++) {
a1 = vertexList.vertices[triList.triangles[i].a1];
a2 = vertexList.vertices[triList.triangles[i].a2];
a3 = vertexList.vertices[triList.triangles[i].a3];
tempNormal = triList.triangles[i].normal;
glNormal3f(tempNormal.i, tempNormal.j, tempNormal.k);
glVertex3f(a1.x, a1.y, a1.z);
glVertex3f(a2.x, a2.y, a2.z);
glVertex3f(a3.x, a3.y, a3.z);
}
glEnd();
glEndList();
return sceneList;
}
/*
* Initialize the gouraud scene
*/
GLuint init_gouraud_scene ( )
{
GLuint sceneList = glGenLists(1);
SNormal tempNormal;
SVertex a1, a2, a3;
glNewList(sceneList,GL_COMPILE);
glBegin(GL_TRIANGLES);
for (int i = 0; i < triList.length; i++) {
a1 = vertexList.vertices[triList.triangles[i].a1];
a2 = vertexList.vertices[triList.triangles[i].a2];
a3 = vertexList.vertices[triList.triangles[i].a3];
tempNormal = a1.normal;
glNormal3f(tempNormal.i, tempNormal.j, tempNormal.k);
glVertex3f(a1.x, a1.y, a1.z);
tempNormal = a2.normal;
glNormal3f(tempNormal.i, tempNormal.j, tempNormal.k);
glVertex3f(a2.x, a2.y, a2.z);
tempNormal = a3.normal;
glNormal3f(tempNormal.i, tempNormal.j, tempNormal.k);
glVertex3f(a3.x, a3.y, a3.z);
}
glEnd();
glEndList();
return sceneList;
}
GLuint create_scene(GLuint triangleList) {
GLuint sceneList = glGenLists(1);
glNewList(sceneList,GL_COMPILE);
set_material_properties(1.0,1.0,1.0);
/* Correctly size the object */
assert(vertexList.length > 0);
SVertex Max;
SVertex Min;
SVertex Center;
Max.x = Min.x = vertexList.vertices[0].x;
Max.y = Min.y = vertexList.vertices[0].y;
Max.z = Min.z = vertexList.vertices[0].z;
for (int i = 1; i < vertexList.length; i++) {
if (vertexList.vertices[i].x > Max.x) {
Max.x = vertexList.vertices[i].x;
} else if (vertexList.vertices[i].x < Min.x) {
Min.x = vertexList.vertices[i].x;
}
if (vertexList.vertices[i].y > Max.y) {
Max.y = vertexList.vertices[i].y;
} else if (vertexList.vertices[i].y < Min.y) {
Min.y = vertexList.vertices[i].y;
}
if (vertexList.vertices[i].z > Max.z) {
Max.z = vertexList.vertices[i].z;
} else if (vertexList.vertices[i].z < Min.z) {
Min.z = vertexList.vertices[i].z;
}
}
Center.x = (Max.x + Min.x) / 2.;
Center.y = (Max.y + Min.y) / 2.;
Center.z = (Max.z + Min.z) / 2.;
float scaleX, scaleY, scaleZ;
scaleX = (Max.x - Min.x) / 2.;
scaleY = (Max.y - Min.y) / 2.;
scaleZ = (Max.z - Min.z) / 2.;
float scaleFactor;
scaleFactor = scaleX > scaleY ? scaleX : scaleY;
scaleFactor = scaleZ > scaleFactor ? scaleZ : scaleFactor;
scaleFactor = 1. / scaleFactor;
//printf("ScaleFactor: %f\n",scaleFactor);
glPushMatrix();
glTranslatef(0.-(Center.x*scaleFactor),0.-(Center.y*scaleFactor),0.-(Center.z*scaleFactor));
glScalef(scaleFactor,scaleFactor,scaleFactor);
glCallList(triangleList);
glPopMatrix();
glEndList();
return sceneList;
}
GLuint create_flat_scene ( )
{
return create_scene( init_flat_scene() );
}
GLuint create_gouraud_scene ( )
{
return create_scene( init_gouraud_scene() );
}
/* --------------------------------------------- */
/* redraw the scene */
GLvoid draw(GLvoid)
{
/* set the projection matrix */
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(viewDist,1.0,15.0,25.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
/* initialize light */
if (worldLight) {
//World Lighting
init_lightsource();
glTranslatef(0,0,-20);
glMultMatrixf(currModelTransform);
} else {
//Model Lighting
glTranslatef(0,0,-20);
glMultMatrixf(currModelTransform);
init_lightsource();
}
/* ensure we're drawing to the correct GLUT window */
glutSetWindow(wid);
/* clear the color buffers */
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
/* DRAW WHAT IS IN THE DISPLAY LIST */
glCallList(triangleScene);
/* flush the pipeline */
glFlush();
/* look at our handiwork */
glutSwapBuffers();
}
/* --------------------------------------------- */
/* handle mouse events */
SPoint oldPoint; //stores the previous point used in the virtual trackball
GLvoid mouse_button(GLint btn, GLint state, GLint mx, GLint my)
{
switch( btn ) {
case GLUT_LEFT_BUTTON:
switch( state ) {
case GLUT_DOWN:
oldPoint.x = mx;
oldPoint.y = my;
oldPoint.z = -1;
break;
case GLUT_UP:
break;
}
break;
case GLUT_MIDDLE_BUTTON:
switch( state ) {
case GLUT_DOWN:
break;
case GLUT_UP:
break;
}
break;
case GLUT_RIGHT_BUTTON:
switch( state ) {
case GLUT_DOWN:
break;
case GLUT_UP:
break;
}
break;
}
}
inline void scalePoint(SPoint& p, GLint mx, GLint my) {
//scale to -1 and 1
float scale = ceil(vpd/2.);
p.x = (mx / scale) -1.;
p.y = (my / scale) -1.;
p.y*=-1.; //handle reversed y
p.z = 1.-pow(p.x,2)-pow(p.y,2);
if (p.z < 0) {
float under = sqrt((p.x*p.x)+(p.y*p.y));
p.x /= under;
p.y /= under;
p.z = 0;
} else {
p.z = sqrt(p.z);
}
}
inline GLfloat vecLength(SPoint& p) {
return sqrt(pow(p.x,2)+pow(p.y,2)+pow(p.z,2));
}
inline GLfloat dot(SPoint &a, SPoint &b) {
return (a.x*b.x)+(a.y*b.y)+(a.z*b.z);
}
inline void cross(SPoint &dest, SPoint &a, SPoint &b) {
dest.x = ( (a.y*b.z) - (a.z*b.y) ); //i
dest.y = ( (a.z*b.x) - (a.x*b.z) ); //j
dest.z = ( (a.x*b.y) - (a.y*b.x) ); //k
}
inline void calcAngle(GLfloat *newMatrix, GLfloat angle, SPoint& a) {
newMatrix[0] = 1.+(1.-cos(angle))*(pow(a.x,2)-1.);
newMatrix[1] = a.z*sin(angle) + (1.-cos(angle)) * a.x * a.y;
newMatrix[2] = -1. * a.y * sin(angle) + (1.-cos(angle))*a.x*a.z;
newMatrix[3] = 0;
newMatrix[4] = -1. * a.z * sin(angle) + (1.-cos(angle)) * a.x * a.y;
newMatrix[5] = 1. + (1. - cos(angle))*(pow(a.y,2)-1.);
newMatrix[6] = a.x * sin(angle) + (1.-cos(angle))*a.y*a.z;
newMatrix[7] = 0;
newMatrix[8] = a.y * sin(angle) + (1.-cos(angle))*a.x * a.z;
newMatrix[9] = -1. * a.x * sin(angle) + (1.-cos(angle))*a.y*a.z;
newMatrix[10] = 1. + (1.-cos(angle))*(pow(a.z,2)-1.);
newMatrix[11] = newMatrix[12] = newMatrix[13] = newMatrix[14] = 0;
newMatrix[15] = 1.;
}
GLvoid button_motion(GLint mx, GLint my)
{
/* First calculate P */
static SPoint v;
SPoint p, w, a;
//Give us the scaled p on the sphere
scalePoint(p,mx,my);
//get the unit vector of p
GLfloat length = vecLength(p);
if (length==0) {
return;
} else {
w.x = p.x / length;
w.y = p.y / length;
w.z = p.z / length;
}
//This is the first time the movement has been made
if (oldPoint.z == -1) {
scalePoint(oldPoint,(int)oldPoint.x,(int)oldPoint.y);
length = vecLength(oldPoint);
if (length==0) {
return;
} else {
v.x = oldPoint.x / length;
v.y = oldPoint.y / length;
v.z = oldPoint.z / length;
}
}
cross(a,oldPoint,p);
length = vecLength(a);
if (length==0) {
return;
} else {
a.x /= length;
a.y /= length;
a.z /= length;
}
GLfloat angle = dot(v,w);
if (angle > 1) {
angle = 1;
} else if (angle < -1) {
angle = -1;
}
angle = acos(angle);
/* Perform the rotation calculation */
GLfloat newMatrix[16];
calcAngle(newMatrix,angle,a);
/* Make OpenGL do our work */
glPushMatrix();
glLoadMatrixf(newMatrix);
glMultMatrixf(currModelTransform);
glGetFloatv(GL_MODELVIEW_MATRIX,currModelTransform);
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
oldPoint = p;
v = w;
glutPostRedisplay();
return;
}
GLvoid passive_motion(GLint mx, GLint my)
{
return;
}
/* --------------------------------------------- */
/* handle keyboard events; here, just exit if ESC is hit */
GLvoid keyboard(GLubyte key, GLint x, GLint y)
{
switch(key) {
case 27: /* ESC */
exit(0);
case 'w':
viewDist -= .1;
glutPostRedisplay();
break;
case 's':
viewDist += .1;
glutPostRedisplay();
break;
case 'a':
currModelTransform[12] -= .01;
glutPostRedisplay();
break;
case 'd':
currModelTransform[12] += .01;
glutPostRedisplay();
break;
default: break;
}
}
/* --------------------------------------------- */
GLvoid menu ( int value )
{
switch(value)
{
case MENU_SWITCH_SHADING:
if (triangleScene == gouraudID) {
glShadeModel(GL_FLAT);
triangleScene = flatID;
} else {
glShadeModel(GL_SMOOTH);
triangleScene = gouraudID;
}
glutPostRedisplay();
break;
case MENU_ZOOM_IN:
viewDist -= 1.;
glutPostRedisplay();
break;
case MENU_ZOOM_OUT:
viewDist += 1.;
glutPostRedisplay();
break;
case MENU_POINTS:
glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
glutPostRedisplay();
break;
case MENU_LINES:
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glutPostRedisplay();
break;
case MENU_TRIANGLES:
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glutPostRedisplay();
break;
case MENU_SWITCH_CULLING:
if (cullMode == GL_FRONT) {
glCullFace(GL_BACK);
cullMode = GL_BACK;
} else {
glCullFace(GL_FRONT);
cullMode = GL_FRONT;
}
glutPostRedisplay();
break;
case MENU_TURN_ON_CULLING:
glEnable(GL_CULL_FACE);
glutPostRedisplay();
break;
case MENU_TURN_OFF_CULLING:
glDisable(GL_CULL_FACE);
glutPostRedisplay();
break;
case MENU_SWITCH_LIGHT:
worldLight = !worldLight;
glutPostRedisplay();
break;
case MENU_RESET_MODELVIEW:
glPushMatrix();
glLoadIdentity();
glGetFloatv(GL_MODELVIEW_MATRIX,currModelTransform);
glPopMatrix();
glutPostRedisplay();
default: break;
}
}
/* --------------------------------------------- */
/* handle resizing the glut window */
GLvoid reshape(GLint vpw, GLint vph)
{
glutSetWindow(wid);
/* maintain a square viewport, not too small, not too big */
if( vpw < vph ) vpd = vph;
else vpd = vpw;
if( vpd < VPD_MIN ) vpd = VPD_MIN;
if( vpd > VPD_MAX ) vpd = VPD_MAX;
glViewport(0, 0, vpd, vpd);
glutReshapeWindow(vpd, vpd);
glutPostRedisplay();
}
/* --------------------------------------------- */
GLint init_glut(GLint *argc, char **argv)
{
GLint id;
glutInit(argc,argv);
/* size and placement hints to the window system */
glutInitWindowSize(vpd, vpd);
glutInitWindowPosition(10,10);
/* double buffered, RGB color mode */
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
/* create a GLUT window (not drawn until glutMainLoop() is entered) */
id = glutCreateWindow("cs4451 assignment 2");
/* register callbacks */
/* window size changes */
glutReshapeFunc(reshape);
/* keypress handling when the current window has input focus */
glutKeyboardFunc(keyboard);
/* mouse event handling */
glutMouseFunc(mouse_button); /* button press/release */
glutMotionFunc(button_motion); /* mouse motion w/ button down */
glutPassiveMotionFunc(passive_motion); /* mouse motion with button up */
/* window obscured/revealed event handler */
glutVisibilityFunc(NULL);
/* handling of keyboard SHIFT, ALT, CTRL keys */
glutSpecialFunc(NULL);
/* what to do when mouse cursor enters/exits the current window */
glutEntryFunc(NULL);
/* what to do on each display loop iteration */
glutDisplayFunc(draw);
/* Create the menu */
//Create the Zoom Menu
GLint zoomMenu = glutCreateMenu(menu);
glutAddMenuEntry("Zoom In (w)",MENU_ZOOM_IN);
glutAddMenuEntry("Zoom Out (s)",MENU_ZOOM_OUT);
//Create the Render Mode Menu
GLint renderMenu = glutCreateMenu(menu);
glutAddMenuEntry("Points Only",MENU_POINTS);
glutAddMenuEntry("Lines Only",MENU_LINES);
glutAddMenuEntry("Full Model",MENU_TRIANGLES);
//Create the Culling Menu
GLint cullingMenu = glutCreateMenu(menu);
glutAddMenuEntry("Switch Culling Mode",MENU_SWITCH_CULLING);
glutAddMenuEntry("Turn on Culling",MENU_TURN_ON_CULLING);
glutAddMenuEntry("Turn off Culling",MENU_TURN_OFF_CULLING);
GLint menuID = glutCreateMenu(menu);
glutAddMenuEntry("Switch Shading Mode",MENU_SWITCH_SHADING);
glutAddMenuEntry("Toggle World/Model Relative Light",MENU_SWITCH_LIGHT);
glutAddSubMenu("Zoom",zoomMenu);
glutAddSubMenu("Render", renderMenu);
glutAddSubMenu("Culling", cullingMenu);
glutAddMenuEntry("Reset View Model",MENU_RESET_MODELVIEW);
glutSetMenu(menuID);
glutAttachMenu(GLUT_RIGHT_BUTTON);
return id;
}
/* --------------------------------------------- */
GLvoid init_opengl(GLvoid)
{
/* back-face culling on */
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK); /* We want to cull the back */
glFrontFace(GL_CW); /* The vertices we get are clockwise */
/* automatically scale normals to unit length after transformation */
glEnable(GL_NORMALIZE);
/* clear to BLACK */
glClearColor(0.0, 0.0, 0.0, 1.0);
/* Enable depth test */
glEnable(GL_DEPTH_TEST);
}
/* --------------------------------------------- */
void generateNormals() {
/* Generate normals for triangles and Vertices */
SNormal tempNormal;
SVertex a1a2, a1a3;
SVertex a1, a2, a3;
for (int i = 0; i < triList.length; i++) {
a1 = vertexList.vertices[triList.triangles[i].a1];
a2 = vertexList.vertices[triList.triangles[i].a2];
a3 = vertexList.vertices[triList.triangles[i].a3];
a1a2.x = a2.x - a1.x;
a1a2.y = a2.y - a1.y;
a1a2.z = a2.z - a1.z;
a1a3.x = a3.x - a1.x;
a1a3.y = a3.y - a1.y;
a1a3.z = a3.z - a1.z;
cross(tempNormal,a1a2,a1a3);
tempNormal.i *= -1;
tempNormal.j *= -1;
tempNormal.k *= -1;
/* Store the normal for the triangle */
triList.triangles[i].normal = tempNormal;
/* Add this normal to the normal of all the vertices */
vertexList.vertices[triList.triangles[i].a1].normal.i += tempNormal.i;
vertexList.vertices[triList.triangles[i].a1].normal.j += tempNormal.j;
vertexList.vertices[triList.triangles[i].a1].normal.k += tempNormal.k;
vertexList.vertices[triList.triangles[i].a2].normal.i += tempNormal.i;
vertexList.vertices[triList.triangles[i].a2].normal.j += tempNormal.j;
vertexList.vertices[triList.triangles[i].a2].normal.k += tempNormal.k;
vertexList.vertices[triList.triangles[i].a3].normal.i += tempNormal.i;
vertexList.vertices[triList.triangles[i].a3].normal.j += tempNormal.j;
vertexList.vertices[triList.triangles[i].a3].normal.k += tempNormal.k;
}
}
/* --------------------------------------------- */
GLint main(GLint argc, char **argv)
{
/* Scan Input */
scanInput();
generateNormals();
/* initialize light */
init_lightsource();
/* Initialize the currentTransformation */
currModelTransform[0] = 1;
currModelTransform[5] = 1;
currModelTransform[10] = 1;
currModelTransform[15] = 1;
/* initialize GLUT: register callbacks, etc */
wid = init_glut(&argc, argv);
/* any OpenGL state initialization we need to do */
init_opengl();
/* CREATE THE DISPLAY LIST FOR THE SCENE */
flatID = create_flat_scene();
gouraudID = create_gouraud_scene();
triangleScene = gouraudID;
glutMainLoop();
return 0;
}
void scanInput(GLvoid) {
char input[81];
char *inputPtr;
int i;
//Get the # of vertices and # of triangles
std::cin.getline(input,81);
triList.length = strtol(input,&inputPtr,0);
triList.triangles = (STriangle*)malloc(sizeof(STriangle)*triList.length);
vertexList.length = strtol(inputPtr,NULL,0);
vertexList.vertices = (SVertex*)malloc(sizeof(SVertex)*vertexList.length);
//Skip over the first newline
std::cin.getline(input,81);
for (i=0; i < triList.length; i++) {
std::cin.getline(input,81);
//get points
triList.triangles[i].a1 = strtol(input,&inputPtr,0);
triList.triangles[i].a2 = strtol(inputPtr,&inputPtr,0);
triList.triangles[i].a3 = strtol(inputPtr,NULL,0);
triList.triangles[i].normal.i = 0;
triList.triangles[i].normal.j = 0;
triList.triangles[i].normal.k = 0;
}
//skip over separation newline
std::cin.getline(input,81);
for (i=0; i < vertexList.length; i++) {
std::cin.getline(input,81);
//get coordinates
vertexList.vertices[i].x = strtod(input,&inputPtr);
vertexList.vertices[i].y = strtod(inputPtr,&inputPtr);
vertexList.vertices[i].z = strtod(inputPtr,NULL);
vertexList.vertices[i].normal.i = 0;
vertexList.vertices[i].normal.j = 0;
vertexList.vertices[i].normal.k = 0;
}
}