ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/ranimove.c
Revision: 3.17
Committed: Mon Mar 21 19:06:08 2016 UTC (8 years, 1 month ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 3.16: +3 -3 lines
Log Message:
Improved error-checking for too many words in file or string

File Contents

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