Night Version 2.20

Trevor Paquette paquette at cpsc.ucalgary.ca
Sat Jul 7 02:24:42 AEST 1990


  Here is the newest version of night. Future enhancements should include
a 'landscape', mail checker, command line switches, and if I have time
a 'proper' phase of the moon calculator.

 Watchout for the .signature at the end.

----------------- cut here ------------------------
/*
 Version 2.20

 Original program from: howardl at landis.csd.sgi.com (Howard Look)
   Here's yet another little background program. It looks like the
   sky at sunset. It will only run properly on 24 or more bit plane systems.
 Enjoy.

 night enhancements uunet!alberta!calgary!paquette
 Jun-19-1990: Trevor Paquette
	      - hacked up data structures for 'square stars'
	      - added twinkle feature
    Please email any enhancements to me so I can keep an upto date version

 Jun-25-1990: Reuel Nash
	      - changed timers from timeout/signal handler to 
		queued device TIMER1: you can't do graphics reliably 
	        from inside a signal handler and main, too.
		Change overall timer rate with noise() call.
	      - removed unecessary stuff from trand().
	      - the pixel readback scheme to find out what color
		to "blink" to won't work if there are windows obscuring 
		the background on startup. This is now calculated 
		by the program from background colors and Y1 and Y2.
		See get_sky().
	      - stars don't need to be shaded. Use single packed color
		for each star and background of star.
	      - added "comets". (really more like shooting stars). 

 Jun-26-1990: tristram at sgi.com for:
              - aspect ratio of screen added. Makes stars look 'squarer'
	        (rounder?)
	      - added 'venus'

	      Note to tristram: The 'sunset' color scheme that you added
	        looked to much like a 'rainbow'

 Jul-03-1990: Trevor Paquette
              - Stars are brighter nearer the top of the screen then the bottom
	        (allows for 'sunset dimming of stars')
              - No stars should be in the actual 'sunset' area.
	      - added 'mars'
 
 Compile it with:
 cc -o night night.c -lm -lgl_s -lc_s

*/

#include <stdio.h>
#include <gl.h>
#include <device.h>
#include <sys/time.h>
#include <math.h>

/* a star is actually a "square"
        x,y         
          +----------+ color   = col
          |    ^     | bgcolor = back
          |    |     |
          |<- rad -->|
          |    |     |
          |    V     |
          +--------- +
*/
        
/* DO NOT CHANGE THE ORDER OF THE DECLARATIONS in starstruct, if you want to add
   something, add it at the end of the structure */
typedef struct _dummy {
  float x, y, rad;	/* location and radius of star 	*/
  long color;		/* color of star		*/
  long back;		/* background color behind star	*/
} starstruct;
 
struct {
  float x0,y0,x1,y1;
  int active;
} comet;

starstruct venus, moon, mars;

#define Y1 		0.0
#define Y2 		0.2
#define SMALL_MAX_BLINK	128
#define BIG_MAX_BLINK   5
#define ASPECT ((float) XMAXSCREEN / (float) YMAXSCREEN )
#define MOONSCALE       0.04
#define INMOON(a) sqrt(((moon.x-a.x)*(moon.x-a.x))+((moon.y-a.y)*(moon.y-a.y))) < MOONSCALE

/* num of groups of 256 stars */
int numgroups = 8;
/* num of big stars */
int numbig =  175;
/* pointer to locations of small stars */
starstruct *small_stars = NULL;
/* pointer to locations of big stars */
starstruct *big_stars = NULL;
/* at most SMALL_MAX_BLINK small stars blink at a time */
starstruct *small_blinker[SMALL_MAX_BLINK];
/* at most BIG_MAX_BLINK big_stars blink at a time */
starstruct *big_blinker[BIG_MAX_BLINK];

/* colors now global so get_sky() works */
int orange[] = {255,72,0};
int blueish[] = {0,110,189};
int black[] = {0,0,0};
int red[] = {255,0,0};

float cross[][2] = {
  { 0.0, 3.0 },
  { 0.15, 0.15 },
  { 3.0, 0.0 },
  { 0.15, -0.15 },
  { 0.0, -6.0 },
  { -0.15, -0.15 },
  { -3.0, 0.0 },
  { -0.15, 0.15 },
};

/* this is bogus, should just be a rotation in y */
static float arcparm[][2] = {
  { 1.0002, 88.8542 },
  { 1.0008, 87.7094 },
  { 1.0018, 86.5664 },
  { 1.00319, 85.4261 },
  { 1.00499, 84.2894 },
  { 1.00717, 83.1572 },
  { 1.00975, 82.0304 },
  { 1.01272, 80.9097 },
  { 1.01607, 79.796 },
  { 1.0198, 78.6901 },
  { 1.02391, 77.5926 },
  { 1.0284, 76.5043 },
  { 1.03325, 75.4258 },
};
 
