Back to index

radiance  4R0+20100331
rpmain.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char    RCSid[] = "$Id: rpmain.c,v 2.14 2008/03/11 02:21:47 greg Exp $";
00003 #endif
00004 /*
00005  *  rpmain.c - main for rpict batch rendering program
00006  */
00007 
00008 #include "copyright.h"
00009 
00010 #include  <time.h>
00011 #include  <signal.h>
00012 
00013 #include  "platform.h"
00014 #include  "rtprocess.h" /* getpid() */
00015 #include  "ray.h"
00016 #include  "source.h"
00017 #include  "ambient.h"
00018 #include  "random.h"
00019 #include  "paths.h"
00020 #include  "view.h"
00021 
00022                                    /* persistent processes define */
00023 #ifdef  F_SETLKW
00024 #define  PERSIST     1             /* normal persist */
00025 #define  PARALLEL    2             /* parallel persist */
00026 #define  PCHILD             3             /* child of normal persist */
00027 #endif
00028 
00029 char  *progname;                   /* argv[0] */
00030 char  *octname;                           /* octree name */
00031 char  *sigerr[NSIG];               /* signal error messages */
00032 char  *shm_boundary = NULL;        /* boundary of shared memory */
00033 char  *errfile = NULL;                    /* error output file */
00034 
00035 extern time_t  time();
00036 extern time_t  tstart;                    /* start time */
00037 
00038 extern int  ralrm;                 /* seconds between reports */
00039 
00040 extern VIEW  ourview;                     /* viewing parameters */
00041 
00042 extern int  hresolu;               /* horizontal resolution */
00043 extern int  vresolu;               /* vertical resolution */
00044 extern double  pixaspect;          /* pixel aspect ratio */
00045 
00046 extern int  psample;               /* pixel sample size */
00047 extern double  maxdiff;                   /* max. sample difference */
00048 extern double  dstrpix;                   /* square pixel distribution */
00049 
00050 extern double  mblur;                     /* motion blur parameter */
00051 
00052 extern double  dblur;                     /* depth-of-field blur parameter */
00053 
00054 static void onsig(int signo);
00055 static void sigdie(int  signo, char  *msg);
00056 static void printdefaults(void);
00057 
00058 
00059 int
00060 main(int  argc, char  *argv[])
00061 {
00062 #define        check(ol,al)        if (argv[i][ol] || \
00063                             badarg(argc-i-1,argv+i+1,al)) \
00064                             goto badopt
00065 #define        bool(olen,var)             switch (argv[i][olen]) { \
00066                             case '\0': var = !var; break; \
00067                             case 'y': case 'Y': case 't': case 'T': \
00068                             case '+': case '1': var = 1; break; \
00069                             case 'n': case 'N': case 'f': case 'F': \
00070                             case '-': case '0': var = 0; break; \
00071                             default: goto badopt; }
00072        char  *err;
00073        char  *recover = NULL;
00074        char  *outfile = NULL;
00075        char  *zfile = NULL;
00076        int  loadflags = ~IO_FILES;
00077        int  seqstart = 0;
00078        int  persist = 0;
00079        int  duped1;
00080        int  rval;
00081        int  i;
00082                                    /* record start time */
00083        tstart = time((time_t *)NULL);
00084                                    /* global program name */
00085        progname = argv[0] = fixargv0(argv[0]);
00086                                    /* option city */
00087        for (i = 1; i < argc; i++) {
00088                                           /* expand arguments */
00089               while ((rval = expandarg(&argc, &argv, i)) > 0)
00090                      ;
00091               if (rval < 0) {
00092                      sprintf(errmsg, "cannot expand '%s'", argv[i]);
00093                      error(SYSTEM, errmsg);
00094               }
00095               if (argv[i] == NULL || argv[i][0] != '-')
00096                      break;               /* break from options */
00097               if (!strcmp(argv[i], "-version")) {
00098                      puts(VersionID);
00099                      quit(0);
00100               }
00101               if (!strcmp(argv[i], "-defaults") ||
00102                             !strcmp(argv[i], "-help")) {
00103                      printdefaults();
00104                      quit(0);
00105               }
00106               rval = getrenderopt(argc-i, argv+i);
00107               if (rval >= 0) {
00108                      i += rval;
00109                      continue;
00110               }
00111               rval = getviewopt(&ourview, argc-i, argv+i);
00112               if (rval >= 0) {
00113                      i += rval;
00114                      continue;
00115               }
00116                                           /* rpict options */
00117               switch (argv[i][1]) {
00118               case 'v':                          /* view file */
00119                      if (argv[i][2] != 'f')
00120                             goto badopt;
00121                      check(3,"s");
00122                      rval = viewfile(argv[++i], &ourview, NULL);
00123                      if (rval < 0) {
00124                             sprintf(errmsg,
00125                             "cannot open view file \"%s\"",
00126                                           argv[i]);
00127                             error(SYSTEM, errmsg);
00128                      } else if (rval == 0) {
00129                             sprintf(errmsg,
00130                                    "bad view file \"%s\"",
00131                                           argv[i]);
00132                             error(USER, errmsg);
00133                      }
00134                      break;
00135               case 'p':                          /* pixel */
00136                      switch (argv[i][2]) {
00137                      case 's':                          /* sample */
00138                             check(3,"i");
00139                             psample = atoi(argv[++i]);
00140                             break;
00141                      case 't':                          /* threshold */
00142                             check(3,"f");
00143                             maxdiff = atof(argv[++i]);
00144                             break;
00145                      case 'j':                          /* jitter */
00146                             check(3,"f");
00147                             dstrpix = atof(argv[++i]);
00148                             break;
00149                      case 'a':                          /* aspect */
00150                             check(3,"f");
00151                             pixaspect = atof(argv[++i]);
00152                             break;
00153                      case 'm':                          /* motion */
00154                             check(3,"f");
00155                             mblur = atof(argv[++i]);
00156                             break;
00157                      case 'd':                          /* aperture */
00158                             check(3,"f");
00159                             dblur = atof(argv[++i]);
00160                             break;
00161                      default:
00162                             goto badopt;
00163                      }
00164                      break;
00165               case 'x':                          /* x resolution */
00166                      check(2,"i");
00167                      hresolu = atoi(argv[++i]);
00168                      break;
00169               case 'y':                          /* y resolution */
00170                      check(2,"i");
00171                      vresolu = atoi(argv[++i]);
00172                      break;
00173               case 'S':                          /* slave index */
00174                      check(2,"i");
00175                      seqstart = atoi(argv[++i]);
00176                      break;
00177               case 'o':                          /* output file */
00178                      check(2,"s");
00179                      outfile = argv[++i];
00180                      break;
00181               case 'z':                          /* z file */
00182                      check(2,"s");
00183                      zfile = argv[++i];
00184                      break;
00185               case 'r':                          /* recover file */
00186                      if (argv[i][2] == 'o') {           /* +output */
00187                             check(3,"s");
00188                             outfile = argv[i+1];
00189                      } else
00190                             check(2,"s");
00191                      recover = argv[++i];
00192                      break;
00193               case 't':                          /* timer */
00194                      check(2,"i");
00195                      ralrm = atoi(argv[++i]);
00196                      break;
00197 #ifdef  PERSIST
00198               case 'P':                          /* persist file */
00199                      if (argv[i][2] == 'P') {
00200                             check(3,"s");
00201                             persist = PARALLEL;
00202                      } else {
00203                             check(2,"s");
00204                             persist = PERSIST;
00205                      }
00206                      persistfile(argv[++i]);
00207                      break;
00208 #endif
00209               case 'w':                          /* warnings */
00210                      rval = erract[WARNING].pf != NULL;
00211                      bool(2,rval);
00212                      if (rval) erract[WARNING].pf = wputs;
00213                      else erract[WARNING].pf = NULL;
00214                      break;
00215               case 'e':                          /* error file */
00216                      check(2,"s");
00217                      errfile = argv[++i];
00218                      break;
00219               default:
00220                      goto badopt;
00221               }
00222        }
00223        err = setview(&ourview);    /* set viewing parameters */
00224        if (err != NULL)
00225               error(USER, err);
00226                                    /* initialize object types */
00227        initotypes();
00228                                    /* initialize urand */
00229        if (rand_samp) {
00230               srandom((long)time(0));
00231               initurand(0);
00232        } else {
00233               srandom(0L);
00234               initurand(2048);
00235        }
00236                                    /* set up signal handling */
00237        sigdie(SIGINT, "Interrupt");
00238 #ifdef SIGHUP
00239        sigdie(SIGHUP, "Hangup");
00240 #endif
00241        sigdie(SIGTERM, "Terminate");
00242 #ifdef SIGPIPE
00243        sigdie(SIGPIPE, "Broken pipe");
00244 #endif
00245 #ifdef SIGALRM
00246        sigdie(SIGALRM, "Alarm clock");
00247 #endif
00248 #ifdef SIGXCPU
00249        sigdie(SIGXCPU, "CPU limit exceeded");
00250        sigdie(SIGXFSZ, "File size exceeded");
00251 #endif
00252                                    /* open error file */
00253        if (errfile != NULL) {
00254               if (freopen(errfile, "a", stderr) == NULL)
00255                      quit(2);
00256               fprintf(stderr, "**************\n*** PID %5d: ",
00257                             getpid());
00258               printargs(argc, argv, stderr);
00259               putc('\n', stderr);
00260               fflush(stderr);
00261        }
00262 #ifdef NICE
00263        nice(NICE);                 /* lower priority */
00264 #endif
00265                                    /* get octree */
00266        if (i == argc)
00267               octname = NULL;
00268        else if (i == argc-1)
00269               octname = argv[i];
00270        else
00271               goto badopt;
00272        if (seqstart > 0 && octname == NULL)
00273               error(USER, "missing octree argument");
00274                                    /* set up output */
00275 #ifdef  PERSIST
00276        if (persist) {
00277               if (recover != NULL)
00278                      error(USER, "persist option used with recover file");
00279               if (seqstart <= 0)
00280                      error(USER, "persist option only for sequences");
00281               if (outfile == NULL)
00282               duped1 = dup(fileno(stdout));      /* don't lose our output */
00283               openheader();
00284        } else
00285 #endif
00286        if (outfile != NULL)
00287               openheader();
00288 #ifdef _WIN32
00289        SET_FILE_BINARY(stdout);
00290        if (octname == NULL)
00291               SET_FILE_BINARY(stdin);
00292 #endif
00293        readoct(octname, loadflags, &thescene, NULL);
00294        nsceneobjs = nobjects;
00295 
00296        if (loadflags & IO_INFO) {  /* print header */
00297               printargs(i, argv, stdout);
00298               printf("SOFTWARE= %s\n", VersionID);
00299        }
00300 
00301        marksources();                     /* find and mark sources */
00302 
00303        setambient();               /* initialize ambient calculation */
00304 
00305 #ifdef  PERSIST
00306        if (persist) {
00307               fflush(stdout);
00308               if (outfile == NULL) {             /* reconnect stdout */
00309                      dup2(duped1, fileno(stdout));
00310                      close(duped1);
00311               }
00312               if (persist == PARALLEL) {  /* multiprocessing */
00313                      preload_objs();             /* preload scene */
00314                      shm_boundary = (char *)malloc(16);
00315                      strcpy(shm_boundary, "SHM_BOUNDARY");
00316                      while ((rval=fork()) == 0) {       /* keep on forkin' */
00317                             pflock(1);
00318                             pfhold();
00319                             tstart = time((time_t *)NULL);
00320                             ambsync();           /* load new values */
00321                      }
00322                      if (rval < 0)
00323                             error(SYSTEM, "cannot fork child for persist function");
00324                      pfdetach();          /* parent will run then exit */
00325               }
00326        }
00327 runagain:
00328        if (persist) {
00329               if (outfile == NULL)               /* if out to stdout */
00330                      dupheader();                /* send header */
00331               else                               /* if out to file */
00332                      duped1 = dup(fileno(stdout));      /* hang onto pipe */
00333        }
00334 #endif
00335                                    /* batch render picture(s) */
00336        rpict(seqstart, outfile, zfile, recover);
00337                                    /* flush ambient file */
00338        ambsync();
00339 #ifdef  PERSIST
00340        if (persist == PERSIST) {   /* first run-through */
00341               if ((rval=fork()) == 0) {   /* child loops until killed */
00342                      pflock(1);
00343                      persist = PCHILD;
00344               } else {                    /* original process exits */
00345                      if (rval < 0)
00346                             error(SYSTEM, "cannot fork child for persist function");
00347                      pfdetach();          /* parent exits */
00348               }
00349        }
00350        if (persist == PCHILD) {    /* wait for a signal then go again */
00351               if (outfile != NULL)
00352                      close(duped1);              /* release output handle */
00353               pfhold();
00354               tstart = time((time_t *)NULL);     /* reinitialize */
00355               raynum = nrays = 0;
00356               goto runagain;
00357        }
00358 #endif
00359        quit(0);
00360 
00361 badopt:
00362        sprintf(errmsg, "command line error at '%s'", argv[i]);
00363        error(USER, errmsg);
00364        return 1; /* pro forma return */
00365 
00366 #undef check
00367 #undef bool
00368 }
00369 
00370 
00371 void
00372 wputs(                      /* warning output function */
00373        char   *s
00374 )
00375 {
00376        int  lasterrno = errno;
00377        eputs(s);
00378        errno = lasterrno;
00379 }
00380 
00381 
00382 void
00383 eputs(                      /* put string to stderr */
00384        register char  *s
00385 )
00386 {
00387        static int  midline = 0;
00388 
00389        if (!*s)
00390               return;
00391        if (!midline++) {
00392               fputs(progname, stderr);
00393               fputs(": ", stderr);
00394        }
00395        fputs(s, stderr);
00396        if (s[strlen(s)-1] == '\n') {
00397               fflush(stderr);
00398               midline = 0;
00399        }
00400 }
00401 
00402 
00403 static void
00404 onsig(                      /* fatal signal */
00405        int  signo
00406 )
00407 {
00408        static int  gotsig = 0;
00409 
00410        if (gotsig++)               /* two signals and we're gone! */
00411               _exit(signo);
00412 
00413 #ifdef SIGALRM /* XXX how critical is this? */
00414        alarm(15);                  /* allow 15 seconds to clean up */
00415        signal(SIGALRM, SIG_DFL);   /* make certain we do die */
00416 #endif
00417        eputs("signal - ");
00418        eputs(sigerr[signo]);
00419        eputs("\n");
00420        quit(3);
00421 }
00422 
00423 
00424 static void
00425 sigdie(                     /* set fatal signal */
00426        int  signo,
00427        char  *msg
00428 )
00429 {
00430        if (signal(signo, onsig) == SIG_IGN)
00431               signal(signo, SIG_IGN);
00432        sigerr[signo] = msg;
00433 }
00434 
00435 
00436 static void
00437 printdefaults(void)                /* print default values to stdout */
00438 {
00439        printf("-vt%c\t\t\t\t# view type %s\n", ourview.type,
00440                      ourview.type==VT_PER ? "perspective" :
00441                      ourview.type==VT_PAR ? "parallel" :
00442                      ourview.type==VT_HEM ? "hemispherical" :
00443                      ourview.type==VT_ANG ? "angular" :
00444                      ourview.type==VT_CYL ? "cylindrical" :
00445                      ourview.type==VT_PLS ? "planisphere" :
00446                      "unknown");
00447        printf("-vp %f %f %f\t# view point\n",
00448                      ourview.vp[0], ourview.vp[1], ourview.vp[2]);
00449        printf("-vd %f %f %f\t# view direction\n",
00450                      ourview.vdir[0], ourview.vdir[1], ourview.vdir[2]);
00451        printf("-vu %f %f %f\t# view up\n",
00452                      ourview.vup[0], ourview.vup[1], ourview.vup[2]);
00453        printf("-vh %f\t\t\t# view horizontal size\n", ourview.horiz);
00454        printf("-vv %f\t\t\t# view vertical size\n", ourview.vert);
00455        printf("-vo %f\t\t\t# view fore clipping plane\n", ourview.vfore);
00456        printf("-va %f\t\t\t# view aft clipping plane\n", ourview.vaft);
00457        printf("-vs %f\t\t\t# view shift\n", ourview.hoff);
00458        printf("-vl %f\t\t\t# view lift\n", ourview.voff);
00459        printf("-x  %-9d\t\t\t# x resolution\n", hresolu);
00460        printf("-y  %-9d\t\t\t# y resolution\n", vresolu);
00461        printf("-pa %f\t\t\t# pixel aspect ratio\n", pixaspect);
00462        printf("-pj %f\t\t\t# pixel jitter\n", dstrpix);
00463        printf("-pm %f\t\t\t# pixel motion\n", mblur);
00464        printf("-pd %f\t\t\t# pixel depth-of-field\n", dblur);
00465        printf("-ps %-9d\t\t\t# pixel sample\n", psample);
00466        printf("-pt %f\t\t\t# pixel threshold\n", maxdiff);
00467        printf("-t  %-9d\t\t\t# time between reports\n", ralrm);
00468        printf(erract[WARNING].pf != NULL ?
00469                      "-w+\t\t\t\t# warning messages on\n" :
00470                      "-w-\t\t\t\t# warning messages off\n");
00471        print_rdefaults();
00472 }