132001f49Smrg
232001f49Smrg
332001f49Smrg#include <assert.h>
432001f49Smrg#include <stdio.h>
532001f49Smrg#include <stddef.h>
632001f49Smrg#include <stdlib.h>
732001f49Smrg#include <string.h>
832001f49Smrg#include <GL/glew.h>
932001f49Smrg#include "readtex.h"
1032001f49Smrg#include "skybox.h"
1132001f49Smrg
1232001f49Smrg
1332001f49Smrgstatic int
1432001f49Smrgload(GLenum target, const char *filename,
1532001f49Smrg     GLboolean flipTB, GLboolean flipLR)
1632001f49Smrg{
1732001f49Smrg   GLint w, h;
1832001f49Smrg   GLenum format;
1932001f49Smrg   GLubyte *img = LoadRGBImage( filename, &w, &h, &format );
2032001f49Smrg   if (!img) {
2132001f49Smrg      printf("Error: couldn't load texture image %s\n", filename);
2232001f49Smrg      return 0;
2332001f49Smrg   }
2432001f49Smrg   assert(format == GL_RGB);
2532001f49Smrg
2632001f49Smrg   printf("Load cube face 0x%x: %s %d x %d\n", target, filename, w, h);
2732001f49Smrg
2832001f49Smrg   /* <sigh> the way the texture cube mapping works, we have to flip
2932001f49Smrg    * images to make things look right.
3032001f49Smrg    */
3132001f49Smrg   if (flipTB) {
3232001f49Smrg      const int stride = 3 * w;
3332001f49Smrg      GLubyte temp[3*1024];
3432001f49Smrg      int i;
3532001f49Smrg      for (i = 0; i < h / 2; i++) {
3632001f49Smrg         memcpy(temp, img + i * stride, stride);
3732001f49Smrg         memcpy(img + i * stride, img + (h - i - 1) * stride, stride);
3832001f49Smrg         memcpy(img + (h - i - 1) * stride, temp, stride);
3932001f49Smrg      }
4032001f49Smrg   }
4132001f49Smrg   if (flipLR) {
4232001f49Smrg      const int stride = 3 * w;
4332001f49Smrg      GLubyte temp[3];
4432001f49Smrg      GLubyte *row;
4532001f49Smrg      int i, j;
4632001f49Smrg      for (i = 0; i < h; i++) {
4732001f49Smrg         row = img + i * stride;
4832001f49Smrg         for (j = 0; j < w / 2; j++) {
4932001f49Smrg            int k = w - j - 1;
5032001f49Smrg            temp[0] = row[j*3+0];
5132001f49Smrg            temp[1] = row[j*3+1];
5232001f49Smrg            temp[2] = row[j*3+2];
5332001f49Smrg            row[j*3+0] = row[k*3+0];
5432001f49Smrg            row[j*3+1] = row[k*3+1];
5532001f49Smrg            row[j*3+2] = row[k*3+2];
5632001f49Smrg            row[k*3+0] = temp[0];
5732001f49Smrg            row[k*3+1] = temp[1];
5832001f49Smrg            row[k*3+2] = temp[2];
5932001f49Smrg         }
6032001f49Smrg      }
6132001f49Smrg   }
6232001f49Smrg
6332001f49Smrg   gluBuild2DMipmaps(target, GL_RGB, w, h, format, GL_UNSIGNED_BYTE, img);
6432001f49Smrg   free(img);
6532001f49Smrg   return 1;
6632001f49Smrg}
6732001f49Smrg
6832001f49Smrg
6932001f49SmrgGLuint
7032001f49SmrgLoadSkyBoxCubeTexture(const char *filePosX,
7132001f49Smrg                      const char *fileNegX,
7232001f49Smrg                      const char *filePosY,
7332001f49Smrg                      const char *fileNegY,
7432001f49Smrg                      const char *filePosZ,
7532001f49Smrg                      const char *fileNegZ)
7632001f49Smrg{
7732001f49Smrg   GLuint tex;
7832001f49Smrg
7932001f49Smrg   glGenTextures(1, &tex);
8032001f49Smrg   glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
8132001f49Smrg
8232001f49Smrg   glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
8332001f49Smrg   glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER,
8432001f49Smrg                   GL_LINEAR_MIPMAP_NEAREST);
8532001f49Smrg
8632001f49Smrg   if (!load(GL_TEXTURE_CUBE_MAP_POSITIVE_X, filePosX, GL_TRUE, GL_TRUE))
8732001f49Smrg      return 0;
8832001f49Smrg   if (!load(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, fileNegX, GL_TRUE, GL_TRUE))
8932001f49Smrg      return 0;
9032001f49Smrg   if (!load(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, filePosY, GL_TRUE, GL_TRUE))
9132001f49Smrg      return 0;
9232001f49Smrg   if (!load(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, fileNegY, GL_TRUE, GL_TRUE))
9332001f49Smrg      return 0;
9432001f49Smrg   if (!load(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, filePosZ, GL_TRUE, GL_TRUE))
9532001f49Smrg      return 0;
9632001f49Smrg   if (!load(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, fileNegZ, GL_TRUE, GL_TRUE))
9732001f49Smrg      return 0;
9832001f49Smrg
9932001f49Smrg   return tex;
10032001f49Smrg}
10132001f49Smrg
10232001f49Smrg
10332001f49Smrg#define eps1 0.99
10432001f49Smrg#define br   20.0  /* box radius */
10532001f49Smrg
10632001f49Smrgvoid
10732001f49SmrgDrawSkyBoxCubeTexture(GLuint tex)
10832001f49Smrg{
10932001f49Smrg   struct vertex {
11032001f49Smrg      float x, y, z, s, t, r;
11132001f49Smrg   };
11232001f49Smrg
11332001f49Smrg   static const struct vertex verts[24] = {
11432001f49Smrg      /* +X side */
11532001f49Smrg      { br, -br, -br,  1.0, -eps1, -eps1 },
11632001f49Smrg      { br, -br,  br,  1.0, -eps1,  eps1 },
11732001f49Smrg      { br,  br,  br,  1.0,  eps1,  eps1 },
11832001f49Smrg      { br,  br, -br,  1.0,  eps1, -eps1 },
11932001f49Smrg
12032001f49Smrg      /* -X side */
12132001f49Smrg      { -br,  br, -br,  -1.0,  eps1, -eps1 },
12232001f49Smrg      { -br,  br,  br,  -1.0,  eps1,  eps1 },
12332001f49Smrg      { -br, -br,  br,  -1.0, -eps1,  eps1 },
12432001f49Smrg      { -br, -br, -br,  -1.0, -eps1, -eps1 },
12532001f49Smrg
12632001f49Smrg      /* +Y side */
12732001f49Smrg      {  br,  br, -br,   eps1, 1.0, -eps1 },
12832001f49Smrg      {  br,  br,  br,   eps1, 1.0,  eps1 },
12932001f49Smrg      { -br,  br,  br,  -eps1, 1.0,  eps1 },
13032001f49Smrg      { -br,  br, -br,  -eps1, 1.0, -eps1 },
13132001f49Smrg
13232001f49Smrg      /* -Y side */
13332001f49Smrg      { -br, -br, -br,  -eps1, -1.0, -eps1 },
13432001f49Smrg      { -br, -br,  br,  -eps1, -1.0,  eps1 },
13532001f49Smrg      {  br, -br,  br,   eps1, -1.0,  eps1 },
13632001f49Smrg      {  br, -br, -br,   eps1, -1.0, -eps1 },
13732001f49Smrg
13832001f49Smrg      /* +Z side */
13932001f49Smrg      {  br, -br, br,   eps1, -eps1, 1.0 },
14032001f49Smrg      { -br, -br, br,  -eps1, -eps1, 1.0 },
14132001f49Smrg      { -br,  br, br,  -eps1,  eps1, 1.0 },
14232001f49Smrg      {  br,  br, br,   eps1,  eps1, 1.0 },
14332001f49Smrg
14432001f49Smrg      /* -Z side */
14532001f49Smrg      {  br,  br, -br,   eps1,  eps1, -1.0 },
14632001f49Smrg      { -br,  br, -br,  -eps1,  eps1, -1.0 },
14732001f49Smrg      { -br, -br, -br,  -eps1, -eps1, -1.0 },
14832001f49Smrg      {  br, -br, -br,   eps1, -eps1, -1.0 },
14932001f49Smrg   };
15032001f49Smrg
15132001f49Smrg   static GLuint vbo = 0;
15232001f49Smrg
15332001f49Smrg   if (!vbo ) {
15432001f49Smrg      glGenBuffersARB(1, &vbo);
15532001f49Smrg      glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo);
15632001f49Smrg      glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts), verts,
15732001f49Smrg                      GL_STATIC_DRAW_ARB);
15832001f49Smrg   }
15932001f49Smrg   else {
16032001f49Smrg      glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo);
16132001f49Smrg   }
16232001f49Smrg
16332001f49Smrg   glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
16432001f49Smrg
16532001f49Smrg   glVertexPointer(3, GL_FLOAT, sizeof(struct vertex),
16632001f49Smrg                   (void *) offsetof(struct vertex, x));
16732001f49Smrg   glTexCoordPointer(3, GL_FLOAT, sizeof(struct vertex),
16832001f49Smrg                     (void *) offsetof(struct vertex, s));
16932001f49Smrg   glEnableClientState(GL_VERTEX_ARRAY);
17032001f49Smrg   glEnableClientState(GL_TEXTURE_COORD_ARRAY);
17132001f49Smrg
17232001f49Smrg   glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
17332001f49Smrg   glEnable(GL_TEXTURE_CUBE_MAP);
17432001f49Smrg
17532001f49Smrg   glDisable(GL_BLEND);
17632001f49Smrg
17732001f49Smrg   glDrawArrays(GL_QUADS, 0, 24);
17832001f49Smrg
17932001f49Smrg   glDisable(GL_TEXTURE_CUBE_MAP);
18032001f49Smrg
18132001f49Smrg   glDisableClientState(GL_VERTEX_ARRAY);
18232001f49Smrg   glDisableClientState(GL_TEXTURE_COORD_ARRAY);
18332001f49Smrg
18432001f49Smrg   glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
18532001f49Smrg}
18632001f49Smrg
187