added skybox and options to load real images
authorBrian Paul <brian.paul@tungstengraphics.com>
Fri, 25 Oct 2002 17:20:26 +0000 (17:20 +0000)
committerBrian Paul <brian.paul@tungstengraphics.com>
Fri, 25 Oct 2002 17:20:26 +0000 (17:20 +0000)
progs/demos/cubemap.c

index 56e7ea1457a4bc874e5594e1d43aa346c258849b..5818337c12679dc61592e461dafe817ffcefa086 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: cubemap.c,v 1.3 2000/06/27 17:04:43 brianp Exp $ */
+/* $Id: cubemap.c,v 1.4 2002/10/25 17:20:26 brianp Exp $ */
 
 /*
  * GL_ARB_texture_cube_map demo
  */
 
 
+#include <assert.h>
 #include <math.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include "GL/glut.h"
+#include "../util/readtex.c" /* a hack */
+
 
 static GLfloat Xrot = 0, Yrot = 0;
+static GLfloat EyeDist = 10;
+
+
+static void draw_skybox( void )
+{
+   const GLfloat eps1 = 0.99;
+   const GLfloat br = 20.0; /* box radius */
+
+   glBegin(GL_QUADS);
+
+   /* +X side */
+   glTexCoord3f(1.0, -eps1, -eps1);  glVertex3f(br, -br, -br);
+   glTexCoord3f(1.0, -eps1,  eps1);  glVertex3f(br, -br,  br);
+   glTexCoord3f(1.0,  eps1,  eps1);  glVertex3f(br,  br,  br);
+   glTexCoord3f(1.0,  eps1, -eps1);  glVertex3f(br,  br, -br);
+
+   /* -X side */
+   glTexCoord3f(-1.0,  eps1, -eps1);  glVertex3f(-br,  br, -br);
+   glTexCoord3f(-1.0,  eps1,  eps1);  glVertex3f(-br,  br,  br);
+   glTexCoord3f(-1.0, -eps1,  eps1);  glVertex3f(-br, -br,  br);
+   glTexCoord3f(-1.0, -eps1, -eps1);  glVertex3f(-br, -br, -br);
+
+   /* +Y side */
+   glTexCoord3f(-eps1, 1.0, -eps1);  glVertex3f(-br,  br, -br);
+   glTexCoord3f(-eps1, 1.0,  eps1);  glVertex3f(-br,  br,  br);
+   glTexCoord3f( eps1, 1.0,  eps1);  glVertex3f( br,  br,  br);
+   glTexCoord3f( eps1, 1.0, -eps1);  glVertex3f( br,  br, -br);
+
+   /* -Y side */
+   glTexCoord3f(-eps1, -1.0, -eps1);  glVertex3f(-br, -br, -br);
+   glTexCoord3f(-eps1, -1.0,  eps1);  glVertex3f(-br, -br,  br);
+   glTexCoord3f( eps1, -1.0,  eps1);  glVertex3f( br, -br,  br);
+   glTexCoord3f( eps1, -1.0, -eps1);  glVertex3f( br, -br, -br);
+
+   /* +Z side */
+   glTexCoord3f( eps1, -eps1, 1.0);  glVertex3f( br, -br, br);
+   glTexCoord3f(-eps1, -eps1, 1.0);  glVertex3f(-br, -br, br);
+   glTexCoord3f(-eps1,  eps1, 1.0);  glVertex3f(-br,  br, br);
+   glTexCoord3f( eps1,  eps1, 1.0);  glVertex3f( br,  br, br);
+
+   /* -Z side */
+   glTexCoord3f( eps1,  eps1, -1.0);  glVertex3f( br,  br, -br);
+   glTexCoord3f(-eps1,  eps1, -1.0);  glVertex3f(-br,  br, -br);
+   glTexCoord3f(-eps1, -eps1, -1.0);  glVertex3f(-br, -br, -br);
+   glTexCoord3f( eps1, -eps1, -1.0);  glVertex3f( br, -br, -br);
+
+   glEnd();
+}
 
 
 static void draw( void )
 {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
-   glMatrixMode(GL_TEXTURE);
-   glLoadIdentity();
-   glRotatef(Xrot, 1, 0, 0);
-   glRotatef(Yrot, 0, 1, 0);
-   glutSolidSphere(2.0, 20, 20);
-   glMatrixMode(GL_MODELVIEW);
+   glPushMatrix(); /*MODELVIEW*/
+      glTranslatef( 0.0, 0.0, -EyeDist );
+
+      /* skybox */
+      glDisable(GL_TEXTURE_GEN_S);
+      glDisable(GL_TEXTURE_GEN_T);
+      glDisable(GL_TEXTURE_GEN_R);
+
+      glMatrixMode(GL_MODELVIEW);
+      glPushMatrix();
+         glRotatef(Xrot, 1, 0, 0);
+         glRotatef(Yrot, 0, 1, 0);
+         draw_skybox();
+      glPopMatrix();
+
+      /* sphere */
+      glMatrixMode(GL_TEXTURE);
+      glLoadIdentity();
+      glRotatef(-Yrot, 0, 1, 0);
+      glRotatef(-Xrot, 1, 0, 0);
+
+      glEnable(GL_TEXTURE_GEN_S);
+      glEnable(GL_TEXTURE_GEN_T);
+      glEnable(GL_TEXTURE_GEN_R);
+      glutSolidSphere(2.0, 20, 20);
+
+      glLoadIdentity(); /* texture */
+
+      glMatrixMode(GL_MODELVIEW);
+   glPopMatrix();
 
    glutSwapBuffers();
 }
