rev |
line source |
nuclear@2
|
1 #include <stdio.h>
|
nuclear@2
|
2 #include <stdlib.h>
|
nuclear@34
|
3 #include <string.h>
|
nuclear@2
|
4 #include <assert.h>
|
nuclear@29
|
5 #include <signal.h>
|
nuclear@19
|
6 #include <vector>
|
nuclear@26
|
7 #include <chrono>
|
nuclear@29
|
8 #include <imago2.h>
|
nuclear@32
|
9 #include <drawtext.h>
|
nuclear@2
|
10 #include "opengl.h"
|
nuclear@4
|
11 #include "erebus.h"
|
nuclear@2
|
12
|
nuclear@26
|
13 using namespace std::chrono;
|
nuclear@26
|
14
|
nuclear@2
|
15 static bool init();
|
nuclear@2
|
16 static void cleanup();
|
nuclear@32
|
17 static void begin_frame(long tm);
|
nuclear@32
|
18 static void end_frame();
|
nuclear@2
|
19 static void resize_rtarget(int xsz, int ysz);
|
nuclear@2
|
20 static void update_rect(int x, int y, int xsz, int ysz, float *pixels);
|
nuclear@4
|
21 static void idle();
|
nuclear@2
|
22 static void display();
|
nuclear@32
|
23 static void display_statusbar(const erb_render_status &status);
|
nuclear@29
|
24 static void save_image(const char *fname = 0);
|
nuclear@2
|
25 static void reshape(int x, int y);
|
nuclear@2
|
26 static void keyb(unsigned char key, int x, int y);
|
nuclear@9
|
27 static void keyb_up(unsigned char key, int x, int y);
|
nuclear@2
|
28 static void mouse(int bn, int st, int x, int y);
|
nuclear@9
|
29 static void motion(int x, int y);
|
nuclear@9
|
30 static void sball_button(int bn, int st);
|
nuclear@9
|
31 static void sball_motion(int x, int y, int z);
|
nuclear@2
|
32 static int next_pow2(int x);
|
nuclear@29
|
33 static void sighandler(int s);
|
nuclear@32
|
34 static bool parse_args(int argc, char **argv);
|
nuclear@2
|
35
|
nuclear@32
|
36 static int win_width, win_height, width, height, rtex_width, rtex_height;
|
nuclear@2
|
37 static unsigned int rtex;
|
nuclear@2
|
38
|
nuclear@32
|
39 static int opt_samples = -1;
|
nuclear@32
|
40 static int opt_iter = -1;
|
nuclear@32
|
41 static int opt_threads = -1;
|
nuclear@32
|
42 static float opt_imgscale = 2.0f;
|
nuclear@32
|
43
|
nuclear@4
|
44 static erebus *erb;
|
nuclear@4
|
45 static bool render_pending;
|
nuclear@32
|
46 static bool show_status = true;
|
nuclear@32
|
47 static steady_clock::time_point start_time;
|
nuclear@4
|
48
|
nuclear@19
|
49 static std::vector<char*> sfiles;
|
nuclear@4
|
50
|
nuclear@32
|
51 static dtx_font *font;
|
nuclear@32
|
52
|
nuclear@2
|
53 int main(int argc, char **argv)
|
nuclear@2
|
54 {
|
nuclear@2
|
55 glutInitWindowSize(1024, 600);
|
nuclear@2
|
56 glutInit(&argc, argv);
|
nuclear@19
|
57
|
nuclear@32
|
58 if(!parse_args(argc, argv)) {
|
nuclear@32
|
59 return 1;
|
nuclear@19
|
60 }
|
nuclear@19
|
61
|
nuclear@2
|
62 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
|
nuclear@2
|
63 glutCreateWindow("erebus OpenGL frontend");
|
nuclear@2
|
64
|
nuclear@2
|
65 glutDisplayFunc(display);
|
nuclear@2
|
66 glutReshapeFunc(reshape);
|
nuclear@2
|
67 glutKeyboardFunc(keyb);
|
nuclear@9
|
68 glutKeyboardUpFunc(keyb_up);
|
nuclear@2
|
69 glutMouseFunc(mouse);
|
nuclear@9
|
70 glutMotionFunc(motion);
|
nuclear@9
|
71 glutSpaceballButtonFunc(sball_button);
|
nuclear@9
|
72 glutSpaceballMotionFunc(sball_motion);
|
nuclear@2
|
73
|
nuclear@2
|
74 if(!init()) {
|
nuclear@2
|
75 return 1;
|
nuclear@2
|
76 }
|
nuclear@2
|
77 atexit(cleanup);
|
nuclear@29
|
78 signal(SIGINT, sighandler);
|
nuclear@29
|
79 signal(SIGSEGV, sighandler);
|
nuclear@29
|
80 signal(SIGILL, sighandler);
|
nuclear@29
|
81 signal(SIGTERM, sighandler);
|
nuclear@29
|
82 signal(SIGFPE, sighandler);
|
nuclear@2
|
83
|
nuclear@2
|
84 glutMainLoop();
|
nuclear@2
|
85 }
|
nuclear@2
|
86
|
nuclear@2
|
87 static bool init()
|
nuclear@2
|
88 {
|
nuclear@32
|
89 width = glutGet(GLUT_WINDOW_WIDTH) / opt_imgscale;
|
nuclear@32
|
90 height = glutGet(GLUT_WINDOW_HEIGHT) / opt_imgscale;
|
nuclear@32
|
91
|
nuclear@34
|
92 //if(!(font = dtx_open_font("/usr/share/fonts/opentype/linux-libertine/LinLibertine_R.otf", 22))) {
|
nuclear@32
|
93 if(!(font = dtx_open_font_glyphmap("data/serif.glyphmap"))) {
|
nuclear@32
|
94 fprintf(stderr, "warning: failed to load font!\n");
|
nuclear@32
|
95 }
|
nuclear@5
|
96
|
nuclear@4
|
97 if(!(erb = erb_init())) {
|
nuclear@4
|
98 return false;
|
nuclear@4
|
99 }
|
nuclear@4
|
100 erb_setopti(erb, ERB_OPT_WIDTH, width);
|
nuclear@4
|
101 erb_setopti(erb, ERB_OPT_HEIGHT, height);
|
nuclear@4
|
102
|
nuclear@32
|
103 if(opt_samples != -1) {
|
nuclear@32
|
104 erb_setopti(erb, ERB_OPT_MAX_SAMPLES, opt_samples);
|
nuclear@32
|
105 }
|
nuclear@32
|
106 if(opt_iter != -1) {
|
nuclear@32
|
107 erb_setopti(erb, ERB_OPT_MAX_ITER, opt_iter);
|
nuclear@32
|
108 }
|
nuclear@32
|
109 if(opt_threads != -1) {
|
nuclear@32
|
110 erb_setopti(erb, ERB_OPT_NUM_THREADS, opt_threads);
|
nuclear@32
|
111 }
|
nuclear@32
|
112
|
nuclear@19
|
113 for(size_t i=0; i<sfiles.size(); i++) {
|
nuclear@19
|
114 printf("loading scene file: %s\n", sfiles[i]);
|
nuclear@19
|
115 if(erb_load_scene(erb, sfiles[i]) == -1) {
|
nuclear@19
|
116 return false;
|
nuclear@19
|
117 }
|
nuclear@4
|
118 }
|
nuclear@4
|
119
|
nuclear@21
|
120 if(!sfiles.empty()) {
|
nuclear@32
|
121 begin_frame(0);
|
nuclear@21
|
122 }
|
nuclear@4
|
123
|
nuclear@8
|
124 glEnable(GL_TEXTURE_2D);
|
nuclear@2
|
125 return true;
|
nuclear@2
|
126 }
|
nuclear@2
|
127
|
nuclear@2
|
128 static void cleanup()
|
nuclear@2
|
129 {
|
nuclear@29
|
130 save_image("final.png");
|
nuclear@4
|
131 erb_destroy(erb);
|
nuclear@2
|
132 }
|
nuclear@2
|
133
|
nuclear@32
|
134 static void begin_frame(long tm)
|
nuclear@32
|
135 {
|
nuclear@32
|
136 printf("rendering frame (t=%ld) ... ", tm);
|
nuclear@32
|
137 fflush(stdout);
|
nuclear@32
|
138
|
nuclear@32
|
139 render_pending = true;
|
nuclear@32
|
140 glutIdleFunc(idle);
|
nuclear@32
|
141 erb_begin_frame(erb, 0);
|
nuclear@32
|
142
|
nuclear@32
|
143 start_time = steady_clock::now();
|
nuclear@32
|
144 }
|
nuclear@32
|
145
|
nuclear@32
|
146 static void end_frame()
|
nuclear@32
|
147 {
|
nuclear@32
|
148 if(!render_pending) return;
|
nuclear@32
|
149
|
nuclear@32
|
150 auto dur = steady_clock::now() - start_time;
|
nuclear@32
|
151 long full_msec = duration_cast<milliseconds>(dur).count();
|
nuclear@32
|
152 long msec, sec, min, hr, days;
|
nuclear@32
|
153
|
nuclear@32
|
154 msec = full_msec;
|
nuclear@32
|
155 printf("done in ");
|
nuclear@32
|
156 if((sec = msec / 1000) > 0) {
|
nuclear@32
|
157 msec %= 1000;
|
nuclear@32
|
158 if((min = sec / 60) > 0) {
|
nuclear@32
|
159 sec %= 60;
|
nuclear@32
|
160 if((hr = min / 60) > 0) {
|
nuclear@32
|
161 min %= 60;
|
nuclear@32
|
162 if((days = hr / 24) > 0) {
|
nuclear@32
|
163 hr %= 24;
|
nuclear@32
|
164 printf("%ld days ", days);
|
nuclear@32
|
165 }
|
nuclear@32
|
166 printf("%ld hours ", hr);
|
nuclear@32
|
167 }
|
nuclear@32
|
168 printf("%ld min ", min);
|
nuclear@32
|
169 }
|
nuclear@32
|
170 printf("%ld sec ", sec);
|
nuclear@32
|
171 }
|
nuclear@32
|
172 printf("%ld ms (%ld total msec)\n", msec, full_msec);
|
nuclear@32
|
173
|
nuclear@32
|
174 render_pending = false;
|
nuclear@32
|
175 glutIdleFunc(0);
|
nuclear@32
|
176 }
|
nuclear@32
|
177
|
nuclear@2
|
178 static void resize_rtarget(int xsz, int ysz)
|
nuclear@2
|
179 {
|
nuclear@2
|
180 static unsigned char *defpix;
|
nuclear@2
|
181
|
nuclear@32
|
182 win_width = xsz;
|
nuclear@32
|
183 win_height = ysz;
|
nuclear@32
|
184
|
nuclear@32
|
185 width = xsz / opt_imgscale;
|
nuclear@32
|
186 height = ysz / opt_imgscale;
|
nuclear@2
|
187
|
nuclear@8
|
188 if(width <= rtex_width && height <= rtex_height) {
|
nuclear@2
|
189 return;
|
nuclear@2
|
190 }
|
nuclear@8
|
191 rtex_width = next_pow2(width);
|
nuclear@8
|
192 rtex_height = next_pow2(height);
|
nuclear@2
|
193
|
nuclear@2
|
194 printf("resizing framebuffer texture: %dx%d\n", rtex_width, rtex_height);
|
nuclear@2
|
195
|
nuclear@2
|
196 if(!rtex) {
|
nuclear@2
|
197 glGenTextures(1, &rtex);
|
nuclear@2
|
198 }
|
nuclear@2
|
199
|
nuclear@2
|
200 delete [] defpix;
|
nuclear@2
|
201 defpix = new unsigned char[rtex_width * rtex_height * 4];
|
nuclear@2
|
202 unsigned char *ptr = defpix;
|
nuclear@2
|
203 for(int i=0; i<rtex_height; i++) {
|
nuclear@2
|
204 for(int j=0; j<rtex_width; j++) {
|
nuclear@2
|
205 bool chess = ((i >> 4) & 1) == ((j >> 4) & 1);
|
nuclear@2
|
206
|
nuclear@2
|
207 int val = chess ? 64 : 48;
|
nuclear@2
|
208
|
nuclear@2
|
209 *ptr++ = val;
|
nuclear@2
|
210 *ptr++ = val;
|
nuclear@2
|
211 *ptr++ = val;
|
nuclear@2
|
212 *ptr++ = 255;
|
nuclear@2
|
213 }
|
nuclear@2
|
214 }
|
nuclear@2
|
215
|
nuclear@2
|
216 glBindTexture(GL_TEXTURE_2D, rtex);
|
nuclear@2
|
217 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
nuclear@2
|
218 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
nuclear@2
|
219 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F_ARB, rtex_width, rtex_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, defpix);
|
nuclear@2
|
220 }
|
nuclear@2
|
221
|
nuclear@2
|
222 static void update_rect(int x, int y, int xsz, int ysz, float *pixels)
|
nuclear@2
|
223 {
|
nuclear@2
|
224 glBindTexture(GL_TEXTURE_2D, rtex);
|
nuclear@2
|
225 glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, xsz, ysz, GL_RGBA, GL_FLOAT, pixels);
|
nuclear@2
|
226 }
|
nuclear@2
|
227
|
nuclear@4
|
228 static void idle()
|
nuclear@4
|
229 {
|
nuclear@4
|
230 glutPostRedisplay();
|
nuclear@4
|
231 }
|
nuclear@4
|
232
|
nuclear@2
|
233 static void display()
|
nuclear@2
|
234 {
|
nuclear@32
|
235 static struct erb_render_status status;
|
nuclear@32
|
236
|
nuclear@4
|
237 if(render_pending) {
|
nuclear@8
|
238 if(erb_render(erb, 64) == 0) {
|
nuclear@32
|
239 end_frame();
|
nuclear@4
|
240 }
|
nuclear@4
|
241 update_rect(0, 0, width, height, erb_get_framebuffer(erb));
|
nuclear@32
|
242 erb_get_status(erb, &status);
|
nuclear@4
|
243 }
|
nuclear@4
|
244
|
nuclear@2
|
245 float maxu = (float)width / (float)rtex_width;
|
nuclear@2
|
246 float maxv = (float)height / (float)rtex_height;
|
nuclear@2
|
247
|
nuclear@34
|
248 glEnable(GL_TEXTURE_2D);
|
nuclear@34
|
249 glBindTexture(GL_TEXTURE_2D, rtex);
|
nuclear@34
|
250
|
nuclear@2
|
251 glBegin(GL_QUADS);
|
nuclear@32
|
252 glColor4f(1, 1, 1, 1);
|
nuclear@2
|
253 glTexCoord2f(0, maxv); glVertex2f(-1, -1);
|
nuclear@2
|
254 glTexCoord2f(maxu, maxv); glVertex2f(1, -1);
|
nuclear@2
|
255 glTexCoord2f(maxu, 0); glVertex2f(1, 1);
|
nuclear@2
|
256 glTexCoord2f(0, 0); glVertex2f(-1, 1);
|
nuclear@2
|
257 glEnd();
|
nuclear@2
|
258
|
nuclear@32
|
259 // draw progress information etc...
|
nuclear@32
|
260 if(show_status) {
|
nuclear@32
|
261 display_statusbar(status);
|
nuclear@32
|
262 }
|
nuclear@32
|
263
|
nuclear@2
|
264 glutSwapBuffers();
|
nuclear@2
|
265 assert(glGetError() == GL_NO_ERROR);
|
nuclear@2
|
266 }
|
nuclear@2
|
267
|
nuclear@32
|
268 static void display_statusbar(const erb_render_status &status)
|
nuclear@32
|
269 {
|
nuclear@32
|
270 if(!font) return;
|
nuclear@32
|
271
|
nuclear@32
|
272 bool show_progress = opt_samples > 0;
|
nuclear@32
|
273
|
nuclear@32
|
274 glDisable(GL_TEXTURE_2D);
|
nuclear@32
|
275
|
nuclear@32
|
276 glMatrixMode(GL_PROJECTION);
|
nuclear@32
|
277 glPushMatrix();
|
nuclear@32
|
278 glLoadIdentity();
|
nuclear@32
|
279 glOrtho(0, win_width, 0, win_height, -1, 1);
|
nuclear@32
|
280
|
nuclear@32
|
281 glMatrixMode(GL_MODELVIEW);
|
nuclear@32
|
282 glPushMatrix();
|
nuclear@32
|
283 glLoadIdentity();
|
nuclear@32
|
284
|
nuclear@34
|
285 dtx_box bbox;
|
nuclear@34
|
286 dtx_glyph_box('Q', &bbox);
|
nuclear@34
|
287
|
nuclear@34
|
288 // draw progress/status bar
|
nuclear@34
|
289 int bar_height = bbox.height + 4;
|
nuclear@32
|
290 int prog_width = show_progress ? status.progress_percent * win_width / 100 : 0;
|
nuclear@32
|
291
|
nuclear@32
|
292 glBegin(GL_QUADS);
|
nuclear@32
|
293 glColor4f(0, 0, 0, 1);
|
nuclear@32
|
294 glVertex2f(prog_width, 0);
|
nuclear@32
|
295 glVertex2f(win_width, 0);
|
nuclear@34
|
296 glVertex2f(win_width, bar_height);
|
nuclear@34
|
297 glVertex2f(prog_width, bar_height);
|
nuclear@32
|
298
|
nuclear@32
|
299 glColor4f(0.25, 0, 0, 1);
|
nuclear@32
|
300 glVertex2f(0, 0);
|
nuclear@32
|
301 glVertex2f(prog_width, 0);
|
nuclear@34
|
302 glVertex2f(prog_width, bar_height);
|
nuclear@34
|
303 glVertex2f(0, bar_height);
|
nuclear@32
|
304 glEnd();
|
nuclear@32
|
305
|
nuclear@34
|
306 // draw the text
|
nuclear@34
|
307 glTranslatef(bbox.x + 2, bbox.y + 2, 0);
|
nuclear@32
|
308
|
nuclear@32
|
309 glColor4f(1, 1, 1, 1);
|
nuclear@32
|
310
|
nuclear@32
|
311 if(opt_samples > 0) {
|
nuclear@34
|
312 dtx_printf("samples: %ld / %ld", status.samples, status.max_samples);
|
nuclear@32
|
313
|
nuclear@34
|
314 glLoadIdentity();
|
nuclear@34
|
315 glTranslatef(win_width - dtx_string_width("progress: 100%") - 2, bbox.y + 2, 0);
|
nuclear@34
|
316 dtx_printf("progress: %ld%%", status.progress_percent);
|
nuclear@32
|
317 } else {
|
nuclear@34
|
318 dtx_printf("samples: %ld", status.samples);
|
nuclear@32
|
319 }
|
nuclear@34
|
320
|
nuclear@34
|
321 // samples/sec display
|
nuclear@34
|
322 static long paths_per_sec, prev_msec, prev_paths;
|
nuclear@34
|
323
|
nuclear@34
|
324 long msec = duration_cast<milliseconds>(steady_clock::now() - start_time).count();
|
nuclear@34
|
325 long dt = msec - prev_msec;
|
nuclear@34
|
326
|
nuclear@34
|
327 if(dt >= 1500) { // average over 1.5 seconds
|
nuclear@34
|
328 long paths = status.samples * width * height;
|
nuclear@34
|
329 if(prev_msec > 0 && prev_paths <= paths) { // check valid interval (not a restart or whatever)
|
nuclear@34
|
330 paths_per_sec = 1000 * (paths - prev_paths) / dt;
|
nuclear@34
|
331 }
|
nuclear@34
|
332 prev_msec = msec;
|
nuclear@34
|
333 prev_paths = paths;
|
nuclear@34
|
334 }
|
nuclear@34
|
335
|
nuclear@34
|
336 glLoadIdentity();
|
nuclear@34
|
337 glTranslatef((win_width - dtx_string_width("paths/s: 999999")) / 2, bbox.y + 2, 0);
|
nuclear@34
|
338 if(paths_per_sec) {
|
nuclear@34
|
339 dtx_printf("paths/s: %ld", paths_per_sec);
|
nuclear@34
|
340 } else {
|
nuclear@34
|
341 dtx_printf("paths/s: ???");
|
nuclear@34
|
342 }
|
nuclear@34
|
343
|
nuclear@32
|
344 glPopMatrix();
|
nuclear@32
|
345 glMatrixMode(GL_PROJECTION);
|
nuclear@32
|
346 glPopMatrix();
|
nuclear@32
|
347 }
|
nuclear@32
|
348
|
nuclear@29
|
349 static void save_image(const char *fname)
|
nuclear@29
|
350 {
|
nuclear@29
|
351 float *fb = erb_get_framebuffer(erb);
|
nuclear@29
|
352
|
nuclear@29
|
353 if(img_save_pixels(fname ? fname : "output.png", fb, width, height, IMG_FMT_RGBAF) == -1) {
|
nuclear@29
|
354 fprintf(stderr, "failed to save image\n");
|
nuclear@29
|
355 }
|
nuclear@29
|
356 }
|
nuclear@29
|
357
|
nuclear@2
|
358 static void reshape(int x, int y)
|
nuclear@2
|
359 {
|
nuclear@2
|
360 glViewport(0, 0, x, y);
|
nuclear@2
|
361 resize_rtarget(x, y);
|
nuclear@4
|
362
|
nuclear@4
|
363 erb_setopti(erb, ERB_OPT_WIDTH, width);
|
nuclear@4
|
364 erb_setopti(erb, ERB_OPT_HEIGHT, height);
|
nuclear@2
|
365 }
|
nuclear@2
|
366
|
nuclear@2
|
367 static void keyb(unsigned char key, int x, int y)
|
nuclear@2
|
368 {
|
nuclear@2
|
369 switch(key) {
|
nuclear@2
|
370 case 27:
|
nuclear@32
|
371 end_frame();
|
nuclear@2
|
372 exit(0);
|
nuclear@4
|
373
|
nuclear@4
|
374 case ' ':
|
nuclear@32
|
375 begin_frame(0);
|
nuclear@4
|
376 break;
|
nuclear@29
|
377
|
nuclear@34
|
378 case '\b':
|
nuclear@29
|
379 printf("saving image.\n");
|
nuclear@29
|
380 save_image();
|
nuclear@29
|
381 break;
|
nuclear@32
|
382
|
nuclear@34
|
383 case '`':
|
nuclear@32
|
384 show_status = !show_status;
|
nuclear@32
|
385 glutPostRedisplay();
|
nuclear@32
|
386 break;
|
nuclear@2
|
387 }
|
nuclear@9
|
388
|
nuclear@10
|
389 if(erb_input_keyboard(erb, key, true)) {
|
nuclear@9
|
390 glutPostRedisplay();
|
nuclear@9
|
391 }
|
nuclear@9
|
392 }
|
nuclear@9
|
393
|
nuclear@9
|
394 static void keyb_up(unsigned char key, int x, int y)
|
nuclear@9
|
395 {
|
nuclear@10
|
396 if(erb_input_keyboard(erb, key, false)) {
|
nuclear@9
|
397 glutPostRedisplay();
|
nuclear@9
|
398 }
|
nuclear@2
|
399 }
|
nuclear@2
|
400
|
nuclear@2
|
401 static void mouse(int bn, int st, int x, int y)
|
nuclear@2
|
402 {
|
nuclear@10
|
403 if(erb_input_mouse_button(erb, bn - GLUT_LEFT_BUTTON, st == GLUT_DOWN, x, y)) {
|
nuclear@9
|
404 glutPostRedisplay();
|
nuclear@9
|
405 }
|
nuclear@9
|
406 }
|
nuclear@9
|
407
|
nuclear@9
|
408 static void motion(int x, int y)
|
nuclear@9
|
409 {
|
nuclear@15
|
410 if(erb_input_mouse_motion(erb, x, y)) {
|
nuclear@9
|
411 glutPostRedisplay();
|
nuclear@9
|
412 }
|
nuclear@9
|
413 }
|
nuclear@9
|
414
|
nuclear@9
|
415 static void sball_button(int bn, int state)
|
nuclear@9
|
416 {
|
nuclear@10
|
417 if(erb_input_6dof_button(erb, bn, state == GLUT_DOWN)) {
|
nuclear@9
|
418 glutPostRedisplay();
|
nuclear@9
|
419 }
|
nuclear@9
|
420 }
|
nuclear@9
|
421
|
nuclear@9
|
422 static void sball_motion(int x, int y, int z)
|
nuclear@9
|
423 {
|
nuclear@10
|
424 if(erb_input_6dof_motion(erb, x / 65536.0, y / 65536.0, z / 65536.0)) {
|
nuclear@9
|
425 glutPostRedisplay();
|
nuclear@9
|
426 }
|
nuclear@2
|
427 }
|
nuclear@2
|
428
|
nuclear@2
|
429 static int next_pow2(int x)
|
nuclear@2
|
430 {
|
nuclear@2
|
431 int res = 2;
|
nuclear@2
|
432 while(res < x) {
|
nuclear@2
|
433 res <<= 1;
|
nuclear@2
|
434 }
|
nuclear@2
|
435 return res;
|
nuclear@2
|
436 }
|
nuclear@29
|
437
|
nuclear@29
|
438 static void sighandler(int s)
|
nuclear@29
|
439 {
|
nuclear@29
|
440 exit(0);
|
nuclear@29
|
441 }
|
nuclear@32
|
442
|
nuclear@32
|
443 static bool parse_args(int argc, char **argv)
|
nuclear@32
|
444 {
|
nuclear@32
|
445 for(int i=1; i<argc; i++) {
|
nuclear@32
|
446 if(argv[i][0] == '-') {
|
nuclear@32
|
447 if(strcmp(argv[i], "-samples") == 0) {
|
nuclear@32
|
448 opt_samples = atoi(argv[++i]);
|
nuclear@32
|
449 if(opt_samples <= 0) {
|
nuclear@32
|
450 fprintf(stderr, "invalid -samples option: %s\n", argv[i]);
|
nuclear@32
|
451 return false;
|
nuclear@32
|
452 }
|
nuclear@32
|
453
|
nuclear@32
|
454 } else if(strcmp(argv[i], "-iter") == 0) {
|
nuclear@32
|
455 opt_iter = atoi(argv[++i]);
|
nuclear@32
|
456 if(opt_iter <= 0) {
|
nuclear@32
|
457 fprintf(stderr, "invalid -iter option: %s\n", argv[i]);
|
nuclear@32
|
458 return false;
|
nuclear@32
|
459 }
|
nuclear@32
|
460
|
nuclear@32
|
461 } else if(strcmp(argv[i], "-threads") == 0) {
|
nuclear@32
|
462 opt_threads = atoi(argv[++i]);
|
nuclear@32
|
463 if(opt_threads <= 0) {
|
nuclear@32
|
464 fprintf(stderr, "invalid -threads option: %s\n", argv[i]);
|
nuclear@32
|
465 return false;
|
nuclear@32
|
466 }
|
nuclear@32
|
467
|
nuclear@32
|
468 } else if(strcmp(argv[i], "-scale") == 0) {
|
nuclear@32
|
469 opt_imgscale = atof(argv[++i]);
|
nuclear@32
|
470 if(opt_imgscale <= 0.0f) {
|
nuclear@32
|
471 fprintf(stderr, "invalid -scale option: %s\n", argv[i]);
|
nuclear@32
|
472 return false;
|
nuclear@32
|
473 }
|
nuclear@32
|
474
|
nuclear@32
|
475 } else {
|
nuclear@32
|
476 fprintf(stderr, "invalid option: %s\n", argv[i]);
|
nuclear@32
|
477 return false;
|
nuclear@32
|
478 }
|
nuclear@32
|
479 } else {
|
nuclear@32
|
480 sfiles.push_back(argv[i]);
|
nuclear@32
|
481 }
|
nuclear@32
|
482 }
|
nuclear@32
|
483
|
nuclear@32
|
484 return true;
|
nuclear@34
|
485 }
|