132001f49Smrg/*
232001f49Smrg * This program is under the GNU GPL.
332001f49Smrg * Use at your own risk.
432001f49Smrg *
532001f49Smrg * written by David Bucciarelli (tech.hmw@plus.it)
632001f49Smrg *            Humanware s.r.l.
732001f49Smrg */
832001f49Smrg
932001f49Smrg#include <stdio.h>
1032001f49Smrg#include <stdlib.h>
1132001f49Smrg#include <math.h>
1232001f49Smrg#include <time.h>
1332001f49Smrg#include <string.h>
1432001f49Smrg
1532001f49Smrg#ifdef WIN32
1632001f49Smrg#include <windows.h>
1732001f49Smrg#endif
1832001f49Smrg
1932001f49Smrg#include "glut_wrap.h"
2032001f49Smrg#include "readtex.h"
2132001f49Smrg
2232001f49Smrg#ifdef XMESA
2332001f49Smrg#include "GL/xmesa.h"
2432001f49Smrgstatic int fullscreen=1;
2532001f49Smrg#endif
2632001f49Smrg
2732001f49Smrgstatic int WIDTH=640;
2832001f49Smrgstatic int HEIGHT=480;
2932001f49Smrg
3032001f49Smrgstatic GLint T0 = 0;
3132001f49Smrgstatic GLint Frames = 0;
3232001f49Smrg
3332001f49Smrg#define BASESIZE 10.0
3432001f49Smrg
3532001f49Smrg#define BASERES 12
3632001f49Smrg#define TEAPOTRES 3
3732001f49Smrg
3832001f49Smrg#ifndef M_PI
3932001f49Smrg#define M_PI 3.1415926535
4032001f49Smrg#endif
4132001f49Smrg
4232001f49Smrgextern void shadowmatrix(GLfloat [4][4], GLfloat [4], GLfloat [4]);
4332001f49Smrgextern void findplane(GLfloat [4], GLfloat [3], GLfloat [3], GLfloat [3]);
4432001f49Smrg
4532001f49Smrg
4632001f49Smrgstatic int win=0;
4732001f49Smrg
4832001f49Smrgstatic float obs[3]={5.0,0.0,1.0};
4932001f49Smrgstatic float dir[3];
5032001f49Smrgstatic float v=0.0;
5132001f49Smrgstatic float alpha=-90.0;
5232001f49Smrgstatic float beta=90.0;
5332001f49Smrg
5432001f49Smrgstatic GLfloat baseshadow[4][4];
5532001f49Smrgstatic GLfloat lightpos[4]={2.3,0.0,3.0,1.0};
5632001f49Smrgstatic GLfloat lightdir[3]={-2.3,0.0,-3.0};
5732001f49Smrgstatic GLfloat lightalpha=0.0;
5832001f49Smrg
5932001f49Smrgstatic int fog=1;
6032001f49Smrgstatic int bfcull=1;
6132001f49Smrgstatic int usetex=1;
6232001f49Smrgstatic int help=1;
6332001f49Smrgstatic int joyavailable=0;
6432001f49Smrgstatic int joyactive=0;
6532001f49Smrg
6632001f49Smrgstatic GLuint t1id,t2id;
6732001f49Smrgstatic GLuint teapotdlist,basedlist,lightdlist;
6832001f49Smrg
6932001f49Smrg
7032001f49Smrg
7132001f49Smrg/******************** begin shadow code ********************/
7232001f49Smrg
7332001f49Smrg/* Taken from the projshadow.c - by Tom McReynolds, SGI */
7432001f49Smrg
7532001f49Smrg/* Modified by David Bucciarelli */
7632001f49Smrg
7732001f49Smrgenum {
7832001f49Smrg  X, Y, Z, W
7932001f49Smrg};
8032001f49Smrgenum {
8132001f49Smrg  A, B, C, D
8232001f49Smrg};
8332001f49Smrg
8432001f49Smrg/* create a matrix that will project the desired shadow */
8532001f49Smrgvoid
8632001f49Smrgshadowmatrix(GLfloat shadowMat[4][4],
8732001f49Smrg  GLfloat groundplane[4],
8832001f49Smrg  GLfloat lightpos[4])
8932001f49Smrg{
9032001f49Smrg  GLfloat dot;
9132001f49Smrg
9232001f49Smrg  /* find dot product between light position vector and ground plane normal */
9332001f49Smrg  dot = groundplane[X] * lightpos[X] +
9432001f49Smrg    groundplane[Y] * lightpos[Y] +
9532001f49Smrg    groundplane[Z] * lightpos[Z] +
9632001f49Smrg    groundplane[W] * lightpos[W];
9732001f49Smrg
9832001f49Smrg  shadowMat[0][0] = dot - lightpos[X] * groundplane[X];
9932001f49Smrg  shadowMat[1][0] = 0.f - lightpos[X] * groundplane[Y];
10032001f49Smrg  shadowMat[2][0] = 0.f - lightpos[X] * groundplane[Z];
10132001f49Smrg  shadowMat[3][0] = 0.f - lightpos[X] * groundplane[W];
10232001f49Smrg
10332001f49Smrg  shadowMat[X][1] = 0.f - lightpos[Y] * groundplane[X];
10432001f49Smrg  shadowMat[1][1] = dot - lightpos[Y] * groundplane[Y];
10532001f49Smrg  shadowMat[2][1] = 0.f - lightpos[Y] * groundplane[Z];
10632001f49Smrg  shadowMat[3][1] = 0.f - lightpos[Y] * groundplane[W];
10732001f49Smrg
10832001f49Smrg  shadowMat[X][2] = 0.f - lightpos[Z] * groundplane[X];
10932001f49Smrg  shadowMat[1][2] = 0.f - lightpos[Z] * groundplane[Y];
11032001f49Smrg  shadowMat[2][2] = dot - lightpos[Z] * groundplane[Z];
11132001f49Smrg  shadowMat[3][2] = 0.f - lightpos[Z] * groundplane[W];
11232001f49Smrg
11332001f49Smrg  shadowMat[X][3] = 0.f - lightpos[W] * groundplane[X];
11432001f49Smrg  shadowMat[1][3] = 0.f - lightpos[W] * groundplane[Y];
11532001f49Smrg  shadowMat[2][3] = 0.f - lightpos[W] * groundplane[Z];
11632001f49Smrg  shadowMat[3][3] = dot - lightpos[W] * groundplane[W];
11732001f49Smrg
11832001f49Smrg}
11932001f49Smrg
12032001f49Smrg/* find the plane equation given 3 points */
12132001f49Smrgvoid
12232001f49Smrgfindplane(GLfloat plane[4],
12332001f49Smrg  GLfloat v0[3], GLfloat v1[3], GLfloat v2[3])
12432001f49Smrg{
12532001f49Smrg  GLfloat vec0[3], vec1[3];
12632001f49Smrg
12732001f49Smrg  /* need 2 vectors to find cross product */
12832001f49Smrg  vec0[X] = v1[X] - v0[X];
12932001f49Smrg  vec0[Y] = v1[Y] - v0[Y];
13032001f49Smrg  vec0[Z] = v1[Z] - v0[Z];
13132001f49Smrg
13232001f49Smrg  vec1[X] = v2[X] - v0[X];
13332001f49Smrg  vec1[Y] = v2[Y] - v0[Y];
13432001f49Smrg  vec1[Z] = v2[Z] - v0[Z];
13532001f49Smrg
13632001f49Smrg  /* find cross product to get A, B, and C of plane equation */
13732001f49Smrg  plane[A] = vec0[Y] * vec1[Z] - vec0[Z] * vec1[Y];
13832001f49Smrg  plane[B] = -(vec0[X] * vec1[Z] - vec0[Z] * vec1[X]);
13932001f49Smrg  plane[C] = vec0[X] * vec1[Y] - vec0[Y] * vec1[X];
14032001f49Smrg
14132001f49Smrg  plane[D] = -(plane[A] * v0[X] + plane[B] * v0[Y] + plane[C] * v0[Z]);
14232001f49Smrg}
14332001f49Smrg
14432001f49Smrg/******************** end shadow code ********************/
14532001f49Smrg
14632001f49Smrg
14732001f49Smrgstatic void calcposobs(void)
14832001f49Smrg{
14932001f49Smrg  dir[0]=sin(alpha*M_PI/180.0);
15032001f49Smrg  dir[1]=cos(alpha*M_PI/180.0)*sin(beta*M_PI/180.0);
15132001f49Smrg  dir[2]=cos(beta*M_PI/180.0);
15232001f49Smrg
15332001f49Smrg  obs[0]+=v*dir[0];
15432001f49Smrg  obs[1]+=v*dir[1];
15532001f49Smrg  obs[2]+=v*dir[2];
15632001f49Smrg}
15732001f49Smrg
15832001f49Smrgstatic void special(int k, int x, int y)
15932001f49Smrg{
16032001f49Smrg  switch(k) {
16132001f49Smrg  case GLUT_KEY_LEFT:
16232001f49Smrg    alpha-=2.0;
16332001f49Smrg    break;
16432001f49Smrg  case GLUT_KEY_RIGHT:
16532001f49Smrg    alpha+=2.0;
16632001f49Smrg    break;
16732001f49Smrg  case GLUT_KEY_DOWN:
16832001f49Smrg    beta-=2.0;
16932001f49Smrg    break;
17032001f49Smrg  case GLUT_KEY_UP:
17132001f49Smrg    beta+=2.0;
17232001f49Smrg    break;
17332001f49Smrg  }
17432001f49Smrg}
17532001f49Smrg
17632001f49Smrgstatic void cleanup(void)
17732001f49Smrg{
17832001f49Smrg  glDeleteTextures(1, &t1id);
17932001f49Smrg  glDeleteTextures(1, &t2id);
18032001f49Smrg  glDeleteLists(teapotdlist, 1);
18132001f49Smrg  glDeleteLists(basedlist, 1);
18232001f49Smrg  glDeleteLists(lightdlist, 1);
18332001f49Smrg}
18432001f49Smrg
18532001f49Smrgstatic void key(unsigned char k, int x, int y)
18632001f49Smrg{
18732001f49Smrg  switch(k) {
18832001f49Smrg  case 27:
18932001f49Smrg    cleanup();
19032001f49Smrg    exit(0);
19132001f49Smrg    break;
19232001f49Smrg
19332001f49Smrg  case 'a':
19432001f49Smrg    v+=0.005;
19532001f49Smrg    break;
19632001f49Smrg  case 'z':
19732001f49Smrg    v-=0.005;
19832001f49Smrg    break;
19932001f49Smrg
20032001f49Smrg  case 'j':
20132001f49Smrg    joyactive=(!joyactive);
20232001f49Smrg    break;
20332001f49Smrg  case 'h':
20432001f49Smrg    help=(!help);
20532001f49Smrg    break;
20632001f49Smrg  case 'f':
20732001f49Smrg    fog=(!fog);
20832001f49Smrg    break;
20932001f49Smrg  case 't':
21032001f49Smrg    usetex=(!usetex);
21132001f49Smrg    break;
21232001f49Smrg  case 'b':
21332001f49Smrg    if(bfcull) {
21432001f49Smrg      glDisable(GL_CULL_FACE);
21532001f49Smrg      bfcull=0;
21632001f49Smrg    } else {
21732001f49Smrg      glEnable(GL_CULL_FACE);
21832001f49Smrg      bfcull=1;
21932001f49Smrg    }
22032001f49Smrg    break;
22132001f49Smrg#ifdef XMESA
22232001f49Smrg  case ' ':
22332001f49Smrg    XMesaSetFXmode(fullscreen ? XMESA_FX_FULLSCREEN : XMESA_FX_WINDOW);
22432001f49Smrg    fullscreen=(!fullscreen);
22532001f49Smrg    break;
22632001f49Smrg#endif
22732001f49Smrg  }
22832001f49Smrg}
22932001f49Smrg
23032001f49Smrgstatic void reshape(int w, int h)
23132001f49Smrg{
23232001f49Smrg  WIDTH=w;
23332001f49Smrg  HEIGHT=h;
23432001f49Smrg  glMatrixMode(GL_PROJECTION);
23532001f49Smrg  glLoadIdentity();
23632001f49Smrg  gluPerspective(45.0,w/(float)h,0.2,40.0);
23732001f49Smrg  glMatrixMode(GL_MODELVIEW);
23832001f49Smrg  glLoadIdentity();
23932001f49Smrg  glViewport(0,0,w,h);
24032001f49Smrg}
24132001f49Smrg
24232001f49Smrgstatic void printstring(void *font, char *string)
24332001f49Smrg{
24432001f49Smrg  int len,i;
24532001f49Smrg
24632001f49Smrg  len=(int)strlen(string);
24732001f49Smrg  for(i=0;i<len;i++)
24832001f49Smrg    glutBitmapCharacter(font,string[i]);
24932001f49Smrg}
25032001f49Smrg
25132001f49Smrgstatic void printhelp(void)
25232001f49Smrg{
25332001f49Smrg  glEnable(GL_BLEND);
25432001f49Smrg  glColor4f(0.5,0.5,0.5,0.5);
25532001f49Smrg  glRecti(40,40,600,440);
25632001f49Smrg  glDisable(GL_BLEND);
25732001f49Smrg
25832001f49Smrg  glColor3f(1.0,0.0,0.0);
25932001f49Smrg  glRasterPos2i(300,420);
26032001f49Smrg  printstring(GLUT_BITMAP_TIMES_ROMAN_24,"Help");
26132001f49Smrg
26232001f49Smrg  glRasterPos2i(60,390);
26332001f49Smrg  printstring(GLUT_BITMAP_TIMES_ROMAN_24,"h - Toggle Help");
26432001f49Smrg  glRasterPos2i(60,360);
26532001f49Smrg  printstring(GLUT_BITMAP_TIMES_ROMAN_24,"t - Toggle Textures");
26632001f49Smrg  glRasterPos2i(60,330);
26732001f49Smrg  printstring(GLUT_BITMAP_TIMES_ROMAN_24,"f - Toggle Fog");
26832001f49Smrg  glRasterPos2i(60,300);
26932001f49Smrg  printstring(GLUT_BITMAP_TIMES_ROMAN_24,"b - Toggle Back face culling");
27032001f49Smrg  glRasterPos2i(60,270);
27132001f49Smrg  printstring(GLUT_BITMAP_TIMES_ROMAN_24,"Arrow Keys - Rotate");
27232001f49Smrg  glRasterPos2i(60,240);
27332001f49Smrg  printstring(GLUT_BITMAP_TIMES_ROMAN_24,"a - Increase velocity");
27432001f49Smrg  glRasterPos2i(60,210);
27532001f49Smrg  printstring(GLUT_BITMAP_TIMES_ROMAN_24,"z - Decrease velocity");
27632001f49Smrg
27732001f49Smrg  glRasterPos2i(60,180);
27832001f49Smrg  if(joyavailable)
27932001f49Smrg    printstring(GLUT_BITMAP_TIMES_ROMAN_24,"j - Toggle jostick control (Joystick control available)");
28032001f49Smrg  else
28132001f49Smrg    printstring(GLUT_BITMAP_TIMES_ROMAN_24,"(No Joystick control available)");
28232001f49Smrg}
28332001f49Smrg
28432001f49Smrgstatic void drawbase(void)
28532001f49Smrg{
28632001f49Smrg  static const GLfloat amb[4] = { 1, .5, 0.2, 1 };
28732001f49Smrg  static const GLfloat diff[4] = { 1, .4, 0.2, 1 };
28832001f49Smrg  int i,j;
28932001f49Smrg  float x,y,dx,dy;
29032001f49Smrg
29132001f49Smrg  glBindTexture(GL_TEXTURE_2D,t1id);
29232001f49Smrg
29332001f49Smrg  glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, amb);
29432001f49Smrg  glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diff);
29532001f49Smrg  dx=BASESIZE/BASERES;
29632001f49Smrg  dy=-BASESIZE/BASERES;
29732001f49Smrg  for(y=BASESIZE/2.0,j=0;j<BASERES;y+=dy,j++) {
29832001f49Smrg    glBegin(GL_QUAD_STRIP);
29932001f49Smrg    glColor3f(1.0,1.0,1.0);
30032001f49Smrg    glNormal3f(0.0,0.0,1.0);
30132001f49Smrg    for(x=-BASESIZE/2.0,i=0;i<BASERES;x+=dx,i++) {
30232001f49Smrg      glTexCoord2f(x,y);
30332001f49Smrg      glVertex3f(x,y,0.0);
30432001f49Smrg
30532001f49Smrg      glTexCoord2f(x,y+dy);
30632001f49Smrg      glVertex3f(x,y+dy,0.0);
30732001f49Smrg    }
30832001f49Smrg    glEnd();
30932001f49Smrg  }
31032001f49Smrg}
31132001f49Smrg
31232001f49Smrgstatic void drawteapot(void)
31332001f49Smrg{
31432001f49Smrg  static const GLfloat amb[4] = {  0.2, 0.2, 0.2, 1 };
31532001f49Smrg  static const GLfloat diff[4] = { 0.8, 0.3, 0.5, 1 };
31632001f49Smrg  static float xrot=0.0;
31732001f49Smrg  static float zrot=0.0;
31832001f49Smrg
31932001f49Smrg  glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, amb);
32032001f49Smrg  glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diff);
32132001f49Smrg
32232001f49Smrg  glPushMatrix();
32332001f49Smrg  glRotatef(lightalpha,0.0,0.0,1.0);
32432001f49Smrg  glMultMatrixf((GLfloat *)baseshadow);
32532001f49Smrg  glRotatef(-lightalpha,0.0,0.0,1.0);
32632001f49Smrg
32732001f49Smrg  glTranslatef(0.0,0.0,1.0);
32832001f49Smrg  glRotatef(xrot,1.0,0.0,0.0);
32932001f49Smrg  glRotatef(zrot,0.0,0.0,1.0);
33032001f49Smrg
33132001f49Smrg  glDisable(GL_TEXTURE_2D);
33232001f49Smrg  glDisable(GL_DEPTH_TEST);
33332001f49Smrg  glDisable(GL_LIGHTING);
33432001f49Smrg
33532001f49Smrg  glColor3f(0.0,0.0,0.0);
33632001f49Smrg  glCallList(teapotdlist);
33732001f49Smrg
33832001f49Smrg  glEnable(GL_DEPTH_TEST);
33932001f49Smrg  glEnable(GL_LIGHTING);
34032001f49Smrg  if(usetex)
34132001f49Smrg    glEnable(GL_TEXTURE_2D);
34232001f49Smrg
34332001f49Smrg  glPopMatrix();
34432001f49Smrg
34532001f49Smrg  glPushMatrix();
34632001f49Smrg  glTranslatef(0.0,0.0,1.0);
34732001f49Smrg  glRotatef(xrot,1.0,0.0,0.0);
34832001f49Smrg  glRotatef(zrot,0.0,0.0,1.0);
34932001f49Smrg
35032001f49Smrg  glCallList(teapotdlist);
35132001f49Smrg  glPopMatrix();
35232001f49Smrg
35332001f49Smrg  xrot+=2.0;
35432001f49Smrg  zrot+=1.0;
35532001f49Smrg}
35632001f49Smrg
35732001f49Smrgstatic void drawlight1(void)
35832001f49Smrg{
35932001f49Smrg  glPushMatrix();
36032001f49Smrg  glRotatef(lightalpha,0.0,0.0,1.0);
36132001f49Smrg  glLightfv(GL_LIGHT0,GL_POSITION,lightpos);
36232001f49Smrg  glLightfv(GL_LIGHT0,GL_SPOT_DIRECTION,lightdir);
36332001f49Smrg
36432001f49Smrg  glPopMatrix();
36532001f49Smrg}
36632001f49Smrg
36732001f49Smrgstatic void drawlight2(void)
36832001f49Smrg{
36932001f49Smrg  glPushMatrix();
37032001f49Smrg  glRotatef(lightalpha,0.0,0.0,1.0);
37132001f49Smrg  glTranslatef(lightpos[0],lightpos[1],lightpos[2]);
37232001f49Smrg
37332001f49Smrg  glDisable(GL_TEXTURE_2D);
37432001f49Smrg  glCallList(lightdlist);
37532001f49Smrg  if(usetex)
37632001f49Smrg    glEnable(GL_TEXTURE_2D);
37732001f49Smrg
37832001f49Smrg  glPopMatrix();
37932001f49Smrg
38032001f49Smrg  lightalpha+=1.0;
38132001f49Smrg}
38232001f49Smrg
38332001f49Smrgstatic void dojoy(void)
38432001f49Smrg{
38532001f49Smrg#ifdef WIN32
38632001f49Smrg  static UINT max[2]={0,0};
38732001f49Smrg  static UINT min[2]={0xffffffff,0xffffffff},center[2];
38832001f49Smrg  MMRESULT res;
38932001f49Smrg  JOYINFO joy;
39032001f49Smrg
39132001f49Smrg  res=joyGetPos(JOYSTICKID1,&joy);
39232001f49Smrg
39332001f49Smrg  if(res==JOYERR_NOERROR) {
39432001f49Smrg    joyavailable=1;
39532001f49Smrg
39632001f49Smrg    if(max[0]<joy.wXpos)
39732001f49Smrg      max[0]=joy.wXpos;
39832001f49Smrg    if(min[0]>joy.wXpos)
39932001f49Smrg      min[0]=joy.wXpos;
40032001f49Smrg    center[0]=(max[0]+min[0])/2;
40132001f49Smrg
40232001f49Smrg    if(max[1]<joy.wYpos)
40332001f49Smrg      max[1]=joy.wYpos;
40432001f49Smrg    if(min[1]>joy.wYpos)
40532001f49Smrg      min[1]=joy.wYpos;
40632001f49Smrg    center[1]=(max[1]+min[1])/2;
40732001f49Smrg
40832001f49Smrg    if(joyactive) {
40932001f49Smrg      if(fabs(center[0]-(float)joy.wXpos)>0.1*(max[0]-min[0]))
41032001f49Smrg	alpha-=2.5*(center[0]-(float)joy.wXpos)/(max[0]-min[0]);
41132001f49Smrg      if(fabs(center[1]-(float)joy.wYpos)>0.1*(max[1]-min[1]))
41232001f49Smrg	beta+=2.5*(center[1]-(float)joy.wYpos)/(max[1]-min[1]);
41332001f49Smrg
41432001f49Smrg      if(joy.wButtons & JOY_BUTTON1)
41532001f49Smrg	v+=0.005;
41632001f49Smrg      if(joy.wButtons & JOY_BUTTON2)
41732001f49Smrg	v-=0.005;
41832001f49Smrg    }
41932001f49Smrg  } else
42032001f49Smrg    joyavailable=0;
42132001f49Smrg#endif
42232001f49Smrg}
42332001f49Smrg
42432001f49Smrgstatic void draw(void)
42532001f49Smrg{
42632001f49Smrg  static char frbuf[80] = "";
42732001f49Smrg
42832001f49Smrg  dojoy();
42932001f49Smrg
43032001f49Smrg  glEnable(GL_DEPTH_TEST);
43132001f49Smrg  glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
43232001f49Smrg
43332001f49Smrg  if(usetex)
43432001f49Smrg    glEnable(GL_TEXTURE_2D);
43532001f49Smrg  else
43632001f49Smrg    glDisable(GL_TEXTURE_2D);
43732001f49Smrg
43832001f49Smrg  if(fog)
43932001f49Smrg    glEnable(GL_FOG);
44032001f49Smrg  else
44132001f49Smrg    glDisable(GL_FOG);
44232001f49Smrg
44332001f49Smrg  glEnable(GL_LIGHTING);
44432001f49Smrg
44532001f49Smrg  glShadeModel(GL_SMOOTH);
44632001f49Smrg
44732001f49Smrg  glPushMatrix();
44832001f49Smrg  calcposobs();
44932001f49Smrg
45032001f49Smrg  gluLookAt(obs[0],obs[1],obs[2],
45132001f49Smrg	    obs[0]+dir[0],obs[1]+dir[1],obs[2]+dir[2],
45232001f49Smrg	    0.0,0.0,1.0);
45332001f49Smrg
45432001f49Smrg  drawlight1();
45532001f49Smrg  glCallList(basedlist);
45632001f49Smrg  drawteapot();
45732001f49Smrg  drawlight2();
45832001f49Smrg  glPopMatrix();
45932001f49Smrg
46032001f49Smrg  glDisable(GL_LIGHTING);
46132001f49Smrg  glDisable(GL_TEXTURE_2D);
46232001f49Smrg  glDisable(GL_DEPTH_TEST);
46332001f49Smrg  glDisable(GL_FOG);
46432001f49Smrg  glShadeModel(GL_FLAT);
46532001f49Smrg
46632001f49Smrg  glMatrixMode(GL_PROJECTION);
46732001f49Smrg  glLoadIdentity();
46832001f49Smrg  glOrtho(-0.5,639.5,-0.5,479.5,-1.0,1.0);
46932001f49Smrg  glMatrixMode(GL_MODELVIEW);
47032001f49Smrg  glLoadIdentity();
47132001f49Smrg
47232001f49Smrg  glColor3f(1.0,0.0,0.0);
47332001f49Smrg  glRasterPos2i(10,10);
47432001f49Smrg  printstring(GLUT_BITMAP_HELVETICA_18,frbuf);
47532001f49Smrg  glRasterPos2i(350,470);
47632001f49Smrg  printstring(GLUT_BITMAP_HELVETICA_10,"Teapot V1.2 Written by David Bucciarelli (tech.hmw@plus.it)");
47732001f49Smrg
47832001f49Smrg  if(help)
47932001f49Smrg    printhelp();
48032001f49Smrg
48132001f49Smrg  reshape(WIDTH,HEIGHT);
48232001f49Smrg
48332001f49Smrg  glutSwapBuffers();
48432001f49Smrg
48532001f49Smrg   Frames++;
48632001f49Smrg
48732001f49Smrg   {
48832001f49Smrg      GLint t = glutGet(GLUT_ELAPSED_TIME);
48932001f49Smrg      if (t - T0 >= 2000) {
49032001f49Smrg         GLfloat seconds = (t - T0) / 1000.0;
49132001f49Smrg         GLfloat fps = Frames / seconds;
49232001f49Smrg         sprintf(frbuf, "Frame rate: %f", fps);
49332001f49Smrg         printf("%s\n", frbuf);
4947ec3b29aSmrg         fflush(stdout);
49532001f49Smrg         T0 = t;
49632001f49Smrg         Frames = 0;
49732001f49Smrg      }
49832001f49Smrg   }
49932001f49Smrg}
50032001f49Smrg
50132001f49Smrgstatic void inittextures(void)
50232001f49Smrg{
50332001f49Smrg  glGenTextures(1,&t1id);
50432001f49Smrg  glBindTexture(GL_TEXTURE_2D,t1id);
50532001f49Smrg
50632001f49Smrg  glPixelStorei(GL_UNPACK_ALIGNMENT,4);
50732001f49Smrg  if (!LoadRGBMipmaps(DEMOS_DATA_DIR "tile.rgb", GL_RGB)) {
50832001f49Smrg    fprintf(stderr,"Error reading a texture.\n");
50932001f49Smrg    exit(-1);
51032001f49Smrg  }
51132001f49Smrg
51232001f49Smrg  glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
51332001f49Smrg  glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
51432001f49Smrg
51532001f49Smrg  glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
51632001f49Smrg  glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
51732001f49Smrg
51832001f49Smrg  glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
51932001f49Smrg
52032001f49Smrg  glGenTextures(1,&t2id);
52132001f49Smrg  glBindTexture(GL_TEXTURE_2D,t2id);
52232001f49Smrg
52332001f49Smrg  glPixelTransferf(GL_RED_SCALE, 0.75);
52432001f49Smrg  glPixelTransferf(GL_RED_BIAS, 0.25);
52532001f49Smrg  glPixelTransferf(GL_GREEN_SCALE, 0.75);
52632001f49Smrg  glPixelTransferf(GL_GREEN_BIAS, 0.25);
52732001f49Smrg  glPixelTransferf(GL_BLUE_SCALE, 0.75);
52832001f49Smrg  glPixelTransferf(GL_BLUE_BIAS, 0.25);
52932001f49Smrg
53032001f49Smrg  if (!LoadRGBMipmaps(DEMOS_DATA_DIR "bw.rgb", GL_RGB)) {
53132001f49Smrg    fprintf(stderr,"Error reading a texture.\n");
53232001f49Smrg    exit(-1);
53332001f49Smrg  }
53432001f49Smrg
53532001f49Smrg  glPixelTransferf(GL_RED_SCALE, 1.0);
53632001f49Smrg  glPixelTransferf(GL_RED_BIAS, 0.0);
53732001f49Smrg  glPixelTransferf(GL_GREEN_SCALE, 1.0);
53832001f49Smrg  glPixelTransferf(GL_GREEN_BIAS, 0.0);
53932001f49Smrg  glPixelTransferf(GL_BLUE_SCALE, 1.0);
54032001f49Smrg  glPixelTransferf(GL_BLUE_BIAS, 0.0);
54132001f49Smrg
54232001f49Smrg
54332001f49Smrg  glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
54432001f49Smrg  glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
54532001f49Smrg
54632001f49Smrg  glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
54732001f49Smrg  glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
54832001f49Smrg
54932001f49Smrg  glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
55032001f49Smrg}
55132001f49Smrg
55232001f49Smrgstatic void initlight(void)
55332001f49Smrg{
55432001f49Smrg  float matamb[4] ={0.5, 0.5, 0.5, 1.0};
55532001f49Smrg  float matdiff[4]={0.9, 0.2, 0.2, 1.0};
55632001f49Smrg  float matspec[4]={1.0,1.0,1.0,1.0};
55732001f49Smrg
55832001f49Smrg  float lamb[4] ={1.5, 1.5, 1.5, 1.0};
55932001f49Smrg  float ldiff[4]={1.0, 1.0, 1.0, 1.0};
56032001f49Smrg  float lspec[4]={1.0, 1.0, 1.0, 1.0};
56132001f49Smrg
56232001f49Smrg  glLightf(GL_LIGHT0,GL_SPOT_CUTOFF,70.0);
56332001f49Smrg  glLightf(GL_LIGHT0,GL_SPOT_EXPONENT,20.0);
56432001f49Smrg  glLightfv(GL_LIGHT0,GL_AMBIENT,lamb);
56532001f49Smrg  glLightfv(GL_LIGHT0,GL_DIFFUSE,ldiff);
56632001f49Smrg  glLightfv(GL_LIGHT0,GL_SPECULAR,lspec);
56732001f49Smrg
56832001f49Smrg  glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 15.0);
56932001f49Smrg  glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, matdiff);
57032001f49Smrg  glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, matspec);
57132001f49Smrg  glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, matamb);
57232001f49Smrg
57332001f49Smrg  glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lamb);
57432001f49Smrg  glEnable(GL_LIGHT0);
57532001f49Smrg}
57632001f49Smrg
57732001f49Smrgstatic void initdlists(void)
57832001f49Smrg{
57932001f49Smrg  GLUquadricObj *lcone,*lbase;
58032001f49Smrg  GLfloat plane[4];
58132001f49Smrg  GLfloat v0[3]={0.0,0.0,0.0};
58232001f49Smrg  GLfloat v1[3]={1.0,0.0,0.0};
58332001f49Smrg  GLfloat v2[3]={0.0,1.0,0.0};
58432001f49Smrg
58532001f49Smrg  findplane(plane,v0,v1,v2);
58632001f49Smrg  shadowmatrix(baseshadow,plane,lightpos);
58732001f49Smrg
58832001f49Smrg  teapotdlist=glGenLists(1);
58932001f49Smrg  glNewList(teapotdlist,GL_COMPILE);
59032001f49Smrg  glRotatef(90.0,1.0,0.0,0.0);
59132001f49Smrg  glCullFace(GL_FRONT);
59232001f49Smrg  glBindTexture(GL_TEXTURE_2D,t2id);
59332001f49Smrg  glutSolidTeapot(0.75);
59432001f49Smrg  glCullFace(GL_BACK);
59532001f49Smrg  glEndList();
59632001f49Smrg
59732001f49Smrg  basedlist=glGenLists(1);
59832001f49Smrg  glNewList(basedlist,GL_COMPILE);
59932001f49Smrg  drawbase();
60032001f49Smrg  glEndList();
60132001f49Smrg
60232001f49Smrg  lightdlist=glGenLists(1);
60332001f49Smrg  glNewList(lightdlist,GL_COMPILE);
60432001f49Smrg  glDisable(GL_LIGHTING);
60532001f49Smrg
60632001f49Smrg  lcone=gluNewQuadric();
60732001f49Smrg  lbase=gluNewQuadric();
60832001f49Smrg  glRotatef(45.0,0.0,1.0,0.0);
60932001f49Smrg
61032001f49Smrg  glColor3f(1.0,1.0,1.0);
61132001f49Smrg  glCullFace(GL_FRONT);
61232001f49Smrg  gluDisk(lbase,0.0,0.2,12.0,1.0);
61332001f49Smrg  glCullFace(GL_BACK);
61432001f49Smrg
61532001f49Smrg  glColor3f(0.5,0.0,0.0);
61632001f49Smrg  gluCylinder(lcone,0.2,0.0,0.5,12,1);
61732001f49Smrg
61832001f49Smrg  gluDeleteQuadric(lcone);
61932001f49Smrg  gluDeleteQuadric(lbase);
62032001f49Smrg
62132001f49Smrg  glEnable(GL_LIGHTING);
62232001f49Smrg  glEndList();
62332001f49Smrg}
62432001f49Smrg
62532001f49Smrgint main(int ac, char **av)
62632001f49Smrg{
62732001f49Smrg  float fogcolor[4]={0.025,0.025,0.025,1.0};
62832001f49Smrg
62932001f49Smrg  fprintf(stderr,"Teapot V1.2\nWritten by David Bucciarelli (tech.hmw@plus.it)\n");
63032001f49Smrg
63132001f49Smrg  /*
63232001f49Smrg    if(!SetPriorityClass(GetCurrentProcess(),REALTIME_PRIORITY_CLASS)) {
63332001f49Smrg    fprintf(stderr,"Error setting the process class.\n");
63432001f49Smrg    return 0;
63532001f49Smrg    }
63632001f49Smrg
63732001f49Smrg    if(!SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_TIME_CRITICAL)) {
63832001f49Smrg    fprintf(stderr,"Error setting the process priority.\n");
63932001f49Smrg    return 0;
64032001f49Smrg    }
64132001f49Smrg    */
64232001f49Smrg
64332001f49Smrg  glutInitWindowSize(WIDTH,HEIGHT);
64432001f49Smrg  glutInit(&ac,av);
64532001f49Smrg
64632001f49Smrg  glutInitDisplayMode(GLUT_RGB|GLUT_DEPTH|GLUT_DOUBLE);
64732001f49Smrg
64832001f49Smrg  if(!(win=glutCreateWindow("Teapot"))) {
64932001f49Smrg    fprintf(stderr,"Error, couldn't open window\n");
65032001f49Smrg	return -1;
65132001f49Smrg  }
65232001f49Smrg
65332001f49Smrg  reshape(WIDTH,HEIGHT);
65432001f49Smrg
65532001f49Smrg  glShadeModel(GL_SMOOTH);
65632001f49Smrg  glEnable(GL_DEPTH_TEST);
65732001f49Smrg  glEnable(GL_CULL_FACE);
65832001f49Smrg  glEnable(GL_TEXTURE_2D);
65932001f49Smrg
66032001f49Smrg  glEnable(GL_FOG);
66132001f49Smrg  glFogi(GL_FOG_MODE,GL_EXP2);
66232001f49Smrg  glFogfv(GL_FOG_COLOR,fogcolor);
66332001f49Smrg
66432001f49Smrg  glFogf(GL_FOG_DENSITY,0.04);
66532001f49Smrg  glHint(GL_FOG_HINT,GL_NICEST);
66632001f49Smrg  glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
66732001f49Smrg
66832001f49Smrg  calcposobs();
66932001f49Smrg
67032001f49Smrg  inittextures();
67132001f49Smrg  initlight();
67232001f49Smrg
67332001f49Smrg  initdlists();
67432001f49Smrg
67532001f49Smrg  glClearColor(fogcolor[0],fogcolor[1],fogcolor[2],fogcolor[3]);
67632001f49Smrg
67732001f49Smrg  glutReshapeFunc(reshape);
67832001f49Smrg  glutDisplayFunc(draw);
67932001f49Smrg  glutKeyboardFunc(key);
68032001f49Smrg  glutSpecialFunc(special);
68132001f49Smrg  glutIdleFunc(draw);
68232001f49Smrg
68332001f49Smrg  glutMainLoop();
68432001f49Smrg  cleanup();
68532001f49Smrg
68632001f49Smrg  return 0;
68732001f49Smrg}
688