@@ -62,7 +137,8 @@ static void draw( void )
 
 static void idle(void)
 {
-   Yrot += 5.0;
+   GLfloat t = 0.05 * glutGet(GLUT_ELAPSED_TIME);
+   Yrot = t;
    glutPostRedisplay();
 }
 
@@ -81,9 +157,6 @@ static void set_mode(GLuint mode)
       glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB);
       printf("GL_NORMAL_MAP_ARB mode\n");
    }
-   glEnable(GL_TEXTURE_GEN_S);
-   glEnable(GL_TEXTURE_GEN_T);
-   glEnable(GL_TEXTURE_GEN_R);
 }
 
 
@@ -105,6 +178,16 @@ static void key(unsigned char k, int x, int y)
          mode = !mode;
          set_mode(mode);
          break;
+      case 'z':
+         EyeDist -= 0.5;
+         if (EyeDist < 6.0)
+            EyeDist = 6.0;
+         break;
+      case 'Z':
+         EyeDist += 0.5;
+         if (EyeDist > 90.0)
+            EyeDist = 90;
+         break;
       case 27:
          exit(0);
    }
@@ -114,15 +197,15 @@ static void key(unsigned char k, int x, int y)
 
 static void specialkey(int key, int x, int y)
 {
-   GLfloat step = 10;
+   GLfloat step = 5;
    (void) x;
    (void) y;
    switch (key) {
       case GLUT_KEY_UP:
-         Xrot -= step;
+         Xrot += step;
          break;
       case GLUT_KEY_DOWN:
-         Xrot += step;
+         Xrot -= step;
          break;
       case GLUT_KEY_LEFT:
          Yrot -= step;
@@ -138,17 +221,17 @@ static void specialkey(int key, int x, int y)
 /* new window size or exposure */
 static void reshape(int width, int height)
 {
+   GLfloat ar = (float) width / (float) height;
    glViewport(0, 0, (GLint)width, (GLint)height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
-   glFrustum( -2.0, 2.0, -2.0, 2.0, 6.0, 20.0 );
+   glFrustum( -2.0*ar, 2.0*ar, -2.0, 2.0, 4.0, 100.0 );
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
-   glTranslatef( 0.0, 0.0, -8.0 );
 }
 
 
-static void init( void )
+static void init_checkers( void )
 {
 #define CUBE_TEX_SIZE 64
    GLubyte image[CUBE_TEX_SIZE][CUBE_TEX_SIZE][3];
@@ -171,16 +254,6 @@ static void init( void )
 
    GLint i, j, f;
 
-   /* check for extension */
-   {
-      char *exten = (char *) glGetString(GL_EXTENSIONS);
-      if (!strstr(exten, "GL_ARB_texture_cube_map")) {
-         printf("Sorry, this demo requires GL_ARB_texture_cube_map\n");
-         exit(0);
-      }
-   }
-
-
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
 
    /* make colored checkerboard cube faces */
@@ -203,18 +276,102 @@ static void init( void )
       glTexImage2D(targets[f], 0, GL_RGB, CUBE_TEX_SIZE, CUBE_TEX_SIZE, 0,
                    GL_RGB, GL_UNSIGNED_BYTE, image);
    }
+}
+
 
-#if 1
-   glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-   glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-#else
-   glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-   glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-#endif
+static void load(GLenum target, const char *filename,
+                 GLboolean flipTB, GLboolean flipLR)
+{
+   GLint w, h;
+   GLenum format;
+   GLubyte *img = LoadRGBImage( filename, &w, &h, &format );
+   if (!img) {
+      printf("Error: couldn't load texture image %s\n", filename);
+      exit(1);
+   }
+   assert(format == GL_RGB);
+
+   /* <sigh> the way the texture cube mapping works, we have to flip
+    * images to make things look right.
+    */
+   if (flipTB) {
+      const int stride = 3 * w;
+      GLubyte temp[3*1024];
+      int i;
+      for (i = 0; i < h / 2; i++) {
+         memcpy(temp, img + i * stride, stride);
+         memcpy(img + i * stride, img + (h - i - 1) * stride, stride);
+         memcpy(img + (h - i - 1) * stride, temp, stride);
+      }
+   }
+   if (flipLR) {
+      const int stride = 3 * w;
+      GLubyte temp[3];
+      GLubyte *row;
+      int i, j;
+      for (i = 0; i < h; i++) {
+         row = img + i * stride;
+         for (j = 0; j < w / 2; j++) {
+            int k = w - j - 1;
+            temp[0] = row[j*3+0];
+            temp[1] = row[j*3+1];
+            temp[2] = row[j*3+2];
+            row[j*3+0] = row[k*3+0];
+            row[j*3+1] = row[k*3+1];
+            row[j*3+2] = row[k*3+2];
+            row[k*3+0] = temp[0];
+            row[k*3+1] = temp[1];
+            row[k*3+2] = temp[2];
+         }
+      }
+   }
+
+   gluBuild2DMipmaps(target, GL_RGB, w, h, format, GL_UNSIGNED_BYTE, img);
+   free(img);
+}
+
+
+static void load_envmaps(void)
+{
+   load(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, "right.rgb", GL_TRUE, GL_FALSE);
+   load(GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB, "left.rgb", GL_TRUE, GL_FALSE);
+   load(GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB, "top.rgb", GL_FALSE, GL_TRUE);
+   load(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB, "bottom.rgb", GL_FALSE, GL_TRUE);
+   load(GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB, "front.rgb", GL_TRUE, GL_FALSE);
+   load(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB, "back.rgb", GL_TRUE, GL_FALSE);
+}
+
+
+static void init( GLboolean useImageFiles )
+{
+   GLenum filter;
+
+   /* check for extension */
+   {
+      char *exten = (char *) glGetString(GL_EXTENSIONS);
+      if (!strstr(exten, "GL_ARB_texture_cube_map")) {
+         printf("Sorry, this demo requires GL_ARB_texture_cube_map\n");
+         exit(0);
+      }
+   }
+   printf("GL_RENDERER: %s\n", (char *) glGetString(GL_RENDERER));
+
+   if (useImageFiles) {
+      load_envmaps();
+      filter = GL_LINEAR;
+   }
+   else {
+      init_checkers();
+      filter = GL_NEAREST;
+   }
+
+   glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, filter);
+   glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, filter);
    glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 
    glEnable(GL_TEXTURE_CUBE_MAP_ARB);
+   glEnable(GL_DEPTH_TEST);
 
    glClearColor(.3, .3, .3, 0);
    glColor3f( 1.0, 1.0, 1.0 );
@@ -229,16 +386,21 @@ static void usage(void)
    printf("  SPACE - toggle animation\n");
    printf("  CURSOR KEYS - rotation\n");
    printf("  m - toggle texgen reflection mode\n");
+   printf("  z/Z - change viewing distance\n");
 }
 
 
 int main( int argc, char *argv[] )
 {
    glutInitWindowPosition(0, 0);
-   glutInitWindowSize(300, 300);
+   glutInitWindowSize(600, 500);
    glutInitDisplayMode( GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE );
    glutCreateWindow("Texture Cube Maping");
-   init();
+
+   if (argc > 1 && strcmp(argv[1] , "-i") == 0)
+      init( 1 );
+   else
+      init( 0 );
    glutReshapeFunc( reshape );
    glutKeyboardFunc( key );
    glutSpecialFunc( specialkey );