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 
32 #ifndef PI
33 #define PI 3.141592657
34 #endif
35 
36 enum {
37     NORMAL = 0,
38     WEIRD = 1
39 };
40 
41 enum {
42     STREAK = 0,
43     CIRCLE = 1
44 };
45 
46 #define MAXSTARS 400
47 #define MAXPOS 10000
48 #define MAXWARP 500
49 #define MAXANGLES 6000
50 
51 
52 typedef struct _starRec {
53     GLint type;
54     float x[2], y[2], z[2];
55     float offsetX, offsetY, offsetR, rotation;
56 } starRec;
57 
58 
59 GLenum doubleBuffer;
60 GLint windW, windH;
61 
62 GLenum flag = NORMAL;
63 GLint starCount = MAXSTARS / 2;
64 float speed = 1.0;
65 GLint nitro = 0;
66 starRec stars[MAXSTARS];
67 float sinTable[MAXANGLES];
68 
69 
Sin(float angle)70 static float Sin(float angle)
71 {
72 
73     return (sinTable[(GLint)angle]);
74 }
75 
Cos(float angle)76 static float Cos(float angle)
77 {
78 
79     return (sinTable[((GLint)angle+(MAXANGLES/4))%MAXANGLES]);
80 }
81 
NewStar(GLint n,GLint d)82 static void NewStar(GLint n, GLint d)
83 {
84 
85     if (rand()%4 == 0) {
86 	stars[n].type = CIRCLE;
87     } else {
88 	stars[n].type = STREAK;
89     }
90     stars[n].x[0] = (float)(rand() % MAXPOS - MAXPOS / 2);
91     stars[n].y[0] = (float)(rand() % MAXPOS - MAXPOS / 2);
92     stars[n].z[0] = (float)(rand() % MAXPOS + d);
93     if (rand()%4 == 0 && flag == WEIRD) {
94 	stars[n].offsetX = (float)(rand() % 100 - 100 / 2);
95 	stars[n].offsetY = (float)(rand() % 100 - 100 / 2);
96 	stars[n].offsetR = (float)(rand() % 25 - 25 / 2);
97     } else {
98 	stars[n].offsetX = 0.0;
99 	stars[n].offsetY = 0.0;
100 	stars[n].offsetR = 0.0;
101     }
102 }
103 
RotatePoint(float * x,float * y,float rotation)104 static void RotatePoint(float *x, float *y, float rotation)
105 {
106     float tmpX, tmpY;
107 
108     tmpX = *x * Cos(rotation) - *y * Sin(rotation);
109     tmpY = *y * Cos(rotation) + *x * Sin(rotation);
110     *x = tmpX;
111     *y = tmpY;
112 }
113 
MoveStars(void)114 static void MoveStars(void)
115 {
116     float offset;
117     GLint n;
118     static double t0 = -1.;
119     double t, dt;
120     t = glutGet(GLUT_ELAPSED_TIME) / 1000.;
121     if (t0 < 0.)
122        t0 = t;
123     dt = 85.*(t - t0);
124     t0 = t;
125 
126     offset = speed * 60.0;
127 
128     for (n = 0; n < starCount; n++) {
129 	stars[n].x[1] = stars[n].x[0];
130 	stars[n].y[1] = stars[n].y[0];
131 	stars[n].z[1] = stars[n].z[0];
132 	stars[n].x[0] += stars[n].offsetX*dt;
133 	stars[n].y[0] += stars[n].offsetY*dt;
134 	stars[n].z[0] -= offset*dt;
135         stars[n].rotation += stars[n].offsetR*dt;
136         if (stars[n].rotation > MAXANGLES) {
137             stars[n].rotation = 0.0;
138 	}
139         else if (stars[n].rotation < 0.0) {
140            stars[n].rotation += 360.0;
141         }
142     }
143 }
144 
StarPoint(GLint n)145 static GLenum StarPoint(GLint n)
146 {
147     float x0, y0, x1, y1, width;
148     GLint i;
149 
150     x0 = stars[n].x[0] * windW / stars[n].z[0];
151     y0 = stars[n].y[0] * windH / stars[n].z[0];
152     RotatePoint(&x0, &y0, stars[n].rotation);
153     x0 += windW / 2.0;
154     y0 += windH / 2.0;
155 
156     if (x0 >= 0.0 && x0 < windW && y0 >= 0.0 && y0 < windH) {
157 	if (stars[n].type == STREAK) {
158 	    x1 = stars[n].x[1] * windW / stars[n].z[1];
159 	    y1 = stars[n].y[1] * windH / stars[n].z[1];
160 	    RotatePoint(&x1, &y1, stars[n].rotation);
161 	    x1 += windW / 2.0;
162 	    y1 += windH / 2.0;
163 
164 	    glLineWidth(MAXPOS/100.0/stars[n].z[0]+1.0);
165 	    glColor3f(1.0, (MAXWARP-speed)/MAXWARP, (MAXWARP-speed)/MAXWARP);
166 	    if (fabs(x0-x1) < 1.0 && fabs(y0-y1) < 1.0) {
167 		glBegin(GL_POINTS);
168 		    glVertex2f(x0, y0);
169 		glEnd();
170 	    } else {
171 		glBegin(GL_LINES);
172 		    glVertex2f(x0, y0);
173 		    glVertex2f(x1, y1);
174 		glEnd();
175 	    }
176 	} else {
177 	    width = MAXPOS / 10.0 / stars[n].z[0] + 1.0;
178 	    glColor3f(1.0, 0.0, 0.0);
179 	    glBegin(GL_POLYGON);
180 		for (i = 0; i < 8; i++) {
181 		    float x = x0 + width * Cos((float)i*MAXANGLES/8.0);
182 		    float y = y0 + width * Sin((float)i*MAXANGLES/8.0);
183 		    glVertex2f(x, y);
184 		};
185 	    glEnd();
186 	}
187 	return GL_TRUE;
188     } else {
189 	return GL_FALSE;
190     }
191 }
192 
ShowStars(void)193 static void ShowStars(void)
194 {
195     GLint n;
196 
197     glClear(GL_COLOR_BUFFER_BIT);
198 
199     for (n = 0; n < starCount; n++) {
200 	if (stars[n].z[0] > speed || (stars[n].z[0] > 0.0 && speed < MAXWARP)) {
201 	    if (StarPoint(n) == GL_FALSE) {
202 		NewStar(n, MAXPOS);
203 	    }
204 	} else {
205 	    NewStar(n, MAXPOS);
206 	}
207     }
208 }
209 
Init(void)210 static void Init(void)
211 {
212     float angle;
213     GLint n;
214 
215     srand((unsigned int) glutGet(GLUT_ELAPSED_TIME) );
216 
217     for (n = 0; n < MAXSTARS; n++) {
218 	NewStar(n, 100);
219     }
220 
221     angle = 0.0;
222     for (n = 0; n < MAXANGLES ; n++) {
223 	sinTable[n] = sin(angle);
224         angle += PI / (MAXANGLES / 2.0);
225     }
226 
227     glClearColor(0.0, 0.0, 0.0, 0.0);
228 
229     glDisable(GL_DITHER);
230 }
231 
Reshape(int width,int height)232 static void Reshape(int width, int height)
233 {
234 
235     windW = (GLint)width;
236     windH = (GLint)height;
237 
238     glViewport(0, 0, windW, windH);
239 
240     glMatrixMode(GL_PROJECTION);
241     glLoadIdentity();
242     gluOrtho2D(-0.5, windW+0.5, -0.5, windH+0.5);
243     glMatrixMode(GL_MODELVIEW);
244 }
245 
Key(unsigned char key,int x,int y)246 static void Key(unsigned char key, int x, int y)
247 {
248 
249     switch (key) {
250       case 27:
251 	exit(1);
252       case 32:
253 	flag = (flag == NORMAL) ? WEIRD : NORMAL;
254 	break;
255       case 't':
256 	nitro = 1;
257 	break;
258       default:
259 	return;
260     }
261 }
262 
Draw(void)263 static void Draw(void)
264 {
265 
266     MoveStars();
267     ShowStars();
268     if (nitro > 0) {
269 	speed = (float)(nitro / 10) + 1.0;
270 	if (speed > MAXWARP) {
271 	    speed = MAXWARP;
272 	}
273 	if (++nitro > MAXWARP*10) {
274 	    nitro = -nitro;
275 	}
276     } else if (nitro < 0) {
277 	nitro++;
278 	speed = (float)(-nitro / 10) + 1.0;
279 	if (speed > MAXWARP) {
280 	    speed = MAXWARP;
281 	}
282     }
283 
284     glFlush();
285     if (doubleBuffer) {
286 	glutSwapBuffers();
287     }
288 }
289 
Args(int argc,char ** argv)290 static GLenum Args(int argc, char **argv)
291 {
292     GLint i;
293 
294     doubleBuffer = GL_TRUE;
295 
296     for (i = 1; i < argc; i++) {
297 	if (strcmp(argv[i], "-sb") == 0) {
298 	    doubleBuffer = GL_FALSE;
299 	} else if (strcmp(argv[i], "-db") == 0) {
300 	    doubleBuffer = GL_TRUE;
301 	}
302     }
303     return GL_TRUE;
304 }
305 
306 #if !defined(GLUTCALLBACK)
307 #define GLUTCALLBACK
308 #endif
309 
glut_post_redisplay_p(void)310 static void GLUTCALLBACK glut_post_redisplay_p(void)
311 {
312       glutPostRedisplay();
313 }
314 
main(int argc,char ** argv)315 int main(int argc, char **argv)
316 {
317     GLenum type;
318 
319     glutInit(&argc, argv);
320 
321     if (Args(argc, argv) == GL_FALSE) {
322 	exit(1);
323     }
324 
325     windW = 300;
326     windH = 300;
327     glutInitWindowPosition(0, 0); glutInitWindowSize( 300, 300);
328 
329     type = GLUT_RGB;
330     type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
331     glutInitDisplayMode(type);
332 
333     if (glutCreateWindow("Stars") == GL_FALSE) {
334 	exit(1);
335     }
336 
337     Init();
338 
339     glutReshapeFunc(Reshape);
340     glutKeyboardFunc(Key);
341     glutDisplayFunc(Draw);
342     glutIdleFunc(glut_post_redisplay_p);
343     glutMainLoop();
344 	return 0;
345 }
346