/* This file was taken from XaoS-the fast portable realtime interactive fractal zoomer. but it is simplified for BB. You may get complette sources at XaoS homepage (http://www.paru.cas.cz/~hubicka/XaoS */ /* * XaoS, a fast portable realtime fractal zoomer * Copyright (C) 1996 by * * Jan Hubicka (hubicka@paru.cas.cz) * Thomas Marsh (tmarsh@austin.ibm.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifdef _plan9_ #include #include #include #else #ifdef __DJGPP__ #include "aconfig.dos" #else #include "aconfig.h" #endif #include #include #include #include #include #ifdef HAVE_UNISTD_H #include #endif #include #endif #include "config.h" #ifndef _plan9_ #include #endif #include "bb.h" #include "zoom.h" #include "autopilo.h" #include "complex.h" #include "ui.h" #include "timers.h" #define ETIME1 (25*1000000+150000) #define ETIME2 (2*1000000) #define VBUFF (zcontext->stereogram?zcontext->svbuff:zcontext->vbuff) #define BACK (zcontext->stereogram?zcontext->sback:zcontext->back) #define SIZE 1024 #define add_buffer(char) if(((end+1)%SIZE)!=begin) {keybuffer[end]=char;end=(end+1)%SIZE;} #define INTERRUPTIBLE 0 #define ANIMATION 1 #define NEW_IMAGE 2 #define UNINTERRUPTIBLE 3 #define xstoc(x) (((number_t) (zcontext->s.nc + (x) * ((zcontext->s.mc - zcontext->s.nc) \ / (number_t) zcontext->width)))) #define ystoc(y) (((number_t) (zcontext->s.ni + (y) * ((zcontext->s.mi - zcontext->s.ni) \ / (number_t) zcontext->height)))) #define FRAMETIME (1000000/FRAMERATE) #define FORMULA 0 #define HELP 1 #define DRIVER 2 #define MENU 3 static tl_timer *maintimer /*, *rotatetimer */ ; static void ui_do_fractal(int); static int displayed; static int ui_autopilot(void); static int incalculation; static int fastmode = 2; static int interruptiblemode; static int autopilot = 0; static double maxstep = MAXSTEP, speedup = STEP; static zoom_context *zcontext; static double mul; static int drawingtime, tbreak = 0; static void ui_display(void) { displayed = 1; aa_render(context, params, 0, 0, aa_imgwidth(context), aa_imgheight(context)); aa_flush(context); #if 0 if (numbertype != FORMULA) rotate_continue(); #endif } static int waitcount; static int waitcount1; static int starttime1; static int endtime1; static int maxtime = 1000000 / 10; #define WAITTIME 200000 #define WAITTIME1 2000000 static void ui_waitfunc(void) { int l; bbupdate(); tl_process_group(syncgroup, NULL); l = tl_lookup_timer(maintimer); if (interruptiblemode) { if (zcontext->incalculation && !starttime1) starttime1 = l; else if (starttime1 && !zcontext->incalculation && !endtime1) endtime1 = l; if (maxtime && l > maxtime && zcontext->readyforinterrupt) zcontext->interrupt = 1, endtime1 = l; } } static float get_pixelwidth(int width) { return (aa_mmwidth(context)); } static float get_pixelheight(int height) { return (aa_mmheight(context)); } #ifdef _RED_ static void rotate_off(void) { if (rotate) { tl_free_timer(rotatetimer); rotate = 0; } } static void rotate_stop(void) { if (rotate && !stopped) { tl_remove_timer(rotatetimer); stopped = 1; } } static void rotate_continue(void) { if (rotate && stopped) { stopped = 0; if (driver->flags & ASYNC_PALETTE) { tl_add_timer(asyncgroup, rotatetimer); } else tl_add_timer(syncgroup, rotatetimer); } } static void rotatehandler(int n) { int direct; direct = direction * n; if (direction > 0) direction %= zcontext->num_colors - 1; else direction = -((-direction) % (zcontext->num_colors - 1)); if (!direction) return; rotated = 1; rotate_palette(zcontext, direction * n); driver->rotate_palette(direction * n); if (ministatus && (driver->flags & PALETTE_REDISPLAYS)) { driver->print(0, 0, statustext); } } static void rotate_update(void) { if (rotationspeed < 0) direction = -1; else direction = 1; tl_set_interval(rotatetimer, 1000000 / rotationspeed * direction); } static void rotate_on(void) { if (driver->rotate_palette != NULL && (driver->flags & PALETTE_ROTATION)) { rotate = 1; rotatetimer = tl_create_timer(); rotate_update(); tl_set_multihandler(rotatetimer, rotatehandler); if (driver->flags & ASYNC_PALETTE) { tl_add_timer(asyncgroup, rotatetimer); } else tl_add_timer(syncgroup, rotatetimer); } else { driver->print(0, 0, "Rotating of palette not supported by this configuration"); } } #endif static char zoomed[256]; static void updatestatus(void) { double times = (zcontext->currentformula->v.mc - zcontext->currentformula->v.nc) / (zcontext->s.mc - zcontext->s.nc); ui_display(); sprintf(zoomed, "%.2f", times); tl_process_group(syncgroup, NULL); bbupdate(); drawingtime = tl_lookup_timer(maintimer); tl_reset_timer(maintimer); if (drawingtime > 200000) drawingtime = 200000; mul = (double) drawingtime / FRAMETIME; incalculation = 0; } static void ui_do_julia(double xx, double yy) { int oldw = zcontext->width, oldh = zcontext->height; float size; unsigned char *vold = zcontext->vbuff; incalculation = 1; zcontext->pre = xx, zcontext->pim = yy; if (zcontext->windowwidth > zcontext->windowheight) size = zcontext->windowheight; else size = zcontext->windowwidth; zcontext->width = zcontext->width * size / zcontext->windowwidth - 1; zcontext->height = zcontext->height * size / zcontext->windowheight - 1; if (!dual) zcontext->vbuff += (oldw - zcontext->width) / 2; else zcontext->vbuff += (oldw / 2 - zcontext->width) / 2; do_julia(zcontext, zcontext->pre, zcontext->pim); if (dual) { zcontext->currentformula = formulas + 1; zcontext->vbuff += aa_imgwidth(context) / 2; do_julia(zcontext, zcontext->pre, zcontext->pim); zcontext->currentformula = formulas; } zcontext->width = oldw; zcontext->height = oldh; zcontext->vbuff = vold; ui_display(); } static void ui_do_fractal(int mode) { int time, time1; if (mode < fastmode + 1) interruptiblemode = 1; else interruptiblemode = 0; if (tbreak) tl_reset_timer(maintimer); incalculation = 1; starttime1 = 0; endtime1 = 0; set_view(zcontext, &zcontext->s); waitcount = tl_lookup_timer(maintimer) / WAITTIME + 2; waitcount1 = tl_lookup_timer(maintimer) / WAITTIME1 + 1; do_fractal(zcontext, interruptiblemode); bbupdate(); if (interruptiblemode) { bbupdate(); time1 = time = tl_lookup_timer(maintimer); time -= endtime1 - starttime1; maxtime = time * 5; if (maxtime > 1000000 / 10) maxtime = time * 3; if (maxtime < 1000000 / 30) maxtime = 1000000 / 30; maxtime -= time1 - endtime1; } updatestatus(); } static double step = 0; void ui_tbreak(void) { tbreak = 2; } static int ui_autopilot(void) { clean_autopilot(); return (autopilot ^= 1); } static void ui_changed(void) { ui_tbreak(); } static int ui_mouse() { int mousex = 0; int mousey = 0; int mousebuttons = 0; int inmovement = 0, slowdown = 1; static double autopilot_counter = 0; static number_t oldx = 0, oldy = 0; static int dirty = 0; static int pressed; if (tbreak) mul = 1.0; if (dirty) ui_do_fractal(NEW_IMAGE), ui_tbreak(), dirty = 0; if (autopilot) { static int mousex1, mousey1, mousebuttons1; autopilot_counter += mul; while (autopilot_counter > 1) { do_autopilot(zcontext, &mousex1, &mousey1, &mousebuttons1, ui_changed); autopilot_counter--; } mousex = mousex1, mousey = mousey1, mousebuttons = mousebuttons1; } if (tbreak) mul = 1; if (mul == 0) mul = 0.001; if (mousebuttons > 0) { switch (mousebuttons) { case BUTTON1: /* button 1 */ step -= speedup * 2 * mul, slowdown = 0; inmovement = 1; break; case BUTTON3: /* button 3 */ step += speedup * 2 * mul, slowdown = 0; inmovement = 1; break; case BUTTON2: /* button 2 */ { number_t x = xstoc(mousex), y = ystoc(mousey); if (pressed && (oldx != x || oldy != y)) { zcontext->s.nc -= x - oldx; zcontext->s.mc -= x - oldx; zcontext->s.ni -= y - oldy; zcontext->s.mi -= y - oldy; if (!step) { ui_do_fractal(ANIMATION), ui_tbreak(); } } pressed = 1; oldx = xstoc(mousex), oldy = ystoc(mousey); } break; default: break; } } if (!(mousebuttons & BUTTON2)) pressed = 0; if (slowdown) { if (step > 0) { if (step < speedup * mul) step = 0; else step -= speedup * mul; } else if (step < 0) { if (step > -speedup * mul) step = 0; else step += speedup * mul; } } if (step > maxstep) step = maxstep; else if (step < -maxstep) step = -maxstep; if (step) { number_t x = xstoc(mousex); number_t y = ystoc(mousey); number_t mmul = pow((double) (1 + step), (double) mul); zcontext->s.mc = x + (zcontext->s.mc - x) * (mmul); zcontext->s.nc = x + (zcontext->s.nc - x) * (mmul); zcontext->s.mi = y + (zcontext->s.mi - y) * (mmul); zcontext->s.ni = y + (zcontext->s.ni - y) * (mmul); inmovement = 1; ui_do_fractal(ANIMATION); if (tbreak) tbreak--; } if (!inmovement) ui_tbreak(); return (1); } #define BTIME 200000 #define BTIME1 1000000 static void main_loop(void) { int inmovement = 1; while (TIME < endtime && !finish_stuff) { if (TIME < starttime + BTIME) { params->bright = 255 - (TIME - starttime) * 255 / BTIME; } else params->bright = 0; if (TIME > endtime - BTIME1) { params->bright = -255 + (endtime - TIME) * 255 / BTIME1; } if (zcontext->uncomplette) { inmovement = 1; if (!displayed) ui_do_fractal(ANIMATION); } displayed = 0; inmovement = ui_mouse(); } } static void flip_buffers(void) { context->imagebuffer = zcontext->back; } static int sef, eef; static double is, ie, rs, re; static void juliov(void) { double time = (TIME - starttime) / (double) (endtime - starttime); if (sef) { if (TIME < starttime + BTIME) { params->bright = 255 - (TIME - starttime) * 255 / BTIME; } else params->bright = 0; } if (eef) { if (TIME > endtime - BTIME) { params->bright = -255 + (endtime - TIME) * 255 / BTIME; } } ui_do_julia(rs + (re - rs) * time, is + (ie - is) * time); } static void mydraw() { clrscr(); dvojprujezd(starttime, zoomed, "Times"); } static void mydraw1() { clrscr(); drawlepic("Zoomed"); } void scene6(void) { int width, height, scanline; int i, formula = 0; char *buffer1, *buffer2; displayed = 0; incalculation = 0; fastmode = 2; interruptiblemode = 0; autopilot = 0; maxstep = MAXSTEP; speedup = STEP; step = 0; tbreak = 0; maintimer = tl_create_timer(); signal(SIGFPE, SIG_IGN); width = aa_imgwidth(context); height = aa_imgheight(context); scanline = width; buffer1 = context->imagebuffer; buffer2 = malloc(width * height); endtime = starttime + ETIME1; params->bright = -255; zcontext = make_context(width, height, scanline, 0, 1, flip_buffers, ui_waitfunc, buffer1, buffer2, get_pixelwidth(width), get_pixelheight(height)); if (!zcontext) { exit(-1); } set_formula(zcontext, formula); for (i = 0; i < 255; i++) { /*zcontext->colors[i] = (i * 15) % 255 + 1; */ zcontext->colors[i] = (i * 8) % 255 + 1; } zcontext->colors[0] = 0; zcontext->num_colors = 255; tbreak = 2; zcontext->maxiter = 150; fastmode--; zcontext->range = 8; zcontext->incoloringmode = 0; zcontext->coloringmode = 0; zcontext->plane = 0; ui_do_fractal(NEW_IMAGE); ui_autopilot(); speedup = 1 * STEP; maxstep *= 5; step = -maxstep; tl_process_group(syncgroup, NULL); bbupdate(); tl_reset_timer(maintimer); main_loop(); starttime = endtime; context->imagebuffer = buffer1; free(buffer2); tl_free_timer(maintimer); params->bright = 0; params->randomval = 0; initlepic(); drawptr = mydraw1; timestuff(-60, ctrllepic, draw, 2000000); drawptr = mydraw; /*timestuff(60, NULL, draw, 4 * 1000000); */ /*timestuff(20, blur, draw, 4 * 1000000); */ timestuff(60, NULL, draw, 3 * 1000000); } void scene7(void) { int width, height, scanline; int i, formula = 0; char *buffer1; signal(SIGFPE, SIG_IGN); width = aa_imgwidth(context); height = aa_imgheight(context); scanline = width; buffer1 = context->imagebuffer; params->bright = -255; params->dither = AA_NONE; zcontext = make_context(width, height, scanline, 0, 1, flip_buffers, ui_waitfunc, buffer1, buffer1, get_pixelwidth(width), get_pixelheight(height)); if (!zcontext) { exit(-1); } set_formula(zcontext, formula); for (i = 0; i < 255; i++) { zcontext->colors[i] = (i * 15) % 255 + 1; } zcontext->colors[0] = 0; zcontext->num_colors = 255; tbreak = 2; zcontext->maxiter = 255; fastmode--; zcontext->range = 8; zcontext->incoloringmode = 0; zcontext->coloringmode = 0; zcontext->plane = 0; starttime = endtime; sef = 1; eef = 0; is = -2; rs = -2; ie = 2; re = 2; timestuff(0, NULL, juliov, ETIME2); sef = 0; eef = 0; is = 2; rs = 2; ie = 0; re = -2; timestuff(0, NULL, juliov, ETIME2); sef = 0; eef = 0; is = 0; rs = -2; ie = 0; re = 2; timestuff(0, NULL, juliov, ETIME2); sef = 0; eef = 1; is = 0; rs = 2; ie = -1; re = -5.0; timestuff(0, NULL, juliov, ETIME2); context->imagebuffer = buffer1; params->bright = 0; params->dither = AA_FLOYD_S; } #if 0 void scene9(void) { int width, height, scanline; int i, formula = 1; char *buffer1; signal(SIGFPE, SIG_IGN); width = aa_imgwidth(context); height = aa_imgheight(context); scanline = width; buffer1 = context->imagebuffer; params->bright = -255; params->dither = AA_NONE; zcontext = make_context(width, height, scanline, 0, 1, flip_buffers, ui_waitfunc, buffer1, buffer1, get_pixelwidth(width), get_pixelheight(height)); if (!zcontext) { exit(-1); } set_formula(zcontext, formula); for (i = 0; i < 255; i++) { zcontext->colors[i] = (i * 15) % 255 + 1; } zcontext->colors[0] = 0; zcontext->num_colors = 255; tbreak = 2; zcontext->maxiter = 255; fastmode--; zcontext->range = 8; zcontext->incoloringmode = 0; zcontext->coloringmode = 0; zcontext->plane = 0; starttime = endtime; sef = 1; eef = 0; is = -1; rs = -1; ie = 2; re = -2; timestuff(0, NULL, juliov, ETIME2); sef = 0; eef = 0; is = ie, rs = re; ie = 2; re = 2; timestuff(0, NULL, juliov, ETIME2); sef = 0; eef = 0; is = ie, rs = re; ie = -2; re = 2; timestuff(0, NULL, juliov, ETIME2); sef = 0; eef = 1; is = ie, rs = re; ie = 2; re = -2; timestuff(0, NULL, juliov, ETIME2); context->imagebuffer = buffer1; params->bright = 0; params->dither = AA_FLOYD_S; } #endif