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