ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/ranimove.c
Revision: 3.5
Committed: Mon Jun 30 14:59:13 2003 UTC (20 years, 9 months ago) by schorsch
Content type: text/plain
Branch: MAIN
Changes since 3.4: +6 -3 lines
Log Message:
Replaced most outdated BSD function calls with their posix equivalents, and cleaned up a few other platform dependencies.

File Contents

# Content
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 #include "copyright.h"
13
14 #include <time.h>
15 #ifndef _WIN32
16 #include <sys/time.h>
17 #endif
18 #include <ctype.h>
19 #include <string.h>
20
21 #include "paths.h"
22 #include "ranimove.h"
23
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 if ((fbeg <= 0 | fend < fbeg))
101 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 if (hirendoptf[0])
145 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 twolevels = memcmp(&lorendparams, &hirendparams, sizeof(RAYPARAMS));
251 }
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 haveprio |= (om->prio < 0.95 | om->prio > 1.05);
303 } 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 /* start with default parameters */
338 ray_defaults(NULL);
339 /* 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 if (rval >= 0) {
353 i += rval;
354 continue;
355 }
356 sprintf(errmsg, "bad render option at '%s'", av[i]);
357 error(USER, errmsg);
358 }
359 }
360
361
362 void
363 getradfile(rfargs) /* run rad and get needed variables */
364 char *rfargs;
365 {
366 static short mvar[] = {OCONV,OCTREEF,RESOLUTION,EXPOSURE,-1};
367 char combuf[256];
368 register int i;
369 register char *cp;
370 char *pippt;
371 /* create rad command */
372 strcpy(lorendoptf, "ranim0.opt");
373 sprintf(combuf,
374 "rad -v 0 -s -e -w %s %s oconv=-f OPTFILE=%s | egrep '^[ \t]*(NOMATCH",
375 rfargs,
376 (vdef(LOWQ) && vval(LOWQ)[0]!='-') ? vval(LOWQ) : "",
377 lorendoptf);
378 cp = combuf;
379 while (*cp) {
380 if (*cp == '|') pippt = cp;
381 cp++;
382 } /* match unset variables */
383 for (i = 0; mvar[i] >= 0; i++)
384 if (!vdef(mvar[i])) {
385 *cp++ = '|';
386 strcpy(cp, vnam(mvar[i]));
387 while (*cp) cp++;
388 pippt = NULL;
389 }
390 if (pippt != NULL)
391 strcpy(pippt, "> " NULL_DEVICE); /* nothing to match */
392 else {
393 strcpy(cp, ")[ \t]*=' > ranimove.var");
394 cp += 11; /* point to file name */
395 }
396 system(combuf); /* ignore exit code */
397 if (pippt == NULL) { /* load variables and remove file */
398 loadvars(cp);
399 unlink(cp);
400 }
401 if (!vdef(HIGHQ) || vval(HIGHQ)[0]=='-') {
402 strcpy(hirendoptf, lorendoptf);
403 return;
404 }
405 /* get high quality options */
406 strcpy(hirendoptf, "ranim1.opt");
407 sprintf(combuf, "rad -v 0 -s -w %s %s OPTFILE=%s",
408 rfargs, vval(HIGHQ), hirendoptf);
409 system(combuf);
410 }
411
412
413 void
414 animate() /* run through animation */
415 {
416 int rpass;
417
418 if (fbeg > 1) /* synchronize transforms */
419 getoctspec(fbeg-1);
420
421 for (fcur = fbeg; fcur <= fend; fcur++) {
422 if (!silent)
423 printf("Frame %d:\n", fcur);
424 /* base rendering */
425 init_frame();
426 /* refinement */
427 for (rpass = 0; refine_frame(rpass); rpass++)
428 ;
429 /* final filter pass */
430 filter_frame();
431 /* output frame */
432 send_frame();
433 }
434 /* free resources */
435 free_frame();
436 if (nprocs > 1)
437 ray_pdone(1);
438 else
439 ray_done(1);
440 getview(0);
441 getexp(0);
442 }
443
444
445 VIEW *
446 getview(n) /* get view number n */
447 int n;
448 {
449 static FILE *viewfp = NULL; /* view file pointer */
450 static int viewnum = 0; /* current view number */
451 static VIEW curview = STDVIEW; /* current view */
452 char linebuf[256];
453
454 if (n == 0) { /* signal to close file and clean up */
455 if (viewfp != NULL) {
456 fclose(viewfp);
457 viewfp = NULL;
458 viewnum = 0;
459 copystruct(&curview, &stdview);
460 }
461 return(NULL);
462 }
463 if (viewfp == NULL) { /* open file */
464 if ((viewfp = fopen(vval(VIEWFILE), "r")) == NULL) {
465 perror(vval(VIEWFILE));
466 quit(1);
467 }
468 } else if (n > 0 && n < viewnum) { /* rewind file */
469 if (viewnum == 1 && feof(viewfp))
470 return(&curview); /* just one view */
471 if (fseek(viewfp, 0L, 0) == EOF) {
472 perror(vval(VIEWFILE));
473 quit(1);
474 }
475 copystruct(&curview, &stdview);
476 viewnum = 0;
477 }
478 if (n < 0) { /* get next view */
479 register int c = getc(viewfp);
480 if (c == EOF)
481 return(NULL); /* that's it */
482 ungetc(c, viewfp);
483 n = viewnum + 1;
484 }
485 while (n > viewnum) { /* scan to desired view */
486 if (fgets(linebuf, sizeof(linebuf), viewfp) == NULL)
487 return(viewnum==1 ? &curview : (VIEW *)NULL);
488 if (isview(linebuf) && sscanview(&curview, linebuf) > 0)
489 viewnum++;
490 }
491 return(&curview); /* return it */
492 }
493
494
495 int
496 countviews() /* count views in view file */
497 {
498 int n;
499
500 if (getview(n=1) == NULL)
501 return(0);
502 while (getview(-1) != NULL)
503 n++;
504 return(n);
505 }
506
507
508 char *
509 getexp(n) /* get exposure for nth frame */
510 int n;
511 {
512 extern char *fskip();
513 static char expval[32];
514 static FILE *expfp = NULL;
515 static int curfrm = 0;
516 register char *cp;
517
518 if (n == 0) { /* signal to close file */
519 if (expfp != NULL) {
520 fclose(expfp);
521 expfp = NULL;
522 }
523 return(NULL);
524 }
525 if (!vdef(EXPOSURE)) /* no setting (auto) */
526 return(NULL);
527 if (isflt(vval(EXPOSURE))) /* always the same */
528 return(vval(EXPOSURE));
529 if (expfp == NULL) { /* open exposure file */
530 if ((expfp = fopen(vval(EXPOSURE), "r")) == NULL) {
531 sprintf(errmsg, "cannot open exposure file \"%s\"",
532 vval(EXPOSURE));
533 error(SYSTEM, errmsg);
534 }
535 curfrm = 0;
536 }
537 if (curfrm > n) { /* rewind if necessary */
538 rewind(expfp);
539 curfrm = 0;
540 }
541 while (n > curfrm) { /* read to line */
542 if (fgets(expval, sizeof(expval), expfp) == NULL) {
543 sprintf(errmsg, "%s: too few exposures",
544 vval(EXPOSURE));
545 error(USER, errmsg);
546 }
547 if (strlen(expval) == sizeof(expval)-1)
548 goto formerr;
549 curfrm++;
550 }
551 cp = fskip(expval); /* check format */
552 if (cp != NULL)
553 while (isspace(*cp))
554 *cp++ = '\0';
555 if (cp == NULL || *cp)
556 goto formerr;
557 return(expval); /* return value */
558 formerr:
559 sprintf(errmsg, "%s: exposure format error on line %d",
560 vval(EXPOSURE), curfrm);
561 error(USER, errmsg);
562 }
563
564
565 double
566 expspec_val(s) /* get exposure value from spec. */
567 char *s;
568 {
569 double expval;
570
571 if (s == NULL || !*s)
572 return(1.0);
573
574 expval = atof(s);
575 if ((s[0] == '+' | s[0] == '-'))
576 return(pow(2.0, expval));
577 return(expval);
578 }
579
580
581 char *
582 getoctspec(n) /* get octree for the given frame */
583 int n;
584 {
585 static char combuf[1024];
586 int cfm = 0;
587 int uses_inline;
588 FILE *fp;
589 int i;
590 /* is octree static? */
591 if (!vdef(MOVE))
592 return(vval(OCTREEF));
593 /* done already */
594 if (n == cfm)
595 return(combuf);
596 /* else create object file */
597 strcpy(objtmpf, "movinobj.rad");
598 fp = fopen(objtmpf, "w");
599 if (fp == NULL) {
600 sprintf(errmsg, "cannot write to moving objects file '%s'",
601 objtmpf);
602 error(SYSTEM, errmsg);
603 }
604 uses_inline = 0;
605 for (i = 0; i < vdef(MOVE); i++) {
606 int inlc = (obj_move[i].spec[0] == '!');
607 if (!obj_move[i].spec[0])
608 continue;
609 if (inlc)
610 fprintf(fp, "%s %d \\\n\t| xform",
611 obj_move[i].spec, n);
612 else
613 fputs("!xform", fp);
614 fprintf(fp, " -n %s", getobjname(&obj_move[i]));
615 fputs(getxf(&obj_move[i], n), fp);
616 if (!inlc)
617 fprintf(fp, " %s\n", obj_move[i].spec);
618 else
619 fputc('\n', fp);
620 uses_inline |= inlc;
621 }
622 if (fclose(fp) == EOF)
623 error(SYSTEM, "error writing moving objects file");
624 if (uses_inline)
625 sprintf(combuf, "!oconv %s -f -i '%s' %s",
626 vdef(OCONV) ? vval(OCONV) : "",
627 vval(OCTREEF), objtmpf);
628 else
629 sprintf(combuf, "!xform -f %s | oconv -f -i '%s' -",
630 objtmpf, vval(OCTREEF));
631 return(combuf);
632 }
633
634
635 char *
636 getobjname(om) /* get fully qualified object name */
637 register struct ObjMove *om;
638 {
639 static char objName[512];
640 register char *cp = objName;
641
642 strcpy(cp, om->name);
643 while (om->parent >= 0) {
644 while (*cp) cp++;
645 *cp++ = '@';
646 om = &obj_move[om->parent];
647 strcpy(cp, om->name);
648 }
649 return(objName);
650 }
651
652
653 char *
654 getxf(om, n) /* get total transform for object */
655 register struct ObjMove *om;
656 int n;
657 {
658 static char xfsbuf[4096];
659 char *xfp;
660 int framestep = 0;
661 XF oxf;
662 FILE *fp;
663 char abuf[512];
664 char *av[64];
665 int ac;
666 int i;
667 register char *cp;
668 /* get parent transform, first */
669 if (om->parent >= 0)
670 xfp = getxf(&obj_move[om->parent], n);
671 else
672 *(xfp = xfsbuf + sizeof(xfsbuf)-1) = '\0';
673 /* get transform spec. & priority */
674 if (om->cfm != n) {
675 if (om->xf_file[0]) {
676 fp = fopen(om->xf_file, "r");
677 if (fp == NULL) {
678 sprintf(errmsg,
679 "cannot open transform file '%s'",
680 om->xf_file);
681 error(SYSTEM, errmsg);
682 }
683 for (i = 0; i < n; i++)
684 if (fgetline(om->xfs, sizeof(om->xfs), fp)
685 == NULL) {
686 sprintf(errmsg,
687 "too few transforms in file '%s'",
688 om->xf_file);
689 error(USER, errmsg);
690 }
691 fclose(fp);
692 }
693 strcpy(cp=abuf, om->xfs);
694 ac = 0;
695 for ( ; ; ) {
696 while (isspace(*cp))
697 *cp++ = '\0';
698 if (!*cp)
699 break;
700 av[ac++] = cp;
701 while (*++cp && !isspace(*cp))
702 ;
703 }
704 av[ac] = NULL;
705 if (xf(&oxf, ac, av) != ac ||
706 fabs(oxf.sca) <= FTINY) {
707 sprintf(errmsg, "bad transform args: %s",
708 om->xfs);
709 error(USER, errmsg);
710 }
711 copymat4(om->xfm, oxf.xfm);
712 if (om->prio_file[0]) {
713 fp = fopen(om->prio_file, "r");
714 if (fp == NULL) {
715 sprintf(errmsg,
716 "cannot open priority file '%s'",
717 om->prio_file);
718 error(SYSTEM, errmsg);
719 }
720 for (i = 0; i < n; i++)
721 if (fgets(abuf, sizeof(abuf), fp)
722 == NULL) {
723 sprintf(errmsg,
724 "too few priorities in file '%s'",
725 om->prio_file);
726 error(USER, errmsg);
727 }
728 fclose(fp);
729 cp = fskip(abuf);
730 if (cp != NULL)
731 while (isspace(*cp))
732 *cp++ = '\0';
733 if (cp == NULL || *cp) {
734 sprintf(errmsg,
735 "priority '%s' in file '%s' not a number",
736 abuf, om->prio_file);
737 error(USER, errmsg);
738 }
739 om->prio = atof(abuf);
740 }
741 framestep = (n == om->cfm + 1);
742 om->cfm = n;
743 }
744 /* prepend to parent transform */
745 if (om->xfs[0]) {
746 i = strlen(om->xfs);
747 if (xfp - i <= xfsbuf)
748 error(INTERNAL, "transform too long in getxf");
749 cp = om->xfs + i;
750 while (i--)
751 *--xfp = *--cp;
752 *--xfp = ' ';
753 }
754 if (framestep)
755 copymat4(oxf.xfm, om->cxfm);
756 if (om->parent >= 0) {
757 multmat4(om->cxfm, om->xfm, obj_move[om->parent].cxfm);
758 om->cprio = obj_move[om->parent].cprio * om->prio;
759 } else {
760 copymat4(om->cxfm, om->xfm);
761 om->cprio = om->prio;
762 }
763 /* XXX bxfm relies on call order */
764 if (framestep)
765 if (invmat4(om->bxfm, om->cxfm))
766 multmat4(om->bxfm, om->bxfm, oxf.xfm);
767 else
768 setident4(om->bxfm);
769 /* 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 if ((obj_move[i].parent < 0 & onm[len] == '.'))
795 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 }