Back to index

radiance  4R0+20100331
mkillum.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char RCSid[] = "$Id: mkillum.c,v 2.36 2009/12/12 19:00:59 greg Exp $";
00003 #endif
00004 /*
00005  * Make illum sources for optimizing rendering process
00006  */
00007 
00008 #include  <signal.h>
00009 #include  <ctype.h>
00010 
00011 #include  "mkillum.h"
00012 
00013                             /* default parameters */
00014 #define  SAMPDENS    48            /* points per projected steradian */
00015 #define  NSAMPS             32            /* samples per point */
00016 #define  DFLMAT             "illum_mat"   /* material name */
00017 #define  DFLDAT             "illum"              /* data file name */
00018                             /* selection options */
00019 #define  S_NONE             0             /* select none */
00020 #define  S_ELEM             1             /* select specified element */
00021 #define  S_COMPL     2             /* select all but element */
00022 #define  S_ALL              3             /* select all */
00023 
00024 struct illum_args  thisillum = {   /* our illum and default values */
00025               0,
00026               UDzpos,
00027               0.,
00028               DFLMAT,
00029               DFLDAT,
00030               0,
00031               VOIDID,
00032               SAMPDENS,
00033               NSAMPS,
00034               NULL,
00035               0.,
00036        };
00037 
00038 char   matcheck[MAXSTR];    /* current material to include or exclude */
00039 int    matselect = S_ALL;   /* selection criterion */
00040 
00041 int    gargc;               /* global argc */
00042 char   **gargv;             /* global argv */
00043 
00044 int    doneheader = 0;             /* printed header yet? */
00045 #define  checkhead() if (!doneheader++) printhead(gargc,gargv)
00046 
00047 int    warnings = 1;        /* print warnings? */
00048 
00049 void init(char *octnm, int np);
00050 void filter(register FILE   *infp, char   *name);
00051 void xoptions(char   *s, char      *nm);
00052 void printopts(void);
00053 void printhead(register int  ac, register char  **av);
00054 void xobject(FILE  *fp, char  *nm);
00055 
00056 
00057 int
00058 main(         /* compute illum distributions using rtrace */
00059        int    argc,
00060        char   *argv[]
00061 )
00062 {
00063        int    nprocs = 1;
00064        FILE   *fp;
00065        int    rval;
00066        register int  i;
00067                             /* set global arguments */
00068        gargv = argv;
00069        progname = gargv[0];
00070                             /* set up rendering defaults */
00071        dstrsrc = 0.5;
00072        directrelay = 3;
00073        directvis = 0;
00074        ambounce = 2;
00075                             /* get options from command line */
00076        for (i = 1; i < argc; i++) {
00077               while ((rval = expandarg(&argc, &argv, i)) > 0)
00078                      ;
00079               if (rval < 0) {
00080                      sprintf(errmsg, "cannot expand '%s'", argv[i]);
00081                      error(SYSTEM, errmsg);
00082               }
00083               if (argv[i][0] != '-')
00084                      break;
00085               if (!strcmp(argv[i], "-w")) {
00086                      warnings = 0;
00087                      continue;
00088               }
00089               if (!strcmp(argv[i], "-n")) {
00090                      nprocs = atoi(argv[++i]);
00091                      if (nprocs <= 0)
00092                             error(USER, "illegal number of processes");
00093                      continue;
00094               }
00095               if (!strcmp(argv[i], "-defaults")) {
00096                      printopts();
00097                      print_rdefaults();
00098                      quit(0);
00099               }
00100               rval = getrenderopt(argc-i, argv+i);
00101               if (rval < 0) {
00102                      sprintf(errmsg, "bad render option at '%s'", argv[i]);
00103                      error(USER, errmsg);
00104               }
00105               i += rval;
00106        }
00107        gargc = ++i;
00108                             /* add "mandatory" render options */
00109        do_irrad = 0;
00110        if (gargc > argc || argv[gargc-1][0] == '-')
00111               error(USER, "missing octree argument");
00112                             /* else initialize and run our calculation */
00113        init(argv[gargc-1], nprocs);
00114        if (gargc < argc) {
00115               if (gargc == argc-1 || argv[gargc][0] != '<' || argv[gargc][1])
00116                      error(USER, "use '< file1 file2 ..' for multiple inputs");
00117               for (i = gargc+1; i < argc; i++) {
00118                      if ((fp = fopen(argv[i], "r")) == NULL) {
00119                             sprintf(errmsg,
00120                             "cannot open scene file \"%s\"", argv[i]);
00121                             error(SYSTEM, errmsg);
00122                      }
00123                      filter(fp, argv[i]);
00124                      fclose(fp);
00125               }
00126        } else
00127               filter(stdin, "standard input");
00128        quit(0);
00129        return 0; /* pro forma return */
00130 }
00131 
00132 
00133 void
00134 init(char *octnm, int np)          /* start rendering process(es) */
00135 {
00136                                    /* set up signal handling */
00137        signal(SIGINT, quit);
00138 #ifdef SIGHUP
00139        signal(SIGHUP, quit);
00140 #endif
00141 #ifdef SIGTERM
00142        signal(SIGTERM, quit);
00143 #endif
00144 #ifdef SIGPIPE
00145        signal(SIGPIPE, quit);
00146 #endif
00147                                    /* start rendering process(es) */
00148        ray_pinit(octnm, np);
00149 }
00150 
00151 
00152 void
00153 eputs(                      /* put string to stderr */
00154        register char  *s
00155 )
00156 {
00157        static int  midline = 0;
00158 
00159        if (!*s) return;
00160        if (!midline) {
00161               fputs(progname, stderr);
00162               fputs(": ", stderr);
00163        }
00164        fputs(s, stderr);
00165        midline = s[strlen(s)-1] != '\n';
00166 }
00167 
00168 
00169 void
00170 wputs(s)                    /* print warning if enabled */
00171 char  *s;
00172 {
00173        if (warnings)
00174               eputs(s);
00175 }
00176 
00177 
00178 void
00179 quit(ec)                    /* make sure exit is called */
00180 int    ec;
00181 {
00182        if (ray_pnprocs > 0) /* close children if any */
00183               ray_pclose(0);              
00184        exit(ec);
00185 }
00186 
00187 
00188 void
00189 filter(              /* process stream */
00190        register FILE *infp,
00191        char   *name
00192 )
00193 {
00194        char   buf[512];
00195        FILE   *pfp;
00196        register int  c;
00197 
00198        while ((c = getc(infp)) != EOF) {
00199               if (isspace(c))
00200                      continue;
00201               if (c == '#') {                           /* comment/options */
00202                      buf[0] = c;
00203                      fgets(buf+1, sizeof(buf)-1, infp);
00204                      xoptions(buf, name);
00205               } else if (c == '!') {                    /* command */
00206                      buf[0] = c;
00207                      fgetline(buf+1, sizeof(buf)-1, infp);
00208                      if ((pfp = popen(buf+1, "r")) == NULL) {
00209                             sprintf(errmsg, "cannot execute \"%s\"", buf);
00210                             error(SYSTEM, errmsg);
00211                      }
00212                      filter(pfp, buf);
00213                      pclose(pfp);
00214               } else {                           /* object */
00215                      ungetc(c, infp);
00216                      xobject(infp, name);
00217               }
00218        }
00219 }
00220 
00221 
00222 void
00223 xoptions(                   /* process options in string s */
00224        char   *s,
00225        char   *nm
00226 )
00227 {
00228        extern FILE   *freopen();
00229        char   buf[64];
00230        int    negax;
00231        int    nerrs = 0;
00232        register char *cp;
00233 
00234        if (strncmp(s, "#@mkillum", 9) || !isspace(s[9])) {
00235               fputs(s, stdout);           /* not for us */
00236               return;
00237        }
00238        cp = s+10;
00239        while (*cp) {
00240               switch (*cp) {
00241               case ' ':
00242               case '\t':
00243               case '\n':
00244               case '\r':
00245               case '\f':
00246                      cp++;
00247                      continue;
00248               case 'm':                   /* material name */
00249                      if (*++cp != '=')
00250                             break;
00251                      if (!*++cp || isspace(*cp))
00252                             break;
00253                      atos(thisillum.matname, MAXSTR, cp);
00254                      cp = sskip(cp);
00255                      if (!(thisillum.flags & IL_DATCLB)) {
00256                             strcpy(thisillum.datafile, thisillum.matname);
00257                             thisillum.dfnum = 0;
00258                      }
00259                      continue;
00260               case 'f':                   /* data file name */
00261                      if (*++cp != '=')
00262                             break;
00263                      if (!*++cp || isspace(*cp)) {
00264                             strcpy(thisillum.datafile,thisillum.matname);
00265                             thisillum.dfnum = 0;
00266                             thisillum.flags &= ~IL_DATCLB;
00267                             continue;
00268                      }
00269                      atos(thisillum.datafile, MAXSTR, cp);
00270                      cp = sskip(cp);
00271                      thisillum.dfnum = 0;
00272                      thisillum.flags |= IL_DATCLB;
00273                      continue;
00274               case 'i':                   /* include material */
00275               case 'e':                   /* exclude material */
00276                      if (cp[1] != '=')
00277                             break;
00278                      matselect = (*cp == 'i') ? S_ELEM : S_COMPL;
00279                      cp += 2;
00280                      atos(matcheck, MAXSTR, cp);
00281                      cp = sskip(cp);
00282                      continue;
00283               case 'a':                   /* use everything */
00284                      cp = sskip(cp);
00285                      matselect = S_ALL;
00286                      continue;
00287               case 'n':                   /* use nothing (passive) */
00288                      cp = sskip(cp);
00289                      matselect = S_NONE;
00290                      continue;
00291               case 'c':                   /* color calculation */
00292                      if (*++cp != '=')
00293                             break;
00294                      switch (*++cp) {
00295                      case 'a':                   /* average */
00296                             thisillum.flags = (thisillum.flags|IL_COLAVG)
00297                                                  & ~IL_COLDST;
00298                             break;
00299                      case 'd':                   /* distribution */
00300                             thisillum.flags |= (IL_COLDST|IL_COLAVG);
00301                             break;
00302                      case 'n':                   /* none */
00303                             thisillum.flags &= ~(IL_COLAVG|IL_COLDST);
00304                             break;
00305                      default:
00306                             goto opterr;
00307                      }
00308                      cp = sskip(cp);
00309                      continue;
00310               case 'd':                   /* sample density / BSDF data */
00311                      if (*++cp != '=')
00312                             break;
00313                      if (thisillum.sd != NULL) {
00314                             free_BSDF(thisillum.sd);
00315                             thisillum.sd = NULL;
00316                      }
00317                      if (!*++cp || isspace(*cp))
00318                             continue;
00319                      if (isintd(cp, " \t\n\r")) {
00320                             thisillum.sampdens = atoi(cp);
00321                      } else {
00322                             atos(buf, sizeof(buf), cp);
00323                             thisillum.sd = load_BSDF(buf);
00324                             if (thisillum.sd == NULL)
00325                                    break;
00326                      }
00327                      cp = sskip(cp);
00328                      continue;
00329               case 's':                   /* surface super-samples */
00330                      if (*++cp != '=')
00331                             break;
00332                      if (!isintd(++cp, " \t\n\r"))
00333                             break;
00334                      thisillum.nsamps = atoi(cp);
00335                      cp = sskip(cp);
00336                      continue;
00337               case 'l':                   /* light sources */
00338                      cp++;
00339                      if (*cp == '+')
00340                             thisillum.flags |= IL_LIGHT;
00341                      else if (*cp == '-')
00342                             thisillum.flags &= ~IL_LIGHT;
00343                      else
00344                             break;
00345                      cp++;
00346                      continue;
00347               case 'b':                   /* brightness */
00348                      if (*++cp != '=')
00349                             break;
00350                      if (!isfltd(++cp, " \t\n\r"))
00351                             break;
00352                      thisillum.minbrt = atof(cp);
00353                      if (thisillum.minbrt < 0.)
00354                             thisillum.minbrt = 0.;
00355                      cp = sskip(cp);
00356                      continue;
00357               case 'o':                   /* output file */
00358                      if (*++cp != '=')
00359                             break;
00360                      if (!*++cp || isspace(*cp))
00361                             break;
00362                      atos(buf, sizeof(buf), cp);
00363                      cp = sskip(cp);
00364                      if (freopen(buf, "w", stdout) == NULL) {
00365                             sprintf(errmsg,
00366                             "cannot open output file \"%s\"", buf);
00367                             error(SYSTEM, errmsg);
00368                      }
00369                      doneheader = 0;
00370                      continue;
00371               case 'u':                   /* up direction */
00372                      if (*++cp != '=')
00373                             break;
00374                      if (!*++cp || isspace(*cp)) {
00375                             thisillum.udir = UDunknown;
00376                             continue;
00377                      }
00378                      negax = 0;
00379                      if (*cp == '+')
00380                             cp++;
00381                      else if (*cp == '-') {
00382                             negax++;
00383                             cp++;
00384                      }
00385                      switch (*cp++) {
00386                      case 'x':
00387                      case 'X':
00388                             thisillum.udir = negax ? UDxneg : UDxpos;
00389                             break;
00390                      case 'y':
00391                      case 'Y':
00392                             thisillum.udir = negax ? UDyneg : UDypos;
00393                             break;
00394                      case 'z':
00395                      case 'Z':
00396                             thisillum.udir = negax ? UDzneg : UDzpos;
00397                             break;
00398                      default:
00399                             thisillum.udir = UDunknown;
00400                             break;
00401                      }
00402                      if (thisillum.udir == UDunknown || !isspace(*cp))
00403                             break;
00404                      continue;
00405               case 't':                   /* object thickness */
00406                      if (*++cp != '=')
00407                             break;
00408                      if (!isfltd(++cp, " \t\n\r"))
00409                             break;
00410                      thisillum.thick = atof(cp);
00411                      if (thisillum.thick < .0)
00412                             thisillum.thick = .0;
00413                      cp = sskip(cp);
00414                      continue;
00415               case '!':                   /* processed file! */
00416                      sprintf(errmsg, "(%s): already processed!", nm);
00417                      error(WARNING, errmsg);
00418                      matselect = S_NONE;
00419                      return;
00420               }
00421        opterr:                                   /* skip faulty option */
00422               while (*cp && !isspace(*cp))
00423                      cp++;
00424               nerrs++;
00425        }
00426                                           /* print header? */
00427        checkhead();
00428                                           /* issue warnings? */
00429        if (nerrs) {
00430               sprintf(errmsg, "(%s): %d error(s) in option line:",
00431                             nm, nerrs);
00432               error(WARNING, errmsg);
00433               wputs(s);
00434               printf("# %s: the following option line has %d error(s):\n",
00435                             progname, nerrs);
00436        }
00437                                           /* print pure comment */
00438        printf("# %s", s+2);
00439 }
00440 
00441 void
00442 printopts(void)                    /* print out option default values */
00443 {
00444        printf("m=%-15s\t\t# material name\n", thisillum.matname);
00445        printf("f=%-15s\t\t# data file name\n", thisillum.datafile);
00446        if (thisillum.flags & IL_COLAVG)
00447               if (thisillum.flags & IL_COLDST)
00448                      printf("c=d\t\t\t\t# color distribution\n");
00449               else
00450                      printf("c=a\t\t\t\t# color average\n");
00451        else
00452               printf("c=n\t\t\t\t# color none\n");
00453        if (thisillum.flags & IL_LIGHT)
00454               printf("l+\t\t\t\t# light type on\n");
00455        else
00456               printf("l-\t\t\t\t# light type off\n");
00457        printf("d=%d\t\t\t\t# density of directions\n", thisillum.sampdens);
00458        printf("s=%d\t\t\t\t# samples per direction\n", thisillum.nsamps);
00459        printf("b=%f\t\t\t# minimum average brightness\n", thisillum.minbrt);
00460        switch (thisillum.udir) {
00461        case UDzneg:
00462               fputs("u=-Z\t\t\t\t# up is negative Z\n", stdout);
00463               break;
00464        case UDyneg:
00465               fputs("u=-Y\t\t\t\t# up is negative Y\n", stdout);
00466               break;
00467        case UDxneg:
00468               fputs("u=-X\t\t\t\t# up is negative X\n", stdout);
00469               break;
00470        case UDxpos:
00471               fputs("u=+X\t\t\t\t# up is positive X\n", stdout);
00472               break;
00473        case UDypos:
00474               fputs("u=+Y\t\t\t\t# up is positive Y\n", stdout);
00475               break;
00476        case UDzpos:
00477               fputs("u=+Z\t\t\t\t# up is positive Z\n", stdout);
00478               break;
00479        case UDunknown:
00480               break;
00481        }
00482        printf("t=%f\t\t\t# object thickness\n", thisillum.thick);
00483 }
00484 
00485 
00486 void
00487 printhead(                  /* print out header */
00488        register int  ac,
00489        register char  **av
00490 )
00491 {
00492        putchar('#');
00493        while (ac-- > 0) {
00494               putchar(' ');
00495               fputs(*av++, stdout);
00496        }
00497        fputs("\n#@mkillum !\n", stdout);
00498 }
00499 
00500 
00501 void
00502 xobject(                           /* translate an object from fp */
00503        FILE  *fp,
00504        char  *nm
00505 )
00506 {
00507        OBJREC  thisobj;
00508        char  str[MAXSTR];
00509        int  doit;
00510                                    /* read the object */
00511        if (fgetword(thisillum.altmat, MAXSTR, fp) == NULL)
00512               goto readerr;
00513        if (fgetword(str, MAXSTR, fp) == NULL)
00514               goto readerr;
00515                                    /* is it an alias? */
00516        if (!strcmp(str, ALIASKEY)) {
00517               if (fgetword(str, MAXSTR, fp) == NULL)
00518                      goto readerr;
00519               printf("\n%s %s %s", thisillum.altmat, ALIASKEY, str);
00520               if (fgetword(str, MAXSTR, fp) == NULL)
00521                      goto readerr;
00522               printf("\t%s\n", str);
00523               return;
00524        }
00525        thisobj.omod = OVOID;              /* unused field */
00526        if ((thisobj.otype = otype(str)) < 0) {
00527               sprintf(errmsg, "(%s): unknown type \"%s\"", nm, str);
00528               error(USER, errmsg);
00529        }
00530        if (fgetword(str, MAXSTR, fp) == NULL)
00531               goto readerr;
00532        thisobj.oname = str;
00533        if (readfargs(&thisobj.oargs, fp) != 1)
00534               goto readerr;
00535        thisobj.os = NULL;
00536                                    /* check for translation */
00537        switch (matselect) {
00538        case S_NONE:
00539               doit = 0;
00540               break;
00541        case S_ALL:
00542               doit = 1;
00543               break;
00544        case S_ELEM:
00545               doit = !strcmp(thisillum.altmat, matcheck);
00546               break;
00547        case S_COMPL:
00548               doit = strcmp(thisillum.altmat, matcheck);
00549               break;
00550        }
00551        doit = doit && issurface(thisobj.otype);
00552                                           /* print header? */
00553        checkhead();
00554                                           /* process object */
00555        if (doit)
00556               switch (thisobj.otype) {
00557               case OBJ_FACE:
00558                      my_face(&thisobj, &thisillum, nm);
00559                      break;
00560               case OBJ_SPHERE:
00561                      my_sphere(&thisobj, &thisillum, nm);
00562                      break;
00563               case OBJ_RING:
00564                      my_ring(&thisobj, &thisillum, nm);
00565                      break;
00566               default:
00567                      my_default(&thisobj, &thisillum, nm);
00568                      break;
00569               }
00570        else
00571               printobj(thisillum.altmat, &thisobj);
00572                                           /* free arguments */
00573        freefargs(&thisobj.oargs);
00574        return;
00575 readerr:
00576        sprintf(errmsg, "(%s): error reading input", nm);
00577        error(USER, errmsg);
00578 }