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