You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
133 lines
2.7 KiB
133 lines
2.7 KiB
/** |
|
Simple SAF program for exploring the Mandelbrot set, arrows to move, A/B to |
|
zoom. |
|
|
|
by drummyfish, released under CC0 1.0, public domain |
|
*/ |
|
|
|
#define SAF_PROGRAM_NAME "Mandelbrot" |
|
#define SAF_SETTING_ENABLE_SOUND 0 |
|
|
|
#include "../saf.h" |
|
|
|
/* |
|
Checks whether the point is in the mandelbrot set, returns number of |
|
iterations, up until 255, to which the point did not diverge to infinity, i.e. |
|
255 means probably inside the set. |
|
*/ |
|
|
|
uint8_t iteratePoint(double x, double y) |
|
{ |
|
// writing this without floats is left as an excercise for the reader |
|
|
|
double current[2]; |
|
|
|
current[0] = x; |
|
current[1] = y; |
|
|
|
uint8_t iterations = 0; |
|
|
|
while (1) |
|
{ |
|
double |
|
newX = current[0] * current[0] - current[1] * current[1] + x, |
|
newY = 2 * current[0] * current[1] + y; |
|
|
|
current[0] = newX; |
|
current[1] = newY; |
|
|
|
#define INF 999999999999 |
|
|
|
if (iterations == 255 || |
|
current[0] > INF || current[0] < -INF || |
|
current[1] > INF || current[1] < -INF) |
|
break; |
|
|
|
#undef INF |
|
|
|
iterations++; |
|
} |
|
|
|
return iterations; |
|
} |
|
|
|
double |
|
cx = -1, |
|
cy = -1, |
|
step = 2.0 / SAF_SCREEN_WIDTH; |
|
|
|
void draw(void) |
|
{ |
|
double dx, dy = cy, halfStep = step / 2; |
|
|
|
for (int y = 0; y < SAF_SCREEN_HEIGHT; ++y) |
|
{ |
|
dx = cx; |
|
|
|
for (int x = 0; x < SAF_SCREEN_WIDTH; ++x) |
|
{ |
|
// antialias (sample at 4 points): |
|
|
|
uint8_t r = 0,g = 0,b = 0; |
|
uint16_t rr = 0, gg = 0, bb = 0; |
|
|
|
SAF_colorToRGB(iteratePoint(dx,dy), &r, &g, &b); |
|
rr = r; gg = g; bb = b; |
|
SAF_colorToRGB(iteratePoint(dx + halfStep,dy), &r, &g, &b); |
|
rr += r; gg += g; bb += b; |
|
SAF_colorToRGB(iteratePoint(dx,dy + halfStep), &r, &g, &b); |
|
rr += r; gg += g; bb += b; |
|
SAF_colorToRGB(iteratePoint(dx + halfStep,dy + halfStep), &r, &g, &b); |
|
rr += r; gg += g; bb += b; |
|
|
|
SAF_drawPixel(x,y,SAF_colorFromRGB(rr / 4, gg / 4, bb / 4)); |
|
|
|
dx += step; |
|
} |
|
|
|
dy += step; |
|
} |
|
} |
|
|
|
void SAF_init(void) |
|
{ |
|
draw(); |
|
} |
|
|
|
uint8_t SAF_loop(void) |
|
{ |
|
uint8_t redraw = 1; |
|
|
|
#define STEP 10 |
|
|
|
if (SAF_buttonJustPressed(SAF_BUTTON_LEFT)) |
|
cx -= step * STEP; |
|
else if (SAF_buttonJustPressed(SAF_BUTTON_RIGHT)) |
|
cx += step * STEP; |
|
else if (SAF_buttonJustPressed(SAF_BUTTON_UP)) |
|
cy -= step * STEP; |
|
else if (SAF_buttonJustPressed(SAF_BUTTON_DOWN)) |
|
cy += step * STEP; |
|
else if (SAF_buttonJustPressed(SAF_BUTTON_A)) |
|
{ |
|
// zoom and shift |
|
step /= 2; |
|
cx += step / 2 * SAF_SCREEN_WIDTH; |
|
cy += step / 2 * SAF_SCREEN_HEIGHT; |
|
} |
|
else if (SAF_buttonJustPressed(SAF_BUTTON_B)) |
|
{ |
|
step *= 2; |
|
cx -= step / 4 * SAF_SCREEN_WIDTH; |
|
cy -= step / 4 * SAF_SCREEN_HEIGHT; |
|
} |
|
else |
|
redraw = 0; |
|
|
|
#undef STEP |
|
|
|
if (redraw) // only redraw when needed, it's expensive |
|
draw(); |
|
|
|
return 1; |
|
}
|
|
|