main(argc, argv)
int argc;
char *argv[];
{
 int gid, skyevent(), i;
 short val;
 long dev;
 char *malloc();
 
 for(i = 0; i < SMALL_MAX_BLINK; i++) {
   small_blinker[i] = NULL;
 }
 for(i = 0; i < BIG_MAX_BLINK; i++) {
   big_blinker[i] = NULL;
 }
  
 small_stars = (starstruct *) malloc(numgroups*256*sizeof(starstruct));
 big_stars =  (starstruct *) malloc(numbig*sizeof(starstruct));

#ifdef DEBUG
 foreground();
#else
 imakebackground() ;
#endif
 gid = winopen("") ;
 RGBmode();
 gconfig();
 shademodel(GOURAUD);
	
 ortho2(0.0, ASPECT, 0.0, 1.0) ;

 qdevice(TIMER1);
 noise(TIMER1, 30);
 qenter(REDRAW,gid);

 while (1) {
   dev = qread(&val) ;
   switch(dev) {
   case REDRAW:
	draw_background();
	break;
   case TIMER1:    
	skyevent();
	break;
   }
 }
}


draw_background()
{
 int i,j, skyevent(), col[3];
 static int first = 1;
 float v1[2],v2[2],v3[2],v4[2];
 register int counter;

 v1[0] = v4[0] = 0.0;
 v2[0] = v3[0] = ASPECT;

 v1[1] = v2[1] = 0.0;
 v3[1] = v4[1] = Y1;

 bgnpolygon();
   c3i(red);
   v2f(v1);
   v2f(v2);
   c3i(orange);
   v2f(v3);
   v2f(v4);
 endpolygon();

 v1[1] = v2[1] = Y2;
 bgnpolygon();
   c3i(orange);
   v2f(v4);
   v2f(v3);
   c3i(blueish);
   v2f(v2);
   v2f(v1);
 endpolygon();

 v3[1] = v4[1] = 1.0;
   bgnpolygon();
   c3i(blueish);
   v2f(v1);
   v2f(v2);
   c3i(black);
   v2f(v3);
   v2f(v4);
 endpolygon();

 if(first) {
   setup_sky();
   first = 0;
 }

 counter = 0;
 for(j=0; j<numgroups; j++) {
   bgnpoint();
   for(i=0; i<256; i++) {
     cpack(small_stars[counter].color);
     v2f(&small_stars[counter].x);
     counter++;
   }
   endpoint();
 }

 for(j=0; j<numbig; j++) {
   bgnpolygon();
     v1[0] = big_stars[j].x;
     v1[1] = big_stars[j].y;
     v2[0] = big_stars[j].x;
     v2[1] = big_stars[j].y - big_stars[j].rad;
     v3[0] = big_stars[j].x + big_stars[j].rad;
     v3[1] = big_stars[j].y - big_stars[j].rad;
     v4[0] = big_stars[j].x + big_stars[j].rad;
     v4[1] = big_stars[j].y;
     cpack(big_stars[j].color);
     v2f(v1);
     v2f(v2);
     v2f(v3);
     v2f(v4);
   endpolygon();
 }

}

/* ----------------------------------------------------------------------
 *  Random number generator
 *  Author: Trevor Paquette
 *  Modified 6/25: Reuel Nash
 *  Purpose: returns a random number between x and y
 *           (positive only)
 */

long
trand(x,y)
int x,y;
{
 long ret;
 static int seeded = 0;

 if(!seeded) {
   srand((int)time(0));
   seeded = 1;
 }

 ret = x + rand() % (y-x+1);
 return(ret);
}
						       

