ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/ranimove.c
Revision: 3.24
Committed: Sat Jun 7 05:09:46 2025 UTC (15 hours, 44 minutes ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 3.23: +1 -2 lines
Log Message:
refactor: Put some declarations into "paths.h" and included in "platform.h"

File Contents

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