#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 eccen;
vlong starttime;
void
usage(void)
{
fprint(2,"usage: %s [-f framerate] [-r rpm] [-w wings] [-e deg]\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;
Point center;
Point wingpoints[6];
radians = fmod(ts / spr, spr) * RAD;
radius = imageradius(screen) * 1.4;
center = imagecenter(screen);
wingpoints[0] = center;
wingpoints[5] = addpt(center, Pt(1, 1));
draw(screen, screen->r, bg, nil, SPt(0, 0));
for(int i = 0; i < wings; i++)
{
wingpoints[1] = addpt(center, vecpt(radians + eccen, radius / 3));
wingpoints[2] = addpt(center, vecpt(radians, radius));
radians += wingrads;
wingpoints[3] = addpt(center, vecpt(radians, radius));
wingpoints[4] = addpt(center, vecpt(radians + eccen, radius / 3));
radians += wingrads;
fillbezspline(screen, wingpoints, 6, ~0, fg, Pt(0, 0));
}
}
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;
eccen = RAD / 6;
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 'e':
eccen = DEG * atof(EARGF(usage()));
break;
default:
usage();
} ARGEND
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());
}
}