skyevent()
{
 /* anything like comets .. astral events etc,, should be added here */
 long event, trand(), tmp;
 register int starnum, i, counter;
 static small_numstars = 0, big_numstars = 0;
 char *malloc();
 int col[3];
 float v1[2], v2[2], v3[2], v4[2], t;

 event = trand(1, 100); 	/* an event is based on percentage chance of happening */
				/* star twinkle = all of the time */
				/* comet = 2% ?? */
				/* percentages should total 100 */

 /* turn on the stars that we turned off last time we were here */
 if(small_numstars) {
   for(i = 0; i < small_numstars; i++) {
     bgnpoint();
       cpack(small_blinker[i]->color);
       v2f(&small_blinker[i]->x);
     endpoint();
   }
 }
 if(big_numstars) {
   for(i = 0; i < big_numstars; i++) {
     bgnpolygon();
       v1[0] = big_blinker[i]->x;
       v1[1] = big_blinker[i]->y;
       v2[0] = big_blinker[i]->x;
       v2[1] = big_blinker[i]->y - big_blinker[i]->rad;
       v3[0] = big_blinker[i]->x + big_blinker[i]->rad;
       v3[1] = big_blinker[i]->y - big_blinker[i]->rad;
       v4[0] = big_blinker[i]->x + big_blinker[i]->rad;
       v4[1] = big_blinker[i]->y;
       cpack(big_blinker[i]->color);
       v2f(v1);
       v2f(v2);
       v2f(v3);
       v2f(v4);
     endpolygon();
   }
 }

 if(comet.active) {
   bgnline();
   cpack(get_sky(comet.y0));
   v2f(&comet.x0);
   cpack(get_sky(comet.y1));
   v2f(&comet.x1);
   endline();
   comet.active = 0;
 }

 small_numstars = trand(1, SMALL_MAX_BLINK); /* blink between 1 and 256 stars */
 for(i = 0; i < small_numstars; i++) {
   starnum = trand(0, numgroups*256);
   small_blinker[i] = &small_stars[starnum];
   bgnpoint();
     cpack(small_stars[starnum].back);
     v2f(&small_stars[starnum].x);
   endpoint();
 }
 big_numstars = trand(1, BIG_MAX_BLINK); /* blink between 1 and 256 stars */
 for(i = 0; i < big_numstars; i++) {
   starnum = trand(0, numbig);
   big_blinker[i] = &big_stars[starnum];
   bgnpolygon();
     v1[0] = big_blinker[i]->x;
     v1[1] = big_blinker[i]->y;
     v2[0] = big_blinker[i]->x;
     v2[1] = big_blinker[i]->y - big_blinker[i]->rad;
     v3[0] = big_blinker[i]->x + big_blinker[i]->rad;
     v3[1] = big_blinker[i]->y - big_blinker[i]->rad;
     v4[0] = big_blinker[i]->x + big_blinker[i]->rad;
     v4[1] = big_blinker[i]->y;
     cpack(big_blinker[i]->back);
     v2f(v1);
     v2f(v2);
     v2f(v3);
     v2f(v4);
   endpolygon();
 }

 if((event >= 1) && (event <= 10)) { /* shooting star event */
   comet.x0 = ((float)trand(0,32767))/32767.0;
   do {
     comet.y0 = ((float)trand(0,32767))/32767.0;
   }
   while(comet.y0  < Y2);
   comet.x1 = comet.x0 + ((float)trand(0,32767))/327670.0;
   comet.y1 = comet.y0 + ((float)trand(0,32767))/327670.0;
   bgnline();
   /* use height of head of comet as basis for color. */
   t = comet.y0 - Y2; /* number between 0.0 and 1.0-Y2 */
   t /= (1.0-Y2);                   /* number between 0.0 and 1.0    */
   tmp = 127 + (long)(t*128.0);     /* color from 128 - 255 based on height */
   tmp += (trand(0,40) - 20);       /* fudge the color a bit */
   tmp |= tmp << 8 | tmp << 16;
   cpack(tmp);
   v2f(&comet.x0);
   cpack(get_sky(comet.y1));
   v2f(&comet.x1);
   endline();
   comet.active = 1;
 }

 if((event >= 2) && (event <= 10)) { /* satilite event (see above)*/
 }


/* mars */
  bgnpolygon();
    v1[0] = mars.x;
    v1[1] = mars.y;
    v2[0] = mars.x;
    v2[1] = mars.y - mars.rad;
    v3[0] = mars.x + mars.rad;
    v3[1] = mars.y - mars.rad;
    v4[0] = mars.x + mars.rad;
    v4[1] = mars.y;
    cpack(mars.color);
    v2f(v1);
    v2f(v2);
    v2f(v3);
    v2f(v4);
   endpolygon();

/* venus */
  cpack(venus.color);
  pushmatrix();
  translate(venus.x, venus.y, 0.0);
  scale(0.004, 0.004, 0.0);
  bgnpolygon();
  for(i = 0; i < 8; i++)
    v2f(&cross[i][0]);
  endpolygon();
  popmatrix();

/* moon */
  pushmatrix();
  pushattributes();
  linewidth(3);
  translate(moon.x, moon.y, 0.0);
  scale(MOONSCALE, MOONSCALE, 0.0);
  rotate(-600, 'z');
  cpack(moon.color);
  for(i = 0; i < 13; i++ ) {
    arc(0.0, 0.0, arcparm[i][0], (int)(-10.0 * arcparm[i][1]),
                                 (int)(10.0 * arcparm[i][1]));
    translate(-0.02, 0.0, 0.0);
  }
  popattributes();
  popmatrix();
}

setup_sky()
{
 register int i, j;
 register int counter;
 long tmp, trand(), get_sky();
 float t;

 comet.active = 0;
 /* moon */
 do {
   moon.x = ASPECT * ((float)trand(0, 32767))/32767.0;
   moon.y = ((float)trand(0,32767))/32767.0;
 }
 while(moon.y < 0.75); /* make sure moon is high in the sky */
 moon.color = 0x00DDDDDD;

 /* setup big stars , should be done BEFORE small stars */
 for(j =0; j<numbig; j++) {
   /* no stars should be visible in the 'sunset' area */
   do {
     big_stars[j].x = ASPECT * (((float)trand(0,32767))/32767.0);
     big_stars[j].y = ((float)trand(0,32767))/32767.0;
   }
   while((big_stars[j].y < Y2) || INMOON(big_stars[j]));
   big_stars[j].rad = 2.00 * (((float)trand(0,32767))/32767.0/500.0);
   big_stars[j].back = get_sky(big_stars[j].y);
   /* star color depends on height to the top of the screen plus some random
    * number between -20 and 20. stars nearer the top of the screen should on
    * average be brighter the those nearer the bottom
    */
   /* use height of star as basis for color. */
   t = big_stars[j].y - Y2;    /* number between 0.0 and 1.0-Y2 */
   t /= (1.0-Y2);              /* number between 0.0 and 1.0    */
   tmp = 127 + (long)(t*128.0);/* color from 128 - 255 based on height */
   tmp += (trand(0,40) - 20);  /* fudge the color a bit */
   tmp |= tmp << 8 | tmp << 16;
   big_stars[j].color =  tmp;
 }

 /* set up small stars. */
 counter = 0;
 for(j=0; j<numgroups; j++) {
   for(i=0; i<256; i++) {
     do {
       small_stars[counter].x = ASPECT * (((float)trand(0,32767))/32767.0);
       small_stars[counter].y = ((float)trand(0,32767))/32767.0;
     }
     while((small_stars[counter].y < Y2) || INMOON(small_stars[counter]));
     small_stars[counter].rad = 0.0;
     small_stars[counter].back = get_sky( small_stars[counter].y);
     /* use height of star as basis for color. */
     t = small_stars[counter].y - Y2; /* number between 0.0 and 1.0-Y2 */
     t /= (1.0-Y2);                   /* number between 0.0 and 1.0    */
     tmp = 127 + (long)(t*128.0);     /* color from 128 - 255 based on height */
     tmp += (trand(0,40) - 20);       /* fudge the color a bit */
     tmp |= tmp << 8 | tmp << 16;
     small_stars[counter].color = tmp;
     counter++;
   }
 }

 /* venus */
 do {
   venus.x = ASPECT * ((float)trand(0, 32767))/32767.0;
   venus.y = ((float)trand(0,32767))/32767.0;
 }
 while(venus.y < Y2*3 || INMOON(venus));
 venus.color = 0x00FFFFFF;

 /* mars */
 do {
   mars.x = ASPECT * ((float)trand(0, 32767))/32767.0;
   mars.y = ((float)trand(0,32767))/32767.0;
 }
 while(mars.y < Y2*3 || INMOON(mars));
 mars.rad = 2.00 * (((float)trand(0,32767))/32767.0/500.0);
 mars.color = 0x000F0FFF;

}

long
get_sky(y)
float y;
{
    int r,g,b;

    if(y < Y1) {
	y /= Y1;
	r = red[0] * (1.-y) + orange[0] * y;
	g = red[1] * (1.-y) + orange[1] * y;
	b = red[2] * (1.-y) + orange[2] * y;
    } else if( y < Y2) {
	y = (y - Y1)/(Y2 - Y1);
	r = orange[0] * (1.-y) + blueish[0] * y;
	g = orange[1] * (1.-y) + blueish[1] * y;
	b = orange[2] * (1.-y) + blueish[2] * y;
    } else {
	y = (y - Y2)/(1 - Y2);
	r = blueish[0] * (1.-y) + black[0] * y;
	g = blueish[1] * (1.-y) + black[1] * y;
	b = blueish[2] * (1.-y) + black[2] * y;
    }

    return (r&0xff) + ((g&0xff)<<8) + ((b&0xff)<<16);
}
___________________________________________/No man is a failure who has friends
Trevor Paquette  ICBM:51'03"N/114'05"W|I accept the challange, body and soul,
{ubc-cs,utai,alberta}!calgary!paquette|to seek the knowledge of the ones of old
paquette at cpsc.ucalgary.ca             | - engraved on the Kersa Blade of Esalon



More information about the Comp.sys.sgi mailing list