hiddenline.c
上传用户:xk288cn
上传日期:2007-05-28
资源大小:4876k
文件大小:9k
- /* hiddenline.c - by Tom McReynolds, SGI */
- /* Line Rendering: Hidden line techniques */
- #include <GL/glut.h>
- #include <stdlib.h>
- #include <stdio.h>
- /*
- ** Create a single component texture map
- */
- GLfloat *make_texture(int maxs, int maxt)
- {
- int s, t;
- static GLfloat *texture;
- texture = (GLfloat *)malloc(maxs * maxt * sizeof(GLfloat));
- for(t = 0; t < maxt; t++) {
- for(s = 0; s < maxs; s++) {
- texture[s + maxs * t] = ((s >> 4) & 0x1) ^ ((t >> 4) & 0x1);
- }
- }
- return texture;
- }
- enum {FILL, WIRE, BACKFACE, FRONTLINES, DEPTH, STENCIL, FAT_STENCIL};
- int rendermode = FILL;
- void
- menu(int selection)
- {
- rendermode = selection;
- glutPostRedisplay();
- }
- /* geometry display list names */
- enum {SPHERE = 1, CONE, FLOOR, WALLS};
- void
- drawscene(void)
- {
- glEnable(GL_TEXTURE_2D);
- glCallList(FLOOR);
- glDisable(GL_TEXTURE_2D);
- glCallList(WALLS);
- glPushMatrix();
- glTranslatef(-40.f, -50.f, -400.f);
- glCallList(SPHERE);
- glPopMatrix();
- glPushMatrix();
- glTranslatef(20.f, -100.f, -420.f);
- glCallList(CONE);
- glPopMatrix();
- }
- /* do hidden line removal on an object in the scene */
- /* use display lists to represent objects */
- void
- hiddenlineobj(GLint dlist)
- {
- GLboolean tex2d;
- glGetBooleanv(GL_TEXTURE_2D, &tex2d);
- if(tex2d)
- glDisable(GL_TEXTURE_2D);
- glDisable(GL_LIGHTING);
- glColor3f(.7f, .7f, .7f);
- glEnable(GL_STENCIL_TEST);
- glStencilFunc(GL_ALWAYS, 0, 0); /* clear stencil for this object */
- glCallList(dlist); /* draw filled object in depth buffer */
- glEnable(GL_LIGHTING);
- if(tex2d)
- glEnable(GL_TEXTURE_2D);
- glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); /* turn off color */
- glDisable(GL_DEPTH_TEST); /* turn off depth */
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- glStencilFunc(GL_ALWAYS, 1, 1);
- glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
- glCallList(dlist); /* draw lines into stencil buffer */
- glStencilFunc(GL_EQUAL, 1 , 1);
- glEnable(GL_DEPTH_TEST);
- glDepthFunc(GL_LEQUAL);
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- glCallList(dlist); /* use lines in stencil to stencil out solid pgons */
- /* clean up state */
- glDisable(GL_STENCIL_TEST);
- glDepthFunc(GL_LESS);
- }
- void
- drawscenestencil(void)
- {
- glEnable(GL_TEXTURE_2D);
- hiddenlineobj(FLOOR);
- glDisable(GL_TEXTURE_2D);
- hiddenlineobj(WALLS);
- glPushMatrix();
- glTranslatef(-40.f, -50.f, -400.f);
- hiddenlineobj(SPHERE);
- glPopMatrix();
- glPushMatrix();
- glTranslatef(20.f, -100.f, -420.f);
- hiddenlineobj(CONE);
- glPopMatrix();
- }
- /* Called when window needs to be redrawn */
- void redraw(void)
- {
- glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
- switch(rendermode) {
- case FILL:
- drawscene();
- break;
- case WIRE: /* basic wireframe mode */
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- drawscene();
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- break;
- case BACKFACE: /* use backface culling to clean things up */
- glEnable(GL_CULL_FACE);
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- drawscene();
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- glDisable(GL_CULL_FACE);
- break;
- case FRONTLINES: /* use polygon mode line on front, fill on back */
- glPolygonMode(GL_FRONT, GL_LINE);
- drawscene();
- glPolygonMode(GL_FRONT, GL_FILL);
- break;
- case DEPTH: /* use depth buffer to remove hidden lines */
- glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
- drawscene();
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- glDepthFunc(GL_LEQUAL);
- drawscene();
- glDepthFunc(GL_LESS);
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- break;
- case STENCIL: /* use stencil to remove hidden lines */
- glEnable(GL_CULL_FACE);
- drawscenestencil();
- glDisable(GL_CULL_FACE);
- break;
- case FAT_STENCIL: /* use stencil with fat lines to fix edges */
- glLineWidth(2.f);
- glEnable(GL_CULL_FACE);
- drawscenestencil();
- glDisable(GL_CULL_FACE);
- glLineWidth(1.f);
- break;
- }
- if(glGetError()) /* to catch programming errors; should never happen */
- printf("Oops! I screwed up my OpenGL calls somewheren");
- glFlush(); /* high end machines may need this */
- }
- /* ARGSUSED1 */
- void key(unsigned char key, int x, int y)
- {
- if(key == ' 33')
- exit(0);
- }
- const int TEXDIM = 256;
- /* Parse arguments, and set up interface between OpenGL and window system */
- int
- main(int argc, char *argv[])
- {
- /* material properties for objects in scene */
- static GLfloat wall_mat[] = {1.f, 1.f, 1.f, 1.f};
- GLfloat *tex;
- static GLfloat lightpos[] = {50.f, 50.f, -320.f, 1.f};
- static GLfloat sphere_mat[] = {1.f, .5f, 0.f, 1.f};
- static GLfloat cone_mat[] = {0.f, .5f, 1.f, 1.f};
- GLUquadricObj *sphere, *cone, *base;
- glutInit(&argc, argv);
- glutInitWindowSize(512, 512);
- glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH|GLUT_STENCIL);
- (void)glutCreateWindow("hidden line removal survey");
- glutDisplayFunc(redraw);
- glutKeyboardFunc(key);
- glutCreateMenu(menu);
- glutAddMenuEntry("Solid Fill", FILL);
- glutAddMenuEntry("Wireframe", WIRE);
- glutAddMenuEntry("Backface Culling", BACKFACE);
- glutAddMenuEntry("Frontface Lines", FRONTLINES);
- glutAddMenuEntry("Depth Test", DEPTH);
- glutAddMenuEntry("Stencil", STENCIL);
- glutAddMenuEntry("Stencil: Fat Lines", FAT_STENCIL);
- glutAttachMenu(GLUT_RIGHT_BUTTON);
- /* draw a perspective scene */
- glMatrixMode(GL_PROJECTION);
- glFrustum(-100., 100., -100., 100., 320., 640.);
- glMatrixMode(GL_MODELVIEW);
- /* turn on features */
- glEnable(GL_DEPTH_TEST);
- glEnable(GL_LIGHTING);
- glEnable(GL_LIGHT0);
- glClearColor(.7f, .7f, .7f, .7f);
- glCullFace(GL_BACK);
- /* place light 0 in the right place */
- glLightfv(GL_LIGHT0, GL_POSITION, lightpos);
- /* remove back faces to speed things up */
- glCullFace(GL_BACK);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glNewList(SPHERE, GL_COMPILE);
- /* make display lists for sphere and cone; for efficiency */
- sphere = gluNewQuadric();
- glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, sphere_mat);
- gluSphere(sphere, 50.f, 20, 20);
- gluDeleteQuadric(sphere);
- glEndList();
- glNewList(CONE, GL_COMPILE);
- cone = gluNewQuadric();
- base = gluNewQuadric();
- glPushMatrix();
- glRotatef(-90.f, 1.f, 0.f, 0.f);
- glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, cone_mat);
- gluQuadricOrientation(base, GLU_INSIDE);
- gluDisk(base, 0., 40., 20, 1);
- gluCylinder(cone, 40., 0., 120., 20, 20);
- glPopMatrix();
- gluDeleteQuadric(cone);
- gluDeleteQuadric(base);
- glEndList();
- glNewList(FLOOR, GL_COMPILE);
- /*
- ** Note: wall verticies are ordered so they are all front facing
- ** this lets me do back face culling to speed things up.
- */
-
- glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, wall_mat);
- /* floor */
- /*
- ** Since we want to turn texturing on for floor only, we have to
- ** make floor a separate glBegin()/glEnd() sequence. You can't
- ** turn texturing on and off between begin and end calls
- */
- glBegin(GL_QUADS);
- glNormal3f(0.f, 1.f, 0.f);
- glTexCoord2i(0, 0);
- glVertex3f(-100.f, -100.f, -320.f);
- glTexCoord2i(1, 0);
- glVertex3f( 100.f, -100.f, -320.f);
- glTexCoord2i(1, 1);
- glVertex3f( 100.f, -100.f, -520.f);
- glTexCoord2i(0, 1);
- glVertex3f(-100.f, -100.f, -520.f);
- glEnd();
- glEndList();
- /* walls */
- glNewList(WALLS, GL_COMPILE);
- glBegin(GL_QUADS);
- /* left wall */
- glNormal3f(1.f, 0.f, 0.f);
- glVertex3f(-100.f, -100.f, -320.f);
- glVertex3f(-100.f, -100.f, -520.f);
- glVertex3f(-100.f, 100.f, -520.f);
- glVertex3f(-100.f, 100.f, -320.f);
- /* right wall */
- glNormal3f(-1.f, 0.f, 0.f);
- glVertex3f( 100.f, -100.f, -320.f);
- glVertex3f( 100.f, 100.f, -320.f);
- glVertex3f( 100.f, 100.f, -520.f);
- glVertex3f( 100.f, -100.f, -520.f);
- /* ceiling */
- glNormal3f(0.f, -1.f, 0.f);
- glVertex3f(-100.f, 100.f, -320.f);
- glVertex3f(-100.f, 100.f, -520.f);
- glVertex3f( 100.f, 100.f, -520.f);
- glVertex3f( 100.f, 100.f, -320.f);
- /* back wall */
- glNormal3f(0.f, 0.f, 1.f);
- glVertex3f(-100.f, -100.f, -520.f);
- glVertex3f( 100.f, -100.f, -520.f);
- glVertex3f( 100.f, 100.f, -520.f);
- glVertex3f(-100.f, 100.f, -520.f);
- glEnd();
- glEndList();
- /* load pattern for current 2d texture */
- tex = make_texture(TEXDIM, TEXDIM);
- glTexImage2D(GL_TEXTURE_2D, 0, 1, TEXDIM, TEXDIM, 0, GL_RED, GL_FLOAT, tex);
- free(tex);
- glutMainLoop();
- return 0; /* ANSI C requires main to return int. */
- }