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

GIS编程

开发平台:

Visual C++

  1. /*
  2. ** An Example of dissolve, using stencil
  3. */
  4. #include <math.h>
  5. #include <stdio.h>
  6. #include <string.h>
  7. #include <stdlib.h>
  8. #include <GL/glut.h>
  9. #ifdef _WIN32
  10. #define drand48() ((double)rand()/RAND_MAX)
  11. #endif
  12. int winWidth = 512;
  13. int winHeight = 512;
  14. /*
  15. ** Create a single component texture map
  16. */
  17. GLfloat *make_texture(int maxs, int maxt)
  18. {
  19.     int s, t;
  20.     static GLfloat *texture;
  21.     texture = (GLfloat *)malloc(maxs * maxt * sizeof(GLfloat));
  22.     for(t = 0; t < maxt; t++) {
  23. for(s = 0; s < maxs; s++) {
  24.     texture[s + maxs * t] = ((s >> 4) & 0x1) ^ ((t >> 4) & 0x1);
  25. }
  26.     }
  27.     return texture;
  28. }
  29. enum {SPHERE = 1, CONE};
  30. GLfloat angle = 0.f; /* angle of rotating object in  layer 0 */
  31. enum {X, Y};
  32. GLboolean eraser = GL_FALSE;
  33. GLint layer = 1;
  34. GLint eraserpos[2] = {512/8, 512/12};
  35. /* draw eraser and erase what's underneath */
  36. GLubyte *eraserpix = 0;
  37. int erasersize = 0;
  38. int eraserWidth;
  39. int eraserHeight;
  40. void
  41. makeEraser(void)
  42. {
  43.   int i;
  44.   int x, y;
  45.   int dx, dy;
  46.   float d;
  47.   eraserWidth = winWidth / 6;
  48.   eraserHeight = winHeight / 6;
  49.   erasersize = 4 * eraserWidth * eraserHeight;
  50.   eraserpix = (GLubyte *)realloc(eraserpix, erasersize * sizeof(GLubyte));
  51.  
  52.   /* make it not erase */
  53.   (void)memset(eraserpix, 0, erasersize * sizeof(GLubyte));
  54.   
  55.   i = 0;
  56.   for(y = 0; y < eraserHeight; y++)
  57.       for(x = 0; x < eraserWidth; x++)
  58.       {
  59.   dx = x - eraserWidth / 2;
  60.   dy = y - eraserHeight / 2;
  61.   d = sqrt(dx * dx + dy * dy);
  62.           if(pow(drand48(), .75) * eraserWidth / 2 > d)
  63.   {
  64.       eraserpix[i + 0] = 255;
  65.       eraserpix[i + 1] = 255;
  66.       eraserpix[i + 2] = 255;
  67.       eraserpix[i + 3] = 255;
  68.   }
  69.   i += 4;
  70.       }
  71. }
  72. /* left button, first layer, middle button, second layer */
  73. /* ARGSUSED */
  74. void
  75. mouse(int button, int state, int x, int y)
  76. {
  77.   if(state == GLUT_DOWN) {
  78.       eraser = GL_TRUE;
  79.       if(button == GLUT_LEFT_BUTTON)
  80. layer = 1;
  81.       else /* GLUT_MIDDLE: GLUT_RIGHT is for menu */
  82. layer = 0;
  83.   } else { /* GLUT_UP */
  84.     eraser = GL_FALSE;
  85.   }
  86.   glutPostRedisplay();
  87. }
  88. enum {CLEAR}; /* menu choices */
  89. GLboolean clearstencil = GL_TRUE;
  90. void
  91. menu(int choice)
  92. {
  93.   switch(choice) {
  94.   case CLEAR:
  95.     clearstencil = GL_TRUE;
  96.     break;
  97.   }
  98.   glutPostRedisplay();
  99. }
  100. /* used to get current width and height of viewport */
  101. void
  102. reshape(int wid, int ht)
  103. {
  104.   glViewport(0, 0, wid, ht);
  105.   winWidth = wid;
  106.   winHeight = ht;
  107.   clearstencil = GL_TRUE;
  108.   makeEraser();
  109.   glutPostRedisplay();
  110. }
  111. void
  112. draweraser(void)
  113. {
  114.   glMatrixMode(GL_PROJECTION);
  115.   glLoadIdentity();
  116.   gluOrtho2D(0, winWidth, 0, winHeight);
  117.   glMatrixMode(GL_MODELVIEW);
  118.   glLoadIdentity();
  119.   /* replace with this layer */
  120.   glStencilFunc(GL_ALWAYS, layer, 0);
  121.   glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE);
  122.   glDisable(GL_LIGHTING);
  123.   glDisable(GL_DEPTH_TEST);
  124.   glEnable(GL_ALPHA_TEST);
  125.   glAlphaFunc(GL_NOTEQUAL, 0);
  126.   glRasterPos2i(eraserpos[X], eraserpos[Y]);
  127.   glBitmap(0, 0, 0.f, 0.f, -winWidth/8.f, -winHeight/12.f, 0);
  128.   glDrawPixels(eraserWidth, eraserHeight, GL_RGBA, GL_UNSIGNED_BYTE, eraserpix);
  129.   glDisable(GL_ALPHA_TEST);
  130. }
  131. void
  132. drawlayer2(void)
  133. {
  134.   glMatrixMode(GL_PROJECTION);
  135.   glLoadIdentity();
  136.   gluOrtho2D(0, winWidth, 0, winHeight);
  137.   glMatrixMode(GL_MODELVIEW);
  138.   glLoadIdentity();
  139.   glDisable(GL_LIGHTING);
  140.   glDisable(GL_DEPTH_TEST);
  141.   glEnable(GL_TEXTURE_2D);
  142.   glBegin(GL_QUADS);
  143.   glTexCoord2i(0, 0);
  144.   glVertex2i(0, 0);
  145.   glTexCoord2i(1, 0);
  146.   glVertex2i(winWidth, 0);
  147.   glTexCoord2i(1, 1);
  148.   glVertex2i(winWidth, winHeight);
  149.   glTexCoord2i(0, 1);
  150.   glVertex2i(0, winHeight);
  151.   glEnd();
  152.   glDisable(GL_TEXTURE_2D);
  153.   if(glGetError()) /* to catch programming errors; should never happen */
  154.        printf("Oops! I screwed up my OpenGL calls somewheren");
  155. }
  156. void
  157. drawlayer1(void)
  158. {
  159.     /* material properties for objects in scene */
  160.     static GLfloat wall_mat[] = {1.f, 1.f, 1.f, 1.f};
  161.     static GLfloat lightpos[] = {50.f, 50.f, -320.f, 1.f};
  162.     /* draw a perspective scene */
  163.     glMatrixMode(GL_PROJECTION);
  164.     glLoadIdentity();
  165.     glFrustum(-100., 100., -100., 100., 320., 640.); 
  166.     glMatrixMode(GL_MODELVIEW);
  167.     glLoadIdentity();
  168.     /* turn on features */
  169.     glEnable(GL_DEPTH_TEST);
  170.     glEnable(GL_LIGHTING);
  171.     glEnable(GL_LIGHT0);
  172.     /* place light 0 in the right place */
  173.     glLightfv(GL_LIGHT0, GL_POSITION, lightpos);
  174.     /* remove back faces to speed things up */
  175.     glCullFace(GL_BACK);
  176.     /*
  177.     ** Note: wall verticies are ordered so they are all front facing
  178.     ** this lets me do back face culling to speed things up.
  179.     */
  180.  
  181.     glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, wall_mat);
  182.     /* floor */
  183.     /* make the floor textured */
  184.     glEnable(GL_TEXTURE_2D);
  185.     /*
  186.     ** Since we want to turn texturing on for floor only, we have to
  187.     ** make floor a separate glBegin()/glEnd() sequence. You can't
  188.     ** turn texturing on and off between begin and end calls
  189.     */
  190.     glBegin(GL_QUADS);
  191.     glNormal3f(0.f, 1.f, 0.f);
  192.     glTexCoord2i(0, 0);
  193.     glVertex3f(-100.f, -100.f, -320.f);
  194.     glTexCoord2i(1, 0);
  195.     glVertex3f( 100.f, -100.f, -320.f);
  196.     glTexCoord2i(1, 1);
  197.     glVertex3f( 100.f, -100.f, -520.f);
  198.     glTexCoord2i(0, 1);
  199.     glVertex3f(-100.f, -100.f, -520.f);
  200.     glEnd();
  201.     glDisable(GL_TEXTURE_2D);
  202.     /* walls */
  203.     glBegin(GL_QUADS);
  204.     /* left wall */
  205.     glNormal3f(1.f, 0.f, 0.f);
  206.     glVertex3f(-100.f, -100.f, -320.f);
  207.     glVertex3f(-100.f, -100.f, -520.f);
  208.     glVertex3f(-100.f,  100.f, -520.f);
  209.     glVertex3f(-100.f,  100.f, -320.f);
  210.     /* right wall */
  211.     glNormal3f(-1.f, 0.f, 0.f);
  212.     glVertex3f( 100.f, -100.f, -320.f);
  213.     glVertex3f( 100.f,  100.f, -320.f);
  214.     glVertex3f( 100.f,  100.f, -520.f);
  215.     glVertex3f( 100.f, -100.f, -520.f);
  216.     /* ceiling */
  217.     glNormal3f(0.f, -1.f, 0.f);
  218.     glVertex3f(-100.f,  100.f, -320.f);
  219.     glVertex3f(-100.f,  100.f, -520.f);
  220.     glVertex3f( 100.f,  100.f, -520.f);
  221.     glVertex3f( 100.f,  100.f, -320.f);
  222.     /* back wall */
  223.     glNormal3f(0.f, 0.f, 1.f);
  224.     glVertex3f(-100.f, -100.f, -520.f);
  225.     glVertex3f( 100.f, -100.f, -520.f);
  226.     glVertex3f( 100.f,  100.f, -520.f);
  227.     glVertex3f(-100.f,  100.f, -520.f);
  228.     glEnd();
  229.     glPushMatrix();
  230.     glTranslatef(-80.f, -80.f, -420.f);
  231.     glCallList(SPHERE);
  232.     glPopMatrix();
  233.     glPushMatrix();
  234.     glTranslatef(-20.f, -100.f, -500.f);
  235.     glCallList(CONE);
  236.     glPopMatrix();
  237.     if(glGetError()) /* to catch programming errors; should never happen */
  238.        printf("Oops! I screwed up my OpenGL calls somewheren");
  239. }
  240. void
  241. drawlayer0(void)
  242. {
  243.   static GLfloat lightpos[] = {50.f, 50.f, 0.f, 1.f};
  244.   glMatrixMode(GL_PROJECTION);
  245.   glLoadIdentity();
  246.   glOrtho(-50.f, 50.f, -50.f, 50.f, 0.f, 100.f);
  247.   glMatrixMode(GL_MODELVIEW);
  248.   glLoadIdentity();
  249.   glTranslatef(0.f, 0.f, -50.f);
  250.   glRotatef(angle, 0.f, 1.f, 0.f);
  251.   glRotatef(90.f, 0.f, 0.f, 1.f);
  252.   glTranslatef(0.f, -25.f, 0.f);
  253.   glEnable(GL_LIGHTING);
  254.   glEnable(GL_LIGHT0);
  255.   glLightfv(GL_LIGHT0, GL_POSITION, lightpos);
  256.   glCullFace(GL_BACK);
  257.   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  258.   glCallList(CONE);
  259. }
  260. void
  261. redraw(void)
  262. {
  263.   if(glutLayerGet(GLUT_NORMAL_DAMAGED) || 
  264.   clearstencil == GL_TRUE) {
  265.     glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
  266.     clearstencil = GL_FALSE;
  267.   } else
  268.     glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  269.   glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
  270.   glStencilFunc(GL_EQUAL, 2, (unsigned)~0);
  271.   drawlayer2();
  272.   glStencilFunc(GL_EQUAL, 1, (unsigned)~0);
  273.   drawlayer1();
  274.   glStencilFunc(GL_EQUAL, 0, (unsigned)~0);
  275.   drawlayer0();
  276.   if(eraser)
  277.     draweraser();
  278.   glutSwapBuffers();
  279. }
  280. void
  281. idle(void)
  282. {
  283.   angle += 1.f;
  284.   glutPostRedisplay();
  285. }
  286. void
  287. passive(int x, int y)
  288. {
  289.   eraserpos[X] = x;
  290.   eraserpos[Y] = winHeight - y;
  291. }
  292. void
  293. motion(int x, int y)
  294. {
  295.   eraserpos[X] = x;
  296.   eraserpos[Y] = winHeight - y;
  297.   glutPostRedisplay();
  298. }
  299. /* ARGSUSED1 */
  300. void key(unsigned char key, int x, int y)
  301. {
  302.   switch(key) {
  303.   case '33':
  304.     exit(0);
  305.   }
  306. }
  307. const int TEXDIM = 256;
  308. GLfloat *tex = 0;
  309. main(int argc, char *argv[])
  310. {
  311.     static GLfloat sphere_mat[] = {1.f, .5f, 0.f, 1.f};
  312.     static GLfloat cone_mat[] = {0.f, .5f, 1.f, 1.f};
  313.     GLUquadricObj *sphere, *cone, *base;
  314.     glutInit(&argc, argv);
  315.     glutInitWindowSize(winWidth, winHeight);
  316.     glutInitDisplayMode(GLUT_DOUBLE|GLUT_STENCIL|GLUT_DEPTH);
  317.     (void)glutCreateWindow("dissolve");
  318.     glutDisplayFunc(redraw);
  319.     glutMouseFunc(mouse);
  320.     glutMotionFunc(motion);
  321.     glutPassiveMotionFunc(passive);
  322.     glutKeyboardFunc(key);
  323.     glutIdleFunc(idle);
  324.     glutReshapeFunc(reshape);
  325.     glutCreateMenu(menu);
  326.     glutAddMenuEntry("Clear Stencil", CLEAR);
  327.     glutAttachMenu(GLUT_RIGHT_BUTTON);
  328.     glNewList(SPHERE, GL_COMPILE);
  329.     /* make display lists for sphere and cone; for efficiency */
  330.     sphere = gluNewQuadric();
  331.     glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, sphere_mat);
  332.     gluSphere(sphere, 20.f, 20, 20);
  333.     gluDeleteQuadric(sphere);
  334.     glEndList();
  335.     glNewList(CONE, GL_COMPILE);
  336.     cone = gluNewQuadric();
  337.     base = gluNewQuadric();
  338.     glRotatef(-90.f, 1.f, 0.f, 0.f);
  339.     glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, cone_mat);
  340.     gluQuadricOrientation(base, GLU_INSIDE);
  341.     gluDisk(base, 0., 20., 20, 1);
  342.     gluCylinder(cone, 20., 0., 60., 20, 20);
  343.     gluDeleteQuadric(cone);
  344.     gluDeleteQuadric(base);
  345.     glEndList();
  346.     makeEraser();
  347.     /* load pattern for current 2d texture */
  348.     tex = make_texture(TEXDIM, TEXDIM);
  349.     glTexImage2D(GL_TEXTURE_2D, 0, 1, TEXDIM, TEXDIM, 0, GL_RED, GL_FLOAT, tex);
  350.     free(tex);
  351.     glClearStencil(2);
  352.     glEnable(GL_STENCIL_TEST); /* used all the time */
  353.     glEnable(GL_CULL_FACE);
  354.     glCullFace(GL_BACK);
  355.     glutMainLoop();
  356.     return 0;
  357. }