ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/ranimove.c
Revision: 3.14
Committed: Wed Nov 3 05:05:21 2010 UTC (13 years, 4 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 3.13: +7 -7 lines
Log Message:
Fixed efficiency and name collision issues with octree creation

File Contents

# User Rev Content
1 greg 3.1 #ifndef lint
2 greg 3.14 static const char RCSid[] = "$Id: ranimove.c,v 3.13 2009/12/12 19:01:00 greg Exp $";
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 greg 3.13 void
192     quit(ec) /* make sure exit is called */
193     int ec;
194     {
195     if (ray_pnprocs > 0) /* close children if any */
196     ray_pclose(0);
197     exit(ec);
198     }
199    
200    
201 schorsch 3.10 static void
202     setdefaults(void) /* set default values */
203 greg 3.1 {
204     int nviews;
205     int decades;
206     char buf[256];
207     int i;
208    
209     if (!vdef(OCTREEF)) {
210     sprintf(errmsg, "%s or %s must be defined",
211     vnam(OCTREEF), vnam(RIF));
212     error(USER, errmsg);
213     }
214     if (!vdef(VIEWFILE)) {
215     sprintf(errmsg, "%s must be defined", vnam(VIEWFILE));
216     error(USER, errmsg);
217     }
218     nviews = countviews();
219     if (!nviews)
220     error(USER, "no views in view file");
221     if (!vdef(END)) {
222     if (nviews == 1) {
223     sprintf(errmsg, "%s must be defined for single view",
224     vnam(END));
225     error(USER, errmsg);
226     }
227     sprintf(buf, "%d", nviews);
228     vval(END) = savqstr(buf);
229     vdef(END)++;
230     }
231     if (!fend)
232     fend = vint(END);
233     if (fbeg > fend)
234     error(USER, "begin after end");
235     if (!vdef(BASENAME)) {
236     decades = (int)log10((double)vint(END)) + 1;
237     if (decades < 3) decades = 3;
238     sprintf(buf, "frame%%0%dd", decades);
239     vval(BASENAME) = savqstr(buf);
240     vdef(BASENAME)++;
241     }
242     if (!vdef(RATE)) {
243     vval(RATE) = "8";
244     vdef(RATE)++;
245     }
246     rate = vflt(RATE);
247     if (!vdef(RESOLUTION)) {
248     vval(RESOLUTION) = "640";
249     vdef(RESOLUTION)++;
250     }
251     if (!vdef(MBLUR)) {
252     vval(MBLUR) = "0";
253     vdef(MBLUR)++;
254     }
255     mblur = vflt(MBLUR);
256     if (mblur > 1.)
257     mblur = 1.;
258     /* set up objects */
259     if (vdef(MOVE)) {
260     obj_move = (struct ObjMove *)malloc(
261     sizeof(struct ObjMove)*vdef(MOVE) );
262     if (obj_move == NULL)
263     error(SYSTEM, "out of memory in setdefaults");
264     for (i = 0; i < vdef(MOVE); i++)
265     setmove(&obj_move[i], nvalue(MOVE, i));
266     }
267     /* set up high quality options */
268     setrendparams(hirendoptf, vval(HIGHQ));
269     ray_save(&hirendparams);
270     /* set up low quality options */
271     setrendparams(lorendoptf, vval(LOWQ));
272     ray_save(&lorendparams);
273     curparams = &lorendparams;
274 schorsch 3.5 twolevels = memcmp(&lorendparams, &hirendparams, sizeof(RAYPARAMS));
275 greg 3.1 }
276    
277    
278 schorsch 3.10 static void
279     setmove( /* assign a move object from spec. */
280     struct ObjMove *om,
281     char *ms
282     )
283 greg 3.1 {
284     char parname[128];
285     char *cp;
286    
287     ms = nextword(parname, sizeof(parname), ms);
288     if (!parname[0])
289     goto badspec;
290     for (cp = parname; *cp; cp++)
291     if (isspace(*cp))
292     *cp = '_';
293     for (om->parent = (om - obj_move); om->parent--; )
294     if (!strcmp(parname, obj_move[om->parent].name))
295     break;
296     if (om->parent < 0 &&
297     strcmp(parname, ".") && strcmp(parname, VOIDID)) {
298     sprintf(errmsg, "undefined parent object '%s'", parname);
299     error(USER, errmsg);
300     }
301     ms = nextword(om->name, sizeof(om->name), ms);
302     if (!om->name[0])
303     goto badspec;
304     for (cp = om->name; *cp; cp++)
305     if (isspace(*cp))
306     *cp = '_';
307     ms = nextword(om->xf_file, sizeof(om->xf_file), ms);
308     if (!strcmp(om->xf_file, "."))
309     om->xf_file[0] = '\0';
310     if (!om->xf_file[0]) {
311     om->xfs[0] = '\0';
312     } else if (om->xf_file[0] == '-') {
313     strcpy(om->xfs, om->xf_file);
314     om->xf_file[0] = '\0';
315     }
316     ms = nextword(om->spec, sizeof(om->spec), ms);
317     if (om->spec[0]) {
318     if (!strcmp(om->spec, ".") || !strcmp(om->spec, VOIDID))
319     om->spec[0] = '\0';
320     ms = nextword(om->prio_file, sizeof(om->prio_file), ms);
321     } else
322     om->prio_file[0] = '\0';
323     if (om->prio_file[0]) {
324     if (isflt(om->prio_file)) {
325     om->prio = atof(om->prio_file);
326     om->prio_file[0] = '\0';
327 schorsch 3.7 haveprio |= ((om->prio < 0.95) | (om->prio > 1.05));
328 greg 3.1 } else
329     haveprio = 1;
330     } else
331     om->prio = 1.;
332     om->cfm = -1;
333     return;
334     badspec:
335     error(USER, "bad object specification");
336     }
337    
338    
339 schorsch 3.10 static void
340     setrendparams( /* set global rendering parameters */
341     char *optf,
342     char *qval
343     )
344 greg 3.1 {
345     char *argv[1024];
346     char **av = argv;
347     int ac, i, rval;
348    
349     av[ac=0] = NULL;
350     /* load options from file, first */
351     if (optf != NULL && *optf) {
352     ac = wordfile(av, optf);
353     if (ac < 0) {
354     sprintf(errmsg, "cannot load options file \"%s\"",
355     optf);
356     error(SYSTEM, errmsg);
357     }
358     }
359     /* then from options string */
360     if (qval != NULL && qval[0] == '-')
361     ac += wordstring(av+ac, qval);
362    
363 greg 3.8 /* restore default parameters */
364     ray_restore(NULL);
365 greg 3.1 /* set what we have */
366     for (i = 0; i < ac; i++) {
367     while ((rval = expandarg(&ac, &av, i)) > 0)
368     ;
369     if (rval < 0) {
370     sprintf(errmsg, "cannot expand '%s'", av[i]);
371     error(SYSTEM, errmsg);
372     }
373     if (!strcmp(av[i], "-w")) {
374     nowarn++;
375     continue;
376     }
377     rval = getrenderopt(ac-i, av+i);
378 greg 3.8 if (rval < 0) {
379     sprintf(errmsg, "bad render option at '%s'", av[i]);
380     error(USER, errmsg);
381 greg 3.1 }
382 greg 3.8 i += rval;
383 greg 3.1 }
384     }
385    
386    
387 schorsch 3.10 static void
388     getradfile( /* run rad and get needed variables */
389     char *rfargs
390     )
391 greg 3.1 {
392     static short mvar[] = {OCONV,OCTREEF,RESOLUTION,EXPOSURE,-1};
393     char combuf[256];
394     register int i;
395     register char *cp;
396 schorsch 3.10 char *pippt = NULL;
397 greg 3.1 /* create rad command */
398     strcpy(lorendoptf, "ranim0.opt");
399     sprintf(combuf,
400     "rad -v 0 -s -e -w %s %s oconv=-f OPTFILE=%s | egrep '^[ \t]*(NOMATCH",
401     rfargs,
402     (vdef(LOWQ) && vval(LOWQ)[0]!='-') ? vval(LOWQ) : "",
403     lorendoptf);
404     cp = combuf;
405     while (*cp) {
406     if (*cp == '|') pippt = cp;
407     cp++;
408     } /* match unset variables */
409     for (i = 0; mvar[i] >= 0; i++)
410     if (!vdef(mvar[i])) {
411     *cp++ = '|';
412     strcpy(cp, vnam(mvar[i]));
413     while (*cp) cp++;
414     pippt = NULL;
415     }
416     if (pippt != NULL)
417 schorsch 3.5 strcpy(pippt, "> " NULL_DEVICE); /* nothing to match */
418 greg 3.1 else {
419     strcpy(cp, ")[ \t]*=' > ranimove.var");
420     cp += 11; /* point to file name */
421     }
422     system(combuf); /* ignore exit code */
423     if (pippt == NULL) { /* load variables and remove file */
424     loadvars(cp);
425     unlink(cp);
426     }
427     if (!vdef(HIGHQ) || vval(HIGHQ)[0]=='-') {
428     strcpy(hirendoptf, lorendoptf);
429     return;
430     }
431     /* get high quality options */
432     strcpy(hirendoptf, "ranim1.opt");
433     sprintf(combuf, "rad -v 0 -s -w %s %s OPTFILE=%s",
434     rfargs, vval(HIGHQ), hirendoptf);
435     system(combuf);
436     }
437    
438    
439 schorsch 3.10 static void
440     animate(void) /* run through animation */
441 greg 3.1 {
442     int rpass;
443    
444     if (fbeg > 1) /* synchronize transforms */
445     getoctspec(fbeg-1);
446    
447     for (fcur = fbeg; fcur <= fend; fcur++) {
448     if (!silent)
449     printf("Frame %d:\n", fcur);
450     /* base rendering */
451     init_frame();
452     /* refinement */
453     for (rpass = 0; refine_frame(rpass); rpass++)
454     ;
455     /* final filter pass */
456     filter_frame();
457     /* output frame */
458     send_frame();
459     }
460     /* free resources */
461     free_frame();
462     if (nprocs > 1)
463     ray_pdone(1);
464     else
465     ray_done(1);
466     getview(0);
467     getexp(0);
468     }
469    
470    
471 schorsch 3.10 extern VIEW *
472     getview( /* get view number n */
473     int n
474     )
475 greg 3.1 {
476     static FILE *viewfp = NULL; /* view file pointer */
477     static int viewnum = 0; /* current view number */
478     static VIEW curview = STDVIEW; /* current view */
479     char linebuf[256];
480    
481     if (n == 0) { /* signal to close file and clean up */
482     if (viewfp != NULL) {
483     fclose(viewfp);
484     viewfp = NULL;
485     viewnum = 0;
486 schorsch 3.6 curview = stdview;
487 greg 3.1 }
488     return(NULL);
489     }
490     if (viewfp == NULL) { /* open file */
491     if ((viewfp = fopen(vval(VIEWFILE), "r")) == NULL) {
492     perror(vval(VIEWFILE));
493     quit(1);
494     }
495     } else if (n > 0 && n < viewnum) { /* rewind file */
496     if (viewnum == 1 && feof(viewfp))
497     return(&curview); /* just one view */
498     if (fseek(viewfp, 0L, 0) == EOF) {
499     perror(vval(VIEWFILE));
500     quit(1);
501     }
502 schorsch 3.6 curview = stdview;
503 greg 3.1 viewnum = 0;
504     }
505     if (n < 0) { /* get next view */
506     register int c = getc(viewfp);
507     if (c == EOF)
508     return(NULL); /* that's it */
509     ungetc(c, viewfp);
510     n = viewnum + 1;
511     }
512     while (n > viewnum) { /* scan to desired view */
513     if (fgets(linebuf, sizeof(linebuf), viewfp) == NULL)
514     return(viewnum==1 ? &curview : (VIEW *)NULL);
515     if (isview(linebuf) && sscanview(&curview, linebuf) > 0)
516     viewnum++;
517     }
518     return(&curview); /* return it */
519     }
520    
521    
522 schorsch 3.10 static int
523     countviews(void) /* count views in view file */
524 greg 3.1 {
525     int n;
526    
527     if (getview(n=1) == NULL)
528     return(0);
529     while (getview(-1) != NULL)
530     n++;
531     return(n);
532     }
533    
534    
535 schorsch 3.10 extern char *
536     getexp( /* get exposure for nth frame */
537     int n
538     )
539 greg 3.1 {
540     extern char *fskip();
541     static char expval[32];
542     static FILE *expfp = NULL;
543     static int curfrm = 0;
544     register char *cp;
545    
546     if (n == 0) { /* signal to close file */
547     if (expfp != NULL) {
548     fclose(expfp);
549     expfp = NULL;
550     }
551     return(NULL);
552     }
553     if (!vdef(EXPOSURE)) /* no setting (auto) */
554     return(NULL);
555     if (isflt(vval(EXPOSURE))) /* always the same */
556     return(vval(EXPOSURE));
557     if (expfp == NULL) { /* open exposure file */
558     if ((expfp = fopen(vval(EXPOSURE), "r")) == NULL) {
559     sprintf(errmsg, "cannot open exposure file \"%s\"",
560     vval(EXPOSURE));
561     error(SYSTEM, errmsg);
562     }
563     curfrm = 0;
564     }
565     if (curfrm > n) { /* rewind if necessary */
566     rewind(expfp);
567     curfrm = 0;
568     }
569     while (n > curfrm) { /* read to line */
570     if (fgets(expval, sizeof(expval), expfp) == NULL) {
571     sprintf(errmsg, "%s: too few exposures",
572     vval(EXPOSURE));
573     error(USER, errmsg);
574     }
575     if (strlen(expval) == sizeof(expval)-1)
576     goto formerr;
577     curfrm++;
578     }
579     cp = fskip(expval); /* check format */
580     if (cp != NULL)
581     while (isspace(*cp))
582     *cp++ = '\0';
583     if (cp == NULL || *cp)
584     goto formerr;
585     return(expval); /* return value */
586     formerr:
587     sprintf(errmsg, "%s: exposure format error on line %d",
588     vval(EXPOSURE), curfrm);
589     error(USER, errmsg);
590 schorsch 3.10 return NULL; /* pro forma return */
591 greg 3.1 }
592    
593    
594 schorsch 3.10 extern double
595     expspec_val( /* get exposure value from spec. */
596     char *s
597     )
598 greg 3.1 {
599     double expval;
600    
601     if (s == NULL || !*s)
602     return(1.0);
603    
604     expval = atof(s);
605 schorsch 3.7 if ((s[0] == '+') | (s[0] == '-'))
606 greg 3.1 return(pow(2.0, expval));
607     return(expval);
608     }
609    
610    
611 schorsch 3.10 extern char *
612     getoctspec( /* get octree for the given frame */
613     int n
614     )
615 greg 3.1 {
616     static char combuf[1024];
617 greg 3.14 static int cfm = 0;
618 greg 3.1 int uses_inline;
619     FILE *fp;
620     int i;
621     /* is octree static? */
622     if (!vdef(MOVE))
623     return(vval(OCTREEF));
624 greg 3.14 /* done already? */
625 greg 3.1 if (n == cfm)
626     return(combuf);
627     /* else create object file */
628 greg 3.14 fp = fopen(mktemp(strcpy(objtmpf, TEMPLATE)), "w");
629 greg 3.1 if (fp == NULL) {
630     sprintf(errmsg, "cannot write to moving objects file '%s'",
631     objtmpf);
632     error(SYSTEM, errmsg);
633     }
634     uses_inline = 0;
635     for (i = 0; i < vdef(MOVE); i++) {
636     int inlc = (obj_move[i].spec[0] == '!');
637     if (!obj_move[i].spec[0])
638     continue;
639     if (inlc)
640     fprintf(fp, "%s %d \\\n\t| xform",
641     obj_move[i].spec, n);
642     else
643     fputs("!xform", fp);
644     fprintf(fp, " -n %s", getobjname(&obj_move[i]));
645     fputs(getxf(&obj_move[i], n), fp);
646     if (!inlc)
647     fprintf(fp, " %s\n", obj_move[i].spec);
648     else
649     fputc('\n', fp);
650     uses_inline |= inlc;
651     }
652     if (fclose(fp) == EOF)
653     error(SYSTEM, "error writing moving objects file");
654     if (uses_inline)
655     sprintf(combuf, "!oconv %s -f -i '%s' %s",
656     vdef(OCONV) ? vval(OCONV) : "",
657     vval(OCTREEF), objtmpf);
658     else
659 greg 3.14 sprintf(combuf, "!xform -f %s | oconv %s -f -i '%s' -",
660     objtmpf, vdef(OCONV) ? vval(OCONV) : "",
661     vval(OCTREEF));
662 greg 3.1 return(combuf);
663     }
664    
665    
666 schorsch 3.10 static char *
667     getobjname( /* get fully qualified object name */
668     register struct ObjMove *om
669     )
670 greg 3.1 {
671     static char objName[512];
672     register char *cp = objName;
673    
674     strcpy(cp, om->name);
675     while (om->parent >= 0) {
676     while (*cp) cp++;
677     *cp++ = '@';
678     om = &obj_move[om->parent];
679     strcpy(cp, om->name);
680     }
681     return(objName);
682     }
683    
684    
685 schorsch 3.10 static char *
686     getxf( /* get total transform for object */
687     register struct ObjMove *om,
688     int n
689     )
690 greg 3.1 {
691     static char xfsbuf[4096];
692     char *xfp;
693     int framestep = 0;
694     XF oxf;
695     FILE *fp;
696     char abuf[512];
697     char *av[64];
698     int ac;
699     int i;
700     register char *cp;
701     /* get parent transform, first */
702     if (om->parent >= 0)
703     xfp = getxf(&obj_move[om->parent], n);
704     else
705     *(xfp = xfsbuf + sizeof(xfsbuf)-1) = '\0';
706     /* get transform spec. & priority */
707     if (om->cfm != n) {
708     if (om->xf_file[0]) {
709     fp = fopen(om->xf_file, "r");
710     if (fp == NULL) {
711     sprintf(errmsg,
712     "cannot open transform file '%s'",
713     om->xf_file);
714     error(SYSTEM, errmsg);
715     }
716     for (i = 0; i < n; i++)
717     if (fgetline(om->xfs, sizeof(om->xfs), fp)
718     == NULL) {
719     sprintf(errmsg,
720     "too few transforms in file '%s'",
721     om->xf_file);
722     error(USER, errmsg);
723     }
724     fclose(fp);
725     }
726     strcpy(cp=abuf, om->xfs);
727     ac = 0;
728     for ( ; ; ) {
729     while (isspace(*cp))
730     *cp++ = '\0';
731     if (!*cp)
732     break;
733     av[ac++] = cp;
734     while (*++cp && !isspace(*cp))
735     ;
736     }
737     av[ac] = NULL;
738     if (xf(&oxf, ac, av) != ac ||
739     fabs(oxf.sca) <= FTINY) {
740     sprintf(errmsg, "bad transform args: %s",
741     om->xfs);
742     error(USER, errmsg);
743     }
744     copymat4(om->xfm, oxf.xfm);
745     if (om->prio_file[0]) {
746     fp = fopen(om->prio_file, "r");
747     if (fp == NULL) {
748     sprintf(errmsg,
749     "cannot open priority file '%s'",
750     om->prio_file);
751     error(SYSTEM, errmsg);
752     }
753     for (i = 0; i < n; i++)
754     if (fgets(abuf, sizeof(abuf), fp)
755     == NULL) {
756     sprintf(errmsg,
757     "too few priorities in file '%s'",
758     om->prio_file);
759     error(USER, errmsg);
760     }
761     fclose(fp);
762     cp = fskip(abuf);
763     if (cp != NULL)
764     while (isspace(*cp))
765     *cp++ = '\0';
766     if (cp == NULL || *cp) {
767     sprintf(errmsg,
768     "priority '%s' in file '%s' not a number",
769     abuf, om->prio_file);
770     error(USER, errmsg);
771     }
772     om->prio = atof(abuf);
773     }
774     framestep = (n == om->cfm + 1);
775     om->cfm = n;
776     }
777     /* prepend to parent transform */
778     if (om->xfs[0]) {
779     i = strlen(om->xfs);
780     if (xfp - i <= xfsbuf)
781     error(INTERNAL, "transform too long in getxf");
782     cp = om->xfs + i;
783     while (i--)
784     *--xfp = *--cp;
785     *--xfp = ' ';
786     }
787     if (framestep)
788     copymat4(oxf.xfm, om->cxfm);
789     if (om->parent >= 0) {
790     multmat4(om->cxfm, om->xfm, obj_move[om->parent].cxfm);
791     om->cprio = obj_move[om->parent].cprio * om->prio;
792     } else {
793     copymat4(om->cxfm, om->xfm);
794     om->cprio = om->prio;
795     }
796     /* XXX bxfm relies on call order */
797 schorsch 3.6 if (framestep) {
798 greg 3.1 if (invmat4(om->bxfm, om->cxfm))
799     multmat4(om->bxfm, om->bxfm, oxf.xfm);
800     else
801     setident4(om->bxfm);
802 schorsch 3.6 }
803 greg 3.1 /* all done */
804     return(xfp);
805     }
806    
807    
808 schorsch 3.10 extern int
809     getmove( /* find matching move object */
810     OBJECT obj
811     )
812 greg 3.1 {
813     static int lasti;
814     static OBJECT lasto = OVOID;
815     char *onm, *objnm;
816     int len, len2;
817     register int i;
818    
819     if (obj == OVOID)
820     return(-1);
821     if (obj == lasto)
822     return(lasti);
823     /* look for matching object */
824     onm = objptr(obj)->oname;
825     for (i = vdef(MOVE); i--; ) {
826     objnm = obj_move[i].name;
827     len = strlen(objnm);
828     if (!strncmp(onm, objnm, len)) {
829 schorsch 3.7 if ((obj_move[i].parent < 0) & (onm[len] == '.'))
830 greg 3.1 break;
831     objnm = getobjname(&obj_move[i]) + len;
832     len2 = strlen(objnm);
833     if (!strncmp(onm+len, objnm, len2) && onm[len+len2] == '.')
834     break;
835     }
836     }
837     lasto = obj; /* cache what we found */
838     return(lasti = i);
839     }
840    
841    
842 schorsch 3.10 extern double
843     obj_prio( /* return priority for object */
844     OBJECT obj
845     )
846 greg 3.1 {
847     int moi;
848    
849     if (obj == OVOID || (moi = getmove(obj)) < 0)
850     return(1.0);
851     return(obj_move[moi].cprio);
852     }
853    
854    
855 schorsch 3.10 extern double
856     getTime(void) /* get current time (CPU or real) */
857 greg 3.1 {
858     struct timeval time_now;
859     /* return CPU time if one process */
860     if (nprocs == 1)
861     return((double)clock()*(1.0/(double)CLOCKS_PER_SEC));
862     /* otherwise, return wall time */
863     gettimeofday(&time_now, NULL);
864     return((double)time_now.tv_sec + 1e-6*(double)time_now.tv_usec);
865     }