#include <u.h>
#include <libc.h>
#include <draw.h>
#include <event.h>
#define RAD (PI * 2)
#define DEG (PI / 180.0)
Image *bg,*fg;
int frametime;
double spr;
int wings;
double wingrads;
double turns;
vlong starttime;
void
usage(void)
{
fprint(2,"usage: %s [-f framerate] [-r rpm] [-w wings] [-t turns]\n", argv0);
exits("usage");
}
Point
SPt(int x, int y)
{
return addpt(Pt(x, y), screen->r.min);
}
Rectangle
SRect(int x0, int y0, int x1, int y1)
{
return rectaddpt(Rect(x0, y0, x1, y1), screen->r.min);
}
Point
imagecenter(Image* img)
{
return divpt(addpt(img->r.min, img->r.max), 2);
}
double
imageradius(Image* img)
{
Point dims;
dims = divpt(subpt(img->r.max, img->r.min), 2);
return 1.4 + sqrt(dims.x*dims.x + dims.y*dims.y);
}
Point
vecpt(double radians, double radius)
{
double x,y;
x = sin(radians) * radius;
y = cos(radians) * radius;
return Pt(x + 1, y + 1);
}
void
drawframe(double ts)
{
double radians, radius, spiralrads, spiralx, spiraly;
uint numpoints, iradius;
int i, j, k;
Point center;
Point *wingpoints;
radians = fmod(ts / spr, spr) * RAD;
radius = imageradius(screen) * 1.4;
iradius = radius + 1;
center = imagecenter(screen);
numpoints = iradius + iradius;
wingpoints = malloc(sizeof(Point) * numpoints);
wingpoints[0] = center;
wingpoints[numpoints - 1] = center;
draw(screen, screen->r, bg, nil, SPt(0, 0));
for(i = 0; i < wings; i++){
for(j = 0; j < iradius; j++){
spiralrads = (double)j / (double)iradius * turns * RAD;
spiralx = sin(radians + spiralrads) * j;
spiraly = cos(radians + spiralrads) * j;
k = j;
wingpoints[k] = addpt(center, Pt(spiralx, spiraly));
}
radians += wingrads;
for(j = 0; j < iradius; j++){
spiralrads = (double)(iradius - j) / (double)iradius * turns * RAD;
spiralx = sin(radians + spiralrads) * (iradius - j);
spiraly = cos(radians + spiralrads) * (iradius - j);
// weird syntax issue
k = j + iradius;
wingpoints[k] = addpt(center, Pt(spiralx, spiraly));
}
fillpoly(screen, wingpoints, numpoints, ~0, fg, Pt(0,0));
radians += wingrads;
}
free(wingpoints);
}
double
ftime(void)
{
return ((double)(nsec() - starttime)) / 1000000000.0;
}
void
eresized(int new)
{
if(new && getwindow(display, Refnone) < 0)
fprint(2,"can't reattach to window\n");
drawframe(ftime());
}
void
main(int argc, char* argv[])
{
int timer,etype;
Event e;
frametime = 1.0 / 30.0 * 1000;
wings = 3;
spr = 2;
turns = 1.0 / 6.0;
ARGBEGIN{
case 'f':
frametime = 1.0 / atof(EARGF(usage())) * 1000;
break;
case 'r':
spr = 1.0 / (atof(EARGF(usage())) / 60.0);
break;
case 'w':
wings = atoi(EARGF(usage()));
break;
case 't':
turns = atof(EARGF(usage()));
break;
default:
usage();
}ARGEND
fprint(2,"turns: %f\n", turns);
if(wings < 1) wings = 1;
wingrads = PI / (double) wings;
if(initdraw(nil, nil, "spiral") < 0)
sysfatal("initdraw: %r");
fg = allocimage(display, Rect(0,0, 1,1), GREY1, 1, DBlack);
if(!fg)
sysfatal("couldn't allocimage!");
bg = allocimage(display, Rect(0,0, 1,1), GREY1, 1, DWhite);
if(!bg)
sysfatal("couldn't allocimage!");
starttime = nsec();
einit(Emouse);
timer = etimer(0, frametime);
for(;;){
etype = event(&e);
if (etype == timer)
drawframe(ftime());
}
}