ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/ranimove.c
Revision: 3.9
Committed: Tue Oct 21 19:19:29 2003 UTC (20 years, 6 months ago) by schorsch
Content type: text/plain
Branch: MAIN
Changes since 3.8: +3 -1 lines
Log Message:
Various platform compatibility fixes.

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