fixed compiler warnings
[mesa.git] / progs / demos / teapot.c
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
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"
24 static int fullscreen=1;
25 #endif
26
27 static int WIDTH=640;
28 static int HEIGHT=480;
29
30 #define FRAME 50
31
32 #define BASESIZE 10.0
33
34 #define BASERES 12
35 #define TEAPOTRES 3
36
37 #ifndef M_PI
38 #define M_PI 3.1415926535
39 #endif
40
41 extern void shadowmatrix(GLfloat [4][4], GLfloat [4], GLfloat [4]);
42 extern void findplane(GLfloat [4], GLfloat [3], GLfloat [3], GLfloat [3]);
43
44
45 static int win=0;
46
47 static float obs[3]={5.0,0.0,1.0};
48 static float dir[3];
49 static float v=0.0;
50 static float alpha=-90.0;
51 static float beta=90.0;
52
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;
57
58 static int fog=1;
59 static int bfcull=1;
60 static int usetex=1;
61 static int help=1;
62 static int joyavailable=0;
63 static int joyactive=0;
64
65 static GLuint t1id,t2id;
66 static GLuint teapotdlist,basedlist,lightdlist;
67
68 static float gettime(void)
69 {
70 static clock_t told=0;
71 clock_t tnew,ris;
72
73 tnew=clock();
74
75 ris=tnew-told;
76
77 told=tnew;
78
79 return(ris/(float)CLOCKS_PER_SEC);
80 }
81
82 static void calcposobs(void)
83 {
84 dir[0]=sin(alpha*M_PI/180.0);
85 dir[1]=cos(alpha*M_PI/180.0)*sin(beta*M_PI/180.0);
86 dir[2]=cos(beta*M_PI/180.0);
87
88 obs[0]+=v*dir[0];
89 obs[1]+=v*dir[1];
90 obs[2]+=v*dir[2];
91 }
92
93 static void special(int k, int x, int y)
94 {
95 switch(k) {
96 case GLUT_KEY_LEFT:
97 alpha-=2.0;
98 break;
99 case GLUT_KEY_RIGHT:
100 alpha+=2.0;
101 break;
102 case GLUT_KEY_DOWN:
103 beta-=2.0;
104 break;
105 case GLUT_KEY_UP:
106 beta+=2.0;
107 break;
108 }
109 }
110
111 static void key(unsigned char k, int x, int y)
112 {
113 switch(k) {
114 case 27:
115 exit(0);
116 break;
117
118 case 'a':
119 v+=0.005;
120 break;
121 case 'z':
122 v-=0.005;
123 break;
124
125 case 'j':
126 joyactive=(!joyactive);
127 break;
128 case 'h':
129 help=(!help);
130 break;
131 case 'f':
132 fog=(!fog);
133 break;
134 case 't':
135 usetex=(!usetex);
136 break;
137 case 'b':
138 if(bfcull) {
139 glDisable(GL_CULL_FACE);
140 bfcull=0;
141 } else {
142 glEnable(GL_CULL_FACE);
143 bfcull=1;
144 }
145 break;
146 #ifdef XMESA
147 case ' ':
148 XMesaSetFXmode(fullscreen ? XMESA_FX_FULLSCREEN : XMESA_FX_WINDOW);
149 fullscreen=(!fullscreen);
150 break;
151 #endif
152 }
153 }
154
155 static void reshape(int w, int h)
156 {
157 WIDTH=w;
158 HEIGHT=h;
159 glMatrixMode(GL_PROJECTION);
160 glLoadIdentity();
161 gluPerspective(45.0,w/(float)h,0.2,40.0);
162 glMatrixMode(GL_MODELVIEW);
163 glLoadIdentity();
164 glViewport(0,0,w,h);
165 }
166
167 static void printstring(void *font, char *string)
168 {
169 int len,i;
170
171 len=(int)strlen(string);
172 for(i=0;i<len;i++)
173 glutBitmapCharacter(font,string[i]);
174 }
175
176 static void printhelp(void)
177 {
178 glEnable(GL_BLEND);
179 glColor4f(0.5,0.5,0.5,0.5);
180 glRecti(40,40,600,440);
181 glDisable(GL_BLEND);
182
183 glColor3f(1.0,0.0,0.0);
184 glRasterPos2i(300,420);
185 printstring(GLUT_BITMAP_TIMES_ROMAN_24,"Help");
186
187 glRasterPos2i(60,390);
188 printstring(GLUT_BITMAP_TIMES_ROMAN_24,"h - Togle Help");
189 glRasterPos2i(60,360);
190 printstring(GLUT_BITMAP_TIMES_ROMAN_24,"t - Togle Textures");
191 glRasterPos2i(60,330);
192 printstring(GLUT_BITMAP_TIMES_ROMAN_24,"f - Togle Fog");
193 glRasterPos2i(60,300);
194 printstring(GLUT_BITMAP_TIMES_ROMAN_24,"b - Togle Back face culling");
195 glRasterPos2i(60,270);
196 printstring(GLUT_BITMAP_TIMES_ROMAN_24,"Arrow Keys - Rotate");
197 glRasterPos2i(60,240);
198 printstring(GLUT_BITMAP_TIMES_ROMAN_24,"a - Increase velocity");
199 glRasterPos2i(60,210);
200 printstring(GLUT_BITMAP_TIMES_ROMAN_24,"z - Decrease velocity");
201
202 glRasterPos2i(60,180);
203 if(joyavailable)
204 printstring(GLUT_BITMAP_TIMES_ROMAN_24,"j - Togle jostick control (Joystick control available)");
205 else
206 printstring(GLUT_BITMAP_TIMES_ROMAN_24,"(No Joystick control available)");
207 }
208
209 static void drawbase(void)
210 {
211 int i,j;
212 float x,y,dx,dy;
213
214 glBindTexture(GL_TEXTURE_2D,t1id);
215
216 dx=BASESIZE/BASERES;
217 dy=-BASESIZE/BASERES;
218 for(y=BASESIZE/2.0,j=0;j<BASERES;y+=dy,j++) {
219 glBegin(GL_QUAD_STRIP);
220 glColor3f(1.0,1.0,1.0);
221 glNormal3f(0.0,0.0,1.0);
222 for(x=-BASESIZE/2.0,i=0;i<BASERES;x+=dx,i++) {
223 glTexCoord2f(x,y);
224 glVertex3f(x,y,0.0);
225
226 glTexCoord2f(x,y+dy);
227 glVertex3f(x,y+dy,0.0);
228 }
229 glEnd();
230 }
231 }
232
233 static void drawteapot(void)
234 {
235 static float xrot=0.0;
236 static float zrot=0.0;
237
238 glPushMatrix();
239 glRotatef(lightalpha,0.0,0.0,1.0);
240 glMultMatrixf((GLfloat *)baseshadow);
241 glRotatef(-lightalpha,0.0,0.0,1.0);
242
243 glTranslatef(0.0,0.0,1.0);
244 glRotatef(xrot,1.0,0.0,0.0);
245 glRotatef(zrot,0.0,0.0,1.0);
246
247 glDisable(GL_TEXTURE_2D);
248 glDisable(GL_DEPTH_TEST);
249 glDisable(GL_LIGHTING);
250
251 glColor3f(0.0,0.0,0.0);
252 glCallList(teapotdlist);
253
254 glEnable(GL_DEPTH_TEST);
255 glEnable(GL_LIGHTING);
256 if(usetex)
257 glEnable(GL_TEXTURE_2D);
258
259 glPopMatrix();
260
261 glPushMatrix();
262 glTranslatef(0.0,0.0,1.0);
263 glRotatef(xrot,1.0,0.0,0.0);
264 glRotatef(zrot,0.0,0.0,1.0);
265
266 glCallList(teapotdlist);
267 glPopMatrix();
268
269 xrot+=2.0;
270 zrot+=1.0;
271 }
272
273 static void drawlight1(void)
274 {
275 glPushMatrix();
276 glRotatef(lightalpha,0.0,0.0,1.0);
277 glLightfv(GL_LIGHT0,GL_POSITION,lightpos);
278 glLightfv(GL_LIGHT0,GL_SPOT_DIRECTION,lightdir);
279
280 glPopMatrix();
281 }
282
283 static void drawlight2(void)
284 {
285 glPushMatrix();
286 glRotatef(lightalpha,0.0,0.0,1.0);
287 glTranslatef(lightpos[0],lightpos[1],lightpos[2]);
288
289 glDisable(GL_TEXTURE_2D);
290 glCallList(lightdlist);
291 if(usetex)
292 glEnable(GL_TEXTURE_2D);
293
294 glPopMatrix();
295
296 lightalpha+=1.0;
297 }
298
299 static void dojoy(void)
300 {
301 #ifdef WIN32
302 static UINT max[2]={0,0};
303 static UINT min[2]={0xffffffff,0xffffffff},center[2];
304 MMRESULT res;
305 JOYINFO joy;
306
307 res=joyGetPos(JOYSTICKID1,&joy);
308
309 if(res==JOYERR_NOERROR) {
310 joyavailable=1;
311
312 if(max[0]<joy.wXpos)
313 max[0]=joy.wXpos;
314 if(min[0]>joy.wXpos)
315 min[0]=joy.wXpos;
316 center[0]=(max[0]+min[0])/2;
317
318 if(max[1]<joy.wYpos)
319 max[1]=joy.wYpos;
320 if(min[1]>joy.wYpos)
321 min[1]=joy.wYpos;
322 center[1]=(max[1]+min[1])/2;
323
324 if(joyactive) {
325 if(fabs(center[0]-(float)joy.wXpos)>0.1*(max[0]-min[0]))
326 alpha-=2.5*(center[0]-(float)joy.wXpos)/(max[0]-min[0]);
327 if(fabs(center[1]-(float)joy.wYpos)>0.1*(max[1]-min[1]))
328 beta+=2.5*(center[1]-(float)joy.wYpos)/(max[1]-min[1]);
329
330 if(joy.wButtons & JOY_BUTTON1)
331 v+=0.005;
332 if(joy.wButtons & JOY_BUTTON2)
333 v-=0.005;
334 }
335 } else
336 joyavailable=0;
337 #endif
338 }
339
340 static void draw(void)
341 {
342 static int count=0;
343 static char frbuf[80];
344 float fr;
345
346 dojoy();
347
348 glEnable(GL_DEPTH_TEST);
349 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
350
351 if(usetex)
352 glEnable(GL_TEXTURE_2D);
353 else
354 glDisable(GL_TEXTURE_2D);
355
356 if(fog)
357 glEnable(GL_FOG);
358 else
359 glDisable(GL_FOG);
360
361 glEnable(GL_LIGHTING);
362
363 glShadeModel(GL_SMOOTH);
364
365 glPushMatrix();
366 calcposobs();
367
368 gluLookAt(obs[0],obs[1],obs[2],
369 obs[0]+dir[0],obs[1]+dir[1],obs[2]+dir[2],
370 0.0,0.0,1.0);
371
372 drawlight1();
373 glCallList(basedlist);
374 drawteapot();
375 drawlight2();
376 glPopMatrix();
377
378 if((count % FRAME)==0) {
379 fr=gettime();
380 sprintf(frbuf,"Frame rate: %f",FRAME/fr);
381 }
382
383 glDisable(GL_LIGHTING);
384 glDisable(GL_TEXTURE_2D);
385 glDisable(GL_DEPTH_TEST);
386 glDisable(GL_FOG);
387 glShadeModel(GL_FLAT);
388
389 glMatrixMode(GL_PROJECTION);
390 glLoadIdentity();
391 glOrtho(-0.5,639.5,-0.5,479.5,-1.0,1.0);
392 glMatrixMode(GL_MODELVIEW);
393 glLoadIdentity();
394
395 glColor3f(1.0,0.0,0.0);
396 glRasterPos2i(10,10);
397 printstring(GLUT_BITMAP_HELVETICA_18,frbuf);
398 glRasterPos2i(350,470);
399 printstring(GLUT_BITMAP_HELVETICA_10,"Teapot V1.2 Written by David Bucciarelli (tech.hmw@plus.it)");
400
401 if(help)
402 printhelp();
403
404 reshape(WIDTH,HEIGHT);
405
406 glutSwapBuffers();
407
408 count++;
409 }
410
411 static void inittextures(void)
412 {
413 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
433 if (!LoadRGBMipmaps("../images/bw.rgb", GL_RGB)) {
434 fprintf(stderr,"Error reading a texture.\n");
435 exit(-1);
436 }
437
438 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
439 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
440
441 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
442 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
443
444 glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
445 }
446
447 static void initlight(void)
448 {
449 float lamb[4]={0.2,0.2,0.2,1.0};
450 float lspec[4]={1.0,1.0,1.0,1.0};
451
452 glLightf(GL_LIGHT0,GL_SPOT_CUTOFF,70.0);
453 glLightf(GL_LIGHT0,GL_SPOT_EXPONENT,20.0);
454 glLightfv(GL_LIGHT0,GL_AMBIENT,lamb);
455 glLightfv(GL_LIGHT0,GL_SPECULAR,lspec);
456
457 glMaterialf(GL_FRONT_AND_BACK,GL_SHININESS,20.0);
458 glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,lspec);
459
460 glEnable(GL_LIGHT0);
461 }
462
463 static void initdlists(void)
464 {
465 GLUquadricObj *lcone,*lbase;
466 GLfloat plane[4];
467 GLfloat v0[3]={0.0,0.0,0.0};
468 GLfloat v1[3]={1.0,0.0,0.0};
469 GLfloat v2[3]={0.0,1.0,0.0};
470
471 findplane(plane,v0,v1,v2);
472 shadowmatrix(baseshadow,plane,lightpos);
473
474 teapotdlist=glGenLists(1);
475 glNewList(teapotdlist,GL_COMPILE);
476 glRotatef(90.0,1.0,0.0,0.0);
477 glCullFace(GL_FRONT);
478 glBindTexture(GL_TEXTURE_2D,t2id);
479 glutSolidTeapot(0.75);
480 glCullFace(GL_BACK);
481 glEndList();
482
483 basedlist=glGenLists(1);
484 glNewList(basedlist,GL_COMPILE);
485 drawbase();
486 glEndList();
487
488 lightdlist=glGenLists(1);
489 glNewList(lightdlist,GL_COMPILE);
490 glDisable(GL_LIGHTING);
491
492 lcone=gluNewQuadric();
493 lbase=gluNewQuadric();
494 glRotatef(45.0,0.0,1.0,0.0);
495
496 glColor3f(1.0,1.0,1.0);
497 glCullFace(GL_FRONT);
498 gluDisk(lbase,0.0,0.2,12.0,1.0);
499 glCullFace(GL_BACK);
500
501 glColor3f(0.5,0.0,0.0);
502 gluCylinder(lcone,0.2,0.0,0.5,12,1);
503
504 gluDeleteQuadric(lcone);
505 gluDeleteQuadric(lbase);
506
507 glEnable(GL_LIGHTING);
508 glEndList();
509 }
510
511 int main(int ac, char **av)
512 {
513 float fogcolor[4]={0.025,0.025,0.025,1.0};
514
515 fprintf(stderr,"Teapot V1.2\nWritten by David Bucciarelli (tech.hmw@plus.it)\n");
516
517 /*
518 if(!SetPriorityClass(GetCurrentProcess(),REALTIME_PRIORITY_CLASS)) {
519 fprintf(stderr,"Error setting the process class.\n");
520 return 0;
521 }
522
523 if(!SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_TIME_CRITICAL)) {
524 fprintf(stderr,"Error setting the process priority.\n");
525 return 0;
526 }
527 */
528
529 glutInitWindowPosition(0,0);
530 glutInitWindowSize(WIDTH,HEIGHT);
531 glutInit(&ac,av);
532
533 glutInitDisplayMode(GLUT_RGB|GLUT_DEPTH|GLUT_DOUBLE);
534
535 if(!(win=glutCreateWindow("Teapot"))) {
536 fprintf(stderr,"Error, couldn't open window\n");
537 return -1;
538 }
539
540 reshape(WIDTH,HEIGHT);
541
542 glShadeModel(GL_SMOOTH);
543 glEnable(GL_DEPTH_TEST);
544 glEnable(GL_CULL_FACE);
545 glEnable(GL_TEXTURE_2D);
546
547 glEnable(GL_FOG);
548 glFogi(GL_FOG_MODE,GL_EXP2);
549 glFogfv(GL_FOG_COLOR,fogcolor);
550
551 glFogf(GL_FOG_DENSITY,0.04);
552 glHint(GL_FOG_HINT,GL_NICEST);
553 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
554
555 calcposobs();
556
557 inittextures();
558 initlight();
559
560 initdlists();
561
562 glClearColor(fogcolor[0],fogcolor[1],fogcolor[2],fogcolor[3]);
563
564 glutReshapeFunc(reshape);
565 glutDisplayFunc(draw);
566 glutKeyboardFunc(key);
567 glutSpecialFunc(special);
568 glutIdleFunc(draw);
569
570 glutMainLoop();
571
572 return 0;
573 }