ARB prog parser: fix parameter binding type
[mesa.git] / progs / demos / projtex.c
1
2 /* projtex.c - by David Yu and David Blythe, SGI */
3
4 /**
5 ** Demonstrates simple projective texture mapping.
6 **
7 ** Button1 changes view, Button2 moves texture.
8 **
9 ** (See: Segal, Korobkin, van Widenfelt, Foran, and Haeberli
10 ** "Fast Shadows and Lighting Effects Using Texture Mapping", SIGGRAPH '92)
11 **
12 ** 1994,1995 -- David G Yu
13 **
14 ** cc -o projtex projtex.c texture.c -lglut -lGLU -lGL -lX11 -lm
15 **/
16
17 #include <assert.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <math.h>
21 #include <GL/glew.h>
22 #include <GL/glut.h>
23 #include "readtex.h"
24
25
26 /* Some <math.h> files do not define M_PI... */
27 #ifndef M_PI
28 #define M_PI 3.14159265358979323846
29 #endif
30
31 #define MAX_TEX 4
32 int NumTextures = 1;
33
34 int winWidth, winHeight;
35
36 GLboolean redrawContinuously = GL_FALSE;
37
38 float angle, axis[3];
39 enum MoveModes {
40 MoveNone, MoveView, MoveObject, MoveTexture
41 };
42 enum MoveModes mode = MoveNone;
43
44 GLfloat objectXform[4][4];
45 GLfloat textureXform[MAX_TEX][4][4];
46
47 void (*drawObject) (void);
48 void (*loadTexture) (void);
49 GLboolean textureEnabled = GL_TRUE;
50 GLboolean showProjection = GL_TRUE;
51 GLboolean linearFilter = GL_TRUE;
52
53 char *texFilename[MAX_TEX] = {
54 "../images/girl.rgb",
55 "../images/tile.rgb",
56 "../images/bw.rgb",
57 "../images/reflect.rgb"
58 };
59
60
61 GLfloat zoomFactor = 1.0;
62
63 /*****************************************************************/
64
65
66 static void
67 ActiveTexture(int i)
68 {
69 glActiveTextureARB(i);
70 }
71
72
73 /* matrix = identity */
74 static void
75 matrixIdentity(GLfloat matrix[16])
76 {
77 matrix[0] = 1.0;
78 matrix[1] = 0.0;
79 matrix[2] = 0.0;
80 matrix[3] = 0.0;
81 matrix[4] = 0.0;
82 matrix[5] = 1.0;
83 matrix[6] = 0.0;
84 matrix[7] = 0.0;
85 matrix[8] = 0.0;
86 matrix[9] = 0.0;
87 matrix[10] = 1.0;
88 matrix[11] = 0.0;
89 matrix[12] = 0.0;
90 matrix[13] = 0.0;
91 matrix[14] = 0.0;
92 matrix[15] = 1.0;
93 }
94
95 /* matrix2 = transpose(matrix1) */
96 static void
97 matrixTranspose(GLfloat matrix2[16], GLfloat matrix1[16])
98 {
99 matrix2[0] = matrix1[0];
100 matrix2[1] = matrix1[4];
101 matrix2[2] = matrix1[8];
102 matrix2[3] = matrix1[12];
103
104 matrix2[4] = matrix1[1];
105 matrix2[5] = matrix1[5];
106 matrix2[6] = matrix1[9];
107 matrix2[7] = matrix1[13];
108
109 matrix2[8] = matrix1[2];
110 matrix2[9] = matrix1[6];
111 matrix2[10] = matrix1[10];
112 matrix2[11] = matrix1[14];
113
114 matrix2[12] = matrix1[3];
115 matrix2[13] = matrix1[7];
116 matrix2[14] = matrix1[14];
117 matrix2[15] = matrix1[15];
118 }
119
120 /*****************************************************************/
121
122 /* load SGI .rgb image (pad with a border of the specified width and color) */
123 #if 0
124 static void
125 imgLoad(char *filenameIn, int borderIn, GLfloat borderColorIn[4],
126 int *wOut, int *hOut, GLubyte ** imgOut)
127 {
128 int border = borderIn;
129 int width, height;
130 int w, h;
131 GLubyte *image, *img, *p;
132 int i, j, components;
133
134 image = (GLubyte *) read_texture(filenameIn, &width, &height, &components);
135 w = width + 2 * border;
136 h = height + 2 * border;
137 img = (GLubyte *) calloc(w * h, 4 * sizeof(unsigned char));
138
139 p = img;
140 for (j = -border; j < height + border; ++j) {
141 for (i = -border; i < width + border; ++i) {
142 if (0 <= j && j <= height - 1 && 0 <= i && i <= width - 1) {
143 p[0] = image[4 * (j * width + i) + 0];
144 p[1] = image[4 * (j * width + i) + 1];
145 p[2] = image[4 * (j * width + i) + 2];
146 p[3] = 0xff;
147 } else {
148 p[0] = borderColorIn[0] * 0xff;
149 p[1] = borderColorIn[1] * 0xff;
150 p[2] = borderColorIn[2] * 0xff;
151 p[3] = borderColorIn[3] * 0xff;
152 }
153 p += 4;
154 }
155 }
156 free(image);
157 *wOut = w;
158 *hOut = h;
159 *imgOut = img;
160 }
161 #endif
162
163
164 /*****************************************************************/
165
166 /* Load the image file specified on the command line as the current texture */
167 static void
168 loadImageTextures(void)
169 {
170 GLfloat borderColor[4] =
171 {1.0, 1.0, 1.0, 1.0};
172 int tex;
173
174 for (tex = 0; tex < NumTextures; tex++) {
175 GLubyte *image, *texData3, *texData4;
176 GLint imgWidth, imgHeight;
177 GLenum imgFormat;
178 int i, j;
179
180 printf("loading %s\n", texFilename[tex]);
181 image = LoadRGBImage(texFilename[tex], &imgWidth, &imgHeight, &imgFormat);
182 if (!image) {
183 printf("can't find %s\n", texFilename[tex]);
184 exit(1);
185 }
186 assert(imgFormat == GL_RGB);
187
188 /* scale to 256x256 */
189 texData3 = malloc(256 * 256 * 4);
190 texData4 = malloc(256 * 256 * 4);
191 assert(texData3);
192 assert(texData4);
193 gluScaleImage(imgFormat, imgWidth, imgHeight, GL_UNSIGNED_BYTE, image,
194 256, 256, GL_UNSIGNED_BYTE, texData3);
195
196 /* convert to rgba */
197 for (i = 0; i < 256 * 256; i++) {
198 texData4[i*4+0] = texData3[i*3+0];
199 texData4[i*4+1] = texData3[i*3+1];
200 texData4[i*4+2] = texData3[i*3+2];
201 texData4[i*4+3] = 128;
202 }
203
204 /* put transparent border around image */
205 for (i = 0; i < 256; i++) {
206 texData4[i*4+0] = 255;
207 texData4[i*4+1] = 255;
208 texData4[i*4+2] = 255;
209 texData4[i*4+3] = 0;
210 }
211 j = 256 * 255 * 4;
212 for (i = 0; i < 256; i++) {
213 texData4[j + i*4+0] = 255;
214 texData4[j + i*4+1] = 255;
215 texData4[j + i*4+2] = 255;
216 texData4[j + i*4+3] = 0;
217 }
218 for (i = 0; i < 256; i++) {
219 j = i * 256 * 4;
220 texData4[j+0] = 255;
221 texData4[j+1] = 255;
222 texData4[j+2] = 255;
223 texData4[j+3] = 0;
224 }
225 for (i = 0; i < 256; i++) {
226 j = i * 256 * 4 + 255 * 4;
227 texData4[j+0] = 255;
228 texData4[j+1] = 255;
229 texData4[j+2] = 255;
230 texData4[j+3] = 0;
231 }
232
233 ActiveTexture(GL_TEXTURE0_ARB + tex);
234 glBindTexture(GL_TEXTURE_2D, tex + 1);
235
236 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
237 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0,
238 GL_RGBA, GL_UNSIGNED_BYTE, texData4);
239
240 if (linearFilter) {
241 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
242 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
243 } else {
244 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
245 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
246 }
247 glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
248
249 free(texData3);
250 free(texData4);
251 free(image);
252 }
253 }
254
255 /* Create a simple spotlight pattern and make it the current texture */
256 static void
257 loadSpotlightTexture(void)
258 {
259 static int texWidth = 64, texHeight = 64;
260 static GLubyte *texData;
261 GLfloat borderColor[4] =
262 {0.1, 0.1, 0.1, 1.0};
263
264 if (!texData) {
265 GLubyte *p;
266 int i, j;
267
268 texData = (GLubyte *) malloc(texWidth * texHeight * 4 * sizeof(GLubyte));
269
270 p = texData;
271 for (j = 0; j < texHeight; ++j) {
272 float dy = (texHeight * 0.5 - j + 0.5) / (texHeight * 0.5);
273
274 for (i = 0; i < texWidth; ++i) {
275 float dx = (texWidth * 0.5 - i + 0.5) / (texWidth * 0.5);
276 float r = cos(M_PI / 2.0 * sqrt(dx * dx + dy * dy));
277 float c;
278
279 r = (r < 0) ? 0 : r * r;
280 c = 0xff * (r + borderColor[0]);
281 p[0] = (c <= 0xff) ? c : 0xff;
282 c = 0xff * (r + borderColor[1]);
283 p[1] = (c <= 0xff) ? c : 0xff;
284 c = 0xff * (r + borderColor[2]);
285 p[2] = (c <= 0xff) ? c : 0xff;
286 c = 0xff * (r + borderColor[3]);
287 p[3] = (c <= 0xff) ? c : 0xff;
288 p += 4;
289 }
290 }
291 }
292 if (linearFilter) {
293 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
294 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
295 } else {
296 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
297 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
298 }
299 glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
300 gluBuild2DMipmaps(GL_TEXTURE_2D, 4, texWidth, texHeight,
301 GL_RGBA, GL_UNSIGNED_BYTE, texData);
302 }
303
304 /*****************************************************************/
305
306 static void
307 checkErrors(void)
308 {
309 GLenum error;
310 while ((error = glGetError()) != GL_NO_ERROR) {
311 fprintf(stderr, "Error: %s\n", (char *) gluErrorString(error));
312 }
313 }
314
315 static void
316 drawCube(void)
317 {
318 glBegin(GL_QUADS);
319
320 glNormal3f(-1.0, 0.0, 0.0);
321 glColor3f(0.80, 0.50, 0.50);
322 glVertex3f(-0.5, -0.5, -0.5);
323 glVertex3f(-0.5, -0.5, 0.5);
324 glVertex3f(-0.5, 0.5, 0.5);
325 glVertex3f(-0.5, 0.5, -0.5);
326
327 glNormal3f(1.0, 0.0, 0.0);
328 glColor3f(0.50, 0.80, 0.50);
329 glVertex3f(0.5, 0.5, 0.5);
330 glVertex3f(0.5, -0.5, 0.5);
331 glVertex3f(0.5, -0.5, -0.5);
332 glVertex3f(0.5, 0.5, -0.5);
333
334 glNormal3f(0.0, -1.0, 0.0);
335 glColor3f(0.50, 0.50, 0.80);
336 glVertex3f(-0.5, -0.5, -0.5);
337 glVertex3f(0.5, -0.5, -0.5);
338 glVertex3f(0.5, -0.5, 0.5);
339 glVertex3f(-0.5, -0.5, 0.5);
340
341 glNormal3f(0.0, 1.0, 0.0);
342 glColor3f(0.50, 0.80, 0.80);
343 glVertex3f(0.5, 0.5, 0.5);
344 glVertex3f(0.5, 0.5, -0.5);
345 glVertex3f(-0.5, 0.5, -0.5);
346 glVertex3f(-0.5, 0.5, 0.5);
347
348 glNormal3f(0.0, 0.0, -1.0);
349 glColor3f(0.80, 0.50, 0.80);
350 glVertex3f(-0.5, -0.5, -0.5);
351 glVertex3f(-0.5, 0.5, -0.5);
352 glVertex3f(0.5, 0.5, -0.5);
353 glVertex3f(0.5, -0.5, -0.5);
354
355 glNormal3f(0.0, 0.0, 1.0);
356 glColor3f(1.00, 0.80, 0.50);
357 glVertex3f(0.5, 0.5, 0.5);
358 glVertex3f(-0.5, 0.5, 0.5);
359 glVertex3f(-0.5, -0.5, 0.5);
360 glVertex3f(0.5, -0.5, 0.5);
361 glEnd();
362 }
363
364 static void
365 drawDodecahedron(void)
366 {
367 #define A (0.5 * 1.61803) /* (sqrt(5) + 1) / 2 */
368 #define B (0.5 * 0.61803) /* (sqrt(5) - 1) / 2 */
369 #define C (0.5 * 1.0)
370 GLfloat vertexes[20][3] =
371 {
372 {-A, 0.0, B},
373 {-A, 0.0, -B},
374 {A, 0.0, -B},
375 {A, 0.0, B},
376 {B, -A, 0.0},
377 {-B, -A, 0.0},
378 {-B, A, 0.0},
379 {B, A, 0.0},
380 {0.0, B, -A},
381 {0.0, -B, -A},
382 {0.0, -B, A},
383 {0.0, B, A},
384 {-C, -C, C},
385 {-C, -C, -C},
386 {C, -C, -C},
387 {C, -C, C},
388 {-C, C, C},
389 {-C, C, -C},
390 {C, C, -C},
391 {C, C, C},
392 };
393 #undef A
394 #undef B
395 #undef C
396 GLint polygons[12][5] =
397 {
398 {0, 12, 10, 11, 16},
399 {1, 17, 8, 9, 13},
400 {2, 14, 9, 8, 18},
401 {3, 19, 11, 10, 15},
402 {4, 14, 2, 3, 15},
403 {5, 12, 0, 1, 13},
404 {6, 17, 1, 0, 16},
405 {7, 19, 3, 2, 18},
406 {8, 17, 6, 7, 18},
407 {9, 14, 4, 5, 13},
408 {10, 12, 5, 4, 15},
409 {11, 19, 7, 6, 16},
410 };
411 int i;
412
413 glColor3f(0.75, 0.75, 0.75);
414 for (i = 0; i < 12; ++i) {
415 GLfloat *p0, *p1, *p2, d;
416 GLfloat u[3], v[3], n[3];
417
418 p0 = &vertexes[polygons[i][0]][0];
419 p1 = &vertexes[polygons[i][1]][0];
420 p2 = &vertexes[polygons[i][2]][0];
421
422 u[0] = p2[0] - p1[0];
423 u[1] = p2[1] - p1[1];
424 u[2] = p2[2] - p1[2];
425
426 v[0] = p0[0] - p1[0];
427 v[1] = p0[1] - p1[1];
428 v[2] = p0[2] - p1[2];
429
430 n[0] = u[1] * v[2] - u[2] * v[1];
431 n[1] = u[2] * v[0] - u[0] * v[2];
432 n[2] = u[0] * v[1] - u[1] * v[0];
433
434 d = 1.0 / sqrt(n[0] * n[0] + n[1] * n[1] + n[2] * n[2]);
435 n[0] *= d;
436 n[1] *= d;
437 n[2] *= d;
438
439 glBegin(GL_POLYGON);
440 glNormal3fv(n);
441 glVertex3fv(p0);
442 glVertex3fv(p1);
443 glVertex3fv(p2);
444 glVertex3fv(vertexes[polygons[i][3]]);
445 glVertex3fv(vertexes[polygons[i][4]]);
446 glEnd();
447 }
448 }
449
450 static void
451 drawSphere(void)
452 {
453 int numMajor = 24;
454 int numMinor = 32;
455 float radius = 0.8;
456 double majorStep = (M_PI / numMajor);
457 double minorStep = (2.0 * M_PI / numMinor);
458 int i, j;
459
460 glColor3f(0.50, 0.50, 0.50);
461 for (i = 0; i < numMajor; ++i) {
462 double a = i * majorStep;
463 double b = a + majorStep;
464 double r0 = radius * sin(a);
465 double r1 = radius * sin(b);
466 GLfloat z0 = radius * cos(a);
467 GLfloat z1 = radius * cos(b);
468
469 glBegin(GL_TRIANGLE_STRIP);
470 for (j = 0; j <= numMinor; ++j) {
471 double c = j * minorStep;
472 GLfloat x = cos(c);
473 GLfloat y = sin(c);
474
475 glNormal3f((x * r0) / radius, (y * r0) / radius, z0 / radius);
476 glTexCoord2f(j / (GLfloat) numMinor, i / (GLfloat) numMajor);
477 glVertex3f(x * r0, y * r0, z0);
478
479 glNormal3f((x * r1) / radius, (y * r1) / radius, z1 / radius);
480 glTexCoord2f(j / (GLfloat) numMinor, (i + 1) / (GLfloat) numMajor);
481 glVertex3f(x * r1, y * r1, z1);
482 }
483 glEnd();
484 }
485 }
486
487 /*****************************************************************/
488
489 float xmin = -0.035, xmax = 0.035;
490 float ymin = -0.035, ymax = 0.035;
491 float nnear = 0.1;
492 float ffar = 1.9;
493 float distance = -1.0;
494
495 static void
496 loadTextureProjection(int texUnit, GLfloat m[16])
497 {
498 GLfloat mInverse[4][4];
499
500 /* Should use true inverse, but since m consists only of rotations, we can
501 just use the transpose. */
502 matrixTranspose((GLfloat *) mInverse, m);
503
504 ActiveTexture(GL_TEXTURE0_ARB + texUnit);
505 glMatrixMode(GL_TEXTURE);
506 glLoadIdentity();
507 glTranslatef(0.5, 0.5, 0.0);
508 glScalef(0.5, 0.5, 1.0);
509 glFrustum(xmin, xmax, ymin, ymax, nnear, ffar);
510 glTranslatef(0.0, 0.0, distance);
511 glMultMatrixf((GLfloat *) mInverse);
512 glMatrixMode(GL_MODELVIEW);
513 }
514
515 static void
516 drawTextureProjection(void)
517 {
518 float t = ffar / nnear;
519 GLfloat n[4][3];
520 GLfloat f[4][3];
521
522 n[0][0] = xmin;
523 n[0][1] = ymin;
524 n[0][2] = -(nnear + distance);
525
526 n[1][0] = xmax;
527 n[1][1] = ymin;
528 n[1][2] = -(nnear + distance);
529
530 n[2][0] = xmax;
531 n[2][1] = ymax;
532 n[2][2] = -(nnear + distance);
533
534 n[3][0] = xmin;
535 n[3][1] = ymax;
536 n[3][2] = -(nnear + distance);
537
538 f[0][0] = xmin * t;
539 f[0][1] = ymin * t;
540 f[0][2] = -(ffar + distance);
541
542 f[1][0] = xmax * t;
543 f[1][1] = ymin * t;
544 f[1][2] = -(ffar + distance);
545
546 f[2][0] = xmax * t;
547 f[2][1] = ymax * t;
548 f[2][2] = -(ffar + distance);
549
550 f[3][0] = xmin * t;
551 f[3][1] = ymax * t;
552 f[3][2] = -(ffar + distance);
553
554 glColor3f(1.0, 1.0, 0.0);
555 glBegin(GL_LINE_LOOP);
556 glVertex3fv(n[0]);
557 glVertex3fv(n[1]);
558 glVertex3fv(n[2]);
559 glVertex3fv(n[3]);
560 glVertex3fv(f[3]);
561 glVertex3fv(f[2]);
562 glVertex3fv(f[1]);
563 glVertex3fv(f[0]);
564 glVertex3fv(n[0]);
565 glVertex3fv(n[1]);
566 glVertex3fv(f[1]);
567 glVertex3fv(f[0]);
568 glVertex3fv(f[3]);
569 glVertex3fv(f[2]);
570 glVertex3fv(n[2]);
571 glVertex3fv(n[3]);
572 glEnd();
573 }
574
575 /*****************************************************************/
576
577 static void
578 initialize(void)
579 {
580 GLfloat light0Pos[4] =
581 {0.3, 0.3, 0.0, 1.0};
582 GLfloat matAmb[4] =
583 {0.01, 0.01, 0.01, 1.00};
584 GLfloat matDiff[4] =
585 {0.65, 0.65, 0.65, 1.00};
586 GLfloat matSpec[4] =
587 {0.30, 0.30, 0.30, 1.00};
588 GLfloat matShine = 10.0;
589 GLfloat eyePlaneS[] =
590 {1.0, 0.0, 0.0, 0.0};
591 GLfloat eyePlaneT[] =
592 {0.0, 1.0, 0.0, 0.0};
593 GLfloat eyePlaneR[] =
594 {0.0, 0.0, 1.0, 0.0};
595 GLfloat eyePlaneQ[] =
596 {0.0, 0.0, 0.0, 1.0};
597 int i;
598
599 /* Setup Misc. */
600 glClearColor(0.41, 0.41, 0.31, 0.0);
601
602 glEnable(GL_DEPTH_TEST);
603
604 /* glLineWidth(2.0);*/
605
606 glCullFace(GL_FRONT);
607 glEnable(GL_CULL_FACE);
608
609 glMatrixMode(GL_PROJECTION);
610 glFrustum(-0.5, 0.5, -0.5, 0.5, 1, 3);
611 glMatrixMode(GL_MODELVIEW);
612 glTranslatef(0, 0, -2);
613
614 matrixIdentity((GLfloat *) objectXform);
615 for (i = 0; i < NumTextures; i++) {
616 matrixIdentity((GLfloat *) textureXform[i]);
617 }
618
619 glMatrixMode(GL_PROJECTION);
620 glPushMatrix();
621 glLoadIdentity();
622 glOrtho(0, 1, 0, 1, -1, 1);
623 glMatrixMode(GL_MODELVIEW);
624 glPushMatrix();
625 glLoadIdentity();
626
627 glRasterPos2i(0, 0);
628
629 glPopMatrix();
630 glMatrixMode(GL_PROJECTION);
631 glPopMatrix();
632 glMatrixMode(GL_MODELVIEW);
633
634 /* Setup Lighting */
635 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, matAmb);
636 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, matDiff);
637 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, matSpec);
638 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, matShine);
639
640 glEnable(GL_COLOR_MATERIAL);
641
642 glLightfv(GL_LIGHT0, GL_POSITION, light0Pos);
643 glEnable(GL_LIGHT0);
644
645 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
646 glEnable(GL_LIGHTING);
647
648 /* Setup Texture */
649
650 (*loadTexture) ();
651
652
653 for (i = 0; i < NumTextures; i++) {
654 ActiveTexture(GL_TEXTURE0_ARB + i);
655
656 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
657 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
658 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
659
660 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
661 glTexGenfv(GL_S, GL_EYE_PLANE, eyePlaneS);
662
663 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
664 glTexGenfv(GL_T, GL_EYE_PLANE, eyePlaneT);
665
666 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
667 glTexGenfv(GL_R, GL_EYE_PLANE, eyePlaneR);
668
669 glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
670 glTexGenfv(GL_Q, GL_EYE_PLANE, eyePlaneQ);
671 }
672 }
673
674 static void
675 display(void)
676 {
677 int i;
678
679 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
680
681 if (textureEnabled) {
682 if (mode == MoveTexture || mode == MoveView) {
683 /* Have OpenGL compute the new transformation (simple but slow). */
684 for (i = 0; i < NumTextures; i++) {
685 glPushMatrix();
686 glLoadIdentity();
687 #if 0
688 if (i & 1)
689 glRotatef(angle, axis[0], axis[1], axis[2]);
690 else
691 #endif
692 glRotatef(angle*(i+1), axis[0], axis[1], axis[2]);
693
694 glMultMatrixf((GLfloat *) textureXform[i]);
695 glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *) textureXform[i]);
696 glPopMatrix();
697 }
698 }
699 for (i = 0; i < NumTextures; i++) {
700 loadTextureProjection(i, (GLfloat *) textureXform[i]);
701 }
702
703 if (showProjection) {
704 for (i = 0; i < NumTextures; i++) {
705 ActiveTexture(GL_TEXTURE0_ARB + i);
706 glPushMatrix();
707 glMultMatrixf((GLfloat *) textureXform[i]);
708 glDisable(GL_LIGHTING);
709 drawTextureProjection();
710 glEnable(GL_LIGHTING);
711 glPopMatrix();
712 }
713 }
714 for (i = 0; i < NumTextures; i++) {
715 ActiveTexture(GL_TEXTURE0_ARB + i);
716 glEnable(GL_TEXTURE_2D);
717 glEnable(GL_TEXTURE_GEN_S);
718 glEnable(GL_TEXTURE_GEN_T);
719 glEnable(GL_TEXTURE_GEN_R);
720 glEnable(GL_TEXTURE_GEN_Q);
721 }
722 }
723 if (mode == MoveObject || mode == MoveView) {
724 /* Have OpenGL compute the new transformation (simple but slow). */
725 glPushMatrix();
726 glLoadIdentity();
727 glRotatef(angle, axis[0], axis[1], axis[2]);
728 glMultMatrixf((GLfloat *) objectXform);
729 glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *) objectXform);
730 glPopMatrix();
731 }
732 glPushMatrix();
733 glMultMatrixf((GLfloat *) objectXform);
734 (*drawObject) ();
735 glPopMatrix();
736
737 for (i = 0; i < NumTextures; i++) {
738 ActiveTexture(GL_TEXTURE0_ARB + i);
739 glDisable(GL_TEXTURE_2D);
740 glDisable(GL_TEXTURE_GEN_S);
741 glDisable(GL_TEXTURE_GEN_T);
742 glDisable(GL_TEXTURE_GEN_R);
743 glDisable(GL_TEXTURE_GEN_Q);
744 }
745
746 if (zoomFactor > 1.0) {
747 glDisable(GL_DEPTH_TEST);
748 glCopyPixels(0, 0, winWidth / zoomFactor, winHeight / zoomFactor, GL_COLOR);
749 glEnable(GL_DEPTH_TEST);
750 }
751 glFlush();
752 glutSwapBuffers();
753 checkErrors();
754 }
755
756 /*****************************************************************/
757
758 /* simple trackball-like motion control */
759 static float lastPos[3];
760 static int lastTime;
761
762 static void
763 ptov(int x, int y, int width, int height, float v[3])
764 {
765 float d, a;
766
767 /* project x,y onto a hemi-sphere centered within width, height */
768 v[0] = (2.0 * x - width) / width;
769 v[1] = (height - 2.0 * y) / height;
770 d = sqrt(v[0] * v[0] + v[1] * v[1]);
771 v[2] = cos((M_PI / 2.0) * ((d < 1.0) ? d : 1.0));
772 a = 1.0 / sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
773 v[0] *= a;
774 v[1] *= a;
775 v[2] *= a;
776 }
777
778 static void
779 startMotion(int x, int y, int but, int time)
780 {
781 if (but == GLUT_LEFT_BUTTON) {
782 mode = MoveView;
783 } else if (but == GLUT_MIDDLE_BUTTON) {
784 mode = MoveTexture;
785 } else {
786 return;
787 }
788
789 lastTime = time;
790 ptov(x, y, winWidth, winHeight, lastPos);
791 }
792
793 static void
794 animate(void)
795 {
796 glutPostRedisplay();
797 }
798
799 static void
800 vis(int visible)
801 {
802 if (visible == GLUT_VISIBLE) {
803 if (redrawContinuously)
804 glutIdleFunc(animate);
805 } else {
806 if (redrawContinuously)
807 glutIdleFunc(NULL);
808 }
809 }
810
811 static void
812 stopMotion(int but, int time)
813 {
814 if ((but == GLUT_LEFT_BUTTON && mode == MoveView) ||
815 (but == GLUT_MIDDLE_BUTTON && mode == MoveTexture)) {
816 } else {
817 return;
818 }
819
820 if (time == lastTime) {
821 /* redrawContinuously = GL_TRUE;*/
822 glutIdleFunc(animate);
823 } else {
824 angle = 0.0;
825 redrawContinuously = GL_FALSE;
826 glutIdleFunc(0);
827 }
828 if (!redrawContinuously) {
829 mode = MoveNone;
830 }
831 }
832
833 static void
834 trackMotion(int x, int y)
835 {
836 float curPos[3], dx, dy, dz;
837
838 ptov(x, y, winWidth, winHeight, curPos);
839
840 dx = curPos[0] - lastPos[0];
841 dy = curPos[1] - lastPos[1];
842 dz = curPos[2] - lastPos[2];
843 angle = 90.0 * sqrt(dx * dx + dy * dy + dz * dz);
844
845 axis[0] = lastPos[1] * curPos[2] - lastPos[2] * curPos[1];
846 axis[1] = lastPos[2] * curPos[0] - lastPos[0] * curPos[2];
847 axis[2] = lastPos[0] * curPos[1] - lastPos[1] * curPos[0];
848
849 lastTime = glutGet(GLUT_ELAPSED_TIME);
850 lastPos[0] = curPos[0];
851 lastPos[1] = curPos[1];
852 lastPos[2] = curPos[2];
853 glutPostRedisplay();
854 }
855
856 /*****************************************************************/
857
858 static void
859 object(void)
860 {
861 static int object;
862
863 object++;
864 object %= 3;
865 switch (object) {
866 case 0:
867 drawObject = drawCube;
868 break;
869 case 1:
870 drawObject = drawDodecahedron;
871 break;
872 case 2:
873 drawObject = drawSphere;
874 break;
875 default:
876 break;
877 }
878 }
879
880 static void
881 nop(void)
882 {
883 }
884
885 static void
886 texture(void)
887 {
888 static int texture = 0;
889
890 texture++;
891 texture %= 3;
892 if (texture == 1 && texFilename == NULL) {
893 /* Skip file texture if not loaded. */
894 texture++;
895 }
896 switch (texture) {
897 case 0:
898 loadTexture = nop;
899 textureEnabled = GL_FALSE;
900 break;
901 case 1:
902 loadTexture = loadImageTextures;
903 (*loadTexture) ();
904 textureEnabled = GL_TRUE;
905 break;
906 case 2:
907 loadTexture = loadSpotlightTexture;
908 (*loadTexture) ();
909 textureEnabled = GL_TRUE;
910 break;
911 default:
912 break;
913 }
914 }
915
916 static void
917 help(void)
918 {
919 printf("'h' - help\n");
920 printf("'l' - toggle linear/nearest filter\n");
921 printf("'s' - toggle projection frustum\n");
922 printf("'t' - toggle projected texture\n");
923 printf("'o' - toggle object\n");
924 printf("'z' - increase zoom factor\n");
925 printf("'Z' - decrease zoom factor\n");
926 printf("left mouse - move view\n");
927 printf("middle mouse - move projection\n");
928 }
929
930 /* ARGSUSED1 */
931 static void
932 key(unsigned char key, int x, int y)
933 {
934 switch (key) {
935 case '\033':
936 exit(0);
937 break;
938 case 'l':
939 linearFilter = !linearFilter;
940 (*loadTexture) ();
941 break;
942 case 's':
943 showProjection = !showProjection;
944 break;
945 case 't':
946 texture();
947 break;
948 case 'o':
949 object();
950 break;
951 case 'z':
952 zoomFactor += 1.0;
953 glPixelZoom(zoomFactor, zoomFactor);
954 glViewport(0, 0, winWidth / zoomFactor, winHeight / zoomFactor);
955 break;
956 case 'Z':
957 zoomFactor -= 1.0;
958 if (zoomFactor < 1.0)
959 zoomFactor = 1.0;
960 glPixelZoom(zoomFactor, zoomFactor);
961 glViewport(0, 0, winWidth / zoomFactor, winHeight / zoomFactor);
962 break;
963 case 'h':
964 help();
965 break;
966 }
967 glutPostRedisplay();
968 }
969
970 static void
971 mouse(int button, int state, int x, int y)
972 {
973 if (state == GLUT_DOWN)
974 startMotion(x, y, button, glutGet(GLUT_ELAPSED_TIME));
975 else if (state == GLUT_UP)
976 stopMotion(button, glutGet(GLUT_ELAPSED_TIME));
977 glutPostRedisplay();
978 }
979
980 static void
981 reshape(int w, int h)
982 {
983 winWidth = w;
984 winHeight = h;
985 glViewport(0, 0, w / zoomFactor, h / zoomFactor);
986 }
987
988
989 static void
990 menu(int selection)
991 {
992 if (selection == 666) {
993 exit(0);
994 }
995 key((unsigned char) selection, 0, 0);
996 }
997
998 int
999 main(int argc, char **argv)
1000 {
1001 glutInit(&argc, argv);
1002
1003 if (argc > 1) {
1004 NumTextures = atoi(argv[1]);
1005 }
1006 assert(NumTextures <= MAX_TEX);
1007
1008 glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
1009 glutInitWindowSize(500,500);
1010 (void) glutCreateWindow("projtex");
1011 glewInit();
1012
1013 loadTexture = loadImageTextures;
1014 drawObject = drawCube;
1015 initialize();
1016 glutDisplayFunc(display);
1017 glutKeyboardFunc(key);
1018 glutReshapeFunc(reshape);
1019 glutMouseFunc(mouse);
1020 glutMotionFunc(trackMotion);
1021 glutVisibilityFunc(vis);
1022 glutCreateMenu(menu);
1023 glutAddMenuEntry("Toggle showing projection", 's');
1024 glutAddMenuEntry("Switch texture", 't');
1025 glutAddMenuEntry("Switch object", 'o');
1026 glutAddMenuEntry("Toggle filtering", 'l');
1027 glutAddMenuEntry("Quit", 666);
1028 glutAttachMenu(GLUT_RIGHT_BUTTON);
1029 texture();
1030 glutMainLoop();
1031 return 0; /* ANSI C requires main to return int. */
1032 }