ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/gen/mkillum.c
Revision: 2.20
Committed: Fri Sep 17 21:43:50 2004 UTC (19 years, 6 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.19: +83 -37 lines
Log Message:
Added -n option to mkillum for multiprocessing on shared memory machine

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: mkillum.c,v 2.19 2003/11/16 10:29:38 schorsch Exp $";
3 #endif
4 /*
5 * Make illum sources for optimizing rendering process
6 */
7
8 #include <signal.h>
9 #include <ctype.h>
10
11 #include "platform.h"
12 #include "mkillum.h"
13 #include "random.h"
14
15 /* default parameters */
16 #define SAMPDENS 48 /* points per projected steradian */
17 #define NSAMPS 32 /* samples per point */
18 #define DFLMAT "illum_mat" /* material name */
19 #define DFLDAT "illum" /* data file name */
20 /* selection options */
21 #define S_NONE 0 /* select none */
22 #define S_ELEM 1 /* select specified element */
23 #define S_COMPL 2 /* select all but element */
24 #define S_ALL 3 /* select all */
25
26 /* rtrace command and defaults */
27 char *rtargv[64] = { "rtrace", "-dj", ".25", "-dr", "3", "-dv-",
28 "-ab", "2", "-ad", "1024", "-as", "512", "-aa", ".1", };
29 int rtargc = 14;
30 /* overriding rtrace options */
31 char *myrtopts[] = { "-I-", "-i-", "-ld-", "-ov", "-h-",
32 "-fff", "-y", "0", NULL };
33
34 struct rtproc rt0; /* head of rtrace process list */
35
36 struct illum_args thisillum = { /* our illum and default values */
37 0,
38 DFLMAT,
39 DFLDAT,
40 0,
41 VOIDID,
42 SAMPDENS,
43 NSAMPS,
44 0.,
45 };
46
47 char matcheck[MAXSTR]; /* current material to include or exclude */
48 int matselect = S_ALL; /* selection criterion */
49
50 FUN ofun[NUMOTYPE] = INIT_OTYPE; /* object types */
51
52 char persistfn[] = "pfXXXXXX"; /* persist file name */
53
54 int gargc; /* global argc */
55 char **gargv; /* global argv */
56 #define progname gargv[0]
57
58 int doneheader = 0; /* printed header yet? */
59 #define checkhead() if (!doneheader++) printhead(gargc,gargv)
60
61 int warnings = 1; /* print warnings? */
62
63 void init(int np);
64 void filter(register FILE *infp, char *name);
65 void xoptions(char *s, char *nm);
66 void printopts(void);
67 void printhead(register int ac, register char **av);
68 void xobject(FILE *fp, char *nm);
69
70
71 int
72 main( /* compute illum distributions using rtrace */
73 int argc,
74 char *argv[]
75 )
76 {
77 int nprocs = 1;
78 char *rtpath;
79 FILE *fp;
80 register int i;
81 /* set global arguments */
82 gargv = argv;
83 /* check for -n option */
84 if (!strcmp(argv[1], "-n")) {
85 nprocs = atoi(argv[2]);
86 if (nprocs <= 0)
87 error(USER, "illegal number of processes");
88 i = 3;
89 } else
90 i = 1;
91 /* set up rtrace command */
92 for ( ; i < argc; i++) {
93 if (argv[i][0] == '<' && argv[i][1] == '\0')
94 break;
95 rtargv[rtargc++] = argv[i];
96 if (argv[i][0] == '-' && argv[i][1] == 'w')
97 switch (argv[i][2]) {
98 case '\0':
99 warnings = !warnings;
100 break;
101 case '+':
102 case 'T': case 't':
103 case 'Y': case 'y':
104 case '1':
105 warnings = 1;
106 break;
107 case '-':
108 case 'F': case 'f':
109 case 'N': case 'n':
110 case '0':
111 warnings = 0;
112 break;
113 }
114 }
115 gargc = i;
116 if (!strcmp(rtargv[--rtargc], "-defaults"))
117 nprocs = 0;
118 if (nprocs > 1) { /* add persist file if parallel invocation */
119 rtargv[rtargc++] = "-PP";
120 rtargv[rtargc++] = mktemp(persistfn);
121 }
122 /* add "mandatory" rtrace options */
123 for (i = 0; myrtopts[i] != NULL; i++)
124 rtargv[rtargc++] = myrtopts[i];
125 /* finally, put back final argument */
126 rtargv[rtargc++] = argv[gargc-1];
127 rtargv[rtargc] = NULL;
128 if (!nprocs) { /* just asking for defaults? */
129 printopts(); fflush(stdout);
130 rtpath = getpath(rtargv[0], getenv("PATH"), X_OK);
131 if (rtpath == NULL) {
132 eputs(rtargv[0]);
133 eputs(": command not found\n");
134 exit(1);
135 }
136 execv(rtpath, rtargv);
137 perror(rtpath); /* execv() should not return */
138 exit(1);
139 }
140 if (gargc < 2 || argv[gargc-1][0] == '-')
141 error(USER, "missing octree argument");
142 /* else initialize and run our calculation */
143 init(nprocs);
144 if (gargc+1 < argc)
145 for (i = gargc+1; i < argc; i++) {
146 if ((fp = fopen(argv[i], "r")) == NULL) {
147 sprintf(errmsg,
148 "cannot open scene file \"%s\"", argv[i]);
149 error(SYSTEM, errmsg);
150 }
151 filter(fp, argv[i]);
152 fclose(fp);
153 }
154 else
155 filter(stdin, "standard input");
156 quit(0);
157 }
158
159 static void
160 killpersist(void) /* kill persistent process */
161 {
162 FILE *fp = fopen(persistfn, "r");
163 int pid;
164
165 if (fp == NULL)
166 return;
167 if (fscanf(fp, "%*s %d", &pid) != 1 || kill(pid, SIGALRM) < 0)
168 unlink(persistfn);
169 fclose(fp);
170 }
171
172 void
173 quit(int status) /* exit with status */
174 {
175 struct rtproc *rtp;
176 int rtstat;
177
178 if (rt0.next != NULL) /* terminate persistent rtrace */
179 killpersist();
180 /* clean up rtrace process(es) */
181 for (rtp = &rt0; rtp != NULL; rtp = rtp->next) {
182 rtstat = close_process(&rtp->pd);
183 if (status == 0) {
184 if (rtstat < 0)
185 error(WARNING,
186 "unknown return status from rtrace process");
187 else
188 status = rtstat;
189 }
190 }
191 exit(status);
192 }
193
194 void
195 init(int np) /* start rtrace and set up buffers */
196 {
197 struct rtproc *rtp;
198 int i;
199 int maxbytes;
200 /* set up object functions */
201 ofun[OBJ_FACE].funp = o_face;
202 ofun[OBJ_SPHERE].funp = o_sphere;
203 ofun[OBJ_RING].funp = o_ring;
204 /* set up signal handling */
205 #ifdef SIGPIPE /* not present on Windows */
206 signal(SIGPIPE, quit);
207 #endif
208 rtp = &rt0; /* start rtrace process(es) */
209 for (i = 0; i++ < np; ) {
210 errno = 0;
211 maxbytes = open_process(&rtp->pd, rtargv);
212 if (maxbytes == 0) {
213 eputs(rtargv[0]);
214 eputs(": command not found\n");
215 exit(1);
216 }
217 if (maxbytes < 0)
218 error(SYSTEM, "cannot start rtrace process");
219 if (!i && np > 1)
220 sleep(2); /* wait for persist file */
221 rtp->bsiz = maxbytes/(6*sizeof(float));
222 rtp->buf = (float *)malloc(6*sizeof(float)*rtp->bsiz--);
223 rtp->dest = (float **)calloc(rtp->bsiz, sizeof(float *));
224 if (rtp->buf == NULL || rtp->dest == NULL)
225 error(SYSTEM, "out of memory in init");
226 rtp->nrays = 0;
227 if (i == np) /* last process? */
228 break;
229 rtp->next = (struct rtproc *)malloc(sizeof(struct rtproc));
230 if (rtp->next == NULL)
231 error(SYSTEM, "out of memory in init");
232 rtp = rtp->next;
233 }
234 rtp->next = NULL;
235 /* set up urand */
236 initurand(16384);
237 }
238
239
240 void
241 eputs( /* put string to stderr */
242 register char *s
243 )
244 {
245 static int midline = 0;
246
247 if (!*s) return;
248 if (!midline) {
249 fputs(progname, stderr);
250 fputs(": ", stderr);
251 }
252 fputs(s, stderr);
253 midline = s[strlen(s)-1] != '\n';
254 }
255
256
257 void
258 wputs(s) /* print warning if enabled */
259 char *s;
260 {
261 if (warnings)
262 eputs(s);
263 }
264
265
266 void
267 filter( /* process stream */
268 register FILE *infp,
269 char *name
270 )
271 {
272 char buf[512];
273 FILE *pfp;
274 register int c;
275
276 while ((c = getc(infp)) != EOF) {
277 if (isspace(c))
278 continue;
279 if (c == '#') { /* comment/options */
280 buf[0] = c;
281 fgets(buf+1, sizeof(buf)-1, infp);
282 xoptions(buf, name);
283 } else if (c == '!') { /* command */
284 buf[0] = c;
285 fgetline(buf+1, sizeof(buf)-1, infp);
286 if ((pfp = popen(buf+1, "r")) == NULL) {
287 sprintf(errmsg, "cannot execute \"%s\"", buf);
288 error(SYSTEM, errmsg);
289 }
290 filter(pfp, buf);
291 pclose(pfp);
292 } else { /* object */
293 ungetc(c, infp);
294 xobject(infp, name);
295 }
296 }
297 }
298
299
300 void
301 xoptions( /* process options in string s */
302 char *s,
303 char *nm
304 )
305 {
306 extern FILE *freopen();
307 char buf[64];
308 int nerrs = 0;
309 register char *cp;
310
311 if (strncmp(s, "#@mkillum", 9) || !isspace(s[9])) {
312 fputs(s, stdout); /* not for us */
313 return;
314 }
315 cp = s+10;
316 while (*cp) {
317 switch (*cp) {
318 case ' ':
319 case '\t':
320 case '\n':
321 case '\r':
322 case '\f':
323 cp++;
324 continue;
325 case 'm': /* material name */
326 if (*++cp != '=')
327 break;
328 if (!*++cp || isspace(*cp))
329 break;
330 atos(thisillum.matname, MAXSTR, cp);
331 cp = sskip(cp);
332 if (!(thisillum.flags & IL_DATCLB)) {
333 strcpy(thisillum.datafile, thisillum.matname);
334 thisillum.dfnum = 0;
335 }
336 continue;
337 case 'f': /* data file name */
338 if (*++cp != '=')
339 break;
340 if (!*++cp || isspace(*cp)) {
341 strcpy(thisillum.datafile,thisillum.matname);
342 thisillum.dfnum = 0;
343 thisillum.flags &= ~IL_DATCLB;
344 continue;
345 }
346 atos(thisillum.datafile, MAXSTR, cp);
347 cp = sskip(cp);
348 thisillum.dfnum = 0;
349 thisillum.flags |= IL_DATCLB;
350 continue;
351 case 'i': /* include material */
352 case 'e': /* exclude material */
353 if (cp[1] != '=')
354 break;
355 matselect = (*cp == 'i') ? S_ELEM : S_COMPL;
356 cp += 2;
357 atos(matcheck, MAXSTR, cp);
358 cp = sskip(cp);
359 continue;
360 case 'a': /* use everything */
361 cp = sskip(cp);
362 matselect = S_ALL;
363 continue;
364 case 'n': /* use nothing (passive) */
365 cp = sskip(cp);
366 matselect = S_NONE;
367 continue;
368 case 'c': /* color calculation */
369 if (*++cp != '=')
370 break;
371 switch (*++cp) {
372 case 'a': /* average */
373 thisillum.flags = (thisillum.flags|IL_COLAVG)
374 & ~IL_COLDST;
375 break;
376 case 'd': /* distribution */
377 thisillum.flags |= (IL_COLDST|IL_COLAVG);
378 break;
379 case 'n': /* none */
380 thisillum.flags &= ~(IL_COLAVG|IL_COLDST);
381 break;
382 default:
383 goto opterr;
384 }
385 cp = sskip(cp);
386 continue;
387 case 'd': /* point sample density */
388 if (*++cp != '=')
389 break;
390 if (!isintd(++cp, " \t\n\r"))
391 break;
392 thisillum.sampdens = atoi(cp);
393 cp = sskip(cp);
394 continue;
395 case 's': /* point super-samples */
396 if (*++cp != '=')
397 break;
398 if (!isintd(++cp, " \t\n\r"))
399 break;
400 thisillum.nsamps = atoi(cp);
401 cp = sskip(cp);
402 continue;
403 case 'l': /* light sources */
404 cp++;
405 if (*cp == '+')
406 thisillum.flags |= IL_LIGHT;
407 else if (*cp == '-')
408 thisillum.flags &= ~IL_LIGHT;
409 else
410 break;
411 cp++;
412 continue;
413 case 'b': /* brightness */
414 if (*++cp != '=')
415 break;
416 if (!isfltd(++cp, " \t\n\r"))
417 break;
418 thisillum.minbrt = atof(cp);
419 if (thisillum.minbrt < 0.)
420 thisillum.minbrt = 0.;
421 cp = sskip(cp);
422 continue;
423 case 'o': /* output file */
424 if (*++cp != '=')
425 break;
426 if (!*++cp || isspace(*cp))
427 break;
428 atos(buf, sizeof(buf), cp);
429 cp = sskip(cp);
430 if (freopen(buf, "w", stdout) == NULL) {
431 sprintf(errmsg,
432 "cannot open output file \"%s\"", buf);
433 error(SYSTEM, errmsg);
434 }
435 doneheader = 0;
436 continue;
437 case '!': /* processed file! */
438 sprintf(errmsg, "(%s): already processed!", nm);
439 error(WARNING, errmsg);
440 matselect = S_NONE;
441 return;
442 }
443 opterr: /* skip faulty option */
444 while (*cp && !isspace(*cp))
445 cp++;
446 nerrs++;
447 }
448 /* print header? */
449 checkhead();
450 /* issue warnings? */
451 if (nerrs) {
452 sprintf(errmsg, "(%s): %d error(s) in option line:",
453 nm, nerrs);
454 error(WARNING, errmsg);
455 wputs(s);
456 printf("# %s: the following option line has %d error(s):\n",
457 progname, nerrs);
458 }
459 /* print pure comment */
460 printf("# %s", s+2);
461 }
462
463 void
464 printopts(void) /* print out option default values */
465 {
466 printf("m=%-15s\t\t# material name\n", thisillum.matname);
467 printf("f=%-15s\t\t# data file name\n", thisillum.datafile);
468 if (thisillum.flags & IL_COLAVG)
469 if (thisillum.flags & IL_COLDST)
470 printf("c=d\t\t\t\t# color distribution\n");
471 else
472 printf("c=a\t\t\t\t# color average\n");
473 else
474 printf("c=n\t\t\t\t# color none\n");
475 if (thisillum.flags & IL_LIGHT)
476 printf("l+\t\t\t\t# light type on\n");
477 else
478 printf("l-\t\t\t\t# light type off\n");
479 printf("d=%d\t\t\t\t# density of points\n", thisillum.sampdens);
480 printf("s=%d\t\t\t\t# samples per point\n", thisillum.nsamps);
481 printf("b=%f\t\t\t# minimum average brightness\n", thisillum.minbrt);
482 }
483
484
485 void
486 printhead( /* print out header */
487 register int ac,
488 register char **av
489 )
490 {
491 putchar('#');
492 while (ac-- > 0) {
493 putchar(' ');
494 fputs(*av++, stdout);
495 }
496 fputs("\n#@mkillum !\n", stdout);
497 }
498
499
500 void
501 xobject( /* translate an object from fp */
502 FILE *fp,
503 char *nm
504 )
505 {
506 OBJREC thisobj;
507 char str[MAXSTR];
508 int doit;
509 /* read the object */
510 if (fgetword(thisillum.altmat, MAXSTR, fp) == NULL)
511 goto readerr;
512 if (fgetword(str, MAXSTR, fp) == NULL)
513 goto readerr;
514 /* is it an alias? */
515 if (!strcmp(str, ALIASKEY)) {
516 if (fgetword(str, MAXSTR, fp) == NULL)
517 goto readerr;
518 printf("\n%s %s %s", thisillum.altmat, ALIASKEY, str);
519 if (fgetword(str, MAXSTR, fp) == NULL)
520 goto readerr;
521 printf("\t%s\n", str);
522 return;
523 }
524 thisobj.omod = OVOID; /* unused field */
525 if ((thisobj.otype = otype(str)) < 0) {
526 sprintf(errmsg, "(%s): unknown type \"%s\"", nm, str);
527 error(USER, errmsg);
528 }
529 if (fgetword(str, MAXSTR, fp) == NULL)
530 goto readerr;
531 thisobj.oname = str;
532 if (readfargs(&thisobj.oargs, fp) != 1)
533 goto readerr;
534 thisobj.os = NULL;
535 /* check for translation */
536 switch (matselect) {
537 case S_NONE:
538 doit = 0;
539 break;
540 case S_ALL:
541 doit = 1;
542 break;
543 case S_ELEM:
544 doit = !strcmp(thisillum.altmat, matcheck);
545 break;
546 case S_COMPL:
547 doit = strcmp(thisillum.altmat, matcheck);
548 break;
549 }
550 doit = doit && issurface(thisobj.otype);
551 /* print header? */
552 checkhead();
553 /* process object */
554 if (doit)
555 (*ofun[thisobj.otype].funp)(&thisobj, &thisillum, &rt0, nm);
556 else
557 printobj(thisillum.altmat, &thisobj);
558 /* free arguments */
559 freefargs(&thisobj.oargs);
560 return;
561 readerr:
562 sprintf(errmsg, "(%s): error reading scene", nm);
563 error(USER, errmsg);
564 }