blob: 93d1fcba5f7ed3ea4c83ab9754d1e918d5968897 [file] [log] [blame]
Brian Paul5b0a7f32000-06-27 16:52:38 +00001/*
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
14#ifdef WIN32
15#include <windows.h>
16#endif
17
18#include <GL/glut.h>
19#include "../util/readtex.c"
20#include "shadow.c"
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
Brian Pauld49b34a2000-09-12 18:44:45 +000030static GLint T0 = 0;
31static GLint Frames = 0;
Brian Paul5b0a7f32000-06-27 16:52:38 +000032
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
Brian Paul5b0a7f32000-06-27 16:52:38 +000069static void calcposobs(void)
70{
71 dir[0]=sin(alpha*M_PI/180.0);
72 dir[1]=cos(alpha*M_PI/180.0)*sin(beta*M_PI/180.0);
73 dir[2]=cos(beta*M_PI/180.0);
74
75 obs[0]+=v*dir[0];
76 obs[1]+=v*dir[1];
77 obs[2]+=v*dir[2];
78}
79
80static void special(int k, int x, int y)
81{
82 switch(k) {
83 case GLUT_KEY_LEFT:
84 alpha-=2.0;
85 break;
86 case GLUT_KEY_RIGHT:
87 alpha+=2.0;
88 break;
89 case GLUT_KEY_DOWN:
90 beta-=2.0;
91 break;
92 case GLUT_KEY_UP:
93 beta+=2.0;
94 break;
95 }
96}
97
98static void key(unsigned char k, int x, int y)
99{
100 switch(k) {
101 case 27:
102 exit(0);
103 break;
104
105 case 'a':
106 v+=0.005;
107 break;
108 case 'z':
109 v-=0.005;
110 break;
111
112 case 'j':
113 joyactive=(!joyactive);
114 break;
115 case 'h':
116 help=(!help);
117 break;
118 case 'f':
119 fog=(!fog);
120 break;
121 case 't':
122 usetex=(!usetex);
123 break;
124 case 'b':
125 if(bfcull) {
126 glDisable(GL_CULL_FACE);
127 bfcull=0;
128 } else {
129 glEnable(GL_CULL_FACE);
130 bfcull=1;
131 }
132 break;
133#ifdef XMESA
134 case ' ':
135 XMesaSetFXmode(fullscreen ? XMESA_FX_FULLSCREEN : XMESA_FX_WINDOW);
136 fullscreen=(!fullscreen);
137 break;
138#endif
139 }
140}
141
142static void reshape(int w, int h)
143{
144 WIDTH=w;
145 HEIGHT=h;
146 glMatrixMode(GL_PROJECTION);
147 glLoadIdentity();
148 gluPerspective(45.0,w/(float)h,0.2,40.0);
149 glMatrixMode(GL_MODELVIEW);
150 glLoadIdentity();
151 glViewport(0,0,w,h);
152}
153
154static void printstring(void *font, char *string)
155{
156 int len,i;
157
158 len=(int)strlen(string);
159 for(i=0;i<len;i++)
160 glutBitmapCharacter(font,string[i]);
161}
162
163static void printhelp(void)
164{
165 glEnable(GL_BLEND);
166 glColor4f(0.5,0.5,0.5,0.5);
167 glRecti(40,40,600,440);
168 glDisable(GL_BLEND);
169
170 glColor3f(1.0,0.0,0.0);
171 glRasterPos2i(300,420);
172 printstring(GLUT_BITMAP_TIMES_ROMAN_24,"Help");
173
174 glRasterPos2i(60,390);
175 printstring(GLUT_BITMAP_TIMES_ROMAN_24,"h - Togle Help");
176 glRasterPos2i(60,360);
177 printstring(GLUT_BITMAP_TIMES_ROMAN_24,"t - Togle Textures");
178 glRasterPos2i(60,330);
179 printstring(GLUT_BITMAP_TIMES_ROMAN_24,"f - Togle Fog");
180 glRasterPos2i(60,300);
181 printstring(GLUT_BITMAP_TIMES_ROMAN_24,"b - Togle Back face culling");
182 glRasterPos2i(60,270);
183 printstring(GLUT_BITMAP_TIMES_ROMAN_24,"Arrow Keys - Rotate");
184 glRasterPos2i(60,240);
185 printstring(GLUT_BITMAP_TIMES_ROMAN_24,"a - Increase velocity");
186 glRasterPos2i(60,210);
187 printstring(GLUT_BITMAP_TIMES_ROMAN_24,"z - Decrease velocity");
188
189 glRasterPos2i(60,180);
190 if(joyavailable)
191 printstring(GLUT_BITMAP_TIMES_ROMAN_24,"j - Togle jostick control (Joystick control available)");
192 else
193 printstring(GLUT_BITMAP_TIMES_ROMAN_24,"(No Joystick control available)");
194}
195
196static void drawbase(void)
197{
Brian Paulfdf20332000-10-05 21:57:00 +0000198 static const GLfloat amb[4] = { 1, .5, 0.2, 1 };
199 static const GLfloat diff[4] = { 1, .4, 0.2, 1 };
Brian Paul5b0a7f32000-06-27 16:52:38 +0000200 int i,j;
201 float x,y,dx,dy;
202
203 glBindTexture(GL_TEXTURE_2D,t1id);
204
Brian Paulfdf20332000-10-05 21:57:00 +0000205 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, amb);
206 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diff);
Brian Paul5b0a7f32000-06-27 16:52:38 +0000207 dx=BASESIZE/BASERES;
208 dy=-BASESIZE/BASERES;
209 for(y=BASESIZE/2.0,j=0;j<BASERES;y+=dy,j++) {
210 glBegin(GL_QUAD_STRIP);
211 glColor3f(1.0,1.0,1.0);
212 glNormal3f(0.0,0.0,1.0);
213 for(x=-BASESIZE/2.0,i=0;i<BASERES;x+=dx,i++) {
214 glTexCoord2f(x,y);
215 glVertex3f(x,y,0.0);
216
217 glTexCoord2f(x,y+dy);
218 glVertex3f(x,y+dy,0.0);
219 }
220 glEnd();
221 }
222}
223
224static void drawteapot(void)
225{
Brian Paulfdf20332000-10-05 21:57:00 +0000226 static const GLfloat amb[4] = { 0.2, 0.2, 0.2, 1 };
227 static const GLfloat diff[4] = { 0.8, 0.3, 0.5, 1 };
Brian Paul5b0a7f32000-06-27 16:52:38 +0000228 static float xrot=0.0;
229 static float zrot=0.0;
230
Brian Paulfdf20332000-10-05 21:57:00 +0000231 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, amb);
232 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diff);
233
Brian Paul5b0a7f32000-06-27 16:52:38 +0000234 glPushMatrix();
235 glRotatef(lightalpha,0.0,0.0,1.0);
236 glMultMatrixf((GLfloat *)baseshadow);
237 glRotatef(-lightalpha,0.0,0.0,1.0);
238
239 glTranslatef(0.0,0.0,1.0);
240 glRotatef(xrot,1.0,0.0,0.0);
241 glRotatef(zrot,0.0,0.0,1.0);
242
243 glDisable(GL_TEXTURE_2D);
244 glDisable(GL_DEPTH_TEST);
245 glDisable(GL_LIGHTING);
246
247 glColor3f(0.0,0.0,0.0);
248 glCallList(teapotdlist);
249
250 glEnable(GL_DEPTH_TEST);
251 glEnable(GL_LIGHTING);
252 if(usetex)
253 glEnable(GL_TEXTURE_2D);
254
255 glPopMatrix();
256
257 glPushMatrix();
258 glTranslatef(0.0,0.0,1.0);
259 glRotatef(xrot,1.0,0.0,0.0);
260 glRotatef(zrot,0.0,0.0,1.0);
261
262 glCallList(teapotdlist);
263 glPopMatrix();
264
265 xrot+=2.0;
266 zrot+=1.0;
267}
268
269static void drawlight1(void)
270{
271 glPushMatrix();
272 glRotatef(lightalpha,0.0,0.0,1.0);
273 glLightfv(GL_LIGHT0,GL_POSITION,lightpos);
274 glLightfv(GL_LIGHT0,GL_SPOT_DIRECTION,lightdir);
275
276 glPopMatrix();
277}
278
279static void drawlight2(void)
280{
281 glPushMatrix();
282 glRotatef(lightalpha,0.0,0.0,1.0);
283 glTranslatef(lightpos[0],lightpos[1],lightpos[2]);
284
285 glDisable(GL_TEXTURE_2D);
286 glCallList(lightdlist);
287 if(usetex)
288 glEnable(GL_TEXTURE_2D);
289
290 glPopMatrix();
291
292 lightalpha+=1.0;
293}
294
295static void dojoy(void)
296{
297#ifdef WIN32
298 static UINT max[2]={0,0};
299 static UINT min[2]={0xffffffff,0xffffffff},center[2];
300 MMRESULT res;
301 JOYINFO joy;
302
303 res=joyGetPos(JOYSTICKID1,&joy);
304
305 if(res==JOYERR_NOERROR) {
306 joyavailable=1;
307
308 if(max[0]<joy.wXpos)
309 max[0]=joy.wXpos;
310 if(min[0]>joy.wXpos)
311 min[0]=joy.wXpos;
312 center[0]=(max[0]+min[0])/2;
313
314 if(max[1]<joy.wYpos)
315 max[1]=joy.wYpos;
316 if(min[1]>joy.wYpos)
317 min[1]=joy.wYpos;
318 center[1]=(max[1]+min[1])/2;
319
320 if(joyactive) {
321 if(fabs(center[0]-(float)joy.wXpos)>0.1*(max[0]-min[0]))
322 alpha-=2.5*(center[0]-(float)joy.wXpos)/(max[0]-min[0]);
323 if(fabs(center[1]-(float)joy.wYpos)>0.1*(max[1]-min[1]))
324 beta+=2.5*(center[1]-(float)joy.wYpos)/(max[1]-min[1]);
325
326 if(joy.wButtons & JOY_BUTTON1)
327 v+=0.005;
328 if(joy.wButtons & JOY_BUTTON2)
329 v-=0.005;
330 }
331 } else
332 joyavailable=0;
333#endif
334}
335
336static void draw(void)
337{
Brian Pauld49b34a2000-09-12 18:44:45 +0000338 static char frbuf[80] = "";
Brian Paul5b0a7f32000-06-27 16:52:38 +0000339
340 dojoy();
341
342 glEnable(GL_DEPTH_TEST);
343 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
344
345 if(usetex)
346 glEnable(GL_TEXTURE_2D);
347 else
348 glDisable(GL_TEXTURE_2D);
349
350 if(fog)
351 glEnable(GL_FOG);
352 else
353 glDisable(GL_FOG);
354
355 glEnable(GL_LIGHTING);
356
357 glShadeModel(GL_SMOOTH);
358
359 glPushMatrix();
360 calcposobs();
361
362 gluLookAt(obs[0],obs[1],obs[2],
363 obs[0]+dir[0],obs[1]+dir[1],obs[2]+dir[2],
364 0.0,0.0,1.0);
365
366 drawlight1();
367 glCallList(basedlist);
368 drawteapot();
369 drawlight2();
370 glPopMatrix();
371
Brian Paul5b0a7f32000-06-27 16:52:38 +0000372 glDisable(GL_LIGHTING);
373 glDisable(GL_TEXTURE_2D);
374 glDisable(GL_DEPTH_TEST);
375 glDisable(GL_FOG);
376 glShadeModel(GL_FLAT);
377
378 glMatrixMode(GL_PROJECTION);
379 glLoadIdentity();
380 glOrtho(-0.5,639.5,-0.5,479.5,-1.0,1.0);
381 glMatrixMode(GL_MODELVIEW);
382 glLoadIdentity();
383
384 glColor3f(1.0,0.0,0.0);
385 glRasterPos2i(10,10);
386 printstring(GLUT_BITMAP_HELVETICA_18,frbuf);
387 glRasterPos2i(350,470);
388 printstring(GLUT_BITMAP_HELVETICA_10,"Teapot V1.2 Written by David Bucciarelli (tech.hmw@plus.it)");
389
390 if(help)
391 printhelp();
392
393 reshape(WIDTH,HEIGHT);
394
395 glutSwapBuffers();
396
Brian Pauld49b34a2000-09-12 18:44:45 +0000397 Frames++;
398
399 {
400 GLint t = glutGet(GLUT_ELAPSED_TIME);
401 if (t - T0 >= 2000) {
402 GLfloat seconds = (t - T0) / 1000.0;
403 GLfloat fps = Frames / seconds;
404 sprintf(frbuf, "Frame rate: %f", fps);
405 T0 = t;
406 Frames = 0;
407 }
408 }
Brian Paul5b0a7f32000-06-27 16:52:38 +0000409}
410
411static void inittextures(void)
412{
Brian Paul5b0a7f32000-06-27 16:52:38 +0000413 glGenTextures(1,&t1id);
414 glBindTexture(GL_TEXTURE_2D,t1id);
415
416 glPixelStorei(GL_UNPACK_ALIGNMENT,4);
417 if (!LoadRGBMipmaps("../images/tile.rgb", GL_RGB)) {
418 fprintf(stderr,"Error reading a texture.\n");
419 exit(-1);
420 }
421
422 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
423 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
424
425 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
426 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
427
428 glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
429
430 glGenTextures(1,&t2id);
431 glBindTexture(GL_TEXTURE_2D,t2id);
432
Brian Paulfdf20332000-10-05 21:57:00 +0000433 glPixelTransferf(GL_RED_SCALE, 0.75);
434 glPixelTransferf(GL_RED_BIAS, 0.25);
435 glPixelTransferf(GL_GREEN_SCALE, 0.75);
436 glPixelTransferf(GL_GREEN_BIAS, 0.25);
437 glPixelTransferf(GL_BLUE_SCALE, 0.75);
438 glPixelTransferf(GL_BLUE_BIAS, 0.25);
439
Brian Paul5b0a7f32000-06-27 16:52:38 +0000440 if (!LoadRGBMipmaps("../images/bw.rgb", GL_RGB)) {
441 fprintf(stderr,"Error reading a texture.\n");
442 exit(-1);
443 }
444
Brian Paulfdf20332000-10-05 21:57:00 +0000445 glPixelTransferf(GL_RED_SCALE, 1.0);
446 glPixelTransferf(GL_RED_BIAS, 0.0);
447 glPixelTransferf(GL_GREEN_SCALE, 1.0);
448 glPixelTransferf(GL_GREEN_BIAS, 0.0);
449 glPixelTransferf(GL_BLUE_SCALE, 1.0);
450 glPixelTransferf(GL_BLUE_BIAS, 0.0);
451
452
Brian Paul5b0a7f32000-06-27 16:52:38 +0000453 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
454 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
455
456 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
457 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
458
459 glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
460}
461
462static void initlight(void)
463{
Brian Paulfdf20332000-10-05 21:57:00 +0000464 float matamb[4] ={0.5, 0.5, 0.5, 1.0};
465 float matdiff[4]={0.9, 0.2, 0.2, 1.0};
466 float matspec[4]={1.0,1.0,1.0,1.0};
467
468 float lamb[4] ={1.5, 1.5, 1.5, 1.0};
469 float ldiff[4]={1.0, 1.0, 1.0, 1.0};
470 float lspec[4]={1.0, 1.0, 1.0, 1.0};
Brian Paul5b0a7f32000-06-27 16:52:38 +0000471
472 glLightf(GL_LIGHT0,GL_SPOT_CUTOFF,70.0);
473 glLightf(GL_LIGHT0,GL_SPOT_EXPONENT,20.0);
474 glLightfv(GL_LIGHT0,GL_AMBIENT,lamb);
Brian Paulfdf20332000-10-05 21:57:00 +0000475 glLightfv(GL_LIGHT0,GL_DIFFUSE,ldiff);
Brian Paul5b0a7f32000-06-27 16:52:38 +0000476 glLightfv(GL_LIGHT0,GL_SPECULAR,lspec);
477
Brian Paulfdf20332000-10-05 21:57:00 +0000478 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 15.0);
479 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, matdiff);
480 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, matspec);
481 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, matamb);
Brian Paul5b0a7f32000-06-27 16:52:38 +0000482
Brian Paulfdf20332000-10-05 21:57:00 +0000483 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lamb);
Brian Paul5b0a7f32000-06-27 16:52:38 +0000484 glEnable(GL_LIGHT0);
485}
486
487static void initdlists(void)
488{
489 GLUquadricObj *lcone,*lbase;
490 GLfloat plane[4];
491 GLfloat v0[3]={0.0,0.0,0.0};
492 GLfloat v1[3]={1.0,0.0,0.0};
493 GLfloat v2[3]={0.0,1.0,0.0};
494
495 findplane(plane,v0,v1,v2);
496 shadowmatrix(baseshadow,plane,lightpos);
497
498 teapotdlist=glGenLists(1);
499 glNewList(teapotdlist,GL_COMPILE);
500 glRotatef(90.0,1.0,0.0,0.0);
501 glCullFace(GL_FRONT);
502 glBindTexture(GL_TEXTURE_2D,t2id);
503 glutSolidTeapot(0.75);
504 glCullFace(GL_BACK);
505 glEndList();
506
507 basedlist=glGenLists(1);
508 glNewList(basedlist,GL_COMPILE);
509 drawbase();
510 glEndList();
511
512 lightdlist=glGenLists(1);
513 glNewList(lightdlist,GL_COMPILE);
514 glDisable(GL_LIGHTING);
515
516 lcone=gluNewQuadric();
517 lbase=gluNewQuadric();
518 glRotatef(45.0,0.0,1.0,0.0);
519
520 glColor3f(1.0,1.0,1.0);
521 glCullFace(GL_FRONT);
522 gluDisk(lbase,0.0,0.2,12.0,1.0);
523 glCullFace(GL_BACK);
524
525 glColor3f(0.5,0.0,0.0);
526 gluCylinder(lcone,0.2,0.0,0.5,12,1);
527
528 gluDeleteQuadric(lcone);
529 gluDeleteQuadric(lbase);
530
531 glEnable(GL_LIGHTING);
532 glEndList();
533}
534
535int main(int ac, char **av)
536{
537 float fogcolor[4]={0.025,0.025,0.025,1.0};
538
539 fprintf(stderr,"Teapot V1.2\nWritten by David Bucciarelli (tech.hmw@plus.it)\n");
540
541 /*
542 if(!SetPriorityClass(GetCurrentProcess(),REALTIME_PRIORITY_CLASS)) {
543 fprintf(stderr,"Error setting the process class.\n");
544 return 0;
545 }
546
547 if(!SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_TIME_CRITICAL)) {
548 fprintf(stderr,"Error setting the process priority.\n");
549 return 0;
550 }
551 */
552
553 glutInitWindowPosition(0,0);
554 glutInitWindowSize(WIDTH,HEIGHT);
555 glutInit(&ac,av);
556
557 glutInitDisplayMode(GLUT_RGB|GLUT_DEPTH|GLUT_DOUBLE);
558
559 if(!(win=glutCreateWindow("Teapot"))) {
560 fprintf(stderr,"Error, couldn't open window\n");
561 return -1;
562 }
563
564 reshape(WIDTH,HEIGHT);
565
566 glShadeModel(GL_SMOOTH);
567 glEnable(GL_DEPTH_TEST);
568 glEnable(GL_CULL_FACE);
569 glEnable(GL_TEXTURE_2D);
570
571 glEnable(GL_FOG);
572 glFogi(GL_FOG_MODE,GL_EXP2);
573 glFogfv(GL_FOG_COLOR,fogcolor);
574
575 glFogf(GL_FOG_DENSITY,0.04);
576 glHint(GL_FOG_HINT,GL_NICEST);
577 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
578
579 calcposobs();
580
581 inittextures();
582 initlight();
583
584 initdlists();
585
586 glClearColor(fogcolor[0],fogcolor[1],fogcolor[2],fogcolor[3]);
587
588 glutReshapeFunc(reshape);
589 glutDisplayFunc(draw);
590 glutKeyboardFunc(key);
591 glutSpecialFunc(special);
592 glutIdleFunc(draw);
593
594 glutMainLoop();
595
596 return 0;
597}