ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/ranimove.c
Revision: 3.22
Committed: Wed Apr 23 02:35:26 2025 UTC (9 days, 14 hours ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 3.21: +4 -1 lines
Log Message:
fix: Added missing calls to initfunc()

File Contents

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