static void draw_mesh(ModeInfo * mi, trianglestruct * tp, int d, int count) { XPoint p[3]; int first = 1; int y_0, y_1, y_2; double dinv = 0.2 / d; if ((tp->j == 0) && (tp->i == 0)) { #if 0 /* jwz */ XClearWindow(MI_DISPLAY(mi), MI_WINDOW(mi)); #else { int x = 0; int y = 0; int x2 = MI_WIN_WIDTH(mi); int y2 = tp->ypos[0]; XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_WIN_BLACK_PIXEL(mi)); XFillRectangle(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), x, y, x2, y2); } #endif } for (; (tp->j < tp->size) && (count > 0); tp->j += ((count) ? d : 0)) { for (tp->i = (first) ? tp->i : 0, first = 0; (tp->i < MAX_SIZE - tp->j) && (count > 0); tp->i += d, count--) { if (tp->i + tp->j < tp->size) { calc_points1(tp, d, &y_0, &y_1, &y_2, p); draw_atriangle(mi, p, y_0, y_1, y_2, dinv); } if (tp->i + tp->j + d < tp->size) { calc_points2(tp, d, &y_0, &y_1, &y_2, p); draw_atriangle(mi, p, y_0, y_1, y_2, dinv); } } } if (tp->j == tp->size) { tp->init_now = 1; } }
static void draw_atriangle(ModeInfo * mi, XPoint * p, int y_0, int y_1, int y_2, double dinv) { Display *display = MI_DISPLAY(mi); Window window = MI_WINDOW(mi); GC gc = MI_GC(mi); if (MI_NCOLORS(mi) > 2) { /* color */ int dmax, dmin; long color; dmin = MIN(y_0, y_1); dmin = MIN(dmin, y_2); dmax = MAX(y_0, y_1); dmax = MAX(dmax, y_2); if (dmax == 0) { color = BLUE; } else { color = MI_NCOLORS(mi) - (int) ((double) MI_NCOLORS(mi) / M_PI_2 * atan(dinv * (dmax - dmin))); } XSetForeground(display, gc, mi->colors[color % MI_NCOLORS(mi)].pixel); XFillPolygon(display, window, gc, p, 3, Convex, CoordModeOrigin); } else { /* mono */ #ifdef BACKFACE_REMOVAL XSetForeground(display, gc, MI_WIN_BLACK_PIXEL(mi)); XFillPolygon(display, window, gc, p, 3, Convex, CoordModeOrigin); #endif XSetForeground(display, gc, MI_WIN_WHITE_PIXEL(mi)); XDrawLine(display, window, gc, p[0].x, p[0].y, p[1].x, p[1].y); XDrawLine(display, window, gc, p[1].x, p[1].y, p[2].x, p[2].y); XDrawLine(display, window, gc, p[2].x, p[2].y, p[0].x, p[0].y); } }
ENTRYPOINT void draw_bouboule(ModeInfo * mi) /****************/ { Display *display = MI_DISPLAY(mi); Window window = MI_WINDOW(mi); GC gc = MI_GC(mi); StarField *sp = &starfield[MI_SCREEN(mi)]; int i, diff = 0; double CX, CY, CZ, SX, SY, SZ; Star *star; XArc *arc = NULL, *arcleft = NULL; #ifdef HAVE_COCOA /* Don't second-guess Quartz's double-buffering */ XClearWindow(MI_DISPLAY(mi), MI_WINDOW(mi)); #endif #if (ADAPT_ERASE == 1) struct timeval tv1; struct timeval tv2; #endif #if ((USEOLDXARCS == 0) || (ADAPT_ERASE == 1)) short x_1, y_1, x_2, y_2; /* bounding rectangle around the old starfield, * for erasing with the smallest rectangle * instead of filling the whole screen */ int maxdiff = 0; /* maximal distance between left and right */ /* star in 3d mode, otherwise 0 */ #endif #if ((USEOLDXARCS == 0) || (ADAPT_ERASE == 1)) if (MI_WIN_IS_USE3D(mi)) { maxdiff = (int) MAXDIFF; } x_1 = (int) sp->x.value - (int) sp->sizex.value - sp->max_star_size - maxdiff; y_1 = (int) sp->y.value - (int) sp->sizey.value - sp->max_star_size; x_2 = 2 * ((int) sp->sizex.value + sp->max_star_size + maxdiff); y_2 = 2 * ((int) sp->sizey.value + sp->max_star_size); #endif /* We make variables vary. */ sinvary(&sp->thetax); sinvary(&sp->thetay); sinvary(&sp->thetaz); sinvary(&sp->x); sinvary(&sp->y); if (MI_WIN_IS_USE3D(mi)) sinvary(&sp->z); /* A little trick to prevent the bouboule from being * bigger than the screen */ sp->sizex.maximum = MIN(((double) sp->width) - sp->x.value, sp->x.value); sp->sizex.minimum = sp->sizex.maximum / 3.0; /* Another trick to make the ball not too flat */ sp->sizey.minimum = MAX(sp->sizex.value / MAX_SIZEX_SIZEY, sp->sizey.maximum / 3.0); sp->sizey.maximum = MIN(sp->sizex.value * MAX_SIZEX_SIZEY, MIN(((double) sp->height) - sp->y.value, sp->y.value)); sinvary(&sp->sizex); sinvary(&sp->sizey); /* * We calculate the rotation matrix values. We just make the * rotation on the fly, without using a matrix. * Star positions are recorded as unit vectors pointing in various * directions. We just make them all rotate. */ CX = cos(sp->thetax.value); SX = sin(sp->thetax.value); CY = cos(sp->thetay.value); SY = sin(sp->thetay.value); CZ = cos(sp->thetaz.value); SZ = sin(sp->thetaz.value); for (i = 0; i < sp->NbStars; i++) { star = &(sp->star[i]); arc = &(sp->xarc[i]); if (MI_WIN_IS_USE3D(mi)) { arcleft = &(sp->xarcleft[i]); /* to help the eyes, the starfield is always as wide as */ /* deep, so .sizex.value can be used. */ diff = (int) GETZDIFF(sp->sizex.value * ((SY * CX) * star->x + (SX) * star->y + (CX * CY) * star->z) + sp->z.value); } arc->x = (short) ((sp->sizex.value * ((CY * CZ - SX * SY * SZ) * star->x + (-CX * SZ) * star->y + (SY * CZ + SZ * SX * CY) * star->z) + sp->x.value)); arc->y = (short) ((sp->sizey.value * ((CY * SZ + SX * SY * CZ) * star->x + (CX * CZ) * star->y + (SY * SZ - SX * CY * CZ) * star->z) + sp->y.value)); if (MI_WIN_IS_USE3D(mi)) { arcleft->x = (short) ((sp->sizex.value * ((CY * CZ - SX * SY * SZ) * star->x + (-CX * SZ) * star->y + (SY * CZ + SZ * SX * CY) * star->z) + sp->x.value)); arcleft->y = (short) ((sp->sizey.value * ((CY * SZ + SX * SY * CZ) * star->x + (CX * CZ) * star->y + (SY * SZ - SX * CY * CZ) * star->z) + sp->y.value)); arc->x += diff; arcleft->x -= diff; } if (star->size != 0) { arc->x -= star->size; arc->y -= star->size; if (MI_WIN_IS_USE3D(mi)) { arcleft->x -= star->size; arcleft->y -= star->size; } } } /* First, we erase the previous starfield */ if (MI_WIN_IS_INSTALL(mi) && MI_WIN_IS_USE3D(mi)) XSetForeground(display, gc, MI_NONE_COLOR(mi)); else XSetForeground(display, gc, MI_WIN_BLACK_PIXEL(mi)); #if (ADAPT_ERASE == 1) if (sp->hasbeenchecked == 0) { /* We just calculate which method is the faster and eventually free * the oldxarc list */ if (sp->xarc_time > ADAPT_ARC_PREFERED * sp->rect_time) { sp->hasbeenchecked = -2; /* XFillRectangle mode */ (void) free((void *) sp->oldxarc); sp->oldxarc = NULL; if (MI_WIN_IS_USE3D(mi)) { (void) free((void *) sp->oldxarcleft); sp->oldxarcleft = NULL; } } else { sp->hasbeenchecked = -1; /* XFillArcs mode */ } } if (sp->hasbeenchecked == -2) { /* Erasing is done with XFillRectangle */ XFillRectangle(display, window, gc, x_1, y_1, x_2, y_2); } else if (sp->hasbeenchecked == -1) { /* Erasing is done with XFillArcs */ XFillArcs(display, window, gc, sp->oldxarc, sp->NbStars); if (MI_WIN_IS_USE3D(mi)) XFillArcs(display, window, gc, sp->oldxarcleft, sp->NbStars); } else { long usec; if (sp->hasbeenchecked > ADAPT_CHECKS) { #ifdef GETTIMEOFDAY_TWO_ARGS (void) gettimeofday(&tv1, NULL); #else (void) gettimeofday(&tv1); #endif XFillRectangle(display, window, gc, x_1, y_1, x_2, y_2); #ifdef GETTIMEOFDAY_TWO_ARGS (void) gettimeofday(&tv2, NULL); #else (void) gettimeofday(&tv2); #endif usec = (tv2.tv_sec - tv1.tv_sec) * 1000000; if (usec + tv2.tv_usec - tv1.tv_usec > 0) { sp->rect_time += usec + tv2.tv_usec - tv1.tv_usec; sp->hasbeenchecked--; } } else { #ifdef GETTIMEOFDAY_TWO_ARGS (void) gettimeofday(&tv1, NULL); #else (void) gettimeofday(&tv1); #endif XFillArcs(display, window, gc, sp->oldxarc, sp->NbStars); if (MI_WIN_IS_USE3D(mi)) XFillArcs(display, window, gc, sp->oldxarcleft, sp->NbStars); #ifdef GETTIMEOFDAY_TWO_ARGS (void) gettimeofday(&tv2, NULL); #else (void) gettimeofday(&tv2); #endif usec = (tv2.tv_sec - tv1.tv_sec) * 1000000; if (usec + tv2.tv_usec - tv1.tv_usec > 0) { sp->xarc_time += usec + tv2.tv_usec - tv1.tv_usec; sp->hasbeenchecked--; } } } #else #if (USEOLDXARCS == 1) XFillArcs(display, window, gc, sp->oldxarc, sp->NbStars); if (MI_WIN_IS_USE3D(mi)) XFillArcs(display, window, gc, sp->oldxarcleft, sp->NbStars); #else XFillRectangle(display, window, gc, x_1, y_1, x_2, y_2); #endif #endif /* Then we draw the new one */ if (MI_WIN_IS_USE3D(mi)) { if (MI_WIN_IS_INSTALL(mi)) XSetFunction(display, gc, GXor); XSetForeground(display, gc, MI_RIGHT_COLOR(mi)); XFillArcs(display, window, gc, sp->xarc, sp->NbStars); XSetForeground(display, gc, MI_LEFT_COLOR(mi)); XFillArcs(display, window, gc, sp->xarcleft, sp->NbStars); if (MI_WIN_IS_INSTALL(mi)) XSetFunction(display, gc, GXcopy); } else { XSetForeground(display, gc, sp->color); XFillArcs(display, window, gc, sp->xarc, sp->NbStars); } #if ((USEOLDXARCS == 1) || (ADAPT_ERASE == 1)) #if (ADAPT_ERASE == 1) if (sp->hasbeenchecked >= -1) { arc = sp->xarc; sp->xarc = sp->oldxarc; sp->oldxarc = arc; if (MI_WIN_IS_USE3D(mi)) { arcleft = sp->xarcleft; sp->xarcleft = sp->oldxarcleft; sp->oldxarcleft = arcleft; } } #else arc = sp->xarc; sp->xarc = sp->oldxarc; sp->oldxarc = arc; if (MI_WIN_IS_USE3D(mi)) { arcleft = sp->xarcleft; sp->xarcleft = sp->oldxarcleft; sp->oldxarcleft = arcleft; } #endif #endif /* We set up the color for the next drawing */ if (!MI_WIN_IS_USE3D(mi) && MI_NPIXELS(mi) > 2 && (++sp->colorchange >= COLOR_CHANGES)) { sp->colorchange = 0; if (++sp->colorp >= MI_NPIXELS(mi)) sp->colorp = 0; sp->color = MI_PIXEL(mi, sp->colorp); } }
ENTRYPOINT void draw_galaxy(ModeInfo * mi) { Display *display = MI_DISPLAY(mi); Window window = MI_WINDOW(mi); GC gc = MI_GC(mi); unistruct *gp = &universes[MI_SCREEN(mi)]; double d, eps, cox, six, cor, sir; /* tmp */ int i, j, k; /* more tmp */ XPoint *dummy = NULL; if (! dbufp) XClearWindow(MI_DISPLAY(mi), MI_WINDOW(mi)); if(spin){ 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 = gtk->mass / (d * sqrt(d)) * DELTAT * DELTAT * QCONS; else d = gtk->mass / (eps * sqrt(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) (((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 = 1 / (d * sqrt(d)) * DELTAT * QCONS; else d = 1 / (EPSILON * sqrt_EPSILON) * DELTAT * QCONS; d0 *= d; d1 *= d; d2 *= d; gt->vel[0] += d0 * gtk->mass; gt->vel[1] += d1 * gtk->mass; gt->vel[2] += d2 * gtk->mass; gtk->vel[0] -= d0 * gt->mass; gtk->vel[1] -= d1 * gt->mass; gtk->vel[2] -= d2 * gt->mass; } gt->pos[0] += gt->vel[0] * DELTAT; gt->pos[1] += gt->vel[1] * DELTAT; gt->pos[2] += gt->vel[2] * DELTAT; #if 1 // hacked and optimized by katahiromz { if (dbufp) { int count = gt->nstars; const XPoint *pt = gt->oldpoints; while (count-- > 0) { SetPixelV(display, pt->x, pt->y, 0); ++pt; } } XSetForeground(display, gc, MI_PIXEL(mi, gt->galcol)); { int count = gt->nstars; const XPoint *pt = gt->newpoints; const unsigned long rgb = gc->foreground_rgb; while (count-- > 0) { SetPixelV(display, pt->x, pt->y, rgb); ++pt; } } } #else if (dbufp) { 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)); XSetForeground(display, gc, MI_PIXEL(mi, gt->galcol)); XDrawPoints(display, window, gc, gt->newpoints, gt->nstars, CoordModeOrigin); #endif dummy = gt->oldpoints; gt->oldpoints = gt->newpoints; gt->newpoints = dummy; } gp->step++; if (gp->step > gp->f_hititerations * 4) startover(mi); }