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

GIS编程

开发平台:

Visual C++

  1. /* hiddenline.c - by Tom McReynolds, SGI */
  2. /* Line Rendering: Hidden line techniques */
  3. #include <GL/glut.h>
  4. #include <stdlib.h>
  5. #include <stdio.h>
  6. /*
  7. ** Create a single component texture map
  8. */
  9. GLfloat *make_texture(int maxs, int maxt)
  10. {
  11.     int s, t;
  12.     static GLfloat *texture;
  13.     texture = (GLfloat *)malloc(maxs * maxt * sizeof(GLfloat));
  14.     for(t = 0; t < maxt; t++) {
  15.         for(s = 0; s < maxs; s++) {
  16.             texture[s + maxs * t] = ((s >> 4) & 0x1) ^ ((t >> 4) & 0x1);
  17.         }
  18.     }
  19.     return texture;
  20. }
  21. enum {FILL, WIRE, BACKFACE, FRONTLINES, DEPTH, STENCIL, FAT_STENCIL};
  22. int rendermode = FILL;
  23. void
  24. menu(int selection)
  25. {
  26.   rendermode = selection;
  27.   glutPostRedisplay();
  28. }
  29. /* geometry display list names */
  30. enum {SPHERE = 1, CONE, FLOOR, WALLS};
  31. void
  32. drawscene(void)
  33. {
  34.     glEnable(GL_TEXTURE_2D);
  35.     glCallList(FLOOR);
  36.     glDisable(GL_TEXTURE_2D);
  37.     glCallList(WALLS);
  38.     glPushMatrix();
  39.     glTranslatef(-40.f, -50.f, -400.f);
  40.     glCallList(SPHERE);
  41.     glPopMatrix();
  42.     glPushMatrix();
  43.     glTranslatef(20.f, -100.f, -420.f);
  44.     glCallList(CONE);
  45.     glPopMatrix();
  46. }
  47. /* do hidden line removal on an object in the scene */
  48. /* use display lists to represent objects */
  49. void
  50. hiddenlineobj(GLint dlist)
  51. {
  52.     GLboolean tex2d;
  53.     glGetBooleanv(GL_TEXTURE_2D, &tex2d);
  54.     if(tex2d)
  55.       glDisable(GL_TEXTURE_2D);
  56.     glDisable(GL_LIGHTING);
  57.     glColor3f(.7f, .7f, .7f);
  58.     glEnable(GL_STENCIL_TEST);
  59.     glStencilFunc(GL_ALWAYS, 0, 0); /* clear stencil for this object */
  60.     glCallList(dlist); /* draw filled object in depth buffer */
  61.     glEnable(GL_LIGHTING);
  62.     if(tex2d)
  63.       glEnable(GL_TEXTURE_2D);
  64.     glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); /* turn off color */
  65.     glDisable(GL_DEPTH_TEST); /* turn off depth */
  66.     glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  67.     glStencilFunc(GL_ALWAYS, 1, 1);
  68.     glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
  69.     glCallList(dlist); /* draw lines into stencil buffer */
  70.     glStencilFunc(GL_EQUAL, 1 , 1);
  71.     glEnable(GL_DEPTH_TEST);
  72.     glDepthFunc(GL_LEQUAL);
  73.     glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  74.     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
  75.     glCallList(dlist); /* use lines in stencil to stencil out solid pgons */
  76.     /* clean up state */
  77.     glDisable(GL_STENCIL_TEST);
  78.     glDepthFunc(GL_LESS);
  79. }
  80. void
  81. drawscenestencil(void)
  82. {
  83.     glEnable(GL_TEXTURE_2D);
  84.     hiddenlineobj(FLOOR);
  85.     glDisable(GL_TEXTURE_2D);
  86.     hiddenlineobj(WALLS);
  87.     glPushMatrix();
  88.     glTranslatef(-40.f, -50.f, -400.f);
  89.     hiddenlineobj(SPHERE);
  90.     glPopMatrix();
  91.     glPushMatrix();
  92.     glTranslatef(20.f, -100.f, -420.f);
  93.     hiddenlineobj(CONE);
  94.     glPopMatrix();
  95. }
  96. /* Called when window needs to be redrawn */
  97. void redraw(void)
  98. {
  99.   glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
  100.   switch(rendermode) {
  101.   case FILL:
  102.     drawscene();
  103.     break;
  104.   case WIRE: /* basic wireframe mode */
  105.     glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  106.     drawscene();
  107.     glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  108.     break;
  109.   case BACKFACE: /* use backface culling to clean things up */
  110.     glEnable(GL_CULL_FACE);
  111.     glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  112.     drawscene();
  113.     glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  114.     glDisable(GL_CULL_FACE);
  115.     break;
  116.   case FRONTLINES: /* use polygon mode line on front, fill on back */
  117.     glPolygonMode(GL_FRONT, GL_LINE);
  118.     drawscene();
  119.     glPolygonMode(GL_FRONT, GL_FILL);
  120.     break;
  121.   case DEPTH: /* use depth buffer to remove hidden lines */
  122.     glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
  123.     drawscene();
  124.     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
  125.     glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  126.     glDepthFunc(GL_LEQUAL);
  127.     drawscene();
  128.     glDepthFunc(GL_LESS);
  129.     glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  130.     break;
  131.   case STENCIL: /* use stencil to remove hidden lines */
  132.     glEnable(GL_CULL_FACE);
  133.     drawscenestencil();
  134.     glDisable(GL_CULL_FACE);
  135.     break;
  136.   case FAT_STENCIL: /* use stencil with fat lines to fix edges */
  137.     glLineWidth(2.f);
  138.     glEnable(GL_CULL_FACE);
  139.     drawscenestencil();
  140.     glDisable(GL_CULL_FACE);
  141.     glLineWidth(1.f);
  142.     break;
  143.   }
  144.     if(glGetError()) /* to catch programming errors; should never happen */
  145.        printf("Oops! I screwed up my OpenGL calls somewheren");
  146.     glFlush(); /* high end machines may need this */
  147. }
  148. /* ARGSUSED1 */
  149. void key(unsigned char key, int x, int y)
  150. {
  151.     if(key == '33')
  152.         exit(0);
  153. }
  154. const int TEXDIM = 256;
  155. /* Parse arguments, and set up interface between OpenGL and window system */
  156. int
  157. main(int argc, char *argv[])
  158. {
  159.     /* material properties for objects in scene */
  160.     static GLfloat wall_mat[] = {1.f, 1.f, 1.f, 1.f};
  161.     GLfloat *tex;
  162.     static GLfloat lightpos[] = {50.f, 50.f, -320.f, 1.f};
  163.     static GLfloat sphere_mat[] = {1.f, .5f, 0.f, 1.f};
  164.     static GLfloat cone_mat[] = {0.f, .5f, 1.f, 1.f};
  165.     GLUquadricObj *sphere, *cone, *base;
  166.     glutInit(&argc, argv);
  167.     glutInitWindowSize(512, 512);
  168.     glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH|GLUT_STENCIL);
  169.     (void)glutCreateWindow("hidden line removal survey");
  170.     glutDisplayFunc(redraw);
  171.     glutKeyboardFunc(key);
  172.     glutCreateMenu(menu);
  173.     glutAddMenuEntry("Solid Fill", FILL);
  174.     glutAddMenuEntry("Wireframe", WIRE);
  175.     glutAddMenuEntry("Backface Culling", BACKFACE);
  176.     glutAddMenuEntry("Frontface Lines", FRONTLINES);
  177.     glutAddMenuEntry("Depth Test", DEPTH);
  178.     glutAddMenuEntry("Stencil", STENCIL);
  179.     glutAddMenuEntry("Stencil: Fat Lines", FAT_STENCIL);
  180.     glutAttachMenu(GLUT_RIGHT_BUTTON);
  181.     /* draw a perspective scene */
  182.     glMatrixMode(GL_PROJECTION);
  183.     glFrustum(-100., 100., -100., 100., 320., 640.); 
  184.     glMatrixMode(GL_MODELVIEW);
  185.     /* turn on features */
  186.     glEnable(GL_DEPTH_TEST);
  187.     glEnable(GL_LIGHTING);
  188.     glEnable(GL_LIGHT0);
  189.     glClearColor(.7f, .7f, .7f, .7f);
  190.     glCullFace(GL_BACK);
  191.     /* place light 0 in the right place */
  192.     glLightfv(GL_LIGHT0, GL_POSITION, lightpos);
  193.     /* remove back faces to speed things up */
  194.     glCullFace(GL_BACK);
  195.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  196.     glNewList(SPHERE, GL_COMPILE);
  197.     /* make display lists for sphere and cone; for efficiency */
  198.     sphere = gluNewQuadric();
  199.     glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, sphere_mat);
  200.     gluSphere(sphere, 50.f, 20, 20);
  201.     gluDeleteQuadric(sphere);
  202.     glEndList();
  203.     glNewList(CONE, GL_COMPILE);
  204.     cone = gluNewQuadric();
  205.     base = gluNewQuadric();
  206.     glPushMatrix();
  207.     glRotatef(-90.f, 1.f, 0.f, 0.f);
  208.     glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, cone_mat);
  209.     gluQuadricOrientation(base, GLU_INSIDE);
  210.     gluDisk(base, 0., 40., 20, 1);
  211.     gluCylinder(cone, 40., 0., 120., 20, 20);
  212.     glPopMatrix();
  213.     gluDeleteQuadric(cone);
  214.     gluDeleteQuadric(base);
  215.     glEndList();
  216.     glNewList(FLOOR, GL_COMPILE);
  217.     /*
  218.     ** Note: wall verticies are ordered so they are all front facing
  219.     ** this lets me do back face culling to speed things up.
  220.     */
  221.  
  222.     glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, wall_mat);
  223.     /* floor */
  224.     /*
  225.     ** Since we want to turn texturing on for floor only, we have to
  226.     ** make floor a separate glBegin()/glEnd() sequence. You can't
  227.     ** turn texturing on and off between begin and end calls
  228.     */
  229.     glBegin(GL_QUADS);
  230.     glNormal3f(0.f, 1.f, 0.f);
  231.     glTexCoord2i(0, 0);
  232.     glVertex3f(-100.f, -100.f, -320.f);
  233.     glTexCoord2i(1, 0);
  234.     glVertex3f( 100.f, -100.f, -320.f);
  235.     glTexCoord2i(1, 1);
  236.     glVertex3f( 100.f, -100.f, -520.f);
  237.     glTexCoord2i(0, 1);
  238.     glVertex3f(-100.f, -100.f, -520.f);
  239.     glEnd();
  240.     glEndList();
  241.     /* walls */
  242.     glNewList(WALLS, GL_COMPILE);
  243.     glBegin(GL_QUADS);
  244.     /* left wall */
  245.     glNormal3f(1.f, 0.f, 0.f);
  246.     glVertex3f(-100.f, -100.f, -320.f);
  247.     glVertex3f(-100.f, -100.f, -520.f);
  248.     glVertex3f(-100.f,  100.f, -520.f);
  249.     glVertex3f(-100.f,  100.f, -320.f);
  250.     /* right wall */
  251.     glNormal3f(-1.f, 0.f, 0.f);
  252.     glVertex3f( 100.f, -100.f, -320.f);
  253.     glVertex3f( 100.f,  100.f, -320.f);
  254.     glVertex3f( 100.f,  100.f, -520.f);
  255.     glVertex3f( 100.f, -100.f, -520.f);
  256.     /* ceiling */
  257.     glNormal3f(0.f, -1.f, 0.f);
  258.     glVertex3f(-100.f,  100.f, -320.f);
  259.     glVertex3f(-100.f,  100.f, -520.f);
  260.     glVertex3f( 100.f,  100.f, -520.f);
  261.     glVertex3f( 100.f,  100.f, -320.f);
  262.     /* back wall */
  263.     glNormal3f(0.f, 0.f, 1.f);
  264.     glVertex3f(-100.f, -100.f, -520.f);
  265.     glVertex3f( 100.f, -100.f, -520.f);
  266.     glVertex3f( 100.f,  100.f, -520.f);
  267.     glVertex3f(-100.f,  100.f, -520.f);
  268.     glEnd();
  269.     glEndList();
  270.     /* load pattern for current 2d texture */
  271.     tex = make_texture(TEXDIM, TEXDIM);
  272.     glTexImage2D(GL_TEXTURE_2D, 0, 1, TEXDIM, TEXDIM, 0, GL_RED, GL_FLOAT, tex);
  273.     free(tex);
  274.     glutMainLoop();
  275.     return 0;             /* ANSI C requires main to return int. */
  276. }