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 (11 days, 22 hours 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

# User Rev Content
1 greg 3.1 #ifndef lint
2 greg 3.24 static const char RCSid[] = "$Id: ranimove.c,v 3.23 2025/06/03 21:31:51 greg Exp $";
3 greg 3.1 #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 greg 3.2 #include "copyright.h"
13 greg 3.1
14 greg 3.3 #include <time.h>
15 schorsch 3.16 #if defined(_WIN32) || defined(_WIN64)
16 schorsch 3.9 #include <winsock.h> /* struct timeval. XXX find a replacement? */
17     #else
18 schorsch 3.4 #include <sys/time.h>
19     #endif
20 greg 3.1 #include <ctype.h>
21 schorsch 3.5 #include <string.h>
22    
23 schorsch 3.16 #include "platform.h"
24 schorsch 3.5 #include "ranimove.h"
25 greg 3.22 #include "func.h"
26 greg 3.1
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 schorsch 3.10 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 greg 3.1
76     int
77 schorsch 3.10 main(
78     int argc,
79     char *argv[]
80     )
81 greg 3.1 {
82     int explicate = 0;
83     char *cfname;
84     int i;
85 greg 3.23 /* set global progname */
86     fixargv0(argv[0]);
87 greg 3.22 /* initialize calcomp */
88     initfunc();
89 greg 3.1 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 schorsch 3.7 if ((fbeg <= 0) | (fend < fbeg))
116 greg 3.1 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 greg 3.8 if (hirendoptf[0] && strcmp(hirendoptf, lorendoptf))
160 greg 3.1 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 schorsch 3.10 return 1; /* pro forma return */
170 greg 3.1 }
171    
172    
173     void
174 schorsch 3.11 eputs( /* put string to stderr */
175 greg 3.20 const char *s
176 schorsch 3.11 )
177 greg 3.1 {
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 greg 3.13 void
195 greg 3.18 quit(int ec) /* make sure exit is called */
196 greg 3.13 {
197     if (ray_pnprocs > 0) /* close children if any */
198 greg 3.19 ray_pclose(0);
199     else if (ray_pnprocs < 0)
200     _exit(ec); /* avoid flush in child */
201 greg 3.13 exit(ec);
202     }
203    
204    
205 schorsch 3.10 static void
206     setdefaults(void) /* set default values */
207 greg 3.1 {
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 schorsch 3.5 twolevels = memcmp(&lorendparams, &hirendparams, sizeof(RAYPARAMS));
279 greg 3.1 }
280    
281    
282 schorsch 3.10 static void
283     setmove( /* assign a move object from spec. */
284     struct ObjMove *om,
285     char *ms
286     )
287 greg 3.1 {
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 schorsch 3.7 haveprio |= ((om->prio < 0.95) | (om->prio > 1.05));
332 greg 3.1 } 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 schorsch 3.10 static void
344     setrendparams( /* set global rendering parameters */
345     char *optf,
346     char *qval
347     )
348 greg 3.1 {
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 greg 3.17 ac = wordfile(av, 1024, optf);
357 greg 3.1 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 greg 3.17 ac += wordstring(av+ac, 1024-ac, qval);
366 greg 3.1
367 greg 3.8 /* restore default parameters */
368     ray_restore(NULL);
369 greg 3.1 /* 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 greg 3.8 if (rval < 0) {
383     sprintf(errmsg, "bad render option at '%s'", av[i]);
384     error(USER, errmsg);
385 greg 3.1 }
386 greg 3.8 i += rval;
387 greg 3.1 }
388     }
389    
390    
391 schorsch 3.10 static void
392     getradfile( /* run rad and get needed variables */
393     char *rfargs
394     )
395 greg 3.1 {
396     static short mvar[] = {OCONV,OCTREEF,RESOLUTION,EXPOSURE,-1};
397     char combuf[256];
398 greg 3.18 int i;
399     char *cp;
400 schorsch 3.10 char *pippt = NULL;
401 greg 3.1 /* 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 schorsch 3.5 strcpy(pippt, "> " NULL_DEVICE); /* nothing to match */
422 greg 3.1 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 schorsch 3.10 static void
444     animate(void) /* run through animation */
445 greg 3.1 {
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 greg 3.18 VIEW *
476 schorsch 3.10 getview( /* get view number n */
477     int n
478     )
479 greg 3.1 {
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 schorsch 3.6 curview = stdview;
491 greg 3.1 }
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 schorsch 3.6 curview = stdview;
507 greg 3.1 viewnum = 0;
508     }
509     if (n < 0) { /* get next view */
510 greg 3.18 int c = getc(viewfp);
511 greg 3.1 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 schorsch 3.10 static int
527     countviews(void) /* count views in view file */
528 greg 3.1 {
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 greg 3.18 char *
540 schorsch 3.10 getexp( /* get exposure for nth frame */
541     int n
542     )
543 greg 3.1 {
544     static char expval[32];
545     static FILE *expfp = NULL;
546     static int curfrm = 0;
547 greg 3.18 char *cp;
548 greg 3.1
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 schorsch 3.10 return NULL; /* pro forma return */
594 greg 3.1 }
595    
596    
597 greg 3.18 double
598 schorsch 3.10 expspec_val( /* get exposure value from spec. */
599     char *s
600     )
601 greg 3.1 {
602     double expval;
603    
604     if (s == NULL || !*s)
605     return(1.0);
606    
607     expval = atof(s);
608 schorsch 3.7 if ((s[0] == '+') | (s[0] == '-'))
609 greg 3.1 return(pow(2.0, expval));
610     return(expval);
611     }
612    
613    
614 greg 3.18 char *
615 schorsch 3.10 getoctspec( /* get octree for the given frame */
616     int n
617     )
618 greg 3.1 {
619     static char combuf[1024];
620 greg 3.14 static int cfm = 0;
621 greg 3.1 int uses_inline;
622     FILE *fp;
623     int i;
624     /* is octree static? */
625     if (!vdef(MOVE))
626     return(vval(OCTREEF));
627 greg 3.14 /* done already? */
628 greg 3.1 if (n == cfm)
629     return(combuf);
630     /* else create object file */
631 greg 3.14 fp = fopen(mktemp(strcpy(objtmpf, TEMPLATE)), "w");
632 greg 3.1 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 greg 3.14 sprintf(combuf, "!xform -f %s | oconv %s -f -i '%s' -",
663     objtmpf, vdef(OCONV) ? vval(OCONV) : "",
664     vval(OCTREEF));
665 greg 3.1 return(combuf);
666     }
667    
668    
669 schorsch 3.10 static char *
670     getobjname( /* get fully qualified object name */
671 greg 3.18 struct ObjMove *om
672 schorsch 3.10 )
673 greg 3.1 {
674     static char objName[512];
675 greg 3.18 char *cp = objName;
676 greg 3.1
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 schorsch 3.10 static char *
689     getxf( /* get total transform for object */
690 greg 3.18 struct ObjMove *om,
691 schorsch 3.10 int n
692     )
693 greg 3.1 {
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 greg 3.18 char *cp;
704 greg 3.1 /* 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 schorsch 3.6 if (framestep) {
801 greg 3.1 if (invmat4(om->bxfm, om->cxfm))
802     multmat4(om->bxfm, om->bxfm, oxf.xfm);
803     else
804     setident4(om->bxfm);
805 schorsch 3.6 }
806 greg 3.1 /* all done */
807     return(xfp);
808     }
809    
810    
811 greg 3.18 int
812 schorsch 3.10 getmove( /* find matching move object */
813     OBJECT obj
814     )
815 greg 3.1 {
816     static int lasti;
817     static OBJECT lasto = OVOID;
818     char *onm, *objnm;
819     int len, len2;
820 greg 3.18 int i;
821 greg 3.1
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 schorsch 3.7 if ((obj_move[i].parent < 0) & (onm[len] == '.'))
833 greg 3.1 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 greg 3.18 double
846 schorsch 3.10 obj_prio( /* return priority for object */
847     OBJECT obj
848     )
849 greg 3.1 {
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 schorsch 3.16 #if defined(_WIN32) || defined(_WIN64)
859 greg 3.15 /* 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 greg 3.18 double
897 schorsch 3.10 getTime(void) /* get current time (CPU or real) */
898 greg 3.1 {
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     }