1/* 2 * This program is under the GNU GPL. 3 * Use at your own risk. 4 * 5 * written by David Bucciarelli (tech.hmw@plus.it) 6 * Humanware s.r.l. 7 */ 8 9#include <stdio.h> 10#include <stdlib.h> 11#include <math.h> 12#include <time.h> 13#include <string.h> 14 15#ifdef WIN32 16#include <windows.h> 17#endif 18 19#include "glut_wrap.h" 20#include "readtex.h" 21 22#ifdef XMESA 23#include "GL/xmesa.h" 24static int fullscreen=1; 25#endif 26 27static int WIDTH=640; 28static int HEIGHT=480; 29 30static GLint T0 = 0; 31static GLint Frames = 0; 32 33#define BASESIZE 10.0 34 35#define BASERES 12 36#define TEAPOTRES 3 37 38#ifndef M_PI 39#define M_PI 3.1415926535 40#endif 41 42extern void shadowmatrix(GLfloat [4][4], GLfloat [4], GLfloat [4]); 43extern void findplane(GLfloat [4], GLfloat [3], GLfloat [3], GLfloat [3]); 44 45 46static int win=0; 47 48static float obs[3]={5.0,0.0,1.0}; 49static float dir[3]; 50static float v=0.0; 51static float alpha=-90.0; 52static float beta=90.0; 53 54static GLfloat baseshadow[4][4]; 55static GLfloat lightpos[4]={2.3,0.0,3.0,1.0}; 56static GLfloat lightdir[3]={-2.3,0.0,-3.0}; 57static GLfloat lightalpha=0.0; 58 59static int fog=1; 60static int bfcull=1; 61static int usetex=1; 62static int help=1; 63static int joyavailable=0; 64static int joyactive=0; 65 66static GLuint t1id,t2id; 67static GLuint teapotdlist,basedlist,lightdlist; 68 69 70 71/******************** begin shadow code ********************/ 72 73/* Taken from the projshadow.c - by Tom McReynolds, SGI */ 74 75/* Modified by David Bucciarelli */ 76 77enum { 78 X, Y, Z, W 79}; 80enum { 81 A, B, C, D 82}; 83 84/* create a matrix that will project the desired shadow */ 85void 86shadowmatrix(GLfloat shadowMat[4][4], 87 GLfloat groundplane[4], 88 GLfloat lightpos[4]) 89{ 90 GLfloat dot; 91 92 /* find dot product between light position vector and ground plane normal */ 93 dot = groundplane[X] * lightpos[X] + 94 groundplane[Y] * lightpos[Y] + 95 groundplane[Z] * lightpos[Z] + 96 groundplane[W] * lightpos[W]; 97 98 shadowMat[0][0] = dot - lightpos[X] * groundplane[X]; 99 shadowMat[1][0] = 0.f - lightpos[X] * groundplane[Y]; 100 shadowMat[2][0] = 0.f - lightpos[X] * groundplane[Z]; 101 shadowMat[3][0] = 0.f - lightpos[X] * groundplane[W]; 102 103 shadowMat[X][1] = 0.f - lightpos[Y] * groundplane[X]; 104 shadowMat[1][1] = dot - lightpos[Y] * groundplane[Y]; 105 shadowMat[2][1] = 0.f - lightpos[Y] * groundplane[Z]; 106 shadowMat[3][1] = 0.f - lightpos[Y] * groundplane[W]; 107 108 shadowMat[X][2] = 0.f - lightpos[Z] * groundplane[X]; 109 shadowMat[1][2] = 0.f - lightpos[Z] * groundplane[Y]; 110 shadowMat[2][2] = dot - lightpos[Z] * groundplane[Z]; 111 shadowMat[3][2] = 0.f - lightpos[Z] * groundplane[W]; 112 113 shadowMat[X][3] = 0.f - lightpos[W] * groundplane[X]; 114 shadowMat[1][3] = 0.f - lightpos[W] * groundplane[Y]; 115 shadowMat[2][3] = 0.f - lightpos[W] * groundplane[Z]; 116 shadowMat[3][3] = dot - lightpos[W] * groundplane[W]; 117 118} 119 120/* find the plane equation given 3 points */ 121void 122findplane(GLfloat plane[4], 123 GLfloat v0[3], GLfloat v1[3], GLfloat v2[3]) 124{ 125 GLfloat vec0[3], vec1[3]; 126 127 /* need 2 vectors to find cross product */ 128 vec0[X] = v1[X] - v0[X]; 129 vec0[Y] = v1[Y] - v0[Y]; 130 vec0[Z] = v1[Z] - v0[Z]; 131 132 vec1[X] = v2[X] - v0[X]; 133 vec1[Y] = v2[Y] - v0[Y]; 134 vec1[Z] = v2[Z] - v0[Z]; 135 136 /* find cross product to get A, B, and C of plane equation */ 137 plane[A] = vec0[Y] * vec1[Z] - vec0[Z] * vec1[Y]; 138 plane[B] = -(vec0[X] * vec1[Z] - vec0[Z] * vec1[X]); 139 plane[C] = vec0[X] * vec1[Y] - vec0[Y] * vec1[X]; 140 141 plane[D] = -(plane[A] * v0[X] + plane[B] * v0[Y] + plane[C] * v0[Z]); 142} 143 144/******************** end shadow code ********************/ 145 146 147static void calcposobs(void) 148{ 149 dir[0]=sin(alpha*M_PI/180.0); 150 dir[1]=cos(alpha*M_PI/180.0)*sin(beta*M_PI/180.0); 151 dir[2]=cos(beta*M_PI/180.0); 152 153 obs[0]+=v*dir[0]; 154 obs[1]+=v*dir[1]; 155 obs[2]+=v*dir[2]; 156} 157 158static void special(int k, int x, int y) 159{ 160 switch(k) { 161 case GLUT_KEY_LEFT: 162 alpha-=2.0; 163 break; 164 case GLUT_KEY_RIGHT: 165 alpha+=2.0; 166 break; 167 case GLUT_KEY_DOWN: 168 beta-=2.0; 169 break; 170 case GLUT_KEY_UP: 171 beta+=2.0; 172 break; 173 } 174} 175 176static void cleanup(void) 177{ 178 glDeleteTextures(1, &t1id); 179 glDeleteTextures(1, &t2id); 180 glDeleteLists(teapotdlist, 1); 181 glDeleteLists(basedlist, 1); 182 glDeleteLists(lightdlist, 1); 183} 184 185static void key(unsigned char k, int x, int y) 186{ 187 switch(k) { 188 case 27: 189 cleanup(); 190 exit(0); 191 break; 192 193 case 'a': 194 v+=0.005; 195 break; 196 case 'z': 197 v-=0.005; 198 break; 199 200 case 'j': 201 joyactive=(!joyactive); 202 break; 203 case 'h': 204 help=(!help); 205 break; 206 case 'f': 207 fog=(!fog); 208 break; 209 case 't': 210 usetex=(!usetex); 211 break; 212 case 'b': 213 if(bfcull) { 214 glDisable(GL_CULL_FACE); 215 bfcull=0; 216 } else { 217 glEnable(GL_CULL_FACE); 218 bfcull=1; 219 } 220 break; 221#ifdef XMESA 222 case ' ': 223 XMesaSetFXmode(fullscreen ? XMESA_FX_FULLSCREEN : XMESA_FX_WINDOW); 224 fullscreen=(!fullscreen); 225 break; 226#endif 227 } 228} 229 230static void reshape(int w, int h) 231{ 232 WIDTH=w; 233 HEIGHT=h; 234 glMatrixMode(GL_PROJECTION); 235 glLoadIdentity(); 236 gluPerspective(45.0,w/(float)h,0.2,40.0); 237 glMatrixMode(GL_MODELVIEW); 238 glLoadIdentity(); 239 glViewport(0,0,w,h); 240} 241 242static void printstring(void *font, char *string) 243{ 244 int len,i; 245 246 len=(int)strlen(string); 247 for(i=0;i<len;i++) 248 glutBitmapCharacter(font,string[i]); 249} 250 251static void printhelp(void) 252{ 253 glEnable(GL_BLEND); 254 glColor4f(0.5,0.5,0.5,0.5); 255 glRecti(40,40,600,440); 256 glDisable(GL_BLEND); 257 258 glColor3f(1.0,0.0,0.0); 259 glRasterPos2i(300,420); 260 printstring(GLUT_BITMAP_TIMES_ROMAN_24,"Help"); 261 262 glRasterPos2i(60,390); 263 printstring(GLUT_BITMAP_TIMES_ROMAN_24,"h - Toggle Help"); 264 glRasterPos2i(60,360); 265 printstring(GLUT_BITMAP_TIMES_ROMAN_24,"t - Toggle Textures"); 266 glRasterPos2i(60,330); 267 printstring(GLUT_BITMAP_TIMES_ROMAN_24,"f - Toggle Fog"); 268 glRasterPos2i(60,300); 269 printstring(GLUT_BITMAP_TIMES_ROMAN_24,"b - Toggle Back face culling"); 270 glRasterPos2i(60,270); 271 printstring(GLUT_BITMAP_TIMES_ROMAN_24,"Arrow Keys - Rotate"); 272 glRasterPos2i(60,240); 273 printstring(GLUT_BITMAP_TIMES_ROMAN_24,"a - Increase velocity"); 274 glRasterPos2i(60,210); 275 printstring(GLUT_BITMAP_TIMES_ROMAN_24,"z - Decrease velocity"); 276 277 glRasterPos2i(60,180); 278 if(joyavailable) 279 printstring(GLUT_BITMAP_TIMES_ROMAN_24,"j - Toggle jostick control (Joystick control available)"); 280 else 281 printstring(GLUT_BITMAP_TIMES_ROMAN_24,"(No Joystick control available)"); 282} 283 284static void drawbase(void) 285{ 286 static const GLfloat amb[4] = { 1, .5, 0.2, 1 }; 287 static const GLfloat diff[4] = { 1, .4, 0.2, 1 }; 288 int i,j; 289 float x,y,dx,dy; 290 291 glBindTexture(GL_TEXTURE_2D,t1id); 292 293 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, amb); 294 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diff); 295 dx=BASESIZE/BASERES; 296 dy=-BASESIZE/BASERES; 297 for(y=BASESIZE/2.0,j=0;j<BASERES;y+=dy,j++) { 298 glBegin(GL_QUAD_STRIP); 299 glColor3f(1.0,1.0,1.0); 300 glNormal3f(0.0,0.0,1.0); 301 for(x=-BASESIZE/2.0,i=0;i<BASERES;x+=dx,i++) { 302 glTexCoord2f(x,y); 303 glVertex3f(x,y,0.0); 304 305 glTexCoord2f(x,y+dy); 306 glVertex3f(x,y+dy,0.0); 307 } 308 glEnd(); 309 } 310} 311 312static void drawteapot(void) 313{ 314 static const GLfloat amb[4] = { 0.2, 0.2, 0.2, 1 }; 315 static const GLfloat diff[4] = { 0.8, 0.3, 0.5, 1 }; 316 static float xrot=0.0; 317 static float zrot=0.0; 318 319 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, amb); 320 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diff); 321 322 glPushMatrix(); 323 glRotatef(lightalpha,0.0,0.0,1.0); 324 glMultMatrixf((GLfloat *)baseshadow); 325 glRotatef(-lightalpha,0.0,0.0,1.0); 326 327 glTranslatef(0.0,0.0,1.0); 328 glRotatef(xrot,1.0,0.0,0.0); 329 glRotatef(zrot,0.0,0.0,1.0); 330 331 glDisable(GL_TEXTURE_2D); 332 glDisable(GL_DEPTH_TEST); 333 glDisable(GL_LIGHTING); 334 335 glColor3f(0.0,0.0,0.0); 336 glCallList(teapotdlist); 337 338 glEnable(GL_DEPTH_TEST); 339 glEnable(GL_LIGHTING); 340 if(usetex) 341 glEnable(GL_TEXTURE_2D); 342 343 glPopMatrix(); 344 345 glPushMatrix(); 346 glTranslatef(0.0,0.0,1.0); 347 glRotatef(xrot,1.0,0.0,0.0); 348 glRotatef(zrot,0.0,0.0,1.0); 349 350 glCallList(teapotdlist); 351 glPopMatrix(); 352 353 xrot+=2.0; 354 zrot+=1.0; 355} 356 357static void drawlight1(void) 358{ 359 glPushMatrix(); 360 glRotatef(lightalpha,0.0,0.0,1.0); 361 glLightfv(GL_LIGHT0,GL_POSITION,lightpos); 362 glLightfv(GL_LIGHT0,GL_SPOT_DIRECTION,lightdir); 363 364 glPopMatrix(); 365} 366 367static void drawlight2(void) 368{ 369 glPushMatrix(); 370 glRotatef(lightalpha,0.0,0.0,1.0); 371 glTranslatef(lightpos[0],lightpos[1],lightpos[2]); 372 373 glDisable(GL_TEXTURE_2D); 374 glCallList(lightdlist); 375 if(usetex) 376 glEnable(GL_TEXTURE_2D); 377 378 glPopMatrix(); 379 380 lightalpha+=1.0; 381} 382 383static void dojoy(void) 384{ 385#ifdef WIN32 386 static UINT max[2]={0,0}; 387 static UINT min[2]={0xffffffff,0xffffffff},center[2]; 388 MMRESULT res; 389 JOYINFO joy; 390 391 res=joyGetPos(JOYSTICKID1,&joy); 392 393 if(res==JOYERR_NOERROR) { 394 joyavailable=1; 395 396 if(max[0]<joy.wXpos) 397 max[0]=joy.wXpos; 398 if(min[0]>joy.wXpos) 399 min[0]=joy.wXpos; 400 center[0]=(max[0]+min[0])/2; 401 402 if(max[1]<joy.wYpos) 403 max[1]=joy.wYpos; 404 if(min[1]>joy.wYpos) 405 min[1]=joy.wYpos; 406 center[1]=(max[1]+min[1])/2; 407 408 if(joyactive) { 409 if(fabs(center[0]-(float)joy.wXpos)>0.1*(max[0]-min[0])) 410 alpha-=2.5*(center[0]-(float)joy.wXpos)/(max[0]-min[0]); 411 if(fabs(center[1]-(float)joy.wYpos)>0.1*(max[1]-min[1])) 412 beta+=2.5*(center[1]-(float)joy.wYpos)/(max[1]-min[1]); 413 414 if(joy.wButtons & JOY_BUTTON1) 415 v+=0.005; 416 if(joy.wButtons & JOY_BUTTON2) 417 v-=0.005; 418 } 419 } else 420 joyavailable=0; 421#endif 422} 423 424static void draw(void) 425{ 426 static char frbuf[80] = ""; 427 428 dojoy(); 429 430 glEnable(GL_DEPTH_TEST); 431 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); 432 433 if(usetex) 434 glEnable(GL_TEXTURE_2D); 435 else 436 glDisable(GL_TEXTURE_2D); 437 438 if(fog) 439 glEnable(GL_FOG); 440 else 441 glDisable(GL_FOG); 442 443 glEnable(GL_LIGHTING); 444 445 glShadeModel(GL_SMOOTH); 446 447 glPushMatrix(); 448 calcposobs(); 449 450 gluLookAt(obs[0],obs[1],obs[2], 451 obs[0]+dir[0],obs[1]+dir[1],obs[2]+dir[2], 452 0.0,0.0,1.0); 453 454 drawlight1(); 455 glCallList(basedlist); 456 drawteapot(); 457 drawlight2(); 458 glPopMatrix(); 459 460 glDisable(GL_LIGHTING); 461 glDisable(GL_TEXTURE_2D); 462 glDisable(GL_DEPTH_TEST); 463 glDisable(GL_FOG); 464 glShadeModel(GL_FLAT); 465 466 glMatrixMode(GL_PROJECTION); 467 glLoadIdentity(); 468 glOrtho(-0.5,639.5,-0.5,479.5,-1.0,1.0); 469 glMatrixMode(GL_MODELVIEW); 470 glLoadIdentity(); 471 472 glColor3f(1.0,0.0,0.0); 473 glRasterPos2i(10,10); 474 printstring(GLUT_BITMAP_HELVETICA_18,frbuf); 475 glRasterPos2i(350,470); 476 printstring(GLUT_BITMAP_HELVETICA_10,"Teapot V1.2 Written by David Bucciarelli (tech.hmw@plus.it)"); 477 478 if(help) 479 printhelp(); 480 481 reshape(WIDTH,HEIGHT); 482 483 glutSwapBuffers(); 484 485 Frames++; 486 487 { 488 GLint t = glutGet(GLUT_ELAPSED_TIME); 489 if (t - T0 >= 2000) { 490 GLfloat seconds = (t - T0) / 1000.0; 491 GLfloat fps = Frames / seconds; 492 sprintf(frbuf, "Frame rate: %f", fps); 493 printf("%s\n", frbuf); 494 fflush(stdout); 495 T0 = t; 496 Frames = 0; 497 } 498 } 499} 500 501static void inittextures(void) 502{ 503 glGenTextures(1,&t1id); 504 glBindTexture(GL_TEXTURE_2D,t1id); 505 506 glPixelStorei(GL_UNPACK_ALIGNMENT,4); 507 if (!LoadRGBMipmaps(DEMOS_DATA_DIR "tile.rgb", GL_RGB)) { 508 fprintf(stderr,"Error reading a texture.\n"); 509 exit(-1); 510 } 511 512 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); 513 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); 514 515 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); 516 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); 517 518 glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE); 519 520 glGenTextures(1,&t2id); 521 glBindTexture(GL_TEXTURE_2D,t2id); 522 523 glPixelTransferf(GL_RED_SCALE, 0.75); 524 glPixelTransferf(GL_RED_BIAS, 0.25); 525 glPixelTransferf(GL_GREEN_SCALE, 0.75); 526 glPixelTransferf(GL_GREEN_BIAS, 0.25); 527 glPixelTransferf(GL_BLUE_SCALE, 0.75); 528 glPixelTransferf(GL_BLUE_BIAS, 0.25); 529 530 if (!LoadRGBMipmaps(DEMOS_DATA_DIR "bw.rgb", GL_RGB)) { 531 fprintf(stderr,"Error reading a texture.\n"); 532 exit(-1); 533 } 534 535 glPixelTransferf(GL_RED_SCALE, 1.0); 536 glPixelTransferf(GL_RED_BIAS, 0.0); 537 glPixelTransferf(GL_GREEN_SCALE, 1.0); 538 glPixelTransferf(GL_GREEN_BIAS, 0.0); 539 glPixelTransferf(GL_BLUE_SCALE, 1.0); 540 glPixelTransferf(GL_BLUE_BIAS, 0.0); 541 542 543 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); 544 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); 545 546 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); 547 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); 548 549 glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE); 550} 551 552static void initlight(void) 553{ 554 float matamb[4] ={0.5, 0.5, 0.5, 1.0}; 555 float matdiff[4]={0.9, 0.2, 0.2, 1.0}; 556 float matspec[4]={1.0,1.0,1.0,1.0}; 557 558 float lamb[4] ={1.5, 1.5, 1.5, 1.0}; 559 float ldiff[4]={1.0, 1.0, 1.0, 1.0}; 560 float lspec[4]={1.0, 1.0, 1.0, 1.0}; 561 562 glLightf(GL_LIGHT0,GL_SPOT_CUTOFF,70.0); 563 glLightf(GL_LIGHT0,GL_SPOT_EXPONENT,20.0); 564 glLightfv(GL_LIGHT0,GL_AMBIENT,lamb); 565 glLightfv(GL_LIGHT0,GL_DIFFUSE,ldiff); 566 glLightfv(GL_LIGHT0,GL_SPECULAR,lspec); 567 568 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 15.0); 569 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, matdiff); 570 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, matspec); 571 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, matamb); 572 573 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lamb); 574 glEnable(GL_LIGHT0); 575} 576 577static void initdlists(void) 578{ 579 GLUquadricObj *lcone,*lbase; 580 GLfloat plane[4]; 581 GLfloat v0[3]={0.0,0.0,0.0}; 582 GLfloat v1[3]={1.0,0.0,0.0}; 583 GLfloat v2[3]={0.0,1.0,0.0}; 584 585 findplane(plane,v0,v1,v2); 586 shadowmatrix(baseshadow,plane,lightpos); 587 588 teapotdlist=glGenLists(1); 589 glNewList(teapotdlist,GL_COMPILE); 590 glRotatef(90.0,1.0,0.0,0.0); 591 glCullFace(GL_FRONT); 592 glBindTexture(GL_TEXTURE_2D,t2id); 593 glutSolidTeapot(0.75); 594 glCullFace(GL_BACK); 595 glEndList(); 596 597 basedlist=glGenLists(1); 598 glNewList(basedlist,GL_COMPILE); 599 drawbase(); 600 glEndList(); 601 602 lightdlist=glGenLists(1); 603 glNewList(lightdlist,GL_COMPILE); 604 glDisable(GL_LIGHTING); 605 606 lcone=gluNewQuadric(); 607 lbase=gluNewQuadric(); 608 glRotatef(45.0,0.0,1.0,0.0); 609 610 glColor3f(1.0,1.0,1.0); 611 glCullFace(GL_FRONT); 612 gluDisk(lbase,0.0,0.2,12.0,1.0); 613 glCullFace(GL_BACK); 614 615 glColor3f(0.5,0.0,0.0); 616 gluCylinder(lcone,0.2,0.0,0.5,12,1); 617 618 gluDeleteQuadric(lcone); 619 gluDeleteQuadric(lbase); 620 621 glEnable(GL_LIGHTING); 622 glEndList(); 623} 624 625int main(int ac, char **av) 626{ 627 float fogcolor[4]={0.025,0.025,0.025,1.0}; 628 629 fprintf(stderr,"Teapot V1.2\nWritten by David Bucciarelli (tech.hmw@plus.it)\n"); 630 631 /* 632 if(!SetPriorityClass(GetCurrentProcess(),REALTIME_PRIORITY_CLASS)) { 633 fprintf(stderr,"Error setting the process class.\n"); 634 return 0; 635 } 636 637 if(!SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_TIME_CRITICAL)) { 638 fprintf(stderr,"Error setting the process priority.\n"); 639 return 0; 640 } 641 */ 642 643 glutInitWindowSize(WIDTH,HEIGHT); 644 glutInit(&ac,av); 645 646 glutInitDisplayMode(GLUT_RGB|GLUT_DEPTH|GLUT_DOUBLE); 647 648 if(!(win=glutCreateWindow("Teapot"))) { 649 fprintf(stderr,"Error, couldn't open window\n"); 650 return -1; 651 } 652 653 reshape(WIDTH,HEIGHT); 654 655 glShadeModel(GL_SMOOTH); 656 glEnable(GL_DEPTH_TEST); 657 glEnable(GL_CULL_FACE); 658 glEnable(GL_TEXTURE_2D); 659 660 glEnable(GL_FOG); 661 glFogi(GL_FOG_MODE,GL_EXP2); 662 glFogfv(GL_FOG_COLOR,fogcolor); 663 664 glFogf(GL_FOG_DENSITY,0.04); 665 glHint(GL_FOG_HINT,GL_NICEST); 666 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); 667 668 calcposobs(); 669 670 inittextures(); 671 initlight(); 672 673 initdlists(); 674 675 glClearColor(fogcolor[0],fogcolor[1],fogcolor[2],fogcolor[3]); 676 677 glutReshapeFunc(reshape); 678 glutDisplayFunc(draw); 679 glutKeyboardFunc(key); 680 glutSpecialFunc(special); 681 glutIdleFunc(draw); 682 683 glutMainLoop(); 684 cleanup(); 685 686 return 0; 687} 688