// I used a base frame from nehe's opengl tutorials // gcc -o dff dff.c -lX11 -lXi -lXmu -lglut -lGL -lGLU -lm -L/usr/X11R6/lib -I/usr/include/ #include // Header File For The GLUT Library #include // Header File For The OpenGL32 Library #include // Header File For The GLu32 Library #include // Header file for standard file i/o. #include // Header file for malloc/free. #include // Header file for sleeping. #include "dff.h" /* ascii codes for the esc key */ #define ESCAPE 27 /* The number of our GLUT window */ int window; float xrot, yrot, zrot; float z = -3; float asdf = 0; float asdf2 = 0; int light = 0; int geoindex = 1; int texture[3]; int filter; int wf; int aa = 0; float LightAmbient[] = { 0.6f, 0.6f, 0.6f, 1.0f }; float LightDiffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f }; float LightPosition[] = { 0.0f, 0.0f, 2.0f, 1.0f }; struct Image { unsigned long sizeX; unsigned long sizeY; char *data; }; typedef struct Image Image; int DisplayGeometry(int j) { int i; //glBindTexture(GL_TEXTURE_2D, texture[filter]); if(geo[j].viewable) { glBegin(GL_TRIANGLES); for ( i = 0; i < geo[j].facecount; i++) { glNormal3f(geo[j].normals[3*geo[j].faces[4*i+1]+0], geo[j].normals[3*geo[j].faces[4*i+1]+1], geo[j].normals[3*geo[j].faces[4*i+1]+2]); glTexCoord2f(geo[j].uv[2*geo[j].faces[4*i+1]+0],-1*geo[j].uv[2*geo[j].faces[4*i+1]+1]); glVertex3f(geo[j].vertices[3*geo[j].faces[4*i+1]+0], geo[j].vertices[3*geo[j].faces[4*i+1]+1],geo[j].vertices[3*geo[j].faces[4*i+1]+2]); glNormal3f(geo[j].normals[3*geo[j].faces[4*i+1]+0], geo[j].normals[3*geo[j].faces[4*i+1]+1], geo[j].normals[3*geo[j].faces[4*i+1]+2]); glTexCoord2f(geo[j].uv[2*geo[j].faces[4*i+0]+0],-1*geo[j].uv[2*geo[j].faces[4*i+0]+1]); glVertex3f(geo[j].vertices[3*geo[j].faces[4*i+0]+0], geo[j].vertices[3*geo[j].faces[4*i+0]+1],geo[j].vertices[3*geo[j].faces[4*i+0]+2]); glNormal3f(geo[j].normals[3*geo[j].faces[4*i+1]+0], geo[j].normals[3*geo[j].faces[4*i+1]+1], geo[j].normals[3*geo[j].faces[4*i+1]+2]); glTexCoord2f(geo[j].uv[2*geo[j].faces[4*i+3]+0],-1*geo[j].uv[2*geo[j].faces[4*i+3]+1]); glVertex3f(geo[j].vertices[3*geo[j].faces[4*i+3]+0], geo[j].vertices[3*geo[j].faces[4*i+3]+1],geo[j].vertices[3*geo[j].faces[4*i+3]+2]); } glEnd(); } } int ImageLoad(char *filename, Image *image) { FILE *file; unsigned long size; // size of the image in bytes. unsigned long i; // standard counter. unsigned short int planes; // number of planes in image (must be 1) unsigned short int bpp; // number of bits per pixel (must be 24) char temp; // temporary color storage for bgr-rgb conversion. // make sure the file is there. if ((file = fopen(filename, "rb"))==NULL) { printf("File Not Found : %s\n",filename); return 0; } // seek through the bmp header, up to the width/height: fseek(file, 18, SEEK_CUR); // read the width if ((i = fread(&image->sizeX, 4, 1, file)) != 1) { printf("Error reading width from %s.\n", filename); return 0; } printf("Width of %s: %lu\n", filename, image->sizeX); // read the height if ((i = fread(&image->sizeY, 4, 1, file)) != 1) { printf("Error reading height from %s.\n", filename); return 0; } printf("Height of %s: %lu\n", filename, image->sizeY); // calculate the size (assuming 24 bits or 3 bytes per pixel). size = image->sizeX * image->sizeY * 3; // read the planes if ((fread(&planes, 2, 1, file)) != 1) { printf("Error reading planes from %s.\n", filename); return 0; } if (planes != 1) { printf("Planes from %s is not 1: %u\n", filename, planes); return 0; } // read the bpp if ((i = fread(&bpp, 2, 1, file)) != 1) { printf("Error reading bpp from %s.\n", filename); return 0; } if (bpp != 24) { printf("Bpp from %s is not 24: %u\n", filename, bpp); return 0; } // seek past the rest of the bitmap header. fseek(file, 24, SEEK_CUR); // read the data. image->data = (char *) malloc(size); if (image->data == NULL) { printf("Error allocating memory for color-corrected image data"); return 0; } if ((i = fread(image->data, size, 1, file)) != 1) { printf("Error reading image data from %s.\n", filename); return 0; } for (i=0;i rgb) temp = image->data[i]; image->data[i] = image->data[i+2]; image->data[i+2] = temp; } // we're done. return 1; } /* Load the Bitmap */ int LoadGLTextures() { Image *image1; // allocate space for texture image1 = (Image *) malloc(sizeof(Image)); if (image1 == NULL) { printf("Error allocating space for image"); exit(0); } if (!ImageLoad("ak47_all.bmp", image1)) { exit(1); } // Create Texture glGenTextures(3, &texture[0]); glBindTexture(GL_TEXTURE_2D, texture[0]); // 2d texture (x and y size) glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // scale linearly when image bigger than texture glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // scale linearly when image smalled than texture // 2d texture, level of detail 0 (normal), 3 components (red, green, blue), x size from image, y size from image, // border 0 (normal), rgb color data, unsigned byte data, and finally the data itself. glTexImage2D(GL_TEXTURE_2D, 0, 3, image1->sizeX, image1->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, image1->data); // second texture - nearest glBindTexture(GL_TEXTURE_2D, texture[1]); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, 3, image1->sizeX, image1->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, image1->data); // third texture - mipmap glBindTexture(GL_TEXTURE_2D, texture[2]); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, 3, image1->sizeX, image1->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, image1->data); gluBuild2DMipmaps(GL_TEXTURE_2D, 3, image1->sizeX, image1->sizeY, GL_RGB, GL_UNSIGNED_BYTE, image1->data); }; /* A general OpenGL initialization function. Sets all of the initial parameters. */ void InitGL(int Width, int Height) // We call this right after our OpenGL window is created. { LoadGLTextures(); // glEnable(GL_TEXTURE_2D); glClearColor(0.3f, 0.3f, 0.3f, 0.0f); // This Will Clear The Background Color To Black glClearDepth(1.0); // Enables Clearing Of The Depth Buffer glDepthFunc(GL_LESS); // The Type Of Depth Test To Do glEnable(GL_DEPTH_TEST); // Enables Depth Testing glShadeModel(GL_SMOOTH); // Enables Smooth Color Shading //glEnable(GL_LINE_SMOOTH); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations //glHint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE); //glLineWidth(1.5); glMatrixMode(GL_PROJECTION); glLoadIdentity(); // Reset The Projection Matrix gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f); // Calculate The Aspect Ratio Of The Window glMatrixMode(GL_MODELVIEW); // light glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient); glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse); glLightfv(GL_LIGHT1, GL_POSITION, LightPosition); glEnable(GL_LIGHT1); } /* The function called when our window is resized (which shouldn't happen, because we're fullscreen) */ void ReSizeGLScene(int Width, int Height) { if (Height==0) // Prevent A Divide By Zero If The Window Is Too Small Height=1; glViewport(0, 0, Width, Height); // Reset The Current Viewport And Perspective Transformation glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f); glMatrixMode(GL_MODELVIEW); } /* The main drawing function. */ void DrawGLScene() { int i; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer glLoadIdentity(); // Reset The View glTranslatef(asdf, asdf2, z); glRotatef(xrot, 1.0f, 0.0f, 0.0f); glRotatef(yrot, 0.0f, 1.0f, 0.0f); glRotatef(zrot, 0.0f, 0.0f, 1.0f); for(i = 0; i < framecount; i++) { glTranslatef(frm[i].pos[0], frm[i].pos[1], frm[i].pos[2]); if(frm[i].isgeo == 1) DisplayGeometry(frm[i].geo); } // since this is double buffered, swap the buffers to display what just got drawn. glutSwapBuffers(); } /* The function called whenever a key is pressed. */ void keyPressed(unsigned char key, int x, int y) { /* avoid thrashing this procedure */ usleep(100); switch (key) { case ESCAPE: glutDestroyWindow(window); exit(0); break; case 'f': case 'F': printf("Filter is now %d\n", filter); filter++; if(filter == 3) filter = 0; printf("Filter is now %d\n", filter); break; case 'l': case 'L': printf("Light is %d\n", light); light = light ? 0 : 1; printf("Light is now %d\n", light); if (!light) glDisable(GL_LIGHTING); else glEnable(GL_LIGHTING); break; case 'r': case 'R': printf("wireframe is %d\n", wf); wf = wf ? 0 : 1; printf("wireframe is now %d\n", wf); if(!wf) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); else glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break; case 'q': zrot -=0.7f; break; case 'Q': zrot -=2.0f; break; case 'e': zrot += 0.7f; break; case 'E': zrot += 2.0f; break; case 'w': asdf2 -= 0.1f; break; case 'W': asdf2 -= 0.2f; break; case 's': asdf2 += 0.1f; break; case 'S': asdf2 += 0.2f; break; case 'a': asdf += 0.1f; break; case 'A': asdf += 0.2f; break; case 'd': asdf -= 0.1f; break; case 'D': asdf -= 0.2f; break; case '+': geoindex++; if(geoindex > geometrycount) geoindex = 1; printf("Geometry %d\n", geoindex); break; case '-': geoindex--; if(geoindex < 1) geoindex = geometrycount; printf("Geometry %d\n", geoindex); break; case 'v': case 'V': printf("Geometry %d is %d\n", geoindex, geo[geoindex-1].viewable); geo[geoindex-1].viewable = geo[geoindex-1].viewable ? 0 : 1; printf("Geometry %d is now %d\n", geoindex, geo[geoindex-1].viewable); break; /*case '.': printf("AA is %d\n", aa); aa = aa ? 0 : 1; printf("AA is now %d\n", aa); if (!light) glDisable(GL_LINE_SMOOTH); else glEnable(GL_LINE_SMOOTH); break; */ default: break; } } void specialKeyPressed(int key, int x, int y) { /* avoid thrashing this procedure */ usleep(100); switch (key) { case GLUT_KEY_UP: if (glutGetModifiers() == GLUT_ACTIVE_SHIFT) xrot -= 2.0f; else xrot -=0.7f; break; case GLUT_KEY_DOWN: if (glutGetModifiers() == GLUT_ACTIVE_SHIFT) xrot += 2.0f; else xrot += 0.7f; break; case GLUT_KEY_LEFT: if (glutGetModifiers() == GLUT_ACTIVE_SHIFT) yrot -= 2.0f; else yrot -= 0.7f; break; case GLUT_KEY_RIGHT: if (glutGetModifiers() == GLUT_ACTIVE_SHIFT) yrot += 2.0f; else yrot += 0.7f; break; case GLUT_KEY_PAGE_UP: if (glutGetModifiers() == GLUT_ACTIVE_SHIFT) z += 0.2f; else z += 0.1f; break; case GLUT_KEY_PAGE_DOWN: if (glutGetModifiers() == GLUT_ACTIVE_SHIFT) z-= 0.2f; else z -= 0.1f; break; default: break; } } int main(int argc, char **argv) { /* Initialize GLUT state - glut will take any command line arguments that pertain to it or X Windows - look at its documentation at http://reality.sgi.com/mjk/spec3/spec3.html */ DffLoad(argv[1]); glutInit(&argc, argv); /* Select type of Display mode: Double buffer RGBA color Alpha components supported Depth buffer */ glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH); /* get a 640 x 480 window */ glutInitWindowSize(640, 480); /* the window starts at the upper left corner of the screen */ glutInitWindowPosition(0, 0); /* Open a window */ window = glutCreateWindow("DFF Viewer"); /* Register the function to do all our OpenGL drawing. */ glutDisplayFunc(&DrawGLScene); /* Go fullscreen. This is as soon as possible. */ //glutFullScreen(); /* Even if there are no events, redraw our gl scene. */ glutIdleFunc(&DrawGLScene); /* Register the function called when our window is resized. */ glutReshapeFunc(&ReSizeGLScene); /* Register the function called when the keyboard is pressed. */ glutKeyboardFunc(&keyPressed); /* Register the function called when a special key is pressed. */ glutSpecialFunc(&specialKeyPressed); /* Initialize our window. */ InitGL(640, 480); /* Start Event Processing Engine */ glutMainLoop(); return 1; }