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 "glut_wrap.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 39GLenum rgb, doubleBuffer; 40 41#include "tkmap.c" 42 43GLint colorIndexes1[3]; 44GLint colorIndexes2[3]; 45GLenum clearMask = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT; 46 47GLenum smooth = GL_FALSE; 48GLenum lighting = GL_TRUE; 49GLenum depth = GL_TRUE; 50GLenum stepMode = GL_FALSE; 51GLenum spinMode = GL_FALSE; 52GLint contouring = 0; 53 54GLint widthX, widthY; 55GLint checkerSize; 56float height; 57 58GLint frames, curFrame = 0, nextFrame = 0; 59 60struct facet { 61 float color[3]; 62 float normal[3]; 63}; 64struct coord { 65 float vertex[3]; 66 float normal[3]; 67}; 68struct 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 77GLubyte contourTexture1[] = { 78 255, 255, 255, 255, 79 255, 255, 255, 255, 80 255, 255, 255, 255, 81 127, 127, 127, 127, 82}; 83GLubyte 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 95static 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 112static 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 202static 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 245static 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 356static 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 398static 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 408static 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 430static void Reshape(int width, int height) 431{ 432 433 glViewport(0, 0, (GLint)width, (GLint)height); 434} 435 436static 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 530static 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 588int 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} 620