/* * This program is under the GNU GPL. * Use at your own risk. * * written by David Bucciarelli (tech.hmw@plus.it) * Humanware s.r.l. */ #include #include #include #include #include #ifdef WIN32 #include #endif #include #include "readtex.h" #ifdef XMESA #include "GL/xmesa.h" static int fullscreen=1; #endif static int WIDTH=640; static int HEIGHT=480; static GLint T0 = 0; static GLint Frames = 0; #define BASESIZE 10.0 #define BASERES 12 #define TEAPOTRES 3 #ifndef M_PI #define M_PI 3.1415926535 #endif extern void shadowmatrix(GLfloat [4][4], GLfloat [4], GLfloat [4]); extern void findplane(GLfloat [4], GLfloat [3], GLfloat [3], GLfloat [3]); static int win=0; static float obs[3]={5.0,0.0,1.0}; static float dir[3]; static float v=0.0; static float alpha=-90.0; static float beta=90.0; static GLfloat baseshadow[4][4]; static GLfloat lightpos[4]={2.3,0.0,3.0,1.0}; static GLfloat lightdir[3]={-2.3,0.0,-3.0}; static GLfloat lightalpha=0.0; static int fog=1; static int bfcull=1; static int usetex=1; static int help=1; static int joyavailable=0; static int joyactive=0; static GLuint t1id,t2id; static GLuint teapotdlist,basedlist,lightdlist; /******************** begin shadow code ********************/ /* Taken from the projshadow.c - by Tom McReynolds, SGI */ /* Modified by David Bucciarelli */ enum { X, Y, Z, W }; enum { A, B, C, D }; /* create a matrix that will project the desired shadow */ void shadowmatrix(GLfloat shadowMat[4][4], GLfloat groundplane[4], GLfloat lightpos[4]) { GLfloat dot; /* find dot product between light position vector and ground plane normal */ dot = groundplane[X] * lightpos[X] + groundplane[Y] * lightpos[Y] + groundplane[Z] * lightpos[Z] + groundplane[W] * lightpos[W]; shadowMat[0][0] = dot - lightpos[X] * groundplane[X]; shadowMat[1][0] = 0.f - lightpos[X] * groundplane[Y]; shadowMat[2][0] = 0.f - lightpos[X] * groundplane[Z]; shadowMat[3][0] = 0.f - lightpos[X] * groundplane[W]; shadowMat[X][1] = 0.f - lightpos[Y] * groundplane[X]; shadowMat[1][1] = dot - lightpos[Y] * groundplane[Y]; shadowMat[2][1] = 0.f - lightpos[Y] * groundplane[Z]; shadowMat[3][1] = 0.f - lightpos[Y] * groundplane[W]; shadowMat[X][2] = 0.f - lightpos[Z] * groundplane[X]; shadowMat[1][2] = 0.f - lightpos[Z] * groundplane[Y]; shadowMat[2][2] = dot - lightpos[Z] * groundplane[Z]; shadowMat[3][2] = 0.f - lightpos[Z] * groundplane[W]; shadowMat[X][3] = 0.f - lightpos[W] * groundplane[X]; shadowMat[1][3] = 0.f - lightpos[W] * groundplane[Y]; shadowMat[2][3] = 0.f - lightpos[W] * groundplane[Z]; shadowMat[3][3] = dot - lightpos[W] * groundplane[W]; } /* find the plane equation given 3 points */ void findplane(GLfloat plane[4], GLfloat v0[3], GLfloat v1[3], GLfloat v2[3]) { GLfloat vec0[3], vec1[3]; /* need 2 vectors to find cross product */ vec0[X] = v1[X] - v0[X]; vec0[Y] = v1[Y] - v0[Y]; vec0[Z] = v1[Z] - v0[Z]; vec1[X] = v2[X] - v0[X]; vec1[Y] = v2[Y] - v0[Y]; vec1[Z] = v2[Z] - v0[Z]; /* find cross product to get A, B, and C of plane equation */ plane[A] = vec0[Y] * vec1[Z] - vec0[Z] * vec1[Y]; plane[B] = -(vec0[X] * vec1[Z] - vec0[Z] * vec1[X]); plane[C] = vec0[X] * vec1[Y] - vec0[Y] * vec1[X]; plane[D] = -(plane[A] * v0[X] + plane[B] * v0[Y] + plane[C] * v0[Z]); } /******************** end shadow code ********************/ static void calcposobs(void) { dir[0]=sin(alpha*M_PI/180.0); dir[1]=cos(alpha*M_PI/180.0)*sin(beta*M_PI/180.0); dir[2]=cos(beta*M_PI/180.0); obs[0]+=v*dir[0]; obs[1]+=v*dir[1]; obs[2]+=v*dir[2]; } static void special(int k, int x, int y) { switch(k) { case GLUT_KEY_LEFT: alpha-=2.0; break; case GLUT_KEY_RIGHT: alpha+=2.0; break; case GLUT_KEY_DOWN: beta-=2.0; break; case GLUT_KEY_UP: beta+=2.0; break; } } static void key(unsigned char k, int x, int y) { switch(k) { case 27: exit(0); break; case 'a': v+=0.005; break; case 'z': v-=0.005; break; case 'j': joyactive=(!joyactive); break; case 'h': help=(!help); break; case 'f': fog=(!fog); break; case 't': usetex=(!usetex); break; case 'b': if(bfcull) { glDisable(GL_CULL_FACE); bfcull=0; } else { glEnable(GL_CULL_FACE); bfcull=1; } break; #ifdef XMESA case ' ': XMesaSetFXmode(fullscreen ? XMESA_FX_FULLSCREEN : XMESA_FX_WINDOW); fullscreen=(!fullscreen); break; #endif } } static void reshape(int w, int h) { WIDTH=w; HEIGHT=h; glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0,w/(float)h,0.2,40.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glViewport(0,0,w,h); } static void printstring(void *font, char *string) { int len,i; len=(int)strlen(string); for(i=0;ijoy.wXpos) min[0]=joy.wXpos; center[0]=(max[0]+min[0])/2; if(max[1]joy.wYpos) min[1]=joy.wYpos; center[1]=(max[1]+min[1])/2; if(joyactive) { if(fabs(center[0]-(float)joy.wXpos)>0.1*(max[0]-min[0])) alpha-=2.5*(center[0]-(float)joy.wXpos)/(max[0]-min[0]); if(fabs(center[1]-(float)joy.wYpos)>0.1*(max[1]-min[1])) beta+=2.5*(center[1]-(float)joy.wYpos)/(max[1]-min[1]); if(joy.wButtons & JOY_BUTTON1) v+=0.005; if(joy.wButtons & JOY_BUTTON2) v-=0.005; } } else joyavailable=0; #endif } static void draw(void) { static char frbuf[80] = ""; dojoy(); glEnable(GL_DEPTH_TEST); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); if(usetex) glEnable(GL_TEXTURE_2D); else glDisable(GL_TEXTURE_2D); if(fog) glEnable(GL_FOG); else glDisable(GL_FOG); glEnable(GL_LIGHTING); glShadeModel(GL_SMOOTH); glPushMatrix(); calcposobs(); gluLookAt(obs[0],obs[1],obs[2], obs[0]+dir[0],obs[1]+dir[1],obs[2]+dir[2], 0.0,0.0,1.0); drawlight1(); glCallList(basedlist); drawteapot(); drawlight2(); glPopMatrix(); glDisable(GL_LIGHTING); glDisable(GL_TEXTURE_2D); glDisable(GL_DEPTH_TEST); glDisable(GL_FOG); glShadeModel(GL_FLAT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-0.5,639.5,-0.5,479.5,-1.0,1.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glColor3f(1.0,0.0,0.0); glRasterPos2i(10,10); printstring(GLUT_BITMAP_HELVETICA_18,frbuf); glRasterPos2i(350,470); printstring(GLUT_BITMAP_HELVETICA_10,"Teapot V1.2 Written by David Bucciarelli (tech.hmw@plus.it)"); if(help) printhelp(); reshape(WIDTH,HEIGHT); glutSwapBuffers(); Frames++; { GLint t = glutGet(GLUT_ELAPSED_TIME); if (t - T0 >= 2000) { GLfloat seconds = (t - T0) / 1000.0; GLfloat fps = Frames / seconds; sprintf(frbuf, "Frame rate: %f", fps); T0 = t; Frames = 0; } } } static void inittextures(void) { glGenTextures(1,&t1id); glBindTexture(GL_TEXTURE_2D,t1id); glPixelStorei(GL_UNPACK_ALIGNMENT,4); if (!LoadRGBMipmaps("../images/tile.rgb", GL_RGB)) { fprintf(stderr,"Error reading a texture.\n"); exit(-1); } glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE); glGenTextures(1,&t2id); glBindTexture(GL_TEXTURE_2D,t2id); glPixelTransferf(GL_RED_SCALE, 0.75); glPixelTransferf(GL_RED_BIAS, 0.25); glPixelTransferf(GL_GREEN_SCALE, 0.75); glPixelTransferf(GL_GREEN_BIAS, 0.25); glPixelTransferf(GL_BLUE_SCALE, 0.75); glPixelTransferf(GL_BLUE_BIAS, 0.25); if (!LoadRGBMipmaps("../images/bw.rgb", GL_RGB)) { fprintf(stderr,"Error reading a texture.\n"); exit(-1); } glPixelTransferf(GL_RED_SCALE, 1.0); glPixelTransferf(GL_RED_BIAS, 0.0); glPixelTransferf(GL_GREEN_SCALE, 1.0); glPixelTransferf(GL_GREEN_BIAS, 0.0); glPixelTransferf(GL_BLUE_SCALE, 1.0); glPixelTransferf(GL_BLUE_BIAS, 0.0); glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE); } static void initlight(void) { float matamb[4] ={0.5, 0.5, 0.5, 1.0}; float matdiff[4]={0.9, 0.2, 0.2, 1.0}; float matspec[4]={1.0,1.0,1.0,1.0}; float lamb[4] ={1.5, 1.5, 1.5, 1.0}; float ldiff[4]={1.0, 1.0, 1.0, 1.0}; float lspec[4]={1.0, 1.0, 1.0, 1.0}; glLightf(GL_LIGHT0,GL_SPOT_CUTOFF,70.0); glLightf(GL_LIGHT0,GL_SPOT_EXPONENT,20.0); glLightfv(GL_LIGHT0,GL_AMBIENT,lamb); glLightfv(GL_LIGHT0,GL_DIFFUSE,ldiff); glLightfv(GL_LIGHT0,GL_SPECULAR,lspec); glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 15.0); glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, matdiff); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, matspec); glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, matamb); glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lamb); glEnable(GL_LIGHT0); } static void initdlists(void) { GLUquadricObj *lcone,*lbase; GLfloat plane[4]; GLfloat v0[3]={0.0,0.0,0.0}; GLfloat v1[3]={1.0,0.0,0.0}; GLfloat v2[3]={0.0,1.0,0.0}; findplane(plane,v0,v1,v2); shadowmatrix(baseshadow,plane,lightpos); teapotdlist=glGenLists(1); glNewList(teapotdlist,GL_COMPILE); glRotatef(90.0,1.0,0.0,0.0); glCullFace(GL_FRONT); glBindTexture(GL_TEXTURE_2D,t2id); glutSolidTeapot(0.75); glCullFace(GL_BACK); glEndList(); basedlist=glGenLists(1); glNewList(basedlist,GL_COMPILE); drawbase(); glEndList(); lightdlist=glGenLists(1); glNewList(lightdlist,GL_COMPILE); glDisable(GL_LIGHTING); lcone=gluNewQuadric(); lbase=gluNewQuadric(); glRotatef(45.0,0.0,1.0,0.0); glColor3f(1.0,1.0,1.0); glCullFace(GL_FRONT); gluDisk(lbase,0.0,0.2,12.0,1.0); glCullFace(GL_BACK); glColor3f(0.5,0.0,0.0); gluCylinder(lcone,0.2,0.0,0.5,12,1); gluDeleteQuadric(lcone); gluDeleteQuadric(lbase); glEnable(GL_LIGHTING); glEndList(); } int main(int ac, char **av) { float fogcolor[4]={0.025,0.025,0.025,1.0}; fprintf(stderr,"Teapot V1.2\nWritten by David Bucciarelli (tech.hmw@plus.it)\n"); /* if(!SetPriorityClass(GetCurrentProcess(),REALTIME_PRIORITY_CLASS)) { fprintf(stderr,"Error setting the process class.\n"); return 0; } if(!SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_TIME_CRITICAL)) { fprintf(stderr,"Error setting the process priority.\n"); return 0; } */ glutInitWindowPosition(0,0); glutInitWindowSize(WIDTH,HEIGHT); glutInit(&ac,av); glutInitDisplayMode(GLUT_RGB|GLUT_DEPTH|GLUT_DOUBLE); if(!(win=glutCreateWindow("Teapot"))) { fprintf(stderr,"Error, couldn't open window\n"); return -1; } reshape(WIDTH,HEIGHT); glShadeModel(GL_SMOOTH); glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); glEnable(GL_TEXTURE_2D); glEnable(GL_FOG); glFogi(GL_FOG_MODE,GL_EXP2); glFogfv(GL_FOG_COLOR,fogcolor); glFogf(GL_FOG_DENSITY,0.04); glHint(GL_FOG_HINT,GL_NICEST); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); calcposobs(); inittextures(); initlight(); initdlists(); glClearColor(fogcolor[0],fogcolor[1],fogcolor[2],fogcolor[3]); glutReshapeFunc(reshape); glutDisplayFunc(draw); glutKeyboardFunc(key); glutSpecialFunc(special); glutIdleFunc(draw); glutMainLoop(); return 0; }