Home | History | Annotate | Line # | Download | only in samples
      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 
     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 }
    620