4769139ed98db7c90861cda41e8d741ca840a43d
[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 static GLint T0 = 0;
31 static GLint Frames = 0;
32
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
42 extern void shadowmatrix(GLfloat [4][4], GLfloat [4], GLfloat [4]);
43 extern void findplane(GLfloat [4], GLfloat [3], GLfloat [3], GLfloat [3]);
44
45
46 static int win=0;
47
48 static float obs[3]={5.0,0.0,1.0};
49 static float dir[3];
50 static float v=0.0;
51 static float alpha=-90.0;
52 static float beta=90.0;
53
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;
58
59 static int fog=1;
60 static int bfcull=1;
61 static int usetex=1;
62 static int help=1;
63 static int joyavailable=0;
64 static int joyactive=0;
65
66 static GLuint t1id,t2id;
67 static GLuint teapotdlist,basedlist,lightdlist;
68
69 static 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
80 static 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
98 static 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
142 static 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
154 static 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
163 static 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
196 static void drawbase(void)
197 {
198 int i,j;
199 float x,y,dx,dy;
200
201 glBindTexture(GL_TEXTURE_2D,t1id);
202
203 dx=BASESIZE/BASERES;
204 dy=-BASESIZE/BASERES;
205 for(y=BASESIZE/2.0,j=0;j<BASERES;y+=dy,j++) {
206 glBegin(GL_QUAD_STRIP);
207 glColor3f(1.0,1.0,1.0);
208 glNormal3f(0.0,0.0,1.0);
209 for(x=-BASESIZE/2.0,i=0;i<BASERES;x+=dx,i++) {
210 glTexCoord2f(x,y);
211 glVertex3f(x,y,0.0);
212
213 glTexCoord2f(x,y+dy);
214 glVertex3f(x,y+dy,0.0);
215 }
216 glEnd();
217 }
218 }
219
220 static void drawteapot(void)
221 {
222 static float xrot=0.0;
223 static float zrot=0.0;
224
225 glPushMatrix();
226 glRotatef(lightalpha,0.0,0.0,1.0);
227 glMultMatrixf((GLfloat *)baseshadow);
228 glRotatef(-lightalpha,0.0,0.0,1.0);
229
230 glTranslatef(0.0,0.0,1.0);
231 glRotatef(xrot,1.0,0.0,0.0);
232 glRotatef(zrot,0.0,0.0,1.0);
233
234 glDisable(GL_TEXTURE_2D);
235 glDisable(GL_DEPTH_TEST);
236 glDisable(GL_LIGHTING);
237
238 glColor3f(0.0,0.0,0.0);
239 glCallList(teapotdlist);
240
241 glEnable(GL_DEPTH_TEST);
242 glEnable(GL_LIGHTING);
243 if(usetex)
244 glEnable(GL_TEXTURE_2D);
245
246 glPopMatrix();
247
248 glPushMatrix();
249 glTranslatef(0.0,0.0,1.0);
250 glRotatef(xrot,1.0,0.0,0.0);
251 glRotatef(zrot,0.0,0.0,1.0);
252
253 glCallList(teapotdlist);
254 glPopMatrix();
255
256 xrot+=2.0;
257 zrot+=1.0;
258 }
259
260 static void drawlight1(void)
261 {
262 glPushMatrix();
263 glRotatef(lightalpha,0.0,0.0,1.0);
264 glLightfv(GL_LIGHT0,GL_POSITION,lightpos);
265 glLightfv(GL_LIGHT0,GL_SPOT_DIRECTION,lightdir);
266
267 glPopMatrix();
268 }
269
270 static void drawlight2(void)
271 {
272 glPushMatrix();
273 glRotatef(lightalpha,0.0,0.0,1.0);
274 glTranslatef(lightpos[0],lightpos[1],lightpos[2]);
275
276 glDisable(GL_TEXTURE_2D);
277 glCallList(lightdlist);
278 if(usetex)
279 glEnable(GL_TEXTURE_2D);
280
281 glPopMatrix();
282
283 lightalpha+=1.0;
284 }
285
286 static void dojoy(void)
287 {
288 #ifdef WIN32
289 static UINT max[2]={0,0};
290 static UINT min[2]={0xffffffff,0xffffffff},center[2];
291 MMRESULT res;
292 JOYINFO joy;
293
294 res=joyGetPos(JOYSTICKID1,&joy);
295
296 if(res==JOYERR_NOERROR) {
297 joyavailable=1;
298
299 if(max[0]<joy.wXpos)
300 max[0]=joy.wXpos;
301 if(min[0]>joy.wXpos)
302 min[0]=joy.wXpos;
303 center[0]=(max[0]+min[0])/2;
304
305 if(max[1]<joy.wYpos)
306 max[1]=joy.wYpos;
307 if(min[1]>joy.wYpos)
308 min[1]=joy.wYpos;
309 center[1]=(max[1]+min[1])/2;
310
311 if(joyactive) {
312 if(fabs(center[0]-(float)joy.wXpos)>0.1*(max[0]-min[0]))
313 alpha-=2.5*(center[0]-(float)joy.wXpos)/(max[0]-min[0]);
314 if(fabs(center[1]-(float)joy.wYpos)>0.1*(max[1]-min[1]))
315 beta+=2.5*(center[1]-(float)joy.wYpos)/(max[1]-min[1]);
316
317 if(joy.wButtons & JOY_BUTTON1)
318 v+=0.005;
319 if(joy.wButtons & JOY_BUTTON2)
320 v-=0.005;
321 }
322 } else
323 joyavailable=0;
324 #endif
325 }
326
327 static void draw(void)
328 {
329 static char frbuf[80] = "";
330
331 dojoy();
332
333 glEnable(GL_DEPTH_TEST);
334 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
335
336 if(usetex)
337 glEnable(GL_TEXTURE_2D);
338 else
339 glDisable(GL_TEXTURE_2D);
340
341 if(fog)
342 glEnable(GL_FOG);
343 else
344 glDisable(GL_FOG);
345
346 glEnable(GL_LIGHTING);
347
348 glShadeModel(GL_SMOOTH);
349
350 glPushMatrix();
351 calcposobs();
352
353 gluLookAt(obs[0],obs[1],obs[2],
354 obs[0]+dir[0],obs[1]+dir[1],obs[2]+dir[2],
355 0.0,0.0,1.0);
356
357 drawlight1();
358 glCallList(basedlist);
359 drawteapot();
360 drawlight2();
361 glPopMatrix();
362
363 glDisable(GL_LIGHTING);
364 glDisable(GL_TEXTURE_2D);
365 glDisable(GL_DEPTH_TEST);
366 glDisable(GL_FOG);
367 glShadeModel(GL_FLAT);
368
369 glMatrixMode(GL_PROJECTION);
370 glLoadIdentity();
371 glOrtho(-0.5,639.5,-0.5,479.5,-1.0,1.0);
372 glMatrixMode(GL_MODELVIEW);
373 glLoadIdentity();
374
375 glColor3f(1.0,0.0,0.0);
376 glRasterPos2i(10,10);
377 printstring(GLUT_BITMAP_HELVETICA_18,frbuf);
378 glRasterPos2i(350,470);
379 printstring(GLUT_BITMAP_HELVETICA_10,"Teapot V1.2 Written by David Bucciarelli (tech.hmw@plus.it)");
380
381 if(help)
382 printhelp();
383
384 reshape(WIDTH,HEIGHT);
385
386 glutSwapBuffers();
387
388 Frames++;
389
390 {
391 GLint t = glutGet(GLUT_ELAPSED_TIME);
392 if (t - T0 >= 2000) {
393 GLfloat seconds = (t - T0) / 1000.0;
394 GLfloat fps = Frames / seconds;
395 sprintf(frbuf, "Frame rate: %f", fps);
396 T0 = t;
397 Frames = 0;
398 }
399 }
400 }
401
402 static void inittextures(void)
403 {
404 glGenTextures(1,&t1id);
405 glBindTexture(GL_TEXTURE_2D,t1id);
406
407 glPixelStorei(GL_UNPACK_ALIGNMENT,4);
408 if (!LoadRGBMipmaps("../images/tile.rgb", GL_RGB)) {
409 fprintf(stderr,"Error reading a texture.\n");
410 exit(-1);
411 }
412
413 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
414 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
415
416 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
417 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
418
419 glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
420
421 glGenTextures(1,&t2id);
422 glBindTexture(GL_TEXTURE_2D,t2id);
423
424 if (!LoadRGBMipmaps("../images/bw.rgb", GL_RGB)) {
425 fprintf(stderr,"Error reading a texture.\n");
426 exit(-1);
427 }
428
429 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
430 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
431
432 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
433 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
434
435 glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
436 }
437
438 static void initlight(void)
439 {
440 float lamb[4]={0.2,0.2,0.2,1.0};
441 float lspec[4]={1.0,1.0,1.0,1.0};
442
443 glLightf(GL_LIGHT0,GL_SPOT_CUTOFF,70.0);
444 glLightf(GL_LIGHT0,GL_SPOT_EXPONENT,20.0);
445 glLightfv(GL_LIGHT0,GL_AMBIENT,lamb);
446 glLightfv(GL_LIGHT0,GL_SPECULAR,lspec);
447
448 glMaterialf(GL_FRONT_AND_BACK,GL_SHININESS,20.0);
449 glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,lspec);
450
451 glEnable(GL_LIGHT0);
452 }
453
454 static void initdlists(void)
455 {
456 GLUquadricObj *lcone,*lbase;
457 GLfloat plane[4];
458 GLfloat v0[3]={0.0,0.0,0.0};
459 GLfloat v1[3]={1.0,0.0,0.0};
460 GLfloat v2[3]={0.0,1.0,0.0};
461
462 findplane(plane,v0,v1,v2);
463 shadowmatrix(baseshadow,plane,lightpos);
464
465 teapotdlist=glGenLists(1);
466 glNewList(teapotdlist,GL_COMPILE);
467 glRotatef(90.0,1.0,0.0,0.0);
468 glCullFace(GL_FRONT);
469 glBindTexture(GL_TEXTURE_2D,t2id);
470 glutSolidTeapot(0.75);
471 glCullFace(GL_BACK);
472 glEndList();
473
474 basedlist=glGenLists(1);
475 glNewList(basedlist,GL_COMPILE);
476 drawbase();
477 glEndList();
478
479 lightdlist=glGenLists(1);
480 glNewList(lightdlist,GL_COMPILE);
481 glDisable(GL_LIGHTING);
482
483 lcone=gluNewQuadric();
484 lbase=gluNewQuadric();
485 glRotatef(45.0,0.0,1.0,0.0);
486
487 glColor3f(1.0,1.0,1.0);
488 glCullFace(GL_FRONT);
489 gluDisk(lbase,0.0,0.2,12.0,1.0);
490 glCullFace(GL_BACK);
491
492 glColor3f(0.5,0.0,0.0);
493 gluCylinder(lcone,0.2,0.0,0.5,12,1);
494
495 gluDeleteQuadric(lcone);
496 gluDeleteQuadric(lbase);
497
498 glEnable(GL_LIGHTING);
499 glEndList();
500 }
501
502 int main(int ac, char **av)
503 {
504 float fogcolor[4]={0.025,0.025,0.025,1.0};
505
506 fprintf(stderr,"Teapot V1.2\nWritten by David Bucciarelli (tech.hmw@plus.it)\n");
507
508 /*
509 if(!SetPriorityClass(GetCurrentProcess(),REALTIME_PRIORITY_CLASS)) {
510 fprintf(stderr,"Error setting the process class.\n");
511 return 0;
512 }
513
514 if(!SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_TIME_CRITICAL)) {
515 fprintf(stderr,"Error setting the process priority.\n");
516 return 0;
517 }
518 */
519
520 glutInitWindowPosition(0,0);
521 glutInitWindowSize(WIDTH,HEIGHT);
522 glutInit(&ac,av);
523
524 glutInitDisplayMode(GLUT_RGB|GLUT_DEPTH|GLUT_DOUBLE);
525
526 if(!(win=glutCreateWindow("Teapot"))) {
527 fprintf(stderr,"Error, couldn't open window\n");
528 return -1;
529 }
530
531 reshape(WIDTH,HEIGHT);
532
533 glShadeModel(GL_SMOOTH);
534 glEnable(GL_DEPTH_TEST);
535 glEnable(GL_CULL_FACE);
536 glEnable(GL_TEXTURE_2D);
537
538 glEnable(GL_FOG);
539 glFogi(GL_FOG_MODE,GL_EXP2);
540 glFogfv(GL_FOG_COLOR,fogcolor);
541
542 glFogf(GL_FOG_DENSITY,0.04);
543 glHint(GL_FOG_HINT,GL_NICEST);
544 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
545
546 calcposobs();
547
548 inittextures();
549 initlight();
550
551 initdlists();
552
553 glClearColor(fogcolor[0],fogcolor[1],fogcolor[2],fogcolor[3]);
554
555 glutReshapeFunc(reshape);
556 glutDisplayFunc(draw);
557 glutKeyboardFunc(key);
558 glutSpecialFunc(special);
559 glutIdleFunc(draw);
560
561 glutMainLoop();
562
563 return 0;
564 }