From mboxrd@z Thu Jan 1 00:00:00 1970 Message-ID: To: 9fans@cse.psu.edu From: andrey mirtchovski MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="upas-kojbavveocoghhvaxhnnsdccem" Subject: [9fans] xscreensaver hacks Date: Fri, 21 Jun 2002 12:43:42 -0600 Topicbox-Message-UUID: b5591978-eaca-11e9-9e20-41e7f4b1d025 This is a multi-part message in MIME format. --upas-kojbavveocoghhvaxhnnsdccem Content-Disposition: inline Content-Type: text/plain; charset="US-ASCII" Content-Transfer-Encoding: 7bit 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 --upas-kojbavveocoghhvaxhnnsdccem Content-Disposition: attachment; filename=galaxy.c Content-Type: text/plain; charset="US-ASCII" Content-Transfer-Encoding: 7bit /* 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 #include #include #include #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 = >->stars[j]; XPoint *oldp = >->oldpoints[j]; XPoint *newp = >->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 = >->stars[j]; XPoint *newp = >->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--