ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/ranimove.c
Revision: 3.8
Committed: Tue Sep 23 03:54:57 2003 UTC (20 years, 7 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 3.7: +7 -8 lines
Log Message:
Bug fix where ranimove was restarting processes unnecessarily

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