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