Created
March 27, 2011 07:38
-
-
Save jmk/889018 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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