#include #include #include #include #include #include "texture.h" /* Some files do not define M_PI... */ #ifndef M_PI #define M_PI 3.14159265358979323846 #endif #ifdef _WIN32 #include #define sleep(x) Sleep((x*1000)) #else #include #endif #include const char defaultBaseName[] = "data/small"; GLuint *faces[6]; GLsizei faceW[6], faceH[6]; GLfloat angle1[6] = {90, 180, 270, 0, 90, -90}; GLfloat axis1[6][3] = {{0,1,0}, {0,1,0}, {0,1,0}, {0,1,0}, {1,0,0}, {1,0,0}}; GLfloat angle2[6] = {0, 0, 0, 0, 180, 180}; GLfloat axis2[6][3] = {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,1,0}, {0,1,0}}; GLuint *load_texture(const char *fname, GLsizei *w, GLsizei *h) { int comps; GLuint *img; int i; img = read_texture(fname, w, h, &comps); if (!img) { fprintf(stderr, "Could not open %s\n", fname); exit(1); } for (i = 0; i < *w * *h; i++) { img[i] |= 0xff; } return img; } void set_texture_border(GLuint val, GLuint mask, GLsizei w, GLsizei h, GLuint *pix) { int x, y; val &= mask; mask = ~mask; /* top & bottom rows */ for (x = 0; x < w; x++) { pix[x] = (pix[x] & mask) | val; pix[x + (h-1)*w] = (pix[x + (h-1)*w] & mask) | val; } for (y = 0; y < h; y++) { pix[y*w] = (pix[y*w] & mask) | val; pix[y*w + (w-1)] = (pix[y*w + (w-1)] & mask) | val; } } void init(void) { glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); } void reshape(GLsizei w, GLsizei h) { glViewport(0, 0, w, h); glLoadIdentity(); glOrtho(-2, 2, -2, 2, 0, 5); } void draw_special_sphere(int tess) { float r = 1.0, r1, r2, z1, z2; float theta, phi; int nlon = tess, nlat = tess; int i, j; glBegin(GL_TRIANGLE_FAN); theta = M_PI*1.0/nlat; r2 = r*sin(theta); z2 = r*cos(theta); glNormal3f(0.0, 0.0, 1.0); glVertex4f(0.0, 0.0, r*r, r); for (j = 0, phi = 0.0; j <= nlon; j++, phi = 2*M_PI*j/nlon) { glNormal3f(r2*cos(phi), r2*sin(phi), z2); glVertex4f(r2*cos(phi)*z2, r2*sin(phi)*z2, z2*z2, z2); /* top */ } glEnd(); for (i = 2; i < nlat; i++) { theta = M_PI*i/nlat; r1 = r*sin(M_PI*(i-1)/nlat); z1 = r*cos(M_PI*(i-1)/nlat); r2 = r*sin(theta); z2 = r*cos(theta); if (fabs(z1) < 0.01 || fabs(z2) < 0.01) break; glBegin(GL_QUAD_STRIP); for (j = 0, phi = 0; j <= nlat; j++, phi = 2*M_PI*j/nlon) { glNormal3f(r1*cos(phi), r1*sin(phi), z1); glVertex4f(r1*cos(phi)*z1, r1*sin(phi)*z1, z1*z1, z1); glNormal3f(r2*cos(phi), r2*sin(phi), z2); glVertex4f(r2*cos(phi)*z2, r2*sin(phi)*z2, z2*z2, z2); } glEnd(); } } void render_spheremap(int width, int height) { GLfloat p[4]; int i; glColor4f(1, 1, 1, 1); glEnable(GL_TEXTURE_2D); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexGenf(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); p[0] = 2.0; p[1] = p[2] = p[3] = 0.0; /* 2zx */ glTexGenfv(GL_S, GL_OBJECT_PLANE, p); glTexGenf(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); p[0] = 0.0; p[1] = 2.0; p[2] = p[3] = 0.0; /* 2zy */ glTexGenfv(GL_T, GL_OBJECT_PLANE, p); glTexGenf(GL_R, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); p[0] = p[1] = 0.0; p[2] = 0.0; p[3] = 2.0; /* 2z */ glTexGenfv(GL_R, GL_OBJECT_PLANE, p); glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); glEnable(GL_TEXTURE_GEN_R); glMatrixMode(GL_PROJECTION); glPushMatrix(); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glMatrixMode(GL_TEXTURE); glPushMatrix(); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-1, 1, -1, 1, 1.0, 100); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(0, 0, 6, 0, 0, 0, 0, 1, 0); glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glClearColor(0.0, 0.0, 0.0, 1.0); glClearDepth(1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); for (i = 0; i < 6; i++) { glTexImage2D(GL_TEXTURE_2D, 0, 4, faceW[i], faceH[i], 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)faces[i]); glMatrixMode(GL_TEXTURE); glLoadIdentity(); glScalef(0.5, 0.5, 1.0); glTranslatef(1.0, 1.0, 0.0); glFrustum(-1.01, 1.01, -1.01, 1.01, 1.0, 100.0); if (angle2[i]) { glRotatef(angle2[i], axis2[i][0], axis2[i][1], axis2[i][2]); } glRotatef(angle1[i], axis1[i][0], axis1[i][1], axis1[i][2]); /* XXX atul does another angle thing here... */ /* XXX atul does a third angle thing here... */ glTranslatef(0.0, 0.0, -1.00); glMatrixMode(GL_MODELVIEW); glClear(GL_DEPTH_BUFFER_BIT); draw_special_sphere(20); sleep(1); } glDisable(GL_BLEND); glDisable(GL_CULL_FACE); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); glMatrixMode(GL_TEXTURE); glPopMatrix(); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); glDisable(GL_TEXTURE_GEN_R); glDisable(GL_TEXTURE_2D); } void draw(void) { GLenum err; glClear(GL_COLOR_BUFFER_BIT); render_spheremap(256, 256); err = glGetError(); if (err != GL_NO_ERROR) printf("Error: %s\n", gluErrorString(err)); } /* ARGSUSED1 */ void key(unsigned char key, int x, int y) { if (key == 27) exit(0); } void show_usage(void) { fprintf(stderr, "Usage:\n"); fprintf(stderr, "genspheremap -- use default files" "(%s0.rgb through %s5.rgb)\n", defaultBaseName, defaultBaseName); fprintf(stderr, "genspheremap baseName -- use files of the form " "baseName0.rgb through baseName5.rgb\n"); fprintf(stderr, "genspheremap f0.rgb f1.rgb f2.rgb f3.rgb f4.rgb f5.rgb\n"); } main(int argc, char *argv[]) { const char *baseName; char fname[128]; int i; glutInitWindowSize(512, 512); glutInitWindowPosition(0, 0); glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGB); glutCreateWindow(argv[0]); glutDisplayFunc(draw); glutKeyboardFunc(key); glutReshapeFunc(reshape); init(); if (argc == 1 || argc == 2) { if (argc == 1) baseName = defaultBaseName; else baseName = argv[1]; assert(strlen(baseName) < 128 - (strlen("0.rgb") + 1)); for (i = 0; i < 6; i++) { sprintf(fname, "%s%d.rgb", baseName, i); faces[i] = load_texture(fname, &faceW[i], &faceH[i]); } } else if (argc == 7) { for (i = 0; i < 6; i++) { faces[i] = load_texture(fname, &faceW[i], &faceH[i]); } } else { show_usage(); exit(1); } for (i = 0; i < 6; i++) { set_texture_border(0x00, 0xff, faceW[i], faceH[i], faces[i]); } glutMainLoop(); return 0; }