2 * This program is under the GNU GPL.
3 * Use at your own risk.
5 * written by David Bucciarelli (tech.hmw@plus.it)
24 static int fullscreen
=1;
28 static int HEIGHT
=480;
31 static GLint Frames
= 0;
39 #define M_PI 3.1415926535
42 extern void shadowmatrix(GLfloat
[4][4], GLfloat
[4], GLfloat
[4]);
43 extern void findplane(GLfloat
[4], GLfloat
[3], GLfloat
[3], GLfloat
[3]);
48 static float obs
[3]={5.0,0.0,1.0};
51 static float alpha
=-90.0;
52 static float beta
=90.0;
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;
63 static int joyavailable
=0;
64 static int joyactive
=0;
66 static GLuint t1id
,t2id
;
67 static GLuint teapotdlist
,basedlist
,lightdlist
;
71 /******************** begin shadow code ********************/
73 /* Taken from the projshadow.c - by Tom McReynolds, SGI */
75 /* Modified by David Bucciarelli */
84 /* create a matrix that will project the desired shadow */
86 shadowmatrix(GLfloat shadowMat
[4][4],
87 GLfloat groundplane
[4],
92 /* find dot product between light position vector and ground plane normal */
93 dot
= groundplane
[X
] * lightpos
[X
] +
94 groundplane
[Y
] * lightpos
[Y
] +
95 groundplane
[Z
] * lightpos
[Z
] +
96 groundplane
[W
] * lightpos
[W
];
98 shadowMat
[0][0] = dot
- lightpos
[X
] * groundplane
[X
];
99 shadowMat
[1][0] = 0.f
- lightpos
[X
] * groundplane
[Y
];
100 shadowMat
[2][0] = 0.f
- lightpos
[X
] * groundplane
[Z
];
101 shadowMat
[3][0] = 0.f
- lightpos
[X
] * groundplane
[W
];
103 shadowMat
[X
][1] = 0.f
- lightpos
[Y
] * groundplane
[X
];
104 shadowMat
[1][1] = dot
- lightpos
[Y
] * groundplane
[Y
];
105 shadowMat
[2][1] = 0.f
- lightpos
[Y
] * groundplane
[Z
];
106 shadowMat
[3][1] = 0.f
- lightpos
[Y
] * groundplane
[W
];
108 shadowMat
[X
][2] = 0.f
- lightpos
[Z
] * groundplane
[X
];
109 shadowMat
[1][2] = 0.f
- lightpos
[Z
] * groundplane
[Y
];
110 shadowMat
[2][2] = dot
- lightpos
[Z
] * groundplane
[Z
];
111 shadowMat
[3][2] = 0.f
- lightpos
[Z
] * groundplane
[W
];
113 shadowMat
[X
][3] = 0.f
- lightpos
[W
] * groundplane
[X
];
114 shadowMat
[1][3] = 0.f
- lightpos
[W
] * groundplane
[Y
];
115 shadowMat
[2][3] = 0.f
- lightpos
[W
] * groundplane
[Z
];
116 shadowMat
[3][3] = dot
- lightpos
[W
] * groundplane
[W
];
120 /* find the plane equation given 3 points */
122 findplane(GLfloat plane
[4],
123 GLfloat v0
[3], GLfloat v1
[3], GLfloat v2
[3])
125 GLfloat vec0
[3], vec1
[3];
127 /* need 2 vectors to find cross product */
128 vec0
[X
] = v1
[X
] - v0
[X
];
129 vec0
[Y
] = v1
[Y
] - v0
[Y
];
130 vec0
[Z
] = v1
[Z
] - v0
[Z
];
132 vec1
[X
] = v2
[X
] - v0
[X
];
133 vec1
[Y
] = v2
[Y
] - v0
[Y
];
134 vec1
[Z
] = v2
[Z
] - v0
[Z
];
136 /* find cross product to get A, B, and C of plane equation */
137 plane
[A
] = vec0
[Y
] * vec1
[Z
] - vec0
[Z
] * vec1
[Y
];
138 plane
[B
] = -(vec0
[X
] * vec1
[Z
] - vec0
[Z
] * vec1
[X
]);
139 plane
[C
] = vec0
[X
] * vec1
[Y
] - vec0
[Y
] * vec1
[X
];
141 plane
[D
] = -(plane
[A
] * v0
[X
] + plane
[B
] * v0
[Y
] + plane
[C
] * v0
[Z
]);
144 /******************** end shadow code ********************/
147 static void calcposobs(void)
149 dir
[0]=sin(alpha
*M_PI
/180.0);
150 dir
[1]=cos(alpha
*M_PI
/180.0)*sin(beta
*M_PI
/180.0);
151 dir
[2]=cos(beta
*M_PI
/180.0);
158 static void special(int k
, int x
, int y
)
176 static void cleanup(void)
178 glDeleteTextures(1, &t1id
);
179 glDeleteTextures(1, &t2id
);
180 glDeleteLists(teapotdlist
, 1);
181 glDeleteLists(basedlist
, 1);
182 glDeleteLists(lightdlist
, 1);
185 static void key(unsigned char k
, int x
, int y
)
201 joyactive
=(!joyactive
);
214 glDisable(GL_CULL_FACE
);
217 glEnable(GL_CULL_FACE
);
223 XMesaSetFXmode(fullscreen
? XMESA_FX_FULLSCREEN
: XMESA_FX_WINDOW
);
224 fullscreen
=(!fullscreen
);
230 static void reshape(int w
, int h
)
234 glMatrixMode(GL_PROJECTION
);
236 gluPerspective(45.0,w
/(float)h
,0.2,40.0);
237 glMatrixMode(GL_MODELVIEW
);
242 static void printstring(void *font
, char *string
)
246 len
=(int)strlen(string
);
248 glutBitmapCharacter(font
,string
[i
]);
251 static void printhelp(void)
254 glColor4f(0.5,0.5,0.5,0.5);
255 glRecti(40,40,600,440);
258 glColor3f(1.0,0.0,0.0);
259 glRasterPos2i(300,420);
260 printstring(GLUT_BITMAP_TIMES_ROMAN_24
,"Help");
262 glRasterPos2i(60,390);
263 printstring(GLUT_BITMAP_TIMES_ROMAN_24
,"h - Toggle Help");
264 glRasterPos2i(60,360);
265 printstring(GLUT_BITMAP_TIMES_ROMAN_24
,"t - Toggle Textures");
266 glRasterPos2i(60,330);
267 printstring(GLUT_BITMAP_TIMES_ROMAN_24
,"f - Toggle Fog");
268 glRasterPos2i(60,300);
269 printstring(GLUT_BITMAP_TIMES_ROMAN_24
,"b - Toggle Back face culling");
270 glRasterPos2i(60,270);
271 printstring(GLUT_BITMAP_TIMES_ROMAN_24
,"Arrow Keys - Rotate");
272 glRasterPos2i(60,240);
273 printstring(GLUT_BITMAP_TIMES_ROMAN_24
,"a - Increase velocity");
274 glRasterPos2i(60,210);
275 printstring(GLUT_BITMAP_TIMES_ROMAN_24
,"z - Decrease velocity");
277 glRasterPos2i(60,180);
279 printstring(GLUT_BITMAP_TIMES_ROMAN_24
,"j - Toggle jostick control (Joystick control available)");
281 printstring(GLUT_BITMAP_TIMES_ROMAN_24
,"(No Joystick control available)");
284 static void drawbase(void)
286 static const GLfloat amb
[4] = { 1, .5, 0.2, 1 };
287 static const GLfloat diff
[4] = { 1, .4, 0.2, 1 };
291 glBindTexture(GL_TEXTURE_2D
,t1id
);
293 glMaterialfv(GL_FRONT_AND_BACK
, GL_AMBIENT
, amb
);
294 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, diff
);
296 dy
=-BASESIZE
/BASERES
;
297 for(y
=BASESIZE
/2.0,j
=0;j
<BASERES
;y
+=dy
,j
++) {
298 glBegin(GL_QUAD_STRIP
);
299 glColor3f(1.0,1.0,1.0);
300 glNormal3f(0.0,0.0,1.0);
301 for(x
=-BASESIZE
/2.0,i
=0;i
<BASERES
;x
+=dx
,i
++) {
305 glTexCoord2f(x
,y
+dy
);
306 glVertex3f(x
,y
+dy
,0.0);
312 static void drawteapot(void)
314 static const GLfloat amb
[4] = { 0.2, 0.2, 0.2, 1 };
315 static const GLfloat diff
[4] = { 0.8, 0.3, 0.5, 1 };
316 static float xrot
=0.0;
317 static float zrot
=0.0;
319 glMaterialfv(GL_FRONT_AND_BACK
, GL_AMBIENT
, amb
);
320 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, diff
);
323 glRotatef(lightalpha
,0.0,0.0,1.0);
324 glMultMatrixf((GLfloat
*)baseshadow
);
325 glRotatef(-lightalpha
,0.0,0.0,1.0);
327 glTranslatef(0.0,0.0,1.0);
328 glRotatef(xrot
,1.0,0.0,0.0);
329 glRotatef(zrot
,0.0,0.0,1.0);
331 glDisable(GL_TEXTURE_2D
);
332 glDisable(GL_DEPTH_TEST
);
333 glDisable(GL_LIGHTING
);
335 glColor3f(0.0,0.0,0.0);
336 glCallList(teapotdlist
);
338 glEnable(GL_DEPTH_TEST
);
339 glEnable(GL_LIGHTING
);
341 glEnable(GL_TEXTURE_2D
);
346 glTranslatef(0.0,0.0,1.0);
347 glRotatef(xrot
,1.0,0.0,0.0);
348 glRotatef(zrot
,0.0,0.0,1.0);
350 glCallList(teapotdlist
);
357 static void drawlight1(void)
360 glRotatef(lightalpha
,0.0,0.0,1.0);
361 glLightfv(GL_LIGHT0
,GL_POSITION
,lightpos
);
362 glLightfv(GL_LIGHT0
,GL_SPOT_DIRECTION
,lightdir
);
367 static void drawlight2(void)
370 glRotatef(lightalpha
,0.0,0.0,1.0);
371 glTranslatef(lightpos
[0],lightpos
[1],lightpos
[2]);
373 glDisable(GL_TEXTURE_2D
);
374 glCallList(lightdlist
);
376 glEnable(GL_TEXTURE_2D
);
383 static void dojoy(void)
386 static UINT max
[2]={0,0};
387 static UINT min
[2]={0xffffffff,0xffffffff},center
[2];
391 res
=joyGetPos(JOYSTICKID1
,&joy
);
393 if(res
==JOYERR_NOERROR
) {
400 center
[0]=(max
[0]+min
[0])/2;
406 center
[1]=(max
[1]+min
[1])/2;
409 if(fabs(center
[0]-(float)joy
.wXpos
)>0.1*(max
[0]-min
[0]))
410 alpha
-=2.5*(center
[0]-(float)joy
.wXpos
)/(max
[0]-min
[0]);
411 if(fabs(center
[1]-(float)joy
.wYpos
)>0.1*(max
[1]-min
[1]))
412 beta
+=2.5*(center
[1]-(float)joy
.wYpos
)/(max
[1]-min
[1]);
414 if(joy
.wButtons
& JOY_BUTTON1
)
416 if(joy
.wButtons
& JOY_BUTTON2
)
424 static void draw(void)
426 static char frbuf
[80] = "";
430 glEnable(GL_DEPTH_TEST
);
431 glClear(GL_COLOR_BUFFER_BIT
|GL_DEPTH_BUFFER_BIT
);
434 glEnable(GL_TEXTURE_2D
);
436 glDisable(GL_TEXTURE_2D
);
443 glEnable(GL_LIGHTING
);
445 glShadeModel(GL_SMOOTH
);
450 gluLookAt(obs
[0],obs
[1],obs
[2],
451 obs
[0]+dir
[0],obs
[1]+dir
[1],obs
[2]+dir
[2],
455 glCallList(basedlist
);
460 glDisable(GL_LIGHTING
);
461 glDisable(GL_TEXTURE_2D
);
462 glDisable(GL_DEPTH_TEST
);
464 glShadeModel(GL_FLAT
);
466 glMatrixMode(GL_PROJECTION
);
468 glOrtho(-0.5,639.5,-0.5,479.5,-1.0,1.0);
469 glMatrixMode(GL_MODELVIEW
);
472 glColor3f(1.0,0.0,0.0);
473 glRasterPos2i(10,10);
474 printstring(GLUT_BITMAP_HELVETICA_18
,frbuf
);
475 glRasterPos2i(350,470);
476 printstring(GLUT_BITMAP_HELVETICA_10
,"Teapot V1.2 Written by David Bucciarelli (tech.hmw@plus.it)");
481 reshape(WIDTH
,HEIGHT
);
488 GLint t
= glutGet(GLUT_ELAPSED_TIME
);
489 if (t
- T0
>= 2000) {
490 GLfloat seconds
= (t
- T0
) / 1000.0;
491 GLfloat fps
= Frames
/ seconds
;
492 sprintf(frbuf
, "Frame rate: %f", fps
);
499 static void inittextures(void)
501 glGenTextures(1,&t1id
);
502 glBindTexture(GL_TEXTURE_2D
,t1id
);
504 glPixelStorei(GL_UNPACK_ALIGNMENT
,4);
505 if (!LoadRGBMipmaps("../images/tile.rgb", GL_RGB
)) {
506 fprintf(stderr
,"Error reading a texture.\n");
510 glTexParameterf(GL_TEXTURE_2D
,GL_TEXTURE_WRAP_S
,GL_REPEAT
);
511 glTexParameterf(GL_TEXTURE_2D
,GL_TEXTURE_WRAP_T
,GL_REPEAT
);
513 glTexParameterf(GL_TEXTURE_2D
,GL_TEXTURE_MIN_FILTER
,GL_LINEAR_MIPMAP_LINEAR
);
514 glTexParameterf(GL_TEXTURE_2D
,GL_TEXTURE_MAG_FILTER
,GL_LINEAR
);
516 glTexEnvf(GL_TEXTURE_ENV
,GL_TEXTURE_ENV_MODE
,GL_MODULATE
);
518 glGenTextures(1,&t2id
);
519 glBindTexture(GL_TEXTURE_2D
,t2id
);
521 glPixelTransferf(GL_RED_SCALE
, 0.75);
522 glPixelTransferf(GL_RED_BIAS
, 0.25);
523 glPixelTransferf(GL_GREEN_SCALE
, 0.75);
524 glPixelTransferf(GL_GREEN_BIAS
, 0.25);
525 glPixelTransferf(GL_BLUE_SCALE
, 0.75);
526 glPixelTransferf(GL_BLUE_BIAS
, 0.25);
528 if (!LoadRGBMipmaps("../images/bw.rgb", GL_RGB
)) {
529 fprintf(stderr
,"Error reading a texture.\n");
533 glPixelTransferf(GL_RED_SCALE
, 1.0);
534 glPixelTransferf(GL_RED_BIAS
, 0.0);
535 glPixelTransferf(GL_GREEN_SCALE
, 1.0);
536 glPixelTransferf(GL_GREEN_BIAS
, 0.0);
537 glPixelTransferf(GL_BLUE_SCALE
, 1.0);
538 glPixelTransferf(GL_BLUE_BIAS
, 0.0);
541 glTexParameterf(GL_TEXTURE_2D
,GL_TEXTURE_WRAP_S
,GL_REPEAT
);
542 glTexParameterf(GL_TEXTURE_2D
,GL_TEXTURE_WRAP_T
,GL_REPEAT
);
544 glTexParameterf(GL_TEXTURE_2D
,GL_TEXTURE_MIN_FILTER
,GL_LINEAR_MIPMAP_LINEAR
);
545 glTexParameterf(GL_TEXTURE_2D
,GL_TEXTURE_MAG_FILTER
,GL_LINEAR
);
547 glTexEnvf(GL_TEXTURE_ENV
,GL_TEXTURE_ENV_MODE
,GL_MODULATE
);
550 static void initlight(void)
552 float matamb
[4] ={0.5, 0.5, 0.5, 1.0};
553 float matdiff
[4]={0.9, 0.2, 0.2, 1.0};
554 float matspec
[4]={1.0,1.0,1.0,1.0};
556 float lamb
[4] ={1.5, 1.5, 1.5, 1.0};
557 float ldiff
[4]={1.0, 1.0, 1.0, 1.0};
558 float lspec
[4]={1.0, 1.0, 1.0, 1.0};
560 glLightf(GL_LIGHT0
,GL_SPOT_CUTOFF
,70.0);
561 glLightf(GL_LIGHT0
,GL_SPOT_EXPONENT
,20.0);
562 glLightfv(GL_LIGHT0
,GL_AMBIENT
,lamb
);
563 glLightfv(GL_LIGHT0
,GL_DIFFUSE
,ldiff
);
564 glLightfv(GL_LIGHT0
,GL_SPECULAR
,lspec
);
566 glMaterialf(GL_FRONT_AND_BACK
, GL_SHININESS
, 15.0);
567 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, matdiff
);
568 glMaterialfv(GL_FRONT_AND_BACK
, GL_SPECULAR
, matspec
);
569 glMaterialfv(GL_FRONT_AND_BACK
, GL_AMBIENT
, matamb
);
571 glLightModelfv(GL_LIGHT_MODEL_AMBIENT
, lamb
);
575 static void initdlists(void)
577 GLUquadricObj
*lcone
,*lbase
;
579 GLfloat v0
[3]={0.0,0.0,0.0};
580 GLfloat v1
[3]={1.0,0.0,0.0};
581 GLfloat v2
[3]={0.0,1.0,0.0};
583 findplane(plane
,v0
,v1
,v2
);
584 shadowmatrix(baseshadow
,plane
,lightpos
);
586 teapotdlist
=glGenLists(1);
587 glNewList(teapotdlist
,GL_COMPILE
);
588 glRotatef(90.0,1.0,0.0,0.0);
589 glCullFace(GL_FRONT
);
590 glBindTexture(GL_TEXTURE_2D
,t2id
);
591 glutSolidTeapot(0.75);
595 basedlist
=glGenLists(1);
596 glNewList(basedlist
,GL_COMPILE
);
600 lightdlist
=glGenLists(1);
601 glNewList(lightdlist
,GL_COMPILE
);
602 glDisable(GL_LIGHTING
);
604 lcone
=gluNewQuadric();
605 lbase
=gluNewQuadric();
606 glRotatef(45.0,0.0,1.0,0.0);
608 glColor3f(1.0,1.0,1.0);
609 glCullFace(GL_FRONT
);
610 gluDisk(lbase
,0.0,0.2,12.0,1.0);
613 glColor3f(0.5,0.0,0.0);
614 gluCylinder(lcone
,0.2,0.0,0.5,12,1);
616 gluDeleteQuadric(lcone
);
617 gluDeleteQuadric(lbase
);
619 glEnable(GL_LIGHTING
);
623 int main(int ac
, char **av
)
625 float fogcolor
[4]={0.025,0.025,0.025,1.0};
627 fprintf(stderr
,"Teapot V1.2\nWritten by David Bucciarelli (tech.hmw@plus.it)\n");
630 if(!SetPriorityClass(GetCurrentProcess(),REALTIME_PRIORITY_CLASS)) {
631 fprintf(stderr,"Error setting the process class.\n");
635 if(!SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_TIME_CRITICAL)) {
636 fprintf(stderr,"Error setting the process priority.\n");
641 glutInitWindowPosition(0,0);
642 glutInitWindowSize(WIDTH
,HEIGHT
);
645 glutInitDisplayMode(GLUT_RGB
|GLUT_DEPTH
|GLUT_DOUBLE
);
647 if(!(win
=glutCreateWindow("Teapot"))) {
648 fprintf(stderr
,"Error, couldn't open window\n");
652 reshape(WIDTH
,HEIGHT
);
654 glShadeModel(GL_SMOOTH
);
655 glEnable(GL_DEPTH_TEST
);
656 glEnable(GL_CULL_FACE
);
657 glEnable(GL_TEXTURE_2D
);
660 glFogi(GL_FOG_MODE
,GL_EXP2
);
661 glFogfv(GL_FOG_COLOR
,fogcolor
);
663 glFogf(GL_FOG_DENSITY
,0.04);
664 glHint(GL_FOG_HINT
,GL_NICEST
);
665 glBlendFunc(GL_SRC_ALPHA
,GL_ONE_MINUS_SRC_ALPHA
);
674 glClearColor(fogcolor
[0],fogcolor
[1],fogcolor
[2],fogcolor
[3]);
676 glutReshapeFunc(reshape
);
677 glutDisplayFunc(draw
);
678 glutKeyboardFunc(key
);
679 glutSpecialFunc(special
);