9fans - fans of the OS Plan 9 from Bell Labs
 help / color / mirror / Atom feed
From: andrey mirtchovski <andrey@lanl.gov>
To: 9fans@cse.psu.edu
Subject: [9fans] xscreensaver hacks
Date: Fri, 21 Jun 2002 12:43:42 -0600	[thread overview]
Message-ID: <f3cac23edf30973a52237b5e31229d82@acl.lanl.gov> (raw)

[-- Attachment #1: Type: text/plain, Size: 1949 bytes --]

this morning I found out that there's not much for me to do today, so
I decided to take a look at the XScreenSaver hacks (the X11 stuff, not
the OpenGL ones) to see if it'd be easy to port them to Plan9...

I was familiar with galaxy.c from an old project I did at usask.ca, so
that was my first choice..

I found out that it's amazingly easy to port (this one specifically)
since there's not much to it -- it calculates pixels and draws them on
the screen.  nothing complex...

so, here it is -- compile and run in a window to see how fast it'll go...

what's missing:
	colors, number of stars was reduced to 1000 (from 3000) to
	display faster, the whole galaxy thingie was rotating around
	the viewpoint.  it was puke-inducing so i removed it

	license -- some parts of xscreensaver think they're under the
	GPL (like the autoconf scripts and some hacks), others do
	not...  no autoconf was used, so no GPL :)

what's added:
	menu (right mouse button exits)
	increased pixel size by 1, it seems to look better on my
	screen
	fps calculation -- the fps will be given upon exit, note that
	it's cpu-bound, rather than graphics-bound

originally galaxy.c kept track of old pixels and filled them in with
black, then drawing the new ones.  this seems to be slower for plan9,
since P9 doesn't have something resembling XDrawPixels() with which to
draw an array of Points (i.e.  each pixel is currently a call to
draw() with a 2x2 rectangle argument).  in this case it's better to
redraw the screen with black at the beginning of each iteration and
then just fill in the white spots one by one...

I'll do more when I have some more time (likely soon :) -- there's
plenty where this one came from :)

andrey

ps: some data, if anyone's interested:
	(all done in a brand new window started with the 'window'
	command)

	GeForce3 video card, athlon 800mhz, 32bpp, gives 20+fps with 3
	galaxies, 26+ with 2

