ARB prog parser: fix parameter binding type
[mesa.git] / progs / samples / wave.c
1 /*
2 * Copyright (c) 1991, 1992, 1993 Silicon Graphics, Inc.
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and
5 * its documentation for any purpose is hereby granted without fee, provided
6 * that (i) the above copyright notices and this permission notice appear in
7 * all copies of the software and related documentation, and (ii) the name of
8 * Silicon Graphics may not be used in any advertising or
9 * publicity relating to the software without the specific, prior written
10 * permission of Silicon Graphics.
11 *
12 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF
13 * ANY KIND,
14 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
15 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
16 *
17 * IN NO EVENT SHALL SILICON GRAPHICS BE LIABLE FOR
18 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
19 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
20 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
21 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
22 * OF THIS SOFTWARE.
23 */
24
25 #include <stdio.h>
26 #include <string.h>
27 #include <stdlib.h>
28 #include <math.h>
29 #include <GL/glut.h>
30
31 #ifndef PI
32 #define PI 3.14159265358979323846
33 #endif
34
35 #define GETCOORD(frame, x, y) (&(theMesh.coords[frame*theMesh.numCoords+(x)+(y)*(theMesh.widthX+1)]))
36 #define GETFACET(frame, x, y) (&(theMesh.facets[frame*theMesh.numFacets+(x)+(y)*theMesh.widthX]))
37
38
39 GLenum rgb, doubleBuffer;
40
41 #include "tkmap.c"
42
43 GLint colorIndexes1[3];
44 GLint colorIndexes2[3];
45 GLenum clearMask = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT;
46
47 GLenum smooth = GL_FALSE;
48 GLenum lighting = GL_TRUE;
49 GLenum depth = GL_TRUE;
50 GLenum stepMode = GL_FALSE;
51 GLenum spinMode = GL_FALSE;
52 GLint contouring = 0;
53
54 GLint widthX, widthY;
55 GLint checkerSize;
56 float height;
57
58 GLint frames, curFrame = 0, nextFrame = 0;
59
60 struct facet {
61 float color[3];
62 float normal[3];
63 };
64 struct coord {
65 float vertex[3];
66 float normal[3];
67 };
68 struct mesh {
69 GLint widthX, widthY;
70 GLint numFacets;
71 GLint numCoords;
72 GLint frames;
73 struct coord *coords;
74 struct facet *facets;
75 } theMesh;
76
77 GLubyte contourTexture1[] = {
78 255, 255, 255, 255,
79 255, 255, 255, 255,
80 255, 255, 255, 255,
81 127, 127, 127, 127,
82 };
83 GLubyte contourTexture2[] = {
84 255, 255, 255, 255,
85 255, 127, 127, 127,
86 255, 127, 127, 127,
87 255, 127, 127, 127,
88 };
89
90 #if !defined(GLUTCALLBACK)
91 #define GLUTCALLBACK
92 #endif
93
94
95 static void GLUTCALLBACK glut_post_redisplay_p(void)
96 {
97 static double t0 = -1.;
98 double t, dt;
99 t = glutGet(GLUT_ELAPSED_TIME) / 1000.;
100 if (t0 < 0.)
101 t0 = t;
102 dt = t - t0;
103
104 if (dt < 1./30.)
105 return;
106
107 t0 = t;
108
109 glutPostRedisplay();
110 }
111
112 static void Animate(void)
113 {
114 struct coord *coord;
115 struct facet *facet;
116 float *lastColor;
117 float *thisColor;
118 GLint i, j;
119
120 glClear(clearMask);
121
122 if (nextFrame || !stepMode) {
123 curFrame++;
124 }
125 if (curFrame >= theMesh.frames) {
126 curFrame = 0;
127 }
128
129 if ((nextFrame || !stepMode) && spinMode) {
130 glRotatef(5.0, 0.0, 0.0, 1.0);
131 }
132 nextFrame = 0;
133
134 for (i = 0; i < theMesh.widthX; i++) {
135 glBegin(GL_QUAD_STRIP);
136 lastColor = NULL;
137 for (j = 0; j < theMesh.widthY; j++) {
138 facet = GETFACET(curFrame, i, j);
139 if (!smooth && lighting) {
140 glNormal3fv(facet->normal);
141 }
142 if (lighting) {
143 if (rgb) {
144 thisColor = facet->color;
145 glColor3fv(facet->color);
146 } else {
147 thisColor = facet->color;
148 glMaterialfv(GL_FRONT_AND_BACK, GL_COLOR_INDEXES,
149 facet->color);
150 }
151 } else {
152 if (rgb) {
153 thisColor = facet->color;
154 glColor3fv(facet->color);
155 } else {
156 thisColor = facet->color;
157 glIndexf(facet->color[1]);
158 }
159 }
160
161 if (!lastColor || (thisColor[0] != lastColor[0] && smooth)) {
162 if (lastColor) {
163 glEnd();
164 glBegin(GL_QUAD_STRIP);
165 }
166 coord = GETCOORD(curFrame, i, j);
167 if (smooth && lighting) {
168 glNormal3fv(coord->normal);
169 }
170 glVertex3fv(coord->vertex);
171
172 coord = GETCOORD(curFrame, i+1, j);
173 if (smooth && lighting) {
174 glNormal3fv(coord->normal);
175 }
176 glVertex3fv(coord->vertex);
177 }
178
179 coord = GETCOORD(curFrame, i, j+1);
180 if (smooth && lighting) {
181 glNormal3fv(coord->normal);
182 }
183 glVertex3fv(coord->vertex);
184
185 coord = GETCOORD(curFrame, i+1, j+1);
186 if (smooth && lighting) {
187 glNormal3fv(coord->normal);
188 }
189 glVertex3fv(coord->vertex);
190
191 lastColor = thisColor;
192 }
193 glEnd();
194 }
195
196 glFlush();
197 if (doubleBuffer) {
198 glutSwapBuffers();
199 }
200 }
201
202 static void SetColorMap(void)
203 {
204 static float green[3] = {0.2, 1.0, 0.2};
205 static float red[3] = {1.0, 0.2, 0.2};
206 float *color = 0, percent;
207 GLint *indexes = 0, entries, i, j;
208
209 entries = glutGet(GLUT_WINDOW_COLORMAP_SIZE);
210
211 colorIndexes1[0] = 1;
212 colorIndexes1[1] = 1 + (GLint)((entries - 1) * 0.3);
213 colorIndexes1[2] = (GLint)((entries - 1) * 0.5);
214 colorIndexes2[0] = 1 + (GLint)((entries - 1) * 0.5);
215 colorIndexes2[1] = 1 + (GLint)((entries - 1) * 0.8);
216 colorIndexes2[2] = entries - 1;
217
218 for (i = 0; i < 2; i++) {
219 switch (i) {
220 case 0:
221 color = green;
222 indexes = colorIndexes1;
223 break;
224 case 1:
225 color = red;
226 indexes = colorIndexes2;
227 break;
228 }
229
230 for (j = indexes[0]; j < indexes[1]; j++) {
231 percent = 0.2 + 0.8 * (j - indexes[0]) /
232 (float)(indexes[1] - indexes[0]);
233 glutSetColor(j, percent*color[0], percent*color[1],
234 percent*color[2]);
235 }
236 for (j=indexes[1]; j<=indexes[2]; j++) {
237 percent = (j - indexes[1]) / (float)(indexes[2] - indexes[1]);
238 glutSetColor(j, percent*(1-color[0])+color[0],
239 percent*(1-color[1])+color[1],
240 percent*(1-color[2])+color[2]);
241 }
242 }
243 }
244
245 static void InitMesh(void)
246 {
247 struct coord *coord;
248 struct facet *facet;
249 float dp1[3], dp2[3];
250 float *pt1, *pt2, *pt3;
251 float angle, d, x, y;
252 GLint numFacets, numCoords, frameNum, i, j;
253
254 theMesh.widthX = widthX;
255 theMesh.widthY = widthY;
256 theMesh.frames = frames;
257
258 numFacets = widthX * widthY;
259 numCoords = (widthX + 1) * (widthY + 1);
260
261 theMesh.numCoords = numCoords;
262 theMesh.numFacets = numFacets;
263
264 theMesh.coords = (struct coord *)malloc(frames*numCoords*
265 sizeof(struct coord));
266 theMesh.facets = (struct facet *)malloc(frames*numFacets*
267 sizeof(struct facet));
268 if (theMesh.coords == NULL || theMesh.facets == NULL) {
269 printf("Out of memory.\n");
270 exit(1);
271 }
272
273 for (frameNum = 0; frameNum < frames; frameNum++) {
274 for (i = 0; i <= widthX; i++) {
275 x = i / (float)widthX;
276 for (j = 0; j <= widthY; j++) {
277 y = j / (float)widthY;
278
279 d = sqrt(x*x+y*y);
280 if (d == 0.0) {
281 d = 0.0001;
282 }
283 angle = 2 * PI * d + (2 * PI / frames * frameNum);
284
285 coord = GETCOORD(frameNum, i, j);
286
287 coord->vertex[0] = x - 0.5;
288 coord->vertex[1] = y - 0.5;
289 coord->vertex[2] = (height - height * d) * cos(angle);
290
291 coord->normal[0] = -(height / d) * x * ((1 - d) * 2 * PI *
292 sin(angle) + cos(angle));
293 coord->normal[1] = -(height / d) * y * ((1 - d) * 2 * PI *
294 sin(angle) + cos(angle));
295 coord->normal[2] = -1;
296
297 d = 1.0 / sqrt(coord->normal[0]*coord->normal[0]+
298 coord->normal[1]*coord->normal[1]+1);
299 coord->normal[0] *= d;
300 coord->normal[1] *= d;
301 coord->normal[2] *= d;
302 }
303 }
304 for (i = 0; i < widthX; i++) {
305 for (j = 0; j < widthY; j++) {
306 facet = GETFACET(frameNum, i, j);
307 if (((i/checkerSize)%2)^(j/checkerSize)%2) {
308 if (rgb) {
309 facet->color[0] = 1.0;
310 facet->color[1] = 0.2;
311 facet->color[2] = 0.2;
312 } else {
313 facet->color[0] = colorIndexes1[0];
314 facet->color[1] = colorIndexes1[1];
315 facet->color[2] = colorIndexes1[2];
316 }
317 } else {
318 if (rgb) {
319 facet->color[0] = 0.2;
320 facet->color[1] = 1.0;
321 facet->color[2] = 0.2;
322 } else {
323 facet->color[0] = colorIndexes2[0];
324 facet->color[1] = colorIndexes2[1];
325 facet->color[2] = colorIndexes2[2];
326 }
327 }
328 pt1 = GETCOORD(frameNum, i, j)->vertex;
329 pt2 = GETCOORD(frameNum, i, j+1)->vertex;
330 pt3 = GETCOORD(frameNum, i+1, j+1)->vertex;
331
332 dp1[0] = pt2[0] - pt1[0];
333 dp1[1] = pt2[1] - pt1[1];
334 dp1[2] = pt2[2] - pt1[2];
335
336 dp2[0] = pt3[0] - pt2[0];
337 dp2[1] = pt3[1] - pt2[1];
338 dp2[2] = pt3[2] - pt2[2];
339
340 facet->normal[0] = dp1[1] * dp2[2] - dp1[2] * dp2[1];
341 facet->normal[1] = dp1[2] * dp2[0] - dp1[0] * dp2[2];
342 facet->normal[2] = dp1[0] * dp2[1] - dp1[1] * dp2[0];
343
344 d = 1.0 / sqrt(facet->normal[0]*facet->normal[0]+
345 facet->normal[1]*facet->normal[1]+
346 facet->normal[2]*facet->normal[2]);
347
348 facet->normal[0] *= d;
349 facet->normal[1] *= d;
350 facet->normal[2] *= d;
351 }
352 }
353 }
354 }
355
356 static void InitMaterials(void)
357 {
358 static float ambient[] = {0.1, 0.1, 0.1, 1.0};
359 static float diffuse[] = {0.5, 1.0, 1.0, 1.0};
360 static float position[] = {90.0, 90.0, 150.0, 0.0};
361 static float front_mat_shininess[] = {60.0};
362 static float front_mat_specular[] = {0.2, 0.2, 0.2, 1.0};
363 static float front_mat_diffuse[] = {0.5, 0.28, 0.38, 1.0};
364 static float back_mat_shininess[] = {60.0};
365 static float back_mat_specular[] = {0.5, 0.5, 0.2, 1.0};
366 static float back_mat_diffuse[] = {1.0, 1.0, 0.2, 1.0};
367 static float lmodel_ambient[] = {1.0, 1.0, 1.0, 1.0};
368 static float lmodel_twoside[] = {GL_TRUE};
369
370 glMatrixMode(GL_PROJECTION);
371 gluPerspective(90.0, 1.0, 0.5, 10.0);
372
373 glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
374 glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
375 glLightfv(GL_LIGHT0, GL_POSITION, position);
376 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
377 glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside);
378 glEnable(GL_LIGHTING);
379 glEnable(GL_LIGHT0);
380
381 glMaterialfv(GL_FRONT, GL_SHININESS, front_mat_shininess);
382 glMaterialfv(GL_FRONT, GL_SPECULAR, front_mat_specular);
383 glMaterialfv(GL_FRONT, GL_DIFFUSE, front_mat_diffuse);
384 glMaterialfv(GL_BACK, GL_SHININESS, back_mat_shininess);
385 glMaterialfv(GL_BACK, GL_SPECULAR, back_mat_specular);
386 glMaterialfv(GL_BACK, GL_DIFFUSE, back_mat_diffuse);
387 if (rgb) {
388 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
389 }
390
391 if (rgb) {
392 glEnable(GL_COLOR_MATERIAL);
393 } else {
394 SetColorMap();
395 }
396 }
397
398 static void InitTexture(void)
399 {
400
401 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
402 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
403 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
404 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
405 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
406 }
407
408 static void Init(void)
409 {
410
411 glClearColor(0.0, 0.0, 0.0, 0.0);
412
413 glShadeModel(GL_FLAT);
414
415 glFrontFace(GL_CW);
416
417 glEnable(GL_DEPTH_TEST);
418
419 InitMaterials();
420 InitTexture();
421 InitMesh();
422
423 glMatrixMode(GL_MODELVIEW);
424 glTranslatef(0.0, 0.4, -1.8);
425 glScalef(2.0, 2.0, 2.0);
426 glRotatef(-35.0, 1.0, 0.0, 0.0);
427 glRotatef(35.0, 0.0, 0.0, 1.0);
428 }
429
430 static void Reshape(int width, int height)
431 {
432
433 glViewport(0, 0, (GLint)width, (GLint)height);
434 }
435
436 static void Key(unsigned char key, int x, int y)
437 {
438
439 switch (key) {
440 case 27:
441 exit(1);
442 case 'c':
443 contouring++;
444 if (contouring == 1) {
445 static GLfloat map[4] = {0, 0, 20, 0};
446
447 glTexImage2D(GL_TEXTURE_2D, 0, 3, 4, 4, 0, GL_LUMINANCE,
448 GL_UNSIGNED_BYTE, (GLvoid *)contourTexture1);
449 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
450 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
451 glTexGenfv(GL_S, GL_OBJECT_PLANE, map);
452 glTexGenfv(GL_T, GL_OBJECT_PLANE, map);
453 glEnable(GL_TEXTURE_2D);
454 glEnable(GL_TEXTURE_GEN_S);
455 glEnable(GL_TEXTURE_GEN_T);
456 } else if (contouring == 2) {
457 static GLfloat map[4] = {0, 0, 20, 0};
458
459 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
460 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
461 glPushMatrix();
462 glMatrixMode(GL_MODELVIEW);
463 glLoadIdentity();
464 glTexGenfv(GL_S, GL_EYE_PLANE, map);
465 glTexGenfv(GL_T, GL_EYE_PLANE, map);
466 glPopMatrix();
467 } else {
468 contouring = 0;
469 glDisable(GL_TEXTURE_GEN_S);
470 glDisable(GL_TEXTURE_GEN_T);
471 glDisable(GL_TEXTURE_2D);
472 }
473 break;
474 case 's':
475 smooth = !smooth;
476 if (smooth) {
477 glShadeModel(GL_SMOOTH);
478 } else {
479 glShadeModel(GL_FLAT);
480 }
481 break;
482 case 'l':
483 lighting = !lighting;
484 if (lighting) {
485 glEnable(GL_LIGHTING);
486 glEnable(GL_LIGHT0);
487 if (rgb) {
488 glEnable(GL_COLOR_MATERIAL);
489 }
490 } else {
491 glDisable(GL_LIGHTING);
492 glDisable(GL_LIGHT0);
493 if (rgb) {
494 glDisable(GL_COLOR_MATERIAL);
495 }
496 }
497 break;
498 case 'd':
499 depth = !depth;
500 if (depth) {
501 glEnable(GL_DEPTH_TEST);
502 clearMask |= GL_DEPTH_BUFFER_BIT;
503 } else {
504 glDisable(GL_DEPTH_TEST);
505 clearMask &= ~GL_DEPTH_BUFFER_BIT;
506 }
507 break;
508 case 32:
509 stepMode = !stepMode;
510 if (stepMode) {
511 glutIdleFunc(0);
512 } else {
513 glutIdleFunc(glut_post_redisplay_p);
514 }
515 break;
516 case 'n':
517 if (stepMode) {
518 nextFrame = 1;
519 }
520 break;
521 case 'a':
522 spinMode = !spinMode;
523 break;
524 default:
525 return;
526 }
527 glutPostRedisplay();
528 }
529
530 static GLenum Args(int argc, char **argv)
531 {
532 GLint i;
533
534 rgb = GL_TRUE;
535 doubleBuffer = GL_TRUE;
536 frames = 10;
537 widthX = 10;
538 widthY = 10;
539 checkerSize = 2;
540 height = 0.2;
541
542 for (i = 1; i < argc; i++) {
543 if (strcmp(argv[i], "-ci") == 0) {
544 rgb = GL_FALSE;
545 } else if (strcmp(argv[i], "-rgb") == 0) {
546 rgb = GL_TRUE;
547 } else if (strcmp(argv[i], "-sb") == 0) {
548 doubleBuffer = GL_FALSE;
549 } else if (strcmp(argv[i], "-db") == 0) {
550 doubleBuffer = GL_TRUE;
551 } else if (strcmp(argv[i], "-grid") == 0) {
552 if (i+2 >= argc || argv[i+1][0] == '-' || argv[i+2][0] == '-') {
553 printf("-grid (No numbers).\n");
554 return GL_FALSE;
555 } else {
556 widthX = atoi(argv[++i]);
557 widthY = atoi(argv[++i]);
558 }
559 } else if (strcmp(argv[i], "-size") == 0) {
560 if (i+1 >= argc || argv[i+1][0] == '-') {
561 printf("-checker (No number).\n");
562 return GL_FALSE;
563 } else {
564 checkerSize = atoi(argv[++i]);
565 }
566 } else if (strcmp(argv[i], "-wave") == 0) {
567 if (i+1 >= argc || argv[i+1][0] == '-') {
568 printf("-wave (No number).\n");
569 return GL_FALSE;
570 } else {
571 height = atof(argv[++i]);
572 }
573 } else if (strcmp(argv[i], "-frames") == 0) {
574 if (i+1 >= argc || argv[i+1][0] == '-') {
575 printf("-frames (No number).\n");
576 return GL_FALSE;
577 } else {
578 frames = atoi(argv[++i]);
579 }
580 } else {
581 printf("%s (Bad option).\n", argv[i]);
582 return GL_FALSE;
583 }
584 }
585 return GL_TRUE;
586 }
587
588 int main(int argc, char **argv)
589 {
590 GLenum type;
591
592 glutInit(&argc, argv);
593
594 if (Args(argc, argv) == GL_FALSE) {
595 exit(1);
596 }
597
598 glutInitWindowPosition(0, 0); glutInitWindowSize( 300, 300);
599
600 type = GLUT_DEPTH;
601 type |= (rgb) ? GLUT_RGB : GLUT_INDEX;
602 type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
603 glutInitDisplayMode(type);
604
605 if (glutCreateWindow("Wave Demo") == GL_FALSE) {
606 exit(1);
607 }
608
609 InitMap();
610
611 Init();
612
613 glutReshapeFunc(Reshape);
614 glutKeyboardFunc(Key);
615 glutDisplayFunc(Animate);
616 glutIdleFunc(glut_post_redisplay_p);
617 glutMainLoop();
618 return 0;
619 }