| 7 |  |  | 
| 8 |  | #include  <signal.h> | 
| 9 |  | #include  <ctype.h> | 
| 10 | – | #include  <stdio.h> | 
| 10 |  |  | 
| 11 | < | #include  "platform.h" | 
| 11 | > | #include  "paths.h"             /* win_popen() */ | 
| 12 |  | #include  "mkillum.h" | 
| 13 |  |  | 
| 14 |  | /* default parameters */ | 
| 22 |  | #define  S_COMPL        2               /* select all but element */ | 
| 23 |  | #define  S_ALL          3               /* select all */ | 
| 24 |  |  | 
| 26 | – | /* rtrace command and defaults */ | 
| 27 | – | char  *rtargv[64] = { "rtrace", "-dj", ".25", "-dr", "3", "-dv-", | 
| 28 | – | "-ab", "2", "-ad", "256", "-as", "128", "-aa", ".15", }; | 
| 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   rt;             /* our rtrace process */ | 
| 35 | – |  | 
| 25 |  | struct illum_args  thisillum = {        /* our illum and default values */ | 
| 26 |  | 0, | 
| 27 |  | DFLMAT, | 
| 36 |  | char    matcheck[MAXSTR];       /* current material to include or exclude */ | 
| 37 |  | int     matselect = S_ALL;      /* selection criterion */ | 
| 38 |  |  | 
| 50 | – | FUN     ofun[NUMOTYPE] = INIT_OTYPE;    /* object types */ | 
| 51 | – |  | 
| 39 |  | int     gargc;                  /* global argc */ | 
| 40 |  | char    **gargv;                /* global argv */ | 
| 54 | – | #define  progname       gargv[0] | 
| 41 |  |  | 
| 42 |  | int     doneheader = 0;         /* printed header yet? */ | 
| 43 |  | #define  checkhead()    if (!doneheader++) printhead(gargc,gargv) | 
| 44 |  |  | 
| 45 |  | int     warnings = 1;           /* print warnings? */ | 
| 46 |  |  | 
| 47 | + | void init(char *octnm, int np); | 
| 48 | + | void filter(FILE        *infp, char     *name); | 
| 49 | + | void xoptions(char      *s, char        *nm); | 
| 50 | + | void printopts(void); | 
| 51 | + | void printhead(int  ac, char  **av); | 
| 52 | + | void xobject(FILE  *fp, char  *nm); | 
| 53 |  |  | 
| 54 | < | main(argc, argv)                /* compute illum distributions using rtrace */ | 
| 55 | < | int     argc; | 
| 56 | < | char    *argv[]; | 
| 54 | > |  | 
| 55 | > | int | 
| 56 | > | main(           /* compute illum distributions using rtrace */ | 
| 57 | > | int     argc, | 
| 58 | > | char    *argv[] | 
| 59 | > | ) | 
| 60 |  | { | 
| 61 | < | char    *rtpath; | 
| 61 | > | int     nprocs = 1; | 
| 62 |  | FILE    *fp; | 
| 63 | < | register int    i; | 
| 63 | > | int     rval; | 
| 64 | > | int     i; | 
| 65 |  | /* set global arguments */ | 
| 66 |  | gargv = argv; | 
| 67 | < | /* set up rtrace command */ | 
| 67 | > | progname = gargv[0]; | 
| 68 | > | /* set up rendering defaults */ | 
| 69 | > | dstrsrc = 0.5; | 
| 70 | > | directrelay = 3; | 
| 71 | > | ambounce = 2; | 
| 72 | > | /* get options from command line */ | 
| 73 |  | for (i = 1; i < argc; i++) { | 
| 74 | < | if (argv[i][0] == '<' && argv[i][1] == '\0') | 
| 74 | > | while ((rval = expandarg(&argc, &argv, i)) > 0) | 
| 75 | > | ; | 
| 76 | > | if (rval < 0) { | 
| 77 | > | sprintf(errmsg, "cannot expand '%s'", argv[i]); | 
| 78 | > | error(SYSTEM, errmsg); | 
| 79 | > | } | 
| 80 | > | if (argv[i][0] != '-') | 
| 81 |  | break; | 
| 82 | < | rtargv[rtargc++] = argv[i]; | 
| 83 | < | if (argv[i][0] == '-' && argv[i][1] == 'w') | 
| 84 | < | switch (argv[i][2]) { | 
| 78 | < | case '\0': | 
| 79 | < | warnings = !warnings; | 
| 80 | < | break; | 
| 81 | < | case '+': | 
| 82 | < | case 'T': case 't': | 
| 83 | < | case 'Y': case 'y': | 
| 84 | < | case '1': | 
| 85 | < | warnings = 1; | 
| 86 | < | break; | 
| 87 | < | case '-': | 
| 88 | < | case 'F': case 'f': | 
| 89 | < | case 'N': case 'n': | 
| 90 | < | case '0': | 
| 91 | < | warnings = 0; | 
| 92 | < | break; | 
| 93 | < | } | 
| 94 | < | } | 
| 95 | < | gargc = i; | 
| 96 | < | rtargc--; | 
| 97 | < | for (i = 0; myrtopts[i] != NULL; i++) | 
| 98 | < | rtargv[rtargc++] = myrtopts[i]; | 
| 99 | < | rtargv[rtargc++] = argv[gargc-1]; | 
| 100 | < | rtargv[rtargc] = NULL; | 
| 101 | < | /* just asking for defaults? */ | 
| 102 | < | if (!strcmp(argv[gargc-1], "-defaults")) { | 
| 103 | < | printopts(); fflush(stdout); | 
| 104 | < | rtpath = getpath(rtargv[0], getenv("PATH"), X_OK); | 
| 105 | < | if (rtpath == NULL) { | 
| 106 | < | eputs(rtargv[0]); | 
| 107 | < | eputs(": command not found\n"); | 
| 108 | < | exit(1); | 
| 82 | > | if (!strcmp(argv[i], "-w")) { | 
| 83 | > | warnings = 0; | 
| 84 | > | continue; | 
| 85 |  | } | 
| 86 | < | execv(rtpath, rtargv); | 
| 87 | < | perror(rtpath); | 
| 88 | < | exit(1); | 
| 86 | > | if (!strcmp(argv[i], "-n")) { | 
| 87 | > | nprocs = atoi(argv[++i]); | 
| 88 | > | if (nprocs <= 0) | 
| 89 | > | error(USER, "illegal number of processes"); | 
| 90 | > | continue; | 
| 91 | > | } | 
| 92 | > | if (!strcmp(argv[i], "-defaults")) { | 
| 93 | > | printopts(); | 
| 94 | > | print_rdefaults(); | 
| 95 | > | quit(0); | 
| 96 | > | } | 
| 97 | > | rval = getrenderopt(argc-i, argv+i); | 
| 98 | > | if (rval < 0) { | 
| 99 | > | sprintf(errmsg, "bad render option at '%s'", argv[i]); | 
| 100 | > | error(USER, errmsg); | 
| 101 | > | } | 
| 102 | > | i += rval; | 
| 103 |  | } | 
| 104 | < | if (gargc < 2 || argv[gargc-1][0] == '-') | 
| 104 | > | gargc = ++i; | 
| 105 | > | /* add "mandatory" render options */ | 
| 106 | > | do_irrad = 0; | 
| 107 | > | if (gargc > argc || argv[gargc-1][0] == '-') | 
| 108 |  | error(USER, "missing octree argument"); | 
| 109 |  | /* else initialize and run our calculation */ | 
| 110 | < | init(); | 
| 111 | < | if (gargc+1 < argc) | 
| 110 | > | init(argv[gargc-1], nprocs); | 
| 111 | > | if (gargc < argc) { | 
| 112 | > | if (gargc == argc-1 || argv[gargc][0] != '<' || argv[gargc][1]) | 
| 113 | > | error(USER, "use '< file1 file2 ..' for multiple inputs"); | 
| 114 |  | for (i = gargc+1; i < argc; i++) { | 
| 115 |  | if ((fp = fopen(argv[i], "r")) == NULL) { | 
| 116 |  | sprintf(errmsg, | 
| 120 |  | filter(fp, argv[i]); | 
| 121 |  | fclose(fp); | 
| 122 |  | } | 
| 123 | < | else | 
| 123 | > | } else | 
| 124 |  | filter(stdin, "standard input"); | 
| 125 |  | quit(0); | 
| 126 | + | return 0; /* pro forma return */ | 
| 127 |  | } | 
| 128 |  |  | 
| 129 |  |  | 
| 130 |  | void | 
| 131 | < | quit(status)                    /* exit with status */ | 
| 136 | < | int  status; | 
| 131 | > | init(char *octnm, int np)               /* start rendering process(es) */ | 
| 132 |  | { | 
| 138 | – | int     rtstat; | 
| 139 | – |  | 
| 140 | – | rtstat = close_process(rt.pd); | 
| 141 | – | if (status == 0) | 
| 142 | – | if (rtstat < 0) | 
| 143 | – | error(WARNING, | 
| 144 | – | "unknown return status from rtrace process"); | 
| 145 | – | else | 
| 146 | – | status = rtstat; | 
| 147 | – | exit(status); | 
| 148 | – | } | 
| 149 | – |  | 
| 150 | – |  | 
| 151 | – | init()                          /* start rtrace and set up buffers */ | 
| 152 | – | { | 
| 153 | – | extern int  o_face(), o_sphere(), o_ring(); | 
| 154 | – | int     maxbytes; | 
| 155 | – | /* set up object functions */ | 
| 156 | – | ofun[OBJ_FACE].funp = o_face; | 
| 157 | – | ofun[OBJ_SPHERE].funp = o_sphere; | 
| 158 | – | ofun[OBJ_RING].funp = o_ring; | 
| 133 |  | /* set up signal handling */ | 
| 134 | < | #ifndef _WIN32 /* XXX what do we use instead? */ | 
| 134 | > | signal(SIGINT, quit); | 
| 135 | > | #ifdef SIGHUP | 
| 136 | > | signal(SIGHUP, quit); | 
| 137 | > | #endif | 
| 138 | > | #ifdef SIGTERM | 
| 139 | > | signal(SIGTERM, quit); | 
| 140 | > | #endif | 
| 141 | > | #ifdef SIGPIPE | 
| 142 |  | signal(SIGPIPE, quit); | 
| 143 |  | #endif | 
| 144 | < | /* start rtrace process */ | 
| 145 | < | errno = 0; | 
| 165 | < | maxbytes = open_process(rt.pd, rtargv); | 
| 166 | < | if (maxbytes == 0) { | 
| 167 | < | eputs(rtargv[0]); | 
| 168 | < | eputs(": command not found\n"); | 
| 169 | < | exit(1); | 
| 170 | < | } | 
| 171 | < | if (maxbytes < 0) | 
| 172 | < | error(SYSTEM, "cannot start rtrace process"); | 
| 173 | < | rt.bsiz = maxbytes/(6*sizeof(float)); | 
| 174 | < | rt.buf = (float *)malloc(6*sizeof(float)*rt.bsiz--); | 
| 175 | < | rt.dest = (float **)malloc(sizeof(float *)*rt.bsiz); | 
| 176 | < | if (rt.buf == NULL || rt.dest == NULL) | 
| 177 | < | error(SYSTEM, "out of memory in init"); | 
| 178 | < | rt.nrays = 0; | 
| 179 | < | /* set up urand */ | 
| 180 | < | initurand(16384); | 
| 144 | > | /* start rendering process(es) */ | 
| 145 | > | ray_pinit(octnm, np); | 
| 146 |  | } | 
| 147 |  |  | 
| 148 |  |  | 
| 149 |  | void | 
| 150 | < | eputs(s)                                /* put string to stderr */ | 
| 151 | < | register char  *s; | 
| 150 | > | eputs(                          /* put string to stderr */ | 
| 151 | > | const char  *s | 
| 152 | > | ) | 
| 153 |  | { | 
| 154 |  | static int  midline = 0; | 
| 155 |  |  | 
| 164 |  |  | 
| 165 |  |  | 
| 166 |  | void | 
| 167 | < | wputs(s)                        /* print warning if enabled */ | 
| 202 | < | char  *s; | 
| 167 | > | wputs(const char *s)                    /* print warning if enabled */ | 
| 168 |  | { | 
| 169 |  | if (warnings) | 
| 170 |  | eputs(s); | 
| 171 |  | } | 
| 172 |  |  | 
| 173 |  |  | 
| 174 | < | filter(infp, name)              /* process stream */ | 
| 175 | < | register FILE   *infp; | 
| 211 | < | char    *name; | 
| 174 | > | void | 
| 175 | > | quit(int ec)                    /* make sure exit is called */ | 
| 176 |  | { | 
| 177 | + | if (ray_pnprocs > 0)    /* close children if any */ | 
| 178 | + | ray_pclose(0); | 
| 179 | + | else if (ray_pnprocs < 0) | 
| 180 | + | _exit(ec);      /* avoid flush() in child */ | 
| 181 | + | exit(ec); | 
| 182 | + | } | 
| 183 | + |  | 
| 184 | + |  | 
| 185 | + | void | 
| 186 | + | filter(         /* process stream */ | 
| 187 | + | FILE    *infp, | 
| 188 | + | char    *name | 
| 189 | + | ) | 
| 190 | + | { | 
| 191 |  | char    buf[512]; | 
| 192 |  | FILE    *pfp; | 
| 193 | < | register int    c; | 
| 193 | > | int     c; | 
| 194 |  |  | 
| 195 |  | while ((c = getc(infp)) != EOF) { | 
| 196 |  | if (isspace(c)) | 
| 207 |  | error(SYSTEM, errmsg); | 
| 208 |  | } | 
| 209 |  | filter(pfp, buf); | 
| 210 | < | pclose(pfp); | 
| 210 | > | if (pclose(pfp) != 0) { | 
| 211 | > | sprintf(errmsg, "bad status from \"%s\"", buf); | 
| 212 | > | error(USER, errmsg); | 
| 213 | > | } | 
| 214 |  | } else {                                /* object */ | 
| 215 |  | ungetc(c, infp); | 
| 216 |  | xobject(infp, name); | 
| 219 |  | } | 
| 220 |  |  | 
| 221 |  |  | 
| 222 | < | xoptions(s, nm)                 /* process options in string s */ | 
| 223 | < | char    *s; | 
| 224 | < | char    *nm; | 
| 222 | > | void | 
| 223 | > | xoptions(                       /* process options in string s */ | 
| 224 | > | char    *s, | 
| 225 | > | char    *nm | 
| 226 | > | ) | 
| 227 |  | { | 
| 245 | – | extern FILE     *freopen(); | 
| 228 |  | char    buf[64]; | 
| 229 | + | int     negax; | 
| 230 |  | int     nerrs = 0; | 
| 231 | < | register char   *cp; | 
| 231 | > | char    *cp; | 
| 232 |  |  | 
| 233 |  | if (strncmp(s, "#@mkillum", 9) || !isspace(s[9])) { | 
| 234 |  | fputs(s, stdout);               /* not for us */ | 
| 306 |  | } | 
| 307 |  | cp = sskip(cp); | 
| 308 |  | continue; | 
| 309 | < | case 'd':                       /* point sample density */ | 
| 309 | > | case 'd':                       /* sample density */ | 
| 310 |  | if (*++cp != '=') | 
| 311 |  | break; | 
| 312 | < | if (!isintd(++cp, " \t\n\r")) | 
| 313 | < | break; | 
| 314 | < | thisillum.sampdens = atoi(cp); | 
| 312 | > | if (!*++cp || isspace(*cp)) | 
| 313 | > | continue; | 
| 314 | > | if (isintd(cp, " \t\n\r")) { | 
| 315 | > | thisillum.sampdens = atoi(cp); | 
| 316 | > | } else { | 
| 317 | > | error(WARNING, "direct BSDF input unsupported"); | 
| 318 | > | goto opterr; | 
| 319 | > | } | 
| 320 |  | cp = sskip(cp); | 
| 321 |  | continue; | 
| 322 | < | case 's':                       /* point super-samples */ | 
| 322 | > | case 's':                       /* surface super-samples */ | 
| 323 |  | if (*++cp != '=') | 
| 324 |  | break; | 
| 325 |  | if (!isintd(++cp, " \t\n\r")) | 
| 387 |  | printf("# %s", s+2); | 
| 388 |  | } | 
| 389 |  |  | 
| 390 | < |  | 
| 391 | < | printopts()                     /* print out option default values */ | 
| 390 | > | void | 
| 391 | > | printopts(void)                 /* print out option default values */ | 
| 392 |  | { | 
| 393 |  | printf("m=%-15s\t\t# material name\n", thisillum.matname); | 
| 394 |  | printf("f=%-15s\t\t# data file name\n", thisillum.datafile); | 
| 403 |  | printf("l+\t\t\t\t# light type on\n"); | 
| 404 |  | else | 
| 405 |  | printf("l-\t\t\t\t# light type off\n"); | 
| 406 | < | printf("d=%d\t\t\t\t# density of points\n", thisillum.sampdens); | 
| 407 | < | printf("s=%d\t\t\t\t# samples per point\n", thisillum.nsamps); | 
| 406 | > | printf("d=%d\t\t\t\t# density of directions\n", thisillum.sampdens); | 
| 407 | > | printf("s=%d\t\t\t\t# samples per direction\n", thisillum.nsamps); | 
| 408 |  | printf("b=%f\t\t\t# minimum average brightness\n", thisillum.minbrt); | 
| 409 |  | } | 
| 410 |  |  | 
| 411 |  |  | 
| 412 | < | printhead(ac, av)                       /* print out header */ | 
| 413 | < | register int  ac; | 
| 414 | < | register char  **av; | 
| 412 | > | void | 
| 413 | > | printhead(                      /* print out header */ | 
| 414 | > | int  ac, | 
| 415 | > | char  **av | 
| 416 | > | ) | 
| 417 |  | { | 
| 418 |  | putchar('#'); | 
| 419 |  | while (ac-- > 0) { | 
| 424 |  | } | 
| 425 |  |  | 
| 426 |  |  | 
| 427 | < | xobject(fp, nm)                         /* translate an object from fp */ | 
| 428 | < | FILE  *fp; | 
| 429 | < | char  *nm; | 
| 427 | > | void | 
| 428 | > | xobject(                                /* translate an object from fp */ | 
| 429 | > | FILE  *fp, | 
| 430 | > | char  *nm | 
| 431 | > | ) | 
| 432 |  | { | 
| 433 |  | OBJREC  thisobj; | 
| 434 |  | char  str[MAXSTR]; | 
| 479 |  | checkhead(); | 
| 480 |  | /* process object */ | 
| 481 |  | if (doit) | 
| 482 | < | (*ofun[thisobj.otype].funp)(&thisobj, &thisillum, &rt, nm); | 
| 482 | > | switch (thisobj.otype) { | 
| 483 | > | case OBJ_FACE: | 
| 484 | > | my_face(&thisobj, &thisillum, nm); | 
| 485 | > | break; | 
| 486 | > | case OBJ_SPHERE: | 
| 487 | > | my_sphere(&thisobj, &thisillum, nm); | 
| 488 | > | break; | 
| 489 | > | case OBJ_RING: | 
| 490 | > | my_ring(&thisobj, &thisillum, nm); | 
| 491 | > | break; | 
| 492 | > | default: | 
| 493 | > | my_default(&thisobj, &thisillum, nm); | 
| 494 | > | break; | 
| 495 | > | } | 
| 496 |  | else | 
| 497 |  | printobj(thisillum.altmat, &thisobj); | 
| 498 |  | /* free arguments */ | 
| 499 |  | freefargs(&thisobj.oargs); | 
| 500 |  | return; | 
| 501 |  | readerr: | 
| 502 | < | sprintf(errmsg, "(%s): error reading scene", nm); | 
| 502 | > | sprintf(errmsg, "(%s): error reading input", nm); | 
| 503 |  | error(USER, errmsg); | 
| 504 |  | } |