9fans - fans of the OS Plan 9 from Bell Labs
 help / color / mirror / Atom feed
* [9fans] Galaxy screensaver updated
@ 2002-06-23 22:44 Sam
  2002-06-24  6:04 ` Micah Stetson
  2002-06-24 13:04 ` andrey mirtchovski
  0 siblings, 2 replies; 4+ messages in thread
From: Sam @ 2002-06-23 22:44 UTC (permalink / raw)
  To: 9fans

[-- 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++;
	}
}

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2002-06-24 13:04 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-06-23 22:44 [9fans] Galaxy screensaver updated Sam
2002-06-24  6:04 ` Micah Stetson
2002-06-24 13:04 ` andrey mirtchovski
2002-06-24 12:20   ` Sam

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).