ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/ranimove.c
Revision: 3.10
Committed: Fri Mar 26 21:36:20 2004 UTC (20 years, 1 month ago) by schorsch
Content type: text/plain
Branch: MAIN
Changes since 3.9: +71 -48 lines
Log Message:
Continued ANSIfication.

File Contents

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