2 * This program is under the GNU GPL.
3 * Use at your own risk.
5 * written by David Bucciarelli (tech.hmw@plus.it)
24 static int fullscreen
=1;
28 static int HEIGHT
=480;
31 static GLint Frames
= 0;
39 #define M_PI 3.1415926535
42 extern void shadowmatrix(GLfloat
[4][4], GLfloat
[4], GLfloat
[4]);
43 extern void findplane(GLfloat
[4], GLfloat
[3], GLfloat
[3], GLfloat
[3]);
48 static float obs
[3]={5.0,0.0,1.0};
51 static float alpha
=-90.0;
52 static float beta
=90.0;
54 static GLfloat baseshadow
[4][4];
55 static GLfloat lightpos
[4]={2.3,0.0,3.0,1.0};
56 static GLfloat lightdir
[3]={-2.3,0.0,-3.0};
57 static GLfloat lightalpha
=0.0;
63 static int joyavailable
=0;
64 static int joyactive
=0;
66 static GLuint t1id
,t2id
;
67 static GLuint teapotdlist
,basedlist
,lightdlist
;
71 /******************** begin shadow code ********************/
73 /* Taken from the projshadow.c - by Tom McReynolds, SGI */
75 /* Modified by David Bucciarelli */
84 /* create a matrix that will project the desired shadow */
86 shadowmatrix(GLfloat shadowMat
[4][4],
87 GLfloat groundplane
[4],
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
];
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
];
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
];
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
];
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
];
120 /* find the plane equation given 3 points */
122 findplane(GLfloat plane
[4],
123 GLfloat v0
[3], GLfloat v1
[3], GLfloat v2
[3])
125 GLfloat vec0
[3], vec1
[3];
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
];
132 vec1
[X
] = v2
[X
] - v0
[X
];
133 vec1
[Y
] = v2
[Y
] - v0
[Y
];
134 vec1
[Z
] = v2
[Z
] - v0
[Z
];
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
];
141 plane
[D
] = -(plane
[A
] * v0
[X
] + plane
[B
] * v0
[Y
] + plane
[C
] * v0
[Z
]);
144 /******************** end shadow code ********************/
147 static void calcposobs(void)
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);
158 static void special(int k
, int x
, int y
)
176 static void key(unsigned char k
, int x
, int y
)
191 joyactive
=(!joyactive
);
204 glDisable(GL_CULL_FACE
);
207 glEnable(GL_CULL_FACE
);
213 XMesaSetFXmode(fullscreen
? XMESA_FX_FULLSCREEN
: XMESA_FX_WINDOW
);
214 fullscreen
=(!fullscreen
);
220 static void reshape(int w
, int h
)
224 glMatrixMode(GL_PROJECTION
);
226 gluPerspective(45.0,w
/(float)h
,0.2,40.0);
227 glMatrixMode(GL_MODELVIEW
);
232 static void printstring(void *font
, char *string
)
236 len
=(int)strlen(string
);
238 glutBitmapCharacter(font
,string
[i
]);
241 static void printhelp(void)
244 glColor4f(0.5,0.5,0.5,0.5);
245 glRecti(40,40,600,440);
248 glColor3f(1.0,0.0,0.0);
249 glRasterPos2i(300,420);
250 printstring(GLUT_BITMAP_TIMES_ROMAN_24
,"Help");
252 glRasterPos2i(60,390);
253 printstring(GLUT_BITMAP_TIMES_ROMAN_24
,"h - Toggle Help");
254 glRasterPos2i(60,360);
255 printstring(GLUT_BITMAP_TIMES_ROMAN_24
,"t - Toggle Textures");
256 glRasterPos2i(60,330);
257 printstring(GLUT_BITMAP_TIMES_ROMAN_24
,"f - Toggle Fog");
258 glRasterPos2i(60,300);
259 printstring(GLUT_BITMAP_TIMES_ROMAN_24
,"b - Toggle Back face culling");
260 glRasterPos2i(60,270);
261 printstring(GLUT_BITMAP_TIMES_ROMAN_24
,"Arrow Keys - Rotate");
262 glRasterPos2i(60,240);
263 printstring(GLUT_BITMAP_TIMES_ROMAN_24
,"a - Increase velocity");
264 glRasterPos2i(60,210);
265 printstring(GLUT_BITMAP_TIMES_ROMAN_24
,"z - Decrease velocity");
267 glRasterPos2i(60,180);
269 printstring(GLUT_BITMAP_TIMES_ROMAN_24
,"j - Toggle jostick control (Joystick control available)");
271 printstring(GLUT_BITMAP_TIMES_ROMAN_24
,"(No Joystick control available)");
274 static void drawbase(void)
276 static const GLfloat amb
[4] = { 1, .5, 0.2, 1 };
277 static const GLfloat diff
[4] = { 1, .4, 0.2, 1 };
281 glBindTexture(GL_TEXTURE_2D
,t1id
);
283 glMaterialfv(GL_FRONT_AND_BACK
, GL_AMBIENT
, amb
);
284 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, diff
);
286 dy
=-BASESIZE
/BASERES
;
287 for(y
=BASESIZE
/2.0,j
=0;j
<BASERES
;y
+=dy
,j
++) {
288 glBegin(GL_QUAD_STRIP
);
289 glColor3f(1.0,1.0,1.0);
290 glNormal3f(0.0,0.0,1.0);
291 for(x
=-BASESIZE
/2.0,i
=0;i
<BASERES
;x
+=dx
,i
++) {
295 glTexCoord2f(x
,y
+dy
);
296 glVertex3f(x
,y
+dy
,0.0);
302 static void drawteapot(void)
304 static const GLfloat amb
[4] = { 0.2, 0.2, 0.2, 1 };
305 static const GLfloat diff
[4] = { 0.8, 0.3, 0.5, 1 };
306 static float xrot
=0.0;
307 static float zrot
=0.0;
309 glMaterialfv(GL_FRONT_AND_BACK
, GL_AMBIENT
, amb
);
310 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, diff
);
313 glRotatef(lightalpha
,0.0,0.0,1.0);
314 glMultMatrixf((GLfloat
*)baseshadow
);
315 glRotatef(-lightalpha
,0.0,0.0,1.0);
317 glTranslatef(0.0,0.0,1.0);
318 glRotatef(xrot
,1.0,0.0,0.0);
319 glRotatef(zrot
,0.0,0.0,1.0);
321 glDisable(GL_TEXTURE_2D
);
322 glDisable(GL_DEPTH_TEST
);
323 glDisable(GL_LIGHTING
);
325 glColor3f(0.0,0.0,0.0);
326 glCallList(teapotdlist
);
328 glEnable(GL_DEPTH_TEST
);
329 glEnable(GL_LIGHTING
);
331 glEnable(GL_TEXTURE_2D
);
336 glTranslatef(0.0,0.0,1.0);
337 glRotatef(xrot
,1.0,0.0,0.0);
338 glRotatef(zrot
,0.0,0.0,1.0);
340 glCallList(teapotdlist
);
347 static void drawlight1(void)
350 glRotatef(lightalpha
,0.0,0.0,1.0);
351 glLightfv(GL_LIGHT0
,GL_POSITION
,lightpos
);
352 glLightfv(GL_LIGHT0
,GL_SPOT_DIRECTION
,lightdir
);
357 static void drawlight2(void)
360 glRotatef(lightalpha
,0.0,0.0,1.0);
361 glTranslatef(lightpos
[0],lightpos
[1],lightpos
[2]);
363 glDisable(GL_TEXTURE_2D
);
364 glCallList(lightdlist
);
366 glEnable(GL_TEXTURE_2D
);
373 static void dojoy(void)
376 static UINT max
[2]={0,0};
377 static UINT min
[2]={0xffffffff,0xffffffff},center
[2];
381 res
=joyGetPos(JOYSTICKID1
,&joy
);
383 if(res
==JOYERR_NOERROR
) {
390 center
[0]=(max
[0]+min
[0])/2;
396 center
[1]=(max
[1]+min
[1])/2;
399 if(fabs(center
[0]-(float)joy
.wXpos
)>0.1*(max
[0]-min
[0]))
400 alpha
-=2.5*(center
[0]-(float)joy
.wXpos
)/(max
[0]-min
[0]);
401 if(fabs(center
[1]-(float)joy
.wYpos
)>0.1*(max
[1]-min
[1]))
402 beta
+=2.5*(center
[1]-(float)joy
.wYpos
)/(max
[1]-min
[1]);
404 if(joy
.wButtons
& JOY_BUTTON1
)
406 if(joy
.wButtons
& JOY_BUTTON2
)
414 static void draw(void)
416 static char frbuf
[80] = "";
420 glEnable(GL_DEPTH_TEST
);
421 glClear(GL_COLOR_BUFFER_BIT
|GL_DEPTH_BUFFER_BIT
);
424 glEnable(GL_TEXTURE_2D
);
426 glDisable(GL_TEXTURE_2D
);
433 glEnable(GL_LIGHTING
);
435 glShadeModel(GL_SMOOTH
);
440 gluLookAt(obs
[0],obs
[1],obs
[2],
441 obs
[0]+dir
[0],obs
[1]+dir
[1],obs
[2]+dir
[2],
445 glCallList(basedlist
);
450 glDisable(GL_LIGHTING
);
451 glDisable(GL_TEXTURE_2D
);
452 glDisable(GL_DEPTH_TEST
);
454 glShadeModel(GL_FLAT
);
456 glMatrixMode(GL_PROJECTION
);
458 glOrtho(-0.5,639.5,-0.5,479.5,-1.0,1.0);
459 glMatrixMode(GL_MODELVIEW
);
462 glColor3f(1.0,0.0,0.0);
463 glRasterPos2i(10,10);
464 printstring(GLUT_BITMAP_HELVETICA_18
,frbuf
);
465 glRasterPos2i(350,470);
466 printstring(GLUT_BITMAP_HELVETICA_10
,"Teapot V1.2 Written by David Bucciarelli (tech.hmw@plus.it)");
471 reshape(WIDTH
,HEIGHT
);
478 GLint t
= glutGet(GLUT_ELAPSED_TIME
);
479 if (t
- T0
>= 2000) {
480 GLfloat seconds
= (t
- T0
) / 1000.0;
481 GLfloat fps
= Frames
/ seconds
;
482 sprintf(frbuf
, "Frame rate: %f", fps
);
489 static void inittextures(void)
491 glGenTextures(1,&t1id
);
492 glBindTexture(GL_TEXTURE_2D
,t1id
);
494 glPixelStorei(GL_UNPACK_ALIGNMENT
,4);
495 if (!LoadRGBMipmaps("../images/tile.rgb", GL_RGB
)) {
496 fprintf(stderr
,"Error reading a texture.\n");
500 glTexParameterf(GL_TEXTURE_2D
,GL_TEXTURE_WRAP_S
,GL_REPEAT
);
501 glTexParameterf(GL_TEXTURE_2D
,GL_TEXTURE_WRAP_T
,GL_REPEAT
);
503 glTexParameterf(GL_TEXTURE_2D
,GL_TEXTURE_MIN_FILTER
,GL_LINEAR_MIPMAP_LINEAR
);
504 glTexParameterf(GL_TEXTURE_2D
,GL_TEXTURE_MAG_FILTER
,GL_LINEAR
);
506 glTexEnvf(GL_TEXTURE_ENV
,GL_TEXTURE_ENV_MODE
,GL_MODULATE
);
508 glGenTextures(1,&t2id
);
509 glBindTexture(GL_TEXTURE_2D
,t2id
);
511 glPixelTransferf(GL_RED_SCALE
, 0.75);
512 glPixelTransferf(GL_RED_BIAS
, 0.25);
513 glPixelTransferf(GL_GREEN_SCALE
, 0.75);
514 glPixelTransferf(GL_GREEN_BIAS
, 0.25);
515 glPixelTransferf(GL_BLUE_SCALE
, 0.75);
516 glPixelTransferf(GL_BLUE_BIAS
, 0.25);
518 if (!LoadRGBMipmaps("../images/bw.rgb", GL_RGB
)) {
519 fprintf(stderr
,"Error reading a texture.\n");
523 glPixelTransferf(GL_RED_SCALE
, 1.0);
524 glPixelTransferf(GL_RED_BIAS
, 0.0);
525 glPixelTransferf(GL_GREEN_SCALE
, 1.0);
526 glPixelTransferf(GL_GREEN_BIAS
, 0.0);
527 glPixelTransferf(GL_BLUE_SCALE
, 1.0);
528 glPixelTransferf(GL_BLUE_BIAS
, 0.0);
531 glTexParameterf(GL_TEXTURE_2D
,GL_TEXTURE_WRAP_S
,GL_REPEAT
);
532 glTexParameterf(GL_TEXTURE_2D
,GL_TEXTURE_WRAP_T
,GL_REPEAT
);
534 glTexParameterf(GL_TEXTURE_2D
,GL_TEXTURE_MIN_FILTER
,GL_LINEAR_MIPMAP_LINEAR
);
535 glTexParameterf(GL_TEXTURE_2D
,GL_TEXTURE_MAG_FILTER
,GL_LINEAR
);
537 glTexEnvf(GL_TEXTURE_ENV
,GL_TEXTURE_ENV_MODE
,GL_MODULATE
);
540 static void initlight(void)
542 float matamb
[4] ={0.5, 0.5, 0.5, 1.0};
543 float matdiff
[4]={0.9, 0.2, 0.2, 1.0};
544 float matspec
[4]={1.0,1.0,1.0,1.0};
546 float lamb
[4] ={1.5, 1.5, 1.5, 1.0};
547 float ldiff
[4]={1.0, 1.0, 1.0, 1.0};
548 float lspec
[4]={1.0, 1.0, 1.0, 1.0};
550 glLightf(GL_LIGHT0
,GL_SPOT_CUTOFF
,70.0);
551 glLightf(GL_LIGHT0
,GL_SPOT_EXPONENT
,20.0);
552 glLightfv(GL_LIGHT0
,GL_AMBIENT
,lamb
);
553 glLightfv(GL_LIGHT0
,GL_DIFFUSE
,ldiff
);
554 glLightfv(GL_LIGHT0
,GL_SPECULAR
,lspec
);
556 glMaterialf(GL_FRONT_AND_BACK
, GL_SHININESS
, 15.0);
557 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, matdiff
);
558 glMaterialfv(GL_FRONT_AND_BACK
, GL_SPECULAR
, matspec
);
559 glMaterialfv(GL_FRONT_AND_BACK
, GL_AMBIENT
, matamb
);
561 glLightModelfv(GL_LIGHT_MODEL_AMBIENT
, lamb
);
565 static void initdlists(void)
567 GLUquadricObj
*lcone
,*lbase
;
569 GLfloat v0
[3]={0.0,0.0,0.0};
570 GLfloat v1
[3]={1.0,0.0,0.0};
571 GLfloat v2
[3]={0.0,1.0,0.0};
573 findplane(plane
,v0
,v1
,v2
);
574 shadowmatrix(baseshadow
,plane
,lightpos
);
576 teapotdlist
=glGenLists(1);
577 glNewList(teapotdlist
,GL_COMPILE
);
578 glRotatef(90.0,1.0,0.0,0.0);
579 glCullFace(GL_FRONT
);
580 glBindTexture(GL_TEXTURE_2D
,t2id
);
581 glutSolidTeapot(0.75);
585 basedlist
=glGenLists(1);
586 glNewList(basedlist
,GL_COMPILE
);
590 lightdlist
=glGenLists(1);
591 glNewList(lightdlist
,GL_COMPILE
);
592 glDisable(GL_LIGHTING
);
594 lcone
=gluNewQuadric();
595 lbase
=gluNewQuadric();
596 glRotatef(45.0,0.0,1.0,0.0);
598 glColor3f(1.0,1.0,1.0);
599 glCullFace(GL_FRONT
);
600 gluDisk(lbase
,0.0,0.2,12.0,1.0);
603 glColor3f(0.5,0.0,0.0);
604 gluCylinder(lcone
,0.2,0.0,0.5,12,1);
606 gluDeleteQuadric(lcone
);
607 gluDeleteQuadric(lbase
);
609 glEnable(GL_LIGHTING
);
613 int main(int ac
, char **av
)
615 float fogcolor
[4]={0.025,0.025,0.025,1.0};
617 fprintf(stderr
,"Teapot V1.2\nWritten by David Bucciarelli (tech.hmw@plus.it)\n");
620 if(!SetPriorityClass(GetCurrentProcess(),REALTIME_PRIORITY_CLASS)) {
621 fprintf(stderr,"Error setting the process class.\n");
625 if(!SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_TIME_CRITICAL)) {
626 fprintf(stderr,"Error setting the process priority.\n");
631 glutInitWindowPosition(0,0);
632 glutInitWindowSize(WIDTH
,HEIGHT
);
635 glutInitDisplayMode(GLUT_RGB
|GLUT_DEPTH
|GLUT_DOUBLE
);
637 if(!(win
=glutCreateWindow("Teapot"))) {
638 fprintf(stderr
,"Error, couldn't open window\n");
642 reshape(WIDTH
,HEIGHT
);
644 glShadeModel(GL_SMOOTH
);
645 glEnable(GL_DEPTH_TEST
);
646 glEnable(GL_CULL_FACE
);
647 glEnable(GL_TEXTURE_2D
);
650 glFogi(GL_FOG_MODE
,GL_EXP2
);
651 glFogfv(GL_FOG_COLOR
,fogcolor
);
653 glFogf(GL_FOG_DENSITY
,0.04);
654 glHint(GL_FOG_HINT
,GL_NICEST
);
655 glBlendFunc(GL_SRC_ALPHA
,GL_ONE_MINUS_SRC_ALPHA
);
664 glClearColor(fogcolor
[0],fogcolor
[1],fogcolor
[2],fogcolor
[3]);
666 glutReshapeFunc(reshape
);
667 glutDisplayFunc(draw
);
668 glutKeyboardFunc(key
);
669 glutSpecialFunc(special
);