| 1 | – | /* Copyright (c) 1991 Regents of the University of California */ | 
| 2 | – |  | 
| 1 |  | #ifndef lint | 
| 2 | < | static char SCCSid[] = "$SunId$ LBL"; | 
| 2 | > | static const char RCSid[] = "$Id$"; | 
| 3 |  | #endif | 
| 6 | – |  | 
| 4 |  | /* | 
| 5 |  | * Make illum sources for optimizing rendering process | 
| 6 |  | */ | 
| 7 |  |  | 
| 11 | – | #include  "mkillum.h" | 
| 12 | – |  | 
| 8 |  | #include  <signal.h> | 
| 14 | – |  | 
| 9 |  | #include  <ctype.h> | 
| 10 |  |  | 
| 11 | + | #include  "paths.h"             /* win_popen() */ | 
| 12 | + | #include  "mkillum.h" | 
| 13 | + |  | 
| 14 |  | /* default parameters */ | 
| 15 |  | #define  SAMPDENS       48              /* points per projected steradian */ | 
| 16 |  | #define  NSAMPS         32              /* samples per point */ | 
| 22 |  | #define  S_COMPL        2               /* select all but element */ | 
| 23 |  | #define  S_ALL          3               /* select all */ | 
| 24 |  |  | 
| 28 | – | /* rtrace command and defaults */ | 
| 29 | – | char  *rtargv[64] = { "rtrace", "-dj", ".25", "-dr", "3", "-di+", | 
| 30 | – | "-ab", "2", "-ad", "256", "-as", "128", "-aa", ".15", }; | 
| 31 | – | int  rtargc = 14; | 
| 32 | – | /* overriding rtrace options */ | 
| 33 | – | char  *myrtopts[] = { "-I-", "-i-", "-ov", "-h-", "-fff", "-y", "0", NULL }; | 
| 34 | – |  | 
| 35 | – | struct rtproc   rt;             /* our rtrace process */ | 
| 36 | – |  | 
| 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 |  |  | 
| 51 | – | FUN     ofun[NUMOTYPE] = INIT_OTYPE;    /* object types */ | 
| 52 | – |  | 
| 39 |  | int     gargc;                  /* global argc */ | 
| 40 |  | char    **gargv;                /* global argv */ | 
| 55 | – | #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 | < | extern char     *fgetline(), *fgetword(), *sskip(), | 
| 48 | < | *atos(), *iskip(), *fskip(), *strcpy(); | 
| 49 | < | extern FILE     *popen(); | 
| 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 |  |  | 
| 55 | < | main(argc, argv)                /* compute illum distributions using rtrace */ | 
| 56 | < | int     argc; | 
| 57 | < | char    *argv[]; | 
| 55 | > | int | 
| 56 | > | main(           /* compute illum distributions using rtrace */ | 
| 57 | > | int     argc, | 
| 58 | > | char    *argv[] | 
| 59 | > | ) | 
| 60 |  | { | 
| 61 | < | extern char     *getenv(), *getpath(); | 
| 72 | < | 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]) | 
| 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 | < | warnings = !warnings; | 
| 84 | < | } | 
| 85 | < | gargc = i; | 
| 86 | < | rtargc--; | 
| 87 | < | for (i = 0; myrtopts[i] != NULL; i++) | 
| 88 | < | rtargv[rtargc++] = myrtopts[i]; | 
| 89 | < | rtargv[rtargc++] = argv[gargc-1]; | 
| 90 | < | rtargv[rtargc] = NULL; | 
| 91 | < | /* just asking for defaults? */ | 
| 92 | < | if (!strcmp(argv[gargc-1], "-defaults")) { | 
| 93 | < | printopts(); fflush(stdout); | 
| 94 | < | rtpath = getpath(rtargv[0], getenv("PATH"), X_OK); | 
| 95 | < | if (rtpath == NULL) { | 
| 96 | < | eputs(rtargv[0]); | 
| 97 | < | eputs(": command not found\n"); | 
| 98 | < | 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 | < | quit(status)                    /* exit with status */ | 
| 131 | < | int  status; | 
| 130 | > | void | 
| 131 | > | init(char *octnm, int np)               /* start rendering process(es) */ | 
| 132 |  | { | 
| 127 | – | int     rtstat; | 
| 128 | – |  | 
| 129 | – | rtstat = close_process(rt.pd); | 
| 130 | – | if (status == 0) | 
| 131 | – | if (rtstat < 0) | 
| 132 | – | error(WARNING, | 
| 133 | – | "unknown return status from rtrace process"); | 
| 134 | – | else | 
| 135 | – | status = rtstat; | 
| 136 | – | exit(status); | 
| 137 | – | } | 
| 138 | – |  | 
| 139 | – |  | 
| 140 | – | init()                          /* start rtrace and set up buffers */ | 
| 141 | – | { | 
| 142 | – | extern int  o_face(), o_sphere(), o_ring(); | 
| 143 | – | int     maxbytes; | 
| 144 | – | /* set up object functions */ | 
| 145 | – | ofun[OBJ_FACE].funp = o_face; | 
| 146 | – | ofun[OBJ_SPHERE].funp = o_sphere; | 
| 147 | – | ofun[OBJ_RING].funp = o_ring; | 
| 133 |  | /* set up signal handling */ | 
| 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 | < | /* start rtrace process */ | 
| 144 | < | errno = 0; | 
| 145 | < | maxbytes = open_process(rt.pd, rtargv); | 
| 153 | < | if (maxbytes == 0) { | 
| 154 | < | eputs(rtargv[0]); | 
| 155 | < | eputs(": command not found\n"); | 
| 156 | < | exit(1); | 
| 157 | < | } | 
| 158 | < | if (maxbytes < 0) | 
| 159 | < | error(SYSTEM, "cannot start rtrace process"); | 
| 160 | < | rt.bsiz = maxbytes/(6*sizeof(float)); | 
| 161 | < | rt.buf = (float *)malloc(6*sizeof(float)*rt.bsiz--); | 
| 162 | < | rt.dest = (float **)malloc(sizeof(float *)*rt.bsiz); | 
| 163 | < | if (rt.buf == NULL || rt.dest == NULL) | 
| 164 | < | error(SYSTEM, "out of memory in init"); | 
| 165 | < | rt.nrays = 0; | 
| 166 | < | /* set up urand */ | 
| 167 | < | initurand(2048); | 
| 143 | > | #endif | 
| 144 | > | /* start rendering process(es) */ | 
| 145 | > | ray_pinit(octnm, np); | 
| 146 |  | } | 
| 147 |  |  | 
| 148 |  |  | 
| 149 | < | eputs(s)                                /* put string to stderr */ | 
| 150 | < | register char  *s; | 
| 149 | > | void | 
| 150 | > | eputs(                          /* put string to stderr */ | 
| 151 | > | const char  *s | 
| 152 | > | ) | 
| 153 |  | { | 
| 154 |  | static int  midline = 0; | 
| 155 |  |  | 
| 163 |  | } | 
| 164 |  |  | 
| 165 |  |  | 
| 166 | < | wputs(s)                        /* print warning if enabled */ | 
| 167 | < | char  *s; | 
| 166 | > | void | 
| 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; | 
| 196 | < | 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 |  | { | 
| 230 | – | 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 */ | 
| 240 |  | case ' ': | 
| 241 |  | case '\t': | 
| 242 |  | case '\n': | 
| 243 | + | case '\r': | 
| 244 | + | case '\f': | 
| 245 |  | cp++; | 
| 246 |  | continue; | 
| 247 |  | case 'm':                       /* material name */ | 
| 248 |  | if (*++cp != '=') | 
| 249 |  | break; | 
| 250 | < | if (!*++cp) | 
| 250 | > | if (!*++cp || isspace(*cp)) | 
| 251 |  | break; | 
| 252 |  | atos(thisillum.matname, MAXSTR, cp); | 
| 253 |  | cp = sskip(cp); | 
| 259 |  | case 'f':                       /* data file name */ | 
| 260 |  | if (*++cp != '=') | 
| 261 |  | break; | 
| 262 | < | if (!*++cp) { | 
| 262 | > | if (!*++cp || isspace(*cp)) { | 
| 263 |  | strcpy(thisillum.datafile,thisillum.matname); | 
| 264 |  | thisillum.dfnum = 0; | 
| 265 |  | thisillum.flags &= ~IL_DATCLB; | 
| 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")) | 
| 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")) | 
| 325 | > | if (!isintd(++cp, " \t\n\r")) | 
| 326 |  | break; | 
| 327 |  | thisillum.nsamps = atoi(cp); | 
| 328 |  | cp = sskip(cp); | 
| 340 |  | case 'b':                       /* brightness */ | 
| 341 |  | if (*++cp != '=') | 
| 342 |  | break; | 
| 343 | < | if (!isfltd(++cp, " \t\n")) | 
| 343 | > | if (!isfltd(++cp, " \t\n\r")) | 
| 344 |  | break; | 
| 345 |  | thisillum.minbrt = atof(cp); | 
| 346 |  | if (thisillum.minbrt < 0.) | 
| 350 |  | case 'o':                       /* output file */ | 
| 351 |  | if (*++cp != '=') | 
| 352 |  | break; | 
| 353 | < | if (!*++cp) | 
| 353 | > | if (!*++cp || isspace(*cp)) | 
| 354 |  | break; | 
| 355 |  | atos(buf, sizeof(buf), cp); | 
| 356 |  | cp = sskip(cp); | 
| 368 |  | return; | 
| 369 |  | } | 
| 370 |  | opterr:                                 /* skip faulty option */ | 
| 371 | < | cp = sskip(cp); | 
| 371 | > | while (*cp && !isspace(*cp)) | 
| 372 | > | cp++; | 
| 373 |  | nerrs++; | 
| 374 |  | } | 
| 375 |  | /* print header? */ | 
| 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]; | 
| 439 |  | if (fgetword(str, MAXSTR, fp) == NULL) | 
| 440 |  | goto readerr; | 
| 441 |  | /* is it an alias? */ | 
| 442 | < | if (!strcmp(str, ALIASID)) { | 
| 442 | > | if (!strcmp(str, ALIASKEY)) { | 
| 443 |  | if (fgetword(str, MAXSTR, fp) == NULL) | 
| 444 |  | goto readerr; | 
| 445 | < | printf("\n%s %s %s", thisillum.altmat, ALIASID, str); | 
| 445 | > | printf("\n%s %s %s", thisillum.altmat, ALIASKEY, str); | 
| 446 |  | if (fgetword(str, MAXSTR, fp) == NULL) | 
| 447 |  | goto readerr; | 
| 448 |  | printf("\t%s\n", str); | 
| 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 |  | } |