From d3465c5cd0e6e9b414e669e8c8aa464b03f2fd24 Mon Sep 17 00:00:00 2001 From: Ash Tyndall Date: Thu, 20 Oct 2011 11:06:23 +0800 Subject: [PATCH] Reorganised structure by splitting code into several seperate files * globals.c/.h: Contains global variables used by the code * helper.c/.h: Contains independant helper functions used by the code * types.h: Contains typedef and enum declarations for the code * scene.c/.h: Contains event handling and state initialisation --- Makefile | 8 +- globals.c | 77 +++++++++ globals.h | 70 +++++++++ helper.c | 271 ++++++++++++++++++++++++++++++++ helper.h | 25 +++ scene.c | 457 +++++------------------------------------------------- scene.h | 27 ++++ types.h | 69 +++++++++ 8 files changed, 583 insertions(+), 421 deletions(-) create mode 100644 globals.c create mode 100644 globals.h create mode 100644 helper.c create mode 100644 helper.h create mode 100644 scene.h create mode 100644 types.h diff --git a/Makefile b/Makefile index 8aacfe5..aeaa326 100644 --- a/Makefile +++ b/Makefile @@ -22,14 +22,16 @@ LIBS += -lglut -lGLU -lGL CFLAGS += -ggdb -Wall -std=c99 +FILES=scene.c scene.h bitmap.c bitmap.h globals.c globals.h helper.c helper.h types.h + .PHONY: all all: scene commit -scene: scene.c bitmap.c bitmap.h - gcc $(CFLAGS) -o scene scene.c bitmap.c $(LIBS) +scene: $(FILES) + gcc $(CFLAGS) -o $(FILES) $(LIBS) -commit: scene.c bitmap.c bitmap.h +commit: $(FILES) git commit -a --allow-empty-message --message="" --untracked-files=no; true clean: diff --git a/globals.c b/globals.c new file mode 100644 index 0000000..07e0efd --- /dev/null +++ b/globals.c @@ -0,0 +1,77 @@ +/** + * Global Variables File + * Contains all of the project's global variables + * @author Ashley Tyndall (20915779), Jenna de la Harpe (20367932) + */ + +#include "types.h" +#include "globals.h" + +mesh* meshes[NMESH]; // An array of pointers to the meshes - see getMesh +texture* textures[NTEXTURE]; // An array of texture pointers - see getTexture + +// Menu arrays +const char *textureMenuEntries[NTEXTURE] = { + "1 Plain", "2 Rust", "3 Concrete", "4 Carpet", "5 Beach Sand", + "6 Rocky", "7 Brick", "8 Water", "9 Paper", "10 Marble", + "11 Wood", "12 Scales", "13 Fur", "14 Denim", "15 Hessian", + "16 Orange Peel", "17 Ice Crystals", "18 Grass", "19 Corrugated Iron", "20 Styrofoam", + "21 Bubble Wrap", "22 Leather", "23 Camouflage", "24 Asphalt", "25 Scratched Ice", + "26 Rattan", "27 Snow", "28 Dry Mud", "29 Old Concrete", "30 Leopard Skin" +}; + +const char *objectMenuEntries[NMESH] = { + "1 Thin Dinosaur","2 Big Dog","3 Saddle Dinosaur", "4 Dragon", "5 Cleopatra", + "6 Bone I", "7 Bone II", "8 Rabbit", "9 Long Dragon", "10 Buddha", + "11 Sitting Rabbit", "12 Frog", "13 Cow", "14 Monster", "15 Sea Horse", + "16 Head", "17 Pelican", "18 Horse", "19 Kneeling Angel", "20 Porsche I", + "21 Truck", "22 Statue of Liberty", "23 Sitting Angel", "24 Metal Part", "25 Car", + "26 Apatosaurus", "27 Airliner", "28 Motorbike", "29 Dolphin", "30 Spaceman", + "31 Winnie the Pooh", "32 Shark", "33 Crocodile", "34 Toddler", "35 Fat Dinosaur", + "36 Chihuahua", "37 Sabre-toothed Tiger", "38 Lioness", "39 Fish", "40 Horse (head down)", + "41 Horse (head up)", "42 Skull", "43 Fighter Jet I", "44 Toad", "45 Convertible", + "46 Porsche II", "47 Hare", "48 Vintage Car", "49 Fighter Jet II", "50 Winged Monkey", + "51 Chef", "52 Parasaurolophus", "53 Rooster", "54 T-rex" +}; + +SceneObject sceneObjs[MAXOBJECTS]; // An array with details of the objects in a scene +int nObjects=0; // How many objects there are in the scene currently. + +// Directories containing models +char *dirDefault1 = "models-textures"; +char *dirDefault2 = "/cslinux/examples/CITS2231/project-files/models-textures"; + +char dataDir[200]; // Stores the directory name for the meshes and textures. + +GLfloat lightColor[] = {1.0, 1.0, 1.0, 1.0}; // White light +GLfloat lightPosition[4]; + +int moving, startx, starty; +int lightMoving = 0, lightStartX, lightStartY; + +/* Time varying or user-controled variables. */ +float jump = 0.0; +float lightAngle = 0.0, lightHeight = 5; +GLfloat angle = -150; /* in degrees */ +GLfloat angle2 = 30; /* in degrees */ + +/* Near and far parameters */ +GLfloat near = -100; +GLfloat far = 100; + +/* Zoom factor for mouse movements */ +GLfloat zoomFactor = 1.0; + +/* Recursion level for floor drawing */ +int drawFloorRecurse = 5; + +/* Size of floor, from -n to n */ +int floorSize = 200; + +/* Light 0 parameters */ +GLfloat diffuse0[] = {1.0, 1.0, 1.0, 1.0}; +GLfloat ambient0[] = {0.0, 0.0, 0.0, 1.0}; +GLfloat specular0[] = {1.0, 1.0, 1.0, 1.0}; +GLfloat emission0[] = {0.0, 0.0, 0.0, 0.0}; +GLfloat light0_pos[] ={1.0, 1.0, 0,0, 1.0}; +GLfloat glightmodel[] = {0.2,0.2,0.2,1}; \ No newline at end of file diff --git a/globals.h b/globals.h new file mode 100644 index 0000000..e85ea25 --- /dev/null +++ b/globals.h @@ -0,0 +1,70 @@ +/** + * Global Variables Header File + * @author Ashley Tyndall (20915779), Jenna de la Harpe (20367932) + */ + +#include "types.h" + +#ifndef GLOBALS_H +#define GLOBALS_H + +// Defined values +#define NMESH 54 // The number of meshes (in the models-textures dir) +#define NTEXTURE 30 // The number of textures (in the models-textures dir) +#define MAXOBJECTS 256 + +// Meshes and textures arrays +extern mesh* meshes[]; +extern texture* textures[]; + +// Menu arrays +extern const char *textureMenuEntries[]; +extern const char *objectMenuEntries[]; + +// Scene object arrays +extern SceneObject sceneObjs[]; +extern int nObjects; + +// Directories containing models +extern char *dirDefault1; +extern char *dirDefault2; + +// Stores the directory name for the meshes and textures. +extern char dataDir[]; + +// Lighting +extern GLfloat lightColor[]; +extern GLfloat lightPosition[]; + +extern int moving, startx, starty; +extern int lightMoving, lightStartX, lightStartY; + + +extern float jump; +extern float lightAngle, lightHeight; +extern GLfloat angle; +extern GLfloat angle2; + +/* Near and far parameters */ +extern GLfloat near; +extern GLfloat far; + +/* Zoom factor for mouse movements */ +extern GLfloat zoomFactor; + +/* Recursion level for floor drawing */ +extern int drawFloorRecurse; + +/* Size of floor, from -n to n */ +extern int floorSize; + +/* Light 0 parameters */ +extern GLfloat diffuse0[]; +extern GLfloat ambient0[]; +extern GLfloat specular0[]; +extern GLfloat emission0[]; +extern GLfloat light0_pos[]; +extern GLfloat glightmodel[]; + +#endif /* GLOBALS_H */ + diff --git a/helper.c b/helper.c new file mode 100644 index 0000000..d685e51 --- /dev/null +++ b/helper.c @@ -0,0 +1,271 @@ +/** + * Helper Function File + * Contains all of the project's helper functions + * @author Ashley Tyndall (20915779), Jenna de la Harpe (20367932) + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bitmap.h" +#include "types.h" +#include "globals.h" +#include "helper.h" + +/** + * Prints out error message when file cannot be read + * @param fileName Name of file that could not be read + */ +void fileErr(char* fileName) { + printf("Error reading file: %s\n", fileName); + printf("If not in the CSSE labs, you will need to include the directory containing\n"); + printf("the models on the command line, or put it in the same folder as the exectutable."); + exit(EXIT_FAILURE); +} + +/** + * Reads .bmp texture files and converts them to a texture object + * @param fileName .bmp texture file + * @return texture object + */ +texture* loadTexture(char *fileName) { + texture* t = malloc(sizeof (texture)); + BITMAPINFO *info; + + t->rgbData = LoadDIBitmap(fileName, &info); + t->height=info->bmiHeader.biHeight; + t->width=info->bmiHeader.biWidth; + + return t; +} + +/** + * Reads .x files and converts them to a mesh object + * @param fileName .x mesh file + * @return mesh object + */ +mesh* loadMesh(char* fileName) { + mesh* m = malloc(sizeof (mesh)); + FILE* fp = fopen(fileName, "r"); + char line[256] = ""; + int lineBuffSize = 256; + + if(fp == NULL) fileErr(fileName); + + while(strcmp(line,"Mesh {\r\n") != 0 && strcmp(line,"Mesh {\n") != 0 ) + fgets(line, lineBuffSize, fp); + + fscanf(fp, "%d;\n", &(m->nVertices)); + m->vertices = malloc(m->nVertices * sizeof(vertex)); + for(int i=0; i < m->nVertices; i++) + fscanf(fp, "%f; %f; %f;%*[,;]\n", &(m->vertices[i][0]), &(m->vertices[i][1]), &(m->vertices[i][2]) ); + + fscanf(fp, "%d;\n", &(m->nTriangles)); + m->triangles = malloc(m->nTriangles * sizeof(triangle)); + for(int i=0; i < m->nTriangles; i++) + fscanf(fp, "%*d; %d, %d, %d;%*[;,]", m->triangles[i], m->triangles[i]+1, m->triangles[i]+2); + + while(strcmp(line," MeshNormals {\r\n") != 0 && strcmp(line," MeshNormals {\n") != 0) + fgets(line, lineBuffSize, fp); + + fgets(line, lineBuffSize, fp); + m->normals = malloc(m->nVertices * sizeof(normal)); + for(int i=0; i < m->nVertices; i++) + fscanf(fp, "%f; %f; %f;%*[;,]\n", + &(m->normals[i][0]), &(m->normals[i][1]), &(m->normals[i][2])); + + while(strcmp(line,"MeshTextureCoords {\r\n") != 0 && strcmp(line,"MeshTextureCoords {\n") != 0) + fgets(line, lineBuffSize, fp); + + fgets(line, lineBuffSize, fp); + m->texCoords = malloc(m->nVertices * sizeof(texCoord)); + for(int i=0; i < m->nVertices; i++) + fscanf(fp, "%f;%f;%*[,;]\n", &(m->texCoords[i][0]), &(m->texCoords[i][1]) ); + fclose(fp); + + return m; +} + +// [You may want to add to this function.] +/** + * Loads mesh[i] if it isn't already loaded. + * You must call getMesh(i) at least once before using mesh[i]. + * + * @param i Mesh ID + */ +void getMesh(int i) { // getMesh(i) loads mesh[i] if it isn't already loaded. + char fileName[220]; + if(i>=NMESH || i<0) { + printf("Error in getMesh - wrong model number"); + exit(1); + } + if(meshes[i] != NULL) + return; + sprintf(fileName, "%s/model%d.x", dataDir, i+1); + meshes[i] = loadMesh(fileName); +} + +/** + * Loads texture i if it isn't already loaded + * + * After calling getTexture(i), you can make texture i the current texture using + * glBindTexture(GL_TEXTURE_2D, i); + * Use i=0 to return to the default plain texture. + * + * You can then scale the texture via: + * glMatrixMode(GL_TEXTURE); + * See the textbook, section 8.8.3. + * + * You must call getTexture(i) at least once before using texture i. + * @param i Texture ID + */ +void getTexture(int i) { + char fileName[220]; + if(i<1 || i>NTEXTURE) { + printf("Error in getTexture - wrong texture number"); + exit(1); + } + if(textures[i-1] != NULL) + return; + sprintf(fileName, "%s/texture%d.bmp", dataDir, i); + + textures[i-1] = loadTexture(fileName); + + glBindTexture(GL_TEXTURE_2D, i); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, textures[i-1]->width, textures[i-1]->height, + 0, GL_RGB, GL_UNSIGNED_BYTE, textures[i-1]->rgbData); + gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, textures[i-1]->width, textures[i-1]->height, GL_RGB, + GL_UNSIGNED_BYTE, textures[i-1]->rgbData); + 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_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + + glBindTexture(GL_TEXTURE_2D, 0); // Back to default texture +} + +/** + * Rounds up numbers, from http://stackoverflow.com/questions/3407012/c-rounding-up-to-the-nearest-multiple-of-a-number + * @param numToRound Number to round + * @param multiple Multiple to round up to + * @return Rounded number + */ +int roundUp(int numToRound, int multiple) { + if(multiple == 0) { + return numToRound; + } + + int remainder = numToRound % multiple; + if (remainder == 0) + return numToRound; + return numToRound + multiple - remainder; +} + +/** + * Makes a submenu from an array of items, splitting the list into subsubmenus + * of only 10 items. + * @param menuEntries Array of menu items + * @param menuEntriesSize Size of menuEntries + * @param callback Callback function for this array of menu items + * @return Reference to menu created + */ +int makeSubmenuFromArray( const char *menuEntries[], unsigned int menuEntriesSize, void *callback ) { + if ( menuEntriesSize == 0 ) return -1; + + int menuNumber = roundUp(menuEntriesSize, 10) / 10; + int submenuObjects[menuNumber-1]; + + for( int i = 0; i < menuNumber; i++ ) { + submenuObjects[i] = glutCreateMenu(callback); + int startNum = i*11 - (i-1); + for ( int j = startNum - 1; j < (startNum+9); j++ ) { + if ( j == menuEntriesSize ) break; // Detect if we've reached the end of the array + glutAddMenuEntry( menuEntries[j], j + 1 ); + } + } + + int mainMenu = glutCreateMenu(callback); + for ( int i = 0; i < menuNumber; i++ ) { + char name[10]; // buffer to hold name + int startNum = i*11 - (i-1); + int endNum = startNum + 9; + if ( i == menuNumber - 1 ) { // We're on the last one + endNum = startNum + (menuEntriesSize - startNum); // Work out final number + } + sprintf(name, "%d-%d", startNum, endNum); + glutAddSubMenu( name, submenuObjects[i] ); + } + + return mainMenu; +} + +/** + * Recursive function to draw a square by drawing smaller and smaller + * divisions of the square, determined by drawFloorRecurse. + * @param recurseLevel Current level of recursion, only pass 0 + * @param x1 top-left x + * @param z1 top-left z + * @param x2 bottom-left x + * @param z2 bottom-left z + */ +void drawSquare(int recurseLevel, float x1, float z1, float x2, float z2) { + + if ( drawFloorRecurse != recurseLevel ) { + // Calculate middle points + float xm = (x1 + x2) / 2.0; + float zm = (z1 + z2) / 2.0; + + // Increment recursion level + int rnew = recurseLevel + 1; + + // Split into four sub-quads + drawSquare(rnew, x1, z1, xm, zm); + drawSquare(rnew, x1, zm, xm, z2); + drawSquare(rnew, xm, zm, x2, z2); + drawSquare(rnew, xm, z1, x2, zm); + + } else { + // Draw square. + // **NOTE: Is the polygon facing in the right direction? + glBegin(GL_QUADS); + glVertex3f(x1, 0.0, z1); + glVertex3f(x1, 0.0, z2); + glVertex3f(x2, 0.0, z2); + glVertex3f(x2, 0.0, z1); + glEnd(); + } + +} + +/** + * Draw a floor by calling the drawSquare recursion + */ +void drawFloor() { + drawSquare(0, -floorSize, -floorSize, floorSize, floorSize); +} + +/** + * Draw x, z axis on floor + */ +void drawLine() { + // **NOTE: fix function + glDisable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glColor4ub( 0.0, 0.0, 0.0, 0.5 ); + + glBegin(GL_LINES); + glVertex3i( 10.0, 0.1, 10.0); + glVertex3i( -10.0, 0.1, -10.0); + glEnd(); + + glDisable(GL_BLEND); + glEnable(GL_TEXTURE_2D); +} \ No newline at end of file diff --git a/helper.h b/helper.h new file mode 100644 index 0000000..9dccd18 --- /dev/null +++ b/helper.h @@ -0,0 +1,25 @@ +/** + * Helper Function Header File + * Contains forward declarations of all of the project's helper functions + * @author Ashley Tyndall (20915779), Jenna de la Harpe (20367932) + */ + +#ifndef HELPER_H +#define HELPER_H + +void fileErr(char* fileName); + +texture* loadTexture(char *fileName); +mesh* loadMesh(char* fileName); + +void getMesh(int i); +void getTexture(int i); +int roundUp(int numToRound, int multiple); + +int makeSubmenuFromArray( const char *menuEntries[], unsigned int menuEntriesSize, void *callback ); + +void drawSquare(int recurseLevel, float x1, float z1, float x2, float z2); +void drawFloor(); +void drawLine(); + +#endif /* HELPER_H */ diff --git a/scene.c b/scene.c index 2e2f93c..61cddf9 100644 --- a/scene.c +++ b/scene.c @@ -13,269 +13,11 @@ #include #include "bitmap.h" +#include "globals.h" +#include "helper.h" +#include "types.h" +#include "scene.h" -// Type definitions for vertex-coordinates, normals, texture-coordinates, -// and triangles (via the indices of 3 vertices). -typedef GLfloat vertex[3]; -typedef GLfloat normal[3]; -typedef GLfloat texCoord[2]; -typedef GLint vertexIndex; -typedef vertexIndex triangle[3]; - -// A type for a mesh -typedef struct { - int nVertices; // The number of vertices in the mesh - vertex* vertices; // Array with coordinates of vertices - normal* normals; // Array with normals of vertices - texCoord* texCoords; // Array with texture-coordinates of vertices - int nTriangles; // The number of triangles in the mesh - triangle* triangles; // Array of trangles via 3 indices into "vertices" -} mesh; - -#define NMESH 54 // The number of meshes (in the models-textures dir) -mesh* meshes[NMESH]; // An array of pointers to the meshes - see getMesh - -// A type for a 2D texture, with height and width in pixels -typedef struct { - int height; - int width; - GLubyte *rgbData; // Array of bytes with the colour data for the texture -} texture; - -#define NTEXTURE 30 // The number of textures (in the models-textures dir) -texture* textures[NTEXTURE]; // An array of texture pointers - see getTexture - -typedef struct { - // You'll need to add scale, rotation, material, mesh number, etc., - // to this structure - float x,y,z; -} SceneObject; - -// Menu enum -enum menu { - // Main menu - ROTATE_MOVE_CAMERA, - POSITION_SCALE, - ROTATION_TEXTURE_SCALE, - EXIT, - - // Material submenu - MATERIAL_ALL_RGB, - MATERIAL_AMBIENT_RGB, - MATERIAL_DIFFUSE_RGB, - MATERIAL_SPECULAR_RGB, - MATERIAL_ALL_ADSS, - MATERIAL_RED_ADSS, - MATERIAL_GREEN_ADSS, - MATERIAL_BLUE_ADSS, - - // Light submenu - LIGHT_MOVE_LIGHT_1, - LIGHT_RGBALL_LIGHT_1, - LIGHT_MOVE_LIGHT_2, - LIGHT_RGBALL_LIGHT_2 -}; - -// Menu arrays -const char *textureMenuEntries[NTEXTURE] = { - "1 Plain", "2 Rust", "3 Concrete", "4 Carpet", "5 Beach Sand", - "6 Rocky", "7 Brick", "8 Water", "9 Paper", "10 Marble", - "11 Wood", "12 Scales", "13 Fur", "14 Denim", "15 Hessian", - "16 Orange Peel", "17 Ice Crystals", "18 Grass", "19 Corrugated Iron", "20 Styrofoam", - "21 Bubble Wrap", "22 Leather", "23 Camouflage", "24 Asphalt", "25 Scratched Ice", - "26 Rattan", "27 Snow", "28 Dry Mud", "29 Old Concrete", "30 Leopard Skin" -}; - -const char *objectMenuEntries[NMESH] = { - "1 Thin Dinosaur","2 Big Dog","3 Saddle Dinosaur", "4 Dragon", "5 Cleopatra", - "6 Bone I", "7 Bone II", "8 Rabbit", "9 Long Dragon", "10 Buddha", - "11 Sitting Rabbit", "12 Frog", "13 Cow", "14 Monster", "15 Sea Horse", - "16 Head", "17 Pelican", "18 Horse", "19 Kneeling Angel", "20 Porsche I", - "21 Truck", "22 Statue of Liberty", "23 Sitting Angel", "24 Metal Part", "25 Car", - "26 Apatosaurus", "27 Airliner", "28 Motorbike", "29 Dolphin", "30 Spaceman", - "31 Winnie the Pooh", "32 Shark", "33 Crocodile", "34 Toddler", "35 Fat Dinosaur", - "36 Chihuahua", "37 Sabre-toothed Tiger", "38 Lioness", "39 Fish", "40 Horse (head down)", - "41 Horse (head up)", "42 Skull", "43 Fighter Jet I", "44 Toad", "45 Convertible", - "46 Porsche II", "47 Hare", "48 Vintage Car", "49 Fighter Jet II", "50 Winged Monkey", - "51 Chef", "52 Parasaurolophus", "53 Rooster", "54 T-rex" -}; - -#define MAXOBJECTS 256 -SceneObject sceneObjs[MAXOBJECTS]; // An array with details of the objects in a scene -int nObjects=0; // How many objects there are in the scene currently. - -// Directories containing models -char *dirDefault1 = "models-textures"; -char *dirDefault2 = "/cslinux/examples/CITS2231/project-files/models-textures"; - -char dataDir[200]; // Stores the directory name for the meshes and textures. - -static GLfloat lightColor[] = {1.0, 1.0, 1.0, 1.0}; // White light -static GLfloat lightPosition[4]; - -int moving, startx, starty; -int lightMoving = 0, lightStartX, lightStartY; - -/* Time varying or user-controled variables. */ -static float jump = 0.0; -static float lightAngle = 0.0, lightHeight = 5; -GLfloat angle = -150; /* in degrees */ -GLfloat angle2 = 30; /* in degrees */ - -/* Near and far parameters */ -GLfloat near = -100; -GLfloat far = 100; - -/* Zoom factor for mouse movements */ -GLfloat zoomFactor = 1.0; - -/* Recursion level for floor drawing */ -int drawFloorRecurse = 5; - -/* Size of floor, from -n to n */ -int floorSize = 200; - -/* Light 0 parameters */ -GLfloat diffuse0[] = {1.0, 1.0, 1.0, 1.0}; -GLfloat ambient0[] = {0.0, 0.0, 0.0, 1.0}; -GLfloat specular0[] = {1.0, 1.0, 1.0, 1.0}; -GLfloat emission0[] = {0.0, 0.0, 0.0, 0.0}; -GLfloat light0_pos[] ={1.0, 1.0, 0,0, 1.0}; -GLfloat glightmodel[] = {0.2,0.2,0.2,1}; - - -/** - * Prints out error message when file cannot be read - * @param fileName Name of file that could not be read - */ -void fileErr(char* fileName) { - printf("Error reading file: %s\n", fileName); - printf("If not in the CSSE labs, you will need to include the directory containing\n"); - printf("the models on the command line, or put it in the same folder as the exectutable."); - exit(EXIT_FAILURE); -} - -/** - * Reads .bmp texture files and converts them to a texture object - * @param fileName .bmp texture file - * @return texture object - */ -texture* loadTexture(char *fileName) { - texture* t = malloc(sizeof (texture)); - BITMAPINFO *info; - - t->rgbData = LoadDIBitmap(fileName, &info); - t->height=info->bmiHeader.biHeight; - t->width=info->bmiHeader.biWidth; - - return t; -} - -/** - * Reads .x files and converts them to a mesh object - * @param fileName .x mesh file - * @return mesh object - */ -mesh* loadMesh(char* fileName) { - mesh* m = malloc(sizeof (mesh)); - FILE* fp = fopen(fileName, "r"); - char line[256] = ""; - int lineBuffSize = 256; - - if(fp == NULL) fileErr(fileName); - - while(strcmp(line,"Mesh {\r\n") != 0 && strcmp(line,"Mesh {\n") != 0 ) - fgets(line, lineBuffSize, fp); - - fscanf(fp, "%d;\n", &(m->nVertices)); - m->vertices = malloc(m->nVertices * sizeof(vertex)); - for(int i=0; i < m->nVertices; i++) - fscanf(fp, "%f; %f; %f;%*[,;]\n", &(m->vertices[i][0]), &(m->vertices[i][1]), &(m->vertices[i][2]) ); - - fscanf(fp, "%d;\n", &(m->nTriangles)); - m->triangles = malloc(m->nTriangles * sizeof(triangle)); - for(int i=0; i < m->nTriangles; i++) - fscanf(fp, "%*d; %d, %d, %d;%*[;,]", m->triangles[i], m->triangles[i]+1, m->triangles[i]+2); - - while(strcmp(line," MeshNormals {\r\n") != 0 && strcmp(line," MeshNormals {\n") != 0) - fgets(line, lineBuffSize, fp); - - fgets(line, lineBuffSize, fp); - m->normals = malloc(m->nVertices * sizeof(normal)); - for(int i=0; i < m->nVertices; i++) - fscanf(fp, "%f; %f; %f;%*[;,]\n", - &(m->normals[i][0]), &(m->normals[i][1]), &(m->normals[i][2])); - - while(strcmp(line,"MeshTextureCoords {\r\n") != 0 && strcmp(line,"MeshTextureCoords {\n") != 0) - fgets(line, lineBuffSize, fp); - - fgets(line, lineBuffSize, fp); - m->texCoords = malloc(m->nVertices * sizeof(texCoord)); - for(int i=0; i < m->nVertices; i++) - fscanf(fp, "%f;%f;%*[,;]\n", &(m->texCoords[i][0]), &(m->texCoords[i][1]) ); - fclose(fp); - - return m; -} - -// [You may want to add to this function.] -/** - * Loads mesh[i] if it isn't already loaded. - * You must call getMesh(i) at least once before using mesh[i]. - * - * @param i Mesh ID - */ -void getMesh(int i) { // getMesh(i) loads mesh[i] if it isn't already loaded. - char fileName[220]; - if(i>=NMESH || i<0) { - printf("Error in getMesh - wrong model number"); - exit(1); - } - if(meshes[i] != NULL) - return; - sprintf(fileName, "%s/model%d.x", dataDir, i+1); - meshes[i] = loadMesh(fileName); -} - -/** - * Loads texture i if it isn't already loaded - * - * After calling getTexture(i), you can make texture i the current texture using - * glBindTexture(GL_TEXTURE_2D, i); - * Use i=0 to return to the default plain texture. - * - * You can then scale the texture via: - * glMatrixMode(GL_TEXTURE); - * See the textbook, section 8.8.3. - * - * You must call getTexture(i) at least once before using texture i. - * @param i Texture ID - */ -void getTexture(int i) { - char fileName[220]; - if(i<1 || i>NTEXTURE) { - printf("Error in getTexture - wrong texture number"); - exit(1); - } - if(textures[i-1] != NULL) - return; - sprintf(fileName, "%s/texture%d.bmp", dataDir, i); - - textures[i-1] = loadTexture(fileName); - - glBindTexture(GL_TEXTURE_2D, i); - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, textures[i-1]->width, textures[i-1]->height, - 0, GL_RGB, GL_UNSIGNED_BYTE, textures[i-1]->rgbData); - gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, textures[i-1]->width, textures[i-1]->height, GL_RGB, - GL_UNSIGNED_BYTE, textures[i-1]->rgbData); - 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_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - - glBindTexture(GL_TEXTURE_2D, 0); // Back to default texture -} /** * Event hander for main menu events @@ -283,19 +25,19 @@ void getTexture(int i) { */ void processMainEvents(int id) { switch (id) { - case ROTATE_MOVE_CAMERA: + case M_ROTATE_MOVE_CAMERA: // Do stuff break; - case POSITION_SCALE: + case M_POSITION_SCALE: // Do stuff break; - case ROTATION_TEXTURE_SCALE: + case M_ROTATION_TEXTURE_SCALE: // Do stuff break; - case EXIT: + case M_EXIT: exit(EXIT_SUCCESS); } @@ -307,35 +49,35 @@ void processMainEvents(int id) { */ void processMaterialEvents(int id) { switch (id) { - case MATERIAL_ALL_RGB: + case M_MATERIAL_ALL_RGB: // Do stuff break; - case MATERIAL_AMBIENT_RGB: + case M_MATERIAL_AMBIENT_RGB: // Do stuff break; - case MATERIAL_DIFFUSE_RGB: + case M_MATERIAL_DIFFUSE_RGB: // Do stuff break; - case MATERIAL_SPECULAR_RGB: + case M_MATERIAL_SPECULAR_RGB: // Do stuff break; - case MATERIAL_ALL_ADSS: + case M_MATERIAL_ALL_ADSS: // Do stuff break; - case MATERIAL_RED_ADSS: + case M_MATERIAL_RED_ADSS: // Do stuff break; - case MATERIAL_GREEN_ADSS: + case M_MATERIAL_GREEN_ADSS: // Do stuff break; - case MATERIAL_BLUE_ADSS: + case M_MATERIAL_BLUE_ADSS: // Do stuff break; @@ -348,19 +90,19 @@ void processMaterialEvents(int id) { */ void processLightEvents(int id) { switch (id) { - case LIGHT_MOVE_LIGHT_1: + case M_LIGHT_MOVE_LIGHT_1: // Do stuff break; - case LIGHT_RGBALL_LIGHT_1: + case M_LIGHT_RGBALL_LIGHT_1: // Do stuff break; - case LIGHT_MOVE_LIGHT_2: + case M_LIGHT_MOVE_LIGHT_2: // Do stuff break; - case LIGHT_RGBALL_LIGHT_2: + case M_LIGHT_RGBALL_LIGHT_2: // Do stuff break; @@ -391,103 +133,46 @@ void processGTextureEvents(int id) { } -/** - * Rounds up numbers, from http://stackoverflow.com/questions/3407012/c-rounding-up-to-the-nearest-multiple-of-a-number - * @param numToRound Number to round - * @param multiple Multiple to round up to - * @return Rounded number - */ -int roundUp(int numToRound, int multiple) { - if(multiple == 0) { - return numToRound; - } - - int remainder = numToRound % multiple; - if (remainder == 0) - return numToRound; - return numToRound + multiple - remainder; -} - -/** - * Makes a submenu from an array of items, splitting the list into subsubmenus - * of only 10 items. - * @param menuEntries Array of menu items - * @param menuEntriesSize Size of menuEntries - * @param callback Callback function for this array of menu items - * @return Reference to menu created - */ -int makeSubmenuFromArray( const char *menuEntries[], unsigned int menuEntriesSize, void *callback ) { - if ( menuEntriesSize == 0 ) return -1; - - int menuNumber = roundUp(menuEntriesSize, 10) / 10; - int submenuObjects[menuNumber-1]; - - for( int i = 0; i < menuNumber; i++ ) { - submenuObjects[i] = glutCreateMenu(callback); - int startNum = i*11 - (i-1); - for ( int j = startNum - 1; j < (startNum+9); j++ ) { - if ( j == menuEntriesSize ) break; // Detect if we've reached the end of the array - glutAddMenuEntry( menuEntries[j], j + 1 ); - } - } - - int mainMenu = glutCreateMenu(callback); - for ( int i = 0; i < menuNumber; i++ ) { - char name[10]; // buffer to hold name - int startNum = i*11 - (i-1); - int endNum = startNum + 9; - if ( i == menuNumber - 1 ) { // We're on the last one - endNum = startNum + (menuEntriesSize - startNum); // Work out final number - } - sprintf(name, "%d-%d", startNum, endNum); - glutAddSubMenu( name, submenuObjects[i] ); - } - - return mainMenu; -} - /** * Creates menu for program */ void makeMenu() { // Construct material menu int materialMenu = glutCreateMenu(processMaterialEvents); - glutAddMenuEntry("All R/G/B", MATERIAL_ALL_RGB); - glutAddMenuEntry("Ambient R/G/B", MATERIAL_AMBIENT_RGB); - glutAddMenuEntry("Diffuse R/G/B", MATERIAL_DIFFUSE_RGB); - glutAddMenuEntry("Specular R/G/B", MATERIAL_SPECULAR_RGB); - glutAddMenuEntry("All Amb/Diff/Spec/Shine", MATERIAL_ALL_ADSS); - glutAddMenuEntry("Red Amb/Diff/Spec/Shine", MATERIAL_RED_ADSS); - glutAddMenuEntry("Green Amb/Diff/Spec/Shine", MATERIAL_GREEN_ADSS); - glutAddMenuEntry("Blue Amb/Diff/Spec/Shine", MATERIAL_BLUE_ADSS); + glutAddMenuEntry("All R/G/B", M_MATERIAL_ALL_RGB); + glutAddMenuEntry("Ambient R/G/B", M_MATERIAL_AMBIENT_RGB); + glutAddMenuEntry("Diffuse R/G/B", M_MATERIAL_DIFFUSE_RGB); + glutAddMenuEntry("Specular R/G/B", M_MATERIAL_SPECULAR_RGB); + glutAddMenuEntry("All Amb/Diff/Spec/Shine", M_MATERIAL_ALL_ADSS); + glutAddMenuEntry("Red Amb/Diff/Spec/Shine", M_MATERIAL_RED_ADSS); + glutAddMenuEntry("Green Amb/Diff/Spec/Shine", M_MATERIAL_GREEN_ADSS); + glutAddMenuEntry("Blue Amb/Diff/Spec/Shine", M_MATERIAL_BLUE_ADSS); // Construct light menu int lightMenu = glutCreateMenu(processLightEvents); - glutAddMenuEntry("Move Light 1", LIGHT_MOVE_LIGHT_1); - glutAddMenuEntry("R/G/B/All Light 1", LIGHT_RGBALL_LIGHT_1); - glutAddMenuEntry("Move Light 2", LIGHT_MOVE_LIGHT_2); - glutAddMenuEntry("R/G/B/All Light 2", LIGHT_RGBALL_LIGHT_2); + glutAddMenuEntry("Move Light 1", M_LIGHT_MOVE_LIGHT_1); + glutAddMenuEntry("R/G/B/All Light 1", M_LIGHT_RGBALL_LIGHT_1); + glutAddMenuEntry("Move Light 2", M_LIGHT_MOVE_LIGHT_2); + glutAddMenuEntry("R/G/B/All Light 2", M_LIGHT_RGBALL_LIGHT_2); // Construct object menu - int objectMenuEntriesSize = sizeof(objectMenuEntries) / sizeof(objectMenuEntries[0]); - int objectMenu = makeSubmenuFromArray( objectMenuEntries, objectMenuEntriesSize, processObjectEvents ); + int objectMenu = makeSubmenuFromArray( objectMenuEntries, NMESH, processObjectEvents ); // Construct texture / ground texture menus - int textureMenuEntriesSize = sizeof(textureMenuEntries) / sizeof(textureMenuEntries[0]); - int textureMenu = makeSubmenuFromArray( textureMenuEntries, textureMenuEntriesSize, processTextureEvents ); - int gTextureMenu = makeSubmenuFromArray( textureMenuEntries, textureMenuEntriesSize, processGTextureEvents ); + int textureMenu = makeSubmenuFromArray( textureMenuEntries, NTEXTURE, processTextureEvents ); + int gTextureMenu = makeSubmenuFromArray( textureMenuEntries, NTEXTURE, processGTextureEvents ); // Construct main menu glutCreateMenu(processMainEvents); - //glutAddMenuEntry("Rotate/Move Camera", ROTATE_MOVE_CAMERA); + //glutAddMenuEntry("Rotate/Move Camera", M_ROTATE_MOVE_CAMERA); //glutAddSubMenu("Add object", objectMenu); - //glutAddMenuEntry("Position/Scale", POSITION_SCALE); - //glutAddMenuEntry("Rotation/Texture Scale", ROTATION_TEXTURE_SCALE); + //glutAddMenuEntry("Position/Scale", M_POSITION_SCALE); + //glutAddMenuEntry("Rotation/Texture Scale", M_ROTATION_TEXTURE_SCALE); //glutAddSubMenu("Material", materialMenu); //glutAddSubMenu("Texture", textureMenu); //glutAddSubMenu("Ground texture", gTextureMenu); //glutAddSubMenu("Lights", lightMenu); - glutAddMenuEntry("Exit", EXIT); + glutAddMenuEntry("Exit", M_EXIT); // Bind to right mouse button glutAttachMenu(GLUT_RIGHT_BUTTON); @@ -564,70 +249,6 @@ void motion(int x, int y) { } } -/** - * Recursive function to draw a square by drawing smaller and smaller - * divisions of the square, determined by drawFloorRecurse. - * @param recurseLevel Current level of recursion, only pass 0 - * @param x1 top-left x - * @param z1 top-left z - * @param x2 bottom-left x - * @param z2 bottom-left z - */ -void drawSquare(int recurseLevel, float x1, float z1, float x2, float z2) { - - if ( drawFloorRecurse != recurseLevel ) { - // Calculate middle points - float xm = (x1 + x2) / 2.0; - float zm = (z1 + z2) / 2.0; - - // Increment recursion level - int rnew = recurseLevel + 1; - - // Split into four sub-quads - drawSquare(rnew, x1, z1, xm, zm); - drawSquare(rnew, x1, zm, xm, z2); - drawSquare(rnew, xm, zm, x2, z2); - drawSquare(rnew, xm, z1, x2, zm); - - } else { - // Draw square. - // **NOTE: Is the polygon facing in the right direction? - glBegin(GL_QUADS); - glVertex3f(x1, 0.0, z1); - glVertex3f(x1, 0.0, z2); - glVertex3f(x2, 0.0, z2); - glVertex3f(x2, 0.0, z1); - glEnd(); - } - -} - -/** - * Draw a floor by calling the drawSquare recursion - */ -void drawFloor() { - drawSquare(0, -floorSize, -floorSize, floorSize, floorSize); -} - -/** - * Draw x, z axis on floor - */ -void drawLine() { - // **NOTE: fix function - glDisable(GL_TEXTURE_2D); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glColor4ub( 0.0, 0.0, 0.0, 0.5 ); - - glBegin(GL_LINES); - glVertex3i( 10.0, 0.1, 10.0); - glVertex3i( -10.0, 0.1, -10.0); - glEnd(); - - glDisable(GL_BLEND); - glEnable(GL_TEXTURE_2D); -} - /** * Display function */ diff --git a/scene.h b/scene.h new file mode 100644 index 0000000..57fb933 --- /dev/null +++ b/scene.h @@ -0,0 +1,27 @@ +/** + * Main File Header + * @author Ashley Tyndall (20915779), Jenna de la Harpe (20367932) + */ + +#ifndef SCENE_H +#define SCENE_H + +void processMainEvents(int id); +void processMaterialEvents(int id); +void processLightEvents(int id); +void processObjectEvents(int id); +void processTextureEvents(int id); +void processGTextureEvents(int id); + +void makeMenu(); + +void windowReshape(int w, int h); +void mouse(int button, int state, int x, int y); +void motion(int x, int y); + +void display(); +void init(); +int main(int argc, char **argv); + +#endif /* SCENE_H */ + diff --git a/types.h b/types.h new file mode 100644 index 0000000..573418d --- /dev/null +++ b/types.h @@ -0,0 +1,69 @@ +/** + * Type definition file + * @author Ashley Tyndall (20915779), Jenna de la Harpe (20367932) + */ + +#include +#include + +#ifndef TYPES_H +#define TYPES_H + +// Type definitions for vertex-coordinates, normals, texture-coordinates, +// and triangles (via the indices of 3 vertices). +typedef GLfloat vertex[3]; +typedef GLfloat normal[3]; +typedef GLfloat texCoord[2]; +typedef GLint vertexIndex; +typedef vertexIndex triangle[3]; + +// A type for a mesh +typedef struct { + int nVertices; // The number of vertices in the mesh + vertex* vertices; // Array with coordinates of vertices + normal* normals; // Array with normals of vertices + texCoord* texCoords; // Array with texture-coordinates of vertices + int nTriangles; // The number of triangles in the mesh + triangle* triangles; // Array of trangles via 3 indices into "vertices" +} mesh; + +// A type for a 2D texture, with height and width in pixels +typedef struct { + int height; + int width; + GLubyte *rgbData; // Array of bytes with the colour data for the texture +} texture; + +typedef struct { + // You'll need to add scale, rotation, material, mesh number, etc., + // to this structure + float x,y,z; +} SceneObject; + +// Menu enum +enum menu { + // Main menu + M_ROTATE_MOVE_CAMERA, + M_POSITION_SCALE, + M_ROTATION_TEXTURE_SCALE, + M_EXIT, + + // Material submenu + M_MATERIAL_ALL_RGB, + M_MATERIAL_AMBIENT_RGB, + M_MATERIAL_DIFFUSE_RGB, + M_MATERIAL_SPECULAR_RGB, + M_MATERIAL_ALL_ADSS, + M_MATERIAL_RED_ADSS, + M_MATERIAL_GREEN_ADSS, + M_MATERIAL_BLUE_ADSS, + + // Light submenu + M_LIGHT_MOVE_LIGHT_1, + M_LIGHT_RGBALL_LIGHT_1, + M_LIGHT_MOVE_LIGHT_2, + M_LIGHT_RGBALL_LIGHT_2 +}; + +#endif /* TYPES_H */ + -- 2.20.1