ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/ranimove.c
Revision: 3.3
Committed: Mon Mar 10 17:26:26 2003 UTC (21 years, 1 month ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R5
Changes since 3.2: +2 -1 lines
Log Message:
Compile fixes for Linux

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