2 * This program is under the GNU GPL.
3 * Use at your own risk.
5 * written by David Bucciarelli (tech.hmw@plus.it)
23 static int fullscreen
=1;
27 static int HEIGHT
=480;
30 static GLint Frames
= 0;
38 #define M_PI 3.1415926535
41 extern void shadowmatrix(GLfloat
[4][4], GLfloat
[4], GLfloat
[4]);
42 extern void findplane(GLfloat
[4], GLfloat
[3], GLfloat
[3], GLfloat
[3]);
47 static float obs
[3]={5.0,0.0,1.0};
50 static float alpha
=-90.0;
51 static float beta
=90.0;
53 static GLfloat baseshadow
[4][4];
54 static GLfloat lightpos
[4]={2.3,0.0,3.0,1.0};
55 static GLfloat lightdir
[3]={-2.3,0.0,-3.0};
56 static GLfloat lightalpha
=0.0;
62 static int joyavailable
=0;
63 static int joyactive
=0;
65 static GLuint t1id
,t2id
;
66 static GLuint teapotdlist
,basedlist
,lightdlist
;
70 /******************** begin shadow code ********************/
72 /* Taken from the projshadow.c - by Tom McReynolds, SGI */
74 /* Modified by David Bucciarelli */
83 /* create a matrix that will project the desired shadow */
85 shadowmatrix(GLfloat shadowMat
[4][4],
86 GLfloat groundplane
[4],
91 /* find dot product between light position vector and ground plane normal */
92 dot
= groundplane
[X
] * lightpos
[X
] +
93 groundplane
[Y
] * lightpos
[Y
] +
94 groundplane
[Z
] * lightpos
[Z
] +
95 groundplane
[W
] * lightpos
[W
];
97 shadowMat
[0][0] = dot
- lightpos
[X
] * groundplane
[X
];
98 shadowMat
[1][0] = 0.f
- lightpos
[X
] * groundplane
[Y
];
99 shadowMat
[2][0] = 0.f
- lightpos
[X
] * groundplane
[Z
];
100 shadowMat
[3][0] = 0.f
- lightpos
[X
] * groundplane
[W
];
102 shadowMat
[X
][1] = 0.f
- lightpos
[Y
] * groundplane
[X
];
103 shadowMat
[1][1] = dot
- lightpos
[Y
] * groundplane
[Y
];
104 shadowMat
[2][1] = 0.f
- lightpos
[Y
] * groundplane
[Z
];
105 shadowMat
[3][1] = 0.f
- lightpos
[Y
] * groundplane
[W
];
107 shadowMat
[X
][2] = 0.f
- lightpos
[Z
] * groundplane
[X
];
108 shadowMat
[1][2] = 0.f
- lightpos
[Z
] * groundplane
[Y
];
109 shadowMat
[2][2] = dot
- lightpos
[Z
] * groundplane
[Z
];
110 shadowMat
[3][2] = 0.f
- lightpos
[Z
] * groundplane
[W
];
112 shadowMat
[X
][3] = 0.f
- lightpos
[W
] * groundplane
[X
];
113 shadowMat
[1][3] = 0.f
- lightpos
[W
] * groundplane
[Y
];
114 shadowMat
[2][3] = 0.f
- lightpos
[W
] * groundplane
[Z
];
115 shadowMat
[3][3] = dot
- lightpos
[W
] * groundplane
[W
];
119 /* find the plane equation given 3 points */
121 findplane(GLfloat plane
[4],
122 GLfloat v0
[3], GLfloat v1
[3], GLfloat v2
[3])
124 GLfloat vec0
[3], vec1
[3];
126 /* need 2 vectors to find cross product */
127 vec0
[X
] = v1
[X
] - v0
[X
];
128 vec0
[Y
] = v1
[Y
] - v0
[Y
];
129 vec0
[Z
] = v1
[Z
] - v0
[Z
];
131 vec1
[X
] = v2
[X
] - v0
[X
];
132 vec1
[Y
] = v2
[Y
] - v0
[Y
];
133 vec1
[Z
] = v2
[Z
] - v0
[Z
];
135 /* find cross product to get A, B, and C of plane equation */
136 plane
[A
] = vec0
[Y
] * vec1
[Z
] - vec0
[Z
] * vec1
[Y
];
137 plane
[B
] = -(vec0
[X
] * vec1
[Z
] - vec0
[Z
] * vec1
[X
]);
138 plane
[C
] = vec0
[X
] * vec1
[Y
] - vec0
[Y
] * vec1
[X
];
140 plane
[D
] = -(plane
[A
] * v0
[X
] + plane
[B
] * v0
[Y
] + plane
[C
] * v0
[Z
]);
143 /******************** end shadow code ********************/
146 static void calcposobs(void)
148 dir
[0]=sin(alpha
*M_PI
/180.0);
149 dir
[1]=cos(alpha
*M_PI
/180.0)*sin(beta
*M_PI
/180.0);
150 dir
[2]=cos(beta
*M_PI
/180.0);
157 static void special(int k
, int x
, int y
)
175 static void key(unsigned char k
, int x
, int y
)
190 joyactive
=(!joyactive
);
203 glDisable(GL_CULL_FACE
);
206 glEnable(GL_CULL_FACE
);
212 XMesaSetFXmode(fullscreen
? XMESA_FX_FULLSCREEN
: XMESA_FX_WINDOW
);
213 fullscreen
=(!fullscreen
);
219 static void reshape(int w
, int h
)
223 glMatrixMode(GL_PROJECTION
);
225 gluPerspective(45.0,w
/(float)h
,0.2,40.0);
226 glMatrixMode(GL_MODELVIEW
);
231 static void printstring(void *font
, char *string
)
235 len
=(int)strlen(string
);
237 glutBitmapCharacter(font
,string
[i
]);
240 static void printhelp(void)
243 glColor4f(0.5,0.5,0.5,0.5);
244 glRecti(40,40,600,440);
247 glColor3f(1.0,0.0,0.0);
248 glRasterPos2i(300,420);
249 printstring(GLUT_BITMAP_TIMES_ROMAN_24
,"Help");
251 glRasterPos2i(60,390);
252 printstring(GLUT_BITMAP_TIMES_ROMAN_24
,"h - Togle Help");
253 glRasterPos2i(60,360);
254 printstring(GLUT_BITMAP_TIMES_ROMAN_24
,"t - Togle Textures");
255 glRasterPos2i(60,330);
256 printstring(GLUT_BITMAP_TIMES_ROMAN_24
,"f - Togle Fog");
257 glRasterPos2i(60,300);
258 printstring(GLUT_BITMAP_TIMES_ROMAN_24
,"b - Togle Back face culling");
259 glRasterPos2i(60,270);
260 printstring(GLUT_BITMAP_TIMES_ROMAN_24
,"Arrow Keys - Rotate");
261 glRasterPos2i(60,240);
262 printstring(GLUT_BITMAP_TIMES_ROMAN_24
,"a - Increase velocity");
263 glRasterPos2i(60,210);
264 printstring(GLUT_BITMAP_TIMES_ROMAN_24
,"z - Decrease velocity");
266 glRasterPos2i(60,180);
268 printstring(GLUT_BITMAP_TIMES_ROMAN_24
,"j - Togle jostick control (Joystick control available)");
270 printstring(GLUT_BITMAP_TIMES_ROMAN_24
,"(No Joystick control available)");
273 static void drawbase(void)
275 static const GLfloat amb
[4] = { 1, .5, 0.2, 1 };
276 static const GLfloat diff
[4] = { 1, .4, 0.2, 1 };
280 glBindTexture(GL_TEXTURE_2D
,t1id
);
282 glMaterialfv(GL_FRONT_AND_BACK
, GL_AMBIENT
, amb
);
283 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, diff
);
285 dy
=-BASESIZE
/BASERES
;
286 for(y
=BASESIZE
/2.0,j
=0;j
<BASERES
;y
+=dy
,j
++) {
287 glBegin(GL_QUAD_STRIP
);
288 glColor3f(1.0,1.0,1.0);
289 glNormal3f(0.0,0.0,1.0);
290 for(x
=-BASESIZE
/2.0,i
=0;i
<BASERES
;x
+=dx
,i
++) {
294 glTexCoord2f(x
,y
+dy
);
295 glVertex3f(x
,y
+dy
,0.0);
301 static void drawteapot(void)
303 static const GLfloat amb
[4] = { 0.2, 0.2, 0.2, 1 };
304 static const GLfloat diff
[4] = { 0.8, 0.3, 0.5, 1 };
305 static float xrot
=0.0;
306 static float zrot
=0.0;
308 glMaterialfv(GL_FRONT_AND_BACK
, GL_AMBIENT
, amb
);
309 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, diff
);
312 glRotatef(lightalpha
,0.0,0.0,1.0);
313 glMultMatrixf((GLfloat
*)baseshadow
);
314 glRotatef(-lightalpha
,0.0,0.0,1.0);
316 glTranslatef(0.0,0.0,1.0);
317 glRotatef(xrot
,1.0,0.0,0.0);
318 glRotatef(zrot
,0.0,0.0,1.0);
320 glDisable(GL_TEXTURE_2D
);
321 glDisable(GL_DEPTH_TEST
);
322 glDisable(GL_LIGHTING
);
324 glColor3f(0.0,0.0,0.0);
325 glCallList(teapotdlist
);
327 glEnable(GL_DEPTH_TEST
);
328 glEnable(GL_LIGHTING
);
330 glEnable(GL_TEXTURE_2D
);
335 glTranslatef(0.0,0.0,1.0);
336 glRotatef(xrot
,1.0,0.0,0.0);
337 glRotatef(zrot
,0.0,0.0,1.0);
339 glCallList(teapotdlist
);
346 static void drawlight1(void)
349 glRotatef(lightalpha
,0.0,0.0,1.0);
350 glLightfv(GL_LIGHT0
,GL_POSITION
,lightpos
);
351 glLightfv(GL_LIGHT0
,GL_SPOT_DIRECTION
,lightdir
);
356 static void drawlight2(void)
359 glRotatef(lightalpha
,0.0,0.0,1.0);
360 glTranslatef(lightpos
[0],lightpos
[1],lightpos
[2]);
362 glDisable(GL_TEXTURE_2D
);
363 glCallList(lightdlist
);
365 glEnable(GL_TEXTURE_2D
);
372 static void dojoy(void)
375 static UINT max
[2]={0,0};
376 static UINT min
[2]={0xffffffff,0xffffffff},center
[2];
380 res
=joyGetPos(JOYSTICKID1
,&joy
);
382 if(res
==JOYERR_NOERROR
) {
389 center
[0]=(max
[0]+min
[0])/2;
395 center
[1]=(max
[1]+min
[1])/2;
398 if(fabs(center
[0]-(float)joy
.wXpos
)>0.1*(max
[0]-min
[0]))
399 alpha
-=2.5*(center
[0]-(float)joy
.wXpos
)/(max
[0]-min
[0]);
400 if(fabs(center
[1]-(float)joy
.wYpos
)>0.1*(max
[1]-min
[1]))
401 beta
+=2.5*(center
[1]-(float)joy
.wYpos
)/(max
[1]-min
[1]);
403 if(joy
.wButtons
& JOY_BUTTON1
)
405 if(joy
.wButtons
& JOY_BUTTON2
)
413 static void draw(void)
415 static char frbuf
[80] = "";
419 glEnable(GL_DEPTH_TEST
);
420 glClear(GL_COLOR_BUFFER_BIT
|GL_DEPTH_BUFFER_BIT
);
423 glEnable(GL_TEXTURE_2D
);
425 glDisable(GL_TEXTURE_2D
);
432 glEnable(GL_LIGHTING
);
434 glShadeModel(GL_SMOOTH
);
439 gluLookAt(obs
[0],obs
[1],obs
[2],
440 obs
[0]+dir
[0],obs
[1]+dir
[1],obs
[2]+dir
[2],
444 glCallList(basedlist
);
449 glDisable(GL_LIGHTING
);
450 glDisable(GL_TEXTURE_2D
);
451 glDisable(GL_DEPTH_TEST
);
453 glShadeModel(GL_FLAT
);
455 glMatrixMode(GL_PROJECTION
);
457 glOrtho(-0.5,639.5,-0.5,479.5,-1.0,1.0);
458 glMatrixMode(GL_MODELVIEW
);
461 glColor3f(1.0,0.0,0.0);
462 glRasterPos2i(10,10);
463 printstring(GLUT_BITMAP_HELVETICA_18
,frbuf
);
464 glRasterPos2i(350,470);
465 printstring(GLUT_BITMAP_HELVETICA_10
,"Teapot V1.2 Written by David Bucciarelli (tech.hmw@plus.it)");
470 reshape(WIDTH
,HEIGHT
);
477 GLint t
= glutGet(GLUT_ELAPSED_TIME
);
478 if (t
- T0
>= 2000) {
479 GLfloat seconds
= (t
- T0
) / 1000.0;
480 GLfloat fps
= Frames
/ seconds
;
481 sprintf(frbuf
, "Frame rate: %f", fps
);
488 static void inittextures(void)
490 glGenTextures(1,&t1id
);
491 glBindTexture(GL_TEXTURE_2D
,t1id
);
493 glPixelStorei(GL_UNPACK_ALIGNMENT
,4);
494 if (!LoadRGBMipmaps("../images/tile.rgb", GL_RGB
)) {
495 fprintf(stderr
,"Error reading a texture.\n");
499 glTexParameterf(GL_TEXTURE_2D
,GL_TEXTURE_WRAP_S
,GL_REPEAT
);
500 glTexParameterf(GL_TEXTURE_2D
,GL_TEXTURE_WRAP_T
,GL_REPEAT
);
502 glTexParameterf(GL_TEXTURE_2D
,GL_TEXTURE_MIN_FILTER
,GL_LINEAR_MIPMAP_LINEAR
);
503 glTexParameterf(GL_TEXTURE_2D
,GL_TEXTURE_MAG_FILTER
,GL_LINEAR
);
505 glTexEnvf(GL_TEXTURE_ENV
,GL_TEXTURE_ENV_MODE
,GL_MODULATE
);
507 glGenTextures(1,&t2id
);
508 glBindTexture(GL_TEXTURE_2D
,t2id
);
510 glPixelTransferf(GL_RED_SCALE
, 0.75);
511 glPixelTransferf(GL_RED_BIAS
, 0.25);
512 glPixelTransferf(GL_GREEN_SCALE
, 0.75);
513 glPixelTransferf(GL_GREEN_BIAS
, 0.25);
514 glPixelTransferf(GL_BLUE_SCALE
, 0.75);
515 glPixelTransferf(GL_BLUE_BIAS
, 0.25);
517 if (!LoadRGBMipmaps("../images/bw.rgb", GL_RGB
)) {
518 fprintf(stderr
,"Error reading a texture.\n");
522 glPixelTransferf(GL_RED_SCALE
, 1.0);
523 glPixelTransferf(GL_RED_BIAS
, 0.0);
524 glPixelTransferf(GL_GREEN_SCALE
, 1.0);
525 glPixelTransferf(GL_GREEN_BIAS
, 0.0);
526 glPixelTransferf(GL_BLUE_SCALE
, 1.0);
527 glPixelTransferf(GL_BLUE_BIAS
, 0.0);
530 glTexParameterf(GL_TEXTURE_2D
,GL_TEXTURE_WRAP_S
,GL_REPEAT
);
531 glTexParameterf(GL_TEXTURE_2D
,GL_TEXTURE_WRAP_T
,GL_REPEAT
);
533 glTexParameterf(GL_TEXTURE_2D
,GL_TEXTURE_MIN_FILTER
,GL_LINEAR_MIPMAP_LINEAR
);
534 glTexParameterf(GL_TEXTURE_2D
,GL_TEXTURE_MAG_FILTER
,GL_LINEAR
);
536 glTexEnvf(GL_TEXTURE_ENV
,GL_TEXTURE_ENV_MODE
,GL_MODULATE
);
539 static void initlight(void)
541 float matamb
[4] ={0.5, 0.5, 0.5, 1.0};
542 float matdiff
[4]={0.9, 0.2, 0.2, 1.0};
543 float matspec
[4]={1.0,1.0,1.0,1.0};
545 float lamb
[4] ={1.5, 1.5, 1.5, 1.0};
546 float ldiff
[4]={1.0, 1.0, 1.0, 1.0};
547 float lspec
[4]={1.0, 1.0, 1.0, 1.0};
549 glLightf(GL_LIGHT0
,GL_SPOT_CUTOFF
,70.0);
550 glLightf(GL_LIGHT0
,GL_SPOT_EXPONENT
,20.0);
551 glLightfv(GL_LIGHT0
,GL_AMBIENT
,lamb
);
552 glLightfv(GL_LIGHT0
,GL_DIFFUSE
,ldiff
);
553 glLightfv(GL_LIGHT0
,GL_SPECULAR
,lspec
);
555 glMaterialf(GL_FRONT_AND_BACK
, GL_SHININESS
, 15.0);
556 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, matdiff
);
557 glMaterialfv(GL_FRONT_AND_BACK
, GL_SPECULAR
, matspec
);
558 glMaterialfv(GL_FRONT_AND_BACK
, GL_AMBIENT
, matamb
);
560 glLightModelfv(GL_LIGHT_MODEL_AMBIENT
, lamb
);
564 static void initdlists(void)
566 GLUquadricObj
*lcone
,*lbase
;
568 GLfloat v0
[3]={0.0,0.0,0.0};
569 GLfloat v1
[3]={1.0,0.0,0.0};
570 GLfloat v2
[3]={0.0,1.0,0.0};
572 findplane(plane
,v0
,v1
,v2
);
573 shadowmatrix(baseshadow
,plane
,lightpos
);
575 teapotdlist
=glGenLists(1);
576 glNewList(teapotdlist
,GL_COMPILE
);
577 glRotatef(90.0,1.0,0.0,0.0);
578 glCullFace(GL_FRONT
);
579 glBindTexture(GL_TEXTURE_2D
,t2id
);
580 glutSolidTeapot(0.75);
584 basedlist
=glGenLists(1);
585 glNewList(basedlist
,GL_COMPILE
);
589 lightdlist
=glGenLists(1);
590 glNewList(lightdlist
,GL_COMPILE
);
591 glDisable(GL_LIGHTING
);
593 lcone
=gluNewQuadric();
594 lbase
=gluNewQuadric();
595 glRotatef(45.0,0.0,1.0,0.0);
597 glColor3f(1.0,1.0,1.0);
598 glCullFace(GL_FRONT
);
599 gluDisk(lbase
,0.0,0.2,12.0,1.0);
602 glColor3f(0.5,0.0,0.0);
603 gluCylinder(lcone
,0.2,0.0,0.5,12,1);
605 gluDeleteQuadric(lcone
);
606 gluDeleteQuadric(lbase
);
608 glEnable(GL_LIGHTING
);
612 int main(int ac
, char **av
)
614 float fogcolor
[4]={0.025,0.025,0.025,1.0};
616 fprintf(stderr
,"Teapot V1.2\nWritten by David Bucciarelli (tech.hmw@plus.it)\n");
619 if(!SetPriorityClass(GetCurrentProcess(),REALTIME_PRIORITY_CLASS)) {
620 fprintf(stderr,"Error setting the process class.\n");
624 if(!SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_TIME_CRITICAL)) {
625 fprintf(stderr,"Error setting the process priority.\n");
630 glutInitWindowPosition(0,0);
631 glutInitWindowSize(WIDTH
,HEIGHT
);
634 glutInitDisplayMode(GLUT_RGB
|GLUT_DEPTH
|GLUT_DOUBLE
);
636 if(!(win
=glutCreateWindow("Teapot"))) {
637 fprintf(stderr
,"Error, couldn't open window\n");
641 reshape(WIDTH
,HEIGHT
);
643 glShadeModel(GL_SMOOTH
);
644 glEnable(GL_DEPTH_TEST
);
645 glEnable(GL_CULL_FACE
);
646 glEnable(GL_TEXTURE_2D
);
649 glFogi(GL_FOG_MODE
,GL_EXP2
);
650 glFogfv(GL_FOG_COLOR
,fogcolor
);
652 glFogf(GL_FOG_DENSITY
,0.04);
653 glHint(GL_FOG_HINT
,GL_NICEST
);
654 glBlendFunc(GL_SRC_ALPHA
,GL_ONE_MINUS_SRC_ALPHA
);
663 glClearColor(fogcolor
[0],fogcolor
[1],fogcolor
[2],fogcolor
[3]);
665 glutReshapeFunc(reshape
);
666 glutDisplayFunc(draw
);
667 glutKeyboardFunc(key
);
668 glutSpecialFunc(special
);