132001f49Smrg 232001f49Smrg/* Copyright (c) Mark J. Kilgard, 1997. */ 332001f49Smrg 432001f49Smrg/* This program is freely distributable without licensing fees 532001f49Smrg and is provided without guarantee or warrantee expressed or 632001f49Smrg implied. This program is -not- in the public domain. */ 732001f49Smrg 832001f49Smrg/* This example demonstrates how to render particle effects 932001f49Smrg with OpenGL. A cloud of pinkish/orange particles explodes with the 1032001f49Smrg particles bouncing off the ground. When the EXT_point_parameters 1132001f49Smrg is present , the particle size is attenuated based on eye distance. */ 1232001f49Smrg 1332001f49Smrg 1432001f49Smrg#include <stdio.h> 1532001f49Smrg#include <stdlib.h> 1632001f49Smrg#include <string.h> 1732001f49Smrg#include <math.h> /* for cos(), sin(), and sqrt() */ 1832001f49Smrg#ifdef _WIN32 1932001f49Smrg#include <windows.h> 2032001f49Smrg#endif 2132001f49Smrg#include <GL/glew.h> 2232001f49Smrg#include "glut_wrap.h" 2332001f49Smrg 2432001f49Smrg/* Some <math.h> files do not define M_PI... */ 2532001f49Smrg#ifndef M_PI 2632001f49Smrg#define M_PI 3.14159265 2732001f49Smrg#endif 2832001f49Smrg 2932001f49Smrg#if 0 /* For debugging. */ 3032001f49Smrg#undef GL_EXT_point_parameters 3132001f49Smrg#endif 3232001f49Smrg 3332001f49Smrgstatic GLfloat angle = -150; /* in degrees */ 3432001f49Smrgstatic int spin = 0; 3532001f49Smrgstatic int moving, begin; 3632001f49Smrgstatic int newModel = 1; 3732001f49Smrgstatic float theTime; 3832001f49Smrgstatic int repeat = 1; 3932001f49Smrgstatic int blend = 1; 4032001f49Smrgint useMipmaps = 1; 4132001f49Smrgint linearFiltering = 1; 4232001f49Smrg 4332001f49Smrgstatic GLfloat constant[3] = { 1/5.0, 0.0, 0.0 }; 4432001f49Smrgstatic GLfloat linear[3] = { 0.0, 1/5.0, 0.0 }; 4532001f49Smrgstatic GLfloat theQuad[3] = { 0.25, 0.0, 1/60.0 }; 4632001f49Smrg 4732001f49Smrg#define MAX_POINTS 2000 4832001f49Smrg 4932001f49Smrgstatic int numPoints = 200; 5032001f49Smrg 5132001f49Smrgstatic GLfloat pointList[MAX_POINTS][3]; 5232001f49Smrgstatic GLfloat pointTime[MAX_POINTS]; 5332001f49Smrgstatic GLfloat pointVelocity[MAX_POINTS][2]; 5432001f49Smrgstatic GLfloat pointDirection[MAX_POINTS][2]; 5532001f49Smrgstatic int colorList[MAX_POINTS]; 5632001f49Smrgstatic int animate = 1, motion = 0; 5732001f49Smrg 5832001f49Smrgstatic GLfloat colorSet[][4] = { 5932001f49Smrg /* Shades of red. */ 6032001f49Smrg { 0.7, 0.2, 0.4, 0.5 }, 6132001f49Smrg { 0.8, 0.0, 0.7, 0.5 }, 6232001f49Smrg { 1.0, 0.0, 0.0, 0.5 }, 6332001f49Smrg { 0.9, 0.3, 0.6, 0.5 }, 6432001f49Smrg { 1.0, 0.4, 0.0, 0.5 }, 6532001f49Smrg { 1.0, 0.0, 0.5, 0.5 }, 6632001f49Smrg}; 6732001f49Smrg 6832001f49Smrg#define NUM_COLORS (sizeof(colorSet)/sizeof(colorSet[0])) 6932001f49Smrg 7032001f49Smrg#define DEAD (NUM_COLORS+1) 7132001f49Smrg 7232001f49Smrg 7332001f49Smrg#if 0 /* drand48 might be better on Unix machines */ 7432001f49Smrg#define RANDOM_RANGE(lo, hi) ((lo) + (hi - lo) * drand48()) 7532001f49Smrg#else 7632001f49Smrgstatic float float_rand(void) { return rand() / (float) RAND_MAX; } 7732001f49Smrg#define RANDOM_RANGE(lo, hi) ((lo) + (hi - lo) * float_rand()) 7832001f49Smrg#endif 7932001f49Smrg 8032001f49Smrg#define MEAN_VELOCITY 3.0 8132001f49Smrg#define GRAVITY 2.0 8232001f49Smrg 8332001f49Smrg/* Modeling units of ground extent in each X and Z direction. */ 8432001f49Smrg#define EDGE 12 8532001f49Smrg 8632001f49Smrgstatic void 8732001f49SmrgmakePointList(void) 8832001f49Smrg{ 8932001f49Smrg float angle, velocity, direction; 9032001f49Smrg int i; 9132001f49Smrg 9232001f49Smrg motion = 1; 9332001f49Smrg for (i=0; i<numPoints; i++) { 9432001f49Smrg pointList[i][0] = 0.0; 9532001f49Smrg pointList[i][1] = 0.0; 9632001f49Smrg pointList[i][2] = 0.0; 9732001f49Smrg pointTime[i] = 0.0; 9832001f49Smrg angle = (RANDOM_RANGE(60.0, 70.0)) * M_PI/180.0; 9932001f49Smrg direction = RANDOM_RANGE(0.0, 360.0) * M_PI/180.0; 10032001f49Smrg pointDirection[i][0] = cos(direction); 10132001f49Smrg pointDirection[i][1] = sin(direction); 10232001f49Smrg velocity = MEAN_VELOCITY + RANDOM_RANGE(-0.8, 1.0); 10332001f49Smrg pointVelocity[i][0] = velocity * cos(angle); 10432001f49Smrg pointVelocity[i][1] = velocity * sin(angle); 10532001f49Smrg colorList[i] = rand() % NUM_COLORS; 10632001f49Smrg } 10732001f49Smrg theTime = 0.0; 10832001f49Smrg} 10932001f49Smrg 11032001f49Smrgstatic void 11132001f49SmrgupdatePointList(void) 11232001f49Smrg{ 11332001f49Smrg float distance; 11432001f49Smrg int i; 11532001f49Smrg 11632001f49Smrg static double t0 = -1.; 11732001f49Smrg double dt, t = glutGet(GLUT_ELAPSED_TIME) / 1000.0; 11832001f49Smrg if (t0 < 0.0) 11932001f49Smrg t0 = t; 12032001f49Smrg dt = t - t0; 12132001f49Smrg t0 = t; 12232001f49Smrg 12332001f49Smrg motion = 0; 12432001f49Smrg for (i=0; i<numPoints; i++) { 12532001f49Smrg distance = pointVelocity[i][0] * theTime; 12632001f49Smrg 12732001f49Smrg /* X and Z */ 12832001f49Smrg pointList[i][0] = pointDirection[i][0] * distance; 12932001f49Smrg pointList[i][2] = pointDirection[i][1] * distance; 13032001f49Smrg 13132001f49Smrg /* Z */ 13232001f49Smrg pointList[i][1] = 13332001f49Smrg (pointVelocity[i][1] - 0.5 * GRAVITY * pointTime[i])*pointTime[i]; 13432001f49Smrg 13532001f49Smrg /* If we hit the ground, bounce the point upward again. */ 13632001f49Smrg if (pointList[i][1] <= 0.0) { 13732001f49Smrg if (distance > EDGE) { 13832001f49Smrg /* Particle has hit ground past the distance duration of 13932001f49Smrg the particles. Mark particle as dead. */ 14032001f49Smrg colorList[i] = NUM_COLORS; /* Not moving. */ 14132001f49Smrg continue; 14232001f49Smrg } 14332001f49Smrg 14432001f49Smrg pointVelocity[i][1] *= 0.8; /* 80% of previous up velocity. */ 14532001f49Smrg pointTime[i] = 0.0; /* Reset the particles sense of up time. */ 14632001f49Smrg } 14732001f49Smrg motion = 1; 14832001f49Smrg pointTime[i] += dt; 14932001f49Smrg } 15032001f49Smrg theTime += dt; 15132001f49Smrg if (!motion && !spin) { 15232001f49Smrg if (repeat) { 15332001f49Smrg makePointList(); 15432001f49Smrg } else { 15532001f49Smrg glutIdleFunc(NULL); 15632001f49Smrg } 15732001f49Smrg } 15832001f49Smrg} 15932001f49Smrg 16032001f49Smrgstatic void 16132001f49Smrgidle(void) 16232001f49Smrg{ 16332001f49Smrg updatePointList(); 16432001f49Smrg if (spin) { 16532001f49Smrg angle += 0.3; 16632001f49Smrg newModel = 1; 16732001f49Smrg } 16832001f49Smrg glutPostRedisplay(); 16932001f49Smrg} 17032001f49Smrg 17132001f49Smrgstatic void 17232001f49Smrgvisible(int vis) 17332001f49Smrg{ 17432001f49Smrg if (vis == GLUT_VISIBLE) { 17532001f49Smrg if (animate && (motion || spin)) { 17632001f49Smrg glutIdleFunc(idle); 17732001f49Smrg } 17832001f49Smrg } else { 17932001f49Smrg glutIdleFunc(NULL); 18032001f49Smrg } 18132001f49Smrg} 18232001f49Smrg 18332001f49Smrgstatic void 18432001f49SmrgrecalcModelView(void) 18532001f49Smrg{ 18632001f49Smrg glPopMatrix(); 18732001f49Smrg glPushMatrix(); 18832001f49Smrg glRotatef(angle, 0.0, 1.0, 0.0); 18932001f49Smrg newModel = 0; 19032001f49Smrg} 19132001f49Smrg 19232001f49Smrgstatic void 19332001f49Smrgredraw(void) 19432001f49Smrg{ 19532001f49Smrg int i; 19632001f49Smrg 19732001f49Smrg glDepthMask(GL_TRUE); 19832001f49Smrg glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 19932001f49Smrg if (newModel) 20032001f49Smrg recalcModelView(); 20132001f49Smrg 20232001f49Smrg 20332001f49Smrg /* Draw the floor. */ 20432001f49Smrg/* glEnable(GL_TEXTURE_2D);*/ 20532001f49Smrg glColor3f(0.5, 1.0, 0.5); 20632001f49Smrg glBegin(GL_QUADS); 20732001f49Smrg glTexCoord2f(0.0, 0.0); 20832001f49Smrg glVertex3f(-EDGE, -0.05, -EDGE); 20932001f49Smrg glTexCoord2f(20.0, 0.0); 21032001f49Smrg glVertex3f(EDGE, -0.05, -EDGE); 21132001f49Smrg glTexCoord2f(20.0, 20.0); 21232001f49Smrg glVertex3f(EDGE, -0.05, EDGE); 21332001f49Smrg glTexCoord2f(0.0, 20.0); 21432001f49Smrg glVertex3f(-EDGE, -0.05, EDGE); 21532001f49Smrg glEnd(); 21632001f49Smrg 21732001f49Smrg /* Allow particles to blend with each other. */ 21832001f49Smrg glDepthMask(GL_FALSE); 21932001f49Smrg 22032001f49Smrg if (blend) 22132001f49Smrg glEnable(GL_BLEND); 22232001f49Smrg 22332001f49Smrg glDisable(GL_TEXTURE_2D); 22432001f49Smrg glBegin(GL_POINTS); 22532001f49Smrg for (i=0; i<numPoints; i++) { 22632001f49Smrg /* Draw alive particles. */ 22732001f49Smrg if (colorList[i] != DEAD) { 22832001f49Smrg glColor4fv(colorSet[colorList[i]]); 22932001f49Smrg glVertex3fv(pointList[i]); 23032001f49Smrg } 23132001f49Smrg } 23232001f49Smrg glEnd(); 23332001f49Smrg 23432001f49Smrg glDisable(GL_BLEND); 23532001f49Smrg 23632001f49Smrg glutSwapBuffers(); 23732001f49Smrg} 23832001f49Smrg 23932001f49Smrg/* ARGSUSED2 */ 24032001f49Smrgstatic void 24132001f49Smrgmouse(int button, int state, int x, int y) 24232001f49Smrg{ 24332001f49Smrg /* Scene can be spun around Y axis using left 24432001f49Smrg mouse button movement. */ 24532001f49Smrg if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) { 24632001f49Smrg moving = 1; 24732001f49Smrg begin = x; 24832001f49Smrg } 24932001f49Smrg if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) { 25032001f49Smrg moving = 0; 25132001f49Smrg } 25232001f49Smrg} 25332001f49Smrg 25432001f49Smrg/* ARGSUSED1 */ 25532001f49Smrgstatic void 25632001f49SmrgmouseMotion(int x, int y) 25732001f49Smrg{ 25832001f49Smrg if (moving) { 25932001f49Smrg angle = angle + (x - begin); 26032001f49Smrg begin = x; 26132001f49Smrg newModel = 1; 26232001f49Smrg glutPostRedisplay(); 26332001f49Smrg } 26432001f49Smrg} 26532001f49Smrg 26632001f49Smrgstatic void 26732001f49Smrgmenu(int option) 26832001f49Smrg{ 26932001f49Smrg switch (option) { 27032001f49Smrg case 0: 27132001f49Smrg makePointList(); 27232001f49Smrg break; 27332001f49Smrg#ifdef GL_ARB_point_parameters 27432001f49Smrg case 1: 27532001f49Smrg glPointParameterfvARB(GL_POINT_DISTANCE_ATTENUATION_ARB, constant); 27632001f49Smrg break; 27732001f49Smrg case 2: 27832001f49Smrg glPointParameterfvARB(GL_POINT_DISTANCE_ATTENUATION_ARB, linear); 27932001f49Smrg break; 28032001f49Smrg case 3: 28132001f49Smrg glPointParameterfvARB(GL_POINT_DISTANCE_ATTENUATION_ARB, theQuad); 28232001f49Smrg break; 28332001f49Smrg#endif 28432001f49Smrg case 4: 28532001f49Smrg blend = 1; 28632001f49Smrg break; 28732001f49Smrg case 5: 28832001f49Smrg blend = 0; 28932001f49Smrg break; 29032001f49Smrg#ifdef GL_ARB_point_parameters 29132001f49Smrg case 6: 29232001f49Smrg glPointParameterfARB(GL_POINT_FADE_THRESHOLD_SIZE_ARB, 1.0); 29332001f49Smrg break; 29432001f49Smrg case 7: 29532001f49Smrg glPointParameterfARB(GL_POINT_FADE_THRESHOLD_SIZE_ARB, 10.0); 29632001f49Smrg break; 29732001f49Smrg#endif 29832001f49Smrg case 8: 29932001f49Smrg glEnable(GL_POINT_SMOOTH); 30032001f49Smrg break; 30132001f49Smrg case 9: 30232001f49Smrg glDisable(GL_POINT_SMOOTH); 30332001f49Smrg break; 30432001f49Smrg case 10: 30532001f49Smrg glPointSize(2.0); 30632001f49Smrg break; 30732001f49Smrg case 11: 30832001f49Smrg glPointSize(4.0); 30932001f49Smrg break; 31032001f49Smrg case 12: 31132001f49Smrg glPointSize(8.0); 31232001f49Smrg break; 31332001f49Smrg case 13: 31432001f49Smrg spin = 1 - spin; 31532001f49Smrg if (animate && (spin || motion)) { 31632001f49Smrg glutIdleFunc(idle); 31732001f49Smrg } else { 31832001f49Smrg glutIdleFunc(NULL); 31932001f49Smrg } 32032001f49Smrg break; 32132001f49Smrg case 14: 32232001f49Smrg numPoints = 200; 32332001f49Smrg break; 32432001f49Smrg case 15: 32532001f49Smrg numPoints = 500; 32632001f49Smrg break; 32732001f49Smrg case 16: 32832001f49Smrg numPoints = 1000; 32932001f49Smrg break; 33032001f49Smrg case 17: 33132001f49Smrg numPoints = 2000; 33232001f49Smrg break; 33332001f49Smrg case 666: 33432001f49Smrg exit(0); 33532001f49Smrg } 33632001f49Smrg glutPostRedisplay(); 33732001f49Smrg} 33832001f49Smrg 33932001f49Smrg/* ARGSUSED1 */ 34032001f49Smrgstatic void 34132001f49Smrgkey(unsigned char c, int x, int y) 34232001f49Smrg{ 34332001f49Smrg switch (c) { 34432001f49Smrg case 13: 34532001f49Smrg animate = 1 - animate; /* toggle. */ 34632001f49Smrg if (animate && (motion || spin)) { 34732001f49Smrg glutIdleFunc(idle); 34832001f49Smrg } else { 34932001f49Smrg glutIdleFunc(NULL); 35032001f49Smrg } 35132001f49Smrg break; 35232001f49Smrg case ' ': 35332001f49Smrg animate = 1; 35432001f49Smrg makePointList(); 35532001f49Smrg glutIdleFunc(idle); 35632001f49Smrg break; 35732001f49Smrg case 27: 35832001f49Smrg exit(0); 35932001f49Smrg } 36032001f49Smrg} 36132001f49Smrg 36232001f49Smrg/* Nice floor texture tiling pattern. */ 36332001f49Smrgstatic char *circles[] = { 36432001f49Smrg "....xxxx........", 36532001f49Smrg "..xxxxxxxx......", 36632001f49Smrg ".xxxxxxxxxx.....", 36732001f49Smrg ".xxx....xxx.....", 36832001f49Smrg "xxx......xxx....", 36932001f49Smrg "xxx......xxx....", 37032001f49Smrg "xxx......xxx....", 37132001f49Smrg "xxx......xxx....", 37232001f49Smrg ".xxx....xxx.....", 37332001f49Smrg ".xxxxxxxxxx.....", 37432001f49Smrg "..xxxxxxxx......", 37532001f49Smrg "....xxxx........", 37632001f49Smrg "................", 37732001f49Smrg "................", 37832001f49Smrg "................", 37932001f49Smrg "................", 38032001f49Smrg}; 38132001f49Smrg 38232001f49Smrgstatic void 38332001f49SmrgmakeFloorTexture(void) 38432001f49Smrg{ 38532001f49Smrg GLubyte floorTexture[16][16][3]; 38632001f49Smrg GLubyte *loc; 38732001f49Smrg int s, t; 38832001f49Smrg 38932001f49Smrg /* Setup RGB image for the texture. */ 39032001f49Smrg loc = (GLubyte*) floorTexture; 39132001f49Smrg for (t = 0; t < 16; t++) { 39232001f49Smrg for (s = 0; s < 16; s++) { 39332001f49Smrg if (circles[t][s] == 'x') { 39432001f49Smrg /* Nice blue. */ 39532001f49Smrg loc[0] = 0x1f; 39632001f49Smrg loc[1] = 0x1f; 39732001f49Smrg loc[2] = 0x8f; 39832001f49Smrg } else { 39932001f49Smrg /* Light gray. */ 40032001f49Smrg loc[0] = 0xca; 40132001f49Smrg loc[1] = 0xca; 40232001f49Smrg loc[2] = 0xca; 40332001f49Smrg } 40432001f49Smrg loc += 3; 40532001f49Smrg } 40632001f49Smrg } 40732001f49Smrg 40832001f49Smrg glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 40932001f49Smrg 41032001f49Smrg if (useMipmaps) { 41132001f49Smrg glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, 41232001f49Smrg GL_LINEAR_MIPMAP_LINEAR); 41332001f49Smrg gluBuild2DMipmaps(GL_TEXTURE_2D, 3, 16, 16, 41432001f49Smrg GL_RGB, GL_UNSIGNED_BYTE, floorTexture); 41532001f49Smrg } else { 41632001f49Smrg if (linearFiltering) { 41732001f49Smrg glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 41832001f49Smrg } else { 41932001f49Smrg glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 42032001f49Smrg } 42132001f49Smrg glTexImage2D(GL_TEXTURE_2D, 0, 3, 16, 16, 0, 42232001f49Smrg GL_RGB, GL_UNSIGNED_BYTE, floorTexture); 42332001f49Smrg } 42432001f49Smrg} 42532001f49Smrg 42632001f49Smrgint 42732001f49Smrgmain(int argc, char **argv) 42832001f49Smrg{ 42932001f49Smrg int i; 43032001f49Smrg 43132001f49Smrg glutInitWindowSize(300, 300); 43232001f49Smrg glutInit(&argc, argv); 43332001f49Smrg glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_MULTISAMPLE); 43432001f49Smrg 43532001f49Smrg for (i=1; i<argc; i++) { 43632001f49Smrg if(!strcmp("-noms", argv[i])) { 43732001f49Smrg glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); 43832001f49Smrg printf("forcing no multisampling\n"); 43932001f49Smrg } else if(!strcmp("-nomipmaps", argv[i])) { 44032001f49Smrg useMipmaps = 0; 44132001f49Smrg } else if(!strcmp("-nearest", argv[i])) { 44232001f49Smrg linearFiltering = 0; 44332001f49Smrg } 44432001f49Smrg } 44532001f49Smrg 44632001f49Smrg glutCreateWindow("point burst"); 44732001f49Smrg glewInit(); 44832001f49Smrg glutDisplayFunc(redraw); 44932001f49Smrg glutMouseFunc(mouse); 45032001f49Smrg glutMotionFunc(mouseMotion); 45132001f49Smrg glutVisibilityFunc(visible); 45232001f49Smrg glutKeyboardFunc(key); 45332001f49Smrg glutCreateMenu(menu); 45432001f49Smrg glutAddMenuEntry("Reset time", 0); 45532001f49Smrg glutAddMenuEntry("Constant", 1); 45632001f49Smrg glutAddMenuEntry("Linear", 2); 45732001f49Smrg glutAddMenuEntry("Quadratic", 3); 45832001f49Smrg glutAddMenuEntry("Blend on", 4); 45932001f49Smrg glutAddMenuEntry("Blend off", 5); 46032001f49Smrg glutAddMenuEntry("Threshold 1", 6); 46132001f49Smrg glutAddMenuEntry("Threshold 10", 7); 46232001f49Smrg glutAddMenuEntry("Point smooth on", 8); 46332001f49Smrg glutAddMenuEntry("Point smooth off", 9); 46432001f49Smrg glutAddMenuEntry("Point size 2", 10); 46532001f49Smrg glutAddMenuEntry("Point size 4", 11); 46632001f49Smrg glutAddMenuEntry("Point size 8", 12); 46732001f49Smrg glutAddMenuEntry("Toggle spin", 13); 46832001f49Smrg glutAddMenuEntry("200 points ", 14); 46932001f49Smrg glutAddMenuEntry("500 points ", 15); 47032001f49Smrg glutAddMenuEntry("1000 points ", 16); 47132001f49Smrg glutAddMenuEntry("2000 points ", 17); 47232001f49Smrg glutAddMenuEntry("Quit", 666); 47332001f49Smrg glutAttachMenu(GLUT_RIGHT_BUTTON); 47432001f49Smrg 47532001f49Smrg if (!glutExtensionSupported("GL_ARB_point_parameters")) { 47632001f49Smrg fprintf(stderr, "Sorry, GL_ARB_point_parameters is not supported.\n"); 47732001f49Smrg return -1; 47832001f49Smrg } 47932001f49Smrg 48032001f49Smrg glShadeModel(GL_FLAT); 48132001f49Smrg glEnable(GL_DEPTH_TEST); 48232001f49Smrg glEnable(GL_POINT_SMOOTH); 48332001f49Smrg glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 48432001f49Smrg glPointSize(8.0); 48532001f49Smrg#if GL_ARB_point_parameters 48632001f49Smrg glPointParameterfvARB(GL_POINT_DISTANCE_ATTENUATION_ARB, theQuad); 48732001f49Smrg#endif 48832001f49Smrg glMatrixMode(GL_PROJECTION); 48932001f49Smrg gluPerspective( /* field of view in degree */ 40.0, 49032001f49Smrg /* aspect ratio */ 1.0, 49132001f49Smrg /* Z near */ 0.5, /* Z far */ 40.0); 49232001f49Smrg glMatrixMode(GL_MODELVIEW); 49332001f49Smrg gluLookAt(0.0, 1.0, 8.0, /* eye location */ 49432001f49Smrg 0.0, 1.0, 0.0, /* center is at (0,0,0) */ 49532001f49Smrg 0.0, 1.0, 0.); /* up is in postivie Y direction */ 49632001f49Smrg glPushMatrix(); /* dummy push so we can pop on model 49732001f49Smrg recalc */ 49832001f49Smrg 49932001f49Smrg makePointList(); 50032001f49Smrg makeFloorTexture(); 50132001f49Smrg 50232001f49Smrg glutMainLoop(); 50332001f49Smrg return 0; /* ANSI C requires main to return int. */ 50432001f49Smrg} 505