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, 1 month 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

# 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 "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 }