/* Copyright (c) 1991 Regents of the University of California */ #ifndef lint static char SCCSid[] = "$SunId$ LBL"; #endif /* * Make illum sources for optimizing rendering process */ #include "mkillum.h" #include #include /* default parameters */ #define SAMPDENS 48 /* points per projected steradian */ #define NSAMPS 32 /* samples per point */ #define DFLMAT "illum_mat" /* material name */ #define DFLDAT "illum" /* data file name */ /* selection options */ #define S_NONE 0 /* select none */ #define S_ELEM 1 /* select specified element */ #define S_COMPL 2 /* select all but element */ #define S_ALL 3 /* select all */ /* rtrace command and defaults */ char *rtargv[64] = { "rtrace", "-dj", ".25", "-dr", "3", "-di+", "-ab", "2", "-ad", "256", "-as", "128", "-aa", ".15", }; int rtargc = 14; /* overriding rtrace options */ char *myrtopts[] = { "-I-", "-i-", "-ov", "-h-", "-fff", NULL }; struct rtproc rt; /* our rtrace process */ struct illum_args thisillum = { /* our illum and default values */ 0, DFLMAT, DFLDAT, 0, VOIDID, SAMPDENS, NSAMPS, 0., }; char matcheck[MAXSTR]; /* current material to include or exclude */ int matselect = S_ALL; /* selection criterion */ FUN ofun[NUMOTYPE] = INIT_OTYPE; /* object types */ int gargc; /* global argc */ char **gargv; /* global argv */ #define progname gargv[0] int doneheader = 0; /* printed header yet? */ #define checkhead() if (!doneheader++) printhead(gargc,gargv) int warnings = 1; /* print warnings? */ extern char *fgetline(), *fgetword(), *sskip(), *atos(), *iskip(), *fskip(), *strcpy(); extern FILE *popen(); main(argc, argv) /* compute illum distributions using rtrace */ int argc; char *argv[]; { extern char *getenv(), *getpath(); char *rtpath; FILE *fp; register int i; /* set global arguments */ gargv = argv; /* set up rtrace command */ for (i = 1; i < argc; i++) { if (argv[i][0] == '<' && !argv[i][1]) break; rtargv[rtargc++] = argv[i]; if (argv[i][0] == '-' && argv[i][1] == 'w') warnings = !warnings; } if ((gargc = i) < 2) error(USER, "too few arguments"); rtargc--; for (i = 0; myrtopts[i] != NULL; i++) rtargv[rtargc++] = myrtopts[i]; rtargv[rtargc++] = argv[gargc-1]; rtargv[rtargc] = NULL; /* just asking for defaults? */ if (!strcmp(argv[gargc-1], "-defaults")) { printopts(); fflush(stdout); rtpath = getpath(rtargv[0], getenv("PATH"), X_OK); if (rtpath == NULL) { eputs(rtargv[0]); eputs(": command not found\n"); exit(1); } execv(rtpath, rtargv); perror(rtpath); exit(1); } /* else initialize and run our calculation */ init(); if (gargc+1 < argc) for (i = gargc+1; i < argc; i++) { if ((fp = fopen(argv[i], "r")) == NULL) { sprintf(errmsg, "cannot open scene file \"%s\"", argv[i]); error(SYSTEM, errmsg); } filter(fp, argv[i]); fclose(fp); } else filter(stdin, "standard input"); quit(0); } quit(status) /* exit with status */ int status; { int rtstat; rtstat = close_process(rt.pd); if (status == 0) if (rtstat < 0) error(WARNING, "unknown return status from rtrace process"); else status = rtstat; exit(status); } init() /* start rtrace and set up buffers */ { extern int o_face(), o_sphere(), o_ring(); int maxbytes; /* set up object functions */ ofun[OBJ_FACE].funp = o_face; ofun[OBJ_SPHERE].funp = o_sphere; ofun[OBJ_RING].funp = o_ring; /* set up signal handling */ signal(SIGPIPE, quit); /* start rtrace process */ maxbytes = open_process(rt.pd, rtargv); if (maxbytes == 0) { eputs(rtargv[0]); eputs(": command not found\n"); exit(1); } if (maxbytes < 0) error(SYSTEM, "cannot start rtrace process"); rt.bsiz = maxbytes/(6*sizeof(float)); rt.buf = (float *)malloc(6*sizeof(float)*rt.bsiz--); rt.dest = (float **)malloc(sizeof(float *)*rt.bsiz); if (rt.buf == NULL || rt.dest == NULL) error(SYSTEM, "out of memory in init"); rt.nrays = 0; /* set up urand */ initurand(2048); } eputs(s) /* put string to stderr */ register char *s; { static int midline = 0; if (!*s) return; if (!midline) { fputs(progname, stderr); fputs(": ", stderr); } fputs(s, stderr); midline = s[strlen(s)-1] != '\n'; } wputs(s) /* print warning if enabled */ char *s; { if (warnings) eputs(s); } filter(infp, name) /* process stream */ register FILE *infp; char *name; { char buf[512]; FILE *pfp; register int c; while ((c = getc(infp)) != EOF) { if (isspace(c)) continue; if (c == '#') { /* comment/options */ buf[0] = c; fgets(buf+1, sizeof(buf)-1, infp); xoptions(buf, name); } else if (c == '!') { /* command */ buf[0] = c; fgetline(buf+1, sizeof(buf)-1, infp); if ((pfp = popen(buf+1, "r")) == NULL) { sprintf(errmsg, "cannot execute \"%s\"", buf); error(SYSTEM, errmsg); } filter(pfp, buf); pclose(pfp); } else { /* object */ ungetc(c, infp); xobject(infp, name); } } } xoptions(s, nm) /* process options in string s */ char *s; char *nm; { extern FILE *freopen(); char buf[64]; int nerrs = 0; register char *cp; if (strncmp(s, "#@mkillum", 9) || !isspace(s[9])) { fputs(s, stdout); /* not for us */ return; } cp = s+10; while (*cp) { switch (*cp) { case ' ': case '\t': case '\n': cp++; continue; case 'm': /* material name */ if (*++cp != '=') break; if (!*++cp) break; atos(thisillum.matname, MAXSTR, cp); cp = sskip(cp); if (!(thisillum.flags & IL_DATCLB)) { strcpy(thisillum.datafile, thisillum.matname); thisillum.dfnum = 0; } continue; case 'f': /* data file name */ if (*++cp != '=') break; if (!*++cp) { strcpy(thisillum.datafile,thisillum.matname); thisillum.dfnum = 0; thisillum.flags &= ~IL_DATCLB; continue; } atos(thisillum.datafile, MAXSTR, cp); cp = sskip(cp); thisillum.dfnum = 0; thisillum.flags |= IL_DATCLB; continue; case 'i': /* include material */ case 'e': /* exclude material */ if (cp[1] != '=') break; matselect = (*cp == 'i') ? S_ELEM : S_COMPL; cp += 2; atos(matcheck, MAXSTR, cp); cp = sskip(cp); continue; case 'a': /* use everything */ cp = sskip(cp); matselect = S_ALL; continue; case 'n': /* use nothing (passive) */ cp = sskip(cp); matselect = S_NONE; continue; case 'c': /* color calculation */ if (*++cp != '=') break; switch (*++cp) { case 'a': /* average */ thisillum.flags = (thisillum.flags|IL_COLAVG) & ~IL_COLDST; break; case 'd': /* distribution */ thisillum.flags |= (IL_COLDST|IL_COLAVG); break; case 'n': /* none */ thisillum.flags &= ~(IL_COLAVG|IL_COLDST); break; default: goto opterr; } cp = sskip(cp); continue; case 'd': /* point sample density */ if (*++cp != '=') break; if (!isintd(++cp, " \t\n")) break; thisillum.sampdens = atoi(cp); cp = sskip(cp); continue; case 's': /* point super-samples */ if (*++cp != '=') break; if (!isintd(++cp, " \t\n")) break; thisillum.nsamps = atoi(cp); cp = sskip(cp); continue; case 'l': /* light sources */ cp++; if (*cp == '+') thisillum.flags |= IL_LIGHT; else if (*cp == '-') thisillum.flags &= ~IL_LIGHT; else break; cp++; continue; case 'b': /* brightness */ if (*++cp != '=') break; if (!isfltd(++cp, " \t\n")) break; thisillum.minbrt = atof(cp); cp = sskip(cp); continue; case 'o': /* output file */ if (*++cp != '=') break; if (!*++cp) break; atos(buf, sizeof(buf), cp); cp = sskip(cp); if (freopen(buf, "w", stdout) == NULL) { sprintf(errmsg, "cannot open output file \"%s\"", buf); error(SYSTEM, errmsg); } doneheader = 0; continue; case '!': /* processed file! */ sprintf(errmsg, "(%s): already processed!", nm); error(WARNING, errmsg); matselect = S_NONE; return; } opterr: /* skip faulty option */ cp = sskip(cp); nerrs++; } /* print header? */ checkhead(); /* issue warnings? */ if (nerrs) { sprintf(errmsg, "(%s): %d error(s) in option line:", nm, nerrs); error(WARNING, errmsg); wputs(s); printf("# %s: the following option line has %d error(s):\n", progname, nerrs); } /* print pure comment */ printf("# %s", s+2); } printopts() /* print out option default values */ { printf("m=%-15s\t\t# material name\n", thisillum.matname); printf("f=%-15s\t\t# data file name\n", thisillum.datafile); printf("c=n\t\t\t\t# color none\n"); printf("d=%d\t\t\t\t# density of points\n", thisillum.sampdens); printf("s=%d\t\t\t\t# samples per point\n", thisillum.nsamps); printf("b=%f\t\t\t# minimum average brightness\n", thisillum.minbrt); } printhead(ac, av) /* print out header */ register int ac; register char **av; { putchar('#'); while (ac-- > 0) { putchar(' '); fputs(*av++, stdout); } fputs("\n#@mkillum !\n", stdout); } xobject(fp, nm) /* translate an object from fp */ FILE *fp; char *nm; { OBJREC thisobj; char str[MAXSTR]; int doit; /* read the object */ if (fgetword(thisillum.altmat, MAXSTR, fp) == NULL) goto readerr; if (fgetword(str, MAXSTR, fp) == NULL) goto readerr; /* is it an alias? */ if (!strcmp(str, ALIASID)) { if (fgetword(str, MAXSTR, fp) == NULL) goto readerr; printf("\n%s %s %s", thisillum.altmat, ALIASID, str); if (fgetword(str, MAXSTR, fp) == NULL) goto readerr; printf("\t%s\n", str); return; } thisobj.omod = OVOID; /* unused field */ if ((thisobj.otype = otype(str)) < 0) { sprintf(errmsg, "(%s): unknown type \"%s\"", nm, str); error(USER, errmsg); } if (fgetword(str, MAXSTR, fp) == NULL) goto readerr; thisobj.oname = str; if (readfargs(&thisobj.oargs, fp) != 1) goto readerr; thisobj.os = NULL; /* check for translation */ switch (matselect) { case S_NONE: doit = 0; break; case S_ALL: doit = 1; break; case S_ELEM: doit = !strcmp(thisillum.altmat, matcheck); break; case S_COMPL: doit = strcmp(thisillum.altmat, matcheck); break; } doit = doit && issurface(thisobj.otype); /* print header? */ checkhead(); /* process object */ if (doit) (*ofun[thisobj.otype].funp)(&thisobj, &thisillum, &rt, nm); else printobj(thisillum.altmat, &thisobj); /* free arguments */ freefargs(&thisobj.oargs); return; readerr: sprintf(errmsg, "(%s): error reading scene", nm); error(USER, errmsg); }