zcomposite.c
上传用户:xk288cn
上传日期:2007-05-28
资源大小:4876k
文件大小:11k
- /* zcomposite.c - by Tom McReynolds, SGI */
- /* Compositing images that include depth information. */
- /* To use this program, you select a region of the "room" scene by
- rubber-banding the region with the left mouse button. Once a
- region is selected, position the region with the middle mouse
- button. The region will be composited using the region image and
- the region's depth information. With the right mouse button, you
- can shift the region's depth values nearer or further away. */
- #include <stdlib.h>
- #include <GL/glut.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;
- }
- GLboolean stencil = GL_TRUE;
- /* ARGSUSED1 */
- void
- key(unsigned char key, int x, int y)
- {
- switch (key) {
- case 't': /* toggle using stencil */
- if (stencil == GL_TRUE)
- stencil = GL_FALSE;
- else
- stencil = GL_TRUE;
- glutPostRedisplay();
- break;
- case ' 33':
- exit(0);
- break;
- }
- }
- enum {
- SPHERE = 1, CONE
- };
- enum {
- X, Y, Z
- };
- int startx, starty;
- int wid, ht;
- int oldwid = 0, oldht = 0;
- const int WINDIM = 512;
- const GLfloat FRUSTDIM = 110.f;
- const GLfloat FRUSTNEAR = 320.f;
- const GLfloat FRUSTFAR = 540.f;
- const GLfloat FRUSTDIFF = 540.f - 320.f;
- GLboolean drawmode = GL_FALSE;
- GLboolean depthmode = GL_FALSE;
- GLboolean rubberbandmode = GL_FALSE;
- GLfloat *color;
- GLfloat *depth;
- GLfloat depthbias = 0.f;
- GLfloat raspos[] =
- {0.f, 0.f, -430.f};
- int winWidth = 512;
- int winHeight = 512;
- GLfloat sx = 0;
- GLfloat sy = 0;
- /* Overlay Stuff */
- int transparent;
- int red;
- int overlaySupport = 0;
- void
- setRasterPosXY(int x, int y)
- {
- raspos[X] = (x - winWidth / 2) * sx;
- raspos[Y] = (y - winHeight / 2) * sy;
- glRasterPos3fv(raspos);
- glutPostRedisplay();
- }
- void
- setRasterPosZ(int y)
- {
- raspos[Z] = -(FRUSTNEAR + y * FRUSTDIFF / winHeight);
- depthbias = (y - winHeight / 2.f) / winHeight;
- glRasterPos3fv(raspos);
- glutPostRedisplay();
- }
- void
- motion(int x, int y)
- {
- y = winHeight - y;
- if (drawmode)
- setRasterPosXY(x, y);
- if (rubberbandmode) {
- wid = x - startx;
- ht = y - starty;
- if (overlaySupport) glutPostOverlayRedisplay();
- }
- if (depthmode)
- setRasterPosZ(y);
- }
- /* redraw function for overlay: used to show selected region */
- void
- overlay(void)
- {
- if (glutLayerGet(GLUT_OVERLAY_DAMAGED)) {
- glClear(GL_COLOR_BUFFER_BIT);
- } else {
- glIndexi(transparent);
- glBegin(GL_LINE_LOOP);
- glVertex2i(startx, starty);
- glVertex2i(startx + oldwid, starty);
- glVertex2i(startx + oldwid, starty + oldht);
- glVertex2i(startx, starty + oldht);
- glEnd();
- }
- glIndexi(red);
- glBegin(GL_LINE_LOOP);
- glVertex2i(startx, starty);
- glVertex2i(startx + wid, starty);
- glVertex2i(startx + wid, starty + ht);
- glVertex2i(startx, starty + ht);
- glEnd();
- oldwid = wid;
- oldht = ht;
- glFlush();
- }
- /* used to get current width and height of viewport */
- void
- reshape(int wid, int ht)
- {
- if (overlaySupport) {
- glutUseLayer(GLUT_OVERLAY);
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- gluOrtho2D(0, wid, 0, ht); /* 1 to 1 with window */
- glMatrixMode(GL_MODELVIEW);
- glViewport(0, 0, wid, ht);
- }
- glutUseLayer(GLUT_NORMAL);
- glViewport((GLint) (-wid * .1), (GLint) (-ht * .1),
- (GLuint) (wid * 1.2), (GLuint) (ht * 1.2));
- winWidth = wid;
- winHeight = ht;
- sx = 2 * FRUSTDIM / (winWidth * 1.2);
- sy = 2 * FRUSTDIM / (winHeight * 1.2);
- }
- void
- mouse(int button, int state, int x, int y)
- {
- y = winHeight - y; /* flip y orientation */
- if (state == GLUT_DOWN)
- switch (button) {
- case GLUT_LEFT_BUTTON: /* select an image */
- startx = x;
- starty = y;
- wid = 0;
- ht = 0;
- rubberbandmode = GL_TRUE;
- if (overlaySupport) glutShowOverlay();
- break;
- case GLUT_MIDDLE_BUTTON:
- glutUseLayer(GLUT_NORMAL);
- if (color && depth) {
- drawmode = GL_TRUE;
- setRasterPosXY(x, y);
- }
- break;
- case GLUT_RIGHT_BUTTON: /* change depth */
- glutUseLayer(GLUT_NORMAL);
- if (color && depth) {
- depthmode = GL_TRUE;
- setRasterPosZ(y);
- }
- break;
- } else /* GLUT_UP */
- switch (button) {
- case GLUT_LEFT_BUTTON:
- rubberbandmode = GL_FALSE;
- if (overlaySupport) glutHideOverlay();
- wid = x - startx;
- ht = y - starty;
- if (wid < 0) {
- wid = -wid;
- startx = x;
- }
- if (ht < 0) {
- ht = -ht;
- starty = y;
- }
- color = (GLfloat *) realloc(color, wid * ht * 3 * sizeof(GLfloat));
- depth = (GLfloat *) realloc(depth, wid * ht * sizeof(GLfloat));
- glutUseLayer(GLUT_NORMAL);
- glReadPixels(startx, starty, wid, ht, GL_RGB, GL_FLOAT, color);
- glReadPixels(startx, starty, wid, ht, GL_DEPTH_COMPONENT, GL_FLOAT,
- depth);
- break;
- case GLUT_MIDDLE_BUTTON:
- drawmode = GL_FALSE;
- break;
- case GLUT_RIGHT_BUTTON: /* change depth */
- depthmode = GL_FALSE;
- break;
- }
- }
- /* Called when window needs to be redrawn */
- void
- redraw(void)
- {
- /* material properties for objects in scene */
- static GLfloat wall_mat[] =
- {1.f, 1.f, 1.f, 1.f};
- glutUseLayer(GLUT_NORMAL);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
- /* 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 */
- /* make the floor textured */
- glEnable(GL_TEXTURE_2D);
- /* 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();
- glDisable(GL_TEXTURE_2D);
- /* walls */
- 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();
- glPushMatrix();
- glTranslatef(-80.f, -80.f, -420.f);
- glCallList(SPHERE);
- glPopMatrix();
- glPushMatrix();
- glTranslatef(-20.f, -100.f, -500.f);
- glCallList(CONE);
- glPopMatrix();
- if (stencil) {
- glEnable(GL_STENCIL_TEST);
- glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
- glStencilFunc(GL_ALWAYS, 1, 1);
- glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
- glPixelTransferf(GL_DEPTH_BIAS, depthbias);
- glDrawPixels(wid, ht, GL_DEPTH_COMPONENT, GL_FLOAT, depth);
- glPixelTransferf(GL_DEPTH_BIAS, 0.f);
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- glStencilFunc(GL_EQUAL, 1, 1);
- glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
- glDisable(GL_DEPTH_TEST);
- glDrawPixels(wid, ht, GL_RGB, GL_FLOAT, color);
- glEnable(GL_DEPTH_TEST);
- glDisable(GL_STENCIL_TEST);
- } else
- glDrawPixels(wid, ht, GL_RGB, GL_FLOAT, color);
- glutSwapBuffers();
- }
- const int TEXDIM = 256;
- /* Parse arguments, and set up interface between OpenGL and window system */
- int
- main(int argc, char *argv[])
- {
- 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 *obj;
- glutInit(&argc, argv);
- glutInitWindowSize(WINDIM, WINDIM);
- glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL | GLUT_DOUBLE);
- (void) glutCreateWindow("compositing images with depth");
- glutDisplayFunc(redraw);
- glutKeyboardFunc(key);
- glutMouseFunc(mouse);
- glutMotionFunc(motion);
- glutReshapeFunc(reshape);
- /* draw a perspective scene */
- glMatrixMode(GL_PROJECTION);
- glFrustum(-FRUSTDIM, FRUSTDIM, -FRUSTDIM, FRUSTDIM, FRUSTNEAR, FRUSTFAR);
- glMatrixMode(GL_MODELVIEW);
- /* turn on features */
- glEnable(GL_DEPTH_TEST);
- glEnable(GL_LIGHTING);
- glEnable(GL_LIGHT0);
- /* 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 */
- obj = gluNewQuadric();
- glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, sphere_mat);
- gluSphere(obj, 20.f, 20, 20);
- glEndList();
- glNewList(CONE, GL_COMPILE);
- glRotatef(-90.f, 1.f, 0.f, 0.f);
- glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, cone_mat);
- gluQuadricOrientation(obj, GLU_INSIDE);
- gluDisk(obj, 0., 20., 20, 1);
- gluQuadricOrientation(obj, GLU_OUTSIDE);
- gluCylinder(obj, 20., 0., 60., 20, 20);
- glEndList();
- gluDeleteQuadric(obj);
- /* 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);
- /* storage for saved image */
- color = 0;
- depth = 0;
- glReadBuffer(GL_FRONT); /* so glReadPixel() always get the right image */
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- glPixelStorei(GL_PACK_ALIGNMENT, 1);
- glutInitDisplayMode(GLUT_SINGLE | GLUT_INDEX);
- if (glutLayerGet(GLUT_OVERLAY_POSSIBLE)) {
- glutEstablishOverlay();
- glutHideOverlay();
- transparent = glutLayerGet(GLUT_TRANSPARENT_INDEX);
- glClearIndex(transparent);
- red = (transparent + 1) % glutGet(GLUT_WINDOW_COLORMAP_SIZE);
- glutSetColor(red, 1.0, 0.0, 0.0); /* Red. */
- glutOverlayDisplayFunc(overlay);
- overlaySupport = 1;
- } else {
- printf("Running without overlay rubber banding support.n");
- }
- glutMainLoop();
- return 0; /* ANSI C requires main to return int. */
- }