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