ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/ranimove.c
Revision: 3.21
Committed: Wed Aug 21 16:18:54 2024 UTC (8 months, 1 week ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 3.20: +1 -2 lines
Log Message:
chore: Minor compiler warning fixes

File Contents

# User Rev Content
1 greg 3.1 #ifndef lint
2 greg 3.21 static const char RCSid[] = "$Id: ranimove.c,v 3.20 2023/02/06 22:40:21 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.20 const 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     static char expval[32];
543     static FILE *expfp = NULL;
544     static int curfrm = 0;
545 greg 3.18 char *cp;
546 greg 3.1
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 greg 3.18 double
596 schorsch 3.10 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 greg 3.18 char *
613 schorsch 3.10 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 greg 3.18 struct ObjMove *om
670 schorsch 3.10 )
671 greg 3.1 {
672     static char objName[512];
673 greg 3.18 char *cp = objName;
674 greg 3.1
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 greg 3.18 struct ObjMove *om,
689 schorsch 3.10 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 greg 3.18 char *cp;
702 greg 3.1 /* 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 greg 3.18 int
810 schorsch 3.10 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 greg 3.18 int i;
819 greg 3.1
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 greg 3.18 double
844 schorsch 3.10 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 greg 3.18 double
895 schorsch 3.10 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     }