#include #include #include #include //#include // Header File For The Glaux Library #include "glui.h" #include "utilz.h" GLImage myTextureImage; //--------------------------- // Function prototype section int LoadPPMTexture(char *name); int objload(char *name,OBJECT *k); // Loads Object From File (name) bool ComputeVertexNormal (int num, VERTEX *pOut); // compute num vertex normal into pOut bool ComputeFaceNormal (VERTEX *p1, VERTEX *p2, VERTEX *p3, VERTEX *pOut); // Compute p1,p2,p3 face normal into pOut void drawVertex(int vert); VERTEX average (int numFace); void renderObject(); //--------------------------- GLuint texture[1]; // Storage For One Texture ( NEW ) int init=0; char displayfilename[50]; int surftype=0; int normals=0; // 0 - Face normals, 1 - Vertex normals; bool rendermode=0; int wireframe; char * filename; int shownormals=0; bool showVertexNormals=false; bool showFaceNormals=false; int maxver; OBJECT cube; VERTEX* faceNormVectors; VERTEX* vertexNormVectors; float xy_aspect; int last_x, last_y; float rotationX = 0.0, rotationY = 0.0; /** These are the live variables passed into GLUI ***/ int scale = 1; int obj_type = 1; int segments = 8; int segments2 = 8; int light0_enabled = 1; float light0_intensity = 1.0; int main_window; int customFlag=0; int show_sphere=1; // glui boolean flag, controls where sphere is rendered int show_torus=1; // glui boolean flag, controls where sphere is rendered int show_axes = 1; // glui boolean flag, controls where sphere is rendered int show_text = 1; // glui boolean flag, controls where sphere is rendered float sphere_rotate[16] = { 1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1 }; // holds the rotating coordinates for the sphere rotate ball control float torus_rotate[16] = { 1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1 }; // holds the rotating coordinates for the torus rotate ball control float view_rotate[16] = { 1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1 }; // holds the rotating coordinates for the objects rotate ball control float obj_pos[] = { 0.0, 0.0, 0.0 }; // holds the translating coordinates for the objects move control int curr_string = 0; // points to the currently selected index in the following array int curr2_string = 0; // points to the currently selected index in the following array char *string_list[] = { "cube.wrl", "icosa.wrl", "beethoven.wrl", "venus.wrl" }; // array of text values (filenames) for the model selection textbox char *texture_list[] = { "cloth.ppm", "stone.ppm", "marble.ppm", "fits.ppm"}; // array of text values (filenames) for the model selection textbox const int texture_num=4; const int text_num=4; int toggleViewControls=1; // boolean value controls whether or not bottom controls window is shown GLfloat lights_rotation[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1 }; // holds the rotating coordinates for the lights rotate ball control /** Pointers to the windows and some of the controls we'll create **/ GLUI *glui, *glui2; GLUI_Checkbox *checkbox; GLUI_Spinner *spinner, *light0_spinner; GLUI_RadioGroup *radio; GLUI_Panel *obj_panel; GLUI_EditText *edittext, *cmd_line, *status_line, *cmd2_line, *status2_line; /********** User IDs for callbacks ********/ #define CMD_LINE_ID 100 #define CMD_STATUS_ID 102 #define TOGGLE_ID 303 #define LOAD_ID 304 #define LOAD_TEXTURE_ID 305 /********** Miscellaneous global variables **********/ GLfloat light0_ambient[] = {0.3f, 0.3f, 0.3f, 1.0f}; GLfloat light0_diffuse[] = {.9f, .9f, 0.5f, 1.0f}; GLfloat light0_position[] = {.5f, .5f, 1.0f, 0.0f}; void printmyArray(int x, int y, unsigned char* data) { int index_X=2; int index_Y=3; int max=100; printf("%d by %d Texture Loaded. \n", x, y); /* for (int i=x-1; i>=0; i--) for (int j=0; jshow(); else glui2->hide(); } if ( control == LOAD_ID ) { if (strlen(cmd_line->get_text())<=1) { retValue=objload(string_list[curr_string],&cube); strcpy(displayfilename, ""); } else { retValue=objload(cmd_line->get_text(),&cube); strcpy(displayfilename, cmd_line->get_text()); } switch (retValue) { case 1: status_line->set_text("File does not exist."); break; case -1: status_line->set_text("File is not VRML."); break; default: status_line->set_text("Model Loaded."); } } if ( control == LOAD_TEXTURE_ID ) { if (strlen(cmd2_line->get_text())<=1) retValue=LoadPPMTexture(texture_list[curr2_string]); else retValue=LoadPPMTexture(cmd2_line->get_text()); switch (retValue) { case 1: status2_line->set_text("File does not exist."); break; case -1: status2_line->set_text("File is not PPM."); break; case -2: status2_line->set_text("Invalid dimensions."); break; default: status2_line->set_text("Texture Loaded."); } } } /**************************************** myGlutKeyboard() **********/ void myGlutKeyboard(unsigned char Key, int x, int y) { switch(Key) { case 27: case 'q': exit(0); break; }; glutPostRedisplay(); } /***************************************** myGlutIdle() ***********/ void myGlutIdle( void ) { /* According to the GLUT specification, the current window is undefined during an idle callback. So we need to explicitly change it if necessary */ if ( glutGetWindow() != main_window ) glutSetWindow(main_window); /* GLUI_Master.sync_live_all(); -- not needed - nothing to sync in this application */ glutPostRedisplay(); } /**************************************** myGlutReshape() *************/ void myGlutReshape( int x, int y ) { int tx, ty, tw, th; GLUI_Master.get_viewport_area( &tx, &ty, &tw, &th ); glViewport( tx, ty, tw, th ); xy_aspect = (float)tw / (float)th; glutPostRedisplay(); } /************************************************** draw_axes() **********/ /* Disables lighting, then draws RGB axes */ void draw_axes( float scale ) { glDisable( GL_LIGHTING ); glPushMatrix(); glScalef( scale, scale, scale ); glBegin( GL_LINES ); glColor3f( 1.0, 0.0, 0.0 ); glVertex3f( .8f, 0.05f, 0.0 ); glVertex3f( 1.0, 0.25f, 0.0 ); /* Letter X */ glVertex3f( 0.8f, .25f, 0.0 ); glVertex3f( 1.0, 0.05f, 0.0 ); glVertex3f( 0.0, 0.0, 0.0 ); glVertex3f( 1.0, 0.0, 0.0 ); /* X axis */ glColor3f( 0.0, 1.0, 0.0 ); glVertex3f( 0.0, 0.0, 0.0 ); glVertex3f( 0.0, 1.0, 0.0 ); /* Y axis */ glColor3f( 0.0, 0.0, 1.0 ); glVertex3f( 0.0, 0.0, 0.0 ); glVertex3f( 0.0, 0.0, 1.0 ); /* Z axis */ glEnd(); glPopMatrix(); glEnable( GL_LIGHTING ); } /*********** temp *******/ /* int LoadBMPTexture(char* filename) // Load Bitmaps And Convert To Textures { int Status=false; // Status Indicator AUX_RGBImageRec *TextureImage[1]; // Create Storage Space For The Texture memset(TextureImage,0,sizeof(void *)*1); // Set The Pointer To NULL // Load The Bitmap, Check For Errors, If Bitmap's Not Found Quit TextureImage[0]=auxDIBImageLoad(filename); Status=true; // Set The Status To TRUE glGenTextures(1, &texture[0]); // Create The Texture printmyArray(TextureImage[0]->sizeX, TextureImage[0]->sizeY, TextureImage[0]->data); // Typical Texture Generation Using Data From The Bitmap glBindTexture(GL_TEXTURE_2D, texture[0]); glTexImage2D(GL_TEXTURE_2D, 0, 3,TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); gluBuild2DMipmaps(GL_TEXTURE_2D,4,TextureImage[0]->sizeX, TextureImage[0]->sizeY,GL_RGBA,GL_UNSIGNED_BYTE,TextureImage[0]->data); glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE); if (TextureImage[0]) // If Texture Exists { if (TextureImage[0]->data) // If Texture Image Exists free(TextureImage[0]->data); // Free The Texture Image Memory free(TextureImage[0]); // Free The Image Structure } return Status; // Return The Status } */ /***************************************** myGlutDisplay() *****************/ void myGlutDisplay( void ) { glClearColor( .9f, .9f, .9f, 1.0f ); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glMatrixMode( GL_PROJECTION ); glLoadIdentity(); glFrustum( -xy_aspect*.04, xy_aspect*.04, -.04, .04, .1, 15.0 ); glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); glMultMatrixf( lights_rotation ); glLightfv(GL_LIGHT0, GL_POSITION, light0_position); glLoadIdentity(); glTranslatef( 0.0, 0.0, -2.6f ); glTranslatef( obj_pos[0], obj_pos[1], -obj_pos[2] ); glMultMatrixf( view_rotate ); glScalef( scale, scale, scale ); /*** Now we render object, using the variables 'obj_type', 'segments', and 'wireframe'. These are _live_ variables, which are transparently updated by GLUI ***/ glPushMatrix(); glTranslatef( 0.8, 0.0, 0.0 ); glMultMatrixf( sphere_rotate ); if ( wireframe && show_sphere) switch (surftype){ case 1: glutWireSphere(0.3, 20, 20); break; case 0: glScalef( .3, .3, .3 ); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); drawPlane(shownormals); break; case 2: glutWireCube(1); break; default: glutWireSphere(0.3, 20, 20); } else if ( show_sphere ) switch (surftype){ VERTEX center; center.x=1; center.y=1; center.z=1; case 1: //glutSolidSphere(0.3, 20, 20); CreateSphere(center,2,4); break; case 0: glScalef( .3, .3, .3 ); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); drawPlane(shownormals); break; case 2: glutSolidCube(1); break; default: glutSolidSphere(0.3, 20, 20); } if ( show_axes ) draw_axes(.52f); glPopMatrix(); glPushMatrix(); glTranslatef( -.3, 0.0, 0.0 ); glMultMatrixf( torus_rotate ); if ( show_axes ) draw_axes(.52f); if ( show_torus ) { glScalef( .2, .2, .2 ); renderObject(); } glPopMatrix(); if ( show_text ) { glDisable( GL_LIGHTING ); /* Disable lighting while we render text */ glMatrixMode( GL_PROJECTION ); glLoadIdentity(); gluOrtho2D( 0.0, 100.0, 0.0, 100.0 ); glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); glColor3ub( 0, 0, 0 ); glRasterPos2i( 3, 3 ); /*** Render the live character array 'text' ***/ int i; if (strlen(displayfilename)==0) { for( i=0; i<(int)strlen( string_list[curr_string] ); i++ ) glutBitmapCharacter( GLUT_BITMAP_HELVETICA_18, string_list[curr_string][i] ); } else { for( i=0; i<(int)strlen(displayfilename); i++ ) glutBitmapCharacter( GLUT_BITMAP_HELVETICA_18,displayfilename[i] ); } } glEnable( GL_LIGHTING ); glutSwapBuffers(); } /**************************************** main() ********************/ void main(int argc, char* argv[]) { /****************************************/ /* Initialize GLUT and create window */ /****************************************/ glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH ); glutInitWindowPosition( 50, 50 ); glutInitWindowSize( 800, 600 ); main_window = glutCreateWindow( "GLUI Example 5" ); glutDisplayFunc( myGlutDisplay ); GLUI_Master.set_glutReshapeFunc( myGlutReshape ); GLUI_Master.set_glutKeyboardFunc( myGlutKeyboard ); GLUI_Master.set_glutSpecialFunc( NULL ); /*** Setup Lighting ***/ glEnable(GL_LIGHTING); glEnable( GL_NORMALIZE ); glEnable(GL_LIGHT0); glLightfv(GL_LIGHT0, GL_AMBIENT, light0_ambient); glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse); glLightfv(GL_LIGHT0, GL_POSITION, light0_position); glEnable(GL_DEPTH_TEST); /****************************************/ /* Here's the GLUI code */ /****************************************/ /*** Create the side subwindow ***/ glui = GLUI_Master.create_glui_subwindow( main_window, GLUI_SUBWINDOW_RIGHT ); /***** Control for object params *****/ obj_panel = glui->add_rollout( "Properties", false ); checkbox = glui->add_checkbox_to_panel( obj_panel, "Wireframe", &wireframe, 0,control_cb ); checkbox = glui->add_checkbox_to_panel( obj_panel, "Show Normals", &shownormals, 0,control_cb ); checkbox = glui->add_checkbox_to_panel( obj_panel, "Use Vertex Normals", &normals, 0,control_cb ); /*** Add surface rollout ***/ GLUI_Panel *obj_panel = glui->add_rollout( "Surface Type", false ); radio = glui->add_radiogroup_to_panel(obj_panel,&surftype,3,control_cb); glui->add_radiobutton_to_group( radio, "Plane" ); glui->add_radiobutton_to_group( radio, "Surface" ); glui->add_radiobutton_to_group( radio, "Cylinder " ); /*** Add options rollout ***/ GLUI_Rollout *options = glui->add_rollout( "Options", false ); glui->add_checkbox_to_panel( options, "Draw surface", &show_sphere ); glui->add_checkbox_to_panel( options, "Draw VRML object ", &show_torus ); glui->add_checkbox_to_panel( options, "Draw axes", &show_axes ); glui->add_checkbox_to_panel( options, "Draw text", &show_text ); /*** Add model selection rollout ***/ GLUI_Rollout *wrl = glui->add_rollout( "Model Selection", true ); glui->add_statictext( "" ); GLUI_Listbox *list = glui->add_listbox_to_panel(wrl, "Built-in:", &curr_string ); int i; for( i=0; iadd_item( i, string_list[i] ); cmd_line = glui->add_edittext_to_panel(wrl, "Custom:", GLUI_EDITTEXT_TEXT, NULL, CMD_LINE_ID, control_cb ); cmd_line->set_w( 200 ); /** Widen 'command line' control **/ glui->add_button_to_panel(wrl, "Load File", LOAD_ID, control_cb ); status_line = glui->add_edittext_to_panel(wrl, "", GLUI_EDITTEXT_TEXT, NULL, CMD_STATUS_ID, control_cb ); status_line->set_w( 200 ); /** Widen 'command line' control **/ status_line->disable(); /*** Add texture selection rollout ***/ GLUI_Rollout *txtur = glui->add_rollout( "Texture Selection", true ); glui->add_statictext( "" ); GLUI_Listbox *list2 = glui->add_listbox_to_panel(txtur, "Built-in:", &curr2_string ); for( i=0; iadd_item( i, texture_list[i] ); cmd2_line = glui->add_edittext_to_panel(txtur, "Custom:", GLUI_EDITTEXT_TEXT, NULL, CMD_LINE_ID, control_cb ); cmd2_line->set_w( 200 ); /** Widen 'command line' control **/ glui->add_button_to_panel(txtur, "Load Texture", LOAD_TEXTURE_ID, control_cb ); status2_line = glui->add_edittext_to_panel(txtur, "", GLUI_EDITTEXT_TEXT, NULL, CMD_STATUS_ID, control_cb ); status2_line->set_w( 200 ); /** Widen 'command line' control **/ status2_line->disable(); glui->add_statictext( "" ); /*** Toggle Controls buttons ***/ glui->add_button( "Toggle Controls", TOGGLE_ID, control_cb ); glui->add_statictext( "" ); /****** A 'quit' button *****/ glui->add_button( "Quit", 0,(GLUI_Update_CB)exit ); /**** Link windows to GLUI, and register idle callback ******/ glui->set_main_gfx_window( main_window ); /*** Create the bottom subwindow ***/ glui2 = GLUI_Master.create_glui_subwindow( main_window, GLUI_SUBWINDOW_BOTTOM ); glui2->set_main_gfx_window( main_window ); GLUI_Rotation *view_rot = glui2->add_rotation( "Objects", view_rotate ); view_rot->set_spin( 1.0 ); glui2->add_column( false ); GLUI_Rotation *tor_rot = glui2->add_rotation( "VRML", torus_rotate ); tor_rot->set_spin( .98 ); glui2->add_column( false ); GLUI_Rotation *sph_rot = glui2->add_rotation( "Surface", sphere_rotate ); sph_rot->set_spin( .98 ); glui2->add_column( false ); GLUI_Rotation *lights_rot = glui2->add_rotation( "Light", lights_rotation ); lights_rot->set_spin( .82 ); glui2->add_column( false ); GLUI_Translation *trans_xy = glui2->add_translation( "Objects XY", GLUI_TRANSLATION_XY, obj_pos ); trans_xy->set_speed( .005 ); glui2->add_column( false ); GLUI_Translation *trans_x = glui2->add_translation( "Objects X", GLUI_TRANSLATION_X, obj_pos ); trans_x->set_speed( .005 ); glui2->add_column( false ); GLUI_Translation *trans_y = glui2->add_translation( "Objects Y", GLUI_TRANSLATION_Y, &obj_pos[1] ); trans_y->set_speed( .005 ); glui2->add_column( false ); GLUI_Translation *trans_z = glui2->add_translation( "Objects Z", GLUI_TRANSLATION_Z, &obj_pos[2] ); trans_z->set_speed( .005 ); /***** end of GLUI code *******************************************/ /**** We register the idle callback with GLUI, *not* with GLUT ****/ GLUI_Master.set_glutIdleFunc( myGlutIdle ); char texturename[20]; strcpy(texturename,""); strcpy(displayfilename, ""); // init if (argc!=3) { printf("Usage: lab1 file.wrl texture.ppm \n"); filename="cube.wrl"; strcpy(texturename,"cloth.ppm"); } else { filename=argv[1]; strcpy(texturename,argv[2]); } objload(filename,&cube); LoadPPMTexture(texturename); //LoadBMPTexture("test.bmp"); /**** Regular GLUT main loop ****/ glutMainLoop(); } int LoadPPMTexture(char *name) { int status=0; status=loadPPM(name, &myTextureImage); if (status!=0) return status; if(!init) { init=1; glGenTextures(1, &texture[0]); // Create The Texture } printmyArray(myTextureImage.sizeX, myTextureImage.sizeY, myTextureImage.data); // Typical Texture Generation Using Data From The Bitmap glBindTexture(GL_TEXTURE_2D, texture[0]); glTexImage2D(GL_TEXTURE_2D, 0, 3,myTextureImage.sizeX, myTextureImage.sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, myTextureImage.data); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE); free(myTextureImage.data); // Free The Texture Image Memory return status; } int objload(char *name,OBJECT *k) // Loads Object From File (name) { long ver; // Will Hold Vertice Count FILE *filein; // Filename To Open char oneline[255]; // Holds One Line Of Text (255 Chars Max) char header[255]; float rx, ry, rz; long ix, iy, iz, iq; ver=1000000; filein = fopen(name, "rt"); // Opens The File For Reading Text In Translated Mode if (filein==NULL) return 1; readstr(filein,header); // Jumps To Code That Reads One Line Of Text From The File if (strstr(header,"#VRML V1.0")==NULL) return -1; objfree(k); objallocate(k,ver, ver); // Jumps To Code That Allocates Ram To Hold The Object long i,j; i=0; do readstr(filein,header); // Jumps To Code That Reads One Line Of Text From The File while (strstr(header,"point [")==NULL && !feof(filein)); do { readstr(filein,oneline); // Reads In The Next Line Of Text j=sscanf(oneline, "%f %f %f", &rx, &ry, &rz); // Searches For 3 Floating Point Numbers, Store In rx,ry & rz if (j!=3) break; k->points[i].x = rx; // Sets Objects (k) points.x Value To rx k->points[i].y = ry; // Sets Objects (k) points.y Value To ry k->points[i].z = rz; // Sets Objects (k) points.z Value To rz i++; // if (i%100 ==0) // printf("."); } while (!feof(filein)); ver=i; k->verts=i; // printf("Read in %i vertices.\n", i); k->faces=0; do readstr(filein,header); // Jumps To Code That Reads One Line Of Text From The File while (strstr(header,"coordIndex")==NULL && !feof(filein)); i=0; do { readstr(filein,oneline); // Reads In The Next Line Of Text j=sscanf(oneline, "%i, %i, %i, %i, -1,", &ix, &iy, &iz, &iq); // Searches For 3 Floating Point Numbers, Store In rx,ry & rz if (j!=4) break; if (iq==-1) // its a triangle { k->facearray[i].face=(long *)malloc(sizeof(long)*3); k->facearray[i].facenumber=3; k->facearray[i].face[0]=ix; k->facearray[i].face[1]=iy; k->facearray[i].face[2]=iz; } else { k->facearray[i].face=(long *)malloc(sizeof(long)*4); k->facearray[i].facenumber=4; k->facearray[i].face[0]=ix; k->facearray[i].face[1]=iy; k->facearray[i].face[2]=iz; k->facearray[i].face[3]=iq; } i++; // if (i%100 ==0) // printf("."); } while (!feof(filein)); // printf("Read in %i faces.\n", i); k->faces=i; fclose(filein); printf("Read in file %s - %d vertices, %d faces. \n",name, k->verts, k->faces); status_line->set_text("Model Loaded."); // Close The File if(ver>maxver) maxver=ver; // If ver Is Greater Than maxver Set maxver Equal To ver // calculate the face normal vectors // printf("calculating face normals: "); faceNormVectors=(VERTEX *)malloc(sizeof(VERTEX)*cube.faces); for (ix = 0; ix < cube.faces; ix++) { // if (ix%100==0) // printf("."); ComputeFaceNormal(&cube.points[(cube.facearray[ix].face[0])], &cube.points[(cube.facearray[ix].face[1])], &cube.points[(cube.facearray[ix].face[2])], &faceNormVectors[ix]); } // calculate the vertex normal vectors // printf("calculating vert normals: "); vertexNormVectors= (VERTEX *)malloc(sizeof(VERTEX)*cube.verts); //printf("calculating vert normals: "); for (ix = 0; ix < cube.verts; ix++) { // if (ix%100==0) // printf("."); ComputeVertexNormal(ix, &vertexNormVectors[ix]); } return 0; } bool ComputeVertexNormal (int num, VERTEX *pOut) { // Allocate a temporary storage to store adjacent faces indexes int * adjFaces; int i; int j; adjFaces = new int[cube.faces]; // Store each face which has an intersection with the vertex num vertex int countAdjFaces = 0; for (i=0; i