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, 9 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

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