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 36enum { 37 NORMAL = 0, 38 WEIRD = 1 39}; 40 41enum { 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 52typedef struct _starRec { 53 GLint type; 54 float x[2], y[2], z[2]; 55 float offsetX, offsetY, offsetR, rotation; 56} starRec; 57 58 59GLenum doubleBuffer; 60GLint windW, windH; 61 62GLenum flag = NORMAL; 63GLint starCount = MAXSTARS / 2; 64float speed = 1.0; 65GLint nitro = 0; 66starRec stars[MAXSTARS]; 67float sinTable[MAXANGLES]; 68 69 70static float Sin(float angle) 71{ 72 73 return (sinTable[(GLint)angle]); 74} 75 76static float Cos(float angle) 77{ 78 79 return (sinTable[((GLint)angle+(MAXANGLES/4))%MAXANGLES]); 80} 81 82static 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 104static 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 114static 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 145static 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 193static 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 210static 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 232static 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 246static 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 263static 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 290static 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 310static void GLUTCALLBACK glut_post_redisplay_p(void) 311{ 312 glutPostRedisplay(); 313} 314 315int 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