dissolve.c
上传用户:xk288cn
上传日期:2007-05-28
资源大小:4876k
文件大小:10k
- /*
- ** An Example of dissolve, using stencil
- */
- #include <math.h>
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <GL/glut.h>
- #ifdef _WIN32
- #define drand48() ((double)rand()/RAND_MAX)
- #endif
- int winWidth = 512;
- int winHeight = 512;
- /*
- ** 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 {SPHERE = 1, CONE};
- GLfloat angle = 0.f; /* angle of rotating object in layer 0 */
- enum {X, Y};
- GLboolean eraser = GL_FALSE;
- GLint layer = 1;
- GLint eraserpos[2] = {512/8, 512/12};
- /* draw eraser and erase what's underneath */
- GLubyte *eraserpix = 0;
- int erasersize = 0;
- int eraserWidth;
- int eraserHeight;
- void
- makeEraser(void)
- {
- int i;
- int x, y;
- int dx, dy;
- float d;
- eraserWidth = winWidth / 6;
- eraserHeight = winHeight / 6;
- erasersize = 4 * eraserWidth * eraserHeight;
- eraserpix = (GLubyte *)realloc(eraserpix, erasersize * sizeof(GLubyte));
-
- /* make it not erase */
- (void)memset(eraserpix, 0, erasersize * sizeof(GLubyte));
-
- i = 0;
- for(y = 0; y < eraserHeight; y++)
- for(x = 0; x < eraserWidth; x++)
- {
- dx = x - eraserWidth / 2;
- dy = y - eraserHeight / 2;
- d = sqrt(dx * dx + dy * dy);
- if(pow(drand48(), .75) * eraserWidth / 2 > d)
- {
- eraserpix[i + 0] = 255;
- eraserpix[i + 1] = 255;
- eraserpix[i + 2] = 255;
- eraserpix[i + 3] = 255;
- }
- i += 4;
- }
- }
- /* left button, first layer, middle button, second layer */
- /* ARGSUSED */
- void
- mouse(int button, int state, int x, int y)
- {
- if(state == GLUT_DOWN) {
- eraser = GL_TRUE;
- if(button == GLUT_LEFT_BUTTON)
- layer = 1;
- else /* GLUT_MIDDLE: GLUT_RIGHT is for menu */
- layer = 0;
- } else { /* GLUT_UP */
- eraser = GL_FALSE;
- }
- glutPostRedisplay();
- }
- enum {CLEAR}; /* menu choices */
- GLboolean clearstencil = GL_TRUE;
- void
- menu(int choice)
- {
- switch(choice) {
- case CLEAR:
- clearstencil = GL_TRUE;
- break;
- }
- glutPostRedisplay();
- }
- /* used to get current width and height of viewport */
- void
- reshape(int wid, int ht)
- {
- glViewport(0, 0, wid, ht);
- winWidth = wid;
- winHeight = ht;
- clearstencil = GL_TRUE;
- makeEraser();
- glutPostRedisplay();
- }
- void
- draweraser(void)
- {
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- gluOrtho2D(0, winWidth, 0, winHeight);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- /* replace with this layer */
- glStencilFunc(GL_ALWAYS, layer, 0);
- glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE);
- glDisable(GL_LIGHTING);
- glDisable(GL_DEPTH_TEST);
- glEnable(GL_ALPHA_TEST);
- glAlphaFunc(GL_NOTEQUAL, 0);
- glRasterPos2i(eraserpos[X], eraserpos[Y]);
- glBitmap(0, 0, 0.f, 0.f, -winWidth/8.f, -winHeight/12.f, 0);
- glDrawPixels(eraserWidth, eraserHeight, GL_RGBA, GL_UNSIGNED_BYTE, eraserpix);
- glDisable(GL_ALPHA_TEST);
- }
- void
- drawlayer2(void)
- {
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- gluOrtho2D(0, winWidth, 0, winHeight);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- glDisable(GL_LIGHTING);
- glDisable(GL_DEPTH_TEST);
- glEnable(GL_TEXTURE_2D);
- glBegin(GL_QUADS);
- glTexCoord2i(0, 0);
- glVertex2i(0, 0);
- glTexCoord2i(1, 0);
- glVertex2i(winWidth, 0);
- glTexCoord2i(1, 1);
- glVertex2i(winWidth, winHeight);
- glTexCoord2i(0, 1);
- glVertex2i(0, winHeight);
- glEnd();
- glDisable(GL_TEXTURE_2D);
- if(glGetError()) /* to catch programming errors; should never happen */
- printf("Oops! I screwed up my OpenGL calls somewheren");
- }
- void
- drawlayer1(void)
- {
- /* material properties for objects in scene */
- static GLfloat wall_mat[] = {1.f, 1.f, 1.f, 1.f};
- static GLfloat lightpos[] = {50.f, 50.f, -320.f, 1.f};
- /* draw a perspective scene */
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glFrustum(-100., 100., -100., 100., 320., 640.);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- /* 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);
- /*
- ** 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(glGetError()) /* to catch programming errors; should never happen */
- printf("Oops! I screwed up my OpenGL calls somewheren");
- }
- void
- drawlayer0(void)
- {
- static GLfloat lightpos[] = {50.f, 50.f, 0.f, 1.f};
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glOrtho(-50.f, 50.f, -50.f, 50.f, 0.f, 100.f);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- glTranslatef(0.f, 0.f, -50.f);
- glRotatef(angle, 0.f, 1.f, 0.f);
- glRotatef(90.f, 0.f, 0.f, 1.f);
- glTranslatef(0.f, -25.f, 0.f);
- glEnable(GL_LIGHTING);
- glEnable(GL_LIGHT0);
- glLightfv(GL_LIGHT0, GL_POSITION, lightpos);
- glCullFace(GL_BACK);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glCallList(CONE);
- }
- void
- redraw(void)
- {
- if(glutLayerGet(GLUT_NORMAL_DAMAGED) ||
- clearstencil == GL_TRUE) {
- glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
- clearstencil = GL_FALSE;
- } else
- glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
- glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
- glStencilFunc(GL_EQUAL, 2, (unsigned)~0);
- drawlayer2();
- glStencilFunc(GL_EQUAL, 1, (unsigned)~0);
- drawlayer1();
- glStencilFunc(GL_EQUAL, 0, (unsigned)~0);
- drawlayer0();
- if(eraser)
- draweraser();
- glutSwapBuffers();
- }
- void
- idle(void)
- {
- angle += 1.f;
- glutPostRedisplay();
- }
- void
- passive(int x, int y)
- {
- eraserpos[X] = x;
- eraserpos[Y] = winHeight - y;
- }
- void
- motion(int x, int y)
- {
- eraserpos[X] = x;
- eraserpos[Y] = winHeight - y;
- glutPostRedisplay();
- }
- /* ARGSUSED1 */
- void key(unsigned char key, int x, int y)
- {
- switch(key) {
- case ' 33':
- exit(0);
- }
- }
- const int TEXDIM = 256;
- GLfloat *tex = 0;
- main(int argc, char *argv[])
- {
- 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(winWidth, winHeight);
- glutInitDisplayMode(GLUT_DOUBLE|GLUT_STENCIL|GLUT_DEPTH);
- (void)glutCreateWindow("dissolve");
- glutDisplayFunc(redraw);
- glutMouseFunc(mouse);
- glutMotionFunc(motion);
- glutPassiveMotionFunc(passive);
- glutKeyboardFunc(key);
- glutIdleFunc(idle);
- glutReshapeFunc(reshape);
- glutCreateMenu(menu);
- glutAddMenuEntry("Clear Stencil", CLEAR);
- glutAttachMenu(GLUT_RIGHT_BUTTON);
- 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, 20.f, 20, 20);
- gluDeleteQuadric(sphere);
- glEndList();
- glNewList(CONE, GL_COMPILE);
- cone = gluNewQuadric();
- base = gluNewQuadric();
- 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., 20., 20, 1);
- gluCylinder(cone, 20., 0., 60., 20, 20);
- gluDeleteQuadric(cone);
- gluDeleteQuadric(base);
- glEndList();
- makeEraser();
- /* 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);
- glClearStencil(2);
- glEnable(GL_STENCIL_TEST); /* used all the time */
- glEnable(GL_CULL_FACE);
- glCullFace(GL_BACK);
- glutMainLoop();
- return 0;
- }