ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/ranimove.c
Revision: 3.16
Committed: Sun Mar 6 01:13:18 2016 UTC (8 years, 1 month ago) by schorsch
Content type: text/plain
Branch: MAIN
Changes since 3.15: +4 -3 lines
Log Message:
Prepare for SCons build on Win32 and Win64

File Contents

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