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

GIS编程

开发平台:

Visual C++

  1. /* convolve.c - by Tom McReynolds, SGI */
  2. /* Using the accumulation buffer for fast convolutions. */
  3. #include <GL/glut.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. /* convolution choices */
  8. enum {CONV_NONE, 
  9.       CONV_BOX_3X3,
  10.       CONV_BOX_5X5,
  11.       CONV_SOBEL_X,
  12.       CONV_LAPLACE
  13. };
  14. /* Filter contents and size */
  15. typedef struct {
  16.   GLfloat scale; /* 1/scale applied to image to prevent overflow */
  17.   GLfloat bias; /* for biasing images */
  18.   int rows;
  19.   int cols;
  20.   GLfloat *array;
  21. } Filter;
  22. Filter *curmat; /* current filter to use for redrawing */
  23. /* identity filter */
  24. void
  25. identity(Filter *mat)
  26. {
  27.   int n, size;
  28.   size = mat->rows * mat->cols;
  29.   mat->array[0] = 1.f;
  30.   for(n = 1; n < size; n++)
  31.     mat->array[n] = 0.f;
  32.   mat->scale = 1.f;
  33.   mat->bias = 0.f;
  34. }
  35. /* create a new filter with identity filter in it */
  36. Filter *
  37. newfilter(int rows, int cols)
  38. {
  39.   Filter *mat;
  40.   mat = (Filter *)malloc(sizeof(Filter));
  41.   mat->rows = rows;
  42.   mat->cols = cols;
  43.   mat->array = (GLfloat *)malloc(rows * cols * sizeof(GLfloat));
  44.   identity(mat);
  45.   
  46.   return mat;
  47. }
  48. /* doesn't re-initialize matrix */
  49. void
  50. resize(Filter *mat, int rows, int cols)
  51. {
  52.   if(mat->rows != rows ||
  53.      mat->cols != cols) {
  54.     free(mat->array);
  55.     mat->array = NULL;
  56.     mat->array = (GLfloat *)realloc(mat->array, rows * cols * sizeof(GLfloat));
  57.   }
  58.   mat->rows = rows;
  59.   mat->cols = cols;
  60. }
  61. /* box filter blur */
  62. void
  63. box(Filter *mat)
  64. {
  65.   int n, count;
  66.   GLfloat blur;
  67.   count = mat->cols * mat->rows;
  68.   blur = 1.f/count;
  69.   for(n = 0; n < count; n++)
  70.      mat->array[n] = blur;
  71.   mat->scale = 1.f;
  72.   mat->bias = 0.f;
  73. }
  74. /* sobel filter */
  75. void
  76. sobel(Filter *mat)
  77. {
  78.   static GLfloat sobel[] = {-.5f, 0.f, .5f,
  79.                             -1.f, 0.f, 1.f,
  80.                             -.5f, 0.f, .5f};
  81.   /* sobel is fixed size */
  82.   resize(mat, 3, 3); /* will do nothing if size is right already */
  83.   
  84.   memcpy(mat->array, sobel, sizeof(sobel));
  85.   mat->scale = 2.f;
  86.   mat->bias = 0.f;
  87. }
  88. /* laplacian filter */
  89. void
  90. laplace(Filter *mat)
  91. {
  92.   static GLfloat laplace[] = {  0.f, -.25f,   0.f,
  93.                               -.25f,   1.f, -.25f,
  94.                                 0.f, -.25f,   0.f};
  95.   /* sobel is fixed size */
  96.   resize(mat, 3, 3); /* will do nothing if size is right already */
  97.   
  98.   memcpy(mat->array, laplace, sizeof(laplace));
  99.   mat->scale = 4.f;
  100.   mat->bias = .125f;
  101. }
  102. /* add menu callback */
  103. void menu(int filter)
  104. {
  105.   switch(filter) {
  106.     case CONV_NONE:
  107.       resize(curmat, 1,1);
  108.       identity(curmat);
  109.       break;
  110.     case CONV_BOX_3X3:
  111.       resize(curmat, 3, 3);
  112.       box(curmat);
  113.       break;
  114.     case CONV_BOX_5X5:
  115.       resize(curmat, 5, 5);
  116.       box(curmat);
  117.       break;
  118.     case CONV_SOBEL_X:
  119.       sobel(curmat);
  120.       break;
  121.     case CONV_LAPLACE:
  122.       laplace(curmat);
  123.       break;
  124.   }
  125.   glutPostRedisplay();
  126. }
  127. int winWidth = 0;
  128. int winHeight = 0;
  129. /* used to get current width and height of viewport */
  130. void
  131. reshape(int wid, int ht)
  132. {
  133.   glViewport(0, 0, wid, ht);
  134.   winWidth = wid;
  135.   winHeight = ht;
  136. }
  137. /* ARGSUSED1 */
  138. void key(unsigned char key, int x, int y)
  139. {
  140.     if(key == '33')
  141.         exit(0);
  142. }
  143. /*
  144. ** Create a single component texture map
  145. */
  146. GLfloat *make_texture(int maxs, int maxt)
  147. {
  148.     int s, t;
  149.     static GLfloat *texture;
  150.     texture = (GLfloat *)malloc(maxs * maxt * sizeof(GLfloat));
  151.     for(t = 0; t < maxt; t++) {
  152.         for(s = 0; s < maxs; s++) {
  153.             texture[s + maxs * t] = ((s >> 4) & 0x1) ^ ((t >> 4) & 0x1);
  154.         }
  155.     }
  156.     return texture;
  157. }
  158. enum {SPHERE = 1, CONE};
  159. void
  160. render(void)
  161. {
  162.     /* material properties for objects in scene */
  163.     static GLfloat wall_mat[] = {1.f, 1.f, 1.f, 1.f};
  164.     glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);
  165.     /*
  166.     ** Note: wall verticies are ordered so they are all front facing
  167.     ** this lets me do back face culling to speed things up.
  168.     */
  169.  
  170.     glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, wall_mat);
  171.     /* floor */
  172.     /* make the floor textured */
  173.     glEnable(GL_TEXTURE_2D);
  174.     /*
  175.     ** Since we want to turn texturing on for floor only, we have to
  176.     ** make floor a separate glBegin()/glEnd() sequence. You can't
  177.     ** turn texturing on and off between begin and end calls
  178.     */
  179.     glBegin(GL_QUADS);
  180.     glNormal3f(0.f, 1.f, 0.f);
  181.     glTexCoord2i(0, 0);
  182.     glVertex3f(-100.f, -100.f, -320.f);
  183.     glTexCoord2i(1, 0);
  184.     glVertex3f( 100.f, -100.f, -320.f);
  185.     glTexCoord2i(1, 1);
  186.     glVertex3f( 100.f, -100.f, -520.f);
  187.     glTexCoord2i(0, 1);
  188.     glVertex3f(-100.f, -100.f, -520.f);
  189.     glEnd();
  190.     glDisable(GL_TEXTURE_2D);
  191.     /* walls */
  192.     glBegin(GL_QUADS);
  193.     /* left wall */
  194.     glNormal3f(1.f, 0.f, 0.f);
  195.     glVertex3f(-100.f, -100.f, -320.f);
  196.     glVertex3f(-100.f, -100.f, -520.f);
  197.     glVertex3f(-100.f,  100.f, -520.f);
  198.     glVertex3f(-100.f,  100.f, -320.f);
  199.     /* right wall */
  200.     glNormal3f(-1.f, 0.f, 0.f);
  201.     glVertex3f( 100.f, -100.f, -320.f);
  202.     glVertex3f( 100.f,  100.f, -320.f);
  203.     glVertex3f( 100.f,  100.f, -520.f);
  204.     glVertex3f( 100.f, -100.f, -520.f);
  205.     /* ceiling */
  206.     glNormal3f(0.f, -1.f, 0.f);
  207.     glVertex3f(-100.f,  100.f, -320.f);
  208.     glVertex3f(-100.f,  100.f, -520.f);
  209.     glVertex3f( 100.f,  100.f, -520.f);
  210.     glVertex3f( 100.f,  100.f, -320.f);
  211.     /* back wall */
  212.     glNormal3f(0.f, 0.f, 1.f);
  213.     glVertex3f(-100.f, -100.f, -520.f);
  214.     glVertex3f( 100.f, -100.f, -520.f);
  215.     glVertex3f( 100.f,  100.f, -520.f);
  216.     glVertex3f(-100.f,  100.f, -520.f);
  217.     glEnd();
  218.     glPushMatrix();
  219.     glTranslatef(-80.f, -60.f, -420.f);
  220.     glCallList(SPHERE);
  221.     glPopMatrix();
  222.     glPushMatrix();
  223.     glTranslatef(-20.f, -80.f, -500.f);
  224.     glCallList(CONE);
  225.     glPopMatrix();
  226. }
  227. void
  228. convolve(void (*draw)(void), Filter *mat)
  229. {
  230.   int i, j;
  231.   int imax, jmax;
  232.   imax = mat->cols;
  233.   jmax = mat->rows;
  234.   for(j = 0; j < jmax; j++) {
  235.       for(i = 0; i < imax; i++) {
  236.         glViewport(-i, -j, winWidth - i, winHeight - j);
  237.         draw();
  238.         glAccum(GL_ACCUM, mat->array[i + j * imax]);
  239.       }
  240.   }
  241. }
  242. /* Called when window needs to be redrawn */
  243. void redraw(void)
  244. {
  245.     glClearAccum(curmat->bias,
  246.                  curmat->bias,
  247.                  curmat->bias,
  248.                  1.0);
  249.     glClear(GL_ACCUM_BUFFER_BIT);
  250.     convolve(render, curmat);
  251.     glViewport(0, 0, winWidth, winHeight);
  252.     glAccum(GL_RETURN, curmat->scale);
  253.     glutSwapBuffers();
  254.     if(glGetError()) /* to catch programming errors; should never happen */
  255.        printf("Oops! I screwed up my OpenGL calls somewheren");
  256. }
  257. const int TEXDIM = 256;
  258. int
  259. main(int argc, char *argv[])
  260. {
  261.     GLfloat *tex;
  262.     static GLfloat lightpos[] = {50.f, 50.f, -320.f, 1.f};
  263.     static GLfloat sphere_mat[] = {1.f, .5f, 0.f, 1.f};
  264.     static GLfloat cone_mat[] = {0.f, .5f, 1.f, 1.f};
  265.     GLUquadricObj *sphere, *cone, *base;
  266.     glutInit(&argc, argv);
  267.     glutInitWindowSize(512, 512);
  268.     glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH|GLUT_ACCUM|GLUT_DOUBLE);
  269.     (void)glutCreateWindow("accumulation buffer convolve");
  270.     glutDisplayFunc(redraw);
  271.     glutKeyboardFunc(key);
  272.     glutReshapeFunc(reshape);
  273.     /* draw a perspective scene */
  274.     glMatrixMode(GL_PROJECTION);
  275.     glFrustum(-100., 100., -100., 100., 320., 640.); 
  276.     glMatrixMode(GL_MODELVIEW);
  277.     /* turn on features */
  278.     glEnable(GL_DEPTH_TEST);
  279.     glEnable(GL_LIGHTING);
  280.     glEnable(GL_LIGHT0);
  281.     /* place light 0 in the right place */
  282.     glLightfv(GL_LIGHT0, GL_POSITION, lightpos);
  283.     /* remove back faces to speed things up */
  284.     glCullFace(GL_BACK);
  285.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  286.     /* make display lists for sphere and cone; for efficiency */
  287.     glNewList(SPHERE, GL_COMPILE);
  288.     sphere = gluNewQuadric();
  289.     glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, sphere_mat);
  290.     gluSphere(sphere, 20.f, 20, 20);
  291.     gluDeleteQuadric(sphere);
  292.     glEndList();
  293.     glNewList(CONE, GL_COMPILE);
  294.     cone = gluNewQuadric();
  295.     base = gluNewQuadric();
  296.     glRotatef(-90.f, 1.f, 0.f, 0.f);
  297.     glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, cone_mat);
  298.     gluDisk(base, 0., 20., 20, 1);
  299.     gluCylinder(cone, 20., 0., 60., 20, 20);
  300.     gluDeleteQuadric(cone);
  301.     gluDeleteQuadric(base);
  302.     glEndList();
  303.     glutCreateMenu(menu);
  304.     glutAddMenuEntry("none", CONV_NONE);
  305.     glutAddMenuEntry("box filter (3x3 blur)", CONV_BOX_3X3);
  306.     glutAddMenuEntry("box filter (5x5 blur)", CONV_BOX_5X5);
  307.     glutAddMenuEntry("Sobel(x direction)", CONV_SOBEL_X);
  308.     glutAddMenuEntry("Laplace", CONV_LAPLACE);
  309.     glutAttachMenu(GLUT_RIGHT_BUTTON);
  310.     /* load pattern for current 2d texture */
  311.     tex = make_texture(TEXDIM, TEXDIM);
  312.     glTexImage2D(GL_TEXTURE_2D, 0, 1, TEXDIM, TEXDIM, 0, GL_RED, GL_FLOAT, tex);
  313.     free(tex);
  314.     curmat = newfilter(1, 1);
  315.     identity(curmat);
  316.     glutMainLoop();
  317.     return 0;             /* ANSI C requires main to return int. */
  318. }