123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590 |
- /*
- * Demo of a reflective, texture-mapped surface with OpenGL.
- * Brian Paul August 14, 1995 This file is in the public domain.
- *
- * Hardware texture mapping is highly recommended!
- *
- * The basic steps are:
- * 1. Render the reflective object (a polygon) from the normal viewpoint,
- * setting the stencil planes = 1.
- * 2. Render the scene from a special viewpoint: the viewpoint which
- * is on the opposite side of the reflective plane. Only draw where
- * stencil = 1. This draws the objects in the reflective surface.
- * 3. Render the scene from the original viewpoint. This draws the
- * objects in the normal fashion. Use blending when drawing
- * the reflective, textured surface.
- *
- * This is a very crude demo. It could be much better.
- */
-
- /*
- * Authors:
- * Brian Paul
- * Dirk Reiners (reiners@igd.fhg.de) made some modifications to this code.
- * Mark Kilgard (April 1997)
- * Brian Paul (April 2000 - added keyboard d/s options)
- * Brian Paul (August 2005 - added multi window feature)
- */
-
-
- #include <assert.h>
- #include <math.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include "GL/glut.h"
- #include "showbuffer.h"
- #include "readtex.h"
-
-
- #define DEG2RAD (3.14159/180.0)
- #define TABLE_TEXTURE "../images/tile.rgb"
- #define MAX_OBJECTS 2
- #define INIT_WIDTH 400
- #define INIT_HEIGHT 300
-
- #ifdef _WIN32
- #undef CreateWindowA
- #endif
-
- struct window {
- int id; /* returned by glutCreateWindow() */
- int width, height;
- GLboolean anim;
- GLfloat xrot, yrot;
- GLfloat spin;
- GLenum showBuffer;
- GLenum drawBuffer;
- GLuint table_list;
- GLuint objects_list[MAX_OBJECTS];
- double t0;
- struct window *next;
- };
-
-
- static struct window *FirstWindow = NULL;
-
-
- static void
- CreateWindow(void);
-
-
- static struct window *
- CurrentWindow(void)
- {
- int id = glutGetWindow();
- struct window *w;
- for (w = FirstWindow; w; w = w->next) {
- if (w->id == id)
- return w;
- }
- return NULL;
- }
-
-
- static GLboolean
- AnyAnimating(void)
- {
- struct window *w;
- for (w = FirstWindow; w; w = w->next) {
- if (w->anim)
- return 1;
- }
- return 0;
- }
-
-
- static void
- KillWindow(struct window *w)
- {
- struct window *win, *prev = NULL;
- for (win = FirstWindow; win; win = win->next) {
- if (win == w) {
- if (prev) {
- prev->next = win->next;
- }
- else {
- FirstWindow = win->next;
- }
- glutDestroyWindow(win->id);
- win->next = NULL;
- free(win);
- return;
- }
- prev = win;
- }
- }
-
-
- static void
- KillAllWindows(void)
- {
- while (FirstWindow)
- KillWindow(FirstWindow);
- }
-
-
- static GLuint
- MakeTable(void)
- {
- static GLfloat table_mat[] = { 1.0, 1.0, 1.0, 0.6 };
- static GLfloat gray[] = { 0.4, 0.4, 0.4, 1.0 };
- GLuint table_list;
-
- table_list = glGenLists(1);
- glNewList( table_list, GL_COMPILE );
-
- /* load table's texture */
- glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, table_mat );
- /*glMaterialfv( GL_FRONT, GL_EMISSION, gray );*/
- glMaterialfv( GL_FRONT, GL_DIFFUSE, table_mat );
- glMaterialfv( GL_FRONT, GL_AMBIENT, gray );
-
- /* draw textured square for the table */
- glPushMatrix();
- glScalef( 4.0, 4.0, 4.0 );
- glBegin( GL_POLYGON );
- glNormal3f( 0.0, 1.0, 0.0 );
- glTexCoord2f( 0.0, 0.0 ); glVertex3f( -1.0, 0.0, 1.0 );
- glTexCoord2f( 1.0, 0.0 ); glVertex3f( 1.0, 0.0, 1.0 );
- glTexCoord2f( 1.0, 1.0 ); glVertex3f( 1.0, 0.0, -1.0 );
- glTexCoord2f( 0.0, 1.0 ); glVertex3f( -1.0, 0.0, -1.0 );
- glEnd();
- glPopMatrix();
-
- glDisable( GL_TEXTURE_2D );
-
- glEndList();
- return table_list;
- }
-
-
- static void
- MakeObjects(GLuint *objects_list)
- {
- GLUquadricObj *q;
-
- static GLfloat cyan[] = { 0.0, 1.0, 1.0, 1.0 };
- static GLfloat green[] = { 0.2, 1.0, 0.2, 1.0 };
- static GLfloat black[] = { 0.0, 0.0, 0.0, 0.0 };
-
- q = gluNewQuadric();
- gluQuadricDrawStyle( q, GLU_FILL );
- gluQuadricNormals( q, GLU_SMOOTH );
-
- objects_list[0] = glGenLists(1);
- glNewList( objects_list[0], GL_COMPILE );
- glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, cyan );
- glMaterialfv( GL_FRONT, GL_EMISSION, black );
- gluCylinder( q, 0.5, 0.5, 1.0, 15, 1 );
- glEndList();
-
- objects_list[1] = glGenLists(1);
- glNewList( objects_list[1], GL_COMPILE );
- glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green );
- glMaterialfv( GL_FRONT, GL_EMISSION, black );
- gluCylinder( q, 1.5, 0.0, 2.5, 15, 1 );
- glEndList();
-
- gluDeleteQuadric(q);
- }
-
-
- static void
- InitWindow(struct window *w)
- {
- GLint imgWidth, imgHeight;
- GLenum imgFormat;
- GLubyte *image = NULL;
-
- w->table_list = MakeTable();
- MakeObjects(w->objects_list);
-
- image = LoadRGBImage( TABLE_TEXTURE, &imgWidth, &imgHeight, &imgFormat );
- if (!image) {
- printf("Couldn't read %s\n", TABLE_TEXTURE);
- exit(0);
- }
-
- gluBuild2DMipmaps(GL_TEXTURE_2D, 3, imgWidth, imgHeight,
- imgFormat, GL_UNSIGNED_BYTE, image);
- free(image);
-
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
-
- glShadeModel( GL_FLAT );
-
- glEnable( GL_LIGHT0 );
- glEnable( GL_LIGHTING );
-
- glClearColor( 0.5, 0.5, 0.9, 0.0 );
-
- glEnable( GL_NORMALIZE );
- }
-
-
- static void
- Reshape(int width, int height)
- {
- struct window *w = CurrentWindow();
- GLfloat yAspect = 2.5;
- GLfloat xAspect = yAspect * (float) width / (float) height;
- w->width = width;
- w->height = height;
- glViewport(0, 0, width, height);
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glFrustum( -xAspect, xAspect, -yAspect, yAspect, 10.0, 30.0 );
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- }
-
-
- static void
- DrawObjects(struct window *w, GLfloat eyex, GLfloat eyey, GLfloat eyez)
- {
- (void) eyex;
- (void) eyey;
- (void) eyez;
- #ifndef USE_ZBUFFER
- if (eyex<0.5) {
- #endif
- glPushMatrix();
- glTranslatef( 1.0, 1.5, 0.0 );
- glRotatef( w->spin, 1.0, 0.5, 0.0 );
- glRotatef( 0.5*w->spin, 0.0, 0.5, 1.0 );
- glCallList( w->objects_list[0] );
- glPopMatrix();
-
- glPushMatrix();
- glTranslatef( -1.0, 0.85+3.0*fabs( cos(0.01*w->spin) ), 0.0 );
- glRotatef( 0.5*w->spin, 0.0, 0.5, 1.0 );
- glRotatef( w->spin, 1.0, 0.5, 0.0 );
- glScalef( 0.5, 0.5, 0.5 );
- glCallList( w->objects_list[1] );
- glPopMatrix();
- #ifndef USE_ZBUFFER
- }
- else {
- glPushMatrix();
- glTranslatef( -1.0, 0.85+3.0*fabs( cos(0.01*w->spin) ), 0.0 );
- glRotatef( 0.5*w->spin, 0.0, 0.5, 1.0 );
- glRotatef( w->spin, 1.0, 0.5, 0.0 );
- glScalef( 0.5, 0.5, 0.5 );
- glCallList( w->objects_list[1] );
- glPopMatrix();
-
- glPushMatrix();
- glTranslatef( 1.0, 1.5, 0.0 );
- glRotatef( w->spin, 1.0, 0.5, 0.0 );
- glRotatef( 0.5*w->spin, 0.0, 0.5, 1.0 );
- glCallList( w->objects_list[0] );
- glPopMatrix();
- }
- #endif
- }
-
-
- static void
- DrawTable(struct window *w)
- {
- glCallList(w->table_list);
- }
-
-
- static void
- DrawWindow(void)
- {
- struct window *w = CurrentWindow();
- static GLfloat light_pos[] = { 0.0, 20.0, 0.0, 1.0 };
- GLfloat dist = 20.0;
- GLfloat eyex, eyey, eyez;
-
- if (w->drawBuffer == GL_NONE) {
- glDrawBuffer(GL_BACK);
- glReadBuffer(GL_BACK);
- }
- else {
- glDrawBuffer(w->drawBuffer);
- glReadBuffer(w->drawBuffer);
- }
-
- glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
-
- if (w->drawBuffer == GL_NONE) {
- glDrawBuffer(GL_NONE);
- }
-
- eyex = dist * cos(w->yrot * DEG2RAD) * cos(w->xrot * DEG2RAD);
- eyez = dist * sin(w->yrot * DEG2RAD) * cos(w->xrot * DEG2RAD);
- eyey = dist * sin(w->xrot * DEG2RAD);
-
- /* view from top */
- glPushMatrix();
- gluLookAt( eyex, eyey, eyez, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0 );
-
- glLightfv( GL_LIGHT0, GL_POSITION, light_pos );
-
- /* draw table into stencil planes */
- glDisable( GL_DEPTH_TEST );
- glEnable( GL_STENCIL_TEST );
- glStencilFunc( GL_ALWAYS, 1, 0xffffffff );
- glStencilOp( GL_REPLACE, GL_REPLACE, GL_REPLACE );
- glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
- DrawTable(w);
- glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
-
- glEnable( GL_DEPTH_TEST );
-
- /* render view from below (reflected viewport) */
- /* only draw where stencil==1 */
- if (eyey>0.0) {
- glPushMatrix();
-
- glStencilFunc( GL_EQUAL, 1, 0xffffffff ); /* draw if ==1 */
- glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
- glScalef( 1.0, -1.0, 1.0 );
-
- /* Reposition light in reflected space. */
- glLightfv(GL_LIGHT0, GL_POSITION, light_pos);
-
- DrawObjects(w, eyex, eyey, eyez);
- glPopMatrix();
-
- /* Restore light's original unreflected position. */
- glLightfv(GL_LIGHT0, GL_POSITION, light_pos);
- }
-
- glDisable( GL_STENCIL_TEST );
-
- glEnable( GL_BLEND );
- glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
-
- glEnable( GL_TEXTURE_2D );
- DrawTable(w);
- glDisable( GL_TEXTURE_2D );
- glDisable( GL_BLEND );
-
- /* view from top */
- glPushMatrix();
-
- DrawObjects(w, eyex, eyey, eyez);
-
- glPopMatrix();
-
- glPopMatrix();
-
- if (w->showBuffer == GL_DEPTH) {
- ShowDepthBuffer(w->width, w->height, 1.0, 0.0);
- }
- else if (w->showBuffer == GL_STENCIL) {
- ShowStencilBuffer(w->width, w->height, 255.0, 0.0);
- }
- else if (w->showBuffer == GL_ALPHA) {
- ShowAlphaBuffer(w->width, w->height);
- }
-
- if (w->drawBuffer == GL_FRONT)
- glFinish();
- else
- glutSwapBuffers();
-
- /* calc/show frame rate */
- {
- static GLint t0 = 0;
- static GLint frames = 0;
- GLint t = glutGet(GLUT_ELAPSED_TIME);
- frames++;
- if (t - t0 >= 5000) {
- GLfloat seconds = (t - t0) / 1000.0;
- GLfloat fps = frames / seconds;
- printf("%d frames in %g seconds = %g FPS\n", frames, seconds, fps);
- t0 = t;
- frames = 0;
- }
- }
- }
-
-
- static void
- Idle(void)
- {
- double t = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
- struct window *w;
- for (w = FirstWindow; w; w = w->next) {
- if (w->anim) {
- double dt;
- if (w->t0 < 0.0)
- w->t0 = t;
- dt = t - w->t0;
- w->t0 = t;
- w->spin += 60.0 * dt;
- w->yrot += 90.0 * dt;
- assert(w->id);
- glutSetWindow(w->id);
- glutPostRedisplay();
- }
- }
- }
-
-
- static void
- UpdateIdleFunc(void)
- {
- if (AnyAnimating())
- glutIdleFunc(Idle);
- else
- glutIdleFunc(NULL);
- }
-
- static void
- Key(unsigned char key, int x, int y)
- {
- struct window *w = CurrentWindow();
- (void) x;
- (void) y;
-
- switch (key) {
- case 'd':
- w->showBuffer = GL_DEPTH;
- glutPostRedisplay();
- break;
- case 's':
- w->showBuffer = GL_STENCIL;
- glutPostRedisplay();
- break;
- case 'a':
- w->showBuffer = GL_ALPHA;
- glutPostRedisplay();
- break;
- case 'c':
- w->showBuffer = GL_NONE;
- glutPostRedisplay();
- break;
- case 'f':
- if (w->drawBuffer == GL_FRONT)
- w->drawBuffer = GL_BACK;
- else
- w->drawBuffer = GL_FRONT;
- glutPostRedisplay();
- break;
- case '0':
- w->drawBuffer = GL_NONE;
- glutPostRedisplay();
- break;
- case ' ':
- w->anim = !w->anim;
- w->t0 = -1;
- UpdateIdleFunc();
- glutPostRedisplay();
- break;
- case 'n':
- CreateWindow();
- UpdateIdleFunc();
- break;
- case 'k':
- KillWindow(w);
- if (FirstWindow == NULL)
- exit(0);
- break;
- case 27:
- KillAllWindows();
- exit(0);
- break;
- default:
- ;
- }
- }
-
-
- static void
- SpecialKey(int key, int x, int y)
- {
- struct window *w = CurrentWindow();
- (void) x;
- (void) y;
- switch (key) {
- case GLUT_KEY_UP:
- w->xrot += 3.0;
- if (w->xrot > 85)
- w->xrot = 85;
- break;
- case GLUT_KEY_DOWN:
- w->xrot -= 3.0;
- if (w->xrot < 5)
- w->xrot = 5;
- break;
- case GLUT_KEY_LEFT:
- w->yrot += 3.0;
- break;
- case GLUT_KEY_RIGHT:
- w->yrot -= 3.0;
- break;
- }
- glutPostRedisplay();
- }
-
-
- static void
- CreateWindow(void)
- {
- char title[1000];
- struct window *w = (struct window *) calloc(1, sizeof(struct window));
-
- glutInitWindowSize(INIT_WIDTH, INIT_HEIGHT);
- w->id = glutCreateWindow("foo");
- sprintf(title, "reflect window %d", w->id);
- glutSetWindowTitle(title);
- assert(w->id);
- w->width = INIT_WIDTH;
- w->height = INIT_HEIGHT;
- w->anim = GL_TRUE;
- w->xrot = 30.0;
- w->yrot = 50.0;
- w->spin = 0.0;
- w->showBuffer = GL_NONE;
- w->drawBuffer = GL_BACK;
-
- InitWindow(w);
-
- glutReshapeFunc(Reshape);
- glutDisplayFunc(DrawWindow);
- glutKeyboardFunc(Key);
- glutSpecialFunc(SpecialKey);
-
- /* insert at head of list */
- w->next = FirstWindow;
- FirstWindow = w;
- }
-
-
- static void
- Usage(void)
- {
- printf("Keys:\n");
- printf(" a - show alpha buffer\n");
- printf(" d - show depth buffer\n");
- printf(" s - show stencil buffer\n");
- printf(" c - show color buffer\n");
- printf(" f - toggle rendering to front/back color buffer\n");
- printf(" n - create new window\n");
- printf(" k - kill window\n");
- printf(" SPACE - toggle animation\n");
- printf(" ARROWS - rotate scene\n");
- }
-
-
- int
- main(int argc, char *argv[])
- {
- glutInit(&argc, argv);
- glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH |
- GLUT_STENCIL | GLUT_ALPHA);
- CreateWindow();
- glutIdleFunc(Idle);
- Usage();
- glutMainLoop();
- return 0;
- }
|