ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/ranimove.c
Revision: 3.15
Committed: Wed Oct 5 17:20:55 2011 UTC (12 years, 5 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad4R2P2, rad5R0, rad4R2, rad4R1, rad4R2P1
Changes since 3.14: +39 -1 lines
Log Message:
Windows compatibility changes from Bill Hoffman

File Contents

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