rev |
line source |
nuclear@0
|
1 #include <stdio.h>
|
nuclear@0
|
2 #include <complex.h>
|
nuclear@1
|
3 #include <SDL2/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@1
|
9 static SDL_Window *win;
|
nuclear@1
|
10 static SDL_Surface *winsurf;
|
nuclear@0
|
11 static int win_width, win_height;
|
nuclear@0
|
12 static float win_aspect;
|
nuclear@0
|
13 static float xoffs, yoffs, zoom = 1.0;
|
nuclear@0
|
14 static int max_iter = 64;
|
nuclear@0
|
15
|
nuclear@1
|
16 static void trysdl2stuff(void)
|
nuclear@1
|
17 {
|
nuclear@1
|
18 int i, j, num_modes, num_scr;
|
nuclear@1
|
19
|
nuclear@1
|
20 num_scr = SDL_GetNumVideoDisplays();
|
nuclear@1
|
21
|
nuclear@1
|
22 for(i=0; i<num_scr; i++) {
|
nuclear@1
|
23 printf("Screen %d: %s\n", i, SDL_GetDisplayName(i));
|
nuclear@1
|
24
|
nuclear@1
|
25 num_modes = SDL_GetNumDisplayModes(i);
|
nuclear@1
|
26 for(j=0; j<num_modes; j++) {
|
nuclear@1
|
27 SDL_DisplayMode mode;
|
nuclear@1
|
28 int bpp;
|
nuclear@1
|
29 unsigned int rmask, gmask, bmask, amask;
|
nuclear@1
|
30
|
nuclear@1
|
31 SDL_GetDisplayMode(i, j, &mode);
|
nuclear@1
|
32 SDL_PixelFormatEnumToMasks(mode.format, &bpp, &rmask, &gmask, &bmask, &amask);
|
nuclear@1
|
33
|
nuclear@1
|
34 printf(" %dx%d %dbpp %dhz\n", mode.w, mode.h, bpp, mode.refresh_rate);
|
nuclear@1
|
35 }
|
nuclear@1
|
36 }
|
nuclear@1
|
37
|
nuclear@1
|
38 SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, "Information", "Mandelbrot rules!", 0);
|
nuclear@1
|
39 }
|
nuclear@1
|
40
|
nuclear@0
|
41 int main(void)
|
nuclear@0
|
42 {
|
nuclear@0
|
43 win_width = 800;
|
nuclear@0
|
44 win_height = 600;
|
nuclear@0
|
45 win_aspect = (float)win_width / (float)win_height;
|
nuclear@0
|
46
|
nuclear@0
|
47 SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER);
|
nuclear@1
|
48 trysdl2stuff();
|
nuclear@1
|
49
|
nuclear@1
|
50 if(!(win = SDL_CreateWindow("Mandelbrot", 0, 0, win_width, win_height, SDL_WINDOW_RESIZABLE))) {
|
nuclear@0
|
51 fprintf(stderr, "failed to create framebuffer\n");
|
nuclear@0
|
52 return 1;
|
nuclear@0
|
53 }
|
nuclear@1
|
54 winsurf = SDL_GetWindowSurface(win);
|
nuclear@0
|
55
|
nuclear@0
|
56 for(;;) {
|
nuclear@0
|
57 SDL_Event ev;
|
nuclear@0
|
58
|
nuclear@0
|
59 while(SDL_PollEvent(&ev)) {
|
nuclear@0
|
60 if(handle_event(&ev) == -1) {
|
nuclear@0
|
61 goto done;
|
nuclear@0
|
62 }
|
nuclear@0
|
63 }
|
nuclear@0
|
64
|
nuclear@0
|
65 display();
|
nuclear@0
|
66 }
|
nuclear@0
|
67
|
nuclear@0
|
68 done:
|
nuclear@0
|
69 SDL_Quit();
|
nuclear@0
|
70 return 0;
|
nuclear@0
|
71 }
|
nuclear@0
|
72
|
nuclear@0
|
73 void display(void)
|
nuclear@0
|
74 {
|
nuclear@0
|
75 unsigned char *fbuf, *pixptr;
|
nuclear@0
|
76 int i, j, xsz, ysz;
|
nuclear@0
|
77
|
nuclear@1
|
78 if(SDL_MUSTLOCK(winsurf)) {
|
nuclear@1
|
79 SDL_LockSurface(winsurf);
|
nuclear@0
|
80 }
|
nuclear@1
|
81 fbuf = winsurf->pixels;
|
nuclear@1
|
82 xsz = winsurf->w;
|
nuclear@1
|
83 ysz = winsurf->h;
|
nuclear@0
|
84
|
nuclear@0
|
85 pixptr = fbuf;
|
nuclear@0
|
86 for(i=0; i<ysz; i++) {
|
nuclear@0
|
87 float y = 2.0 * (float)i / (float)ysz - 1.0;
|
nuclear@0
|
88 for(j=0; j<xsz; j++) {
|
nuclear@0
|
89 float x = (2.0 * (float)j / (float)xsz - 1.0) * win_aspect;
|
nuclear@0
|
90
|
nuclear@0
|
91 int iter, r, g, b;
|
nuclear@0
|
92 int inset = mandelbrot((x - xoffs) * zoom, (y - yoffs) * zoom, max_iter, &iter);
|
nuclear@0
|
93 if(!inset) {
|
nuclear@0
|
94 r = iter * 256 / max_iter;
|
nuclear@0
|
95 g = 0;
|
nuclear@0
|
96 b = 0;
|
nuclear@0
|
97 } else {
|
nuclear@0
|
98 r = g = b = 0;
|
nuclear@0
|
99 }
|
nuclear@0
|
100
|
nuclear@0
|
101 pixptr[0] = b;
|
nuclear@0
|
102 pixptr[1] = g;
|
nuclear@0
|
103 pixptr[2] = r;
|
nuclear@0
|
104 pixptr[3] = 255;
|
nuclear@0
|
105 pixptr += 4;
|
nuclear@0
|
106 }
|
nuclear@0
|
107 }
|
nuclear@0
|
108
|
nuclear@1
|
109 if(SDL_MUSTLOCK(winsurf)) {
|
nuclear@1
|
110 SDL_UnlockSurface(winsurf);
|
nuclear@0
|
111 }
|
nuclear@1
|
112 SDL_UpdateWindowSurface(win);
|
nuclear@0
|
113 }
|
nuclear@0
|
114
|
nuclear@0
|
115 int mandelbrot(float x, float y, int max_iter, int *iter)
|
nuclear@0
|
116 {
|
nuclear@0
|
117 int i;
|
nuclear@0
|
118 complex float c = x + y * I;
|
nuclear@0
|
119 complex float z = c;
|
nuclear@0
|
120
|
nuclear@0
|
121 for(i=0; i<max_iter; i++) {
|
nuclear@0
|
122 float re = creal(z);
|
nuclear@0
|
123 float im = cimag(z);
|
nuclear@0
|
124 if(re * re + im * im > 4) {
|
nuclear@0
|
125 if(iter) *iter = i;
|
nuclear@0
|
126 return 0;
|
nuclear@0
|
127 }
|
nuclear@0
|
128
|
nuclear@0
|
129 z = z * z + c;
|
nuclear@0
|
130 }
|
nuclear@0
|
131
|
nuclear@0
|
132 return 1;
|
nuclear@0
|
133 }
|
nuclear@0
|
134
|
nuclear@0
|
135 int handle_event(SDL_Event *ev)
|
nuclear@0
|
136 {
|
nuclear@0
|
137 static int prev_x, prev_y;
|
nuclear@0
|
138 static int bnstate[32];
|
nuclear@0
|
139
|
nuclear@0
|
140 switch(ev->type) {
|
nuclear@0
|
141 case SDL_KEYDOWN:
|
nuclear@0
|
142 if(ev->key.keysym.sym == SDLK_ESCAPE) {
|
nuclear@0
|
143 return -1;
|
nuclear@0
|
144 }
|
nuclear@0
|
145
|
nuclear@0
|
146 case SDL_MOUSEBUTTONDOWN:
|
nuclear@0
|
147 prev_x = ev->button.x;
|
nuclear@0
|
148 prev_y = ev->button.y;
|
nuclear@0
|
149 bnstate[ev->button.button - SDL_BUTTON_LEFT] = 1;
|
nuclear@0
|
150 break;
|
nuclear@0
|
151
|
nuclear@0
|
152 case SDL_MOUSEBUTTONUP:
|
nuclear@0
|
153 bnstate[ev->button.button - SDL_BUTTON_LEFT] = 0;
|
nuclear@0
|
154 break;
|
nuclear@0
|
155
|
nuclear@0
|
156 case SDL_MOUSEMOTION:
|
nuclear@0
|
157 {
|
nuclear@0
|
158 int dx = ev->button.x - prev_x;
|
nuclear@0
|
159 int dy = ev->button.y - prev_y;
|
nuclear@0
|
160 prev_x = ev->button.x;
|
nuclear@0
|
161 prev_y = ev->button.y;
|
nuclear@0
|
162
|
nuclear@0
|
163 if(!dx && !dy) break;
|
nuclear@0
|
164
|
nuclear@0
|
165 if(bnstate[0]) {
|
nuclear@0
|
166 xoffs += win_aspect * 2.0 * (float)dx / (float)win_width;
|
nuclear@0
|
167 yoffs += 2.0 * (float)dy / (float)win_height;
|
nuclear@0
|
168 }
|
nuclear@0
|
169 if(bnstate[2]) {
|
nuclear@0
|
170 zoom += (float)dy / (float)win_height;
|
nuclear@0
|
171 if(zoom < 1e-6) zoom = 1e-6;
|
nuclear@0
|
172 }
|
nuclear@0
|
173 }
|
nuclear@0
|
174 break;
|
nuclear@0
|
175
|
nuclear@1
|
176 case SDL_WINDOWEVENT:
|
nuclear@1
|
177 if(ev->window.event == SDL_WINDOWEVENT_RESIZED) {
|
nuclear@1
|
178 win_width = ev->window.data1;
|
nuclear@1
|
179 win_height = ev->window.data2;
|
nuclear@1
|
180 win_aspect = (float)win_width / (float)win_height;
|
nuclear@1
|
181 }
|
nuclear@0
|
182 break;
|
nuclear@0
|
183
|
nuclear@0
|
184 default:
|
nuclear@0
|
185 break;
|
nuclear@0
|
186 }
|
nuclear@0
|
187 return 0;
|
nuclear@0
|
188 }
|