[-- Attachment #2: galaxy.c --]
[-- Type: text/plain, Size: 10613 bytes --]

/* standard defines -- it's better to have them here than
  * having to s/X/Y/g the whole thing over and over again...
  * andrey
  */
#include <u.h>
#include <libc.h>
#include <draw.h>
#include <event.h>

#define NULL nil
#define XPoint Point
#define SINF sin
#define COSF cos
#define NRAND nrand
#define LRAND lrand
#define MAXRAND ((2<<31)-1)
#define FLOATRAND frand()
#define M_PI 3.141592653589793238462643383 /* should be enough, no? */
/* end of plan9-related defines */


#define MINSIZE       1
#define MINGALAXIES    2
#define MAX_STARS    1000
#define MAX_IDELTAT    50
/* These come originally from the Cluster-version */
#define DEFAULT_GALAXIES  3
#define DEFAULT_STARS    1000
#define DEFAULT_HITITERATIONS  7500
#define DEFAULT_IDELTAT    200 /* 0.02 */
#define EPSILON 0.00000001

#define sqrt_EPSILON 0.0001

#define DELTAT (MAX_IDELTAT * 0.0001)

#define GALAXYRANGESIZE  0.1
#define GALAXYMINSIZE  0.15
#define QCONS    0.001


#define COLORBASE  16
  /* Colors for stars start here */
#define COLORSTEP  (NUMCOLORS/COLORBASE)
/* NUMCOLORS / COLORBASE colors per galaxy */


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


typedef struct {
 int         mass;
 int         nstars;
 Star       *stars;
 XPoint     *oldpoints;
 XPoint     *newpoints;
 double      pos[3], vel[3];
 int         galcol;
} Galaxy;

typedef struct {
 double      mat[3][3]; /* Movement of stars(?) */
 double      scale; /* Scale */
 int         midx; /* Middle of screen, x */
 int         midy; /* Middle of screen, y */
 double      size; /* */
 double      diff[3]; /* */
 Galaxy     *galaxies; /* the Whole Universe */
 int         ngalaxies; /* # galaxies */
 int         f_hititerations; /* # iterations before restart */
 int         step; /* */
 double      rot_y; /* rotation of eye around center of universe, around
y-axis*/
 double      rot_x; /* rotation of eye around center of universe, around
x-axis */
} unistruct;

static unistruct *universes = NULL;

static void
free_galaxies(unistruct * gp)
{
 if (gp->galaxies != NULL) {
  int         i;

  for (i = 0; i < gp->ngalaxies; i++) {
   Galaxy     *gt = &gp->galaxies[i];

   if (gt->stars != NULL)
    (void) free((void *) gt->stars);
   if (gt->oldpoints != NULL)
       (void) free((void *) gt->oldpoints);
   if (gt->newpoints != NULL)
       (void) free((void *) gt->newpoints);
  }
  (void) free((void *) gp->galaxies);
  gp->galaxies = NULL;
 }
}

static void
startover(void)
{
 unistruct  *gp = &universes[0];
 int         i, j; /* more tmp */
 double      w1, w2; /* more tmp */
 double      d, v, w, h; /* yet more tmp */

 gp->step = 0;
 gp->rot_y = 0;
 gp->rot_x = 0;

  gp->ngalaxies = MINGALAXIES + (int)(FLOATRAND+0.5);
 if (gp->galaxies == NULL)
  gp->galaxies = (Galaxy *) calloc(gp->ngalaxies, sizeof (Galaxy));

 for (i = 0; i < gp->ngalaxies; ++i) {
  Galaxy     *gt = &gp->galaxies[i];
  double      sinw1, sinw2, cosw1, cosw2;

  gt->galcol = NRAND(COLORBASE - 2);
  if (gt->galcol > 1)
   gt->galcol += 2; /* Mult 8; 16..31 no green stars */
  /* Galaxies still may have some green stars but are not all green. */

 if (gt->stars != NULL) {
   (void) free((void *) gt->stars);
   gt->stars = NULL;
  }
  gt->nstars = (NRAND(MAX_STARS / 2)) + MAX_STARS / 2;
  gt->stars = (Star *) malloc(gt->nstars * sizeof (Star));
  gt->oldpoints = (XPoint *) malloc(gt->nstars * sizeof (XPoint));
  gt->newpoints = (XPoint *) malloc(gt->nstars * sizeof (XPoint));

  w1 = 2.0 * M_PI * FLOATRAND;
  w2 = 2.0 * M_PI * FLOATRAND;
  sinw1 = SINF(w1);
  sinw2 = SINF(w2);
  cosw1 = COSF(w1);
  cosw2 = COSF(w2);

  gp->mat[0][0] = cosw2;
  gp->mat[0][1] = -sinw1 * sinw2;
  gp->mat[0][2] = cosw1 * sinw2;
  gp->mat[1][0] = 0.0;
  gp->mat[1][1] = cosw1;
  gp->mat[1][2] = sinw1;
  gp->mat[2][0] = -sinw2;
  gp->mat[2][1] = -sinw1 * cosw2;
  gp->mat[2][2] = cosw1 * cosw2;

  gt->vel[0] = FLOATRAND * 2.0 - 1.0;
  gt->vel[1] = FLOATRAND * 2.0 - 1.0;
  gt->vel[2] = FLOATRAND * 2.0 - 1.0;
  gt->pos[0] = -gt->vel[0] * DELTAT * gp->f_hititerations + FLOATRAND -
0.5;
  gt->pos[1] = -gt->vel[1] * DELTAT * gp->f_hititerations + FLOATRAND -
0.5;
  gt->pos[2] = -gt->vel[2] * DELTAT * gp->f_hititerations + FLOATRAND -
0.5;

 gt->mass = (int) (FLOATRAND * 1000.0) + 1;

  gp->size = GALAXYRANGESIZE * FLOATRAND;
 gp->size  +=  GALAXYMINSIZE;
 for (j = 0; j < gt->nstars; ++j) {
   Star       *st = &gt->stars[j];
   XPoint     *oldp = &gt->oldpoints[j];
   XPoint     *newp = &gt->newpoints[j];

   double      sinw, cosw;

   w = 2.0 * M_PI * FLOATRAND;
   sinw = SINF(w);
   cosw = COSF(w);
   d = FLOATRAND * gp->size;
   h = FLOATRAND * exp(-2.0 * (d / gp->size)) / 5.0 * gp->size;
   if (FLOATRAND < 0.5)
    h = -h;
   st->pos[0] = gp->mat[0][0] * d * cosw + gp->mat[1][0] * d * sinw +
gp->mat[2][0] * h + gt->pos[0];
   st->pos[1] = gp->mat[0][1] * d * cosw + gp->mat[1][1] * d * sinw +
gp->mat[2][1] * h + gt->pos[1];
   st->pos[2] = gp->mat[0][2] * d * cosw + gp->mat[1][2] * d * sinw +
gp->mat[2][2] * h + gt->pos[2];

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

   st->vel[0] *= DELTAT;
   st->vel[1] *= DELTAT;
   st->vel[2] *= DELTAT;

   oldp->x = 0;
   oldp->y = 0;
   newp->x = 0;
   newp->y = 0;
  }

 }

 draw(screen, screen->r, display->black, nil, ZP);

}

void
init_galaxy(void)
{
 unistruct  *gp;

 if (universes == NULL) {
  if ((universes = (unistruct *) calloc(1, sizeof (unistruct))) == NULL)
   return;
 }
 gp = &universes[0];

 gp->f_hititerations = 100;

 gp->scale = (double) (Dx(screen->r) + Dy(screen->r)) / 8.0;
 gp->midx =  screen->r.min.x + Dx(screen->r)  / 2;
 gp->midy =  screen->r.min.y +Dy(screen->r) / 2;
startover();
}

void
draw_galaxy(void)
{
 unistruct  *gp = &universes[0];
 double      d, eps, cox, six, cor, sir;  /* tmp */
 int         i, j, k; /* more tmp */
 int 	     i2;
    XPoint    *dummy = NULL;

//draw(screen, screen->r, display->black, nil, ZP);

gp->rot_y += 0.01;
 gp->rot_x += 0.004;

 cox = COSF(gp->rot_y);
 six = SINF(gp->rot_y);
    cor = COSF(gp->rot_x);
    sir = SINF(gp->rot_x);


    eps = 1/(EPSILON * sqrt_EPSILON * DELTAT * DELTAT * QCONS);

 for (i = 0; i < gp->ngalaxies; ++i) {
  Galaxy     *gt = &gp->galaxies[i];

  for (j = 0; j < gp->galaxies[i].nstars; ++j) {
   Star       *st = &gt->stars[j];
   XPoint     *newp = &gt->newpoints[j];
   double      v0 = st->vel[0];
   double      v1 = st->vel[1];
   double      v2 = st->vel[2];

   for (k = 0; k < gp->ngalaxies; ++k) {
    Galaxy     *gtk = &gp->galaxies[k];
    double      d0 = gtk->pos[0] - st->pos[0];
    double      d1 = gtk->pos[1] - st->pos[1];
    double      d2 = gtk->pos[2] - st->pos[2];

    d = d0 * d0 + d1 * d1 + d2 * d2;
    if (d > EPSILON)
     d = gt->mass / (d * sqrt(d)) * DELTAT * DELTAT * QCONS;
    else
        d = gt->mass * eps;
    v0 += d0 * d;
    v1 += d1 * d;
    v2 += d2 * d;
   }

   st->vel[0] = v0;
   st->vel[1] = v1;
   st->vel[2] = v2;

   st->pos[0] += v0;
   st->pos[1] += v1;
   st->pos[2] += v2;

   newp->x = (short) (((st->pos[0]) - (st->pos[2])) * gp->scale) + gp->midx;
   newp->y = (short) (((st->pos[1]) - (((st->pos[0]) + (st->pos[2])))) * gp->scale) + gp->midy;
//   newp->x = (short) (((cox * st->pos[0]) - (six * st->pos[2])) * gp->scale) + gp->midx;
//   newp->y = (short) (((cor * st->pos[1]) - (sir * ((six * st->pos[0]) + (cox * st->pos[2])))) * gp->scale) + gp->midy;

  }

  for (k = i + 1; k < gp->ngalaxies; ++k) {
   Galaxy     *gtk = &gp->galaxies[k];
   double      d0 = gtk->pos[0] - gt->pos[0];
   double      d1 = gtk->pos[1] - gt->pos[1];
   double      d2 = gtk->pos[2] - gt->pos[2];

   d = d0 * d0 + d1 * d1 + d2 * d2;
   if (d > EPSILON)
    d = gt->mass * gt->mass / (d * sqrt(d)) * DELTAT * QCONS;
   else
    d = gt->mass * gt->mass / (EPSILON * sqrt_EPSILON) * DELTAT * QCONS;

   d0 *= d;
   d1 *= d;
   d2 *= d;
   gt->vel[0] += d0 / gt->mass;
   gt->vel[1] += d1 / gt->mass;
   gt->vel[2] += d2 / gt->mass;
   gtk->vel[0] -= d0 / gtk->mass;
   gtk->vel[1] -= d1 / gtk->mass;
   gtk->vel[2] -= d2 / gtk->mass;
  }

  gt->pos[0] += gt->vel[0] * DELTAT;
  gt->pos[1] += gt->vel[1] * DELTAT;
  gt->pos[2] += gt->vel[2] * DELTAT;


/* original drawing routines */
//         	XSetForeground(display, gc, MI_WIN_BLACK_PIXEL(mi));
//   		XDrawPoints(display, window, gc, gt->oldpoints, gt->nstars, CoordModeOrigin);
// 		XSetForeground(display, gc, MI_PIXEL(mi, COLORSTEP * gt->galcol));
//        	XDrawPoints(display, window, gc, gt->newpoints, gt->nstars,CoordModeOrigin);

		for(i2 = 0; i2 < gt->nstars; i2++) {
			Rectangle r;
			Point p = Pt(1, 1);

			p = gt->oldpoints[i2];
			r = Rpt(p, addpt(p, Pt(2, 2)));
			draw(screen, r, display->black, nil, ZP);

			p = gt->newpoints[i2];
			r = Rpt(p, addpt(p, Pt(2, 2)));
			draw(screen, r, display->white, nil, ZP);

		}
	dummy = gt->oldpoints;
	gt->oldpoints = gt->newpoints;
	gt->newpoints = dummy;
 }

 gp->step++;
 if (gp->step > gp->f_hititerations * 4)
  startover();
}

void
release_galaxy(void)
{
 if (universes != NULL) {

   free_galaxies(&universes[0]);
  (void) free((void *) universes);
  universes = NULL;
 }
}

void
refresh_galaxy(void)
{
 /* Do nothing, it will refresh by itself */
}

void
eresized(int new)
{

	if(new && getwindow(display, Refnone) < 0) {
		sysfatal("can't reattach to window");
	}

	draw(screen, screen->r, display->black, nil, ZP);

	if(universes != nil)
		release_galaxy();
	init_galaxy();
}

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

Menu menu =
{
	buttons
};

void
main(int argc, char **argv)
{
	Mouse m;
	vlong tbegin, tend;
	ulong frames;

	srand(time(0));

	if(initdraw(nil, nil, "bez") < 0)
		sysfatal("initdraw failed: %r");

	einit(Emouse);

	eresized(0);
	tbegin = nsec();
	for(;;) {
		if(ecanmouse()) {
			m = emouse();
			if(m.buttons&4)
				if(emenuhit(3, &m, &menu) == 0) {
					tend = nsec();
					print("fps: %uf\n", frames/((tend - tbegin)/1000000000.0));
					exits(0);
				}
		}
		draw_galaxy();
		frames++;
	}
}--upas-kojbavveocoghhvaxhnnsdccem--

             reply	other threads:[~2002-06-21 18:43 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <andrey@lanl.gov>
2002-06-21 18:43 ` andrey mirtchovski [this message]
2002-06-21 18:55   ` Scott Schwartz
2002-06-22 20:39   ` Sam
2002-06-21 19:20 Andrey S. Kukhar
2002-06-21 19:53 Andrey S. Kukhar
2002-06-21 20:20 andrey mirtchovski
2002-06-21 19:33 ` Sam
2002-06-21 20:21 Andrey S. Kukhar
2002-06-21 21:17 andrey mirtchovski

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=f3cac23edf30973a52237b5e31229d82@acl.lanl.gov \
    --to=andrey@lanl.gov \
    --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).