textile.c
上传用户:xk288cn
上传日期:2007-05-28
资源大小:4876k
文件大小:9k
源码类别:

GIS编程

开发平台:

Visual C++

  1. /*
  2. ** cc -o textile textile.c -lGLU -lGL -lglut -lXmu -lX11 -lm
  3. */
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <math.h>
  7. #include <string.h>
  8. #include <GL/glut.h>
  9. #include "texture.h"
  10. int maxTextureSize;
  11. int maxTextureLevel;
  12. int imageWidth, imageHeight;
  13. GLubyte *imageData;
  14. int texWidthLevel0, texHeightLevel0;
  15. int texWidthTiles, texHeightTiles;
  16. GLubyte **texImageLevel;
  17. GLboolean useBorder = GL_TRUE;
  18. GLboolean useClamp = GL_TRUE;
  19. GLboolean useLinear = GL_TRUE;
  20. GLboolean useMipmap = GL_TRUE;
  21. GLboolean useTextureTiling = GL_TRUE;
  22. /* (int)floor(log2(a)) */
  23. static int
  24. iflog2(unsigned int a)
  25. {
  26.     int x = 0;
  27.     while (a >>= 1) ++x;
  28.     return x;
  29. }
  30. static void
  31. initialize(void)
  32. {
  33.     glMatrixMode(GL_PROJECTION);
  34.     glLoadIdentity();
  35.     glFrustum(-0.5, 0.5, -0.5, 0.5, 0.5, 1.5);
  36.     glMatrixMode(GL_MODELVIEW);
  37.     glLoadIdentity();
  38.     glTranslatef(0, 0, -0.90);
  39.     glRotatef( 45.0, 0, 1, 0);
  40.     glTranslatef(-0.5, -0.5, 0.0);
  41. #if 0
  42.     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
  43. #else
  44.     maxTextureSize = 32;
  45. #endif
  46.     maxTextureLevel = iflog2(maxTextureSize);
  47.     texImageLevel = (GLubyte **) calloc(maxTextureLevel+1, sizeof(GLubyte *));
  48.     if (texImageLevel == NULL) {
  49. fprintf(stderr, "texture level image allocation failedn");
  50. exit(EXIT_FAILURE);
  51.     }
  52.     glClearColor(0.1, 0.1, 0.1, 0.1);
  53. }
  54. static void
  55. imgLoad(char *filename_in, int *w_out, int *h_out, GLubyte **img_out)
  56. {
  57.     int comp;
  58.     *img_out = (GLubyte *)read_texture(filename_in, w_out, h_out, &comp);
  59.     if (img_out == NULL) {
  60. fprintf(stderr, "unable to read %sn", filename_in);
  61. exit(EXIT_FAILURE);
  62.     }
  63.     if (comp != 3 && comp != 4) {
  64. fprintf(stderr, "%s: image is not RGB or RGBAn", filename_in);
  65. exit(EXIT_FAILURE);
  66.     }
  67. }
  68. static void
  69. buildMipmaps(void)
  70. {
  71.     int level, levelWidth, levelHeight;
  72.     if (useTextureTiling) {
  73. int width2 = iflog2(imageWidth);
  74. int height2 = iflog2(imageHeight);
  75. width2 = (width2 > maxTextureLevel) ? width2 : maxTextureLevel;
  76. height2 = (height2 > maxTextureLevel) ? height2 : maxTextureLevel;
  77. texWidthLevel0 = 1 << width2;
  78. texHeightLevel0 = 1 << height2;
  79. texWidthTiles = texWidthLevel0 >> maxTextureLevel;
  80. texHeightTiles = texHeightLevel0 >> maxTextureLevel;
  81.     } else {
  82. texWidthLevel0 = maxTextureSize;
  83. texHeightLevel0 = maxTextureSize;
  84. texWidthTiles = 1;
  85. texHeightTiles = 1;
  86.     }
  87.     texImageLevel[0] = (GLubyte *)
  88. calloc(1, (texWidthLevel0+2)*(texHeightLevel0+2)*4*sizeof(GLubyte));
  89.     glPixelStorei(GL_PACK_ROW_LENGTH, texWidthLevel0+2);
  90.     glPixelStorei(GL_PACK_SKIP_PIXELS, 1);
  91.     glPixelStorei(GL_PACK_SKIP_ROWS, 1);
  92.     gluScaleImage(GL_RGBA, imageWidth, imageHeight,
  93.   GL_UNSIGNED_BYTE, imageData,
  94.   texWidthLevel0, texHeightLevel0,
  95.   GL_UNSIGNED_BYTE, texImageLevel[0]);
  96.     glPixelStorei(GL_UNPACK_SKIP_PIXELS, 1);
  97.     glPixelStorei(GL_UNPACK_SKIP_ROWS, 1);
  98.     levelWidth = texWidthLevel0;
  99.     levelHeight = texHeightLevel0;
  100.     for (level=0; level<maxTextureLevel; ++level) {
  101. int newLevelWidth = (levelWidth > 1) ? levelWidth / 2 : 1;
  102. int newLevelHeight = (levelHeight > 1) ? levelHeight / 2 : 1;
  103. texImageLevel[level+1] = (GLubyte *)
  104.     calloc(1, (newLevelWidth+2)*(newLevelHeight+2)*4*sizeof(GLubyte));
  105. glPixelStorei(GL_PACK_ROW_LENGTH, newLevelWidth+2);
  106. glPixelStorei(GL_UNPACK_ROW_LENGTH, levelWidth+2);
  107. gluScaleImage(GL_RGBA, levelWidth, levelHeight,
  108.       GL_UNSIGNED_BYTE, texImageLevel[level],
  109.       newLevelWidth, newLevelHeight,
  110.       GL_UNSIGNED_BYTE, texImageLevel[level+1]);
  111. levelWidth = newLevelWidth;
  112. levelHeight = newLevelHeight;
  113.     }
  114.     glPixelStorei(GL_PACK_ROW_LENGTH, 0);
  115.     glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
  116.     glPixelStorei(GL_PACK_SKIP_ROWS, 0);
  117.     glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
  118.     glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
  119.     glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
  120. }
  121. static void
  122. freeMipmaps(void)
  123. {
  124.     int i;
  125.     for (i=0; i<=maxTextureLevel; ++i) {
  126. if (texImageLevel[i] != NULL) {
  127.     free(texImageLevel[i]);
  128.     texImageLevel[i] = NULL;
  129. }
  130.     }
  131. }
  132. static void
  133. loadTile(int row, int col)
  134. {
  135.     int border = useBorder ? 1 : 0;
  136.     int level, levelWidth, levelHeight;
  137.     levelWidth = texWidthLevel0;
  138.     levelHeight = texHeightLevel0;
  139.     for (level=0; level<=maxTextureLevel; ++level) {
  140. int tileWidth = levelWidth / texWidthTiles;
  141. int tileHeight = levelHeight / texHeightTiles;
  142. int skipPixels = col * tileWidth + (1 - border);
  143. int skipRows = row * tileHeight + (1 - border);
  144. glPixelStorei(GL_UNPACK_ROW_LENGTH, levelWidth+2);
  145. glPixelStorei(GL_UNPACK_SKIP_PIXELS, skipPixels);
  146. glPixelStorei(GL_UNPACK_SKIP_ROWS, skipRows);
  147. glTexImage2D(GL_TEXTURE_2D, level, 4,
  148.      tileWidth + 2*border, tileHeight + 2*border,
  149.      border, GL_RGBA, GL_UNSIGNED_BYTE, texImageLevel[level]);
  150. if (levelWidth > 1) levelWidth = levelWidth / 2;
  151. if (levelHeight > 1) levelHeight = levelHeight / 2;
  152.     }
  153.     glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
  154.     glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
  155.     glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
  156. }
  157. static void
  158. redraw(void)
  159. {
  160.     GLenum minFilterMode, magFilterMode, wrapMode;
  161.     char *minFilterName, *magFilterName, *wrapName;
  162.     int i, j;
  163.     if (useLinear) {
  164. if (useMipmap) {
  165.     minFilterMode = GL_LINEAR_MIPMAP_LINEAR;
  166.     minFilterName = "LINEAR_MIPMAP_LINEAR";
  167. } else {
  168.     minFilterMode = GL_LINEAR;
  169.     minFilterName = "LINEAR";
  170. }
  171. magFilterMode = GL_LINEAR;
  172. magFilterName = "LINEAR";
  173.     } else {
  174. if (useMipmap) {
  175.     minFilterMode = GL_NEAREST_MIPMAP_LINEAR;
  176.     minFilterName = "NEAREST_MIPMAP_LINEAR";
  177. } else {
  178.     minFilterMode = GL_NEAREST;
  179.     minFilterName = "NEAREST";
  180. }
  181. magFilterMode = GL_NEAREST;
  182. magFilterName = "NEAREST";
  183.     }
  184.     if (useClamp) {
  185. wrapMode = GL_CLAMP;
  186. wrapName = "CLAMP";
  187.     } else {
  188. wrapMode = GL_REPEAT;
  189. wrapName = "REPEAT";
  190.     }
  191.     fprintf(stderr, "tile(%s) ", useTextureTiling ? "yes" : "no");
  192.     fprintf(stderr, "border(%s) ", useBorder ? "yes" : "no");
  193.     fprintf(stderr, "filter(%s, %s) ", minFilterName, magFilterName);
  194.     fprintf(stderr, "wrap(%s) ", wrapName);
  195.     fprintf(stderr, "n");
  196.     glClear(GL_COLOR_BUFFER_BIT);
  197.     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  198.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilterMode);
  199.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilterMode);
  200.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapMode);
  201.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapMode);
  202.     buildMipmaps();
  203.     glEnable(GL_TEXTURE_2D);
  204.     for (i=0; i<texHeightTiles; ++i) {
  205. float ySize = 1.0 / texHeightTiles;
  206. float y0 = i * ySize;
  207. float y1 = y0 + ySize;
  208. for (j=0; j<texWidthTiles; ++j) {
  209.     float xSize = 1.0 / texWidthTiles;
  210.     float x0 = j * xSize;
  211.     float x1 = x0 + xSize;
  212.     loadTile(i, j);
  213.     glBegin(GL_TRIANGLE_STRIP);
  214.     glTexCoord2f(0.0, 1.0); glVertex2f(x0, y1);
  215.     glTexCoord2f(0.0, 0.0); glVertex2f(x0, y0);
  216.     glTexCoord2f(1.0, 1.0); glVertex2f(x1, y1);
  217.     glTexCoord2f(1.0, 0.0); glVertex2f(x1, y0);
  218.     glEnd();
  219. }
  220.     }
  221.     glDisable(GL_TEXTURE_2D);
  222.     freeMipmaps();
  223. }
  224. static void
  225. usage(char *argv[])
  226. {
  227.     fprintf(stderr, "n");
  228.     fprintf(stderr, "usage: %s [ options ] filenamen", argv[0]);
  229.     fprintf(stderr, "n");
  230.     fprintf(stderr, "    Demonstrates using texture bordersn");
  231.     fprintf(stderr, "    to tile a large texturen");
  232.     fprintf(stderr, "n");
  233.     fprintf(stderr, "  Options:n");
  234.     fprintf(stderr, "    -sb  single bufferedn");
  235.     fprintf(stderr, "    -db  double bufferedn");
  236.     fprintf(stderr, "n");
  237. }
  238. /*ARGSUSED1*/
  239. void
  240. key(unsigned char key, int x, int y) {
  241.     switch(key) {
  242.     case '33': exit(EXIT_SUCCESS); break;
  243.     case 'b': useBorder = !useBorder; break;
  244.     case 'w': useClamp = !useClamp; break;
  245.     case 'l': useLinear = !useLinear; break;
  246.     case 'm': useMipmap = !useMipmap; break;
  247.     case 't': useTextureTiling = !useTextureTiling; break;
  248.     default: break;
  249.     }
  250.     glutPostRedisplay();
  251. }
  252. int doubleBuffered = GL_FALSE;
  253. void display(void) {
  254.     GLenum error;
  255.     redraw();
  256.     if (doubleBuffered)
  257. glutSwapBuffers();
  258.     else
  259. glFlush();
  260.     while ((error = glGetError()) != GL_NO_ERROR) {
  261. fprintf(stderr, "Error: %sn", (char *) gluErrorString(error));
  262.     }
  263. }
  264. void
  265. reshape(int w, int h) {
  266.     glViewport(0, 0, w, h);
  267. }
  268. int
  269. main(int argc, char *argv[])
  270. {
  271.     char *name = "Texture Tiling Test";
  272.     int width = 300, height = 300;
  273.     char *filename = "../data/fendi.rgb";
  274.     int i;
  275.     glutInitWindowSize(width, height);
  276.     glutInit(&argc, argv);
  277.     for (i=1; i<argc; ++i) {
  278. if (!strcmp("-sb", argv[i])) {
  279.     doubleBuffered = GL_FALSE;
  280. } else if (!strcmp("-db", argv[i])) {
  281.     doubleBuffered = GL_TRUE;
  282. } else if (argv[i][0] != '-' && i==argc-1) {
  283.     filename = argv[i];
  284. } else {
  285.     usage(argv);
  286.     exit(EXIT_FAILURE);
  287. }
  288.     }
  289.     if (filename == NULL) {
  290. usage(argv);
  291. exit(EXIT_FAILURE);
  292.     }
  293.     imgLoad(filename, &imageWidth, &imageHeight, &imageData);
  294.     glutInitDisplayMode(GLUT_RGBA|(doubleBuffered ? GLUT_DOUBLE : 0));
  295.     (void)glutCreateWindow(name);
  296.     glutDisplayFunc(display);
  297.     glutReshapeFunc(reshape);
  298.     glutKeyboardFunc(key);
  299.     initialize();
  300.     glutMainLoop();
  301.     return 0;
  302. }