Merge branch 'mesa_7_7_branch'
[mesa.git] / progs / demos / ray.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 <string.h>
12 #include <math.h>
13
14 #ifdef WIN32
15 #include <windows.h>
16 #endif
17
18 #include <GL/glut.h>
19
20 #ifdef XMESA
21 #include "GL/xmesa.h"
22 static int fullscreen = 1;
23 #endif
24
25 static int WIDTH = 640;
26 static int HEIGHT = 480;
27
28 static GLint T0 = 0;
29 static GLint Frames = 0;
30
31 #define BASESIZE 7.5f
32 #define SPHERE_RADIUS 0.75f
33
34 #define TEX_CHECK_WIDTH 256
35 #define TEX_CHECK_HEIGHT 256
36 #define TEX_CHECK_SLOT_SIZE (TEX_CHECK_HEIGHT/16)
37 #define TEX_CHECK_NUMSLOT (TEX_CHECK_HEIGHT/TEX_CHECK_SLOT_SIZE)
38
39 #define TEX_REFLECT_WIDTH 256
40 #define TEX_REFLECT_HEIGHT 256
41 #define TEX_REFLECT_SLOT_SIZE (TEX_REFLECT_HEIGHT/16)
42 #define TEX_REFLECT_NUMSLOT (TEX_REFLECT_HEIGHT/TEX_REFLECT_SLOT_SIZE)
43
44 #ifndef M_PI
45 #define M_PI 3.1415926535
46 #endif
47
48 #define EPSILON 0.0001
49
50 #define clamp255(a) ( (a)<(0.0f) ? (0.0f) : ((a)>(255.0f) ? (255.0f) : (a)) )
51
52 #ifndef fabs
53 #define fabs(x) ((x)<0.0f?-(x):(x))
54 #endif
55
56 #define vequ(a,b) { (a)[0]=(b)[0]; (a)[1]=(b)[1]; (a)[2]=(b)[2]; }
57 #define vsub(a,b,c) { (a)[0]=(b)[0]-(c)[0]; (a)[1]=(b)[1]-(c)[1]; (a)[2]=(b)[2]-(c)[2]; }
58 #define dprod(a,b) ((a)[0]*(b)[0]+(a)[1]*(b)[1]+(a)[2]*(b)[2])
59 #define vnormalize(a,b) { \
60 register float m_norm; \
61 m_norm=sqrt((double)dprod((a),(a))); \
62 (a)[0] /=m_norm; \
63 (a)[1] /=m_norm; \
64 (a)[2] /=m_norm; }
65
66 static GLubyte checkmap[TEX_CHECK_HEIGHT][TEX_CHECK_WIDTH][3];
67 static GLuint checkid;
68 static int checkmap_currentslot = 0;
69
70 static GLubyte reflectmap[TEX_REFLECT_HEIGHT][TEX_REFLECT_WIDTH][3];
71 static GLuint reflectid;
72 static int reflectmap_currentslot = 0;
73
74 static GLuint lightdlist;
75 static GLuint objdlist;
76
77 static float lightpos[3] = { 2.1, 2.1, 2.8 };
78 static float objpos[3] = { 0.0, 0.0, 1.0 };
79
80 static float sphere_pos[TEX_CHECK_HEIGHT][TEX_REFLECT_WIDTH][3];
81
82 static int win = 0;
83
84 static float fogcolor[4] = { 0.05, 0.05, 0.05, 1.0 };
85
86 static float obs[3] = { 7.0, 0.0, 2.0 };
87 static float dir[3];
88 static float v = 0.0;
89 static float alpha = -90.0;
90 static float beta = 90.0;
91
92 static int fog = 1;
93 static int bfcull = 1;
94 static int poutline = 0;
95 static int help = 1;
96 static int showcheckmap = 1;
97 static int showreflectmap = 1;
98 static int joyavailable = 0;
99 static int joyactive = 0;
100
101 static void
102 calcposobs(void)
103 {
104 dir[0] = sin(alpha * M_PI / 180.0);
105 dir[1] = cos(alpha * M_PI / 180.0) * sin(beta * M_PI / 180.0);
106 dir[2] = cos(beta * M_PI / 180.0);
107
108 if (dir[0] < 1.0e-5 && dir[0] > -1.0e-5)
109 dir[0] = 0;
110 if (dir[1] < 1.0e-5 && dir[1] > -1.0e-5)
111 dir[1] = 0;
112 if (dir[2] < 1.0e-5 && dir[2] > -1.0e-5)
113 dir[2] = 0;
114
115 obs[0] += v * dir[0];
116 obs[1] += v * dir[1];
117 obs[2] += v * dir[2];
118 }
119
120 static void
121 special(int k, int x, int y)
122 {
123 switch (k) {
124 case GLUT_KEY_LEFT:
125 alpha -= 2.0;
126 break;
127 case GLUT_KEY_RIGHT:
128 alpha += 2.0;
129 break;
130 case GLUT_KEY_DOWN:
131 beta -= 2.0;
132 break;
133 case GLUT_KEY_UP:
134 beta += 2.0;
135 break;
136 }
137 }
138
139 static void
140 key(unsigned char k, int x, int y)
141 {
142 switch (k) {
143 case 27:
144 exit(0);
145 break;
146
147 case 's':
148 lightpos[1] -= 0.1;
149 break;
150 case 'd':
151 lightpos[1] += 0.1;
152 break;
153 case 'e':
154 lightpos[0] -= 0.1;
155 break;
156 case 'x':
157 lightpos[0] += 0.1;
158 break;
159 case 'w':
160 lightpos[2] -= 0.1;
161 break;
162 case 'r':
163 lightpos[2] += 0.1;
164 break;
165
166 case 'j':
167 objpos[1] -= 0.1;
168 break;
169 case 'k':
170 objpos[1] += 0.1;
171 break;
172 case 'i':
173 objpos[0] -= 0.1;
174 break;
175 case 'm':
176 objpos[0] += 0.1;
177 break;
178 case 'u':
179 objpos[2] -= 0.1;
180 break;
181 case 'o':
182 objpos[2] += 0.1;
183 break;
184
185 case 'a':
186 v += 0.005;
187 break;
188 case 'z':
189 v -= 0.005;
190 break;
191
192 case 'g':
193 joyactive = (!joyactive);
194 break;
195 case 'h':
196 help = (!help);
197 break;
198 case 'f':
199 fog = (!fog);
200 break;
201
202 case '1':
203 showcheckmap = (!showcheckmap);
204 break;
205 case '2':
206 showreflectmap = (!showreflectmap);
207 break;
208
209 case 'b':
210 if (bfcull) {
211 glDisable(GL_CULL_FACE);
212 bfcull = 0;
213 }
214 else {
215 glEnable(GL_CULL_FACE);
216 bfcull = 1;
217 }
218 break;
219 case 'p':
220 if (poutline) {
221 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
222 poutline = 0;
223 }
224 else {
225 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
226 poutline = 1;
227 }
228 break;
229 #ifdef XMESA
230 case ' ':
231 XMesaSetFXmode(fullscreen ? XMESA_FX_FULLSCREEN : XMESA_FX_WINDOW);
232 fullscreen = (!fullscreen);
233 break;
234 #endif
235 }
236 }
237
238 static void
239 reshape(int w, int h)
240 {
241 WIDTH = w;
242 HEIGHT = h;
243 glViewport(0, 0, w, h);
244 glMatrixMode(GL_PROJECTION);
245 glLoadIdentity();
246 gluPerspective(45.0, w / (float) h, 0.8, 40.0);
247 glMatrixMode(GL_MODELVIEW);
248 glLoadIdentity();
249 }
250
251 static void
252 printstring(void *font, char *string)
253 {
254 int len, i;
255
256 len = (int) strlen(string);
257 for (i = 0; i < len; i++)
258 glutBitmapCharacter(font, string[i]);
259 }
260
261 static void
262 printhelp(void)
263 {
264 glEnable(GL_BLEND);
265 glColor4f(0.5, 0.5, 0.5, 0.5);
266 glRecti(40, 40, 600, 440);
267 glDisable(GL_BLEND);
268
269 glColor3f(0.0, 0.0, 1.0);
270 glRasterPos2i(300, 420);
271 printstring(GLUT_BITMAP_HELVETICA_18, "Help");
272
273 glRasterPos2i(60, 390);
274 printstring(GLUT_BITMAP_HELVETICA_12, "h - Toggle Help");
275 glRasterPos2i(60, 370);
276 printstring(GLUT_BITMAP_HELVETICA_12, "f - Toggle Fog");
277 glRasterPos2i(60, 350);
278 printstring(GLUT_BITMAP_HELVETICA_12, "b - Toggle Back face culling");
279 glRasterPos2i(60, 330);
280 printstring(GLUT_BITMAP_HELVETICA_12, "p - Toggle Wire frame");
281 glRasterPos2i(60, 310);
282 printstring(GLUT_BITMAP_HELVETICA_12, "Arrow Keys - Rotate");
283 glRasterPos2i(60, 290);
284 printstring(GLUT_BITMAP_HELVETICA_12, "a - Increase velocity");
285 glRasterPos2i(60, 270);
286 printstring(GLUT_BITMAP_HELVETICA_12, "z - Decrease velocity");
287
288 glRasterPos2i(60, 250);
289 if (joyavailable)
290 printstring(GLUT_BITMAP_HELVETICA_12,
291 "j - Toggle jostick control (Joystick control available)");
292 else
293 printstring(GLUT_BITMAP_HELVETICA_12,
294 "(No Joystick control available)");
295
296 glRasterPos2i(60, 230);
297 printstring(GLUT_BITMAP_HELVETICA_12,
298 "To move the light source: s - left, d - right, e - far, x - near, w - down r - up");
299 glRasterPos2i(60, 210);
300 printstring(GLUT_BITMAP_HELVETICA_12,
301 "To move the mirror sphere: j - left, k - right, i - far, m - near, u - down o - up");
302
303 glRasterPos2i(60, 190);
304 printstring(GLUT_BITMAP_HELVETICA_12,
305 "1 - Toggle the plane texture map window");
306
307 glRasterPos2i(60, 170);
308 printstring(GLUT_BITMAP_HELVETICA_12,
309 "2 - Toggle the sphere texture map window");
310 }
311
312 static GLboolean
313 seelight(float p[3], float dir[3])
314 {
315 float c[3], b, a, d, t, dist[3];
316
317 vsub(c, p, objpos);
318 b = -dprod(c, dir);
319 a = dprod(c, c) - SPHERE_RADIUS * SPHERE_RADIUS;
320
321 if ((d = b * b - a) < 0.0 || (b < 0.0 && a > 0.0))
322 return GL_FALSE;
323
324 d = sqrt(d);
325
326 t = b - d;
327
328 if (t < EPSILON) {
329 t = b + d;
330 if (t < EPSILON)
331 return GL_FALSE;
332 }
333
334 vsub(dist, lightpos, p);
335 if (dprod(dist, dist) < t * t)
336 return GL_FALSE;
337
338 return GL_TRUE;
339 }
340
341 static int
342 colorcheckmap(float ppos[3], float c[3])
343 {
344 static float norm[3] = { 0.0f, 0.0f, 1.0f };
345 float ldir[3], vdir[3], h[3], dfact, kfact, r, g, b;
346 int x, y;
347
348 x = (int) ((ppos[0] + BASESIZE / 2) * (10.0f / BASESIZE));
349 if ((x < 0) || (x > 10))
350 return GL_FALSE;
351
352 y = (int) ((ppos[1] + BASESIZE / 2) * (10.0f / BASESIZE));
353 if ((y < 0) || (y > 10))
354 return GL_FALSE;
355
356 r = 255.0f;
357 if (y & 1) {
358 if (x & 1)
359 g = 255.0f;
360 else
361 g = 0.0f;
362 }
363 else {
364 if (x & 1)
365 g = 0.0f;
366 else
367 g = 255.0f;
368 }
369 b = 0.0f;
370
371 vsub(ldir, lightpos, ppos);
372 vnormalize(ldir, ldir);
373
374 if (seelight(ppos, ldir)) {
375 c[0] = r * 0.05f;
376 c[1] = g * 0.05f;
377 c[2] = b * 0.05f;
378
379 return GL_TRUE;
380 }
381
382 dfact = dprod(ldir, norm);
383 if (dfact < 0.0f)
384 dfact = 0.0f;
385
386 vsub(vdir, obs, ppos);
387 vnormalize(vdir, vdir);
388 h[0] = 0.5f * (vdir[0] + ldir[0]);
389 h[1] = 0.5f * (vdir[1] + ldir[1]);
390 h[2] = 0.5f * (vdir[2] + ldir[2]);
391 kfact = dprod(h, norm);
392 kfact = pow(kfact, 6.0) * 7.0 * 255.0;
393
394 r = r * dfact + kfact;
395 g = g * dfact + kfact;
396 b = b * dfact + kfact;
397
398 c[0] = clamp255(r);
399 c[1] = clamp255(g);
400 c[2] = clamp255(b);
401
402 return GL_TRUE;
403 }
404
405 static void
406 updatecheckmap(int slot)
407 {
408 float c[3], ppos[3];
409 int x, y;
410
411 glBindTexture(GL_TEXTURE_2D, checkid);
412
413 ppos[2] = 0.0f;
414 for (y = slot * TEX_CHECK_SLOT_SIZE; y < (slot + 1) * TEX_CHECK_SLOT_SIZE;
415 y++) {
416 ppos[1] = (y / (float) TEX_CHECK_HEIGHT) * BASESIZE - BASESIZE / 2;
417
418 for (x = 0; x < TEX_CHECK_WIDTH; x++) {
419 ppos[0] = (x / (float) TEX_CHECK_WIDTH) * BASESIZE - BASESIZE / 2;
420
421 colorcheckmap(ppos, c);
422 checkmap[y][x][0] = (GLubyte) c[0];
423 checkmap[y][x][1] = (GLubyte) c[1];
424 checkmap[y][x][2] = (GLubyte) c[2];
425 }
426 }
427
428 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, slot * TEX_CHECK_SLOT_SIZE,
429 TEX_CHECK_WIDTH, TEX_CHECK_SLOT_SIZE, GL_RGB,
430 GL_UNSIGNED_BYTE,
431 &checkmap[slot * TEX_CHECK_SLOT_SIZE][0][0]);
432
433 }
434
435 static void
436 updatereflectmap(int slot)
437 {
438 float rf, r, g, b, t, dfact, kfact, rdir[3];
439 float rcol[3], ppos[3], norm[3], ldir[3], h[3], vdir[3], planepos[3];
440 int x, y;
441
442 glBindTexture(GL_TEXTURE_2D, reflectid);
443
444 for (y = slot * TEX_REFLECT_SLOT_SIZE;
445 y < (slot + 1) * TEX_REFLECT_SLOT_SIZE; y++)
446 for (x = 0; x < TEX_REFLECT_WIDTH; x++) {
447 ppos[0] = sphere_pos[y][x][0] + objpos[0];
448 ppos[1] = sphere_pos[y][x][1] + objpos[1];
449 ppos[2] = sphere_pos[y][x][2] + objpos[2];
450
451 vsub(norm, ppos, objpos);
452 vnormalize(norm, norm);
453
454 vsub(ldir, lightpos, ppos);
455 vnormalize(ldir, ldir);
456 vsub(vdir, obs, ppos);
457 vnormalize(vdir, vdir);
458
459 rf = 2.0f * dprod(norm, vdir);
460 if (rf > EPSILON) {
461 rdir[0] = rf * norm[0] - vdir[0];
462 rdir[1] = rf * norm[1] - vdir[1];
463 rdir[2] = rf * norm[2] - vdir[2];
464
465 t = -objpos[2] / rdir[2];
466
467 if (t > EPSILON) {
468 planepos[0] = objpos[0] + t * rdir[0];
469 planepos[1] = objpos[1] + t * rdir[1];
470 planepos[2] = 0.0f;
471
472 if (!colorcheckmap(planepos, rcol))
473 rcol[0] = rcol[1] = rcol[2] = 0.0f;
474 }
475 else
476 rcol[0] = rcol[1] = rcol[2] = 0.0f;
477 }
478 else
479 rcol[0] = rcol[1] = rcol[2] = 0.0f;
480
481 dfact = 0.1f * dprod(ldir, norm);
482
483 if (dfact < 0.0f) {
484 dfact = 0.0f;
485 kfact = 0.0f;
486 }
487 else {
488 h[0] = 0.5f * (vdir[0] + ldir[0]);
489 h[1] = 0.5f * (vdir[1] + ldir[1]);
490 h[2] = 0.5f * (vdir[2] + ldir[2]);
491 kfact = dprod(h, norm);
492 kfact = pow(kfact, 4.0);
493 if (kfact < 1.0e-10)
494 kfact = 0.0;
495 }
496
497 r = dfact + kfact;
498 g = dfact + kfact;
499 b = dfact + kfact;
500
501 r *= 255.0f;
502 g *= 255.0f;
503 b *= 255.0f;
504
505 r += rcol[0];
506 g += rcol[1];
507 b += rcol[2];
508
509 r = clamp255(r);
510 g = clamp255(g);
511 b = clamp255(b);
512
513 reflectmap[y][x][0] = (GLubyte) r;
514 reflectmap[y][x][1] = (GLubyte) g;
515 reflectmap[y][x][2] = (GLubyte) b;
516 }
517
518 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, slot * TEX_REFLECT_SLOT_SIZE,
519 TEX_REFLECT_WIDTH, TEX_REFLECT_SLOT_SIZE, GL_RGB,
520 GL_UNSIGNED_BYTE,
521 &reflectmap[slot * TEX_REFLECT_SLOT_SIZE][0][0]);
522 }
523
524 static void
525 drawbase(void)
526 {
527 glColor3f(0.0, 0.0, 0.0);
528 glBindTexture(GL_TEXTURE_2D, checkid);
529 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
530
531 glBegin(GL_QUADS);
532 glTexCoord2f(0.0f, 0.0f);
533 glVertex3f(-BASESIZE / 2.0f, -BASESIZE / 2.0f, 0.0f);
534
535 glTexCoord2f(1.0f, 0.0f);
536 glVertex3f(BASESIZE / 2.0f, -BASESIZE / 2.0f, 0.0f);
537
538 glTexCoord2f(1.0f, 1.0f);
539 glVertex3f(BASESIZE / 2.0f, BASESIZE / 2.0f, 0.0f);
540
541 glTexCoord2f(0.0f, 1.0f);
542 glVertex3f(-BASESIZE / 2.0f, BASESIZE / 2.0f, 0.0f);
543
544 glEnd();
545 }
546
547 static void
548 drawobj(void)
549 {
550 glColor3f(0.0, 0.0, 0.0);
551 glBindTexture(GL_TEXTURE_2D, reflectid);
552 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
553
554 glPushMatrix();
555 glTranslatef(objpos[0], objpos[1], objpos[2]);
556 glCallList(objdlist);
557 glPopMatrix();
558 }
559
560 static void
561 dojoy(void)
562 {
563 #ifdef WIN32
564 static UINT max[2] = { 0, 0 };
565 static UINT min[2] = { 0xffffffff, 0xffffffff }, center[2];
566 MMRESULT res;
567 JOYINFO joy;
568
569 res = joyGetPos(JOYSTICKID1, &joy);
570
571 if (res == JOYERR_NOERROR) {
572 joyavailable = 1;
573
574 if (max[0] < joy.wXpos)
575 max[0] = joy.wXpos;
576 if (min[0] > joy.wXpos)
577 min[0] = joy.wXpos;
578 center[0] = (max[0] + min[0]) / 2;
579
580 if (max[1] < joy.wYpos)
581 max[1] = joy.wYpos;
582 if (min[1] > joy.wYpos)
583 min[1] = joy.wYpos;
584 center[1] = (max[1] + min[1]) / 2;
585
586 if (joyactive) {
587 if (fabs(center[0] - (float) joy.wXpos) > 0.1 * (max[0] - min[0]))
588 alpha -=
589 2.5 * (center[0] - (float) joy.wXpos) / (max[0] - min[0]);
590 if (fabs(center[1] - (float) joy.wYpos) > 0.1 * (max[1] - min[1]))
591 beta += 2.5 * (center[1] - (float) joy.wYpos) / (max[1] - min[1]);
592
593 if (joy.wButtons & JOY_BUTTON1)
594 v += 0.005;
595 if (joy.wButtons & JOY_BUTTON2)
596 v -= 0.005;
597 }
598 }
599 else
600 joyavailable = 0;
601 #endif
602 }
603
604 static void
605 updatemaps(void)
606 {
607 updatecheckmap(checkmap_currentslot);
608 checkmap_currentslot = (checkmap_currentslot + 1) % TEX_CHECK_NUMSLOT;
609
610 updatereflectmap(reflectmap_currentslot);
611 reflectmap_currentslot =
612 (reflectmap_currentslot + 1) % TEX_REFLECT_NUMSLOT;
613 }
614
615 static void
616 draw(void)
617 {
618 static char frbuf[80] = "";
619
620 dojoy();
621
622 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
623
624 glEnable(GL_TEXTURE_2D);
625 glEnable(GL_DEPTH_TEST);
626 if (fog)
627 glEnable(GL_FOG);
628 else
629 glDisable(GL_FOG);
630
631 glPushMatrix();
632 calcposobs();
633
634 gluLookAt(obs[0], obs[1], obs[2],
635 obs[0] + dir[0], obs[1] + dir[1], obs[2] + dir[2],
636 0.0, 0.0, 1.0);
637
638 drawbase();
639 drawobj();
640
641 glColor3f(1.0, 1.0, 1.0);
642 glDisable(GL_TEXTURE_2D);
643
644 glPushMatrix();
645 glTranslatef(lightpos[0], lightpos[1], lightpos[2]);
646 glCallList(lightdlist);
647 glPopMatrix();
648
649 glPopMatrix();
650
651 glDisable(GL_DEPTH_TEST);
652 glDisable(GL_FOG);
653
654 glMatrixMode(GL_PROJECTION);
655 glPushMatrix();
656 glLoadIdentity();
657 glOrtho(-0.5, 639.5, -0.5, 479.5, -1.0, 1.0);
658 glMatrixMode(GL_MODELVIEW);
659
660 glColor3f(0.0f, 0.3f, 1.0f);
661
662 if (showcheckmap) {
663 glEnable(GL_TEXTURE_2D);
664 glBindTexture(GL_TEXTURE_2D, checkid);
665 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
666
667 glBegin(GL_QUADS);
668 glTexCoord2f(1.0f, 0.0f);
669 glVertex2i(10, 30);
670 glTexCoord2f(1.0f, 1.0f);
671 glVertex2i(10 + 90, 30);
672 glTexCoord2f(0.0f, 1.0f);
673 glVertex2i(10 + 90, 30 + 90);
674 glTexCoord2f(0.0f, 0.0f);
675 glVertex2i(10, 30 + 90);
676 glEnd();
677
678 glDisable(GL_TEXTURE_2D);
679 glBegin(GL_LINE_LOOP);
680 glVertex2i(10, 30);
681 glVertex2i(10 + 90, 30);
682 glVertex2i(10 + 90, 30 + 90);
683 glVertex2i(10, 30 + 90);
684 glEnd();
685 glRasterPos2i(105, 65);
686 printstring(GLUT_BITMAP_HELVETICA_18, "Plane Texture Map");
687 }
688
689 if (showreflectmap) {
690 glEnable(GL_TEXTURE_2D);
691 glBindTexture(GL_TEXTURE_2D, reflectid);
692 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
693
694 glBegin(GL_QUADS);
695 glTexCoord2f(1.0f, 0.0f);
696 glVertex2i(540, 30);
697 glTexCoord2f(1.0f, 1.0f);
698 glVertex2i(540 + 90, 30);
699 glTexCoord2f(0.0f, 1.0f);
700 glVertex2i(540 + 90, 30 + 90);
701 glTexCoord2f(0.0f, 0.0f);
702 glVertex2i(540, 30 + 90);
703 glEnd();
704
705 glDisable(GL_TEXTURE_2D);
706 glBegin(GL_LINE_LOOP);
707 glVertex2i(540, 30);
708 glVertex2i(540 + 90, 30);
709 glVertex2i(540 + 90, 30 + 90);
710 glVertex2i(540, 30 + 90);
711 glEnd();
712 glRasterPos2i(360, 65);
713 printstring(GLUT_BITMAP_HELVETICA_18, "Sphere Texture Map");
714 }
715
716 glDisable(GL_TEXTURE_2D);
717
718 glRasterPos2i(10, 10);
719 printstring(GLUT_BITMAP_HELVETICA_18, frbuf);
720 glRasterPos2i(360, 470);
721 printstring(GLUT_BITMAP_HELVETICA_10,
722 "Ray V1.0 Written by David Bucciarelli (tech.hmw@plus.it)");
723
724 if (help)
725 printhelp();
726
727 glMatrixMode(GL_PROJECTION);
728 glPopMatrix();
729 glMatrixMode(GL_MODELVIEW);
730
731 updatemaps();
732
733 glutSwapBuffers();
734
735 Frames++;
736 {
737 GLint t = glutGet(GLUT_ELAPSED_TIME);
738 if (t - T0 >= 2000) {
739 GLfloat seconds = (t - T0) / 1000.0;
740 GLfloat fps = Frames / seconds;
741 sprintf(frbuf, "Frame rate: %f", fps);
742 T0 = t;
743 Frames = 0;
744 }
745 }
746 }
747
748 static void
749 inittextures(void)
750 {
751 int y;
752
753 glGenTextures(1, &checkid);
754 glBindTexture(GL_TEXTURE_2D, checkid);
755
756 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
757 glTexImage2D(GL_TEXTURE_2D, 0, 3, TEX_CHECK_WIDTH, TEX_CHECK_HEIGHT,
758 0, GL_RGB, GL_UNSIGNED_BYTE, checkmap);
759
760 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
761 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
762
763 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
764 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
765
766 for (y = 0; y < TEX_CHECK_NUMSLOT; y++)
767 updatecheckmap(y);
768
769
770
771 glGenTextures(1, &reflectid);
772 glBindTexture(GL_TEXTURE_2D, reflectid);
773
774 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
775 glTexImage2D(GL_TEXTURE_2D, 0, 3, TEX_REFLECT_WIDTH, TEX_REFLECT_HEIGHT,
776 0, GL_RGB, GL_UNSIGNED_BYTE, reflectmap);
777
778 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
779 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
780
781 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
782 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
783
784 for (y = 0; y < TEX_REFLECT_NUMSLOT; y++)
785 updatereflectmap(y);
786
787
788 }
789
790 static void
791 initspherepos(void)
792 {
793 float alpha, beta, sa, ca, sb, cb;
794 int x, y;
795
796 for (y = 0; y < TEX_REFLECT_HEIGHT; y++) {
797 beta = M_PI - y * (M_PI / TEX_REFLECT_HEIGHT);
798
799 for (x = 0; x < TEX_REFLECT_WIDTH; x++) {
800 alpha = -x * (2.0f * M_PI / TEX_REFLECT_WIDTH);
801
802 sa = sin(alpha);
803 ca = cos(alpha);
804
805 sb = sin(beta);
806 cb = cos(beta);
807
808 sphere_pos[y][x][0] = SPHERE_RADIUS * sa * sb;
809 sphere_pos[y][x][1] = SPHERE_RADIUS * ca * sb;
810 sphere_pos[y][x][2] = SPHERE_RADIUS * cb;
811 }
812 }
813 }
814
815 static void
816 initdlists(void)
817 {
818 GLUquadricObj *obj;
819
820 obj = gluNewQuadric();
821
822 lightdlist = glGenLists(1);
823 glNewList(lightdlist, GL_COMPILE);
824 gluQuadricDrawStyle(obj, GLU_FILL);
825 gluQuadricNormals(obj, GLU_NONE);
826 gluQuadricTexture(obj, GL_TRUE);
827 gluSphere(obj, 0.25f, 6, 6);
828 glEndList();
829
830 objdlist = glGenLists(1);
831 glNewList(objdlist, GL_COMPILE);
832 gluQuadricDrawStyle(obj, GLU_FILL);
833 gluQuadricNormals(obj, GLU_NONE);
834 gluQuadricTexture(obj, GL_TRUE);
835 gluSphere(obj, SPHERE_RADIUS, 16, 16);
836 glEndList();
837
838 gluDeleteQuadric(obj);
839 }
840
841 int
842 main(int ac, char **av)
843 {
844 fprintf(stderr,
845 "Ray V1.0\nWritten by David Bucciarelli (tech.hmw@plus.it)\n");
846
847 /*
848 if(!SetPriorityClass(GetCurrentProcess(),REALTIME_PRIORITY_CLASS)) {
849 fprintf(stderr,"Error setting the process class.\n");
850 return 0;
851 }
852
853 if(!SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_TIME_CRITICAL)) {
854 fprintf(stderr,"Error setting the process priority.\n");
855 return 0;
856 }
857 */
858
859 glutInitWindowSize(WIDTH, HEIGHT);
860 glutInit(&ac, av);
861
862 glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
863
864 if (!(win = glutCreateWindow("Ray"))) {
865 fprintf(stderr, "Error, couldn't open window\n");
866 return -1;
867 }
868
869 reshape(WIDTH, HEIGHT);
870
871 glShadeModel(GL_FLAT);
872 glEnable(GL_DEPTH_TEST);
873 glDepthFunc(GL_LEQUAL);
874 glEnable(GL_CULL_FACE);
875 glEnable(GL_TEXTURE_2D);
876 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
877
878 glEnable(GL_FOG);
879 glFogi(GL_FOG_MODE, GL_EXP2);
880 glFogfv(GL_FOG_COLOR, fogcolor);
881
882 glFogf(GL_FOG_DENSITY, 0.01);
883 #ifdef FX
884 glHint(GL_FOG_HINT, GL_NICEST);
885 #endif
886
887 calcposobs();
888
889 initspherepos();
890
891 inittextures();
892 initdlists();
893
894 glClearColor(fogcolor[0], fogcolor[1], fogcolor[2], fogcolor[3]);
895
896 glutReshapeFunc(reshape);
897 glutDisplayFunc(draw);
898 glutKeyboardFunc(key);
899 glutSpecialFunc(special);
900 glutIdleFunc(draw);
901
902 glutMainLoop();
903
904 return 0;
905 }