Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
#include "SDL.h"
#include <stdlib.h>
#include <math.h>
struct Rect
{
Rect() : x0(0), y0(0), x1(0), y1(0) {}
Rect(double a0, double b0, double a1, double b1) :
x0(a0), y0(b0), x1(a1), y1(b1) {}
double width() const { return fabsl(x1 - x0); }
double height() const { return fabsl(y1 - y0); }
double x0; double y0;
double x1; double y1;
};
static int _max_iteration = 50;
static SDL_Surface *screen;
static Rect r(-2, 1, 1, -1);
#define WIDTH 640
#define HEIGHT 480
extern "C" {
void clear();
}
inline void plot(SDL_Surface *screen, int x, int y, int r, int g, int b)
{
int pitch = WIDTH * 4;
int bpp = 4;
int offset = y * pitch + x * bpp;
((uint8_t *)screen->pixels)[offset] = r;
((uint8_t *)screen->pixels)[offset + 1] = g;
((uint8_t *)screen->pixels)[offset + 2] = b;
((uint8_t *)screen->pixels)[offset + 3] = 1; // XXX: alpha doesn't matter
}
void draw(const Rect &rect)
{
printf("Drawing: %.2f, %.2f, %.2f, %.2f\n",
rect.x0, rect.y0, rect.x1, rect.y1);
clear();
SDL_LockSurface(screen);
// XXX: SDL_FillRect not yet implemented by emscripten
// SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 0, 0, 0));
// XXX: screen attributes not properly set by emscripten
// int width = screen->w, height = screen->h;
int width = WIDTH, height = HEIGHT;
double dx = (rect.x1 - rect.x0) / width;
double dy = (rect.y1 - rect.y0) / height;
double x = rect.x0, y = rect.y0;
// Naive Mandelbrot algorithm.
for (int i = 0; i < width; ++i) {
for (int j = 0; j < height; ++j) {
double z = 0.0, zi = 0.0;
int v = 0;
int n = 0;
while ((n < _max_iteration)) {
double z_ = z*z - zi*zi + x;
zi = 2*z*zi + y;
z = z_;
if (z*z + zi*zi > 4) {
// XXX: color hack
v = round((float) 240 * n / _max_iteration) + 15;
break;
}
++n;
}
static int count = 0;
if (v) {
if (count < 50) {
count++;
}
plot(screen, i, j, 0, v, v);
} else {
// interior point
// plot(screen, i, j, 255, 0, 0);
}
y += dy;
}
x += dx;
y = rect.y0;
}
SDL_UnlockSurface(screen);
SDL_Flip(screen);
}
extern "C" {
void zoom(int zoomX, int zoomY)
{
// XXX hacky zoom
double zoom = 1.5;
double x = (double) zoomX / WIDTH;
double y = (double) zoomY / HEIGHT;
double w = r.width();
double h = r.height();
r.x0 += (w * x) - (w / zoom / 2);
r.y0 -= (h * y) - (h / zoom / 2);
r.x1 = r.x0 + (w / zoom);
r.y1 = r.y0 - (h / zoom);
draw(r);
}
}
int main(int argc, char **argv)
{
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE) < 0) {
printf("ERROR: %s\n", SDL_GetError());
exit(1);
}
screen = SDL_SetVideoMode(WIDTH, HEIGHT, 32, 0);
if (!screen) {
printf("ERROR: %s\n", SDL_GetError());
exit(1);
}
draw(r);
// XXX: this info is garbage in emscripten's impl
#if 0
// Debug info.
printf("Created screen:\n");
printf("\tDimensions: %d x %d\n", screen->w, screen->h);
printf("\tPitch: %d\n", screen->pitch);
printf("\tData: %p\n", screen->pixels);
printf("\tBPP: %d\n", screen->format->BitsPerPixel);
// XXX: events not yet supported by emscripten
SDL_Event event;
bool dirty = true;
while (SDL_WaitEvent(&event)) {
if (dirty) {
dirty = false;
draw(screen, r);
SDL_Flip(screen);
}
switch (event.type) {
case SDL_MOUSEBUTTONDOWN:
dirty = true;
{
// XXX hacky zoom
double zoom = 1.5;
double x = (double) event.button.x / screen->w;
double y = (double) event.button.y / screen->h;
double w = r.width();
double h = r.height();
r.x0 += (w * x) - (w / zoom / 2);
r.y0 -= (h * y) - (h / zoom / 2);
r.x1 = r.x0 + (w / zoom);
r.y1 = r.y0 - (h / zoom);
}
break;
case SDL_KEYDOWN:
switch (event.key.keysym.sym) {
case SDLK_ESCAPE:
printf("Adios!\n");
exit(0);
break;
case SDLK_UP:
dirty = true;
_max_iteration += 10;
break;
case SDLK_DOWN:
dirty = true;
_max_iteration -= (_max_iteration > 20) ? 10 : 0;
break;
case SDLK_SPACE:
// Reset.
dirty = true;
r = Rect(-2, 1, 1, -1);
_max_iteration = 50;
break;
}
break;
}
}
SDL_Quit();
#endif
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment