ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/ranimove.c
Revision: 3.12
Committed: Tue Sep 28 17:54:19 2004 UTC (19 years, 6 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R7P2, rad3R7P1, rad3R6, rad3R6P1, rad3R8, rad3R9
Changes since 3.11: +1 -1 lines
Log Message:
Fixed messed-up RCCS Id at top of file

File Contents

# User Rev Content
1 greg 3.1 #ifndef lint
2 greg 3.12 static const char RCSid[] = "$Id$";
3 greg 3.1 #endif
4     /*
5     * Radiance object animation program
6     *
7     * Main program and control file handling.
8     *
9     * See ranimove.h and the ranimove(1) man page for details.
10     */
11    
12 greg 3.2 #include "copyright.h"
13 greg 3.1
14 greg 3.3 #include <time.h>
15 schorsch 3.9 #ifdef _WIN32
16     #include <winsock.h> /* struct timeval. XXX find a replacement? */
17     #else
18 schorsch 3.4 #include <sys/time.h>
19     #endif
20 greg 3.1 #include <ctype.h>
21 schorsch 3.5 #include <string.h>
22    
23     #include "paths.h"
24     #include "ranimove.h"
25 greg 3.1
26     int NVARS = NV_INIT; /* total number of variables */
27    
28     VARIABLE vv[] = VV_INIT; /* variable-value pairs */
29    
30     extern int nowarn; /* don't report warnings? */
31     int silent = 0; /* run silently? */
32    
33     int quickstart = 0; /* time initial frame as well? */
34    
35     int nprocs = 1; /* number of rendering processes */
36    
37     int rtperfrm = 60; /* seconds to spend per frame */
38    
39     double ndthresh = 2.; /* noticeable difference threshold */
40     int ndtset = 0; /* user threshold -- stop when reached? */
41    
42     int fbeg = 1; /* starting frame */
43     int fend = 0; /* ending frame */
44     int fcur; /* current frame being rendered */
45    
46     char lorendoptf[32]; /* low quality options file */
47     RAYPARAMS lorendparams; /* low quality rendering parameters */
48     char hirendoptf[32]; /* high quality options file */
49     RAYPARAMS hirendparams; /* high quality rendering parameters */
50     RAYPARAMS *curparams; /* current parameter settings */
51     int twolevels; /* low and high quality differ */
52    
53     double mblur; /* vflt(MBLUR) */
54     double rate; /* vflt(RATE) */
55    
56     char objtmpf[32]; /* object temporary file */
57    
58     struct ObjMove *obj_move; /* object movements */
59    
60     int haveprio = 0; /* high-level saliency specified */
61    
62     int gargc; /* global argc for printargs */
63     char **gargv; /* global argv for printargs */
64    
65 schorsch 3.10 static void setdefaults(void);
66     static void setmove(struct ObjMove *om, char *ms);
67     static void setrendparams(char *optf, char *qval);
68     static void getradfile(char *rfargs);
69     static void animate(void);
70     static int countviews(void); /* XXX duplicated function */
71     static char * getobjname(struct ObjMove *om);
72     static char * getxf(struct ObjMove *om, int n);
73    
74 greg 3.1
75     int
76 schorsch 3.10 main(
77     int argc,
78     char *argv[]
79     )
80 greg 3.1 {
81     int explicate = 0;
82     char *cfname;
83     int i;
84    
85     progname = argv[0]; /* get arguments */
86     gargc = argc;
87     gargv = argv;
88     for (i = 1; i < argc && argv[i][0] == '-'; i++)
89     switch (argv[i][1]) {
90     case 't': /* seconds per frame */
91     rtperfrm = atoi(argv[++i]);
92     break;
93     case 'd': /* noticeable difference */
94     ndthresh = atof(argv[++i]);
95     ndtset = 1;
96     break;
97     case 'e': /* print variables */
98     explicate++;
99     break;
100     case 's': /* silent running */
101     silent++;
102     break;
103     case 'q': /* start quickly */
104     quickstart++;
105     break;
106     case 'w': /* turn off warnings */
107     nowarn++;
108     break;
109     case 'f': /* frame range */
110     switch (sscanf(argv[++i], "%d,%d", &fbeg, &fend)) {
111     case 2:
112 schorsch 3.7 if ((fbeg <= 0) | (fend < fbeg))
113 greg 3.1 goto userr;
114     break;
115     case 1:
116     if (fbeg <= 0)
117     goto userr;
118     fend = 0;
119     break;
120     default:
121     goto userr;
122     }
123     break;
124     case 'n': /* number of processes */
125     nprocs = atoi(argv[++i]);
126     break;
127     default:
128     goto userr;
129     }
130     if (rtperfrm <= 0) {
131     if (!ndtset)
132     error(USER, "specify -d jnd with -t 0");
133     rtperfrm = 7*24*3600;
134     }
135     if (i != argc-1)
136     goto userr;
137     cfname = argv[i];
138     /* load variables */
139     loadvars(cfname);
140     /* check variables */
141     checkvalues();
142     /* load RIF if any */
143     if (vdef(RIF))
144     getradfile(vval(RIF));
145     /* set defaults */
146     setdefaults();
147     /* print variables */
148     if (explicate)
149     printvars(stdout);
150     /* run animation */
151     if (nprocs > 0)
152     animate();
153     /* all done */
154     if (lorendoptf[0])
155     unlink(lorendoptf);
156 greg 3.8 if (hirendoptf[0] && strcmp(hirendoptf, lorendoptf))
157 greg 3.1 unlink(hirendoptf);
158     if (objtmpf[0])
159     unlink(objtmpf);
160     return(0);
161     userr:
162     fprintf(stderr,
163     "Usage: %s [-n nprocs][-f beg,end][-t sec][-d jnd][-s][-w][-e] anim_file\n",
164     progname);
165     quit(1);
166 schorsch 3.10 return 1; /* pro forma return */
167 greg 3.1 }
168    
169    
170     void
171 schorsch 3.11 eputs( /* put string to stderr */
172     register char *s
173     )
174 greg 3.1 {
175     static int midline = 0;
176    
177     if (!*s)
178     return;
179     if (!midline++) {
180     fputs(progname, stderr);
181     fputs(": ", stderr);
182     }
183     fputs(s, stderr);
184     if (s[strlen(s)-1] == '\n') {
185     fflush(stderr);
186     midline = 0;
187     }
188     }
189    
190    
191 schorsch 3.10 static void
192     setdefaults(void) /* set default values */
193 greg 3.1 {
194     int nviews;
195     int decades;
196     char buf[256];
197     int i;
198    
199     if (!vdef(OCTREEF)) {
200     sprintf(errmsg, "%s or %s must be defined",
201     vnam(OCTREEF), vnam(RIF));
202     error(USER, errmsg);
203     }
204     if (!vdef(VIEWFILE)) {
205     sprintf(errmsg, "%s must be defined", vnam(VIEWFILE));
206     error(USER, errmsg);
207     }
208     nviews = countviews();
209     if (!nviews)
210     error(USER, "no views in view file");
211     if (!vdef(END)) {
212     if (nviews == 1) {
213     sprintf(errmsg, "%s must be defined for single view",
214     vnam(END));
215     error(USER, errmsg);
216     }
217     sprintf(buf, "%d", nviews);
218     vval(END) = savqstr(buf);
219     vdef(END)++;
220     }
221     if (!fend)
222     fend = vint(END);
223     if (fbeg > fend)
224     error(USER, "begin after end");
225     if (!vdef(BASENAME)) {
226     decades = (int)log10((double)vint(END)) + 1;
227     if (decades < 3) decades = 3;
228     sprintf(buf, "frame%%0%dd", decades);
229     vval(BASENAME) = savqstr(buf);
230     vdef(BASENAME)++;
231     }
232     if (!vdef(RATE)) {
233     vval(RATE) = "8";
234     vdef(RATE)++;
235     }
236     rate = vflt(RATE);
237     if (!vdef(RESOLUTION)) {
238     vval(RESOLUTION) = "640";
239     vdef(RESOLUTION)++;
240     }
241     if (!vdef(MBLUR)) {
242     vval(MBLUR) = "0";
243     vdef(MBLUR)++;
244     }
245     mblur = vflt(MBLUR);
246     if (mblur > 1.)
247     mblur = 1.;
248     /* set up objects */
249     if (vdef(MOVE)) {
250     obj_move = (struct ObjMove *)malloc(
251     sizeof(struct ObjMove)*vdef(MOVE) );
252     if (obj_move == NULL)
253     error(SYSTEM, "out of memory in setdefaults");
254     for (i = 0; i < vdef(MOVE); i++)
255     setmove(&obj_move[i], nvalue(MOVE, i));
256     }
257     /* set up high quality options */
258     setrendparams(hirendoptf, vval(HIGHQ));
259     ray_save(&hirendparams);
260     /* set up low quality options */
261     setrendparams(lorendoptf, vval(LOWQ));
262     ray_save(&lorendparams);
263     curparams = &lorendparams;
264 schorsch 3.5 twolevels = memcmp(&lorendparams, &hirendparams, sizeof(RAYPARAMS));
265 greg 3.1 }
266    
267    
268 schorsch 3.10 static void
269     setmove( /* assign a move object from spec. */
270     struct ObjMove *om,
271     char *ms
272     )
273 greg 3.1 {
274     char parname[128];
275     char *cp;
276    
277     ms = nextword(parname, sizeof(parname), ms);
278     if (!parname[0])
279     goto badspec;
280     for (cp = parname; *cp; cp++)
281     if (isspace(*cp))
282     *cp = '_';
283     for (om->parent = (om - obj_move); om->parent--; )
284     if (!strcmp(parname, obj_move[om->parent].name))
285     break;
286     if (om->parent < 0 &&
287     strcmp(parname, ".") && strcmp(parname, VOIDID)) {
288     sprintf(errmsg, "undefined parent object '%s'", parname);
289     error(USER, errmsg);
290     }
291     ms = nextword(om->name, sizeof(om->name), ms);
292     if (!om->name[0])
293     goto badspec;
294     for (cp = om->name; *cp; cp++)
295     if (isspace(*cp))
296     *cp = '_';
297     ms = nextword(om->xf_file, sizeof(om->xf_file), ms);
298     if (!strcmp(om->xf_file, "."))
299     om->xf_file[0] = '\0';
300     if (!om->xf_file[0]) {
301     om->xfs[0] = '\0';
302     } else if (om->xf_file[0] == '-') {
303     strcpy(om->xfs, om->xf_file);
304     om->xf_file[0] = '\0';
305     }
306     ms = nextword(om->spec, sizeof(om->spec), ms);
307     if (om->spec[0]) {
308     if (!strcmp(om->spec, ".") || !strcmp(om->spec, VOIDID))
309     om->spec[0] = '\0';
310     ms = nextword(om->prio_file, sizeof(om->prio_file), ms);
311     } else
312     om->prio_file[0] = '\0';
313     if (om->prio_file[0]) {
314     if (isflt(om->prio_file)) {
315     om->prio = atof(om->prio_file);
316     om->prio_file[0] = '\0';
317 schorsch 3.7 haveprio |= ((om->prio < 0.95) | (om->prio > 1.05));
318 greg 3.1 } else
319     haveprio = 1;
320     } else
321     om->prio = 1.;
322     om->cfm = -1;
323     return;
324     badspec:
325     error(USER, "bad object specification");
326     }
327    
328    
329 schorsch 3.10 static void
330     setrendparams( /* set global rendering parameters */
331     char *optf,
332     char *qval
333     )
334 greg 3.1 {
335     char *argv[1024];
336     char **av = argv;
337     int ac, i, rval;
338    
339     av[ac=0] = NULL;
340     /* load options from file, first */
341     if (optf != NULL && *optf) {
342     ac = wordfile(av, optf);
343     if (ac < 0) {
344     sprintf(errmsg, "cannot load options file \"%s\"",
345     optf);
346     error(SYSTEM, errmsg);
347     }
348     }
349     /* then from options string */
350     if (qval != NULL && qval[0] == '-')
351     ac += wordstring(av+ac, qval);
352    
353 greg 3.8 /* restore default parameters */
354     ray_restore(NULL);
355 greg 3.1 /* set what we have */
356     for (i = 0; i < ac; i++) {
357     while ((rval = expandarg(&ac, &av, i)) > 0)
358     ;
359     if (rval < 0) {
360     sprintf(errmsg, "cannot expand '%s'", av[i]);
361     error(SYSTEM, errmsg);
362     }
363     if (!strcmp(av[i], "-w")) {
364     nowarn++;
365     continue;
366     }
367     rval = getrenderopt(ac-i, av+i);
368 greg 3.8 if (rval < 0) {
369     sprintf(errmsg, "bad render option at '%s'", av[i]);
370     error(USER, errmsg);
371 greg 3.1 }
372 greg 3.8 i += rval;
373 greg 3.1 }
374     }
375    
376    
377 schorsch 3.10 static void
378     getradfile( /* run rad and get needed variables */
379     char *rfargs
380     )
381 greg 3.1 {
382     static short mvar[] = {OCONV,OCTREEF,RESOLUTION,EXPOSURE,-1};
383     char combuf[256];
384     register int i;
385     register char *cp;
386 schorsch 3.10 char *pippt = NULL;
387 greg 3.1 /* create rad command */
388     strcpy(lorendoptf, "ranim0.opt");
389     sprintf(combuf,
390     "rad -v 0 -s -e -w %s %s oconv=-f OPTFILE=%s | egrep '^[ \t]*(NOMATCH",
391     rfargs,
392     (vdef(LOWQ) && vval(LOWQ)[0]!='-') ? vval(LOWQ) : "",
393     lorendoptf);
394     cp = combuf;
395     while (*cp) {
396     if (*cp == '|') pippt = cp;
397     cp++;
398     } /* match unset variables */
399     for (i = 0; mvar[i] >= 0; i++)
400     if (!vdef(mvar[i])) {
401     *cp++ = '|';
402     strcpy(cp, vnam(mvar[i]));
403     while (*cp) cp++;
404     pippt = NULL;
405     }
406     if (pippt != NULL)
407 schorsch 3.5 strcpy(pippt, "> " NULL_DEVICE); /* nothing to match */
408 greg 3.1 else {
409     strcpy(cp, ")[ \t]*=' > ranimove.var");
410     cp += 11; /* point to file name */
411     }
412     system(combuf); /* ignore exit code */
413     if (pippt == NULL) { /* load variables and remove file */
414     loadvars(cp);
415     unlink(cp);
416     }
417     if (!vdef(HIGHQ) || vval(HIGHQ)[0]=='-') {
418     strcpy(hirendoptf, lorendoptf);
419     return;
420     }
421     /* get high quality options */
422     strcpy(hirendoptf, "ranim1.opt");
423     sprintf(combuf, "rad -v 0 -s -w %s %s OPTFILE=%s",
424     rfargs, vval(HIGHQ), hirendoptf);
425     system(combuf);
426     }
427    
428    
429 schorsch 3.10 static void
430     animate(void) /* run through animation */
431 greg 3.1 {
432     int rpass;
433    
434     if (fbeg > 1) /* synchronize transforms */
435     getoctspec(fbeg-1);
436    
437     for (fcur = fbeg; fcur <= fend; fcur++) {
438     if (!silent)
439     printf("Frame %d:\n", fcur);
440     /* base rendering */
441     init_frame();
442     /* refinement */
443     for (rpass = 0; refine_frame(rpass); rpass++)
444     ;
445     /* final filter pass */
446     filter_frame();
447     /* output frame */
448     send_frame();
449     }
450     /* free resources */
451     free_frame();
452     if (nprocs > 1)
453     ray_pdone(1);
454     else
455     ray_done(1);
456     getview(0);
457     getexp(0);
458     }
459    
460    
461 schorsch 3.10 extern VIEW *
462     getview( /* get view number n */
463     int n
464     )
465 greg 3.1 {
466     static FILE *viewfp = NULL; /* view file pointer */
467     static int viewnum = 0; /* current view number */
468     static VIEW curview = STDVIEW; /* current view */
469     char linebuf[256];
470    
471     if (n == 0) { /* signal to close file and clean up */
472     if (viewfp != NULL) {
473     fclose(viewfp);
474     viewfp = NULL;
475     viewnum = 0;
476 schorsch 3.6 curview = stdview;
477 greg 3.1 }
478     return(NULL);
479     }
480     if (viewfp == NULL) { /* open file */
481     if ((viewfp = fopen(vval(VIEWFILE), "r")) == NULL) {
482     perror(vval(VIEWFILE));
483     quit(1);
484     }
485     } else if (n > 0 && n < viewnum) { /* rewind file */
486     if (viewnum == 1 && feof(viewfp))
487     return(&curview); /* just one view */
488     if (fseek(viewfp, 0L, 0) == EOF) {
489     perror(vval(VIEWFILE));
490     quit(1);
491     }
492 schorsch 3.6 curview = stdview;
493 greg 3.1 viewnum = 0;
494     }
495     if (n < 0) { /* get next view */
496     register int c = getc(viewfp);
497     if (c == EOF)
498     return(NULL); /* that's it */
499     ungetc(c, viewfp);
500     n = viewnum + 1;
501     }
502     while (n > viewnum) { /* scan to desired view */
503     if (fgets(linebuf, sizeof(linebuf), viewfp) == NULL)
504     return(viewnum==1 ? &curview : (VIEW *)NULL);
505     if (isview(linebuf) && sscanview(&curview, linebuf) > 0)
506     viewnum++;
507     }
508     return(&curview); /* return it */
509     }
510    
511    
512 schorsch 3.10 static int
513     countviews(void) /* count views in view file */
514 greg 3.1 {
515     int n;
516    
517     if (getview(n=1) == NULL)
518     return(0);
519     while (getview(-1) != NULL)
520     n++;
521     return(n);
522     }
523    
524    
525 schorsch 3.10 extern char *
526     getexp( /* get exposure for nth frame */
527     int n
528     )
529 greg 3.1 {
530     extern char *fskip();
531     static char expval[32];
532     static FILE *expfp = NULL;
533     static int curfrm = 0;
534     register char *cp;
535    
536     if (n == 0) { /* signal to close file */
537     if (expfp != NULL) {
538     fclose(expfp);
539     expfp = NULL;
540     }
541     return(NULL);
542     }
543     if (!vdef(EXPOSURE)) /* no setting (auto) */
544     return(NULL);
545     if (isflt(vval(EXPOSURE))) /* always the same */
546     return(vval(EXPOSURE));
547     if (expfp == NULL) { /* open exposure file */
548     if ((expfp = fopen(vval(EXPOSURE), "r")) == NULL) {
549     sprintf(errmsg, "cannot open exposure file \"%s\"",
550     vval(EXPOSURE));
551     error(SYSTEM, errmsg);
552     }
553     curfrm = 0;
554     }
555     if (curfrm > n) { /* rewind if necessary */
556     rewind(expfp);
557     curfrm = 0;
558     }
559     while (n > curfrm) { /* read to line */
560     if (fgets(expval, sizeof(expval), expfp) == NULL) {
561     sprintf(errmsg, "%s: too few exposures",
562     vval(EXPOSURE));
563     error(USER, errmsg);
564     }
565     if (strlen(expval) == sizeof(expval)-1)
566     goto formerr;
567     curfrm++;
568     }
569     cp = fskip(expval); /* check format */
570     if (cp != NULL)
571     while (isspace(*cp))
572     *cp++ = '\0';
573     if (cp == NULL || *cp)
574     goto formerr;
575     return(expval); /* return value */
576     formerr:
577     sprintf(errmsg, "%s: exposure format error on line %d",
578     vval(EXPOSURE), curfrm);
579     error(USER, errmsg);
580 schorsch 3.10 return NULL; /* pro forma return */
581 greg 3.1 }
582    
583    
584 schorsch 3.10 extern double
585     expspec_val( /* get exposure value from spec. */
586     char *s
587     )
588 greg 3.1 {
589     double expval;
590    
591     if (s == NULL || !*s)
592     return(1.0);
593    
594     expval = atof(s);
595 schorsch 3.7 if ((s[0] == '+') | (s[0] == '-'))
596 greg 3.1 return(pow(2.0, expval));
597     return(expval);
598     }
599    
600    
601 schorsch 3.10 extern char *
602     getoctspec( /* get octree for the given frame */
603     int n
604     )
605 greg 3.1 {
606     static char combuf[1024];
607     int cfm = 0;
608     int uses_inline;
609     FILE *fp;
610     int i;
611     /* is octree static? */
612     if (!vdef(MOVE))
613     return(vval(OCTREEF));
614     /* done already */
615     if (n == cfm)
616     return(combuf);
617     /* else create object file */
618     strcpy(objtmpf, "movinobj.rad");
619     fp = fopen(objtmpf, "w");
620     if (fp == NULL) {
621     sprintf(errmsg, "cannot write to moving objects file '%s'",
622     objtmpf);
623     error(SYSTEM, errmsg);
624     }
625     uses_inline = 0;
626     for (i = 0; i < vdef(MOVE); i++) {
627     int inlc = (obj_move[i].spec[0] == '!');
628     if (!obj_move[i].spec[0])
629     continue;
630     if (inlc)
631     fprintf(fp, "%s %d \\\n\t| xform",
632     obj_move[i].spec, n);
633     else
634     fputs("!xform", fp);
635     fprintf(fp, " -n %s", getobjname(&obj_move[i]));
636     fputs(getxf(&obj_move[i], n), fp);
637     if (!inlc)
638     fprintf(fp, " %s\n", obj_move[i].spec);
639     else
640     fputc('\n', fp);
641     uses_inline |= inlc;
642     }
643     if (fclose(fp) == EOF)
644     error(SYSTEM, "error writing moving objects file");
645     if (uses_inline)
646     sprintf(combuf, "!oconv %s -f -i '%s' %s",
647     vdef(OCONV) ? vval(OCONV) : "",
648     vval(OCTREEF), objtmpf);
649     else
650     sprintf(combuf, "!xform -f %s | oconv -f -i '%s' -",
651     objtmpf, vval(OCTREEF));
652     return(combuf);
653     }
654    
655    
656 schorsch 3.10 static char *
657     getobjname( /* get fully qualified object name */
658     register struct ObjMove *om
659     )
660 greg 3.1 {
661     static char objName[512];
662     register char *cp = objName;
663    
664     strcpy(cp, om->name);
665     while (om->parent >= 0) {
666     while (*cp) cp++;
667     *cp++ = '@';
668     om = &obj_move[om->parent];
669     strcpy(cp, om->name);
670     }
671     return(objName);
672     }
673    
674    
675 schorsch 3.10 static char *
676     getxf( /* get total transform for object */
677     register struct ObjMove *om,
678     int n
679     )
680 greg 3.1 {
681     static char xfsbuf[4096];
682     char *xfp;
683     int framestep = 0;
684     XF oxf;
685     FILE *fp;
686     char abuf[512];
687     char *av[64];
688     int ac;
689     int i;
690     register char *cp;
691     /* get parent transform, first */
692     if (om->parent >= 0)
693     xfp = getxf(&obj_move[om->parent], n);
694     else
695     *(xfp = xfsbuf + sizeof(xfsbuf)-1) = '\0';
696     /* get transform spec. & priority */
697     if (om->cfm != n) {
698     if (om->xf_file[0]) {
699     fp = fopen(om->xf_file, "r");
700     if (fp == NULL) {
701     sprintf(errmsg,
702     "cannot open transform file '%s'",
703     om->xf_file);
704     error(SYSTEM, errmsg);
705     }
706     for (i = 0; i < n; i++)
707     if (fgetline(om->xfs, sizeof(om->xfs), fp)
708     == NULL) {
709     sprintf(errmsg,
710     "too few transforms in file '%s'",
711     om->xf_file);
712     error(USER, errmsg);
713     }
714     fclose(fp);
715     }
716     strcpy(cp=abuf, om->xfs);
717     ac = 0;
718     for ( ; ; ) {
719     while (isspace(*cp))
720     *cp++ = '\0';
721     if (!*cp)
722     break;
723     av[ac++] = cp;
724     while (*++cp && !isspace(*cp))
725     ;
726     }
727     av[ac] = NULL;
728     if (xf(&oxf, ac, av) != ac ||
729     fabs(oxf.sca) <= FTINY) {
730     sprintf(errmsg, "bad transform args: %s",
731     om->xfs);
732     error(USER, errmsg);
733     }
734     copymat4(om->xfm, oxf.xfm);
735     if (om->prio_file[0]) {
736     fp = fopen(om->prio_file, "r");
737     if (fp == NULL) {
738     sprintf(errmsg,
739     "cannot open priority file '%s'",
740     om->prio_file);
741     error(SYSTEM, errmsg);
742     }
743     for (i = 0; i < n; i++)
744     if (fgets(abuf, sizeof(abuf), fp)
745     == NULL) {
746     sprintf(errmsg,
747     "too few priorities in file '%s'",
748     om->prio_file);
749     error(USER, errmsg);
750     }
751     fclose(fp);
752     cp = fskip(abuf);
753     if (cp != NULL)
754     while (isspace(*cp))
755     *cp++ = '\0';
756     if (cp == NULL || *cp) {
757     sprintf(errmsg,
758     "priority '%s' in file '%s' not a number",
759     abuf, om->prio_file);
760     error(USER, errmsg);
761     }
762     om->prio = atof(abuf);
763     }
764     framestep = (n == om->cfm + 1);
765     om->cfm = n;
766     }
767     /* prepend to parent transform */
768     if (om->xfs[0]) {
769     i = strlen(om->xfs);
770     if (xfp - i <= xfsbuf)
771     error(INTERNAL, "transform too long in getxf");
772     cp = om->xfs + i;
773     while (i--)
774     *--xfp = *--cp;
775     *--xfp = ' ';
776     }
777     if (framestep)
778     copymat4(oxf.xfm, om->cxfm);
779     if (om->parent >= 0) {
780     multmat4(om->cxfm, om->xfm, obj_move[om->parent].cxfm);
781     om->cprio = obj_move[om->parent].cprio * om->prio;
782     } else {
783     copymat4(om->cxfm, om->xfm);
784     om->cprio = om->prio;
785     }
786     /* XXX bxfm relies on call order */
787 schorsch 3.6 if (framestep) {
788 greg 3.1 if (invmat4(om->bxfm, om->cxfm))
789     multmat4(om->bxfm, om->bxfm, oxf.xfm);
790     else
791     setident4(om->bxfm);
792 schorsch 3.6 }
793 greg 3.1 /* all done */
794     return(xfp);
795     }
796    
797    
798 schorsch 3.10 extern int
799     getmove( /* find matching move object */
800     OBJECT obj
801     )
802 greg 3.1 {
803     static int lasti;
804     static OBJECT lasto = OVOID;
805     char *onm, *objnm;
806     int len, len2;
807     register int i;
808    
809     if (obj == OVOID)
810     return(-1);
811     if (obj == lasto)
812     return(lasti);
813     /* look for matching object */
814     onm = objptr(obj)->oname;
815     for (i = vdef(MOVE); i--; ) {
816     objnm = obj_move[i].name;
817     len = strlen(objnm);
818     if (!strncmp(onm, objnm, len)) {
819 schorsch 3.7 if ((obj_move[i].parent < 0) & (onm[len] == '.'))
820 greg 3.1 break;
821     objnm = getobjname(&obj_move[i]) + len;
822     len2 = strlen(objnm);
823     if (!strncmp(onm+len, objnm, len2) && onm[len+len2] == '.')
824     break;
825     }
826     }
827     lasto = obj; /* cache what we found */
828     return(lasti = i);
829     }
830    
831    
832 schorsch 3.10 extern double
833     obj_prio( /* return priority for object */
834     OBJECT obj
835     )
836 greg 3.1 {
837     int moi;
838    
839     if (obj == OVOID || (moi = getmove(obj)) < 0)
840     return(1.0);
841     return(obj_move[moi].cprio);
842     }
843    
844    
845 schorsch 3.10 extern double
846     getTime(void) /* get current time (CPU or real) */
847 greg 3.1 {
848     struct timeval time_now;
849     /* return CPU time if one process */
850     if (nprocs == 1)
851     return((double)clock()*(1.0/(double)CLOCKS_PER_SEC));
852     /* otherwise, return wall time */
853     gettimeofday(&time_now, NULL);
854     return((double)time_now.tv_sec + 1e-6*(double)time_now.tv_usec);
855     }