void draw_gasket(ModeInfo * mi) { gasketstruct *gp = &gasket[MI_SCREEN(mi)]; Display *display = MI_DISPLAY(mi); Window window = MI_WINDOW(mi); int angle_incr = 1; if (!gp->glx_context) return; glDrawBuffer(GL_BACK); if (max_depth > 10) max_depth = 10; MI_IS_DRAWN(mi) = True; glXMakeCurrent(display, window, *(gp->glx_context)); draw(mi); /* rotate */ gp->angle = (int) (gp->angle + angle_incr) % 360; rotate(&gp->rotx, &gp->dx, &gp->ddx, gp->d_max, MI_IS_VERBOSE(mi)); rotate(&gp->roty, &gp->dy, &gp->ddy, gp->d_max, MI_IS_VERBOSE(mi)); rotate(&gp->rotz, &gp->dz, &gp->ddz, gp->d_max, MI_IS_VERBOSE(mi)); /* if (mi->fps_p) do_fps (mi); */ if (MI_IS_FPS(mi)) do_fps (mi); glFinish(); glXSwapBuffers(display, window); }
/* Direction angle of an edge. */ static angle_c vertex_dir(ModeInfo * mi, fringe_node_c * vertex, unsigned side) { tiling_c *tp = &tilings[MI_SCREEN(mi)]; fringe_node_c *v2 = (side == S_LEFT ? vertex->next : vertex->prev); register int i; for (i = 0; i < 5; i++) switch (v2->fived[i] - vertex->fived[i]) { case 1: return 2 * i; case -1: return (2 * i + 5) % 10; } tp->done = True; if (MI_IS_VERBOSE(mi)) { (void) fprintf(stderr, "Weirdness in vertex_dir (this has been reported)\n"); for (i = 0; i < 5; i++) (void) fprintf(stderr, "v2->fived[%d]=%d, vertex->fived[%d]=%d\n", i, v2->fived[i], i, vertex->fived[i]); } tp->busyLoop = CELEBRATE; return 0; }
static fringe_node_c * alloc_vertex(ModeInfo * mi, angle_c dir, fringe_node_c * from, tiling_c * tp) { fringe_node_c *v; if ((v = ALLOC_NODE(fringe_node_c)) == NULL) { tp->done = True; if (MI_IS_VERBOSE(mi)) { (void) fprintf(stderr, "No memory in alloc_vertex()\n"); } tp->busyLoop = CELEBRATE; return v; } *v = *from; add_unit_vec(dir, v->fived); fived_to_loc(v->fived, tp, &(v->loc)); if (v->loc.x < 0 || v->loc.y < 0 || v->loc.x >= tp->width || v->loc.y >= tp->height) { v->off_screen = True; if (v->loc.x < -tp->width || v->loc.y < -tp->height || v->loc.x >= 2 * tp->width || v->loc.y >= 2 * tp->height) tp->done = True; } else { v->off_screen = False; tp->fringe.n_nodes++; } v->n_tiles = 0; v->rule_mask = (1 << N_VERTEX_RULES) - 1; v->list_ptr = 0; return v; }
/*- * Delete this vertex. If the vertex is a member of the forced vertex queue, * also remove that entry. We assume that the vertex is no longer * connected to the fringe. Note that tp->fringe.nodes must not point to * the vertex being deleted. */ static void delete_vertex(ModeInfo * mi, fringe_node_c * vertex, tiling_c * tp) { if (tp->fringe.nodes == vertex) { tp->done = True; if (MI_IS_VERBOSE(mi)) { (void) fprintf(stderr, "Weirdness in delete_penrose()\n"); (void) fprintf(stderr, "tp->fringe.nodes == vertex\n"); } tp->busyLoop = CELEBRATE; } if (vertex->list_ptr != 0) { forced_node_c *node = *vertex->list_ptr; *vertex->list_ptr = node->next; if (node->next != 0) node->next->vertex->list_ptr = vertex->list_ptr; free(node); tp->forced.n_nodes--; if (!vertex->off_screen) tp->forced.n_visible--; } if (!vertex->off_screen) tp->fringe.n_nodes--; free(vertex); }
/*- * Update the status of this vertex on the forced vertex queue. If * the vertex has become untileable set tp->done. This is supposed * to detect dislocations -- never call this routine with a completely * tiled vertex. * * Check for untileable vertices in check_vertex and stop tiling as * soon as one finds one. I don't know if it is possible to run out * of forced vertices while untileable vertices exist (or will * cavities inevitably appear). If this can happen, add_random_tile * might get called with an untileable vertex, causing ( n <= 1). * (This is what the tp->done checks for). * * A delayLoop celebrates the dislocation. */ static void check_vertex(ModeInfo * mi, fringe_node_c * vertex, tiling_c * tp) { rule_match_c hits[MAX_TILES_PER_VERTEX * N_VERTEX_RULES]; int n_hits = match_rules(vertex, hits, False); unsigned forced_sides = 0; if (vertex->rule_mask == 0) { tp->done = True; if (MI_IS_VERBOSE(mi)) { (void) fprintf(stderr, "Dislocation occurred!\n"); } tp->busyLoop = CELEBRATE; /* Should be able to recover */ } if (1 == find_completions(vertex, hits, n_hits, S_LEFT, 0 /*, False */ )) forced_sides |= S_LEFT; if (1 == find_completions(vertex, hits, n_hits, S_RIGHT, 0 /*, False */ )) forced_sides |= S_RIGHT; if (forced_sides == 0) { if (vertex->list_ptr != 0) { forced_node_c *node = *vertex->list_ptr; *vertex->list_ptr = node->next; if (node->next != 0) node->next->vertex->list_ptr = vertex->list_ptr; free(node); tp->forced.n_nodes--; if (!vertex->off_screen) tp->forced.n_visible--; vertex->list_ptr = 0; } } else { forced_node_c *node; if (vertex->list_ptr == 0) { if ((node = ALLOC_NODE(forced_node_c)) == NULL) return; node->vertex = vertex; node->next = tp->forced.first; if (tp->forced.first != 0) tp->forced.first->vertex->list_ptr = &(node->next); tp->forced.first = node; vertex->list_ptr = &(tp->forced.first); tp->forced.n_nodes++; if (!vertex->off_screen) tp->forced.n_visible++; } else node = *vertex->list_ptr; node->forced_sides = forced_sides; } }
void make_uniform_colormap(ModeInfo * mi, Colormap cmap, XColor * colors, int *ncolorsP, Bool allocate_p, Bool * writable_pP) { int ncolors = *ncolorsP; Bool wanted_writable = (allocate_p && writable_pP && *writable_pP); double S = ((double) (LRAND() % 34) + 66) / 100.0; /* range 66%-100% */ double V = ((double) (LRAND() % 34) + 66) / 100.0; /* range 66%-100% */ if (*ncolorsP <= 0) return; /* If this visual doesn't support writable cells, don't bother trying. */ if (wanted_writable && !has_writable_cells(mi)) *writable_pP = False; RETRY_NON_WRITABLE: make_color_ramp(MI_DISPLAY(mi), cmap, 0, S, V, 359, S, V, colors, &ncolors, False, True, wanted_writable); /* If we tried for writable cells and got none, try for non-writable. */ if (allocate_p && *ncolorsP == 0 && writable_pP && *writable_pP) { ncolors = *ncolorsP; *writable_pP = False; goto RETRY_NON_WRITABLE; } if (MI_IS_VERBOSE(mi) || MI_IS_DEBUG(mi)) complain(*ncolorsP, ncolors, wanted_writable, wanted_writable && *writable_pP); *ncolorsP = ncolors; }
/*- * Add a forced tile to a given forced vertex. Basically an easy job, * since we know what to add. But it might fail if adding the tile * would cause some untiled area to become enclosed. There is also another * more exotic culprit: we might have a dislocation. Fortunately, they * are very rare (the PRL article reported that perfect tilings of over * 2^50 tiles had been generated). There is a version of the algorithm * that doesn't produce dislocations, but it's a lot hairier than the * simpler version I used. */ static int add_forced_tile(ModeInfo * mi, forced_node_c * node) { tiling_c *tp = &tilings[MI_SCREEN(mi)]; unsigned side; vertex_type_c vtype; rule_match_c hits[MAX_TILES_PER_VERTEX * N_VERTEX_RULES]; int n; if (node->forced_sides == (S_LEFT | S_RIGHT)) side = NRAND(2) ? S_LEFT : S_RIGHT; else side = node->forced_sides; n = match_rules(node->vertex, hits, True); n = find_completions(node->vertex, hits, n, side, &vtype /*, True */ ); if (n <= 0) { tp->done = True; if (MI_IS_VERBOSE(mi)) { (void) fprintf(stderr, "Weirdness in add_forced_tile()\n"); (void) fprintf(stderr, "n = %d\n", n); } } return add_tile(mi, node->vertex, side, vtype); }
ENTRYPOINT void init_hop(ModeInfo * mi) { Display *display = MI_DISPLAY(mi); GC gc = MI_GC(mi); double range; hopstruct *hp; if (hops == NULL) { if ((hops = (hopstruct *) calloc(MI_NUM_SCREENS(mi), sizeof (hopstruct))) == NULL) return; } hp = &hops[MI_SCREEN(mi)]; hp->centerx = MI_WIDTH(mi) / 2; hp->centery = MI_HEIGHT(mi) / 2; /* Make the other operations less common since they are less interesting */ if (MI_IS_FULLRANDOM(mi)) { hp->op = NRAND(OPS); } else { if (martin) hp->op = MARTIN; else if (popcorn) hp->op = POPCORN; else if (ejk1) hp->op = EJK1; else if (ejk2) hp->op = EJK2; else if (ejk3) hp->op = EJK3; else if (ejk4) hp->op = EJK4; else if (ejk5) hp->op = EJK5; else if (ejk6) hp->op = EJK6; else if (rr) hp->op = RR; else if (jong) hp->op = JONG; else if (sine) hp->op = SINE; else hp->op = NRAND(OPS); } range = sqrt((double) hp->centerx * hp->centerx + (double) hp->centery * hp->centery) / (1.0 + LRAND() / MAXRAND); hp->i = hp->j = 0.0; hp->inc = (int) ((LRAND() / MAXRAND) * 200) - 100; #undef XMARTIN switch (hp->op) { case MARTIN: #ifdef XMARTIN hp->a = (LRAND() / MAXRAND) * 1500.0 + 40.0; hp->b = (LRAND() / MAXRAND) * 17.0 + 3.0; hp->c = (LRAND() / MAXRAND) * 3000.0 + 100.0; #else hp->a = ((LRAND() / MAXRAND) * 2.0 - 1.0) * range / 20.0; hp->b = ((LRAND() / MAXRAND) * 2.0 - 1.0) * range / 20.0; if (LRAND() & 1) hp->c = ((LRAND() / MAXRAND) * 2.0 - 1.0) * range / 20.0; else hp->c = 0.0; #endif if (MI_IS_VERBOSE(mi)) (void) fprintf(stdout, "sqrt a=%g, b=%g, c=%g\n", hp->a, hp->b, hp->c); break; case EJK1: #ifdef XMARTIN hp->a = (LRAND() / MAXRAND) * 500.0; hp->c = (LRAND() / MAXRAND) * 100.0 + 10.0; #else hp->a = ((LRAND() / MAXRAND) * 2.0 - 1.0) * range / 30.0; hp->c = ((LRAND() / MAXRAND) * 2.0 - 1.0) * range / 40.0; #endif hp->b = (LRAND() / MAXRAND) * 0.4; if (MI_IS_VERBOSE(mi)) (void) fprintf(stdout, "ejk1 a=%g, b=%g, c=%g\n", hp->a, hp->b, hp->c); break; case EJK2: #ifdef XMARTIN hp->a = (LRAND() / MAXRAND) * 500.0; #else hp->a = ((LRAND() / MAXRAND) * 2.0 - 1.0) * range / 30.0; #endif hp->b = pow(10.0, 6.0 + (LRAND() / MAXRAND) * 24.0); if (LRAND() & 1) hp->b = -hp->b; hp->c = pow(10.0, (LRAND() / MAXRAND) * 9.0); if (LRAND() & 1) hp->c = -hp->c; if (MI_IS_VERBOSE(mi)) (void) fprintf(stdout, "ejk2 a=%g, b=%g, c=%g\n", hp->a, hp->b, hp->c); break; case EJK3: #ifdef XMARTIN hp->a = (LRAND() / MAXRAND) * 500.0; hp->c = (LRAND() / MAXRAND) * 80.0 + 30.0; #else hp->a = ((LRAND() / MAXRAND) * 2.0 - 1.0) * range / 30.0; hp->c = ((LRAND() / MAXRAND) * 2.0 - 1.0) * range / 70.0; #endif hp->b = (LRAND() / MAXRAND) * 0.35 + 0.5; if (MI_IS_VERBOSE(mi)) (void) fprintf(stdout, "ejk3 a=%g, b=%g, c=%g\n", hp->a, hp->b, hp->c); break; case EJK4: #ifdef XMARTIN hp->a = (LRAND() / MAXRAND) * 1000.0; hp->c = (LRAND() / MAXRAND) * 40.0 + 30.0; #else hp->a = ((LRAND() / MAXRAND) * 2.0 - 1.0) * range / 2.0; hp->c = ((LRAND() / MAXRAND) * 2.0 - 1.0) * range / 200.0; #endif hp->b = (LRAND() / MAXRAND) * 9.0 + 1.0; if (MI_IS_VERBOSE(mi)) (void) fprintf(stdout, "ejk4 a=%g, b=%g, c=%g\n", hp->a, hp->b, hp->c); break; case EJK5: #ifdef XMARTIN hp->a = (LRAND() / MAXRAND) * 600.0; hp->c = (LRAND() / MAXRAND) * 90.0 + 20.0; #else hp->a = ((LRAND() / MAXRAND) * 2.0 - 1.0) * range / 2.0; hp->c = ((LRAND() / MAXRAND) * 2.0 - 1.0) * range / 200.0; #endif hp->b = (LRAND() / MAXRAND) * 0.3 + 0.1; if (MI_IS_VERBOSE(mi)) (void) fprintf(stdout, "ejk5 a=%g, b=%g, c=%g\n", hp->a, hp->b, hp->c); break; case EJK6: #ifdef XMARTIN hp->a = (LRAND() / MAXRAND) * 100.0 + 550.0; #else hp->a = ((LRAND() / MAXRAND) * 2.0 - 1.0) * range / 30.0; #endif hp->b = (LRAND() / MAXRAND) + 0.5; if (MI_IS_VERBOSE(mi)) (void) fprintf(stdout, "ejk6 a=%g, b=%g\n", hp->a, hp->b); break; case RR: #ifdef XMARTIN hp->a = (LRAND() / MAXRAND) * 100.0; hp->b = (LRAND() / MAXRAND) * 20.0; hp->c = (LRAND() / MAXRAND) * 200.0; #else hp->a = ((LRAND() / MAXRAND) * 2.0 - 1.0) * range / 40.0; hp->b = ((LRAND() / MAXRAND) * 2.0 - 1.0) * range / 200.0; hp->c = ((LRAND() / MAXRAND) * 2.0 - 1.0) * range / 20.0; #endif hp->d = (LRAND() / MAXRAND) * 0.9; if (MI_IS_VERBOSE(mi)) (void) fprintf(stdout, "rr a=%g, b=%g, c=%g, d=%g\n", hp->a, hp->b, hp->c, hp->d); break; case POPCORN: hp->a = 0.0; hp->b = 0.0; hp->c = ((LRAND() / MAXRAND) * 2.0 - 1.0) * 0.24 + 0.25; hp->inc = 100; if (MI_IS_VERBOSE(mi)) (void) fprintf(stdout, "popcorn a=%g, b=%g, c=%g, d=%g\n", hp->a, hp->b, hp->c, hp->d); break; case JONG: hp->a = ((LRAND() / MAXRAND) * 2.0 - 1.0) * M_PI; hp->b = ((LRAND() / MAXRAND) * 2.0 - 1.0) * M_PI; hp->c = ((LRAND() / MAXRAND) * 2.0 - 1.0) * M_PI; hp->d = ((LRAND() / MAXRAND) * 2.0 - 1.0) * M_PI; if (MI_IS_VERBOSE(mi)) (void) fprintf(stdout, "jong a=%g, b=%g, c=%g, d=%g\n", hp->a, hp->b, hp->c, hp->d); break; case SINE: /* MARTIN2 */ #ifdef XMARTIN hp->a = M_PI + ((LRAND() / MAXRAND) * 2.0 - 1.0) * 0.07; #else hp->a = M_PI + ((LRAND() / MAXRAND) * 2.0 - 1.0) * 0.7; #endif if (MI_IS_VERBOSE(mi)) (void) fprintf(stdout, "sine a=%g\n", hp->a); break; } if (MI_NPIXELS(mi) > 2) hp->pix = NRAND(MI_NPIXELS(mi)); hp->bufsize = MI_COUNT(mi); if (hp->pointBuffer == NULL) { if ((hp->pointBuffer = (XPoint *) malloc(hp->bufsize * sizeof (XPoint))) == NULL) return; } #ifndef STANDALONE MI_CLEARWINDOW(mi); #endif XSetForeground(display, gc, MI_WHITE_PIXEL(mi)); hp->count = 0; }
void init_life1d(ModeInfo * mi) { Display *display = MI_DISPLAY(mi); Window window = MI_WINDOW(mi); int size = MI_SIZE(mi); int i; life1dstruct *lp; if (life1ds == NULL) { if ((life1ds = (life1dstruct *) calloc(MI_NUM_SCREENS(mi), sizeof (life1dstruct))) == NULL) return; } lp = &life1ds[MI_SCREEN(mi)]; if (!init_stuff(mi)) { free_life1d(display, lp); return; } lp->screen_generation = 0; lp->row = 0; if (totalistic) { maxstates = MAXSTATES; maxradius = 4; maxsum_size = (maxstates - 1) * (maxradius * 2 + 1) + 1; } else { maxstates = MAXSTATES - 1; maxradius = 1; maxsum_size = (int) power(maxstates, (2 * maxradius + 1)); } if (lp->nextstate == NULL) { if ((lp->nextstate = (char *) malloc(maxsum_size * sizeof (char))) == NULL) { free_life1d(display, lp); return; } } if (lp->init_bits == 0) { XGCValues gcv; gcv.fill_style = FillOpaqueStippled; if ((lp->stippledGC = XCreateGC(display, window, GCFillStyle, &gcv)) == None) { free_life1d(display, lp); return; } for (i = 0; i < MAXSTATES - 1; i++) { LIFE1DBITS(stipples[i + NUMSTIPPLES - MAXSTATES + 1], STIPPLESIZE, STIPPLESIZE); } LIFE1DBITS(stipples[NUMSTIPPLES / 2], STIPPLESIZE, STIPPLESIZE); /* grey */ } if (lp->newcells != NULL) free(lp->newcells); if (lp->oldcells != NULL) free(lp->oldcells); if (lp->buffer != NULL) free(lp->buffer); if (lp->previousBuffer != NULL) free(lp->previousBuffer); lp->previousBuffer = (unsigned char *) NULL; lp->width = MI_WIDTH(mi); lp->height = MI_HEIGHT(mi); if (lp->width < 2) lp->width = 2; if (lp->height < 2) lp->height = 2; if (size == 0 || MINGRIDSIZE * size > lp->width || MINGRIDSIZE * size > lp->height) { if (lp->width > MINGRIDSIZE * lp->logo->width && lp->height > MINGRIDSIZE * lp->logo->height) { lp->pixelmode = False; lp->xs = lp->logo->width; lp->ys = lp->logo->height; } else { int min = MIN(lp->width, lp->height) / (12 * MINGRIDSIZE); int max = MIN(lp->width, lp->height) / (4 * MINGRIDSIZE); lp->xs = lp->ys = MAX(MINSIZE, min + NRAND(max - min + 1)); lp->pixelmode = True; } } else { lp->pixelmode = True; if (size < -MINSIZE) { lp->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(lp->width, lp->height) / MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE; } else if (size < MINSIZE) { lp->ys = MINSIZE; } else { lp->ys = MIN(size, MAX(MINSIZE, MIN(lp->width, lp->height) / MINGRIDSIZE)); } lp->xs = lp->ys; } lp->ncols = MAX(lp->width / lp->xs, 2); lp->nrows = MAX(lp->height / lp->ys, 2); lp->border = (lp->nrows / 2 + 1) * MI_CYCLES(mi); if ((lp->newcells = (unsigned char *) calloc(lp->ncols + 2 * lp->border, sizeof (unsigned char))) == NULL) { free_life1d(display, lp); return; } if ((lp->oldcells = (unsigned char *) calloc(lp->ncols + 2 * (maxradius + lp->border), sizeof (unsigned char))) == NULL) { free_life1d(display, lp); return; } if ((lp->buffer = (unsigned char *) calloc(lp->ncols * lp->nrows, sizeof (unsigned char))) == NULL) { free_life1d(display, lp); return; } lp->xb = (lp->width - lp->xs * lp->ncols) / 2; lp->yb = (lp->height - lp->ys * lp->nrows) / 2; GetRule(lp, (int) NRAND((totalistic) ? TOTALISTICRULES : LCAURULES)); if (MI_IS_VERBOSE(mi)) { (void) fprintf(stdout, "colors %d, radius %d, code %ld, ", lp->k, lp->r, lp->code); if (totalistic) { (void) fprintf(stdout, "totalistic rule "); for (i = (lp->k - 1) * (lp->r * 2 + 1); i >= 0; i--) (void) fprintf(stdout, "%d", (int) lp->nextstate[i]); } else { (void) fprintf(stdout, "LCAU rule "); for (i = (int) power(lp->k, (lp->r * 2 + 1)); i >= 0; i--) (void) fprintf(stdout, "%d", (int) lp->nextstate[i]); } (void) fprintf(stdout, "\n"); } if (MI_NPIXELS(mi) > 2) { int offset = NRAND(MI_NPIXELS(mi)); for (i = 0; i < lp->k - 1; i++) { lp->colors[i] = ((offset + (i * MI_NPIXELS(mi) / (lp->k - 1))) % MI_NPIXELS(mi)); } } RandomSoup(lp, 40, 25); (void) memcpy((char *) (lp->oldcells + maxradius + lp->border), (char *) (lp->newcells + lp->border), lp->ncols); lp->busyLoop = 0; MI_CLEARWINDOWCOLORMAP(mi, lp->backGC, lp->black); }
/* Constructs the GL shapes of the current molecule */ static void build_molecule (ModeInfo *mi) { molecule_configuration *mc = &mcs[MI_SCREEN(mi)]; int wire = cur_wire; int i; molecule *m = &mc->molecules[mc->which]; if (wire) { glDisable(GL_CULL_FACE); glDisable(GL_LIGHTING); glDisable(GL_LIGHT0); glDisable(GL_DEPTH_TEST); glDisable(GL_NORMALIZE); glDisable(GL_CULL_FACE); } else { glEnable(GL_CULL_FACE); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_DEPTH_TEST); glEnable(GL_NORMALIZE); glEnable(GL_CULL_FACE); } if (!wire) set_atom_color (mi, 0, False); if (do_bonds) for (i = 0; i < m->nbonds; i++) { molecule_bond *b = &m->bonds[i]; molecule_atom *from = get_atom(m->atoms, m->natoms, b->from, MI_IS_VERBOSE(mi)); molecule_atom *to = get_atom(m->atoms, m->natoms, b->to, MI_IS_VERBOSE(mi)); if (wire) { glBegin(GL_LINES); glVertex3f(from->x, from->y, from->z); glVertex3f(to->x, to->y, to->z); glEnd(); } else { int faces = (scale_down ? TUBE_FACES_2 : TUBE_FACES); # ifdef SMOOTH_TUBE int smooth = True; # else int smooth = False; # endif GLfloat thickness = 0.07 * b->strength; GLfloat cap_size = 0.03; if (thickness > 0.3) thickness = 0.3; tube (from->x, from->y, from->z, to->x, to->y, to->z, thickness, cap_size, faces, smooth, !do_atoms, wire); } } for (i = 0; i < m->natoms; i++) { molecule_atom *a = &m->atoms[i]; int i; if (!wire && do_atoms) { GLfloat size = atom_size (a); set_atom_color (mi, a, False); sphere (a->x, a->y, a->z, size, wire); } if (do_labels) { glPushAttrib (GL_LIGHTING_BIT | GL_DEPTH_BUFFER_BIT); glDisable (GL_LIGHTING); glDisable (GL_DEPTH_TEST); if (!wire) set_atom_color (mi, a, True); glRasterPos3f (a->x, a->y, a->z); { GLdouble mm[17], pm[17]; GLint vp[5]; GLdouble wx=-1, wy=-1, wz=-1; glGetDoublev (GL_MODELVIEW_MATRIX, mm); glGetDoublev (GL_PROJECTION_MATRIX, pm); glGetIntegerv (GL_VIEWPORT, vp); /* Convert 3D coordinates to window coordinates */ gluProject (a->x, a->y, a->z, mm, pm, vp, &wx, &wy, &wz); /* Fudge the window coordinates to center the string */ wx -= string_width (mc->xfont1, a->label) / 2; wy -= mc->xfont1->descent; /* Convert new window coordinates back to 3D coordinates */ gluUnProject (wx, wy, wz, mm, pm, vp, &wx, &wy, &wz); glRasterPos3f (wx, wy, wz); } for (i = 0; i < (int) strlen(a->label); i++) glCallList (mc->font1_dlist + (int)(a->label[i])); glPopAttrib(); } } if (do_bbox) draw_bounding_box (mi); if (do_titles && m->label && *m->label) print_title_string (mi, m->label, 10, MI_HEIGHT(mi) - 10, mc->xfont2->ascent + mc->xfont2->descent); }
void draw_molecule (ModeInfo *mi) { /* static time_t last = 0; */ time_t now = time ((time_t *) 0); molecule_configuration *mc; Display *dpy = MI_DISPLAY(mi); Window window = MI_WINDOW(mi); if (mcs == NULL) return; mc = &mcs[MI_SCREEN(mi)]; if (!mc->glx_context) return; MI_IS_DRAWN(mi) = True; if (last + timeout <= now) /* randomize molecules every -timeout seconds */ { if (mc->nmolecules == 1) { if (last != 0) goto SKIP; mc->which = 0; } else if (last == 0) { mc->which = NRAND(mc->nmolecules); } else { int n = mc->which; while (n == mc->which) n = NRAND(mc->nmolecules); mc->which = n; } last = now; glNewList (mc->molecule_dlist, GL_COMPILE); ensure_bounding_box_visible (mi); if (MI_IS_ICONIC(mi)) {do_labels = False; do_bonds = True; do_titles = False; } else { do_labels = orig_do_labels; do_bonds = orig_do_bonds; do_titles = orig_do_titles; } cur_wire = orig_wire; if (mc->molecule_size > mc->no_label_threshold) do_labels = 0; if (mc->molecule_size > mc->wireframe_threshold) cur_wire = 1; if (cur_wire) do_bonds = 1; build_molecule (mi); glEndList(); } SKIP: glPushMatrix (); glScalef(1.1, 1.1, 1.1); { GLfloat x, y, z; if (do_wander) { static int frame = 0; # define SINOID(SCALE,SIZE) \ ((((1 + sin((frame * (SCALE)) / 2 * M_PI)) / 2.0) * (SIZE)) - (SIZE)/2) x = SINOID(0.031, 9.0); y = SINOID(0.023, 9.0); z = SINOID(0.017, 9.0); frame++; glTranslatef(x, y, z); } if (mc->spin_x || mc->spin_y || mc->spin_z) { x = mc->rotx; y = mc->roty; z = mc->rotz; if (x < 0) x = 1 - (x + 1); if (y < 0) y = 1 - (y + 1); if (z < 0) z = 1 - (z + 1); if (mc->spin_x) glRotatef(x * 360, 1.0, 0.0, 0.0); if (mc->spin_y) glRotatef(y * 360, 0.0, 1.0, 0.0); if (mc->spin_z) glRotatef(z * 360, 0.0, 0.0, 1.0); rotate(&mc->rotx, &mc->dx, &mc->ddx, mc->d_max, MI_IS_VERBOSE(mi)); rotate(&mc->roty, &mc->dy, &mc->ddy, mc->d_max, MI_IS_VERBOSE(mi)); rotate(&mc->rotz, &mc->dz, &mc->ddz, mc->d_max, MI_IS_VERBOSE(mi)); } } glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glCallList (mc->molecule_dlist); glPopMatrix (); if (MI_IS_FPS(mi)) do_fps (mi); glFinish(); glXSwapBuffers(dpy, window); }
void getImage(ModeInfo * mi, XImage ** logo, int default_width, int default_height, unsigned char *default_bits, #ifdef HAVE_XPM int default_xpm, char **name, #endif int *graphics_format, Colormap * ncm, unsigned long *black) { Display *display = MI_DISPLAY(mi); static char *bitmap_local = (char *) NULL; #ifndef STANDALONE #ifdef HAVE_XPM XpmAttributes attrib; #endif #if 0 /* This probably works best in most cases but for random mode used with random selection of a file it will fail often. */ *ncm = None; #else if (!fixedColors(mi)) *ncm = XCreateColormap(display, MI_WINDOW(mi), MI_VISUAL(mi), AllocNone); else *ncm = None; #endif #ifdef HAVE_XPM attrib.visual = MI_VISUAL(mi); if (*ncm == None) { attrib.colormap = MI_COLORMAP(mi); } else { attrib.colormap = *ncm; } attrib.depth = MI_DEPTH(mi); attrib.valuemask = XpmVisual | XpmColormap | XpmDepth; #endif #endif /* !STANDALONE */ *graphics_format = 0; if (bitmap_local != NULL) { free(bitmap_local); bitmap_local = (char *) NULL; } if (MI_BITMAP(mi) && strlen(MI_BITMAP(mi))) { #ifdef STANDALONE bitmap_local = MI_BITMAP(mi); #else if ((bitmap_local = (char *) malloc(256)) == NULL) { (void) fprintf(stderr , "no memory for \"%s\"\n" , MI_BITMAP(mi)); return; } (void) strncpy(bitmap_local, MI_BITMAP(mi), 256); #if HAVE_DIRENT_H getRandomFile(MI_BITMAP(mi), bitmap_local); #endif #endif /* STANDALONE */ } if (bitmap_local && strlen(bitmap_local)) { #if defined( USE_MAGICK ) && !defined( STANDALONE ) if ( readable( bitmap_local ) ) { if ( MI_NPIXELS( mi ) > 2 ) { Colormap magick_colormap; if (*ncm == None) { magick_colormap = MI_COLORMAP(mi); } else { magick_colormap = *ncm; } if ( MagickSuccess == MagickFileToImage( mi , bitmap_local , logo , magick_colormap ) ) { *graphics_format = IS_MAGICKFILE; *black = GetColor(mi, MI_BLACK_PIXEL(mi)); (void) GetColor(mi, MI_WHITE_PIXEL(mi)); (void) GetColor(mi, MI_BG_PIXEL(mi)); (void) GetColor(mi, MI_FG_PIXEL(mi)); } } } else { (void) fprintf(stderr , "could not read file \"%s\"\n" , bitmap_local); } #else # ifndef STANDALONE if (readable(bitmap_local)) { if (MI_NPIXELS(mi) > 2) { Colormap ras_colormap; if (*ncm == None) { ras_colormap = MI_COLORMAP(mi); } else { ras_colormap = *ncm; } if (RasterSuccess == RasterFileToImage(mi, bitmap_local, logo , ras_colormap )) { *graphics_format = IS_RASTERFILE; *black = GetColor(mi, MI_BLACK_PIXEL(mi)); (void) GetColor(mi, MI_WHITE_PIXEL(mi)); (void) GetColor(mi, MI_BG_PIXEL(mi)); (void) GetColor(mi, MI_FG_PIXEL(mi)); } } } else { (void) fprintf(stderr, "could not read file \"%s\"\n", bitmap_local); } #ifdef HAVE_XPM #ifndef USE_MONOXPM if (MI_NPIXELS(mi) > 2) #endif { if (*graphics_format <= 0) { if (*ncm != None) reserveColors(mi, *ncm, black); if (XpmSuccess == XpmReadFileToImage(display, bitmap_local, logo, (XImage **) NULL, &attrib)) *graphics_format = IS_XPMFILE; } } #endif #endif /* !STANDALONE */ if (*graphics_format <= 0) { if (!blogo.data) { if (BitmapSuccess == XbmReadFileToImage(bitmap_local, &blogo.width, &blogo.height, (unsigned char **) &blogo.data)) { blogo.bytes_per_line = (blogo.width + 7) / 8; *graphics_format = IS_XBMFILE; *logo = &blogo; } } else { *graphics_format = IS_XBMDONE; *logo = &blogo; } } #endif if (*graphics_format <= 0 && MI_IS_VERBOSE(mi)) (void) fprintf(stderr, "\"%s\" is in an unrecognized format or not compatible with screen\n", bitmap_local); } #ifndef STANDALONE #ifdef HAVE_XPM if (*graphics_format <= 0 && ((MI_IS_FULLRANDOM(mi)) ? LRAND() & 1: default_xpm)) #ifndef USE_MONOXPM if (MI_NPIXELS(mi) > 2) #endif if (XpmSuccess == XpmCreateImageFromData(display, name, logo, (XImage **) NULL, &attrib)) *graphics_format = IS_XPM; #endif #endif /* STANDALONE */ if (*graphics_format <= 0) { if (!blogo.data) { blogo.data = (char *) default_bits; blogo.width = default_width; blogo.height = default_height; blogo.bytes_per_line = (blogo.width + 7) / 8; *graphics_format = IS_XBM; } else *graphics_format = IS_XBMDONE; *logo = &blogo; } #ifndef STANDALONE /* Come back later */ if (*ncm != None && *graphics_format != IS_RASTERFILE && *graphics_format != IS_XPMFILE && *graphics_format != IS_XPM && *graphics_format != IS_MAGICKFILE) { XFreeColormap(display, *ncm); *ncm = None; } #endif /* STANDALONE */ /* Come back later */ }
void init_xcl(ModeInfo * mi) { Display *display = MI_DISPLAY(mi); int i; /* scratch */ xclstruct *dp; if (xcls == NULL) { if ((xcls = (xclstruct *) calloc(MI_NUM_SCREENS(mi), sizeof (xclstruct))) == NULL) return; } dp = &xcls[MI_SCREEN(mi)]; /* Update every time */ dp->width = MI_WIDTH(mi); dp->height = MI_HEIGHT(mi); dp->mid_x = (dp->width / 2); dp->mid_y = (dp->height / 2); if(dp->no_preset != 1) { dp->no_preset = 1; /* some presettings */ dp->planes = MI_COUNT(mi); if (dp->planes < -MINPLANES) { dp->planes = NRAND(-MI_COUNT(mi) -MINPLANES + 1) + MINPLANES; } else if (dp->planes < MINPLANES) { dp->planes = MINPLANES; } if(dp->planes > MAXCOUNT) dp->planes = MAXCOUNT; dp->Alpha = 0.0; /* rotate.1 */ dp->Beta = 0.0; /* rotate.2 */ dp->Gamma = 0.0; /* rotate.3 */ dp->Vx = 1; /* width from zero in X */ dp->Vy = 800; /* width from zero in Y */ dp->Vz = -300; /* width from zero in Z */ dp->G = 500.0; /* ZOOM */ dp->time3 = 1.0; dp->drawtime = 25000; dp->xcldelay = STARTUPDELAY; for(i=0;i< dp->planes; i++) { dp->az[i] = 2 * M_PI * i / (float)((dp->planes)); dp->el[i] = 0.0; dp->alpha[i] = 0.75; /* direction */ dp->turn[i] = 0; dp->turn_direction[i] = 1; speed[i] = speed_in; /* see TODO */ } random_pid = getpid(); /* goes here first for randomstart */ if(randomstart) { for(i=0;i< dp->planes; i++) { switch(i) { case 0: dp->az[0] += (random_pid % 31) / 5.0; break; default: dp->az[i] = dp->az[0] + 2 * M_PI * i / (float)((dp->planes)); } } } dp->bg = MI_BLACK_PIXEL(mi); if(MI_NPIXELS(mi) <= 2) for(i=0;i< dp->planes; i++) { dp->planecolor[i] = MI_WHITE_PIXEL(mi); } else { if(!oldcolor) { for(i=0;i< dp->planes; i++) { dp->planecolor[i] = MI_PIXEL(mi, NRAND(MI_NPIXELS(mi))); } } else { /* with count >2 no so good */ for(i=0;i< dp->planes; i++) { switch(i) { case 0: dp->planecolor[0] = get_color(mi, (char *) "yellow", (XColor *) NULL); break; case 1: dp->planecolor[1] = get_color(mi, (char *) "red", (XColor *) NULL); break; default: dp->planecolor[i] = MI_PIXEL(mi, NRAND(MI_NPIXELS(mi))); } } } } if(dp->erase_gc == None) if (!get_GC(display, MI_WINDOW(mi), &(dp->erase_gc),dp->bg)) { free_xcl(display, dp); return; } dp->lines = countlines(); for(i=0;i< dp->planes; i++) { if(dp->gc[i] == None) if (!get_GC(display, MI_WINDOW(mi), &(dp->gc[i]), dp->planecolor[i])) { free_xcl(display, dp); return; } dp->omega_const[i] = speed[i]/3.6 /line_length*1000.0; if(dp->xseg[i] == NULL) if ((dp-> xseg[i] = (XSegment *) malloc(sizeof(XSegment) * dp->lines)) == NULL) { free_xcl(display, dp); return; } if(dp->xseg_old[i] == NULL) if ((dp->xseg_old[i] = (XSegment *) malloc(sizeof(XSegment) * dp->lines)) == NULL) { free_xcl(display, dp); return; } } if(MI_IS_VERBOSE(mi)) { (void) printf("X control line combat in a box\n"); #if !defined( lint ) && !defined( SABER ) (void) printf("Version: %s\n",sccsid); #endif (void) printf("Line length: %gm\n",line_length/1000.0); (void) printf("Speed %g km/h \n",speed[0]); (void) printf("Lines per plane: %d\n",dp->lines); (void) printf("Spectator at %gm\n",spectator/1000.0); (void) printf("Try %g frames per Second (frametime: %dus)\n", 1000000.0/frametime,frametime); (void) printf("Calibration at %d frames\n",REGULATE); } } /* clear the screen */ MI_CLEARWINDOW(mi); (void) gettimeofday(&(dp->tv1),0); dp->time1 = (double)dp->tv1.tv_sec + (double)dp->tv1.tv_usec/(double)1000000; dp->xcldelay = frametime; }
/*- * Add a tile described by vtype to the side of vertex. This must be * allowed by the rules -- we do not check it here. New vertices are * allocated as necessary. The fringe and the forced vertex pool are updated. * The new tile is drawn on the display. * * One thing we do check here is whether the new tile causes an untiled * area to become enclosed by the tiling. If this would happen, the tile * is not added. The return value is true iff a tile was added. */ static int add_tile(ModeInfo * mi, fringe_node_c * vertex, unsigned side, vertex_type_c vtype) { tiling_c *tp = &tilings[MI_SCREEN(mi)]; fringe_node_c *left = (fringe_node_c *) NULL, *right = (fringe_node_c *) NULL, *far = (fringe_node_c *) NULL, *node; unsigned fc = fringe_changes(mi, vertex, side, vtype, &right, &far, &left); vertex_type_c ltype = VT_LEFT(vtype), rtype = VT_RIGHT(vtype), ftype = VT_FAR(vtype); /* By our conventions vertex->next lies to the left of vertex and vertex->prev to the right. */ /* This should never occur. */ if (fc & FC_BAG) { tp->done = True; if (MI_IS_VERBOSE(mi)) { (void) fprintf(stderr, "Weirdness in add_tile()\n"); (void) fprintf(stderr, "fc = %d, FC_BAG = %d\n", fc, FC_BAG); } } if (side == S_LEFT) { if (right == NULL) if ((right = alloc_vertex(mi, vertex_dir(mi, vertex, S_LEFT) - vtype_angle(vtype), vertex, tp)) == NULL) return False; if (far == NULL) if ((far = alloc_vertex(mi, vertex_dir(mi, left, S_RIGHT) + vtype_angle(ltype), left, tp)) == NULL) return False; } else { if (left == NULL) if ((left = alloc_vertex(mi, vertex_dir(mi, vertex, S_RIGHT) + vtype_angle(vtype), vertex, tp)) == NULL) return False; if (far == NULL) if ((far = alloc_vertex(mi, vertex_dir(mi, right, S_LEFT) - vtype_angle(rtype), right, tp)) == NULL) return False; } /* Having allocated the new vertices, but before joining them with the rest of the fringe, check if vertices with same coordinates already exist. If any such are found, give up. */ node = tp->fringe.nodes; do { if (((fc & FC_NEW_LEFT) && fived_equal(node->fived, left->fived)) || ((fc & FC_NEW_RIGHT) && fived_equal(node->fived, right->fived)) || ((fc & FC_NEW_FAR) && fived_equal(node->fived, far->fived))) { /* Better luck next time. */ if (fc & FC_NEW_LEFT) delete_vertex(mi, left, tp); if (fc & FC_NEW_RIGHT) delete_vertex(mi, right, tp); if (fc & FC_NEW_FAR) delete_vertex(mi, far, tp); return False; } node = node->next; } while (node != tp->fringe.nodes); /* Rechain. */ if (!(fc & FC_CUT_THIS)) { if (side == S_LEFT) { vertex->next = right; right->prev = vertex; } else { vertex->prev = left; left->next = vertex; } } if (!(fc & FC_CUT_FAR)) { if (!(fc & FC_CUT_LEFT)) { far->next = left; left->prev = far; } if (!(fc & FC_CUT_RIGHT)) { far->prev = right; right->next = far; } } draw_tile(vertex, right, far, left, vtype, mi); /* Delete vertices that are no longer on the fringe. Check the others. */ if (fc & FC_CUT_THIS) { tp->fringe.nodes = far; delete_vertex(mi, vertex, tp); } else { add_vtype(vertex, side, vtype); check_vertex(mi, vertex, tp); tp->fringe.nodes = vertex; } if (fc & FC_CUT_FAR) delete_vertex(mi, far, tp); else { add_vtype(far, fc & FC_CUT_RIGHT ? S_LEFT : S_RIGHT, ftype); check_vertex(mi, far, tp); } if (fc & FC_CUT_LEFT) delete_vertex(mi, left, tp); else { add_vtype(left, fc & FC_CUT_FAR ? S_LEFT : S_RIGHT, ltype); check_vertex(mi, left, tp); } if (fc & FC_CUT_RIGHT) delete_vertex(mi, right, tp); else { add_vtype(right, fc & FC_CUT_FAR ? S_RIGHT : S_LEFT, rtype); check_vertex(mi, right, tp); } return True; }
void make_smooth_colormap(ModeInfo * mi, Colormap cmap, XColor * colors, int *ncolorsP, Bool allocate_p, Bool * writable_pP) { int npoints; int ncolors = *ncolorsP; Bool wanted_writable = (allocate_p && writable_pP && *writable_pP); int i; int h[MAXPOINTS]; double s[MAXPOINTS]; double v[MAXPOINTS]; double total_s = 0; double total_v = 0; if (*ncolorsP <= 0) return; { int n = (int) (LRAND() % 20); if (n <= 5) npoints = 2; /* 30% of the time */ else if (n <= 15) npoints = 3; /* 50% of the time */ else if (n <= 18) npoints = 4; /* 15% of the time */ else npoints = 5; /* 5% of the time */ } REPICK_ALL_COLORS: for (i = 0; i < npoints; i++) { REPICK_THIS_COLOR: h[i] = (int) (LRAND() % 360); s[i] = LRAND() / MAXRAND; v[i] = 0.8 * LRAND() / MAXRAND + 0.2; /* Make sure that no two adjascent colors are *too* close together. If they are, try again. */ if (i > 0) { int j = (i + 1 == npoints) ? 0 : (i - 1); double hi = ((double) h[i]) / 360; double hj = ((double) h[j]) / 360; double dh = hj - hi; double distance; if (dh < 0) dh = -dh; if (dh > 0.5) dh = 0.5 - (dh - 0.5); distance = sqrt((dh * dh) + ((s[j] - s[i]) * (s[j] - s[i])) + ((v[j] - v[i]) * (v[j] - v[i]))); if (distance < 0.2) goto REPICK_THIS_COLOR; } total_s += s[i]; total_v += v[i]; } /* If the average saturation or intensity are too low, repick the colors, so that we don't end up with a black-and-white or too-dark map. */ if (total_s / npoints < 0.2) goto REPICK_ALL_COLORS; if (total_v / npoints < 0.3) goto REPICK_ALL_COLORS; /* If this visual doesn't support writable cells, don't bother trying. */ if (wanted_writable && !has_writable_cells(mi)) *writable_pP = False; RETRY_NON_WRITABLE: make_color_path(MI_DISPLAY(mi), cmap, npoints, h, s, v, colors, &ncolors, allocate_p, (writable_pP && *writable_pP)); /* If we tried for writable cells and got none, try for non-writable. */ if (allocate_p && *ncolorsP == 0 && *writable_pP) { *writable_pP = False; goto RETRY_NON_WRITABLE; } if (MI_IS_VERBOSE(mi) || MI_IS_DEBUG(mi)) complain(*ncolorsP, ncolors, wanted_writable, wanted_writable && *writable_pP); *ncolorsP = ncolors; }
void make_random_colormap(ModeInfo * mi, Colormap cmap, XColor * colors, int *ncolorsP, Bool bright_p, Bool allocate_p, Bool * writable_pP) { Bool wanted_writable = (allocate_p && writable_pP && *writable_pP); int ncolors = *ncolorsP; int i; if (*ncolorsP <= 0) return; /* If this visual doesn't support writable cells, don't bother trying. */ if (wanted_writable && !has_writable_cells(mi)) *writable_pP = False; for (i = 0; i < ncolors; i++) { colors[i].flags = DoRed | DoGreen | DoBlue; if (bright_p) { int H = (int) LRAND() % 360; /* range 0-360 */ double S = ((double) (LRAND() % 70) + 30) / 100.0; /* range 30%-100% */ double V = ((double) (LRAND() % 34) + 66) / 100.0; /* range 66%-100% */ hsv_to_rgb(H, S, V, &colors[i].red, &colors[i].green, &colors[i].blue); } else { colors[i].red = (unsigned short) (LRAND() % 0xFFFF); colors[i].green = (unsigned short) (LRAND() % 0xFFFF); colors[i].blue = (unsigned short) (LRAND() % 0xFFFF); } } if (!allocate_p) return; RETRY_NON_WRITABLE: if (writable_pP && *writable_pP) { unsigned long *pixels = (unsigned long *) malloc(sizeof (unsigned long) * (ncolors + 1)); allocate_writable_colors(MI_DISPLAY(mi), cmap, pixels, &ncolors); if (ncolors > 0) for (i = 0; i < ncolors; i++) colors[i].pixel = pixels[i]; free(pixels); if (ncolors > 0) XStoreColors(MI_DISPLAY(mi), cmap, colors, ncolors); } else { for (i = 0; i < ncolors; i++) { XColor color; color = colors[i]; if (!XAllocColor(MI_DISPLAY(mi), cmap, &color)) break; colors[i].pixel = color.pixel; } ncolors = i; } /* If we tried for writable cells and got none, try for non-writable. */ if (allocate_p && ncolors == 0 && writable_pP && *writable_pP) { ncolors = *ncolorsP; *writable_pP = False; goto RETRY_NON_WRITABLE; } if (MI_IS_VERBOSE(mi) || MI_IS_DEBUG(mi)) complain(*ncolorsP, ncolors, wanted_writable, wanted_writable && *writable_pP); *ncolorsP = ncolors; }
/* Called to init the mode. */ void init_penrose(ModeInfo * mi) { tiling_c *tp; fringe_node_c *fp; int i, size; if (tilings == NULL) { if ((tilings = (tiling_c *) calloc(MI_NUM_SCREENS(mi), sizeof (tiling_c))) == NULL) return; } tp = &tilings[MI_SCREEN(mi)]; if (MI_IS_FULLRANDOM(mi)) tp->ammann = (Bool) (LRAND() & 1); else tp->ammann = ammann; tp->done = False; tp->busyLoop = 0; tp->failures = 0; tp->width = MI_WIDTH(mi); tp->height = MI_HEIGHT(mi); if (MI_NPIXELS(mi) > 2) { tp->thick_color = NRAND(MI_NPIXELS(mi)); /* Insure good contrast */ tp->thin_color = (NRAND(2 * MI_NPIXELS(mi) / 3) + tp->thick_color + MI_NPIXELS(mi) / 6) % MI_NPIXELS(mi); } else { if (LRAND() & 1) { tp->thick_color = MI_WHITE_PIXEL(mi); tp->thin_color = MI_BLACK_PIXEL(mi); } else { tp->thick_color = MI_BLACK_PIXEL(mi); tp->thin_color = MI_WHITE_PIXEL(mi); } } size = MI_SIZE(mi); if (size < -MINSIZE) tp->edge_length = NRAND(MIN(-size, MAX(MINSIZE, MIN(tp->width, tp->height) / 2)) - MINSIZE + 1) + MINSIZE; else if (size < MINSIZE) { if (!size) tp->edge_length = MAX(MINSIZE, MIN(tp->width, tp->height) / 2); else tp->edge_length = MINSIZE; } else tp->edge_length = MIN(size, MAX(MINSIZE, MIN(tp->width, tp->height) / 2)); tp->origin.x = (tp->width / 2 + NRAND(tp->width)) / 2; tp->origin.y = (tp->height / 2 + NRAND(tp->height)) / 2; tp->fringe.n_nodes = 2; if (tp->fringe.nodes != NULL) free_penrose(tp); if (tp->fringe.nodes != NULL || tp->forced.first != 0) { if (MI_IS_VERBOSE(mi)) { (void) fprintf(stderr, "Weirdness in init_penrose()\n"); (void) fprintf(stderr, "tp->fringe.nodes = NULL && tp->forced.first = 0\n"); } free_penrose(tp); /* Try again */ tp->done = True; } tp->forced.n_nodes = tp->forced.n_visible = 0; if ((fp = tp->fringe.nodes = ALLOC_NODE(fringe_node_c)) == NULL) { free_penrose(tp); return; } if (fp == 0) { if (MI_IS_VERBOSE(mi)) { (void) fprintf(stderr, "Weirdness in init_penrose()\n"); (void) fprintf(stderr, "fp = 0\n"); } if ((fp = tp->fringe.nodes = ALLOC_NODE(fringe_node_c)) == NULL) { free_penrose(tp); return; } tp->done = True; } /* First vertex. */ fp->rule_mask = (1 << N_VERTEX_RULES) - 1; fp->list_ptr = 0; if ((fp->prev = fp->next = ALLOC_NODE(fringe_node_c)) == NULL) { free_penrose(tp); return; } if (fp->next == 0) { if (MI_IS_VERBOSE(mi)) { (void) fprintf(stderr, "Weirdness in init_penrose()\n"); (void) fprintf(stderr, "fp->next = 0\n"); } if ((fp->prev = fp->next = ALLOC_NODE(fringe_node_c)) == NULL) { free_penrose(tp); return; } tp->done = True; } fp->n_tiles = 0; fp->loc = tp->origin; fp->off_screen = False; for (i = 0; i < 5; i++) fp->fived[i] = 0; /* Second vertex. */ *(fp->next) = *fp; fp->next->prev = fp->next->next = fp; fp = fp->next; i = NRAND(5); fp->fived[i] = 2 * NRAND(2) - 1; fived_to_loc(fp->fived, tp, &(fp->loc)); /* That's it! We have created our first edge. */ }
void init_wire(ModeInfo * mi) { Display *display = MI_DISPLAY(mi); Window window = MI_WINDOW(mi); int i, size = MI_SIZE(mi), n; circuitstruct *wp; XGCValues gcv; if (circuits == NULL) { if ((circuits = (circuitstruct *) calloc(MI_NUM_SCREENS(mi), sizeof (circuitstruct))) == NULL) return; } wp = &circuits[MI_SCREEN(mi)]; wp->redrawing = 0; if ((MI_NPIXELS(mi) <= 2) && (wp->init_bits == 0)) { if (wp->stippledGC == None) { gcv.fill_style = FillOpaqueStippled; if ((wp->stippledGC = XCreateGC(display, window, GCFillStyle, &gcv)) == None) { free_wire(display, wp); return; } } WIREBITS(stipples[NUMSTIPPLES - 1], STIPPLESIZE, STIPPLESIZE); WIREBITS(stipples[NUMSTIPPLES - 3], STIPPLESIZE, STIPPLESIZE); WIREBITS(stipples[2], STIPPLESIZE, STIPPLESIZE); } if (MI_NPIXELS(mi) > 2) { wp->colors[0] = (NRAND(MI_NPIXELS(mi))); wp->colors[1] = (wp->colors[0] + MI_NPIXELS(mi) / 6 + NRAND(MI_NPIXELS(mi) / 4 + 1)) % MI_NPIXELS(mi); wp->colors[2] = (wp->colors[1] + MI_NPIXELS(mi) / 6 + NRAND(MI_NPIXELS(mi) / 4 + 1)) % MI_NPIXELS(mi); } free_list(wp); wp->generation = 0; if (MI_IS_FULLRANDOM(mi)) { wp->vertical = (Bool) (LRAND() & 1); } else { wp->vertical = vertical; } wp->width = MI_WIDTH(mi); wp->height = MI_HEIGHT(mi); for (i = 0; i < NEIGHBORKINDS; i++) { if (neighbors == plots[i]) { wp->neighbors = plots[i]; break; } if (i == NEIGHBORKINDS - 1) { i = NRAND(NEIGHBORKINDS - 3) + 1; /* Skip triangular ones */ wp->neighbors = plots[i]; break; } } wp->prob_array[wp->neighbors - 1] = 100; if (wp->neighbors == 3) { wp->prob_array[1] = 67; wp->prob_array[0] = 33; } else { int incr = 24 / wp->neighbors; for (i = wp->neighbors - 2; i >= 0; i--) { wp->prob_array[i] = wp->prob_array[i + 1] - incr - incr * ((i + 1) != wp->neighbors / 2); } } if (wp->neighbors == 6) { int nccols, ncrows; wp->polygon = 6; if (!wp->vertical) { wp->height = MI_WIDTH(mi); wp->width = MI_HEIGHT(mi); } if (wp->width < 8) wp->width = 8; if (wp->height < 8) wp->height = 8; if (size < -MINSIZE) wp->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(wp->width, wp->height) / MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE; else if (size < MINSIZE) { if (!size) wp->ys = MAX(MINSIZE, MIN(wp->width, wp->height) / MINGRIDSIZE); else wp->ys = MINSIZE; } else wp->ys = MIN(size, MAX(MINSIZE, MIN(wp->width, wp->height) / MINGRIDSIZE)); wp->xs = wp->ys; nccols = MAX(wp->width / wp->xs - 2, 16); ncrows = MAX(wp->height / wp->ys - 1, 16); wp->ncols = nccols / 2; wp->nrows = ncrows / 2; wp->nrows -= !(wp->nrows & 1); /* Must be odd */ wp->xb = (wp->width - wp->xs * nccols) / 2 + wp->xs; wp->yb = (wp->height - wp->ys * ncrows) / 2 + wp->ys; for (i = 0; i < 6; i++) { if (wp->vertical) { wp->shape.hexagon[i].x = (wp->xs - 1) * hexagonUnit[i].x; wp->shape.hexagon[i].y = ((wp->ys - 1) * hexagonUnit[i].y / 2) * 4 / 3; } else { wp->shape.hexagon[i].y = (wp->xs - 1) * hexagonUnit[i].x; wp->shape.hexagon[i].x = ((wp->ys - 1) * hexagonUnit[i].y / 2) * 4 / 3; } } } else if (wp->neighbors == 4 || wp->neighbors == 8) { wp->polygon = 4; if (size < -MINSIZE) wp->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(wp->width, wp->height) / MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE; else if (size < MINSIZE) { if (!size) wp->ys = MAX(MINSIZE, MIN(wp->width, wp->height) / MINGRIDSIZE); else wp->ys = MINSIZE; } else wp->ys = MIN(size, MAX(MINSIZE, MIN(wp->width, wp->height) / MINGRIDSIZE)); wp->xs = wp->ys; wp->ncols = MAX(wp->width / wp->xs, 8); wp->nrows = MAX(wp->height / wp->ys, 8); wp->xb = (wp->width - wp->xs * wp->ncols) / 2; wp->yb = (wp->height - wp->ys * wp->nrows) / 2; } else { /* TRI */ int orient; wp->polygon = 3; if (!wp->vertical) { wp->height = MI_WIDTH(mi); wp->width = MI_HEIGHT(mi); } if (wp->width < 4) wp->width = 4; if (wp->height < 2) wp->height = 2; if (size < -MINSIZE) wp->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(wp->width, wp->height) / MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE; else if (size < MINSIZE) { if (!size) wp->ys = MAX(MINSIZE, MIN(wp->width, wp->height) / MINGRIDSIZE); else wp->ys = MINSIZE; } else wp->ys = MIN(size, MAX(MINSIZE, MIN(wp->width, wp->height) / MINGRIDSIZE)); wp->xs = (int) (1.52 * wp->ys); wp->ncols = (MAX(wp->width / wp->xs - 1, 8) / 2) * 2; wp->nrows = (MAX(wp->height / wp->ys - 1, 8) / 2) * 2 - 1; wp->xb = (wp->width - wp->xs * wp->ncols) / 2 + wp->xs / 2; wp->yb = (wp->height - wp->ys * wp->nrows) / 2 + wp->ys; for (orient = 0; orient < 2; orient++) { for (i = 0; i < 3; i++) { if (wp->vertical) { wp->shape.triangle[orient][i].x = (wp->xs - 2) * triangleUnit[orient][i].x; wp->shape.triangle[orient][i].y = (wp->ys - 2) * triangleUnit[orient][i].y; } else { wp->shape.triangle[orient][i].y = (wp->xs - 2) * triangleUnit[orient][i].x; wp->shape.triangle[orient][i].x = (wp->ys - 2) * triangleUnit[orient][i].y; } } } } /* * I am being a bit naughty here wasting a little bit of memory * but it will give me a real headache to figure out the logic * and to refigure the mappings to save a few bytes * ncols should only need a border of 2 and nrows should only need * a border of 4 when in the neighbors = 9 or 12 */ wp->bncols = wp->ncols + 4; wp->bnrows = wp->nrows + 4; if (MI_IS_VERBOSE(mi)) (void) fprintf(stdout, "neighbors %d, ncols %d, nrows %d\n", wp->neighbors, wp->ncols, wp->nrows); MI_CLEARWINDOW(mi); if (wp->oldcells != NULL) { free(wp->oldcells); wp->oldcells = (unsigned char *) NULL; } if ((wp->oldcells = (unsigned char *) calloc(wp->bncols * wp->bnrows, sizeof (unsigned char))) == NULL) { free_wire(display, wp); return; } if (wp->newcells != NULL) { free(wp->newcells); wp->newcells = (unsigned char *) NULL; } if ((wp->newcells = (unsigned char *) calloc(wp->bncols * wp->bnrows, sizeof (unsigned char))) == NULL) { free_wire(display, wp); return; } n = MI_COUNT(mi); i = (1 + (wp->neighbors == 6)) * wp->ncols * wp->nrows / 4; if (n < -MINWIRES && i > MINWIRES) { n = NRAND(MIN(-n, i) - MINWIRES + 1) + MINWIRES; } else if (n < MINWIRES) { n = MINWIRES; } else if (n > i) { n = MAX(MINWIRES, i); } create_path(wp, n); }
/*- * Add a randomly chosen tile to a given vertex. This requires more checking * as we must make sure the new tile conforms to the vertex rules at every * vertex it touches. */ static void add_random_tile(fringe_node_c * vertex, ModeInfo * mi) { fringe_node_c *right, *left, *far; int i, j, n, n_hits, n_good; unsigned side, fc, no_good, s; vertex_type_c vtypes[MAX_COMPL]; rule_match_c hits[MAX_TILES_PER_VERTEX * N_VERTEX_RULES]; tiling_c *tp = &tilings[MI_SCREEN(mi)]; if (MI_NPIXELS(mi) > 2) { tp->thick_color = NRAND(MI_NPIXELS(mi)); /* Insure good contrast */ tp->thin_color = (NRAND(2 * MI_NPIXELS(mi) / 3) + tp->thick_color + MI_NPIXELS(mi) / 6) % MI_NPIXELS(mi); } else { unsigned long temp = tp->thick_color; tp->thick_color = tp->thin_color; tp->thin_color = temp; } n_hits = match_rules(vertex, hits, False); side = NRAND(2) ? S_LEFT : S_RIGHT; n = find_completions(vertex, hits, n_hits, side, vtypes /*, False */ ); /* One answer would mean a forced tile. */ if (n <= 0) { tp->done = True; if (MI_IS_VERBOSE(mi)) { (void) fprintf(stderr, "Weirdness in add_random_tile()\n"); (void) fprintf(stderr, "n = %d\n", n); } } no_good = 0; n_good = n; for (i = 0; i < n; i++) { fc = fringe_changes(mi, vertex, side, vtypes[i], &right, &far, &left); if (fc & FC_BAG) { tp->done = True; if (MI_IS_VERBOSE(mi)) { (void) fprintf(stderr, "Weirdness in add_random_tile()\n"); (void) fprintf(stderr, "fc = %d, FC_BAG = %d\n", fc, FC_BAG); } } if (right) { s = (((fc & FC_CUT_FAR) && (fc & FC_CUT_LEFT)) ? S_RIGHT : S_LEFT); if (!legal_move(right, s, VT_RIGHT(vtypes[i]))) { no_good |= (1 << i); n_good--; continue; } } if (left) { s = (((fc & FC_CUT_FAR) && (fc & FC_CUT_RIGHT)) ? S_LEFT : S_RIGHT); if (!legal_move(left, s, VT_LEFT(vtypes[i]))) { no_good |= (1 << i); n_good--; continue; } } if (far) { s = ((fc & FC_CUT_LEFT) ? S_RIGHT : S_LEFT); if (!legal_move(far, s, VT_FAR(vtypes[i]))) { no_good |= (1 << i); n_good--; } } } if (n_good <= 0) { tp->done = True; if (MI_IS_VERBOSE(mi)) { (void) fprintf(stderr, "Weirdness in add_random_tile()\n"); (void) fprintf(stderr, "n_good = %d\n", n_good); } } n = NRAND(n_good); for (i = j = 0; i <= n; i++, j++) while (no_good & (1 << j)) j++; if (!add_tile(mi, vertex, side, vtypes[j - 1])) { tp->done = True; if (MI_IS_VERBOSE(mi)) { (void) fprintf(stderr, "Weirdness in add_random_tile()\n"); } free_penrose(tp); } }
ENTRYPOINT void init_flow (ModeInfo * mi) { flowstruct *sp; char *name; if (flows == NULL) { if ((flows = (flowstruct *) calloc(MI_NUM_SCREENS(mi), sizeof (flowstruct))) == NULL) return; } sp = &flows[MI_SCREEN(mi)]; sp->count2 = 0; sp->taillen = MI_SIZE(mi); if (sp->taillen < -MINTRAIL) { /* Change by sqrt so it seems more variable */ sp->taillen = NRAND((int)sqrt((double) (-sp->taillen - MINTRAIL + 1))); sp->taillen = sp->taillen * sp->taillen + MINTRAIL; } else if (sp->taillen < MINTRAIL) { sp->taillen = MINTRAIL; } if(!rotatep && !ridep) rotatep = True; /* We need at least one viewpoint */ /* Start camera at Orbit or Bee */ if(rotatep) { sp->chaseto = ORBIT; } else { sp->chaseto = BEE; } sp->chasetime = 1; /* Go directly to target */ sp->lyap = 0; sp->yperiod = 0; sp->step2 = INITIALSTEP; /* Zero parameter set */ memset(sp->par2, 0, N_PARS * sizeof(dvector)); /* Set up standard examples */ switch (NRAND((periodicp) ? 5 : 3)) { case 0: /* x' = a(y - x) y' = x(b - z) - y z' = xy - cz */ name = "Lorentz"; sp->par2[Y].x = 10 + balance_rand(5*0); /* a */ sp->par2[X].x = - sp->par2[Y].x; /* -a */ sp->par2[X].y = 28 + balance_rand(5*0); /* b */ sp->par2[XZ].y = -1; sp->par2[Y].y = -1; sp->par2[XY].z = 1; sp->par2[Z].z = - 2 + balance_rand(1*0); /* -c */ break; case 1: /* x' = -(y + az) y' = x + by z' = c + z(x - 5.7) */ name = "Rossler"; sp->par2[Y].x = -1; sp->par2[Z].x = -2 + balance_rand(1); /* a */ sp->par2[X].y = 1; sp->par2[Y].y = 0.2 + balance_rand(0.1); /* b */ sp->par2[C].z = 0.2 + balance_rand(0.1); /* c */ sp->par2[XZ].z = 1; sp->par2[Z].z = -5.7; break; case 2: /* x' = -(y + az) y' = x + by - cz^2 z' = 0.2 + z(x - 5.7) */ name = "RosslerCone"; sp->par2[Y].x = -1; sp->par2[Z].x = -2; /* a */ sp->par2[X].y = 1; sp->par2[Y].y = 0.2; /* b */ sp->par2[ZZ].y = -0.331 + balance_rand(0.01); /* c */ sp->par2[C].z = 0.2; sp->par2[XZ].z = 1; sp->par2[Z].z = -5.7; break; case 3: /* x' = -z + b sin(y) y' = c z' = 0.7x + az(0.1 - x^2) */ name = "Birkhoff"; sp->par2[Z].x = -1; sp->par2[SINY].x = 0.35 + balance_rand(0.25); /* b */ sp->par2[C].y = 1.57; /* c */ sp->par2[X].z = 0.7; sp->par2[Z].z = 1 + balance_rand(0.5); /* a/10 */ sp->par2[XXZ].z = -10 * sp->par2[Z].z; /* -a */ sp->yperiod = 2 * M_PI; break; default: /* x' = -ax - z/2 - z^3/8 + b sin(y) y' = c z' = 2x */ name = "Duffing"; sp->par2[X].x = -0.2 + balance_rand(0.1); /* a */ sp->par2[Z].x = -0.5; sp->par2[ZZZ].x = -0.125; sp->par2[SINY].x = 27.0 + balance_rand(3.0); /* b */ sp->par2[C].y = 1.33; /* c */ sp->par2[X].z = 2; sp->yperiod = 2 * M_PI; break; } sp->range.x = 5; sp->range.z = 5; if(sp->yperiod > 0) { sp->ODE = Periodic; /* periodic flows show either uniform distribution or a snapshot on the 'time' axis */ sp->range.y = NRAND(2)? sp->yperiod : 0; } else { sp->range.y = 5; sp->ODE = Cubic; } /* Run discoverer to set up bounding box, etc. Lyapunov will probably be innaccurate, since we're only running it once, but we're using known strange attractors so it should be ok. */ discover(mi); if(MI_IS_VERBOSE(mi)) fprintf(stdout, "flow: Lyapunov exponent: %g, step: %g, size: %g (%s)\n", sp->lyap2, sp->step2, sp->size2, name); /* Install new params */ sp->lyap = sp->lyap2; sp->size = sp->size2; sp->mid = sp->mid2; sp->step = sp->step2; memcpy(sp->par, sp->par2, sizeof(sp->par2)); sp->count2 = 0; /* Reset search */ free_flow(sp); sp->beecount = MI_COUNT(mi); if (sp->beecount < 0) { /* random variations */ sp->beecount = NRAND(-sp->beecount) + 1; /* Minimum 1 */ } # ifdef HAVE_COCOA /* Don't second-guess Quartz's double-buffering */ dbufp = False; # endif if(dbufp) { /* Set up double buffer */ if (sp->buffer != None) XFreePixmap(MI_DISPLAY(mi), sp->buffer); sp->buffer = XCreatePixmap(MI_DISPLAY(mi), MI_WINDOW(mi), MI_WIDTH(mi), MI_HEIGHT(mi), MI_DEPTH(mi)); } else { sp->buffer = MI_WINDOW(mi); } /* no "NoExpose" events from XCopyArea wanted */ XSetGraphicsExposures(MI_DISPLAY(mi), MI_GC(mi), False); /* Make sure we're using 'thin' lines */ XSetLineAttributes(MI_DISPLAY(mi), MI_GC(mi), 0, LineSolid, CapNotLast, JoinMiter); /* Clear the background (may be slow depending on user prefs). */ MI_CLEARWINDOW(mi); /* Allocate memory. */ if (sp->csegs == NULL) { allocate(sp->csegs, XSegment, (sp->beecount + BOX_L) * MI_NPIXELS(mi) * sp->taillen); allocate(sp->cnsegs, int, MI_NPIXELS(mi)); allocate(sp->old_segs, XSegment, sp->beecount * sp->taillen); allocate(sp->p, dvector, sp->beecount * sp->taillen); }
void draw_goop(ModeInfo * mi) { Display *display = MI_DISPLAY(mi); Window window = MI_WINDOW(mi); int i; goopstruct *gp; if (goops == NULL) return; gp = &goops[MI_SCREEN(mi)]; if (gp->layers == NULL) return; MI_IS_DRAWN(mi) = True; switch (gp->mode) { case transparent: for (i = 0; i < gp->nlayers; i++) draw_layer_plane(display, &(gp->layers[i]), gp->width, gp->height); XSetForeground(display, gp->pixmap_gc, gp->background); XSetPlaneMask(display, gp->pixmap_gc, AllPlanes); XFillRectangle(display, gp->pixmap, gp->pixmap_gc, 0, 0, gp->width, gp->height); XSetForeground(display, gp->pixmap_gc, ~0L); for (i = 0; i < gp->nlayers; i++) { XSetPlaneMask(display, gp->pixmap_gc, gp->layers[i].pixel); #if 0 XSetForeground (display, gp->pixmap_gc, ~0L); XFillRectangle (display, gp->pixmap, gp->pixmap_gc, 0, 0, gp->width, gp->height); XSetForeground (display, gp->pixmap_gc, 0L); #endif draw_layer_blobs(display, gp->pixmap, gp->pixmap_gc, &(gp->layers[i]), gp->width, gp->height, True); } XCopyArea(display, gp->pixmap, window, MI_GC(mi), 0, 0, gp->width, gp->height, 0, 0); break; case xored: XSetFunction(display, gp->pixmap_gc, GXcopy); XSetForeground(display, gp->pixmap_gc, 0); XFillRectangle(display, gp->pixmap, gp->pixmap_gc, 0, 0, gp->width, gp->height); XSetFunction(display, gp->pixmap_gc, GXxor); XSetForeground(display, gp->pixmap_gc, 1); for (i = 0; i < gp->nlayers; i++) draw_layer_blobs(display, gp->pixmap, gp->pixmap_gc, &(gp->layers[i]), gp->width, gp->height, (gp->mode != outline)); XCopyPlane(display, gp->pixmap, window, MI_GC(mi), 0, 0, gp->width, gp->height, 0, 0, 1L); break; case opaque: case outline: XSetForeground(display, gp->pixmap_gc, MI_BLACK_PIXEL(mi)); XFillRectangle(display, gp->pixmap, gp->pixmap_gc, 0, 0, gp->width, gp->height); for (i = 0; i < gp->nlayers; i++) { XSetForeground(display, gp->pixmap_gc, gp->layers[i].pixel); draw_layer_blobs(display, gp->pixmap, gp->pixmap_gc, &(gp->layers[i]), gp->width, gp->height, (gp->mode != outline)); } XCopyArea(display, gp->pixmap, window, MI_GC(mi), 0, 0, gp->width, gp->height, 0, 0); break; default: if (MI_IS_VERBOSE(mi)) { (void) fprintf(stderr, "Weirdness in draw_goop()\n"); (void) fprintf(stderr, "gp->mode = %d\n", gp->mode); } break; } }