132001f49Smrg/*
232001f49Smrg * Copyright (c) 1991, 1992, 1993 Silicon Graphics, Inc.
332001f49Smrg *
432001f49Smrg * Permission to use, copy, modify, distribute, and sell this software and
532001f49Smrg * its documentation for any purpose is hereby granted without fee, provided
632001f49Smrg * that (i) the above copyright notices and this permission notice appear in
732001f49Smrg * all copies of the software and related documentation, and (ii) the name of
832001f49Smrg * Silicon Graphics may not be used in any advertising or
932001f49Smrg * publicity relating to the software without the specific, prior written
1032001f49Smrg * permission of Silicon Graphics.
1132001f49Smrg *
1232001f49Smrg * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF
1332001f49Smrg * ANY KIND,
1432001f49Smrg * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
1532001f49Smrg * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
1632001f49Smrg *
1732001f49Smrg * IN NO EVENT SHALL SILICON GRAPHICS BE LIABLE FOR
1832001f49Smrg * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
1932001f49Smrg * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
2032001f49Smrg * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
2132001f49Smrg * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
2232001f49Smrg * OF THIS SOFTWARE.
2332001f49Smrg */
2432001f49Smrg
2532001f49Smrg#include <stdio.h>
2632001f49Smrg#include <string.h>
2732001f49Smrg#include <stdlib.h>
2832001f49Smrg#include <math.h>
2932001f49Smrg#include "glut_wrap.h"
3032001f49Smrg
3132001f49Smrg
3232001f49Smrg#ifndef PI
3332001f49Smrg#define PI 3.141592657
3432001f49Smrg#endif
3532001f49Smrg
3632001f49Smrgenum {
3732001f49Smrg    NORMAL = 0,
3832001f49Smrg    WEIRD = 1
3932001f49Smrg};
4032001f49Smrg
4132001f49Smrgenum {
4232001f49Smrg    STREAK = 0,
4332001f49Smrg    CIRCLE = 1
4432001f49Smrg};
4532001f49Smrg
4632001f49Smrg#define MAXSTARS 400
4732001f49Smrg#define MAXPOS 10000
4832001f49Smrg#define MAXWARP 500
4932001f49Smrg#define MAXANGLES 6000
5032001f49Smrg
5132001f49Smrg
5232001f49Smrgtypedef struct _starRec {
5332001f49Smrg    GLint type;
5432001f49Smrg    float x[2], y[2], z[2];
5532001f49Smrg    float offsetX, offsetY, offsetR, rotation;
5632001f49Smrg} starRec;
5732001f49Smrg
5832001f49Smrg
5932001f49SmrgGLenum doubleBuffer;
6032001f49SmrgGLint windW, windH;
6132001f49Smrg
6232001f49SmrgGLenum flag = NORMAL;
6332001f49SmrgGLint starCount = MAXSTARS / 2;
6432001f49Smrgfloat speed = 1.0;
6532001f49SmrgGLint nitro = 0;
6632001f49SmrgstarRec stars[MAXSTARS];
6732001f49Smrgfloat sinTable[MAXANGLES];
6832001f49Smrg
6932001f49Smrg
7032001f49Smrgstatic float Sin(float angle)
7132001f49Smrg{
7232001f49Smrg
7332001f49Smrg    return (sinTable[(GLint)angle]);
7432001f49Smrg}
7532001f49Smrg
7632001f49Smrgstatic float Cos(float angle)
7732001f49Smrg{
7832001f49Smrg
7932001f49Smrg    return (sinTable[((GLint)angle+(MAXANGLES/4))%MAXANGLES]);
8032001f49Smrg}
8132001f49Smrg
8232001f49Smrgstatic void NewStar(GLint n, GLint d)
8332001f49Smrg{
8432001f49Smrg
8532001f49Smrg    if (rand()%4 == 0) {
8632001f49Smrg	stars[n].type = CIRCLE;
8732001f49Smrg    } else {
8832001f49Smrg	stars[n].type = STREAK;
8932001f49Smrg    }
9032001f49Smrg    stars[n].x[0] = (float)(rand() % MAXPOS - MAXPOS / 2);
9132001f49Smrg    stars[n].y[0] = (float)(rand() % MAXPOS - MAXPOS / 2);
9232001f49Smrg    stars[n].z[0] = (float)(rand() % MAXPOS + d);
9332001f49Smrg    if (rand()%4 == 0 && flag == WEIRD) {
9432001f49Smrg	stars[n].offsetX = (float)(rand() % 100 - 100 / 2);
9532001f49Smrg	stars[n].offsetY = (float)(rand() % 100 - 100 / 2);
9632001f49Smrg	stars[n].offsetR = (float)(rand() % 25 - 25 / 2);
9732001f49Smrg    } else {
9832001f49Smrg	stars[n].offsetX = 0.0;
9932001f49Smrg	stars[n].offsetY = 0.0;
10032001f49Smrg	stars[n].offsetR = 0.0;
10132001f49Smrg    }
10232001f49Smrg}
10332001f49Smrg
10432001f49Smrgstatic void RotatePoint(float *x, float *y, float rotation)
10532001f49Smrg{
10632001f49Smrg    float tmpX, tmpY;
10732001f49Smrg
10832001f49Smrg    tmpX = *x * Cos(rotation) - *y * Sin(rotation);
10932001f49Smrg    tmpY = *y * Cos(rotation) + *x * Sin(rotation);
11032001f49Smrg    *x = tmpX;
11132001f49Smrg    *y = tmpY;
11232001f49Smrg}
11332001f49Smrg
11432001f49Smrgstatic void MoveStars(void)
11532001f49Smrg{
11632001f49Smrg    float offset;
11732001f49Smrg    GLint n;
11832001f49Smrg    static double t0 = -1.;
11932001f49Smrg    double t, dt;
12032001f49Smrg    t = glutGet(GLUT_ELAPSED_TIME) / 1000.;
12132001f49Smrg    if (t0 < 0.)
12232001f49Smrg       t0 = t;
12332001f49Smrg    dt = 85.*(t - t0);
12432001f49Smrg    t0 = t;
12532001f49Smrg
12632001f49Smrg    offset = speed * 60.0;
12732001f49Smrg
12832001f49Smrg    for (n = 0; n < starCount; n++) {
12932001f49Smrg	stars[n].x[1] = stars[n].x[0];
13032001f49Smrg	stars[n].y[1] = stars[n].y[0];
13132001f49Smrg	stars[n].z[1] = stars[n].z[0];
13232001f49Smrg	stars[n].x[0] += stars[n].offsetX*dt;
13332001f49Smrg	stars[n].y[0] += stars[n].offsetY*dt;
13432001f49Smrg	stars[n].z[0] -= offset*dt;
13532001f49Smrg        stars[n].rotation += stars[n].offsetR*dt;
13632001f49Smrg        if (stars[n].rotation > MAXANGLES) {
13732001f49Smrg            stars[n].rotation = 0.0;
13832001f49Smrg	}
13932001f49Smrg        else if (stars[n].rotation < 0.0) {
14032001f49Smrg           stars[n].rotation += 360.0;
14132001f49Smrg        }
14232001f49Smrg    }
14332001f49Smrg}
14432001f49Smrg
14532001f49Smrgstatic GLenum StarPoint(GLint n)
14632001f49Smrg{
14732001f49Smrg    float x0, y0, x1, y1, width;
14832001f49Smrg    GLint i;
14932001f49Smrg
15032001f49Smrg    x0 = stars[n].x[0] * windW / stars[n].z[0];
15132001f49Smrg    y0 = stars[n].y[0] * windH / stars[n].z[0];
15232001f49Smrg    RotatePoint(&x0, &y0, stars[n].rotation);
15332001f49Smrg    x0 += windW / 2.0;
15432001f49Smrg    y0 += windH / 2.0;
15532001f49Smrg
15632001f49Smrg    if (x0 >= 0.0 && x0 < windW && y0 >= 0.0 && y0 < windH) {
15732001f49Smrg	if (stars[n].type == STREAK) {
15832001f49Smrg	    x1 = stars[n].x[1] * windW / stars[n].z[1];
15932001f49Smrg	    y1 = stars[n].y[1] * windH / stars[n].z[1];
16032001f49Smrg	    RotatePoint(&x1, &y1, stars[n].rotation);
16132001f49Smrg	    x1 += windW / 2.0;
16232001f49Smrg	    y1 += windH / 2.0;
16332001f49Smrg
16432001f49Smrg	    glLineWidth(MAXPOS/100.0/stars[n].z[0]+1.0);
16532001f49Smrg	    glColor3f(1.0, (MAXWARP-speed)/MAXWARP, (MAXWARP-speed)/MAXWARP);
16632001f49Smrg	    if (fabs(x0-x1) < 1.0 && fabs(y0-y1) < 1.0) {
16732001f49Smrg		glBegin(GL_POINTS);
16832001f49Smrg		    glVertex2f(x0, y0);
16932001f49Smrg		glEnd();
17032001f49Smrg	    } else {
17132001f49Smrg		glBegin(GL_LINES);
17232001f49Smrg		    glVertex2f(x0, y0);
17332001f49Smrg		    glVertex2f(x1, y1);
17432001f49Smrg		glEnd();
17532001f49Smrg	    }
17632001f49Smrg	} else {
17732001f49Smrg	    width = MAXPOS / 10.0 / stars[n].z[0] + 1.0;
17832001f49Smrg	    glColor3f(1.0, 0.0, 0.0);
17932001f49Smrg	    glBegin(GL_POLYGON);
18032001f49Smrg		for (i = 0; i < 8; i++) {
18132001f49Smrg		    float x = x0 + width * Cos((float)i*MAXANGLES/8.0);
18232001f49Smrg		    float y = y0 + width * Sin((float)i*MAXANGLES/8.0);
18332001f49Smrg		    glVertex2f(x, y);
18432001f49Smrg		};
18532001f49Smrg	    glEnd();
18632001f49Smrg	}
18732001f49Smrg	return GL_TRUE;
18832001f49Smrg    } else {
18932001f49Smrg	return GL_FALSE;
19032001f49Smrg    }
19132001f49Smrg}
19232001f49Smrg
19332001f49Smrgstatic void ShowStars(void)
19432001f49Smrg{
19532001f49Smrg    GLint n;
19632001f49Smrg
19732001f49Smrg    glClear(GL_COLOR_BUFFER_BIT);
19832001f49Smrg
19932001f49Smrg    for (n = 0; n < starCount; n++) {
20032001f49Smrg	if (stars[n].z[0] > speed || (stars[n].z[0] > 0.0 && speed < MAXWARP)) {
20132001f49Smrg	    if (StarPoint(n) == GL_FALSE) {
20232001f49Smrg		NewStar(n, MAXPOS);
20332001f49Smrg	    }
20432001f49Smrg	} else {
20532001f49Smrg	    NewStar(n, MAXPOS);
20632001f49Smrg	}
20732001f49Smrg    }
20832001f49Smrg}
20932001f49Smrg
21032001f49Smrgstatic void Init(void)
21132001f49Smrg{
21232001f49Smrg    float angle;
21332001f49Smrg    GLint n;
21432001f49Smrg
21532001f49Smrg    srand((unsigned int) glutGet(GLUT_ELAPSED_TIME) );
21632001f49Smrg
21732001f49Smrg    for (n = 0; n < MAXSTARS; n++) {
21832001f49Smrg	NewStar(n, 100);
21932001f49Smrg    }
22032001f49Smrg
22132001f49Smrg    angle = 0.0;
22232001f49Smrg    for (n = 0; n < MAXANGLES ; n++) {
22332001f49Smrg	sinTable[n] = sin(angle);
22432001f49Smrg        angle += PI / (MAXANGLES / 2.0);
22532001f49Smrg    }
22632001f49Smrg
22732001f49Smrg    glClearColor(0.0, 0.0, 0.0, 0.0);
22832001f49Smrg
22932001f49Smrg    glDisable(GL_DITHER);
23032001f49Smrg}
23132001f49Smrg
23232001f49Smrgstatic void Reshape(int width, int height)
23332001f49Smrg{
23432001f49Smrg
23532001f49Smrg    windW = (GLint)width;
23632001f49Smrg    windH = (GLint)height;
23732001f49Smrg
23832001f49Smrg    glViewport(0, 0, windW, windH);
23932001f49Smrg
24032001f49Smrg    glMatrixMode(GL_PROJECTION);
24132001f49Smrg    glLoadIdentity();
24232001f49Smrg    gluOrtho2D(-0.5, windW+0.5, -0.5, windH+0.5);
24332001f49Smrg    glMatrixMode(GL_MODELVIEW);
24432001f49Smrg}
24532001f49Smrg
24632001f49Smrgstatic void Key(unsigned char key, int x, int y)
24732001f49Smrg{
24832001f49Smrg
24932001f49Smrg    switch (key) {
25032001f49Smrg      case 27:
25132001f49Smrg	exit(1);
25232001f49Smrg      case 32:
25332001f49Smrg	flag = (flag == NORMAL) ? WEIRD : NORMAL;
25432001f49Smrg	break;
25532001f49Smrg      case 't':
25632001f49Smrg	nitro = 1;
25732001f49Smrg	break;
25832001f49Smrg      default:
25932001f49Smrg	return;
26032001f49Smrg    }
26132001f49Smrg}
26232001f49Smrg
26332001f49Smrgstatic void Draw(void)
26432001f49Smrg{
26532001f49Smrg
26632001f49Smrg    MoveStars();
26732001f49Smrg    ShowStars();
26832001f49Smrg    if (nitro > 0) {
26932001f49Smrg	speed = (float)(nitro / 10) + 1.0;
27032001f49Smrg	if (speed > MAXWARP) {
27132001f49Smrg	    speed = MAXWARP;
27232001f49Smrg	}
27332001f49Smrg	if (++nitro > MAXWARP*10) {
27432001f49Smrg	    nitro = -nitro;
27532001f49Smrg	}
27632001f49Smrg    } else if (nitro < 0) {
27732001f49Smrg	nitro++;
27832001f49Smrg	speed = (float)(-nitro / 10) + 1.0;
27932001f49Smrg	if (speed > MAXWARP) {
28032001f49Smrg	    speed = MAXWARP;
28132001f49Smrg	}
28232001f49Smrg    }
28332001f49Smrg
28432001f49Smrg    glFlush();
28532001f49Smrg    if (doubleBuffer) {
28632001f49Smrg	glutSwapBuffers();
28732001f49Smrg    }
28832001f49Smrg}
28932001f49Smrg
29032001f49Smrgstatic GLenum Args(int argc, char **argv)
29132001f49Smrg{
29232001f49Smrg    GLint i;
29332001f49Smrg
29432001f49Smrg    doubleBuffer = GL_TRUE;
29532001f49Smrg
29632001f49Smrg    for (i = 1; i < argc; i++) {
29732001f49Smrg	if (strcmp(argv[i], "-sb") == 0) {
29832001f49Smrg	    doubleBuffer = GL_FALSE;
29932001f49Smrg	} else if (strcmp(argv[i], "-db") == 0) {
30032001f49Smrg	    doubleBuffer = GL_TRUE;
30132001f49Smrg	}
30232001f49Smrg    }
30332001f49Smrg    return GL_TRUE;
30432001f49Smrg}
30532001f49Smrg
30632001f49Smrg#if !defined(GLUTCALLBACK)
30732001f49Smrg#define GLUTCALLBACK
30832001f49Smrg#endif
30932001f49Smrg
31032001f49Smrgstatic void GLUTCALLBACK glut_post_redisplay_p(void)
31132001f49Smrg{
31232001f49Smrg      glutPostRedisplay();
31332001f49Smrg}
31432001f49Smrg
31532001f49Smrgint main(int argc, char **argv)
31632001f49Smrg{
31732001f49Smrg    GLenum type;
31832001f49Smrg
31932001f49Smrg    glutInit(&argc, argv);
32032001f49Smrg
32132001f49Smrg    if (Args(argc, argv) == GL_FALSE) {
32232001f49Smrg	exit(1);
32332001f49Smrg    }
32432001f49Smrg
32532001f49Smrg    windW = 300;
32632001f49Smrg    windH = 300;
32732001f49Smrg    glutInitWindowPosition(0, 0); glutInitWindowSize( 300, 300);
32832001f49Smrg
32932001f49Smrg    type = GLUT_RGB;
33032001f49Smrg    type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
33132001f49Smrg    glutInitDisplayMode(type);
33232001f49Smrg
33332001f49Smrg    if (glutCreateWindow("Stars") == GL_FALSE) {
33432001f49Smrg	exit(1);
33532001f49Smrg    }
33632001f49Smrg
33732001f49Smrg    Init();
33832001f49Smrg
33932001f49Smrg    glutReshapeFunc(Reshape);
34032001f49Smrg    glutKeyboardFunc(Key);
34132001f49Smrg    glutDisplayFunc(Draw);
34232001f49Smrg    glutIdleFunc(glut_post_redisplay_p);
34332001f49Smrg    glutMainLoop();
34432001f49Smrg	return 0;
34532001f49Smrg}
346