Annotation of thwomper-c/src/thwomper.c, revision 1.2

1.1       nick        1: //
1.2     ! nick        2: //  Thwomper-c
1.1       nick        3: //
1.2     ! nick        4: //    Port of Thwomper for Perl, to C
        !             5: //    Nick DeClario
1.1       nick        6: //
                      7: #include <GL/glut.h>    // Header File For The GLUT Library 
                      8: #include <GL/gl.h>     // Header File For The OpenGL32 Library
                      9: #include <GL/glu.h>    // Header File For The GLu32 Library
                     10: #include <stdio.h>      // Header file for standard file i/o.
                     11: #include <stdlib.h>     // Header file for malloc/free.
                     12: #include <unistd.h>     // needed to sleep.
                     13: #include <math.h>      
                     14: 
                     15: /* ascii code for the escape key */
                     16: #define ESCAPE 27
                     17: #define ZMIN -100
                     18: #define ZMAX -12
                     19: #define MAX_DISPLAY_TIME 5     // in seconds
1.2     ! nick       20: #define VER $Id: thwomper.c,v 1.1.1.1 2009-04-13 04:01:42 nick Exp $
1.1       nick       21: 
                     22: /* The number of our GLUT window */
                     23: int window; 
                     24: int dir = 0;
                     25: int fullscreen = 0;
                     26: 
                     27: /* floats for x rotation, y rotation, z rotation */
                     28: float xrot, yrot, zrot;
                     29: float zoom = ZMIN;
                     30: float locX, locY = 0.0f;
                     31: 
                     32: /* storage for one texture  */
                     33: int texture[1];
                     34: 
                     35: /* Image type - contains height, width, and data */
                     36: struct Image {
                     37:     unsigned long sizeX;
                     38:     unsigned long sizeY;
                     39:     char *data;        
                     40:     float locX, locY, xrot, yrot, zrot, zoom;
                     41:     int displayTime;   // How long have we been still for?
                     42: };
                     43: typedef struct Image Image;
                     44: 
                     45: struct Nick {
                     46:        unsigned long X;
                     47:        unsigned long Y;
                     48: };
                     49: typedef struct Nick Nick;
                     50: 
                     51: 
                     52: /* Letter/Shape 3D Object */
                     53: 
                     54: // quick and dirty bitmap loader...for 24 bit bitmaps with 1 plane only.  
                     55: // See http://www.dcs.ed.ac.uk/~mxr/gfx/2d/BMP.txt for more info.
                     56: int ImageLoad(char *filename, Image *image) {
                     57:     FILE *file;
                     58:     unsigned long size;                 // size of the image in bytes.
                     59:     unsigned long i;                    // standard counter.
                     60:     unsigned short int planes;          // number of planes in image (must be 1) 
                     61:     unsigned short int bpp;             // number of bits per pixel (must be 24)
                     62:     char temp;                          // temporary color storage for bgr-rgb conversion.
                     63:        Nick *ntest;
                     64: 
                     65:     // make sure the file is there.
                     66:     if ((file = fopen(filename, "rb"))==NULL)
                     67:     {
                     68:        printf("File Not Found : %s\n",filename);
                     69:        return 0;
                     70:     }
                     71:     
                     72:     // seek through the bmp header, up to the width/height:
                     73:     fseek(file, 18, SEEK_CUR);
                     74: 
                     75: /*
                     76:     ntest = ( Nick * ) malloc( sizeof( Nick ) );
                     77:     fread( &ntest.X, 4, 1, file );
                     78: printf( " Nick's Width Test: %lu\n", ntest.X );
                     79: */
                     80:     // read the width
                     81:     if ((i = fread(&image->sizeX, 4, 1, file)) != 1) {
                     82:        printf("Error reading width from %s.\n", filename);
                     83:        return 0;
                     84:     }
                     85:     printf("Width of %s: %lu\n", filename, image->sizeX);
                     86:     
                     87:     // read the height 
                     88:     if ((i = fread(&image->sizeY, 4, 1, file)) != 1) {
                     89:        printf("Error reading height from %s.\n", filename);
                     90:        return 0;
                     91:     }
                     92:     printf("Height of %s: %lu\n", filename, image->sizeY);
                     93:     
                     94:     // calculate the size (assuming 24 bits or 3 bytes per pixel).
                     95:     size = image->sizeX * image->sizeY * 3;
                     96: 
                     97:     // read the planes
                     98:     if ((fread(&planes, 2, 1, file)) != 1) {
                     99:        printf("Error reading planes from %s.\n", filename);
                    100:        return 0;
                    101:     }
                    102:     if (planes != 1) {
                    103:        printf("Planes from %s is not 1: %u\n", filename, planes);
                    104:        return 0;
                    105:     }
                    106: 
                    107:     // read the bpp
                    108:     if ((i = fread(&bpp, 2, 1, file)) != 1) {
                    109:        printf("Error reading bpp from %s.\n", filename);
                    110:        return 0;
                    111:     }
                    112:     if (bpp != 24) {
                    113:        printf("Bpp from %s is not 24: %u\n", filename, bpp);
                    114:        return 0;
                    115:     }
                    116:        
                    117:     // seek past the rest of the bitmap header.
                    118:     fseek(file, 24, SEEK_CUR);
                    119: 
                    120:     // read the data. 
                    121:     image->data = (char *) malloc(size);
                    122:     if (image->data == NULL) {
                    123:        printf("Error allocating memory for color-corrected image data\n");
                    124:        return 0;       
                    125:     }
                    126: 
                    127:     if ((i = fread(image->data, size, 1, file)) != 1) {
                    128:        printf("Error reading image data from %s.\n", filename);
                    129:        return 0;
                    130:     }
                    131: 
                    132:     for (i=0;i<size;i+=3) { // reverse all of the colors. (bgr -> rgb)
                    133:        temp = image->data[i];
                    134:        image->data[i] = image->data[i+2];
                    135:        image->data[i+2] = temp;
                    136:     }
                    137:     
                    138:     // we're done.
                    139:     return 1;
                    140: }
                    141:     
                    142: // Load Bitmaps And Convert To Textures
                    143: void LoadGLTextures() {        
                    144:     // Load Texture
                    145:     Image *image1;
                    146:     
                    147:     // allocate space for texture
                    148:     image1 = (Image *) malloc(sizeof(Image));
                    149:     if (image1 == NULL) {
                    150:        printf("Error allocating space for image");
                    151:        exit(0);
                    152:     }
                    153: 
                    154:     if (!ImageLoad("Data/tux-128.bmp", image1)) {
                    155:        exit(1);
                    156:     }        
                    157: 
                    158:     // Create Texture  
                    159:     glGenTextures(1, &texture[0]);
                    160:     glBindTexture(GL_TEXTURE_2D, texture[0]);   // 2d texture (x and y size)
                    161: 
                    162:     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // scale linearly when image bigger than texture
                    163:     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // scale linearly when image smalled than texture
                    164: 
                    165:     // 2d texture, level of detail 0 (normal), 3 components (red, green, blue), x size from image, y size from image, 
                    166:     // border 0 (normal), rgb color data, unsigned byte data, and finally the data itself.
                    167:     glTexImage2D(GL_TEXTURE_2D, 0, 3, image1->sizeX, image1->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, image1->data);
                    168: };
                    169: 
                    170: /* A general OpenGL initialization function.  Sets all of the initial parameters. */
                    171: void InitGL(int Width, int Height)             // We call this right after our OpenGL window is created.
                    172: {
                    173:     LoadGLTextures();                          // Load The Texture(s) 
                    174:     glEnable(GL_TEXTURE_2D);                   // Enable Texture Mapping
                    175:     glClearColor(1.0f, 1.0f, 1.0f, 1.0f);      // Clear The Background Color To Blue 
                    176:     glClearDepth(1.0);                         // Enables Clearing Of The Depth Buffer
                    177:     glDepthFunc(GL_LESS);                      // The Type Of Depth Test To Do
                    178:     glEnable(GL_DEPTH_TEST);                   // Enables Depth Testing
                    179:     glShadeModel(GL_SMOOTH);                   // Enables Smooth Color Shading
                    180: //    glEnable(GL_BLEND);
                    181:     
                    182:     glMatrixMode(GL_PROJECTION);
                    183:     glLoadIdentity();                          // Reset The Projection Matrix
                    184:     
                    185:     gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f);  // Calculate The Aspect Ratio Of The Window
                    186:     
                    187:     glMatrixMode(GL_MODELVIEW);
                    188: }
                    189: 
                    190: /* The function called when our window is resized (which shouldn't happen, because we're fullscreen) */
                    191: void ReSizeGLScene(int Width, int Height)
                    192: {
                    193:     if (Height==0)                             // Prevent A Divide By Zero If The Window Is Too Small
                    194:        Height=1;
                    195: 
                    196:     glViewport(0, 0, Width, Height);           // Reset The Current Viewport And Perspective Transformation
                    197: 
                    198:     glMatrixMode(GL_PROJECTION);
                    199:     glLoadIdentity();
                    200: 
                    201:     gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,400.0f);
                    202:     glMatrixMode(GL_MODELVIEW);
                    203: 
                    204:     printf( "New Width: %i\nNew Height: %i\n", Width, Height );
                    205: }
                    206: 
                    207: void drawCharacter( ) {
                    208:        glPushMatrix();
                    209:        glColor3f(1.0, 0.0, 0.0 );
                    210:        glTranslatef(locX, locY, zoom);
                    211:        glRotatef(xrot, 1.0, 0.0, 0.0);
                    212:        glRotatef(yrot, 0.0, 1.0, 0.0);
                    213:        glRotatef(zrot, 0.0, 0.0, 1.0);
                    214:        glutWireCube(2);
                    215:        glPopMatrix(); //end the current object transformations
                    216: }
                    217: 
                    218: /* The main drawing function. */
                    219: void DrawGLScene()
                    220: {
                    221:     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);                // Clear The Screen And The Depth Buffer
                    222:     glLoadIdentity();                          // Reset The View
                    223: 
                    224:     glColor3f(1.0, 1.0, 1.0 );
                    225:     glTranslatef(locX,locY,zoom);              // move 5 units into the screen.
                    226:     
                    227:     glRotatef(xrot,1.0f,0.0f,0.0f);            // Rotate On The X Axis
                    228:     glRotatef(yrot,0.0f,1.0f,0.0f);            // Rotate On The Y Axis
                    229:     glRotatef(zrot,0.0f,0.0f,1.0f);            // Rotate On The Z Axis
                    230: 
                    231:     glBindTexture(GL_TEXTURE_2D, texture[0]);   // choose the texture to use.
                    232: 
                    233:     glBegin(GL_QUADS);                         // begin drawing a cube
                    234:     
                    235:     // Front Face (note that the texture's corners have to match the quad's corners)
                    236:     glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f); // Bottom Left Of The Texture and Quad
                    237:     glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f); // Bottom Right Of The Texture and Quad
                    238:     glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  1.0f); // Top Right Of The Texture and Quad
                    239:     glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  1.0f); // Top Left Of The Texture and Quad
                    240:     
                    241:     glEnd();                                    // done with the polygon.
                    242: 
                    243: //    xrot+=5.3f;                              // X Axis Rotation      
                    244: //    yrot+=5.3f;                              // Y Axis Rotation
                    245: 
                    246:     usleep( 25000 );
                    247:     if ( zoom <= ZMAX ) {
                    248:        zoom += 1.85f;
                    249:        zrot+=30.0f;
                    250:     }
                    251: /*
                    252:  * Bounce our cube around
                    253:     zrot+=1.63f;                               // Z Axis Rotation
                    254:  
                    255:     if ( dir ) { 
                    256:        zoom += 0.5f;
                    257:         if ( zoom >= ZMAX ) { dir = 0; }
                    258:     }
                    259:     else {
                    260:        zoom -= 0.5f;
                    261:        if ( zoom <= ZMIN ) { dir = 1; }
                    262:     } 
                    263: */
                    264: 
                    265:     // since this is double buffered, swap the buffers to display what just got drawn.
                    266:     glutSwapBuffers();
                    267: }
                    268: 
                    269: /* The function called whenever a key is pressed. */
                    270: void keyPressed(unsigned char key, int x, int y) 
                    271: {
                    272:     /* avoid thrashing this procedure */
                    273:     usleep(100);
                    274: 
                    275:        printf( "Keypressed %c\n", key );
                    276: 
                    277:     /* If escape is pressed, kill everything. */
                    278:     if (key == ESCAPE) 
                    279:     { 
                    280:        /* shut down our window */
                    281:        glutDestroyWindow(window); 
                    282:       
                    283:       /* exit the program...normal termination. */
                    284:        exit(0);                   
                    285:     }
                    286:     else if ( key == '`' ) {
                    287:        fullscreen = !fullscreen;
                    288: 
                    289:        if ( fullscreen ) {
                    290:                glutFullScreen( );
                    291:        }
                    292:        else {
                    293:                glutReshapeWindow(800,600);
                    294:        }
                    295:     }
                    296:     else { 
                    297:        if ( zoom >= ZMAX ) { 
                    298:                zoom = ZMIN; 
                    299:                locX = rand()/(((unsigned)RAND_MAX + 1) / 7.6);
                    300:                locY = rand()/(((unsigned)RAND_MAX + 1) / 4.1);
                    301:                if ( (int)fmod( locX, 2.0f ) ) { locX = ( locX - ( locX * 2.0f ) ) + 1.0f; }
                    302:                if ( (int)fmod( locY, 2.0f ) ) { locY = ( locY - ( locY * 2.0f ) ) + 1.0f; }
                    303:        }
                    304:     }
                    305: }
                    306: 
                    307: int main(int argc, char **argv) 
                    308: {  
                    309:     /* Initialize GLUT state - glut will take any command line arguments that pertain to it or 
                    310:        X Windows - look at its documentation at http://reality.sgi.com/mjk/spec3/spec3.html */  
                    311:     glutInit(&argc, argv);  
                    312: 
                    313:     /* Select type of Display mode:   
                    314:      Double buffer 
                    315:      RGBA color
                    316:      Alpha components supported 
                    317:      Depth buffer */  
                    318:     glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH);  
                    319: 
                    320:     /* get a 640 x 480 window */
                    321:     glutInitWindowSize(800, 600);  
                    322: 
                    323:     /* the window starts at the upper left corner of the screen */
                    324:     glutInitWindowPosition(0, 0);  
                    325: 
                    326:     /* Open a window */  
                    327:     window = glutCreateWindow("Jeff Molofee's GL Code Tutorial ... NeHe '99");  
                    328: 
                    329:     printf("GL_VENDOR     : %s\n", (char *) glGetString (GL_VENDOR));
                    330:     printf("GL_RENDERER   : %s\n", (char *) glGetString (GL_RENDERER));
                    331:     printf("GL_VERSION    : %s\n", (char *) glGetString (GL_VERSION));
                    332:     printf("GL_EXTENSIONS : %s\n", (char *) glGetString (GL_EXTENSIONS));
                    333: 
                    334: 
                    335:     /* Register the function to do all our OpenGL drawing. */
                    336:     glutDisplayFunc(&DrawGLScene);  
                    337: 
                    338:     /* Go fullscreen.  This is as soon as possible. */
                    339: //    glutFullScreen();
                    340: 
                    341:     /* Even if there are no events, redraw our gl scene. */
                    342:     glutIdleFunc(&DrawGLScene);
                    343: 
                    344:     /* Register the function called when our window is resized. */
                    345:     glutReshapeFunc(&ReSizeGLScene);
                    346: 
                    347:     /* Register the function called when the keyboard is pressed. */
                    348:     glutKeyboardFunc(&keyPressed);
                    349: 
                    350:     /* Initialize our window. */
                    351:     InitGL(800, 600);
                    352:   
                    353:     /* Start Event Processing Engine */  
                    354:     glutMainLoop();  
                    355: 
                    356:     return 1;
                    357: }
                    358: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>