Advertisement
Guest User

Nehe lesson8 improved

a guest
Jan 8th, 2011
407
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 17.26 KB | None | 0 0
  1. //
  2. // This code was created by Jeff Molofee '99 (ported to Solaris/GLUT by Lakmal Gunasekara '99)
  3. //
  4. // If you've found this code useful, please let me know.
  5. //
  6. // Visit me at www.demonews.com/hosted/nehe
  7. // (email Richard Campbell at ulmont@bellsouth.net)
  8. // (email Lakmal Gunasekara at lakmal@gunasekara.de)
  9. //
  10. #include <GL/glut.h>    // Header File For The GLUT Library
  11. #include <GL/gl.h>  // Header File For The OpenGL32 Library
  12. #include <GL/glu.h> // Header File For The GLu32 Library
  13. #include <unistd.h>     // Header file for sleeping.
  14. #include <stdio.h>      // Header file for standard file i/o.
  15. #include <stdlib.h>     // Header file for malloc/free.
  16.  
  17. /* ascii codes for various special keys */
  18. #define ESCAPE 27
  19. #define PAGE_UP 73
  20. #define PAGE_DOWN 81
  21. #define UP_ARROW 72
  22. #define DOWN_ARROW 80
  23. #define LEFT_ARROW 75
  24. #define RIGHT_ARROW 77
  25.  
  26. /* The number of our GLUT window */
  27. int window;
  28.  
  29. /* lighting on/off (1 = on, 0 = off) */
  30. int light;
  31.  
  32. /* L pressed (1 = yes, 0 = no) */
  33. int lp;
  34.  
  35. /* F pressed (1 = yes, 0 = no) */
  36. int fp;
  37.  
  38.  
  39. GLfloat xrot;   // x rotation
  40. GLfloat yrot;   // y rotation
  41. GLfloat xspeed; // x rotation speed
  42. GLfloat yspeed; // y rotation speed
  43.  
  44. GLfloat z=-5.0f; // depth into the screen.
  45.  
  46. /* white ambient light at half intensity (rgba) */
  47. GLfloat LightAmbient[] = { 0.5f, 0.5f, 0.5f, 1.0f };
  48.  
  49. /* super bright, full intensity diffuse light. */
  50. GLfloat LightDiffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f };
  51.  
  52. /* position of light (x, y, z, (position of light)) */
  53. GLfloat LightPosition[] = { 0.0f, 0.0f, 2.0f, 1.0f };
  54.  
  55. GLuint  filter;         /* Which Filter To Use (nearest/linear/mipmapped) */
  56. GLuint  texture[3];     /* Storage for 3 textures. */
  57. GLuint  blend;                  /* Turn blending on/off */
  58.  
  59. /* Image type - contains height, width, and data */
  60. struct Image {
  61.     unsigned long sizeX;
  62.     unsigned long sizeY;
  63.     char *data;
  64. };
  65. typedef struct Image Image;
  66.  
  67. /*
  68.  * getint and getshort arehelp functions to load the bitmap byte by byte on
  69.  * SPARC platform.
  70.  * I've got them from xv bitmap load routinebecause the original bmp loader didn't work
  71.  * I've tried to change as less code as possible.
  72.  */
  73.  
  74. static unsigned int getint(fp)
  75.      FILE *fp;
  76. {
  77.   int c, c1, c2, c3;
  78.  
  79.   // get 4 bytes
  80.   c = getc(fp);  
  81.   c1 = getc(fp);  
  82.   c2 = getc(fp);  
  83.   c3 = getc(fp);
  84.  
  85.   return ((unsigned int) c) +  
  86.     (((unsigned int) c1) << 8) +
  87.     (((unsigned int) c2) << 16) +
  88.     (((unsigned int) c3) << 24);
  89. }
  90.  
  91. static unsigned int getshort(fp)
  92.      FILE *fp;
  93. {
  94.   int c, c1;
  95.  
  96.   //get 2 bytes
  97.   c = getc(fp);  
  98.   c1 = getc(fp);
  99.  
  100.   return ((unsigned int) c) + (((unsigned int) c1) << 8);
  101. }
  102.  
  103. // quick and dirty bitmap loader...for 24 bit bitmaps with 1 plane only.  
  104. // See http://www.dcs.ed.ac.uk/~mxr/gfx/2d/BMP.txt for more info.
  105.  
  106. int ImageLoad(char *filename, Image *image) {
  107.     FILE *file;
  108.     unsigned long size;                 // size of the image in bytes.
  109.     unsigned long i;                    // standard counter.
  110.     unsigned short int planes;          // number of planes in image (must be 1)
  111.     unsigned short int bpp;             // number of bits per pixel (must be 24)
  112.     char temp;                          // used to convert bgr to rgb color.
  113.  
  114.     // make sure the file is there.
  115.     if ((file = fopen(filename, "rb"))==NULL) {
  116.       printf("File Not Found : %s\n",filename);
  117.       return 0;
  118.     }
  119.    
  120.     // seek through the bmp header, up to the width/height:
  121.     fseek(file, 18, SEEK_CUR);
  122.  
  123.     // No 100% errorchecking anymore!!!
  124.  
  125.     // read the width
  126.     image->sizeX = getint (file);
  127.     printf("Width of %s: %lu\n", filename, image->sizeX);
  128.    
  129.     // read the height
  130.     image->sizeY = getint (file);
  131.     printf("Height of %s: %lu\n", filename, image->sizeY);
  132.    
  133.     // calculate the size (assuming 24 bits or 3 bytes per pixel).
  134.     size = image->sizeX * image->sizeY * 3;
  135.  
  136.     // read the planes
  137.     planes = getshort(file);
  138.     if (planes != 1) {
  139.     printf("Planes from %s is not 1: %u\n", filename, planes);
  140.     return 0;
  141.     }
  142.  
  143.     // read the bpp
  144.     bpp = getshort(file);
  145.     if (bpp != 24) {
  146.       printf("Bpp from %s is not 24: %u\n", filename, bpp);
  147.       return 0;
  148.     }
  149.    
  150.     // seek past the rest of the bitmap header.
  151.     fseek(file, 24, SEEK_CUR);
  152.  
  153.     // read the data.
  154.     image->data = (char *) malloc(size);
  155.     if (image->data == NULL) {
  156.     printf("Error allocating memory for color-corrected image data");
  157.     return 0;  
  158.     }
  159.  
  160.     if ((i = fread(image->data, size, 1, file)) != 1) {
  161.     printf("Error reading image data from %s.\n", filename);
  162.     return 0;
  163.     }
  164.  
  165.     for (i=0;i<size;i+=3) { // reverse all of the colors. (bgr -> rgb)
  166.     temp = image->data[i];
  167.     image->data[i] = image->data[i+2];
  168.     image->data[i+2] = temp;
  169.     }
  170.  
  171.     // we're done.
  172.     return 1;
  173. }
  174.  
  175. // Load Bitmaps And Convert To Textures
  176. GLvoid LoadGLTextures(GLvoid) {
  177.     // Load Texture
  178.     Image *image1;
  179.    
  180.     // allocate space for texture
  181.     image1 = (Image *) malloc(sizeof(Image));
  182.     if (image1 == NULL) {
  183.     printf("Error allocating space for image");
  184.     exit(0);
  185.     }
  186.  
  187.     if (!ImageLoad("Data/lesson8/glass.bmp", image1)) {
  188.     exit(1);
  189.     }        
  190.  
  191.     // Create Textures 
  192.     glGenTextures(3, &texture[0]);
  193.  
  194.     // texture 1 (poor quality scaling)
  195.     glBindTexture(GL_TEXTURE_2D, texture[0]);   // 2d texture (x and y size)
  196.  
  197.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); // cheap scaling when image bigger than texture
  198.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); // cheap scaling when image smalled than texture
  199.  
  200.     // 2d texture, level of detail 0 (normal), 3 components (red, green, blue), x size from image, y size from image,
  201.     // border 0 (normal), rgb color data, unsigned byte data, and finally the data itself.
  202.     glTexImage2D(GL_TEXTURE_2D, 0, 3, image1->sizeX, image1->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, image1->data);
  203.  
  204.     // texture 2 (linear scaling)
  205.     glBindTexture(GL_TEXTURE_2D, texture[1]);   // 2d texture (x and y size)
  206.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // scale linearly when image bigger than texture
  207.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // scale linearly when image smalled than texture
  208.     glTexImage2D(GL_TEXTURE_2D, 0, 3, image1->sizeX, image1->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, image1->data);
  209.  
  210.     // texture 3 (mipmapped scaling)
  211.     glBindTexture(GL_TEXTURE_2D, texture[2]);   // 2d texture (x and y size)
  212.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // scale linearly when image bigger than texture
  213.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST); // scale linearly + mipmap when image smalled than texture
  214.     glTexImage2D(GL_TEXTURE_2D, 0, 3, image1->sizeX, image1->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, image1->data);
  215.  
  216.     // 2d texture, 3 colors, width, height, RGB in that order, byte data, and the data.
  217.     gluBuild2DMipmaps(GL_TEXTURE_2D, 3, image1->sizeX, image1->sizeY, GL_RGB, GL_UNSIGNED_BYTE, image1->data);
  218. };
  219.  
  220. /* A general OpenGL initialization function.  Sets all of the initial parameters. */
  221. GLvoid InitGL(GLsizei Width, GLsizei Height)    // We call this right after our OpenGL window is created.
  222. {
  223.     LoadGLTextures();                           // load the textures.
  224.     glEnable(GL_TEXTURE_2D);                    // Enable texture mapping.
  225.  
  226.     glClearColor(0.0f, 0.0f, 0.0f, 0.0f);   // This Will Clear The Background Color To Black
  227.     glClearDepth(1.0);              // Enables Clearing Of The Depth Buffer
  228.     glDepthFunc(GL_LESS);           // The Type Of Depth Test To Do
  229.     glEnable(GL_DEPTH_TEST);            // Enables Depth Testing
  230.     glEnable(GL_BLEND);         // Turn Blending On
  231.     glShadeModel(GL_SMOOTH);            // Enables Smooth Color Shading
  232.    
  233.     glMatrixMode(GL_PROJECTION);
  234.     glLoadIdentity();               // Reset The Projection Matrix
  235.    
  236.     gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f);   // Calculate The Aspect Ratio Of The Window
  237.    
  238.     glMatrixMode(GL_MODELVIEW);
  239.  
  240.     // set up light number 1.
  241.     glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient);  // add lighting. (ambient)
  242.     glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse);  // add lighting. (diffuse).
  243.     glLightfv(GL_LIGHT1, GL_POSITION,LightPosition); // set light position.
  244.     glEnable(GL_LIGHT1);                             // turn light 1 on.
  245.    
  246.     /* setup blending */
  247.     glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);           // Set The Blending Function For Translucency
  248. }
  249.  
  250. /* The function called when our window is resized (which shouldn't happen, because we're fullscreen) */
  251. GLvoid ReSizeGLScene(GLsizei Width, GLsizei Height)
  252. {
  253.     if (Height==0)              // Prevent A Divide By Zero If The Window Is Too Small
  254.     Height=1;
  255.  
  256.     glViewport(0, 0, Width, Height);        // Reset The Current Viewport And Perspective Transformation
  257.  
  258.     glMatrixMode(GL_PROJECTION);
  259.     glLoadIdentity();
  260.  
  261.     gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f);
  262.     glMatrixMode(GL_MODELVIEW);
  263. }
  264.  
  265. /* The main drawing function. */
  266. GLvoid DrawGLScene(GLvoid)
  267. {
  268.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);     // Clear The Screen And The Depth Buffer
  269.     glLoadIdentity();               // Reset The View
  270.  
  271.     glTranslatef(0.0f,0.0f,z);                  // move z units out from the screen.
  272.    
  273.     glRotatef(xrot,1.0f,0.0f,0.0f);     // Rotate On The X Axis
  274.     glRotatef(yrot,0.0f,1.0f,0.0f);     // Rotate On The Y Axis
  275.  
  276.     glBindTexture(GL_TEXTURE_2D, texture[filter]);   // choose the texture to use.
  277.  
  278.     glEnable(GL_DEPTH_TEST);            // Enables Depth Testing
  279.     glBegin(GL_QUADS);                      // begin drawing a cube
  280.    
  281.     glColor4f(1.0f, 0.0f, 0.0f, 1.0f);    
  282.  
  283.     // Front Face (note that the texture's corners have to match the quad's corners)
  284.     glNormal3f( 0.0f, 0.0f, 1.0f);                              // front face points out of the screen on z.
  285.     glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);  // Bottom Left Of The Texture and Quad
  286.     glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);  // Bottom Right Of The Texture and Quad
  287.     glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  1.0f);  // Top Right Of The Texture and Quad
  288.     glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  1.0f);  // Top Left Of The Texture and Quad
  289.    
  290.     glColor4f(0.0f, 1.0f, 0.0f, 1.0f);    
  291.    
  292.     // Top Face
  293.     glNormal3f( 0.0f, 1.0f, 0.0f);                              // top face points up on y.
  294.     glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);  // Top Left Of The Texture and Quad
  295.     glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,  1.0f,  1.0f);  // Bottom Left Of The Texture and Quad
  296.     glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,  1.0f,  1.0f);  // Bottom Right Of The Texture and Quad
  297.     glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);  // Top Right Of The Texture and Quad
  298.  
  299.     glColor4f(0.0f, 0.0f, 1.0f, 1.0f);    
  300.  
  301.     // Right face
  302.     glNormal3f( 1.0f, 0.0f, 0.0f);                              // right face points right on x.
  303.     glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);  // Bottom Right Of The Texture and Quad
  304.     glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);  // Top Right Of The Texture and Quad
  305.     glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  1.0f);  // Top Left Of The Texture and Quad
  306.     glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);  // Bottom Left Of The Texture and Quad
  307.  
  308.     glEnd();
  309.     glDisable(GL_DEPTH_TEST);           // Enables Depth Testing
  310.     glBegin(GL_QUADS);                      // begin drawing a cube
  311.     glColor4f(1.0f, 0.0f, 0.0f, 0.4f);    
  312.    
  313.     // Back Face
  314.     glNormal3f( 0.0f, 0.0f,-1.0f);                              // back face points into the screen on z.
  315.     glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);  // Bottom Right Of The Texture and Quad
  316.     glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);  // Top Right Of The Texture and Quad
  317.     glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);  // Top Left Of The Texture and Quad
  318.     glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);  // Bottom Left Of The Texture and Quad
  319.  
  320.     glColor4f(0.0f, 1.0f, 0.0f, 0.4f);    
  321.  
  322.     // Bottom Face      
  323.     glNormal3f( 0.0f, -1.0f, 0.0f);                             // bottom face points down on y.
  324.     glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f);  // Top Right Of The Texture and Quad
  325.     glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, -1.0f);  // Top Left Of The Texture and Quad
  326.     glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);  // Bottom Left Of The Texture and Quad
  327.     glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);  // Bottom Right Of The Texture and Quad
  328.    
  329.     glColor4f(0.0f, 0.0f, 1.0f, 0.4f);    
  330.  
  331.     // Left Face
  332.     glNormal3f(-1.0f, 0.0f, 0.0f);                              // left face points left on x.
  333.     glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);  // Bottom Left Of The Texture and Quad
  334.     glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);  // Bottom Right Of The Texture and Quad
  335.     glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  1.0f);  // Top Right Of The Texture and Quad
  336.     glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);  // Top Left Of The Texture and Quad
  337.    
  338.     glEnd();                                    // done with the polygon.
  339.  
  340.     xrot+=xspeed;                       // X Axis Rotation 
  341.     yrot+=yspeed;                       // Y Axis Rotation
  342.  
  343.     // since this is double buffered, swap the buffers to display what just got drawn.
  344.     glutSwapBuffers();
  345. }
  346.  
  347.  
  348. /* The function called whenever a normal key is pressed. */
  349. void keyPressed(unsigned char key, int x, int y)
  350. {
  351.     /* avoid thrashing this procedure */
  352.     usleep(100);
  353.  
  354.     switch (key) {    
  355.     case ESCAPE: // kill everything.
  356.     /* shut down our window */
  357.     glutDestroyWindow(window);
  358.    
  359.     /* exit the program...normal termination. */
  360.     exit(1);                    
  361.     break; // redundant.
  362.  
  363.     case 76:
  364.     case 108: // switch the lighting.
  365.     printf("L/l pressed; light is: %d\n", light);
  366.     light = light ? 0 : 1;              // switch the current value of light, between 0 and 1.
  367.     printf("Light is now: %d\n", light);
  368.     if (!light) {
  369.         glDisable(GL_LIGHTING);
  370.     } else {
  371.         glEnable(GL_LIGHTING);
  372.     }
  373.     break;
  374.  
  375.     case 70:
  376.     case 102: // switch the filter.
  377.     printf("F/f pressed; filter is: %d\n", filter);
  378.     filter+=1;
  379.     if (filter>2) {
  380.         filter=0;  
  381.     }  
  382.     printf("Filter is now: %d\n", filter);
  383.     break;
  384.  
  385.     case 98:
  386.     case 130: // switch the blending.
  387.     printf("B/b pressed; blending is: %d\n", blend);
  388.     blend = blend ? 0 : 1;              // switch the current value of blend, between 0 and 1.
  389.     printf("Blend is now: %d\n", blend);
  390.     if (!blend) {
  391.       glDisable(GL_BLEND);              // Turn Blending Off
  392.       glEnable(GL_DEPTH_TEST);          // Turn Depth Testing On
  393.     } else {
  394.       glEnable(GL_BLEND);           // Turn Blending On
  395.       //glDisable(GL_DEPTH_TEST);         // Turn Depth Testing Off
  396.     }
  397.     break;
  398.  
  399.     default:
  400.       printf ("Key %d pressed. No action there yet.\n", key);
  401.       break;
  402.     }  
  403. }
  404.  
  405. /* The function called whenever a normal key is pressed. */
  406. void specialKeyPressed(int key, int x, int y)
  407. {
  408.     /* avoid thrashing this procedure */
  409.     usleep(100);
  410.  
  411.     switch (key) {    
  412.     case GLUT_KEY_PAGE_UP: // move the cube into the distance.
  413.     z-=0.02f;
  414.     break;
  415.    
  416.     case GLUT_KEY_PAGE_DOWN: // move the cube closer.
  417.     z+=0.02f;
  418.     break;
  419.  
  420.     case GLUT_KEY_UP: // decrease x rotation speed;
  421.     xspeed-=0.01f;
  422.     break;
  423.  
  424.     case GLUT_KEY_DOWN: // increase x rotation speed;
  425.     xspeed+=0.01f;
  426.     break;
  427.  
  428.     case GLUT_KEY_LEFT: // decrease y rotation speed;
  429.     yspeed-=0.01f;
  430.     break;
  431.    
  432.     case GLUT_KEY_RIGHT: // increase y rotation speed;
  433.     yspeed+=0.01f;
  434.     break;
  435.  
  436.     default:
  437.     break;
  438.     }  
  439. }
  440.  
  441. int main(int argc, char **argv)
  442. {  
  443.     /* Initialize GLUT state - glut will take any command line arguments that pertain to it or
  444.        X Windows - look at its documentation at http://reality.sgi.com/mjk/spec3/spec3.html */  
  445.     glutInit(&argc, argv);  
  446.  
  447.     /* Select type of Display mode:  
  448.      Double buffer
  449.      RGBA color
  450.      Depth buffer
  451.      Alpha blending */  
  452.     glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH | GLUT_ALPHA);  
  453.  
  454.     /* get a 640 x 480 window */
  455.     glutInitWindowSize(640, 480);  
  456.  
  457.     /* the window starts at the upper left corner of the screen */
  458.     glutInitWindowPosition(0, 0);  
  459.  
  460.     /* Open a window */  
  461.     window = glutCreateWindow("Jeff Molofee's GL Code Tutorial ... NeHe '99");  
  462.  
  463.     /* Register the function to do all our OpenGL drawing. */
  464.     glutDisplayFunc(&DrawGLScene);  
  465.  
  466.     /* Go fullscreen.  This is as soon as possible. */
  467.     glutFullScreen();
  468.  
  469.     /* Even if there are no events, redraw our gl scene. */
  470.     glutIdleFunc(&DrawGLScene);
  471.  
  472.     /* Register the function called when our window is resized. */
  473.     glutReshapeFunc(&ReSizeGLScene);
  474.  
  475.     /* Register the function called when the keyboard is pressed. */
  476.     glutKeyboardFunc(&keyPressed);
  477.  
  478.     /* Register the function called when special keys (arrows, page down, etc) are pressed. */
  479.     glutSpecialFunc(&specialKeyPressed);
  480.  
  481.     /* Initialize our window. */
  482.     InitGL(640, 480);
  483.  
  484.     /* Start Event Processing Engine */  
  485.     glutMainLoop();  
  486.  
  487.     return 1;
  488. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement