9fans - fans of the OS Plan 9 from Bell Labs
 help / color / mirror / Atom feed
From: Sam <sah@softcardsystems.com>
To: <9fans@cse.psu.edu>
Subject: [9fans] Galaxy screensaver updated
Date: Sun, 23 Jun 2002 18:44:25 -0400	[thread overview]
Message-ID: <Pine.LNX.4.30.0206231839530.16321-200000@athena> (raw)

[-- Attachment #1: Type: TEXT/PLAIN, Size: 446 bytes --]

Attached is the new and improved galaxy screensaver.  I've put
suggestions as to what to do next, if anyone wants to pick
up the ball.  I've wasted enough time on this. ;)

The middle mouse button picks different colors, as well
as some options.  See the end of the list.  My favourite
is definitely 'Random.'

If you want to see some really neat effects, see line 351.

Thanks Andrey, I had a super blast with this!

Cheers,

Sam

[-- Attachment #2: Type: TEXT/PLAIN, Size: 10260 bytes --]

/* Touched by:
  *  sah@coraid.com, 06/02
  *
  * To do:
  * Decrease the mass of the galaxy as the stars leave.
  * Add fullscreen option on right button menu.
  * Give stars tiny mass and make them react to each other.
  * Give stars size based on their mass.
  */
#include <u.h>
#include <libc.h>
#include <draw.h>
#include <event.h>

#define MIN_GALS			2
#define MAX_GALS			4
#define MAX_STARS			500
#define MAX_IDELTAT		50
#define MIN_GALSZ			1e-1
#define MAX_GALSZ			1.5e-1
#define COLORBASE			16

#define EPSILON 			1e-8
#define SQRT_EPSILON 		1e-4
#define DELTAT 			(MAX_IDELTAT * SQRT_EPSILON)
#define QCONS				1e-3
#define EPS				1/(EPSILON * SQRT_EPSILON * DELTAT * DELTAT * QCONS);
#define M_PI				3.141592653589793238462643383 

typedef struct Star Star;
struct Star {
	double pos[3], vel[3];
};

typedef struct Galaxy Galaxy;
struct Galaxy {
	int mass, nstars, galcol, swappoints, col;
	double pos[3], vel[3], opos[3], ovel[3];
	Star stars[MAX_STARS];
	Point oldpoints[MAX_STARS], newpoints[MAX_STARS];
};

typedef struct Uni Uni;
struct Uni {
	int midx, midy, ngals, f_hititerations, step;
	double mat[3][3], scale, diff[3], rot_x, rot_y;
	Galaxy gals[MAX_GALS];
};

enum {	WHITE, PALEGREYGREEN, PALEGREYBLUE, GREYGREEN, GREYBLUE, 
		RED, GREEN, BLUE, CYAN, MAGENTA, YELLOW, PALEYELLOW, DARKYELLOW, 
		DARKGREEN, PALEGREEN, MEDGREEN, DARKBLUE, PALEBLUEGREEN, PALEBLUE,
		BLUEGREEN, YELLOWGREEN, MEDBLUE, PURPLEBLUE, RANDY, 
		TWINKLE, SPARKLE, FWORKS, NCOLORS,
};

int colors[NCOLORS] = {
[WHITE] 			DWhite,
[RED]			DRed,
[GREEN]			DGreen,
[BLUE]			DBlue,
[CYAN]			DCyan,
[MAGENTA]		DMagenta,
[YELLOW]			DYellow,
[PALEYELLOW]		DPaleyellow,
[DARKYELLOW]		DDarkyellow,
[DARKGREEN]		DDarkgreen,
[PALEGREEN]		DPalegreen,
[MEDGREEN]		DMedgreen,
[DARKBLUE]		DDarkblue,
[PALEBLUEGREEN]	DPalebluegreen,
[PALEBLUE]		DPaleblue,
[BLUEGREEN]		DBluegreen,
[GREYGREEN]		DGreygreen,
[PALEGREYGREEN]	DPalegreygreen,
[YELLOWGREEN]	DYellowgreen,
[MEDBLUE]		DMedblue,
[GREYBLUE]		DGreyblue,
[PALEGREYBLUE]	DPalegreyblue,
[PURPLEBLUE]		DPurpleblue
};

char *mbtns[] = {
[WHITE] 			"White",
[RED]			"Red",
[GREEN]			"Green",
[BLUE]			"Blue",
[CYAN]			"Cyan",
[MAGENTA]		"Magenta",
[YELLOW]			"Yellow",
[PALEYELLOW]		"Paleyellow",
[DARKYELLOW]		"Darkyellow",
[DARKGREEN]		"Darkgreen",
[PALEGREEN]		"Palegreen",
[MEDGREEN]		"Medgreen",
[DARKBLUE]		"Darkblue",
[PALEBLUEGREEN]	"Palebluegreen",
[PALEBLUE]		"Paleblue",
[BLUEGREEN]		"Bluegreen",
[GREYGREEN]		"Greygreen",
[PALEGREYGREEN]	"Palegreygreen",
[YELLOWGREEN]	"Yellowgreen",
[MEDBLUE]		"Medblue",
[GREYBLUE]		"Greyblue",
[PALEGREYBLUE]	"Palegreyblue",
[PURPLEBLUE]		"PurpleBlue",
[RANDY]			"Random",
[FWORKS]			"Fireworks",
[SPARKLE]			"Sparkle",
[TWINKLE]		"Twinkle",
[NCOLORS]		0
};

char *rbtns[] = { "exit", 0 };

Image *images[NCOLORS];
Uni univ;
uint color;

int
alloc_colors(void)
{
	int i;

	for(i=0; i<NCOLORS; i++)
		images[i] = allocimage(display, Rect(0,0,2,2), display->chan, 0, colors[i]);
	return 1;
}

void
free_colors(void)
{
	int i;

	for(i=0; i<NCOLORS; i++)
		freeimage(images[i]);
}

/* mat? */
void
init_mat(void)
{
	double w1, w2, sinw1, sinw2, cosw1, cosw2;

	w1 = w2 = 2.0 * M_PI * frand();

	sinw1 = sin(w1);
	sinw2 = sin(w2);
	cosw1 = cos(w1);
	cosw2 = cos(w2);

	univ.mat[0][0] = cosw2;
	univ.mat[0][1] = -sinw1 * sinw2;
	univ.mat[0][2] = cosw1 * sinw2;
	univ.mat[1][0] = 0.0;
	univ.mat[1][1] = cosw1;
	univ.mat[1][2] = sinw1;
	univ.mat[2][0] = -sinw2;
	univ.mat[2][1] = -sinw1 * cosw2;
	univ.mat[2][2] = cosw1 * cosw2;
}

void
init_gal(Galaxy *g)
{
	g->vel[0] = g->vel[1] = g->vel[2] = frand() * 2.0 - 1.0;
	g->ovel[0] = g->ovel[1] = g->ovel[2] = g->vel[0];
	g->pos[0] = g->opos[0] = -g->vel[0] * DELTAT * univ.f_hititerations + frand() - 0.5;
	g->pos[1] = g->opos[0] = -g->vel[1] * DELTAT * univ.f_hititerations + frand() - 0.5;
	g->pos[2] = g->opos[0] = -g->vel[2] * DELTAT * univ.f_hititerations + frand() - 0.5;
	g->mass = (int) (frand() * 1000.0) + 1;
	g->nstars = nrand(MAX_STARS / 2) + MAX_STARS / 2;

	if(color == RANDY)
		g->col = rand()%RANDY;
}

void
init_stars(Galaxy *g)
{
	int i;
	double galsz, sinw, cosw, d, h, v;
	Star *st;
	Point *oldp, *newp;

	galsz = MAX_GALSZ*frand() + MIN_GALSZ;
	st = g->stars;
	oldp = g->oldpoints;
	newp = g->newpoints;

	for (i=0; i < g->nstars; i++, st++, oldp++, newp++) {
		d = 2.0 * M_PI * frand();
		sinw = sin(d);
		cosw = cos(d);
		d = frand() * galsz;
		h = frand() * exp(-2.0 * (d / galsz)) / 5.0 * galsz;

		if(frand() < 0.5)
			h = -h;
		st->pos[0] = univ.mat[0][0] * d * cosw + univ.mat[1][0] * d * sinw + univ.mat[2][0] *
				 	h + g->pos[0];
		st->pos[1] = univ.mat[0][1] * d * cosw + univ.mat[1][1] * d * sinw + univ.mat[2][1] *
				 	h + g->pos[1];
		st->pos[2] = univ.mat[0][2] * d * cosw + univ.mat[1][2] * d * sinw + univ.mat[2][2] *
				 	h + g->pos[2];

		v = sqrt(g->mass * QCONS / sqrt(d * d + h * h));
		st->vel[0] = -univ.mat[0][0] * v * sinw + univ.mat[1][0] * v * cosw + g->vel[0];
		st->vel[1] = -univ.mat[0][1] * v * sinw + univ.mat[1][1] * v * cosw + g->vel[1];
		st->vel[2] = -univ.mat[0][2] * v * sinw + univ.mat[1][2] * v * cosw + g->vel[2];

		st->vel[0] *= DELTAT;
		st->vel[1] *= DELTAT;
		st->vel[2] *= DELTAT;
	
		*oldp = Pt(0, 0);
		*newp = Pt(0, 0);;
	}
 }

static void
startover(void)
{
	int i;
	Galaxy *g;

	univ.step = 0;
	univ.rot_y = 0;
	univ.rot_x = 0;
	univ.ngals = MIN_GALS + (frand()*(MAX_GALS-MIN_GALS+1));
	for(i=0, g=univ.gals; i < univ.ngals; i++, g++) {
		init_mat();
		init_gal(g);
		init_stars(g);
	}
	draw(screen, screen->r, display->black, nil, ZP);
}

void
init(void)
{
	srand(time(0));

	if(initdraw(nil, nil, "bez") < 0)
		sysfatal("initdraw failed: %r");
	if(!alloc_colors())
		sysfatal("failed to init colors\n");
	univ.f_hititerations = 100;
	univ.scale = (double) (Dx(screen->r) + Dy(screen->r)) / 8.0;
	univ.midx =  screen->r.min.x + Dx(screen->r)  / 2;
	univ.midy =  screen->r.min.y +Dy(screen->r) / 2;
}

/* calculate star pos,vel relative to the gravity of the other galaxies */
void
calc_star_rel_gal(Galaxy *g, Star *s)
{
	double d, d0, d1, d2, v0, v1, v2;

	v0 = s->vel[0], v1 = s->vel[1], v2 = s->vel[2];
	d0 = g->pos[0] - s->pos[0];
	d1 = g->pos[1] - s->pos[1];
	d2 = g->pos[2] - s->pos[2];
	d = d0 * d0 + d1 * d1 + d2 * d2;

	if (d > EPSILON)
		d = g->mass / (d * sqrt(d)) * DELTAT * DELTAT * QCONS;
	else
		d = g->mass * EPS;
	v0 += d0 * d;
	v1 += d1 * d;
	v2 += d2 * d;
	s->vel[0] = v0, s->vel[1] = v1, s->vel[2] = v2;
	s->pos[0] += v0, s->pos[1] += v1, s->pos[2] += v2;
}

/* calculate galaxy pos/vel relative to other galaxies */
void
calc_gal_rel_gals(Galaxy *thisg)
{
	double d, d0, d1, d2;
	int i;
	Galaxy *g;

	for (i=0, g=univ.gals; i < univ.ngals; i++, g++) {
		if(g == thisg)
			continue;
		d0 = g->opos[0] - thisg->pos[0];
		d1 = g->opos[1] - thisg->pos[1];
		d2 = g->opos[2] - thisg->pos[2];
		d = d0 * d0 + d1 * d1 + d2 * d2;

		if(d > EPSILON)
			d = thisg->mass * thisg->mass / (d * sqrt(d));
		else
			d = thisg->mass * thisg->mass / (EPSILON * SQRT_EPSILON);
		d *= DELTAT * QCONS;
		d0 *= d;
		d1 *= d;
		d2 *= d;
		thisg->vel[0] += d0 / thisg->mass;
		thisg->vel[1] += d1 / thisg->mass;
		thisg->vel[2] += d2 / thisg->mass;
		g->vel[0] -= d0 / g->mass;
		g->vel[1] -= d1 / g->mass;
		g->vel[2] -= d2 / g->mass;
	}
	thisg->pos[0] += thisg->vel[0] * DELTAT;
	thisg->pos[1] += thisg->vel[1] * DELTAT;
	thisg->pos[2] += thisg->vel[2] * DELTAT;
}

void
redraw_stars(Galaxy *g)
{
	uint i;
	Rectangle r;
	Point *oldp, *newp;

	if((g->swappoints ^= 1)) {
		oldp = g->newpoints;
		newp = g->oldpoints;
	} else {
		oldp=g->oldpoints;
		newp=g->newpoints;
	}
	if(color == FWORKS)
		g->col = rand()%RANDY;
	for(i=0; i < g->nstars; i++, oldp++, newp++) {
		if(color == SPARKLE)
			g->col = rand()%RANDY;
		else if(color == TWINKLE)
			g->col = rand()%PALEGREYBLUE;
		r = Rpt(*oldp, addpt(*oldp, Pt(2, 2)));
		draw(screen, r, display->black, nil, ZP);
		r = Rpt(*newp, addpt(*newp, Pt(2, 2)));
		draw(screen, r, images[g->col], nil, ZP);

	}
 }

void
redraw_gal(Galaxy *g)
{
	int i;
	Point *p;
	Star *s;

	s=g->stars;

//	try one of these instead for nifty effects ;)
//	p = g->newpoints;
//	p = g->swappoints ? g->oldpoints : g->newpoints;
	p = g->swappoints ? g->newpoints : g->oldpoints;

	for(i=0; i < g->nstars; i++, s++, p++) {
		calc_star_rel_gal(g, s);
		p->x = (((s->pos[0]) - (s->pos[2])) * univ.scale) + univ.midx;
		p->y = (((s->pos[1]) - (((s->pos[0]) + (s->pos[2])))) * univ.scale) + univ.midy;
	}
	calc_gal_rel_gals(g);
	redraw_stars(g);
}

void
redraw_univ(void)
{
	int i; 
	Galaxy *g;

	univ.rot_y += 0.01;
	univ.rot_x += 0.004;

	for(i=0, g=univ.gals; i < univ.ngals; i++, g++)
		redraw_gal(g);
	for(i=0, g=univ.gals; i < univ.ngals; i++, g++) {
		g->ovel[0] = g->vel[0];
		g->ovel[1] = g->vel[1];
		g->ovel[2] = g->vel[2];
		g->opos[0] = g->pos[0];
		g->opos[1] = g->pos[1];
		g->opos[2] = g->pos[2];
	}
	if(++univ.step > univ.f_hititerations * 4)
		startover();
}

void
eresized(int new)
{
	if(new && getwindow(display, Refnone) < 0)
		sysfatal("can't reattach to window");
	draw(screen, screen->r, display->black, nil, ZP);
}

void
set_galcolor(int col)
{
	int i;
	Galaxy *g;

	if(col < RANDY)
		for(i=0, g=univ.gals; i < univ.ngals; i++, g++)
			g->col = col;
	else if(col == RANDY)
		for(i=0, g=univ.gals; i < univ.ngals; i++, g++)
			g->col = rand()%RANDY;
		
}

Menu rmenu = { rbtns }, mmenu = { mbtns };
Mouse m;

void 
main(void)
{
	vlong tbegin, tend;
	ulong frames=0;
	void init(void);
	int col;

	init();
	einit(Emouse);
	eresized(0);
	tbegin = nsec();

	for(;;) {
		if(ecanmouse()) {
			m = emouse();
			if(m.buttons&4)
			if(!emenuhit(3, &m, &rmenu)) {
				tend = nsec();
				print("fps: %uf\n", frames/((tend - tbegin)/1000000000.0));
				exits(0);
			}
			if(m.buttons&2)
			if((col=emenuhit(2, &m, &mmenu)) >= 0)
				set_galcolor(color=col);
		}
		redraw_univ();
		frames++;
	}
}

             reply	other threads:[~2002-06-23 22:44 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2002-06-23 22:44 Sam [this message]
2002-06-24  6:04 ` Micah Stetson
2002-06-24 13:04 ` andrey mirtchovski
2002-06-24 12:20   ` Sam

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=Pine.LNX.4.30.0206231839530.16321-200000@athena \
    --to=sah@softcardsystems.com \
    --cc=9fans@cse.psu.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).