rev |
line source |
nuclear@0
|
1 #include <stdio.h>
|
nuclear@0
|
2 #include <stdlib.h>
|
nuclear@2
|
3 #include <string.h>
|
nuclear@1
|
4 #include <math.h>
|
nuclear@2
|
5 #include <errno.h>
|
nuclear@2
|
6 #include <dirent.h>
|
nuclear@0
|
7 #include <GL/glew.h>
|
nuclear@0
|
8 #include <GL/glut.h>
|
nuclear@0
|
9 #include "sdr.h"
|
nuclear@0
|
10
|
nuclear@0
|
11 int init(void);
|
nuclear@0
|
12 void cleanup(void);
|
nuclear@0
|
13 void disp(void);
|
nuclear@0
|
14 void reshape(int x, int y);
|
nuclear@1
|
15 void keydown(unsigned char key, int x, int y);
|
nuclear@1
|
16 void keyup(unsigned char key, int x, int y);
|
nuclear@0
|
17 void mouse(int bn, int st, int x, int y);
|
nuclear@0
|
18 void motion(int x, int y);
|
nuclear@2
|
19 void screenshot(void);
|
nuclear@0
|
20
|
nuclear@1
|
21 static int win_width = 1280, win_height = 800;
|
nuclear@1
|
22 static float win_aspect;
|
nuclear@1
|
23 static int mouse_x = 640, mouse_y = 400;
|
nuclear@0
|
24 static unsigned int prog_mbrot;
|
nuclear@0
|
25
|
nuclear@1
|
26 static float view_center[2] = {0.7, 0.0};
|
nuclear@1
|
27 static float view_scale = 1.2;
|
nuclear@1
|
28
|
nuclear@1
|
29
|
nuclear@0
|
30 int main(int argc, char **argv)
|
nuclear@0
|
31 {
|
nuclear@0
|
32 glutInit(&argc, argv);
|
nuclear@0
|
33 glutInitWindowSize(1280, 800);
|
nuclear@0
|
34 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
|
nuclear@0
|
35 glutCreateWindow("fractorb");
|
nuclear@0
|
36
|
nuclear@0
|
37 glutDisplayFunc(disp);
|
nuclear@0
|
38 glutReshapeFunc(reshape);
|
nuclear@1
|
39 glutKeyboardFunc(keydown);
|
nuclear@1
|
40 glutKeyboardUpFunc(keyup);
|
nuclear@0
|
41 glutMouseFunc(mouse);
|
nuclear@0
|
42 glutMotionFunc(motion);
|
nuclear@0
|
43
|
nuclear@0
|
44 if(init() == -1) {
|
nuclear@0
|
45 return 1;
|
nuclear@0
|
46 }
|
nuclear@0
|
47 atexit(cleanup);
|
nuclear@0
|
48
|
nuclear@0
|
49 glutMainLoop();
|
nuclear@0
|
50 return 0;
|
nuclear@0
|
51 }
|
nuclear@0
|
52
|
nuclear@0
|
53
|
nuclear@0
|
54 int init(void)
|
nuclear@0
|
55 {
|
nuclear@0
|
56 glewInit();
|
nuclear@0
|
57
|
nuclear@0
|
58 if(!(prog_mbrot = create_program_load("vertex.glsl", "mbrot.glsl"))) {
|
nuclear@0
|
59 return -1;
|
nuclear@0
|
60 }
|
nuclear@0
|
61 return 0;
|
nuclear@0
|
62 }
|
nuclear@0
|
63
|
nuclear@0
|
64 void cleanup(void)
|
nuclear@0
|
65 {
|
nuclear@0
|
66 free_program(prog_mbrot);
|
nuclear@0
|
67 }
|
nuclear@0
|
68
|
nuclear@1
|
69 void pixel_to_complex(float *res, float px, float py)
|
nuclear@1
|
70 {
|
nuclear@1
|
71 float u = (2.0 * px / win_width - 1.0) * win_aspect;
|
nuclear@1
|
72 float v = 2.0 * py / win_height - 1.0;
|
nuclear@1
|
73 res[0] = u * view_scale - view_center[0];
|
nuclear@1
|
74 res[1] = v * view_scale - view_center[1];
|
nuclear@1
|
75 }
|
nuclear@1
|
76
|
nuclear@0
|
77 void disp(void)
|
nuclear@0
|
78 {
|
nuclear@1
|
79 int i;
|
nuclear@1
|
80 float seed[2];
|
nuclear@1
|
81 static const float verts[][2] = {{-1, -1}, {1, -1}, {1, 1}, {-1, 1}};
|
nuclear@1
|
82 static const float corners[][2] = {{0, 1}, {1, 1}, {1, 0}, {0, 0}};
|
nuclear@1
|
83
|
nuclear@1
|
84 pixel_to_complex(seed, mouse_x, mouse_y);
|
nuclear@1
|
85
|
nuclear@1
|
86 set_uniform_float2(prog_mbrot, "seed", seed[0], seed[1]);
|
nuclear@1
|
87 set_uniform_float(prog_mbrot, "view_scale", view_scale);
|
nuclear@1
|
88 set_uniform_float2(prog_mbrot, "view_center", view_center[0], view_center[1]);
|
nuclear@0
|
89 glUseProgram(prog_mbrot);
|
nuclear@0
|
90
|
nuclear@0
|
91 glBegin(GL_QUADS);
|
nuclear@1
|
92 for(i=0; i<4; i++) {
|
nuclear@1
|
93 float bv[2];
|
nuclear@1
|
94 pixel_to_complex(bv, (win_width - 1) * corners[i][0], (win_height - 1) * corners[i][1]);
|
nuclear@1
|
95 glTexCoord2f(bv[0], bv[1]);
|
nuclear@1
|
96 glVertex2f(verts[i][0], verts[i][1]);
|
nuclear@1
|
97 }
|
nuclear@0
|
98 glEnd();
|
nuclear@0
|
99
|
nuclear@0
|
100 glutSwapBuffers();
|
nuclear@0
|
101 }
|
nuclear@0
|
102
|
nuclear@0
|
103 void reshape(int x, int y)
|
nuclear@0
|
104 {
|
nuclear@0
|
105 glViewport(0, 0, x, y);
|
nuclear@0
|
106
|
nuclear@1
|
107 win_aspect = (float)x / (float)y;
|
nuclear@1
|
108 win_width = x;
|
nuclear@1
|
109 win_height = y;
|
nuclear@0
|
110 }
|
nuclear@0
|
111
|
nuclear@1
|
112 static int keystate[256];
|
nuclear@1
|
113
|
nuclear@1
|
114 void keydown(unsigned char key, int x, int y)
|
nuclear@0
|
115 {
|
nuclear@1
|
116 static int fullscreen;
|
nuclear@1
|
117 static int prev_width, prev_height;
|
nuclear@1
|
118
|
nuclear@1
|
119 switch(key) {
|
nuclear@1
|
120 case 27:
|
nuclear@0
|
121 exit(0);
|
nuclear@1
|
122
|
nuclear@1
|
123 case 'f':
|
nuclear@1
|
124 fullscreen = !fullscreen;
|
nuclear@1
|
125 if(fullscreen) {
|
nuclear@1
|
126 prev_width = win_width;
|
nuclear@1
|
127 prev_height = win_height;
|
nuclear@1
|
128 glutFullScreen();
|
nuclear@1
|
129 } else {
|
nuclear@1
|
130 glutReshapeWindow(prev_width, prev_height);
|
nuclear@1
|
131 }
|
nuclear@1
|
132 break;
|
nuclear@1
|
133
|
nuclear@2
|
134 case '`':
|
nuclear@2
|
135 screenshot();
|
nuclear@2
|
136 break;
|
nuclear@2
|
137
|
nuclear@1
|
138 default:
|
nuclear@1
|
139 break;
|
nuclear@0
|
140 }
|
nuclear@1
|
141 keystate[key] = 1;
|
nuclear@0
|
142 }
|
nuclear@0
|
143
|
nuclear@1
|
144 void keyup(unsigned char key, int x, int y)
|
nuclear@1
|
145 {
|
nuclear@1
|
146 keystate[key] = 0;
|
nuclear@1
|
147 }
|
nuclear@1
|
148
|
nuclear@1
|
149 static int prev_x, prev_y;
|
nuclear@1
|
150 static int bnstate[8];
|
nuclear@1
|
151
|
nuclear@0
|
152 void mouse(int bn, int st, int x, int y)
|
nuclear@0
|
153 {
|
nuclear@1
|
154 prev_x = x;
|
nuclear@1
|
155 prev_y = y;
|
nuclear@1
|
156 bnstate[bn - GLUT_LEFT_BUTTON] = st == GLUT_DOWN ? 1 : 0;
|
nuclear@0
|
157 }
|
nuclear@0
|
158
|
nuclear@0
|
159 void motion(int x, int y)
|
nuclear@0
|
160 {
|
nuclear@1
|
161 int dx = x - prev_x;
|
nuclear@1
|
162 int dy = y - prev_y;
|
nuclear@1
|
163 prev_x = x;
|
nuclear@1
|
164 prev_y = y;
|
nuclear@1
|
165
|
nuclear@1
|
166 if(!(dx | dy)) return;
|
nuclear@1
|
167
|
nuclear@1
|
168 if(bnstate[0]) {
|
nuclear@1
|
169 if(keystate['s']) {
|
nuclear@1
|
170 mouse_x = x;
|
nuclear@1
|
171 mouse_y = y;
|
nuclear@1
|
172 } else if(keystate['z']) {
|
nuclear@1
|
173 float s = sqrt(view_scale);
|
nuclear@1
|
174 view_scale += dy * 0.01 * s;
|
nuclear@1
|
175 if(view_scale < 1e-8) view_scale = 1e-8;
|
nuclear@1
|
176 } else {
|
nuclear@1
|
177 float s = sqrt(view_scale);
|
nuclear@1
|
178 view_center[0] += 0.01 * dx * s;
|
nuclear@1
|
179 view_center[1] += 0.01 * dy * s;
|
nuclear@1
|
180 }
|
nuclear@1
|
181 glutPostRedisplay();
|
nuclear@1
|
182 }
|
nuclear@0
|
183 }
|
nuclear@2
|
184
|
nuclear@2
|
185 void screenshot(void)
|
nuclear@2
|
186 {
|
nuclear@2
|
187 FILE *fp;
|
nuclear@2
|
188 DIR *dir;
|
nuclear@2
|
189 struct dirent *dent;
|
nuclear@2
|
190 unsigned char *img;
|
nuclear@2
|
191 static int shotnum = -1;
|
nuclear@2
|
192 char fname[128];
|
nuclear@2
|
193
|
nuclear@2
|
194 if(shotnum == -1) {
|
nuclear@2
|
195 shotnum = 1;
|
nuclear@2
|
196 if((dir = opendir("."))) {
|
nuclear@2
|
197 while((dent = readdir(dir))) {
|
nuclear@2
|
198 int num;
|
nuclear@2
|
199 if(sscanf(dent->d_name, "img%d.ppm", &num) == 1) {
|
nuclear@2
|
200 if(num >= shotnum) shotnum = num + 1;
|
nuclear@2
|
201 }
|
nuclear@2
|
202 }
|
nuclear@2
|
203 closedir(dir);
|
nuclear@2
|
204 }
|
nuclear@2
|
205 } else {
|
nuclear@2
|
206 ++shotnum;
|
nuclear@2
|
207 }
|
nuclear@2
|
208
|
nuclear@2
|
209 sprintf(fname, "img%04d.ppm", shotnum > 0 ? shotnum : 0);
|
nuclear@2
|
210 if(!(fp = fopen(fname, "wb"))) {
|
nuclear@2
|
211 fprintf(stderr, "failed to open %s for writing: %s\n", fname, strerror(errno));
|
nuclear@2
|
212 return;
|
nuclear@2
|
213 }
|
nuclear@2
|
214
|
nuclear@2
|
215 if(!(img = malloc(win_width * win_height * 3))) {
|
nuclear@2
|
216 fprintf(stderr, "failed to allocate screenshot buffer\n");
|
nuclear@2
|
217 fclose(fp);
|
nuclear@2
|
218 return;
|
nuclear@2
|
219 }
|
nuclear@2
|
220
|
nuclear@2
|
221 glReadPixels(0, 0, win_width, win_height, GL_RGB, GL_UNSIGNED_BYTE, img);
|
nuclear@2
|
222
|
nuclear@2
|
223 fprintf(fp, "P6\n%d %d\n255\n", win_width, win_height);
|
nuclear@2
|
224 fwrite(img, 1, win_width * win_height * 3, fp);
|
nuclear@2
|
225 fclose(fp);
|
nuclear@2
|
226 free(img);
|
nuclear@2
|
227 return;
|
nuclear@2
|
228 }
|