X-Git-Url: https://git.ucc.asn.au/?p=atyndall%2Fcits2231.git;a=blobdiff_plain;f=scene.c;h=f50337d5a2795007d2bacbf495301cedf373ec96;hp=9f29cc0ae90cd84bbef9df835fe840f6dda0ed5e;hb=e870d5eada14c45367e8bbd872dc5f9095f8393f;hpb=59ed896916f5a6e79b004534dcc5b988acd7dcf6 diff --git a/scene.c b/scene.c index 9f29cc0..b66be6f 100644 --- a/scene.c +++ b/scene.c @@ -1,9 +1,7 @@ -// compile this program using: -// gcc -O3 -Wall -std=c99 -o scene scene.c bitmap.c -lglut -// Or, with cygwin: (-mno-cygwin is only so the executable runs from windows) -// gcc -mno-cygwin -O3 -Wall -std=c99 -o scene scene.c bitmap.c -lglut32 -lglu32 -lopengl32 -// Or, use make via the supplied Makefile: (For cygwin, install the package for make) -// make +/** + * CITS2231 Graphics Scene Editor + * @author Ashley Tyndall (20915779) + */ #include #include @@ -52,17 +50,92 @@ typedef struct { 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 floorVertices[4][3] = { + { -1000.0, 0.0, 1000.0 }, + { 1000.0, 0.0, 1000.0 }, + { 1000.0, 0.0, -1000.0 }, + { -1000.0, 0.0, -1000.0 }, +}; + +static GLfloat lightColor[] = {1.0, 1.0, 1.0, 1.0}; // White light +static GLfloat lightPosition[4]; +static float lightAngle = 10.0, lightHeight = 20; + +/** + * 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(1); + 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; @@ -74,8 +147,11 @@ texture* loadTexture(char *fileName) { return t; } -// The following works for the supplied .x files -// but probably not for .x files from other sources. +/** + * 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"); @@ -118,11 +194,13 @@ mesh* loadMesh(char* fileName) { return m; } -char dataDir[200]; // Stores the directory name for the meshes and textures. - -// getMesh(i) loads mesh[i] if it isn't already loaded. -// You must call getMesh(i) at least once before using mesh[i]. // [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) { @@ -135,13 +213,21 @@ void getMesh(int i) { // getMesh(i) loads mesh[i] if it isn't already loaded. meshes[i] = loadMesh(fileName); } -// getTexture(i) 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: (See the textbook, section 8.8.3.) -// glMatrixMode(GL_TEXTURE); -// You must call getTexture(i) at least once before using texture i. -void getTexture(int i) { // getTexture(i) loads texture i if it isn't already loaded. +/** + * 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"); @@ -167,87 +253,178 @@ void getTexture(int i) { // getTexture(i) loads texture i if it isn't already lo glBindTexture(GL_TEXTURE_2D, 0); // Back to default texture } -// Menu enum -enum menu { - // Main menu - ROTATE_MOVE_CAMERA, - POSITION_SCALE, - ROTATION_TEXTURE_SCALE, - EXIT, +/** + * Event hander for main menu events + * @param id ID of menu item selected + */ +void processMainEvents(int id) { + switch (id) { + case ROTATE_MOVE_CAMERA: + // Do stuff + break; - // 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, + case POSITION_SCALE: + // Do stuff + break; - // Light submenu - LIGHT_MOVE_LIGHT_1, - LIGHT_RGBALL_LIGHT_1, - LIGHT_MOVE_LIGHT_2, - LIGHT_RGBALL_LIGHT_2 -}; + case ROTATION_TEXTURE_SCALE: + // Do stuff + break; -// 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" -}; + case EXIT: + exit(EXIT_SUCCESS); -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" -}; + } +} +/** + * Event hander for materials menu events + * @param id ID of menu item selected + */ +void processMaterialEvents(int id) { + switch (id) { + case MATERIAL_ALL_RGB: + // Do stuff + break; + case MATERIAL_AMBIENT_RGB: + // Do stuff + break; -void processMainEvents(int id) { - switch (id) { - case EXIT: - exit(0); + case MATERIAL_DIFFUSE_RGB: + // Do stuff + break; + + case MATERIAL_SPECULAR_RGB: + // Do stuff + break; + + case MATERIAL_ALL_ADSS: + // Do stuff + break; + + case MATERIAL_RED_ADSS: + // Do stuff + break; + + case MATERIAL_GREEN_ADSS: + // Do stuff + break; + + case MATERIAL_BLUE_ADSS: + // Do stuff + break; } } -void processObjectEvents(int id) { +/** + * Event hander for light menu events + * @param id ID of menu item selected + */ +void processLightEvents(int id) { + switch (id) { + case LIGHT_MOVE_LIGHT_1: + // Do stuff + break; + + case LIGHT_RGBALL_LIGHT_1: + // Do stuff + break; + + case LIGHT_MOVE_LIGHT_2: + // Do stuff + break; + case LIGHT_RGBALL_LIGHT_2: + // Do stuff + break; + + } } -void processMaterialEvents(int id) { +/** + * Event hander for object menu events + * @param id ID of object selected + */ +void processObjectEvents(int id) { } +/** + * Event hander for texture menu events + * @param id ID of texutre selected + */ void processTextureEvents(int id) { } +/** + * Event hander for ground texture menu events + * @param id ID of ground texture selected + */ void processGTextureEvents(int id) { } -void processLightEvents(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); @@ -267,85 +444,207 @@ void makeMenu() { glutAddMenuEntry("Move Light 2", LIGHT_MOVE_LIGHT_2); glutAddMenuEntry("R/G/B/All Light 2", LIGHT_RGBALL_LIGHT_2); - // Construct add object submenus + // Construct object menu int objectMenuEntriesSize = sizeof(objectMenuEntries) / sizeof(objectMenuEntries[0]); - int menuNumber = objectMenuEntriesSize / 10 + 1; - int addObjectSubmenu[menuNumber-1]; - - for( int i = 0; i < menuNumber; i++ ) { - addObjectSubmenu[i] = glutCreateMenu(processObjectEvents); - int startNum = i*11 - (i-1); - for ( int j = startNum - 1; j < (startNum+9); j++ ) { - if ( j == objectMenuEntriesSize ) break; // Detect if we've reached the end of the array - glutAddMenuEntry( objectMenuEntries[j], j ); - } - } - - // Construct add object menu - int addObjectMenu = glutCreateMenu(processObjectEvents); - 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 + 3; - } - sprintf(name, "%d-%d", startNum, endNum); - glutAddSubMenu( name, addObjectSubmenu[i] ); - } - + int objectMenu = makeSubmenuFromArray( objectMenuEntries, objectMenuEntriesSize, 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 ); + + // Construct main menu + glutCreateMenu(processMainEvents); + //glutAddMenuEntry("Rotate/Move Camera", ROTATE_MOVE_CAMERA); + //glutAddSubMenu("Add object", objectMenu); + //glutAddMenuEntry("Position/Scale", POSITION_SCALE); + //glutAddMenuEntry("Rotation/Texture Scale", ROTATION_TEXTURE_SCALE); + //glutAddSubMenu("Material", materialMenu); + //glutAddSubMenu("Texture", textureMenu); + //glutAddSubMenu("Ground texture", gTextureMenu); + //glutAddSubMenu("Lights", lightMenu); + glutAddMenuEntry("Exit", EXIT); - int mainMenu = glutCreateMenu(processMainEvents); + // Bind to right mouse button + glutAttachMenu(GLUT_RIGHT_BUTTON); +} - glutAddMenuEntry("Rotate/Move Camera", ROTATE_MOVE_CAMERA); - glutAddSubMenu("Add object", addObjectMenu); - glutAddMenuEntry("Position/Scale", POSITION_SCALE); - glutAddMenuEntry("Rotation/Texture Scale", ROTATION_TEXTURE_SCALE); - //material - - +/** + * Called when window is resized + * @param w New width + * @param h New height + */ +void windowReshape(int w, int h) { + GLdouble near = -10.0; + GLdouble far = 10.0; + + glViewport(0, 0, (GLsizei) w, (GLsizei) h); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + if (w <= h) + glOrtho(near, far, near*(GLfloat)h/(GLfloat)w, + far*(GLfloat)h/(GLfloat)w, near, far); + else + glOrtho(near*(GLfloat)w/(GLfloat)h, + far*(GLfloat)w/(GLfloat)h, near, far, near, far); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); +} - glutSetMenu(mainMenu); - glutAddSubMenu("Material", materialMenu); +/** + * Called when mouse event occurs + * @param btn Mouse button + * @param state State of mouse button + * @param x Mouse x position + * @param y Mouse y position + */ +void mouse(int btn, int state, int x, int y) { - //texture - //ground texture - //lights - - - glutAddMenuEntry("Exit", EXIT); +} - glutAttachMenu(GLUT_RIGHT_BUTTON); +/** + * Draw a floor. + */ +void drawFloor() { + glDisable(GL_LIGHTING); + + //if (useTexture) { + // glEnable(GL_TEXTURE_2D); + //} + + glBegin(GL_QUADS); + glTexCoord2f(0.0, 0.0); + glVertex3fv(floorVertices[0]); + glTexCoord2f(0.0, 16.0); + glVertex3fv(floorVertices[1]); + glTexCoord2f(16.0, 16.0); + glVertex3fv(floorVertices[2]); + glTexCoord2f(16.0, 0.0); + glVertex3fv(floorVertices[3]); + glEnd(); + + /*if (useTexture) { + glDisable(GL_TEXTURE_2D); + }*/ + + glEnable(GL_LIGHTING); } +/** + * Display function + */ void display() { - // You probably want to change both of the following. - glClear(GL_COLOR_BUFFER_BIT); - glFlush(); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt( + 0.0, 90.0, 60.0, /* eye is at (x,y,z) */ + 0.0, 0.0, 0.0, /* center is at (x,y,z) */ + 0.0, 100.0, 0.0 /* up is in postivie Y direction */ + ); + + /* Reposition the light source. */ + lightPosition[0] = 12*cos(lightAngle); + lightPosition[1] = lightHeight; + lightPosition[2] = 12*sin(lightAngle); + lightPosition[3] = 0.0; + + glPushMatrix(); + glLightfv(GL_LIGHT0, GL_POSITION, lightPosition); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + drawFloor(); + glDisable(GL_BLEND); + + glPushMatrix(); + glLoadIdentity(); + glTranslatef(0.0, 0.0, 0.0); + + glutSolidTeapot(5); // Draw teapot for test + glPopMatrix(); + + glPushMatrix(); + glDisable(GL_LIGHTING); + glLoadIdentity(); + glColor3f(1.0, 1.0, 1.0); + + /* Draw a yellow ball at the light source. */ + glTranslatef(lightPosition[0], lightPosition[1], lightPosition[2]); + glutSolidSphere(1.0, 5, 5); + + glEnable(GL_LIGHTING); + glPopMatrix(); + + glPopMatrix(); + + glutSwapBuffers(); } -char *dirDefault1 = "models-textures"; -char *dirDefault2 = "/cslinux/examples/CITS2231/project-files/models-textures"; +/** + * init function; sets initial OpenGL state + */ +void init() { + glMatrixMode(GL_PROJECTION); + + gluPerspective( + 60.0, /* field of view in degree */ + 1.0, /* aspect ratio */ + 0.0, /* Z near */ + 900.0 /* Z far */ + ); + + glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1); + glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColor); + glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 0.1); + glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.05); + glEnable(GL_LIGHT0); + glEnable(GL_LIGHTING); +} + +/** + * Main function + * @param argc Number of arguments + * @param argv Array of arguments + * @return Program exit code + */ int main(int argc, char **argv) { + if(argc>1) + strcpy(dataDir, argv[1]); + else if(opendir(dirDefault1)) + strcpy(dataDir, dirDefault1); + else if(opendir(dirDefault2)) + strcpy(dataDir, dirDefault2); + else fileErr(dirDefault1); + + for(int i=0; i1) - strcpy(dataDir, argv[1]); - else if(opendir(dirDefault1)) - strcpy(dataDir, dirDefault1); - else if(opendir(dirDefault2)) - strcpy(dataDir, dirDefault2); - else fileErr(dirDefault1); + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); - for(int i=0; i