Removed all RCS / CVS tags (Id, Header, Date, etc.) from everything.
[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 void GLUTCALLBACK glut_post_redisplay_p(void)
91 {
92 glutPostRedisplay();
93 }
94
95 static void Animate(void)
96 {
97 struct coord *coord;
98 struct facet *facet;
99 float *lastColor;
100 float *thisColor;
101 GLint i, j;
102
103 glClear(clearMask);
104
105 if (nextFrame || !stepMode) {
106 curFrame++;
107 }
108 if (curFrame >= theMesh.frames) {
109 curFrame = 0;
110 }
111
112 if ((nextFrame || !stepMode) && spinMode) {
113 glRotatef(5.0, 0.0, 0.0, 1.0);
114 }
115 nextFrame = 0;
116
117 for (i = 0; i < theMesh.widthX; i++) {
118 glBegin(GL_QUAD_STRIP);
119 lastColor = NULL;
120 for (j = 0; j < theMesh.widthY; j++) {
121 facet = GETFACET(curFrame, i, j);
122 if (!smooth && lighting) {
123 glNormal3fv(facet->normal);
124 }
125 if (lighting) {
126 if (rgb) {
127 thisColor = facet->color;
128 glColor3fv(facet->color);
129 } else {
130 thisColor = facet->color;
131 glMaterialfv(GL_FRONT_AND_BACK, GL_COLOR_INDEXES,
132 facet->color);
133 }
134 } else {
135 if (rgb) {
136 thisColor = facet->color;
137 glColor3fv(facet->color);
138 } else {
139 thisColor = facet->color;
140 glIndexf(facet->color[1]);
141 }
142 }
143
144 if (!lastColor || (thisColor[0] != lastColor[0] && smooth)) {
145 if (lastColor) {
146 glEnd();
147 glBegin(GL_QUAD_STRIP);
148 }
149 coord = GETCOORD(curFrame, i, j);
150 if (smooth && lighting) {
151 glNormal3fv(coord->normal);
152 }
153 glVertex3fv(coord->vertex);
154
155 coord = GETCOORD(curFrame, i+1, j);
156 if (smooth && lighting) {
157 glNormal3fv(coord->normal);
158 }
159 glVertex3fv(coord->vertex);
160 }
161
162 coord = GETCOORD(curFrame, i, j+1);
163 if (smooth && lighting) {
164 glNormal3fv(coord->normal);
165 }
166 glVertex3fv(coord->vertex);
167
168 coord = GETCOORD(curFrame, i+1, j+1);
169 if (smooth && lighting) {
170 glNormal3fv(coord->normal);
171 }
172 glVertex3fv(coord->vertex);
173
174 lastColor = thisColor;
175 }
176 glEnd();
177 }
178
179 glFlush();
180 if (doubleBuffer) {
181 glutSwapBuffers();
182 }
183 }
184
185 static void SetColorMap(void)
186 {
187 static float green[3] = {0.2, 1.0, 0.2};
188 static float red[3] = {1.0, 0.2, 0.2};
189 float *color = 0, percent;
190 GLint *indexes = 0, entries, i, j;
191
192 entries = glutGet(GLUT_WINDOW_COLORMAP_SIZE);
193
194 colorIndexes1[0] = 1;
195 colorIndexes1[1] = 1 + (GLint)((entries - 1) * 0.3);
196 colorIndexes1[2] = (GLint)((entries - 1) * 0.5);
197 colorIndexes2[0] = 1 + (GLint)((entries - 1) * 0.5);
198 colorIndexes2[1] = 1 + (GLint)((entries - 1) * 0.8);
199 colorIndexes2[2] = entries - 1;
200
201 for (i = 0; i < 2; i++) {
202 switch (i) {
203 case 0:
204 color = green;
205 indexes = colorIndexes1;
206 break;
207 case 1:
208 color = red;
209 indexes = colorIndexes2;
210 break;
211 }
212
213 for (j = indexes[0]; j < indexes[1]; j++) {
214 percent = 0.2 + 0.8 * (j - indexes[0]) /
215 (float)(indexes[1] - indexes[0]);
216 glutSetColor(j, percent*color[0], percent*color[1],
217 percent*color[2]);
218 }
219 for (j=indexes[1]; j<=indexes[2]; j++) {
220 percent = (j - indexes[1]) / (float)(indexes[2] - indexes[1]);
221 glutSetColor(j, percent*(1-color[0])+color[0],
222 percent*(1-color[1])+color[1],
223 percent*(1-color[2])+color[2]);
224 }
225 }
226 }
227
228 static void InitMesh(void)
229 {
230 struct coord *coord;
231 struct facet *facet;
232 float dp1[3], dp2[3];
233 float *pt1, *pt2, *pt3;
234 float angle, d, x, y;
235 GLint numFacets, numCoords, frameNum, i, j;
236
237 theMesh.widthX = widthX;
238 theMesh.widthY = widthY;
239 theMesh.frames = frames;
240
241 numFacets = widthX * widthY;
242 numCoords = (widthX + 1) * (widthY + 1);
243
244 theMesh.numCoords = numCoords;
245 theMesh.numFacets = numFacets;
246
247 theMesh.coords = (struct coord *)malloc(frames*numCoords*
248 sizeof(struct coord));
249 theMesh.facets = (struct facet *)malloc(frames*numFacets*
250 sizeof(struct facet));
251 if (theMesh.coords == NULL || theMesh.facets == NULL) {
252 printf("Out of memory.\n");
253 exit(1);
254 }
255
256 for (frameNum = 0; frameNum < frames; frameNum++) {
257 for (i = 0; i <= widthX; i++) {
258 x = i / (float)widthX;
259 for (j = 0; j <= widthY; j++) {
260 y = j / (float)widthY;
261
262 d = sqrt(x*x+y*y);
263 if (d == 0.0) {
264 d = 0.0001;
265 }
266 angle = 2 * PI * d + (2 * PI / frames * frameNum);
267
268 coord = GETCOORD(frameNum, i, j);
269
270 coord->vertex[0] = x - 0.5;
271 coord->vertex[1] = y - 0.5;
272 coord->vertex[2] = (height - height * d) * cos(angle);
273
274 coord->normal[0] = -(height / d) * x * ((1 - d) * 2 * PI *
275 sin(angle) + cos(angle));
276 coord->normal[1] = -(height / d) * y * ((1 - d) * 2 * PI *
277 sin(angle) + cos(angle));
278 coord->normal[2] = -1;
279
280 d = 1.0 / sqrt(coord->normal[0]*coord->normal[0]+
281 coord->normal[1]*coord->normal[1]+1);
282 coord->normal[0] *= d;
283 coord->normal[1] *= d;
284 coord->normal[2] *= d;
285 }
286 }
287 for (i = 0; i < widthX; i++) {
288 for (j = 0; j < widthY; j++) {
289 facet = GETFACET(frameNum, i, j);
290 if (((i/checkerSize)%2)^(j/checkerSize)%2) {
291 if (rgb) {
292 facet->color[0] = 1.0;
293 facet->color[1] = 0.2;
294 facet->color[2] = 0.2;
295 } else {
296 facet->color[0] = colorIndexes1[0];
297 facet->color[1] = colorIndexes1[1];
298 facet->color[2] = colorIndexes1[2];
299 }
300 } else {
301 if (rgb) {
302 facet->color[0] = 0.2;
303 facet->color[1] = 1.0;
304 facet->color[2] = 0.2;
305 } else {
306 facet->color[0] = colorIndexes2[0];
307 facet->color[1] = colorIndexes2[1];
308 facet->color[2] = colorIndexes2[2];
309 }
310 }
311 pt1 = GETCOORD(frameNum, i, j)->vertex;
312 pt2 = GETCOORD(frameNum, i, j+1)->vertex;
313 pt3 = GETCOORD(frameNum, i+1, j+1)->vertex;
314
315 dp1[0] = pt2[0] - pt1[0];
316 dp1[1] = pt2[1] - pt1[1];
317 dp1[2] = pt2[2] - pt1[2];
318
319 dp2[0] = pt3[0] - pt2[0];
320 dp2[1] = pt3[1] - pt2[1];
321 dp2[2] = pt3[2] - pt2[2];
322
323 facet->normal[0] = dp1[1] * dp2[2] - dp1[2] * dp2[1];
324 facet->normal[1] = dp1[2] * dp2[0] - dp1[0] * dp2[2];
325 facet->normal[2] = dp1[0] * dp2[1] - dp1[1] * dp2[0];
326
327 d = 1.0 / sqrt(facet->normal[0]*facet->normal[0]+
328 facet->normal[1]*facet->normal[1]+
329 facet->normal[2]*facet->normal[2]);
330
331 facet->normal[0] *= d;
332 facet->normal[1] *= d;
333 facet->normal[2] *= d;
334 }
335 }
336 }
337 }
338
339 static void InitMaterials(void)
340 {
341 static float ambient[] = {0.1, 0.1, 0.1, 1.0};
342 static float diffuse[] = {0.5, 1.0, 1.0, 1.0};
343 static float position[] = {90.0, 90.0, 150.0, 0.0};
344 static float front_mat_shininess[] = {60.0};
345 static float front_mat_specular[] = {0.2, 0.2, 0.2, 1.0};
346 static float front_mat_diffuse[] = {0.5, 0.28, 0.38, 1.0};
347 static float back_mat_shininess[] = {60.0};
348 static float back_mat_specular[] = {0.5, 0.5, 0.2, 1.0};
349 static float back_mat_diffuse[] = {1.0, 1.0, 0.2, 1.0};
350 static float lmodel_ambient[] = {1.0, 1.0, 1.0, 1.0};
351 static float lmodel_twoside[] = {GL_TRUE};
352
353 glMatrixMode(GL_PROJECTION);
354 gluPerspective(90.0, 1.0, 0.5, 10.0);
355
356 glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
357 glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
358 glLightfv(GL_LIGHT0, GL_POSITION, position);
359 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
360 glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside);
361 glEnable(GL_LIGHTING);
362 glEnable(GL_LIGHT0);
363
364 glMaterialfv(GL_FRONT, GL_SHININESS, front_mat_shininess);
365 glMaterialfv(GL_FRONT, GL_SPECULAR, front_mat_specular);
366 glMaterialfv(GL_FRONT, GL_DIFFUSE, front_mat_diffuse);
367 glMaterialfv(GL_BACK, GL_SHININESS, back_mat_shininess);
368 glMaterialfv(GL_BACK, GL_SPECULAR, back_mat_specular);
369 glMaterialfv(GL_BACK, GL_DIFFUSE, back_mat_diffuse);
370 if (rgb) {
371 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
372 }
373
374 if (rgb) {
375 glEnable(GL_COLOR_MATERIAL);
376 } else {
377 SetColorMap();
378 }
379 }
380
381 static void InitTexture(void)
382 {
383
384 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
385 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
386 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
387 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
388 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
389 }
390
391 static void Init(void)
392 {
393
394 glClearColor(0.0, 0.0, 0.0, 0.0);
395
396 glShadeModel(GL_FLAT);
397
398 glFrontFace(GL_CW);
399
400 glEnable(GL_DEPTH_TEST);
401
402 InitMaterials();
403 InitTexture();
404 InitMesh();
405
406 glMatrixMode(GL_MODELVIEW);
407 glTranslatef(0.0, 0.4, -1.8);
408 glScalef(2.0, 2.0, 2.0);
409 glRotatef(-35.0, 1.0, 0.0, 0.0);
410 glRotatef(35.0, 0.0, 0.0, 1.0);
411 }
412
413 static void Reshape(int width, int height)
414 {
415
416 glViewport(0, 0, (GLint)width, (GLint)height);
417 }
418
419 static void Key(unsigned char key, int x, int y)
420 {
421
422 switch (key) {
423 case 27:
424 exit(1);
425 case 'c':
426 contouring++;
427 if (contouring == 1) {
428 static GLfloat map[4] = {0, 0, 20, 0};
429
430 glTexImage2D(GL_TEXTURE_2D, 0, 3, 4, 4, 0, GL_LUMINANCE,
431 GL_UNSIGNED_BYTE, (GLvoid *)contourTexture1);
432 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
433 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
434 glTexGenfv(GL_S, GL_OBJECT_PLANE, map);
435 glTexGenfv(GL_T, GL_OBJECT_PLANE, map);
436 glEnable(GL_TEXTURE_2D);
437 glEnable(GL_TEXTURE_GEN_S);
438 glEnable(GL_TEXTURE_GEN_T);
439 } else if (contouring == 2) {
440 static GLfloat map[4] = {0, 0, 20, 0};
441
442 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
443 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
444 glPushMatrix();
445 glMatrixMode(GL_MODELVIEW);
446 glLoadIdentity();
447 glTexGenfv(GL_S, GL_EYE_PLANE, map);
448 glTexGenfv(GL_T, GL_EYE_PLANE, map);
449 glPopMatrix();
450 } else {
451 contouring = 0;
452 glDisable(GL_TEXTURE_GEN_S);
453 glDisable(GL_TEXTURE_GEN_T);
454 glDisable(GL_TEXTURE_2D);
455 }
456 break;
457 case 's':
458 smooth = !smooth;
459 if (smooth) {
460 glShadeModel(GL_SMOOTH);
461 } else {
462 glShadeModel(GL_FLAT);
463 }
464 break;
465 case 'l':
466 lighting = !lighting;
467 if (lighting) {
468 glEnable(GL_LIGHTING);
469 glEnable(GL_LIGHT0);
470 if (rgb) {
471 glEnable(GL_COLOR_MATERIAL);
472 }
473 } else {
474 glDisable(GL_LIGHTING);
475 glDisable(GL_LIGHT0);
476 if (rgb) {
477 glDisable(GL_COLOR_MATERIAL);
478 }
479 }
480 break;
481 case 'd':
482 depth = !depth;
483 if (depth) {
484 glEnable(GL_DEPTH_TEST);
485 clearMask |= GL_DEPTH_BUFFER_BIT;
486 } else {
487 glDisable(GL_DEPTH_TEST);
488 clearMask &= ~GL_DEPTH_BUFFER_BIT;
489 }
490 break;
491 case 32:
492 stepMode = !stepMode;
493 if (stepMode) {
494 glutIdleFunc(0);
495 } else {
496 glutIdleFunc(glut_post_redisplay_p);
497 }
498 break;
499 case 'n':
500 if (stepMode) {
501 nextFrame = 1;
502 }
503 break;
504 case 'a':
505 spinMode = !spinMode;
506 break;
507 default:
508 return;
509 }
510 glutPostRedisplay();
511 }
512
513 static GLenum Args(int argc, char **argv)
514 {
515 GLint i;
516
517 rgb = GL_TRUE;
518 doubleBuffer = GL_TRUE;
519 frames = 10;
520 widthX = 10;
521 widthY = 10;
522 checkerSize = 2;
523 height = 0.2;
524
525 for (i = 1; i < argc; i++) {
526 if (strcmp(argv[i], "-ci") == 0) {
527 rgb = GL_FALSE;
528 } else if (strcmp(argv[i], "-rgb") == 0) {
529 rgb = GL_TRUE;
530 } else if (strcmp(argv[i], "-sb") == 0) {
531 doubleBuffer = GL_FALSE;
532 } else if (strcmp(argv[i], "-db") == 0) {
533 doubleBuffer = GL_TRUE;
534 } else if (strcmp(argv[i], "-grid") == 0) {
535 if (i+2 >= argc || argv[i+1][0] == '-' || argv[i+2][0] == '-') {
536 printf("-grid (No numbers).\n");
537 return GL_FALSE;
538 } else {
539 widthX = atoi(argv[++i]);
540 widthY = atoi(argv[++i]);
541 }
542 } else if (strcmp(argv[i], "-size") == 0) {
543 if (i+1 >= argc || argv[i+1][0] == '-') {
544 printf("-checker (No number).\n");
545 return GL_FALSE;
546 } else {
547 checkerSize = atoi(argv[++i]);
548 }
549 } else if (strcmp(argv[i], "-wave") == 0) {
550 if (i+1 >= argc || argv[i+1][0] == '-') {
551 printf("-wave (No number).\n");
552 return GL_FALSE;
553 } else {
554 height = atof(argv[++i]);
555 }
556 } else if (strcmp(argv[i], "-frames") == 0) {
557 if (i+1 >= argc || argv[i+1][0] == '-') {
558 printf("-frames (No number).\n");
559 return GL_FALSE;
560 } else {
561 frames = atoi(argv[++i]);
562 }
563 } else {
564 printf("%s (Bad option).\n", argv[i]);
565 return GL_FALSE;
566 }
567 }
568 return GL_TRUE;
569 }
570
571 int main(int argc, char **argv)
572 {
573 GLenum type;
574
575 glutInit(&argc, argv);
576
577 if (Args(argc, argv) == GL_FALSE) {
578 exit(1);
579 }
580
581 glutInitWindowPosition(0, 0); glutInitWindowSize( 300, 300);
582
583 type = GLUT_DEPTH;
584 type |= (rgb) ? GLUT_RGB : GLUT_INDEX;
585 type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
586 glutInitDisplayMode(type);
587
588 if (glutCreateWindow("Wave Demo") == GL_FALSE) {
589 exit(1);
590 }
591
592 InitMap();
593
594 Init();
595
596 glutReshapeFunc(Reshape);
597 glutKeyboardFunc(Key);
598 glutDisplayFunc(Animate);
599 glutIdleFunc(glut_post_redisplay_p);
600 glutMainLoop();
601 return 0;
602 }