ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/ranimove.c
Revision: 3.4
Committed: Thu Jun 26 00:58:11 2003 UTC (20 years, 9 months ago) by schorsch
Content type: text/plain
Branch: MAIN
Changes since 3.3: +3 -1 lines
Log Message:
Abstracted process and path handling for Windows.
Renamed FLOAT to RREAL because of conflict on Windows.
Added conditional compiles for some signal handlers.

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