blob: addee03a3da7e531cc6a7286bb4ea01c5c0cd11f [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
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
41extern void shadowmatrix(GLfloat [4][4], GLfloat [4], GLfloat [4]);
42extern void findplane(GLfloat [4], GLfloat [3], GLfloat [3], GLfloat [3]);
43
44
45static int win=0;
46
47static float obs[3]={5.0,0.0,1.0};
48static float dir[3];
49static float v=0.0;
50static float alpha=-90.0;
51static float beta=90.0;
52
53static GLfloat baseshadow[4][4];
54static GLfloat lightpos[4]={2.3,0.0,3.0,1.0};
55static GLfloat lightdir[3]={-2.3,0.0,-3.0};
56static GLfloat lightalpha=0.0;
57
58static int fog=1;
59static int bfcull=1;
60static int usetex=1;
61static int help=1;
62static int joyavailable=0;
63static int joyactive=0;
64
65static GLuint t1id,t2id;
66static GLuint teapotdlist,basedlist,lightdlist;
67
68static 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
82static 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
93static 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
111static 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
155static 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
167static 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
176static 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
209static 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
233static 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
273static 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
283static 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
299static 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
340static 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
411static void inittextures(void)
412{
413 GLenum gluerr;
414
415 glGenTextures(1,&t1id);
416 glBindTexture(GL_TEXTURE_2D,t1id);
417
418 glPixelStorei(GL_UNPACK_ALIGNMENT,4);
419 if (!LoadRGBMipmaps("../images/tile.rgb", GL_RGB)) {
420 fprintf(stderr,"Error reading a texture.\n");
421 exit(-1);
422 }
423
424 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
425 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
426
427 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
428 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
429
430 glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
431
432 glGenTextures(1,&t2id);
433 glBindTexture(GL_TEXTURE_2D,t2id);
434
435 if (!LoadRGBMipmaps("../images/bw.rgb", GL_RGB)) {
436 fprintf(stderr,"Error reading a texture.\n");
437 exit(-1);
438 }
439
440 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
441 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
442
443 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
444 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
445
446 glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
447}
448
449static void initlight(void)
450{
451 float lamb[4]={0.2,0.2,0.2,1.0};
452 float lspec[4]={1.0,1.0,1.0,1.0};
453
454 glLightf(GL_LIGHT0,GL_SPOT_CUTOFF,70.0);
455 glLightf(GL_LIGHT0,GL_SPOT_EXPONENT,20.0);
456 glLightfv(GL_LIGHT0,GL_AMBIENT,lamb);
457 glLightfv(GL_LIGHT0,GL_SPECULAR,lspec);
458
459 glMaterialf(GL_FRONT_AND_BACK,GL_SHININESS,20.0);
460 glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,lspec);
461
462 glEnable(GL_LIGHT0);
463}
464
465static void initdlists(void)
466{
467 GLUquadricObj *lcone,*lbase;
468 GLfloat plane[4];
469 GLfloat v0[3]={0.0,0.0,0.0};
470 GLfloat v1[3]={1.0,0.0,0.0};
471 GLfloat v2[3]={0.0,1.0,0.0};
472
473 findplane(plane,v0,v1,v2);
474 shadowmatrix(baseshadow,plane,lightpos);
475
476 teapotdlist=glGenLists(1);
477 glNewList(teapotdlist,GL_COMPILE);
478 glRotatef(90.0,1.0,0.0,0.0);
479 glCullFace(GL_FRONT);
480 glBindTexture(GL_TEXTURE_2D,t2id);
481 glutSolidTeapot(0.75);
482 glCullFace(GL_BACK);
483 glEndList();
484
485 basedlist=glGenLists(1);
486 glNewList(basedlist,GL_COMPILE);
487 drawbase();
488 glEndList();
489
490 lightdlist=glGenLists(1);
491 glNewList(lightdlist,GL_COMPILE);
492 glDisable(GL_LIGHTING);
493
494 lcone=gluNewQuadric();
495 lbase=gluNewQuadric();
496 glRotatef(45.0,0.0,1.0,0.0);
497
498 glColor3f(1.0,1.0,1.0);
499 glCullFace(GL_FRONT);
500 gluDisk(lbase,0.0,0.2,12.0,1.0);
501 glCullFace(GL_BACK);
502
503 glColor3f(0.5,0.0,0.0);
504 gluCylinder(lcone,0.2,0.0,0.5,12,1);
505
506 gluDeleteQuadric(lcone);
507 gluDeleteQuadric(lbase);
508
509 glEnable(GL_LIGHTING);
510 glEndList();
511}
512
513int main(int ac, char **av)
514{
515 float fogcolor[4]={0.025,0.025,0.025,1.0};
516
517 fprintf(stderr,"Teapot V1.2\nWritten by David Bucciarelli (tech.hmw@plus.it)\n");
518
519 /*
520 if(!SetPriorityClass(GetCurrentProcess(),REALTIME_PRIORITY_CLASS)) {
521 fprintf(stderr,"Error setting the process class.\n");
522 return 0;
523 }
524
525 if(!SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_TIME_CRITICAL)) {
526 fprintf(stderr,"Error setting the process priority.\n");
527 return 0;
528 }
529 */
530
531 glutInitWindowPosition(0,0);
532 glutInitWindowSize(WIDTH,HEIGHT);
533 glutInit(&ac,av);
534
535 glutInitDisplayMode(GLUT_RGB|GLUT_DEPTH|GLUT_DOUBLE);
536
537 if(!(win=glutCreateWindow("Teapot"))) {
538 fprintf(stderr,"Error, couldn't open window\n");
539 return -1;
540 }
541
542 reshape(WIDTH,HEIGHT);
543
544 glShadeModel(GL_SMOOTH);
545 glEnable(GL_DEPTH_TEST);
546 glEnable(GL_CULL_FACE);
547 glEnable(GL_TEXTURE_2D);
548
549 glEnable(GL_FOG);
550 glFogi(GL_FOG_MODE,GL_EXP2);
551 glFogfv(GL_FOG_COLOR,fogcolor);
552
553 glFogf(GL_FOG_DENSITY,0.04);
554 glHint(GL_FOG_HINT,GL_NICEST);
555 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
556
557 calcposobs();
558
559 inittextures();
560 initlight();
561
562 initdlists();
563
564 glClearColor(fogcolor[0],fogcolor[1],fogcolor[2],fogcolor[3]);
565
566 glutReshapeFunc(reshape);
567 glutDisplayFunc(draw);
568 glutKeyboardFunc(key);
569 glutSpecialFunc(special);
570 glutIdleFunc(draw);
571
572 glutMainLoop();
573
574 return 0;
575}