rev |
line source |
nuclear@0
|
1 #include <stdio.h>
|
nuclear@0
|
2 #include <complex.h>
|
nuclear@0
|
3 #include <SDL/SDL.h>
|
nuclear@0
|
4
|
nuclear@0
|
5 void display(void);
|
nuclear@0
|
6 int mandelbrot(float x, float y, int max_iter, int *iter);
|
nuclear@0
|
7 int handle_event(SDL_Event *ev);
|
nuclear@0
|
8
|
nuclear@0
|
9 static SDL_Surface *fbsurf;
|
nuclear@0
|
10 static int win_width, win_height;
|
nuclear@0
|
11 static float win_aspect;
|
nuclear@0
|
12 static float xoffs, yoffs, zoom = 1.0;
|
nuclear@0
|
13 static int max_iter = 64;
|
nuclear@0
|
14
|
nuclear@0
|
15 int main(void)
|
nuclear@0
|
16 {
|
nuclear@0
|
17 win_width = 800;
|
nuclear@0
|
18 win_height = 600;
|
nuclear@0
|
19 win_aspect = (float)win_width / (float)win_height;
|
nuclear@0
|
20
|
nuclear@0
|
21 SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER);
|
nuclear@0
|
22 if(!(fbsurf = SDL_SetVideoMode(win_width, win_height, 32, SDL_SWSURFACE | SDL_RESIZABLE))) {
|
nuclear@0
|
23 fprintf(stderr, "failed to create framebuffer\n");
|
nuclear@0
|
24 return 1;
|
nuclear@0
|
25 }
|
nuclear@0
|
26
|
nuclear@0
|
27 SDL_WM_SetCaption("Mandelbrot", 0);
|
nuclear@0
|
28
|
nuclear@0
|
29 for(;;) {
|
nuclear@0
|
30 SDL_Event ev;
|
nuclear@0
|
31
|
nuclear@0
|
32 while(SDL_PollEvent(&ev)) {
|
nuclear@0
|
33 if(handle_event(&ev) == -1) {
|
nuclear@0
|
34 goto done;
|
nuclear@0
|
35 }
|
nuclear@0
|
36 }
|
nuclear@0
|
37
|
nuclear@0
|
38 display();
|
nuclear@0
|
39 }
|
nuclear@0
|
40
|
nuclear@0
|
41 done:
|
nuclear@0
|
42 SDL_Quit();
|
nuclear@0
|
43 return 0;
|
nuclear@0
|
44 }
|
nuclear@0
|
45
|
nuclear@0
|
46 void display(void)
|
nuclear@0
|
47 {
|
nuclear@0
|
48 unsigned char *fbuf, *pixptr;
|
nuclear@0
|
49 int i, j, xsz, ysz;
|
nuclear@0
|
50
|
nuclear@0
|
51 if(SDL_MUSTLOCK(fbsurf)) {
|
nuclear@0
|
52 SDL_LockSurface(fbsurf);
|
nuclear@0
|
53 }
|
nuclear@0
|
54 fbuf = fbsurf->pixels;
|
nuclear@0
|
55 xsz = fbsurf->w;
|
nuclear@0
|
56 ysz = fbsurf->h;
|
nuclear@0
|
57
|
nuclear@0
|
58 pixptr = fbuf;
|
nuclear@0
|
59 for(i=0; i<ysz; i++) {
|
nuclear@0
|
60 float y = 2.0 * (float)i / (float)ysz - 1.0;
|
nuclear@0
|
61 for(j=0; j<xsz; j++) {
|
nuclear@0
|
62 float x = (2.0 * (float)j / (float)xsz - 1.0) * win_aspect;
|
nuclear@0
|
63
|
nuclear@0
|
64 int iter, r, g, b;
|
nuclear@0
|
65 int inset = mandelbrot((x - xoffs) * zoom, (y - yoffs) * zoom, max_iter, &iter);
|
nuclear@0
|
66 if(!inset) {
|
nuclear@0
|
67 r = iter * 256 / max_iter;
|
nuclear@0
|
68 g = 0;
|
nuclear@0
|
69 b = 0;
|
nuclear@0
|
70 } else {
|
nuclear@0
|
71 r = g = b = 0;
|
nuclear@0
|
72 }
|
nuclear@0
|
73
|
nuclear@0
|
74 pixptr[0] = b;
|
nuclear@0
|
75 pixptr[1] = g;
|
nuclear@0
|
76 pixptr[2] = r;
|
nuclear@0
|
77 pixptr[3] = 255;
|
nuclear@0
|
78 pixptr += 4;
|
nuclear@0
|
79 }
|
nuclear@0
|
80 }
|
nuclear@0
|
81
|
nuclear@0
|
82 if(SDL_MUSTLOCK(fbsurf)) {
|
nuclear@0
|
83 SDL_UnlockSurface(fbsurf);
|
nuclear@0
|
84 }
|
nuclear@0
|
85 SDL_Flip(fbsurf);
|
nuclear@0
|
86 }
|
nuclear@0
|
87
|
nuclear@0
|
88 int mandelbrot(float x, float y, int max_iter, int *iter)
|
nuclear@0
|
89 {
|
nuclear@0
|
90 int i;
|
nuclear@0
|
91 complex float c = x + y * I;
|
nuclear@0
|
92 complex float z = c;
|
nuclear@0
|
93
|
nuclear@0
|
94 for(i=0; i<max_iter; i++) {
|
nuclear@0
|
95 float re = creal(z);
|
nuclear@0
|
96 float im = cimag(z);
|
nuclear@0
|
97 if(re * re + im * im > 4) {
|
nuclear@0
|
98 if(iter) *iter = i;
|
nuclear@0
|
99 return 0;
|
nuclear@0
|
100 }
|
nuclear@0
|
101
|
nuclear@0
|
102 z = z * z + c;
|
nuclear@0
|
103 }
|
nuclear@0
|
104
|
nuclear@0
|
105 return 1;
|
nuclear@0
|
106 }
|
nuclear@0
|
107
|
nuclear@0
|
108 int handle_event(SDL_Event *ev)
|
nuclear@0
|
109 {
|
nuclear@0
|
110 static int prev_x, prev_y;
|
nuclear@0
|
111 static int bnstate[32];
|
nuclear@0
|
112
|
nuclear@0
|
113 switch(ev->type) {
|
nuclear@0
|
114 case SDL_KEYDOWN:
|
nuclear@0
|
115 if(ev->key.keysym.sym == SDLK_ESCAPE) {
|
nuclear@0
|
116 return -1;
|
nuclear@0
|
117 }
|
nuclear@0
|
118
|
nuclear@0
|
119 case SDL_MOUSEBUTTONDOWN:
|
nuclear@0
|
120 prev_x = ev->button.x;
|
nuclear@0
|
121 prev_y = ev->button.y;
|
nuclear@0
|
122 bnstate[ev->button.button - SDL_BUTTON_LEFT] = 1;
|
nuclear@0
|
123 break;
|
nuclear@0
|
124
|
nuclear@0
|
125 case SDL_MOUSEBUTTONUP:
|
nuclear@0
|
126 bnstate[ev->button.button - SDL_BUTTON_LEFT] = 0;
|
nuclear@0
|
127 break;
|
nuclear@0
|
128
|
nuclear@0
|
129 case SDL_MOUSEMOTION:
|
nuclear@0
|
130 {
|
nuclear@0
|
131 int dx = ev->button.x - prev_x;
|
nuclear@0
|
132 int dy = ev->button.y - prev_y;
|
nuclear@0
|
133 prev_x = ev->button.x;
|
nuclear@0
|
134 prev_y = ev->button.y;
|
nuclear@0
|
135
|
nuclear@0
|
136 if(!dx && !dy) break;
|
nuclear@0
|
137
|
nuclear@0
|
138 if(bnstate[0]) {
|
nuclear@0
|
139 xoffs += win_aspect * 2.0 * (float)dx / (float)win_width;
|
nuclear@0
|
140 yoffs += 2.0 * (float)dy / (float)win_height;
|
nuclear@0
|
141 }
|
nuclear@0
|
142 if(bnstate[2]) {
|
nuclear@0
|
143 zoom += (float)dy / (float)win_height;
|
nuclear@0
|
144 if(zoom < 1e-6) zoom = 1e-6;
|
nuclear@0
|
145 }
|
nuclear@0
|
146 }
|
nuclear@0
|
147 break;
|
nuclear@0
|
148
|
nuclear@0
|
149 case SDL_VIDEORESIZE:
|
nuclear@0
|
150 win_width = ev->resize.w;
|
nuclear@0
|
151 win_height = ev->resize.h;
|
nuclear@0
|
152 win_aspect = (float)win_width / (float)win_height;
|
nuclear@0
|
153 break;
|
nuclear@0
|
154
|
nuclear@0
|
155 default:
|
nuclear@0
|
156 break;
|
nuclear@0
|
157 }
|
nuclear@0
|
158 return 0;
|
nuclear@0
|
159 }
|