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