ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/ranimove.c
Revision: 3.2
Committed: Tue Feb 25 02:47:24 2003 UTC (21 years, 2 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 3.1: +1 -56 lines
Log Message:
Replaced inline copyright notice with #include "copyright.h"

File Contents

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