Back to index

radiance  4R0+20100331
ranimove.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char RCSid[] = "$Id: ranimove.c,v 3.13 2009/12/12 19:01:00 greg Exp $";
00003 #endif
00004 /*
00005  *  Radiance object animation program
00006  *
00007  *  Main program and control file handling.
00008  *
00009  *  See ranimove.h and the ranimove(1) man page for details.
00010  */
00011 
00012 #include "copyright.h"
00013 
00014 #include <time.h>
00015 #ifdef _WIN32
00016   #include <winsock.h> /* struct timeval. XXX find a replacement? */
00017 #else
00018   #include <sys/time.h>
00019 #endif
00020 #include <ctype.h>
00021 #include <string.h>
00022 
00023 #include "paths.h"
00024 #include "ranimove.h"
00025 
00026 int           NVARS = NV_INIT; /* total number of variables */
00027 
00028 VARIABLE      vv[] = VV_INIT;      /* variable-value pairs */
00029 
00030 extern int    nowarn;              /* don't report warnings? */
00031 int           silent = 0;   /* run silently? */
00032 
00033 int           quickstart = 0;      /* time initial frame as well? */
00034 
00035 int           nprocs = 1;   /* number of rendering processes */
00036 
00037 int           rtperfrm = 60;       /* seconds to spend per frame */
00038 
00039 double        ndthresh = 2.;       /* noticeable difference threshold */
00040 int           ndtset = 0;   /* user threshold -- stop when reached? */
00041 
00042 int           fbeg = 1;     /* starting frame */
00043 int           fend = 0;     /* ending frame */
00044 int           fcur;         /* current frame being rendered */
00045 
00046 char          lorendoptf[32];      /* low quality options file */
00047 RAYPARAMS     lorendparams; /* low quality rendering parameters */
00048 char          hirendoptf[32];      /* high quality options file */
00049 RAYPARAMS     hirendparams; /* high quality rendering parameters */
00050 RAYPARAMS     *curparams;   /* current parameter settings */
00051 int           twolevels;    /* low and high quality differ */
00052 
00053 double        mblur;        /* vflt(MBLUR) */
00054 double        rate;         /* vflt(RATE) */
00055 
00056 char          objtmpf[32];  /* object temporary file */
00057 
00058 struct ObjMove       *obj_move;    /* object movements */
00059 
00060 int           haveprio = 0; /* high-level saliency specified */
00061 
00062 int           gargc;        /* global argc for printargs */
00063 char          **gargv;      /* global argv for printargs */
00064 
00065 static void setdefaults(void);
00066 static void setmove(struct ObjMove *om, char     *ms);
00067 static void setrendparams(char            *optf, char          *qval);
00068 static void getradfile(char *rfargs);
00069 static void animate(void);
00070 static int countviews(void); /* XXX duplicated function */
00071 static char * getobjname(struct ObjMove   *om);
00072 static char * getxf(struct ObjMove *om, int      n);
00073 
00074 
00075 int
00076 main(
00077        int    argc,
00078        char   *argv[]
00079 )
00080 {
00081        int    explicate = 0;
00082        char   *cfname;
00083        int    i;
00084 
00085        progname = argv[0];                /* get arguments */
00086        gargc = argc;
00087        gargv = argv;
00088        for (i = 1; i < argc && argv[i][0] == '-'; i++)
00089               switch (argv[i][1]) {
00090               case 't':                   /* seconds per frame */
00091                      rtperfrm = atoi(argv[++i]);
00092                      break;
00093               case 'd':                   /* noticeable difference */
00094                      ndthresh = atof(argv[++i]);
00095                      ndtset = 1;
00096                      break;
00097               case 'e':                   /* print variables */
00098                      explicate++;
00099                      break;
00100               case 's':                   /* silent running */
00101                      silent++;
00102                      break;
00103               case 'q':                   /* start quickly */
00104                      quickstart++;
00105                      break;
00106               case 'w':                   /* turn off warnings */
00107                      nowarn++;
00108                      break;
00109               case 'f':                   /* frame range */
00110                      switch (sscanf(argv[++i], "%d,%d", &fbeg, &fend)) {
00111                      case 2:
00112                             if ((fbeg <= 0) | (fend < fbeg))
00113                                    goto userr;
00114                             break;
00115                      case 1:
00116                             if (fbeg <= 0)
00117                                    goto userr;
00118                             fend = 0;
00119                             break;
00120                      default:
00121                             goto userr;
00122                      }
00123                      break;
00124               case 'n':                   /* number of processes */
00125                      nprocs = atoi(argv[++i]);
00126                      break;
00127               default:
00128                      goto userr;
00129               }
00130        if (rtperfrm <= 0) {
00131               if (!ndtset)
00132                      error(USER, "specify -d jnd with -t 0");
00133               rtperfrm = 7*24*3600;
00134        }
00135        if (i != argc-1)
00136               goto userr;
00137        cfname = argv[i];
00138                                           /* load variables */
00139        loadvars(cfname);
00140                                           /* check variables */
00141        checkvalues();
00142                                           /* load RIF if any */
00143        if (vdef(RIF))
00144               getradfile(vval(RIF));
00145                                           /* set defaults */
00146        setdefaults();
00147                                           /* print variables */
00148        if (explicate)
00149               printvars(stdout);
00150                                           /* run animation */
00151        if (nprocs > 0)
00152               animate();
00153                                           /* all done */
00154        if (lorendoptf[0])
00155               unlink(lorendoptf);
00156        if (hirendoptf[0] && strcmp(hirendoptf, lorendoptf))
00157               unlink(hirendoptf);
00158        if (objtmpf[0])
00159               unlink(objtmpf);
00160        return(0);
00161 userr:
00162        fprintf(stderr,
00163 "Usage: %s [-n nprocs][-f beg,end][-t sec][-d jnd][-s][-w][-e] anim_file\n",
00164                      progname);
00165        quit(1);
00166        return 1; /* pro forma return */
00167 }
00168 
00169 
00170 void
00171 eputs(                      /* put string to stderr */
00172        register char  *s
00173 )
00174 {
00175        static int  midline = 0;
00176 
00177        if (!*s)
00178               return;
00179        if (!midline++) {
00180               fputs(progname, stderr);
00181               fputs(": ", stderr);
00182        }
00183        fputs(s, stderr);
00184        if (s[strlen(s)-1] == '\n') {
00185               fflush(stderr);
00186               midline = 0;
00187        }
00188 }
00189 
00190 
00191 void
00192 quit(ec)                    /* make sure exit is called */
00193 int    ec;
00194 {
00195        if (ray_pnprocs > 0) /* close children if any */
00196               ray_pclose(0);              
00197        exit(ec);
00198 }
00199 
00200 
00201 static void
00202 setdefaults(void)                  /* set default values */
00203 {
00204        int    nviews;
00205        int    decades;
00206        char   buf[256];
00207        int    i;
00208 
00209        if (!vdef(OCTREEF)) {
00210               sprintf(errmsg, "%s or %s must be defined",
00211                             vnam(OCTREEF), vnam(RIF));
00212               error(USER, errmsg);
00213        }
00214        if (!vdef(VIEWFILE)) {
00215               sprintf(errmsg, "%s must be defined", vnam(VIEWFILE));
00216               error(USER, errmsg);
00217        }
00218        nviews = countviews();
00219        if (!nviews)
00220               error(USER, "no views in view file");
00221        if (!vdef(END)) {
00222               if (nviews == 1) {
00223                      sprintf(errmsg, "%s must be defined for single view",
00224                                    vnam(END));
00225                      error(USER, errmsg);
00226               }
00227               sprintf(buf, "%d", nviews);
00228               vval(END) = savqstr(buf);
00229               vdef(END)++;
00230        }
00231        if (!fend)
00232               fend = vint(END);
00233        if (fbeg > fend)
00234               error(USER, "begin after end");
00235        if (!vdef(BASENAME)) {
00236               decades = (int)log10((double)vint(END)) + 1;
00237               if (decades < 3) decades = 3;
00238               sprintf(buf, "frame%%0%dd", decades);
00239               vval(BASENAME) = savqstr(buf);
00240               vdef(BASENAME)++;
00241        }
00242        if (!vdef(RATE)) {
00243               vval(RATE) = "8";
00244               vdef(RATE)++;
00245        }
00246        rate = vflt(RATE);
00247        if (!vdef(RESOLUTION)) {
00248               vval(RESOLUTION) = "640";
00249               vdef(RESOLUTION)++;
00250        }
00251        if (!vdef(MBLUR)) {
00252               vval(MBLUR) = "0";
00253               vdef(MBLUR)++;
00254        }
00255        mblur = vflt(MBLUR);
00256        if (mblur > 1.)
00257               mblur = 1.;
00258                             /* set up objects */
00259        if (vdef(MOVE)) {
00260               obj_move = (struct ObjMove *)malloc(
00261                             sizeof(struct ObjMove)*vdef(MOVE) );
00262               if (obj_move == NULL)
00263                      error(SYSTEM, "out of memory in setdefaults");
00264               for (i = 0; i < vdef(MOVE); i++)
00265                      setmove(&obj_move[i], nvalue(MOVE, i));
00266        }
00267                             /* set up high quality options */
00268        setrendparams(hirendoptf, vval(HIGHQ));
00269        ray_save(&hirendparams);
00270                             /* set up low quality options */
00271        setrendparams(lorendoptf, vval(LOWQ));
00272        ray_save(&lorendparams);
00273        curparams = &lorendparams;
00274        twolevels = memcmp(&lorendparams, &hirendparams, sizeof(RAYPARAMS));
00275 }
00276 
00277 
00278 static void
00279 setmove(                    /* assign a move object from spec. */
00280        struct ObjMove       *om,
00281        char   *ms
00282 )
00283 {
00284        char   parname[128];
00285        char   *cp;
00286        
00287        ms = nextword(parname, sizeof(parname), ms);
00288        if (!parname[0])
00289               goto badspec;
00290        for (cp = parname; *cp; cp++)
00291               if (isspace(*cp))
00292                      *cp = '_';
00293        for (om->parent = (om - obj_move); om->parent--; )
00294               if (!strcmp(parname, obj_move[om->parent].name))
00295                      break;
00296        if (om->parent < 0 &&
00297                      strcmp(parname, ".") && strcmp(parname, VOIDID)) {
00298               sprintf(errmsg, "undefined parent object '%s'", parname);
00299               error(USER, errmsg);
00300        }
00301        ms = nextword(om->name, sizeof(om->name), ms);
00302        if (!om->name[0])
00303               goto badspec;
00304        for (cp = om->name; *cp; cp++)
00305               if (isspace(*cp))
00306                      *cp = '_';
00307        ms = nextword(om->xf_file, sizeof(om->xf_file), ms);
00308        if (!strcmp(om->xf_file, "."))
00309               om->xf_file[0] = '\0';
00310        if (!om->xf_file[0]) {
00311               om->xfs[0] = '\0';
00312        } else if (om->xf_file[0] == '-') {
00313               strcpy(om->xfs, om->xf_file);
00314               om->xf_file[0] = '\0';
00315        }
00316        ms = nextword(om->spec, sizeof(om->spec), ms);
00317        if (om->spec[0]) {
00318               if (!strcmp(om->spec, ".") || !strcmp(om->spec, VOIDID))
00319                      om->spec[0] = '\0';
00320               ms = nextword(om->prio_file, sizeof(om->prio_file), ms);
00321        } else
00322               om->prio_file[0] = '\0';
00323        if (om->prio_file[0]) {
00324               if (isflt(om->prio_file)) {
00325                      om->prio = atof(om->prio_file);
00326                      om->prio_file[0] = '\0';
00327                      haveprio |= ((om->prio < 0.95) | (om->prio > 1.05));
00328               } else
00329                      haveprio = 1;
00330        } else
00331               om->prio = 1.;
00332        om->cfm = -1;
00333        return;
00334 badspec:
00335        error(USER, "bad object specification");
00336 }
00337 
00338 
00339 static void
00340 setrendparams(       /* set global rendering parameters */
00341        char          *optf,
00342        char          *qval
00343 )
00344 {
00345        char   *argv[1024];
00346        char   **av = argv;
00347        int    ac, i, rval;
00348 
00349        av[ac=0] = NULL;
00350                             /* load options from file, first */
00351        if (optf != NULL && *optf) {
00352               ac = wordfile(av, optf);
00353               if (ac < 0) {
00354                      sprintf(errmsg, "cannot load options file \"%s\"",
00355                                    optf);
00356                      error(SYSTEM, errmsg);
00357               }
00358        }
00359                             /* then from options string */
00360        if (qval != NULL && qval[0] == '-')
00361               ac += wordstring(av+ac, qval);
00362 
00363                             /* restore default parameters */
00364        ray_restore(NULL);
00365                             /* set what we have */
00366        for (i = 0; i < ac; i++) {
00367               while ((rval = expandarg(&ac, &av, i)) > 0)
00368                      ;
00369               if (rval < 0) {
00370                      sprintf(errmsg, "cannot expand '%s'", av[i]);
00371                      error(SYSTEM, errmsg);
00372               }
00373               if (!strcmp(av[i], "-w")) {
00374                      nowarn++;
00375                      continue;
00376               }
00377               rval = getrenderopt(ac-i, av+i);
00378               if (rval < 0) {
00379                      sprintf(errmsg, "bad render option at '%s'", av[i]);
00380                      error(USER, errmsg);
00381               }
00382               i += rval;
00383        }
00384 }
00385 
00386 
00387 static void
00388 getradfile(          /* run rad and get needed variables */
00389        char   *rfargs
00390 )
00391 {
00392        static short  mvar[] = {OCONV,OCTREEF,RESOLUTION,EXPOSURE,-1};
00393        char   combuf[256];
00394        register int  i;
00395        register char *cp;
00396        char   *pippt = NULL;
00397                                    /* create rad command */
00398        strcpy(lorendoptf, "ranim0.opt");
00399        sprintf(combuf,
00400        "rad -v 0 -s -e -w %s %s oconv=-f OPTFILE=%s | egrep '^[ \t]*(NOMATCH",
00401                      rfargs,
00402               (vdef(LOWQ) && vval(LOWQ)[0]!='-') ? vval(LOWQ) : "",
00403                      lorendoptf);
00404        cp = combuf;
00405        while (*cp) {
00406               if (*cp == '|') pippt = cp;
00407               cp++;
00408        }                           /* match unset variables */
00409        for (i = 0; mvar[i] >= 0; i++)
00410               if (!vdef(mvar[i])) {
00411                      *cp++ = '|';
00412                      strcpy(cp, vnam(mvar[i]));
00413                      while (*cp) cp++;
00414                      pippt = NULL;
00415               }
00416        if (pippt != NULL)
00417               strcpy(pippt, "> " NULL_DEVICE);   /* nothing to match */
00418        else {
00419               strcpy(cp, ")[ \t]*=' > ranimove.var");
00420               cp += 11;            /* point to file name */
00421        }
00422        system(combuf);                    /* ignore exit code */
00423        if (pippt == NULL) {        /* load variables and remove file */
00424               loadvars(cp);
00425               unlink(cp);
00426        }
00427        if (!vdef(HIGHQ) || vval(HIGHQ)[0]=='-') {
00428               strcpy(hirendoptf, lorendoptf);
00429               return;
00430        }
00431                                    /* get high quality options */
00432        strcpy(hirendoptf, "ranim1.opt");
00433        sprintf(combuf, "rad -v 0 -s -w %s %s OPTFILE=%s",
00434                      rfargs, vval(HIGHQ), hirendoptf);
00435        system(combuf);
00436 }
00437 
00438 
00439 static void
00440 animate(void)               /* run through animation */
00441 {
00442        int    rpass;
00443 
00444        if (fbeg > 1)                      /* synchronize transforms */
00445               getoctspec(fbeg-1);
00446 
00447        for (fcur = fbeg; fcur <= fend; fcur++) {
00448               if (!silent)
00449                      printf("Frame %d:\n", fcur);
00450                                           /* base rendering */
00451               init_frame();
00452                                           /* refinement */
00453               for (rpass = 0; refine_frame(rpass); rpass++)
00454                      ;
00455                                           /* final filter pass */
00456               filter_frame();
00457                                           /* output frame */
00458               send_frame();
00459        }
00460                                    /* free resources */
00461        free_frame();
00462        if (nprocs > 1)
00463               ray_pdone(1);
00464        else
00465               ray_done(1);
00466        getview(0);
00467        getexp(0);
00468 }
00469 
00470 
00471 extern VIEW *
00472 getview(                    /* get view number n */
00473        int    n
00474 )
00475 {
00476        static FILE   *viewfp = NULL;             /* view file pointer */
00477        static int    viewnum = 0;         /* current view number */
00478        static VIEW   curview = STDVIEW;   /* current view */
00479        char   linebuf[256];
00480 
00481        if (n == 0) {               /* signal to close file and clean up */
00482               if (viewfp != NULL) {
00483                      fclose(viewfp);
00484                      viewfp = NULL;
00485                      viewnum = 0;
00486                      curview = stdview;
00487               }
00488               return(NULL);
00489        }
00490        if (viewfp == NULL) {                     /* open file */
00491               if ((viewfp = fopen(vval(VIEWFILE), "r")) == NULL) {
00492                      perror(vval(VIEWFILE));
00493                      quit(1);
00494               }
00495        } else if (n > 0 && n < viewnum) { /* rewind file */
00496               if (viewnum == 1 && feof(viewfp))
00497                      return(&curview);           /* just one view */
00498               if (fseek(viewfp, 0L, 0) == EOF) {
00499                      perror(vval(VIEWFILE));
00500                      quit(1);
00501               }
00502               curview = stdview;
00503               viewnum = 0;
00504        }
00505        if (n < 0) {                       /* get next view */
00506               register int  c = getc(viewfp);
00507               if (c == EOF)
00508                      return(NULL);               /* that's it */
00509               ungetc(c, viewfp);
00510               n = viewnum + 1;
00511        }
00512        while (n > viewnum) {              /* scan to desired view */
00513               if (fgets(linebuf, sizeof(linebuf), viewfp) == NULL)
00514                      return(viewnum==1 ? &curview : (VIEW *)NULL);
00515               if (isview(linebuf) && sscanview(&curview, linebuf) > 0)
00516                      viewnum++;
00517        }
00518        return(&curview);           /* return it */
00519 }
00520 
00521 
00522 static int
00523 countviews(void)                   /* count views in view file */
00524 {
00525        int    n;
00526 
00527        if (getview(n=1) == NULL)
00528               return(0);
00529        while (getview(-1) != NULL)
00530               n++;
00531        return(n);
00532 }
00533 
00534 
00535 extern char *
00536 getexp(                     /* get exposure for nth frame */
00537        int    n
00538 )
00539 {
00540        extern char   *fskip();
00541        static char   expval[32];
00542        static FILE   *expfp = NULL;
00543        static int    curfrm = 0;
00544        register char *cp;
00545 
00546        if (n == 0) {                      /* signal to close file */
00547               if (expfp != NULL) {
00548                      fclose(expfp);
00549                      expfp = NULL;
00550               }
00551               return(NULL);
00552        }
00553        if (!vdef(EXPOSURE))               /* no setting (auto) */
00554               return(NULL);
00555        if (isflt(vval(EXPOSURE)))         /* always the same */
00556               return(vval(EXPOSURE));
00557        if (expfp == NULL) {               /* open exposure file */
00558               if ((expfp = fopen(vval(EXPOSURE), "r")) == NULL) {
00559                      sprintf(errmsg, "cannot open exposure file \"%s\"",
00560                                    vval(EXPOSURE));
00561                      error(SYSTEM, errmsg);
00562               }
00563               curfrm = 0;
00564        }
00565        if (curfrm > n) {                  /* rewind if necessary */
00566               rewind(expfp);
00567               curfrm = 0;
00568        }
00569        while (n > curfrm) {               /* read to line */
00570               if (fgets(expval, sizeof(expval), expfp) == NULL) {
00571                      sprintf(errmsg, "%s: too few exposures",
00572                                    vval(EXPOSURE));
00573                      error(USER, errmsg);
00574               }
00575               if (strlen(expval) == sizeof(expval)-1)
00576                      goto formerr;
00577               curfrm++;
00578        }
00579        cp = fskip(expval);                /* check format */
00580        if (cp != NULL)
00581               while (isspace(*cp))
00582                      *cp++ = '\0';
00583        if (cp == NULL || *cp)
00584               goto formerr;
00585        return(expval);                           /* return value */
00586 formerr:
00587        sprintf(errmsg, "%s: exposure format error on line %d",
00588                      vval(EXPOSURE), curfrm);
00589        error(USER, errmsg);
00590        return NULL; /* pro forma return */
00591 }
00592 
00593 
00594 extern double
00595 expspec_val(                /* get exposure value from spec. */
00596        char   *s
00597 )
00598 {
00599        double expval;
00600 
00601        if (s == NULL || !*s)
00602               return(1.0);
00603 
00604        expval = atof(s);
00605        if ((s[0] == '+') | (s[0] == '-'))
00606               return(pow(2.0, expval));
00607        return(expval);
00608 }
00609 
00610 
00611 extern char *
00612 getoctspec(                 /* get octree for the given frame */
00613        int    n
00614 )
00615 {
00616        static char   combuf[1024];
00617        int           cfm = 0;
00618        int    uses_inline;
00619        FILE   *fp;
00620        int    i;
00621                                    /* is octree static? */
00622        if (!vdef(MOVE))
00623               return(vval(OCTREEF));
00624                                    /* done already */
00625        if (n == cfm)
00626               return(combuf);
00627                                    /* else create object file */
00628        strcpy(objtmpf, "movinobj.rad");
00629        fp = fopen(objtmpf, "w");
00630        if (fp == NULL) {
00631               sprintf(errmsg, "cannot write to moving objects file '%s'",
00632                             objtmpf);
00633               error(SYSTEM, errmsg);
00634        }
00635        uses_inline = 0;
00636        for (i = 0; i < vdef(MOVE); i++) {
00637               int    inlc = (obj_move[i].spec[0] == '!');
00638               if (!obj_move[i].spec[0])
00639                      continue;
00640               if (inlc)
00641                      fprintf(fp, "%s %d \\\n\t| xform",
00642                                    obj_move[i].spec, n);
00643               else
00644                      fputs("!xform", fp);
00645               fprintf(fp, " -n %s", getobjname(&obj_move[i]));
00646               fputs(getxf(&obj_move[i], n), fp);
00647               if (!inlc)
00648                      fprintf(fp, " %s\n", obj_move[i].spec);
00649               else
00650                      fputc('\n', fp);
00651               uses_inline |= inlc;
00652        }
00653        if (fclose(fp) == EOF)
00654               error(SYSTEM, "error writing moving objects file");
00655        if (uses_inline)
00656               sprintf(combuf, "!oconv %s -f -i '%s' %s",
00657                             vdef(OCONV) ? vval(OCONV) : "",
00658                             vval(OCTREEF), objtmpf);
00659        else
00660               sprintf(combuf, "!xform -f %s | oconv -f -i '%s' -",
00661                             objtmpf, vval(OCTREEF));
00662        return(combuf);
00663 }
00664 
00665 
00666 static char *
00667 getobjname(                 /* get fully qualified object name */
00668        register struct ObjMove     *om
00669 )
00670 {
00671        static char   objName[512];
00672        register char *cp = objName;
00673        
00674        strcpy(cp, om->name);
00675        while (om->parent >= 0) {
00676               while (*cp) cp++;
00677               *cp++ = '@';
00678               om = &obj_move[om->parent];
00679               strcpy(cp, om->name);
00680        }
00681        return(objName);
00682 }
00683 
00684 
00685 static char *
00686 getxf(               /* get total transform for object */
00687        register struct ObjMove     *om,
00688        int    n
00689 )
00690 {
00691        static char   xfsbuf[4096];
00692        char          *xfp;
00693        int           framestep = 0;
00694        XF            oxf;
00695        FILE          *fp;
00696        char          abuf[512];
00697        char          *av[64];
00698        int           ac;
00699        int           i;
00700        register char *cp;
00701                                    /* get parent transform, first */
00702        if (om->parent >= 0)
00703               xfp = getxf(&obj_move[om->parent], n);
00704        else
00705               *(xfp = xfsbuf + sizeof(xfsbuf)-1) = '\0';
00706                                    /* get transform spec. & priority */
00707        if (om->cfm != n) {
00708               if (om->xf_file[0]) {
00709                      fp = fopen(om->xf_file, "r");
00710                      if (fp == NULL) {
00711                             sprintf(errmsg,
00712                                    "cannot open transform file '%s'",
00713                                           om->xf_file);
00714                             error(SYSTEM, errmsg);
00715                      }
00716                      for (i = 0; i < n; i++)
00717                             if (fgetline(om->xfs, sizeof(om->xfs), fp)
00718                                           == NULL) {
00719                                    sprintf(errmsg,
00720                                    "too few transforms in file '%s'",
00721                                                  om->xf_file);
00722                                    error(USER, errmsg);
00723                             }
00724                      fclose(fp);
00725               }
00726               strcpy(cp=abuf, om->xfs);
00727               ac = 0;
00728               for ( ; ; ) {
00729                      while (isspace(*cp))
00730                             *cp++ = '\0';
00731                      if (!*cp)
00732                             break;
00733                      av[ac++] = cp;
00734                      while (*++cp && !isspace(*cp))
00735                             ;
00736               }
00737               av[ac] = NULL;
00738               if (xf(&oxf, ac, av) != ac ||
00739                             fabs(oxf.sca) <= FTINY) {
00740                      sprintf(errmsg, "bad transform args: %s",
00741                                    om->xfs);
00742                      error(USER, errmsg);
00743               }
00744               copymat4(om->xfm, oxf.xfm);
00745               if (om->prio_file[0]) {
00746                      fp = fopen(om->prio_file, "r");
00747                      if (fp == NULL) {
00748                             sprintf(errmsg,
00749                                    "cannot open priority file '%s'",
00750                                           om->prio_file);
00751                             error(SYSTEM, errmsg);
00752                      }
00753                      for (i = 0; i < n; i++)
00754                             if (fgets(abuf, sizeof(abuf), fp)
00755                                           == NULL) {
00756                                    sprintf(errmsg,
00757                                    "too few priorities in file '%s'",
00758                                                  om->prio_file);
00759                                    error(USER, errmsg);
00760                             }
00761                      fclose(fp);
00762                      cp = fskip(abuf);
00763                      if (cp != NULL)
00764                             while (isspace(*cp))
00765                                    *cp++ = '\0';
00766                      if (cp == NULL || *cp) {
00767                             sprintf(errmsg,
00768                             "priority '%s' in file '%s' not a number",
00769                                           abuf, om->prio_file);
00770                             error(USER, errmsg);
00771                      }
00772                      om->prio = atof(abuf);
00773               }
00774               framestep = (n == om->cfm + 1);
00775               om->cfm = n;
00776        }
00777                                    /* prepend to parent transform */
00778        if (om->xfs[0]) {
00779               i = strlen(om->xfs);
00780               if (xfp - i <= xfsbuf)
00781                      error(INTERNAL, "transform too long in getxf");
00782               cp = om->xfs + i;
00783               while (i--)
00784                      *--xfp = *--cp;
00785               *--xfp = ' ';
00786        }
00787        if (framestep)
00788               copymat4(oxf.xfm, om->cxfm);
00789        if (om->parent >= 0) {
00790               multmat4(om->cxfm, om->xfm, obj_move[om->parent].cxfm);
00791               om->cprio = obj_move[om->parent].cprio * om->prio;
00792        } else {
00793               copymat4(om->cxfm, om->xfm);
00794               om->cprio = om->prio;
00795        }
00796                                    /* XXX bxfm relies on call order */
00797        if (framestep) {
00798               if (invmat4(om->bxfm, om->cxfm))
00799                      multmat4(om->bxfm, om->bxfm, oxf.xfm);
00800               else
00801                      setident4(om->bxfm);
00802        }
00803                                    /* all done */
00804        return(xfp);
00805 }
00806 
00807 
00808 extern int
00809 getmove(                           /* find matching move object */
00810        OBJECT obj
00811 )
00812 {
00813        static int    lasti;
00814        static OBJECT lasto = OVOID;
00815        char   *onm, *objnm;
00816        int    len, len2;
00817        register int  i;
00818 
00819        if (obj == OVOID)
00820               return(-1);
00821        if (obj == lasto)
00822               return(lasti);
00823                                    /* look for matching object */
00824        onm = objptr(obj)->oname;
00825        for (i = vdef(MOVE); i--; ) {
00826               objnm = obj_move[i].name;
00827               len = strlen(objnm);
00828               if (!strncmp(onm, objnm, len)) {
00829                      if ((obj_move[i].parent < 0) & (onm[len] == '.'))
00830                             break;
00831                      objnm = getobjname(&obj_move[i]) + len;
00832                      len2 = strlen(objnm);
00833                      if (!strncmp(onm+len, objnm, len2) && onm[len+len2] == '.')
00834                             break;
00835               }
00836        }
00837        lasto = obj;                /* cache what we found */
00838        return(lasti = i);
00839 }
00840 
00841 
00842 extern double
00843 obj_prio(                   /* return priority for object */
00844        OBJECT obj
00845 )
00846 {
00847        int    moi;
00848        
00849        if (obj == OVOID || (moi = getmove(obj)) < 0)
00850               return(1.0);
00851        return(obj_move[moi].cprio);
00852 }
00853 
00854 
00855 extern double
00856 getTime(void)               /* get current time (CPU or real) */
00857 {
00858        struct timeval       time_now;
00859                                    /* return CPU time if one process */
00860        if (nprocs == 1)
00861               return((double)clock()*(1.0/(double)CLOCKS_PER_SEC));
00862                                    /* otherwise, return wall time */
00863        gettimeofday(&time_now, NULL);
00864        return((double)time_now.tv_sec + 1e-6*(double)time_now.tv_usec);
00865 }