/* ** Demonstrates a use of environment texture mapping for improved highlight ** shading. ** ** Press mouse button one to move the object, press mouse button two to ** move the light source. Pressing the key switches between using ** regular lighting or texture mapping for the specular highlights. The ** key will cycle through objects (sphere, cylinder, torus). Check ** out the event loop code below for other keys which do will things. ** Run single buffered (-sb) using two windows (-2w) to see the highlight ** texture maps as they are generated. ** ** TBD ** - improve accuracy of the highlight texture map ** - reduce or eliminate grazing angle artifacts ** - improve user interaction ** ** 1995 -- David G Yu ** ** cc -o envphong envphong.c -lGLU -lGL -lXext -lX11 -lm */ #include #include #include #include #include #ifdef _WIN32 #define sinf(x) ((float)sin((x))) #define cosf(x) ((float)cos((x))) #define sqrtf(x) ((float)sqrt(x)) #define floorf(x) ((float)floor(x)) #ifndef M_PI #define M_PI 3.14159265 #endif #define drand48() ((float)rand()/(float)RAND_MAX) #endif #ifdef GL_POLYGON_OFFSET_FILL #undef GL_POLYGON_OFFSET_EXT #define GL_POLYGON_OFFSET_EXT GL_POLYGON_OFFSET_FILL #endif int win, win2; int needsLightUpdate = GL_TRUE; int useLighting = GL_TRUE; int useSpecularTexture = GL_FALSE; int useTexture = GL_FALSE; int useHighRes = GL_FALSE; int usePattern = GL_FALSE; int moveLight = GL_FALSE; int moveObject = GL_FALSE; int drawObj = 0, maxObj = 2; int useSecondWindow = GL_FALSE; GLfloat lightRotX, lightRotY; GLfloat objectRotX, objectRotY; int curx, cury, width, height; void drawSphere(int numMajor, int numMinor, float radius) { double majorStep = (M_PI / numMajor); double minorStep = (2.0*M_PI / numMinor); int i, j; for (i=0; i 360) lightRotX -= 360; if (lightRotX < 0) lightRotX += 360; lightRotY += dy; if (lightRotY > 360) lightRotY -= 360; if (lightRotY < 0) lightRotY += 360; needsLightUpdate = GL_TRUE; } else if (moveObject) { objectRotX += dx; if (objectRotX > 360) objectRotX -= 360; if (objectRotX < 0) objectRotX += 360; objectRotY += dy; if (objectRotY > 360) objectRotY -= 360; if (objectRotY < 0) objectRotY += 360; } curx = x; cury = y; } glutPostRedisplay(); } void mouse(int button, int state, int x, int y) { if(state == GLUT_DOWN) { switch(button) { case GLUT_LEFT_BUTTON: moveObject = GL_TRUE; motion(curx = x, cury = y); break; case GLUT_MIDDLE_BUTTON: moveLight = GL_TRUE; motion(curx = x, cury = y); break; case GLUT_RIGHT_BUTTON: break; } } else if (state == GLUT_UP) { switch(button) { case GLUT_LEFT_BUTTON: moveObject = GL_FALSE; break; case GLUT_MIDDLE_BUTTON: moveLight = GL_FALSE; break; case GLUT_RIGHT_BUTTON: break; } } } void display(void) { if (useSpecularTexture && needsLightUpdate) { if (useSecondWindow) { glutSetWindow(win2); } setMaterial(MAT_GEN_SPECULAR_TEXTURE); if (useSecondWindow) { glutSetWindow(win); } needsLightUpdate = GL_FALSE; } redraw(); glFlush(); glutSwapBuffers(); checkErrors(); } void reshape(int w, int h) { glViewport(0, 0, width = w, height = h); } void key(unsigned char key, int x, int y) { switch(key) { case 'h': help(); break; case ' ': break; case 'l': useLighting = !useLighting; break; case 's': useSpecularTexture = !useSpecularTexture; needsLightUpdate = GL_TRUE; break; case 't': useTexture = !useTexture; break; case 'r': useHighRes = !useHighRes; break; case 'o': ++drawObj; if (drawObj > maxObj) drawObj = 0; break; case '\033': exit(EXIT_SUCCESS); } glutPostRedisplay(); } int main(int argc, char** argv) { int i; glutInit(&argc, argv); glutInitWindowSize(width = 300, height = 300); glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH|GLUT_DOUBLE); for (i=1; i