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

GIS编程

开发平台:

Visual C++

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