]> git.itanic.dy.fi Git - mandelbrot/blob - mandelbrot.c
Fix printf formatting
[mandelbrot] / mandelbrot.c
1 #include <SDL.h>
2 #include <unistd.h>
3 #include <stdio.h>
4 #include <time.h>
5 #include <string.h>
6
7 struct context {
8         struct SDL_Surface *screen;
9         long double origo_x, origo_y;
10         int motion_x, motion_y;
11         long double zoom;
12         int scroll_enabled;
13         int zooms;
14 };
15
16 static void putpixel(struct SDL_Surface *screen, const int x, const int y,
17                      const unsigned char r, const unsigned char g,
18                      const unsigned char b)
19 {
20         int offset = y * screen->pitch + x * 4;
21         unsigned char *buf = screen->pixels;
22
23         buf[offset++] = b;
24         buf[offset++] = g;
25         buf[offset]   = r;
26 }
27
28 #define MAX_ITERATION 1000
29
30 int get_mandelbrot_iterations(long double x0, long double y0)
31 {
32         long double x = 0, y = 0, xtemp;
33         int iteration = 0;
34
35         while ((x * x + y * y < 2 * 2) && iteration < MAX_ITERATION) {
36
37                 xtemp = x * x - y * y + x0;
38                 y = 2 * x * y + y0;
39
40                 x = xtemp;
41                 iteration++;
42         }
43
44         return iteration;
45 }
46
47 int draw_mandelbrot(struct SDL_Surface *screen, long double x1, long double x2,
48                 long double y1, long double y2)
49 {
50         long double x0, y0, xlen, ylen, xstep, ystep;
51         int iteration, xs, ys;
52
53         xlen = x2 - x1;
54         ylen = y2 - y1;
55         xstep = xlen / (long double)screen->w;
56         ystep = ylen / (long double)screen->h;
57
58         y0 = y1;
59 #pragma omp parallel for private(xs, ys, x0, y0)
60         for (ys = 0; ys < screen->h; ys++) {
61                 y0 = y1 + ystep * ys;
62                 x0 = x1;
63                 for (xs = 0; xs < screen->w; xs++) {
64                         iteration = get_mandelbrot_iterations(x0, y0);
65
66                         if (iteration == MAX_ITERATION)
67                                 putpixel(screen, xs, ys, 255, 255, 255);
68                         else
69                                 putpixel(screen, xs, ys,
70                                         iteration * 8, iteration,
71                                         iteration / 4);
72                         x0 += xstep;
73                 }
74         }
75
76         SDL_Flip(screen);
77         return 0;
78 }
79
80 static int read_events(struct context *ctx)
81 {
82         SDL_Event event;
83         int wait = 1, ret, exit = 0, delayed_exit = 0;
84
85         while (!exit) {
86                 if (wait) {
87                         SDL_WaitEvent(&event);
88                         wait = 0;
89                 } else {
90                         ret = SDL_PollEvent(&event);
91                         if (!ret) {
92                                 wait = 1;
93                                 exit = delayed_exit;
94                         }
95                 }
96
97                 switch (event.type) {
98                 case SDL_KEYDOWN:
99                         switch (event.key.keysym.sym) {
100                         case SDLK_ESCAPE:
101                                 goto quit;
102                         default:
103                                 break;
104                         }
105                         break;
106                 case SDL_KEYUP:
107                         switch (event.key.keysym.sym) {
108                         default:
109                                 break;
110                         }
111                         break;
112                 case SDL_MOUSEBUTTONDOWN:
113                         if (event.button.button == 4) {
114                                 ctx->zoom *= 1.5;
115                                 ctx->zooms++;
116                                 delayed_exit++;
117                         } else if (event.button.button == 5) {
118                                 ctx->zoom /= 1.5;
119                                 ctx->zooms--;
120                                 delayed_exit++;
121                         } else {
122                                 ctx->scroll_enabled = 1;
123                         }
124                         break;
125                 case SDL_MOUSEBUTTONUP:
126                         ctx->scroll_enabled = 0;
127                         exit++;
128                         break;
129                 case SDL_MOUSEMOTION:
130                         if (!ctx->scroll_enabled)
131                                 break;
132
133                         ctx->motion_x -= event.motion.xrel;
134                         ctx->motion_y -= event.motion.yrel;
135                         delayed_exit++;
136                         break;
137                 case SDL_VIDEORESIZE:
138                         ctx->screen =
139                                 SDL_SetVideoMode(event.resize.w,
140                                                  event.resize.h,
141                                                  32,
142                                                  ctx->screen->flags);
143                         exit++;
144                         break;
145                 case SDL_QUIT:
146                         goto quit;
147                 }
148         }
149
150         return 0;
151 quit:
152         printf("\nExiting. Good bye!\n");
153         return 1;
154 }
155
156 static void loop(struct context *ctx)
157 {
158         long double aspect_ratio;
159         long double x1, x2, y1, y2;
160
161         do {
162                 aspect_ratio = ctx->screen->w / ctx->screen->h;
163                 ctx->origo_x += ctx->motion_x / ctx->zoom / ctx->screen->w;
164                 ctx->origo_y += ctx->motion_y / ctx->zoom / ctx->screen->h;
165                 ctx->motion_x = ctx->motion_y = 0;
166
167                 x1 = ctx->origo_x - aspect_ratio / ctx->zoom;
168                 x2 = ctx->origo_x + aspect_ratio / ctx->zoom;
169                 y1 = ctx->origo_y - 1 / ctx->zoom;
170                 y2 = ctx->origo_y + 1 / ctx->zoom;
171                 printf("Drawing area (%LF, %LF)(%LF, %LF), zoom %d\n",
172                         x1, y1, x2, y2, ctx->zooms);
173                 draw_mandelbrot(ctx->screen, x1, x2, y1, y2);
174         } while (!read_events(ctx));
175 }
176
177 int main(int argc, char *argv[])
178 {
179         struct context ctx;
180         int flags = SDL_DOUBLEBUF | SDL_HWSURFACE | SDL_RESIZABLE;
181         int xres = 800, yres = 600;
182
183         memset(&ctx, 0, sizeof(ctx));
184         ctx.zoom = 1;
185
186         if (SDL_Init(SDL_INIT_VIDEO) != 0) {
187                 fprintf(stderr, "Unable to initialize SDL: %s\n",
188                         SDL_GetError());
189
190                 return 1;
191         }
192         atexit(SDL_Quit);
193
194         ctx.screen = SDL_SetVideoMode(xres, yres, 32, flags);
195         if (ctx.screen == NULL) {
196                 fprintf(stderr, "Unable to set video mode: %s\n",
197                         SDL_GetError());
198                 return 2;
199         }
200
201         SDL_WM_SetCaption(argv[0], NULL);
202
203         loop(&ctx);
204
205         return 0;
206 }