| 8 |  | #include  <signal.h> | 
| 9 |  | #include  <ctype.h> | 
| 10 |  |  | 
| 11 | + | #include  "rtprocess.h" /* win_popen() */ | 
| 12 |  | #include  "mkillum.h" | 
| 12 | – | #include  "platform.h" | 
| 13 |  |  | 
| 14 |  | /* default parameters */ | 
| 15 |  | #define  SAMPDENS       48              /* points per projected steradian */ | 
| 22 |  | #define  S_COMPL        2               /* select all but element */ | 
| 23 |  | #define  S_ALL          3               /* select all */ | 
| 24 |  |  | 
| 25 | – | /* rtrace command and defaults */ | 
| 26 | – | char  *rtargv[64] = { "rtrace", "-dj", ".25", "-dr", "3", "-dv-", | 
| 27 | – | "-ab", "2", "-ad", "256", "-as", "128", "-aa", ".15", }; | 
| 28 | – | int  rtargc = 14; | 
| 29 | – | /* overriding rtrace options */ | 
| 30 | – | char  *myrtopts[] = { "-I-", "-i-", "-ld-", "-ov", "-h-", | 
| 31 | – | "-fff", "-y", "0", NULL }; | 
| 32 | – |  | 
| 33 | – | struct rtproc   rt;             /* our rtrace process */ | 
| 34 | – |  | 
| 25 |  | struct illum_args  thisillum = {        /* our illum and default values */ | 
| 26 |  | 0, | 
| 27 | + | UDzpos, | 
| 28 | + | 0., | 
| 29 |  | DFLMAT, | 
| 30 |  | DFLDAT, | 
| 31 |  | 0, | 
| 32 |  | VOIDID, | 
| 33 |  | SAMPDENS, | 
| 34 |  | NSAMPS, | 
| 35 | + | NULL, | 
| 36 |  | 0., | 
| 37 |  | }; | 
| 38 |  |  | 
| 39 |  | char    matcheck[MAXSTR];       /* current material to include or exclude */ | 
| 40 |  | int     matselect = S_ALL;      /* selection criterion */ | 
| 41 |  |  | 
| 49 | – | FUN     ofun[NUMOTYPE] = INIT_OTYPE;    /* object types */ | 
| 50 | – |  | 
| 42 |  | int     gargc;                  /* global argc */ | 
| 43 |  | char    **gargv;                /* global argv */ | 
| 53 | – | #define  progname       gargv[0] | 
| 44 |  |  | 
| 45 |  | int     doneheader = 0;         /* printed header yet? */ | 
| 46 |  | #define  checkhead()    if (!doneheader++) printhead(gargc,gargv) | 
| 47 |  |  | 
| 48 |  | int     warnings = 1;           /* print warnings? */ | 
| 49 |  |  | 
| 50 | + | void init(char *octnm, int np); | 
| 51 | + | void filter(register FILE       *infp, char     *name); | 
| 52 | + | void xoptions(char      *s, char        *nm); | 
| 53 | + | void printopts(void); | 
| 54 | + | void printhead(register int  ac, register char  **av); | 
| 55 | + | void xobject(FILE  *fp, char  *nm); | 
| 56 |  |  | 
| 57 | < | main(argc, argv)                /* compute illum distributions using rtrace */ | 
| 58 | < | int     argc; | 
| 59 | < | char    *argv[]; | 
| 57 | > |  | 
| 58 | > | int | 
| 59 | > | main(           /* compute illum distributions using rtrace */ | 
| 60 | > | int     argc, | 
| 61 | > | char    *argv[] | 
| 62 | > | ) | 
| 63 |  | { | 
| 64 | < | char    *rtpath; | 
| 64 | > | int     nprocs = 1; | 
| 65 |  | FILE    *fp; | 
| 66 | + | int     rval; | 
| 67 |  | register int    i; | 
| 68 |  | /* set global arguments */ | 
| 69 |  | gargv = argv; | 
| 70 | < | /* set up rtrace command */ | 
| 70 | > | progname = gargv[0]; | 
| 71 | > | /* set up rendering defaults */ | 
| 72 | > | dstrsrc = 0.5; | 
| 73 | > | directrelay = 3; | 
| 74 | > | ambounce = 2; | 
| 75 | > | /* get options from command line */ | 
| 76 |  | for (i = 1; i < argc; i++) { | 
| 77 | < | if (argv[i][0] == '<' && argv[i][1] == '\0') | 
| 77 | > | while ((rval = expandarg(&argc, &argv, i)) > 0) | 
| 78 | > | ; | 
| 79 | > | if (rval < 0) { | 
| 80 | > | sprintf(errmsg, "cannot expand '%s'", argv[i]); | 
| 81 | > | error(SYSTEM, errmsg); | 
| 82 | > | } | 
| 83 | > | if (argv[i][0] != '-') | 
| 84 |  | break; | 
| 85 | < | rtargv[rtargc++] = argv[i]; | 
| 86 | < | if (argv[i][0] == '-' && argv[i][1] == 'w') | 
| 87 | < | switch (argv[i][2]) { | 
| 77 | < | case '\0': | 
| 78 | < | warnings = !warnings; | 
| 79 | < | break; | 
| 80 | < | case '+': | 
| 81 | < | case 'T': case 't': | 
| 82 | < | case 'Y': case 'y': | 
| 83 | < | case '1': | 
| 84 | < | warnings = 1; | 
| 85 | < | break; | 
| 86 | < | case '-': | 
| 87 | < | case 'F': case 'f': | 
| 88 | < | case 'N': case 'n': | 
| 89 | < | case '0': | 
| 90 | < | warnings = 0; | 
| 91 | < | break; | 
| 92 | < | } | 
| 93 | < | } | 
| 94 | < | gargc = i; | 
| 95 | < | rtargc--; | 
| 96 | < | for (i = 0; myrtopts[i] != NULL; i++) | 
| 97 | < | rtargv[rtargc++] = myrtopts[i]; | 
| 98 | < | rtargv[rtargc++] = argv[gargc-1]; | 
| 99 | < | rtargv[rtargc] = NULL; | 
| 100 | < | /* just asking for defaults? */ | 
| 101 | < | if (!strcmp(argv[gargc-1], "-defaults")) { | 
| 102 | < | printopts(); fflush(stdout); | 
| 103 | < | rtpath = getpath(rtargv[0], getenv("PATH"), X_OK); | 
| 104 | < | if (rtpath == NULL) { | 
| 105 | < | eputs(rtargv[0]); | 
| 106 | < | eputs(": command not found\n"); | 
| 107 | < | exit(1); | 
| 85 | > | if (!strcmp(argv[i], "-w")) { | 
| 86 | > | warnings = 0; | 
| 87 | > | continue; | 
| 88 |  | } | 
| 89 | < | execv(rtpath, rtargv); | 
| 90 | < | perror(rtpath); | 
| 91 | < | exit(1); | 
| 89 | > | if (!strcmp(argv[i], "-n")) { | 
| 90 | > | nprocs = atoi(argv[++i]); | 
| 91 | > | if (nprocs <= 0) | 
| 92 | > | error(USER, "illegal number of processes"); | 
| 93 | > | continue; | 
| 94 | > | } | 
| 95 | > | if (!strcmp(argv[i], "-defaults")) { | 
| 96 | > | printopts(); | 
| 97 | > | print_rdefaults(); | 
| 98 | > | quit(0); | 
| 99 | > | } | 
| 100 | > | rval = getrenderopt(argc-i, argv+i); | 
| 101 | > | if (rval < 0) { | 
| 102 | > | sprintf(errmsg, "bad render option at '%s'", argv[i]); | 
| 103 | > | error(USER, errmsg); | 
| 104 | > | } | 
| 105 | > | i += rval; | 
| 106 |  | } | 
| 107 | < | if (gargc < 2 || argv[gargc-1][0] == '-') | 
| 107 | > | gargc = ++i; | 
| 108 | > | /* add "mandatory" render options */ | 
| 109 | > | do_irrad = 0; | 
| 110 | > | if (gargc > argc || argv[gargc-1][0] == '-') | 
| 111 |  | error(USER, "missing octree argument"); | 
| 112 |  | /* else initialize and run our calculation */ | 
| 113 | < | init(); | 
| 114 | < | if (gargc+1 < argc) | 
| 113 | > | init(argv[gargc-1], nprocs); | 
| 114 | > | if (gargc < argc) { | 
| 115 | > | if (gargc == argc-1 || argv[gargc][0] != '<' || argv[gargc][1]) | 
| 116 | > | error(USER, "use '< file1 file2 ..' for multiple inputs"); | 
| 117 |  | for (i = gargc+1; i < argc; i++) { | 
| 118 |  | if ((fp = fopen(argv[i], "r")) == NULL) { | 
| 119 |  | sprintf(errmsg, | 
| 123 |  | filter(fp, argv[i]); | 
| 124 |  | fclose(fp); | 
| 125 |  | } | 
| 126 | < | else | 
| 126 | > | } else | 
| 127 |  | filter(stdin, "standard input"); | 
| 128 |  | quit(0); | 
| 129 | + | return 0; /* pro forma return */ | 
| 130 |  | } | 
| 131 |  |  | 
| 132 |  |  | 
| 133 |  | void | 
| 134 | < | quit(status)                    /* exit with status */ | 
| 135 | < | int  status; | 
| 134 | > | init(char *octnm, int np)               /* start rendering process(es) */ | 
| 135 |  | { | 
| 137 | – | int     rtstat; | 
| 138 | – |  | 
| 139 | – | rtstat = close_process(&(rt.pd)); | 
| 140 | – | if (status == 0) { | 
| 141 | – | if (rtstat < 0) | 
| 142 | – | error(WARNING, | 
| 143 | – | "unknown return status from rtrace process"); | 
| 144 | – | else | 
| 145 | – | status = rtstat; | 
| 146 | – | } | 
| 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; | 
| 136 |  | /* set up signal handling */ | 
| 137 | < | #ifdef SIGPIPE /* not present on Windows */ | 
| 137 | > | signal(SIGINT, quit); | 
| 138 | > | #ifdef SIGHUP | 
| 139 | > | signal(SIGHUP, quit); | 
| 140 | > | #endif | 
| 141 | > | #ifdef SIGTERM | 
| 142 | > | signal(SIGTERM, quit); | 
| 143 | > | #endif | 
| 144 | > | #ifdef SIGPIPE | 
| 145 |  | signal(SIGPIPE, quit); | 
| 146 |  | #endif | 
| 147 | < | /* start rtrace process */ | 
| 148 | < | 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); | 
| 147 | > | /* start rendering process(es) */ | 
| 148 | > | ray_pinit(octnm, np); | 
| 149 |  | } | 
| 150 |  |  | 
| 151 |  |  | 
| 152 |  | void | 
| 153 | < | eputs(s)                                /* put string to stderr */ | 
| 154 | < | register char  *s; | 
| 153 | > | eputs(                          /* put string to stderr */ | 
| 154 | > | register char  *s | 
| 155 | > | ) | 
| 156 |  | { | 
| 157 |  | static int  midline = 0; | 
| 158 |  |  | 
| 175 |  | } | 
| 176 |  |  | 
| 177 |  |  | 
| 178 | < | filter(infp, name)              /* process stream */ | 
| 179 | < | register FILE   *infp; | 
| 180 | < | char    *name; | 
| 178 | > | void | 
| 179 | > | quit(ec)                        /* make sure exit is called */ | 
| 180 | > | int     ec; | 
| 181 |  | { | 
| 182 | + | if (ray_pnprocs > 0)    /* close children if any */ | 
| 183 | + | ray_pclose(0); | 
| 184 | + | exit(ec); | 
| 185 | + | } | 
| 186 | + |  | 
| 187 | + |  | 
| 188 | + | void | 
| 189 | + | filter(         /* process stream */ | 
| 190 | + | register FILE   *infp, | 
| 191 | + | char    *name | 
| 192 | + | ) | 
| 193 | + | { | 
| 194 |  | char    buf[512]; | 
| 195 |  | FILE    *pfp; | 
| 196 |  | register int    c; | 
| 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 |  | { | 
| 228 |  | extern FILE     *freopen(); | 
| 229 |  | char    buf[64]; | 
| 230 | + | int     negax; | 
| 231 |  | int     nerrs = 0; | 
| 232 |  | register char   *cp; | 
| 233 |  |  | 
| 307 |  | } | 
| 308 |  | cp = sskip(cp); | 
| 309 |  | continue; | 
| 310 | < | case 'd':                       /* point sample density */ | 
| 310 | > | case 'd':                       /* sample density / BSDF data */ | 
| 311 |  | if (*++cp != '=') | 
| 312 |  | break; | 
| 313 | < | if (!isintd(++cp, " \t\n\r")) | 
| 314 | < | break; | 
| 315 | < | thisillum.sampdens = atoi(cp); | 
| 313 | > | if (thisillum.sd != NULL) { | 
| 314 | > | free_BSDF(thisillum.sd); | 
| 315 | > | thisillum.sd = NULL; | 
| 316 | > | } | 
| 317 | > | if (!*++cp || isspace(*cp)) | 
| 318 | > | continue; | 
| 319 | > | if (isintd(cp, " \t\n\r")) { | 
| 320 | > | thisillum.sampdens = atoi(cp); | 
| 321 | > | } else { | 
| 322 | > | atos(buf, sizeof(buf), cp); | 
| 323 | > | thisillum.sd = load_BSDF(buf); | 
| 324 | > | if (thisillum.sd == NULL) | 
| 325 | > | break; | 
| 326 | > | } | 
| 327 |  | cp = sskip(cp); | 
| 328 |  | continue; | 
| 329 | < | case 's':                       /* point super-samples */ | 
| 329 | > | case 's':                       /* surface super-samples */ | 
| 330 |  | if (*++cp != '=') | 
| 331 |  | break; | 
| 332 |  | if (!isintd(++cp, " \t\n\r")) | 
| 368 |  | } | 
| 369 |  | doneheader = 0; | 
| 370 |  | continue; | 
| 371 | + | case 'u':                       /* up direction */ | 
| 372 | + | if (*++cp != '=') | 
| 373 | + | break; | 
| 374 | + | if (!*++cp || isspace(*cp)) { | 
| 375 | + | thisillum.udir = UDunknown; | 
| 376 | + | continue; | 
| 377 | + | } | 
| 378 | + | negax = 0; | 
| 379 | + | if (*cp == '+') | 
| 380 | + | cp++; | 
| 381 | + | else if (*cp == '-') { | 
| 382 | + | negax++; | 
| 383 | + | cp++; | 
| 384 | + | } | 
| 385 | + | switch (*cp++) { | 
| 386 | + | case 'x': | 
| 387 | + | case 'X': | 
| 388 | + | thisillum.udir = negax ? UDxneg : UDxpos; | 
| 389 | + | break; | 
| 390 | + | case 'y': | 
| 391 | + | case 'Y': | 
| 392 | + | thisillum.udir = negax ? UDyneg : UDypos; | 
| 393 | + | break; | 
| 394 | + | case 'z': | 
| 395 | + | case 'Z': | 
| 396 | + | thisillum.udir = negax ? UDzneg : UDzpos; | 
| 397 | + | break; | 
| 398 | + | default: | 
| 399 | + | thisillum.udir = UDunknown; | 
| 400 | + | break; | 
| 401 | + | } | 
| 402 | + | if (thisillum.udir == UDunknown || !isspace(*cp)) | 
| 403 | + | break; | 
| 404 | + | continue; | 
| 405 | + | case 't':                       /* object thickness */ | 
| 406 | + | if (*++cp != '=') | 
| 407 | + | break; | 
| 408 | + | if (!isfltd(++cp, " \t\n\r")) | 
| 409 | + | break; | 
| 410 | + | thisillum.thick = atof(cp); | 
| 411 | + | if (thisillum.thick < .0) | 
| 412 | + | thisillum.thick = .0; | 
| 413 | + | cp = sskip(cp); | 
| 414 | + | continue; | 
| 415 |  | case '!':                       /* processed file! */ | 
| 416 |  | sprintf(errmsg, "(%s): already processed!", nm); | 
| 417 |  | error(WARNING, errmsg); | 
| 438 |  | printf("# %s", s+2); | 
| 439 |  | } | 
| 440 |  |  | 
| 441 | < |  | 
| 442 | < | printopts()                     /* print out option default values */ | 
| 441 | > | void | 
| 442 | > | printopts(void)                 /* print out option default values */ | 
| 443 |  | { | 
| 444 |  | printf("m=%-15s\t\t# material name\n", thisillum.matname); | 
| 445 |  | printf("f=%-15s\t\t# data file name\n", thisillum.datafile); | 
| 454 |  | printf("l+\t\t\t\t# light type on\n"); | 
| 455 |  | else | 
| 456 |  | printf("l-\t\t\t\t# light type off\n"); | 
| 457 | < | printf("d=%d\t\t\t\t# density of points\n", thisillum.sampdens); | 
| 458 | < | printf("s=%d\t\t\t\t# samples per point\n", thisillum.nsamps); | 
| 457 | > | printf("d=%d\t\t\t\t# density of directions\n", thisillum.sampdens); | 
| 458 | > | printf("s=%d\t\t\t\t# samples per direction\n", thisillum.nsamps); | 
| 459 |  | printf("b=%f\t\t\t# minimum average brightness\n", thisillum.minbrt); | 
| 460 | + | switch (thisillum.udir) { | 
| 461 | + | case UDzneg: | 
| 462 | + | fputs("u=-Z\t\t\t\t# up is negative Z\n", stdout); | 
| 463 | + | break; | 
| 464 | + | case UDyneg: | 
| 465 | + | fputs("u=-Y\t\t\t\t# up is negative Y\n", stdout); | 
| 466 | + | break; | 
| 467 | + | case UDxneg: | 
| 468 | + | fputs("u=-X\t\t\t\t# up is negative X\n", stdout); | 
| 469 | + | break; | 
| 470 | + | case UDxpos: | 
| 471 | + | fputs("u=+X\t\t\t\t# up is positive X\n", stdout); | 
| 472 | + | break; | 
| 473 | + | case UDypos: | 
| 474 | + | fputs("u=+Y\t\t\t\t# up is positive Y\n", stdout); | 
| 475 | + | break; | 
| 476 | + | case UDzpos: | 
| 477 | + | fputs("u=+Z\t\t\t\t# up is positive Z\n", stdout); | 
| 478 | + | break; | 
| 479 | + | case UDunknown: | 
| 480 | + | break; | 
| 481 | + | } | 
| 482 | + | printf("t=%f\t\t\t# object thickness\n", thisillum.thick); | 
| 483 |  | } | 
| 484 |  |  | 
| 485 |  |  | 
| 486 | < | printhead(ac, av)                       /* print out header */ | 
| 487 | < | register int  ac; | 
| 488 | < | register char  **av; | 
| 486 | > | void | 
| 487 | > | printhead(                      /* print out header */ | 
| 488 | > | register int  ac, | 
| 489 | > | register char  **av | 
| 490 | > | ) | 
| 491 |  | { | 
| 492 |  | putchar('#'); | 
| 493 |  | while (ac-- > 0) { | 
| 498 |  | } | 
| 499 |  |  | 
| 500 |  |  | 
| 501 | < | xobject(fp, nm)                         /* translate an object from fp */ | 
| 502 | < | FILE  *fp; | 
| 503 | < | char  *nm; | 
| 501 | > | void | 
| 502 | > | xobject(                                /* translate an object from fp */ | 
| 503 | > | FILE  *fp, | 
| 504 | > | char  *nm | 
| 505 | > | ) | 
| 506 |  | { | 
| 507 |  | OBJREC  thisobj; | 
| 508 |  | char  str[MAXSTR]; | 
| 553 |  | checkhead(); | 
| 554 |  | /* process object */ | 
| 555 |  | if (doit) | 
| 556 | < | (*ofun[thisobj.otype].funp)(&thisobj, &thisillum, &rt, nm); | 
| 556 | > | switch (thisobj.otype) { | 
| 557 | > | case OBJ_FACE: | 
| 558 | > | my_face(&thisobj, &thisillum, nm); | 
| 559 | > | break; | 
| 560 | > | case OBJ_SPHERE: | 
| 561 | > | my_sphere(&thisobj, &thisillum, nm); | 
| 562 | > | break; | 
| 563 | > | case OBJ_RING: | 
| 564 | > | my_ring(&thisobj, &thisillum, nm); | 
| 565 | > | break; | 
| 566 | > | default: | 
| 567 | > | my_default(&thisobj, &thisillum, nm); | 
| 568 | > | break; | 
| 569 | > | } | 
| 570 |  | else | 
| 571 |  | printobj(thisillum.altmat, &thisobj); | 
| 572 |  | /* free arguments */ | 
| 573 |  | freefargs(&thisobj.oargs); | 
| 574 |  | return; | 
| 575 |  | readerr: | 
| 576 | < | sprintf(errmsg, "(%s): error reading scene", nm); | 
| 576 | > | sprintf(errmsg, "(%s): error reading input", nm); | 
| 577 |  | error(USER, errmsg); | 
| 578 |  | } |