]> git.itanic.dy.fi Git - mandelbrot/blobdiff - mandelbrot.c
Add support for navigation
[mandelbrot] / mandelbrot.c
index 624fcf2ebda615e2275021d1d50aa59b91624a30..926b6af0a827be7f7b3ed99db094c35bf2d0a27f 100644 (file)
@@ -2,6 +2,15 @@
 #include <unistd.h>
 #include <stdio.h>
 #include <time.h>
+#include <string.h>
+
+struct context {
+       struct SDL_Surface *screen;
+       double origo_x, origo_y;
+       int motion_x, motion_y;
+       double zoom;
+       int scroll_enabled;
+};
 
 static void putpixel(struct SDL_Surface *screen, const int x, const int y,
                     const unsigned char r, const unsigned char g,
@@ -40,6 +49,8 @@ int draw_mandelbrot(struct SDL_Surface *screen, double x1, double x2,
        double x0, y0, xlen, ylen, xstep, ystep;
        int iteration, xs, ys;
 
+       printf("Drawing area (%f, %f)(%f, %f)\n", x1, y1, x2, y2);
+
        xlen = x2 - x1;
        ylen = y2 - y1;
        xstep = xlen / (double)screen->w;
@@ -67,12 +78,107 @@ int draw_mandelbrot(struct SDL_Surface *screen, double x1, double x2,
        return 0;
 }
 
+static int read_events(struct context *ctx)
+{
+       SDL_Event event;
+       int wait = 1, ret, exit = 0, delayed_exit = 0;
+
+       while (!exit) {
+               if (wait) {
+                       SDL_WaitEvent(&event);
+                       wait = 0;
+               } else {
+                       ret = SDL_PollEvent(&event);
+                       if (!ret) {
+                               wait = 1;
+                               exit = delayed_exit;
+                       }
+               }
+
+               switch (event.type) {
+               case SDL_KEYDOWN:
+                       switch (event.key.keysym.sym) {
+                       case SDLK_ESCAPE:
+                               goto quit;
+                       default:
+                               break;
+                       }
+                       break;
+               case SDL_KEYUP:
+                       switch (event.key.keysym.sym) {
+                       default:
+                               break;
+                       }
+                       break;
+               case SDL_MOUSEBUTTONDOWN:
+                       if (event.button.button == 4) {
+                               ctx->zoom *= 1.5;
+                               exit++;
+                       } else if (event.button.button == 5) {
+                               ctx->zoom /= 1.5;
+                               delayed_exit++;
+                       } else {
+                               ctx->scroll_enabled = 1;
+                       }
+                       break;
+               case SDL_MOUSEBUTTONUP:
+                       ctx->scroll_enabled = 0;
+                       exit++;
+                       break;
+               case SDL_MOUSEMOTION:
+                       if (!ctx->scroll_enabled)
+                               break;
+
+                       ctx->motion_x -= event.motion.xrel;
+                       ctx->motion_y -= event.motion.yrel;
+                       delayed_exit++;
+                       break;
+               case SDL_VIDEORESIZE:
+                       ctx->screen =
+                               SDL_SetVideoMode(event.resize.w,
+                                                event.resize.h,
+                                                32,
+                                                ctx->screen->flags);
+                       exit++;
+                       break;
+               case SDL_QUIT:
+                       goto quit;
+               }
+       }
+
+       return 0;
+quit:
+       printf("\nExiting. Good bye!\n");
+       return 1;
+}
+
+static void loop(struct context *ctx)
+{
+       double aspect_ratio;
+
+       do {
+               aspect_ratio = ctx->screen->w / ctx->screen->h;
+               ctx->origo_x += ctx->motion_x / ctx->zoom / ctx->screen->w;
+               ctx->origo_y += ctx->motion_y / ctx->zoom / ctx->screen->h;
+               ctx->motion_x = ctx->motion_y = 0;
+
+               draw_mandelbrot(ctx->screen,
+                               ctx->origo_x - aspect_ratio / ctx->zoom,
+                               ctx->origo_x + aspect_ratio / ctx->zoom,
+                               ctx->origo_y - 1 / ctx->zoom,
+                               ctx->origo_y + 1 / ctx->zoom);
+       } while (!read_events(ctx));
+}
+
 int main(int argc, char *argv[])
 {
-       SDL_Surface *screen;
+       struct context ctx;
        int flags = SDL_DOUBLEBUF | SDL_HWSURFACE | SDL_RESIZABLE;
        int xres = 800, yres = 600;
 
+       memset(&ctx, 0, sizeof(ctx));
+       ctx.zoom = 1;
+
        if (SDL_Init(SDL_INIT_VIDEO) != 0) {
                fprintf(stderr, "Unable to initialize SDL: %s\n",
                        SDL_GetError());
@@ -81,8 +187,8 @@ int main(int argc, char *argv[])
        }
        atexit(SDL_Quit);
 
-       screen = SDL_SetVideoMode(xres, yres, 32, flags);
-       if (screen == NULL) {
+       ctx.screen = SDL_SetVideoMode(xres, yres, 32, flags);
+       if (ctx.screen == NULL) {
                fprintf(stderr, "Unable to set video mode: %s\n",
                        SDL_GetError());
                return 2;
@@ -90,9 +196,7 @@ int main(int argc, char *argv[])
 
        SDL_WM_SetCaption(argv[0], NULL);
 
-       draw_mandelbrot(screen, -2.5, 1, -1, 1);
-
-       yres = read(0, &xres, 1);
+       loop(&ctx);
 
        return 0;
 }