From b622d928912018951b333d6f7e002fa83a71d3cd Mon Sep 17 00:00:00 2001 From: aiju Date: Fri, 16 Sep 2011 13:32:48 +0200 Subject: [PATCH] added games/mandel --- sys/src/games/mandel.c | 238 +++++++++++++++++++++++++++++++++++++++++ sys/src/games/mkfile | 1 + 2 files changed, 239 insertions(+) create mode 100644 sys/src/games/mandel.c diff --git a/sys/src/games/mandel.c b/sys/src/games/mandel.c new file mode 100644 index 000000000..f574c0330 --- /dev/null +++ b/sys/src/games/mandel.c @@ -0,0 +1,238 @@ +#include +#include +#include +#include +#include +#include + +enum { ncolors = 600 }; + +double xmin = -2, xmax = 1; +double ymin = -1, ymax = 1; +Mousectl *mctl; +Rendez rend; +int stopdraw; +uchar *imagedata; +Image *image; +extern Cursor reading; +uchar colors[3 * (ncolors + 1)]; + +double +convx(Rectangle *r, int x) +{ + return (xmax - xmin) * (x - r->min.x) / (r->max.x - r->min.x) + xmin; +} + +double +convy(Rectangle *r, int y) +{ + return (ymax - ymin) * (r->max.y - y) / (r->max.y - r->min.y) + ymin; +} + +void +pixel(int x, int y) +{ + draw(screen, Rect(x, y, x + 1, y + 1), display->black, nil, ZP); +} + +ulong +iterate(double x, double y) +{ + int i; + double zx, zy, zx2, zy2, v; + + zx = zy = zx2 = zy2 = 0; + for(i = 0; i < 100; i++){ + zy = 2 * zx * zy + y; + zx = zx2 - zy2 + x; + zx2 = zx * zx; + zy2 = zy * zy; + if(zx2 + zy2 >= 4){ + v = 2 + i - log(log(sqrt(zx2 + zy2)) / log(i + 2)) / 0.69314718; + return (int)(v * 1000) % ncolors; + } + } + return 0; +} + +void +redrawproc(void *) +{ + int x, y; + uchar *p, *q; + + qlock(rend.l); + for(;;){ + setcursor(mctl, &reading); + p = imagedata; + for(y = screen->r.min.y; y < screen->r.max.y; y++) + for(x = screen->r.min.x; x < screen->r.max.x; x++){ + if(stopdraw) + goto check; + q = colors + 3 * iterate(convx(&screen->r, x), convy(&screen->r, y)); + *p++ = *q++; + *p++ = *q++; + *p++ = *q; + } + if(stopdraw) + goto check; + lockdisplay(display); + loadimage(image, image->r, imagedata, Dx(image->r) * Dy(image->r) * 3); + draw(screen, screen->r, image, nil, screen->r.min); + flushimage(display, 1); + unlockdisplay(display); + check: + stopdraw = 0; + setcursor(mctl, nil); + rsleep(&rend); + stopdraw = 0; + } +} + +void +zoom(void) +{ + Rectangle r; + double xmin_, xmax_, ymin_, ymax_; + + r = getrect(3, mctl); + if(r.min.x == 0 && r.min.y == 0 && r.max.x == 0 && r.max.y == 0) + return; + xmin_ = convx(&screen->r, r.min.x); + xmax_ = convx(&screen->r, r.max.x); + ymin_ = convy(&screen->r, r.max.y); + ymax_ = convy(&screen->r, r.min.y); + stopdraw = 1; + qlock(rend.l); + xmin = xmin_; + xmax = xmax_; + ymin = ymin_; + ymax = ymax_; + rwakeup(&rend); + qunlock(rend.l); +} + +char *menus[] = { + "zoom in", + "reset", + "quit", + nil, +}; + +Menu menu = { + .item = menus +}; + +void +resizethread(void *) +{ + ulong l; + + for(;;){ + if(recv(mctl->resizec, &l) < 1) + continue; + stopdraw = 1; + qlock(rend.l); + if(getwindow(display, Refnone) < 0) + sysfatal("getwindow: %r"); + freeimage(image); + free(imagedata); + image = allocimage(display, screen->r, RGB24, 0, DBlack); + imagedata = malloc(3 * Dx(screen->r) * Dy(screen->r)); + rwakeup(&rend); + qunlock(rend.l); + } +} + +void +initcolors(void) +{ + uchar *p; + int h, x; + + for(p = colors + 3, h = 0; p < colors + nelem(colors); h++){ + x = 0xFF - abs(h % (ncolors / 3) - ncolors / 6) * 0xFF / (ncolors / 6); + if(h < ncolors/6){ + *p++ = 0xFF; + *p++ = x; + *p++ = 0; + }else if(h < ncolors/3){ + *p++ = x; + *p++ = 0xFF; + *p++ = 0; + }else if(h < ncolors/2){ + *p++ = 0; + *p++ = 0xFF; + *p++ = x; + }else if(h < 2*ncolors/3){ + *p++ = 0; + *p++ = x; + *p++ = 0xFF; + }else if(h < 5*ncolors/6){ + *p++ = x; + *p++ = 0; + *p++ = 0xFF; + }else{ + *p++ = 0xFF; + *p++ = 0; + *p++ = x; + } + } +} + +void +threadmain() +{ + static QLock ql; + int rc; + + if(initdraw(nil, nil, "mandelbrot") < 0) + sysfatal("initdraw: %r"); + display->locking = 1; + unlockdisplay(display); + if((mctl = initmouse(nil, screen)) == nil) + sysfatal("initmouse: %r"); + rend.l = &ql; + image = allocimage(display, screen->r, RGB24, 0, DBlack); + imagedata = malloc(3 * Dx(screen->r) * Dy(screen->r)); + initcolors(); + proccreate(redrawproc, nil, mainstacksize); + threadcreate(resizethread, nil, mainstacksize); + for(;;){ + readmouse(mctl); + if(mctl->buttons & 4){ + lockdisplay(display); + rc = menuhit(3, mctl, &menu, nil); + unlockdisplay(display); + switch(rc){ + case 0: + zoom(); + break; + case 1: + stopdraw = 1; + qlock(rend.l); + xmin = -2; + xmax = 1; + ymin = -1; + ymax = 1; + rwakeup(&rend); + qunlock(rend.l); + break; + case 2: + threadexitsall(nil); + } + } + } +} + +Cursor reading = { + {-1, -1}, + {0xff, 0x80, 0xff, 0x80, 0xff, 0x00, 0xfe, 0x00, + 0xff, 0x00, 0xff, 0x80, 0xff, 0xc0, 0xef, 0xe0, + 0xc7, 0xf0, 0x03, 0xf0, 0x01, 0xe0, 0x00, 0xc0, + 0x03, 0xff, 0x03, 0xff, 0x03, 0xff, 0x03, 0xff, }, + {0x00, 0x00, 0x7f, 0x00, 0x7e, 0x00, 0x7c, 0x00, + 0x7e, 0x00, 0x7f, 0x00, 0x6f, 0x80, 0x47, 0xc0, + 0x03, 0xe0, 0x01, 0xf0, 0x00, 0xe0, 0x00, 0x40, + 0x00, 0x00, 0x01, 0xb6, 0x01, 0xb6, 0x00, 0x00, } +}; diff --git a/sys/src/games/mkfile b/sys/src/games/mkfile index 6e9270ca3..a71c71364 100644 --- a/sys/src/games/mkfile +++ b/sys/src/games/mkfile @@ -11,6 +11,7 @@ TARG=4s\ mole\ glendy\ packet\ + mandel\ OFILES= HFILES=