132001f49Smrg/* Test GL_TEXTURE_BASE_LEVEL and GL_TEXTURE_MAX_LEVEL 232001f49Smrg * Brian Paul 332001f49Smrg * 10 May 2006 432001f49Smrg */ 532001f49Smrg 632001f49Smrg 732001f49Smrg/* Copyright (c) Mark J. Kilgard, 1994. */ 832001f49Smrg 932001f49Smrg/* 1032001f49Smrg * (c) Copyright 1993, Silicon Graphics, Inc. 1132001f49Smrg * ALL RIGHTS RESERVED 1232001f49Smrg * Permission to use, copy, modify, and distribute this software for 1332001f49Smrg * any purpose and without fee is hereby granted, provided that the above 1432001f49Smrg * copyright notice appear in all copies and that both the copyright notice 1532001f49Smrg * and this permission notice appear in supporting documentation, and that 1632001f49Smrg * the name of Silicon Graphics, Inc. not be used in advertising 1732001f49Smrg * or publicity pertaining to distribution of the software without specific, 1832001f49Smrg * written prior permission. 1932001f49Smrg * 2032001f49Smrg * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS" 2132001f49Smrg * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE, 2232001f49Smrg * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR 2332001f49Smrg * FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 2432001f49Smrg * GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT, 2532001f49Smrg * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY 2632001f49Smrg * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION, 2732001f49Smrg * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF 2832001f49Smrg * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN 2932001f49Smrg * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON 3032001f49Smrg * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE 3132001f49Smrg * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE. 3232001f49Smrg * 3332001f49Smrg * US Government Users Restricted Rights 3432001f49Smrg * Use, duplication, or disclosure by the Government is subject to 3532001f49Smrg * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph 3632001f49Smrg * (c)(1)(ii) of the Rights in Technical Data and Computer Software 3732001f49Smrg * clause at DFARS 252.227-7013 and/or in similar or successor 3832001f49Smrg * clauses in the FAR or the DOD or NASA FAR Supplement. 3932001f49Smrg * Unpublished-- rights reserved under the copyright laws of the 4032001f49Smrg * United States. Contractor/manufacturer is Silicon Graphics, 4132001f49Smrg * Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311. 4232001f49Smrg * 4332001f49Smrg * OpenGL(TM) is a trademark of Silicon Graphics, Inc. 4432001f49Smrg */ 4532001f49Smrg/* mipmap.c 4632001f49Smrg * This program demonstrates using mipmaps for texture maps. 4732001f49Smrg * To overtly show the effect of mipmaps, each mipmap reduction 4832001f49Smrg * level has a solidly colored, contrasting texture image. 4932001f49Smrg * Thus, the quadrilateral which is drawn is drawn with several 5032001f49Smrg * different colors. 5132001f49Smrg */ 5232001f49Smrg#include <stdlib.h> 5332001f49Smrg#include <stdio.h> 5432001f49Smrg#include <GL/glew.h> 5532001f49Smrg#include "glut_wrap.h" 5632001f49Smrg 5732001f49Smrg#include "readtex.h" 5832001f49Smrg 5932001f49Smrg#define TEXTURE_FILE DEMOS_DATA_DIR "girl.rgb" 6032001f49Smrg 6132001f49Smrgstatic GLint BaseLevel = 0, MaxLevel = 9; 6232001f49Smrgstatic GLfloat MinLod = -1, MaxLod = 9; 6332001f49Smrgstatic GLfloat LodBias = 0.0; 6432001f49Smrgstatic GLuint texImage, texColor, texCurrent; 6532001f49Smrgstatic GLboolean MagNearestFilter = GL_TRUE; 6632001f49Smrgstatic unsigned int MinFilterIndex = 0; 6732001f49Smrgstatic int Width = 600, Height = 600; 6832001f49Smrg 6932001f49Smrgstatic const struct 7032001f49Smrg{ 7132001f49Smrg GLint value; 7232001f49Smrg const char *name; 7332001f49Smrg} 7432001f49Smrgmin_filters[] = 7532001f49Smrg{ 7632001f49Smrg {GL_LINEAR_MIPMAP_LINEAR, "LINEAR_MIPMAP_LINEAR"}, 7732001f49Smrg {GL_NEAREST_MIPMAP_LINEAR, "NEAREST_MIPMAP_LINEAR"}, 7832001f49Smrg {GL_LINEAR_MIPMAP_NEAREST, "LINEAR_MIPMAP_NEAREST"}, 7932001f49Smrg {GL_NEAREST_MIPMAP_NEAREST, "NEAREST_MIPMAP_NEAREST"}, 8032001f49Smrg {GL_LINEAR, "LINEAR"}, 8132001f49Smrg {GL_NEAREST, "NEAREST"}, 8232001f49Smrg}; 8332001f49Smrg 8432001f49Smrg 8532001f49Smrgstatic void 8632001f49SmrgInitValues(void) 8732001f49Smrg{ 8832001f49Smrg BaseLevel = 0; 8932001f49Smrg MaxLevel = 9; 9032001f49Smrg MinLod = -1; 9132001f49Smrg MaxLod = 9; 9232001f49Smrg LodBias = 0.0; 9332001f49Smrg MagNearestFilter = GL_TRUE; 9432001f49Smrg MinFilterIndex = 0; 9532001f49Smrg} 9632001f49Smrg 9732001f49Smrg 9832001f49Smrgstatic void 9932001f49SmrgMakeImage(int level, int width, int height, const GLubyte color[4]) 10032001f49Smrg{ 10132001f49Smrg const int makeStripes = 0; 10232001f49Smrg GLubyte img[512 * 512 * 3]; 10332001f49Smrg int i, j; 10432001f49Smrg for (i = 0; i < height; i++) { 10532001f49Smrg for (j = 0; j < width; j++) { 10632001f49Smrg int k = (i * width + j) * 3; 10732001f49Smrg int p = (i / 8) & makeStripes; 10832001f49Smrg if (p == 0) { 10932001f49Smrg img[k + 0] = color[0]; 11032001f49Smrg img[k + 1] = color[1]; 11132001f49Smrg img[k + 2] = color[2]; 11232001f49Smrg } 11332001f49Smrg else { 11432001f49Smrg img[k + 0] = 0; 11532001f49Smrg img[k + 1] = 0; 11632001f49Smrg img[k + 2] = 0; 11732001f49Smrg } 11832001f49Smrg } 11932001f49Smrg } 12032001f49Smrg 12132001f49Smrg glTexImage2D(GL_TEXTURE_2D, level, GL_RGB, width, height, 0, 12232001f49Smrg GL_RGB, GL_UNSIGNED_BYTE, img); 12332001f49Smrg} 12432001f49Smrg 12532001f49Smrg 12632001f49Smrgstatic void 12732001f49SmrgmakeImages(int image) 12832001f49Smrg{ 12932001f49Smrg#define WIDTH 512 13032001f49Smrg#define HEIGHT 512 13132001f49Smrg if (glutExtensionSupported("GL_SGIS_generate_mipmap") && image) { 13232001f49Smrg /* test auto mipmap generation */ 13332001f49Smrg GLint width, height, i; 13432001f49Smrg GLenum format; 13532001f49Smrg GLubyte *image = LoadRGBImage(TEXTURE_FILE, &width, &height, &format); 13632001f49Smrg if (!image) { 13732001f49Smrg printf("Error: could not load texture image %s\n", TEXTURE_FILE); 13832001f49Smrg exit(1); 13932001f49Smrg } 14032001f49Smrg /* resize */ 14132001f49Smrg if (width != WIDTH || height != HEIGHT) { 14232001f49Smrg GLubyte *newImage = malloc(WIDTH * HEIGHT * 4); 14332001f49Smrg gluScaleImage(format, width, height, GL_UNSIGNED_BYTE, image, 14432001f49Smrg WIDTH, HEIGHT, GL_UNSIGNED_BYTE, newImage); 14532001f49Smrg free(image); 14632001f49Smrg image = newImage; 14732001f49Smrg } 14832001f49Smrg printf("Using GL_SGIS_generate_mipmap\n"); 14932001f49Smrg glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE); 15032001f49Smrg glTexImage2D(GL_TEXTURE_2D, 0, format, WIDTH, HEIGHT, 0, 15132001f49Smrg format, GL_UNSIGNED_BYTE, image); 15232001f49Smrg glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_FALSE); 15332001f49Smrg free(image); 15432001f49Smrg 15532001f49Smrg /* make sure mipmap was really generated correctly */ 15632001f49Smrg width = WIDTH; 15732001f49Smrg height = HEIGHT; 15832001f49Smrg for (i = 0; i < 10; i++) { 15932001f49Smrg GLint w, h; 16032001f49Smrg glGetTexLevelParameteriv(GL_TEXTURE_2D, i, GL_TEXTURE_WIDTH, &w); 16132001f49Smrg glGetTexLevelParameteriv(GL_TEXTURE_2D, i, GL_TEXTURE_HEIGHT, &h); 16232001f49Smrg printf("Level %d size: %d x %d\n", i, w, h); 16332001f49Smrg width /= 2; 16432001f49Smrg height /= 2; 16532001f49Smrg } 16632001f49Smrg } 16732001f49Smrg else { 16832001f49Smrg static const GLubyte colors[10][3] = { 16932001f49Smrg {128, 128, 128}, 17032001f49Smrg {0, 255, 255}, 17132001f49Smrg {255, 255, 0}, 17232001f49Smrg {255, 0, 255}, 17332001f49Smrg {255, 0, 0}, 17432001f49Smrg {0, 255, 0}, 17532001f49Smrg {0, 0, 255}, 17632001f49Smrg {0, 255, 255}, 17732001f49Smrg {255, 255, 0}, 17832001f49Smrg {255, 255, 255} 17932001f49Smrg }; 18032001f49Smrg int i, sz = 512; 18132001f49Smrg 18232001f49Smrg for (i = 0; i < 10; i++) { 18332001f49Smrg MakeImage(i, sz, sz, colors[i]); 18432001f49Smrg printf("Level %d size: %d x %d\n", i, sz, sz); 18532001f49Smrg sz /= 2; 18632001f49Smrg } 18732001f49Smrg } 18832001f49Smrg} 18932001f49Smrg 19032001f49Smrgstatic void 19132001f49Smrgmyinit(void) 19232001f49Smrg{ 19332001f49Smrg InitValues(); 19432001f49Smrg 19532001f49Smrg glEnable(GL_DEPTH_TEST); 19632001f49Smrg glDepthFunc(GL_LESS); 19732001f49Smrg glShadeModel(GL_FLAT); 19832001f49Smrg 19932001f49Smrg glTranslatef(0.0, 0.0, -3.6); 20032001f49Smrg 20132001f49Smrg glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 20232001f49Smrg glGenTextures(1, &texImage); 20332001f49Smrg glBindTexture(GL_TEXTURE_2D, texImage); 20432001f49Smrg makeImages(1); 20532001f49Smrg glGenTextures(1, &texColor); 20632001f49Smrg glBindTexture(GL_TEXTURE_2D, texColor); 20732001f49Smrg makeImages(0); 20832001f49Smrg 20932001f49Smrg texCurrent = texImage; 21032001f49Smrg 21132001f49Smrg glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 21232001f49Smrg glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 21332001f49Smrg glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); 21432001f49Smrg glEnable(GL_TEXTURE_2D); 21532001f49Smrg} 21632001f49Smrg 21732001f49Smrgstatic void 21832001f49Smrgprint_string(const char *s) 21932001f49Smrg{ 22032001f49Smrg while (*s) { 22132001f49Smrg glutBitmapCharacter(GLUT_BITMAP_8_BY_13, (int) *s); 22232001f49Smrg s++; 22332001f49Smrg } 22432001f49Smrg} 22532001f49Smrg 22632001f49Smrgstatic void 22732001f49Smrgprint_info(void) 22832001f49Smrg{ 22932001f49Smrg int dy = 17; 23032001f49Smrg int x = Width-320, y = Height - dy; 23132001f49Smrg char s[100]; 23232001f49Smrg 23332001f49Smrg glDisable(GL_TEXTURE_2D); 23432001f49Smrg glColor3f(1, 1, 1); 23532001f49Smrg 23632001f49Smrg glWindowPos2i(x, y); 23732001f49Smrg sprintf(s, "MIN_FILTER (f/F): %s", min_filters[MinFilterIndex].name); 23832001f49Smrg print_string(s); 23932001f49Smrg y -= dy; 24032001f49Smrg 24132001f49Smrg glWindowPos2i(x, y); 24232001f49Smrg sprintf(s, " MAG_FILTER (g): %s", MagNearestFilter ? "NEAREST" : "LINEAR"); 24332001f49Smrg print_string(s); 24432001f49Smrg y -= dy; 24532001f49Smrg 24632001f49Smrg glWindowPos2i(x, y); 24732001f49Smrg sprintf(s, "Toggle Image (t):"); 24832001f49Smrg print_string(s); 24932001f49Smrg y -= dy; 25032001f49Smrg 25132001f49Smrg glWindowPos2i(x, y); 25232001f49Smrg sprintf(s, "BASE_LEVEL (b/B): %d", BaseLevel); 25332001f49Smrg print_string(s); 25432001f49Smrg y -= dy; 25532001f49Smrg 25632001f49Smrg glWindowPos2i(x, y); 25732001f49Smrg sprintf(s, " MAX_LEVEL (m/M): %d", MaxLevel); 25832001f49Smrg print_string(s); 25932001f49Smrg y -= dy; 26032001f49Smrg 26132001f49Smrg glWindowPos2i(x, y); 26232001f49Smrg sprintf(s, " MIN_LOD (n/N): %f", MinLod); 26332001f49Smrg print_string(s); 26432001f49Smrg y -= dy; 26532001f49Smrg 26632001f49Smrg glWindowPos2i(x, y); 26732001f49Smrg sprintf(s, " MAX_LOD (x/X): %f", MaxLod); 26832001f49Smrg print_string(s); 26932001f49Smrg y -= dy; 27032001f49Smrg 27132001f49Smrg glWindowPos2i(x, y); 27232001f49Smrg sprintf(s, " LOD_BIAS (l/L): %f", LodBias); 27332001f49Smrg print_string(s); 27432001f49Smrg y -= dy; 27532001f49Smrg 27632001f49Smrg glWindowPos2i(x, y); 27732001f49Smrg sprintf(s, " RESET (space)"); 27832001f49Smrg print_string(s); 27932001f49Smrg y -= dy; 28032001f49Smrg 28132001f49Smrg 28232001f49Smrg glEnable(GL_TEXTURE_2D); 28332001f49Smrg} 28432001f49Smrg 28532001f49Smrg 28632001f49Smrgstatic void 28732001f49Smrgdisplay(void) 28832001f49Smrg{ 28932001f49Smrg GLfloat tcm = 1.0; 29032001f49Smrg glBindTexture(GL_TEXTURE_2D, texCurrent); 29132001f49Smrg 29232001f49Smrg printf 29332001f49Smrg ("BASE_LEVEL=%d MAX_LEVEL=%d MIN_LOD=%.2g MAX_LOD=%.2g Bias=%.2g Filter=%s/%s\n", 29432001f49Smrg BaseLevel, MaxLevel, MinLod, MaxLod, LodBias, min_filters[MinFilterIndex].name, 29532001f49Smrg MagNearestFilter ? "NEAREST" : "LINEAR"); 29632001f49Smrg fflush(stdout); 29732001f49Smrg 29832001f49Smrg glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, BaseLevel); 29932001f49Smrg glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, MaxLevel); 30032001f49Smrg 30132001f49Smrg glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, MinLod); 30232001f49Smrg glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, MaxLod); 30332001f49Smrg 30432001f49Smrg glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filters[MinFilterIndex].value); 30532001f49Smrg glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, MagNearestFilter ? GL_NEAREST : GL_LINEAR); 30632001f49Smrg 30732001f49Smrg glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, LodBias); 30832001f49Smrg 30932001f49Smrg glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 31032001f49Smrg glBegin(GL_QUADS); 31132001f49Smrg glTexCoord2f(0.0, 0.0); 31232001f49Smrg glVertex3f(-2.0, -1.0, 0.0); 31332001f49Smrg glTexCoord2f(0.0, tcm); 31432001f49Smrg glVertex3f(-2.0, 1.0, 0.0); 31532001f49Smrg glTexCoord2f(tcm * 3000.0, tcm); 31632001f49Smrg glVertex3f(3000.0, 1.0, -6000.0); 31732001f49Smrg glTexCoord2f(tcm * 3000.0, 0.0); 31832001f49Smrg glVertex3f(3000.0, -1.0, -6000.0); 31932001f49Smrg glEnd(); 32032001f49Smrg 32132001f49Smrg print_info(); 32232001f49Smrg 32332001f49Smrg glFlush(); 32432001f49Smrg} 32532001f49Smrg 32632001f49Smrgstatic void 32732001f49SmrgmyReshape(int w, int h) 32832001f49Smrg{ 32932001f49Smrg Width = w; 33032001f49Smrg Height = h; 33132001f49Smrg glViewport(0, 0, w, h); 33232001f49Smrg glMatrixMode(GL_PROJECTION); 33332001f49Smrg glLoadIdentity(); 33432001f49Smrg gluPerspective(60.0, 1.0 * (GLfloat) w / (GLfloat) h, 1.0, 30000.0); 33532001f49Smrg glMatrixMode(GL_MODELVIEW); 33632001f49Smrg glLoadIdentity(); 33732001f49Smrg} 33832001f49Smrg 33932001f49Smrg 34032001f49Smrgstatic void 34132001f49Smrgusage(void) 34232001f49Smrg{ 34332001f49Smrg printf("usage:\n"); 34432001f49Smrg printf(" b/B decrease/increase GL_TEXTURE_BASE_LEVEL\n"); 34532001f49Smrg printf(" m/M decrease/increase GL_TEXTURE_MAX_LEVEL\n"); 34632001f49Smrg printf(" n/N decrease/increase GL_TEXTURE_MIN_LOD\n"); 34732001f49Smrg printf(" x/X decrease/increase GL_TEXTURE_MAX_LOD\n"); 34832001f49Smrg printf(" l/L decrease/increase GL_TEXTURE_LOD_BIAS\n"); 34932001f49Smrg printf(" f/F cycle minification filter\n"); 35032001f49Smrg printf(" g toggle nearest/linear magnification filter\n"); 35132001f49Smrg printf(" t toggle texture color/image\n"); 35232001f49Smrg printf(" SPACE reset values\n"); 35332001f49Smrg fflush(stdout); 35432001f49Smrg} 35532001f49Smrg 35632001f49Smrgstatic void 35732001f49Smrgkey(unsigned char k, int x, int y) 35832001f49Smrg{ 35932001f49Smrg (void) x; 36032001f49Smrg (void) y; 36132001f49Smrg switch (k) { 36232001f49Smrg case 'b': 36332001f49Smrg BaseLevel--; 36432001f49Smrg if (BaseLevel < 0) 36532001f49Smrg BaseLevel = 0; 36632001f49Smrg break; 36732001f49Smrg case 'B': 36832001f49Smrg BaseLevel++; 36932001f49Smrg if (BaseLevel > 10) 37032001f49Smrg BaseLevel = 10; 37132001f49Smrg break; 37232001f49Smrg case 'm': 37332001f49Smrg MaxLevel--; 37432001f49Smrg if (MaxLevel < 0) 37532001f49Smrg MaxLevel = 0; 37632001f49Smrg break; 37732001f49Smrg case 'M': 37832001f49Smrg MaxLevel++; 37932001f49Smrg if (MaxLevel > 10) 38032001f49Smrg MaxLevel = 10; 38132001f49Smrg break; 38232001f49Smrg case 'l': 38332001f49Smrg LodBias -= 0.25; 38432001f49Smrg break; 38532001f49Smrg case 'L': 38632001f49Smrg LodBias += 0.25; 38732001f49Smrg break; 38832001f49Smrg case 'n': 38932001f49Smrg MinLod -= 0.25; 39032001f49Smrg break; 39132001f49Smrg case 'N': 39232001f49Smrg MinLod += 0.25; 39332001f49Smrg break; 39432001f49Smrg case 'x': 39532001f49Smrg MaxLod -= 0.25; 39632001f49Smrg break; 39732001f49Smrg case 'X': 39832001f49Smrg MaxLod += 0.25; 39932001f49Smrg break; 40032001f49Smrg case 'f': 40132001f49Smrg if (MinFilterIndex == 0) 40232001f49Smrg MinFilterIndex = sizeof(min_filters) / sizeof(*min_filters); 40332001f49Smrg MinFilterIndex--; 40432001f49Smrg break; 40532001f49Smrg case 'F': 40632001f49Smrg MinFilterIndex++; 40732001f49Smrg if (MinFilterIndex == sizeof(min_filters) / sizeof(*min_filters)) 40832001f49Smrg MinFilterIndex = 0; 40932001f49Smrg break; 41032001f49Smrg case 'g': 41132001f49Smrg MagNearestFilter = !MagNearestFilter; 41232001f49Smrg break; 41332001f49Smrg case 't': 41432001f49Smrg if (texCurrent == texColor) 41532001f49Smrg texCurrent = texImage; 41632001f49Smrg else 41732001f49Smrg texCurrent = texColor; 41832001f49Smrg break; 41932001f49Smrg case ' ': 42032001f49Smrg InitValues(); 42132001f49Smrg /* fall-through */ 42232001f49Smrg case 'u': 42332001f49Smrg usage(); 42432001f49Smrg break; 42532001f49Smrg case 27: /* Escape */ 42632001f49Smrg exit(0); 42732001f49Smrg break; 42832001f49Smrg default: 42932001f49Smrg return; 43032001f49Smrg } 43132001f49Smrg glutPostRedisplay(); 43232001f49Smrg} 43332001f49Smrg 43432001f49Smrg 43532001f49Smrgint 43632001f49Smrgmain(int argc, char **argv) 43732001f49Smrg{ 43832001f49Smrg glutInit(&argc, argv); 43932001f49Smrg glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); 44032001f49Smrg glutInitWindowSize(Width, Height); 44132001f49Smrg glutCreateWindow(argv[0]); 44232001f49Smrg glewInit(); 44332001f49Smrg myinit(); 44432001f49Smrg glutReshapeFunc(myReshape); 44532001f49Smrg glutDisplayFunc(display); 44632001f49Smrg glutKeyboardFunc(key); 44732001f49Smrg usage(); 44832001f49Smrg glutMainLoop(); 44932001f49Smrg return 0; /* ANSI C requires main to return int. */ 45032001f49Smrg} 451