ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/ranimove.c
Revision: 3.19
Committed: Mon Jul 20 15:54:29 2020 UTC (3 years, 8 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R3
Changes since 3.18: +4 -2 lines
Log Message:
fix(mkillum, rcontrib, rtrace, ranimove, rsensor): stall under macOS 10.15
due to broken flockfile() implementation -- workaround is better, anyway

File Contents

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