ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/ranimove.c
Revision: 3.1
Committed: Sat Feb 22 02:07:30 2003 UTC (21 years, 1 month ago) by greg
Content type: text/plain
Branch: MAIN
Log Message:
Changes and check-in for 3.5 release
Includes new source files and modifications not recorded for many years
See ray/doc/notes/ReleaseNotes for notes between 3.1 and 3.5 release

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id$";
3 #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 /* ====================================================================
13 * The Radiance Software License, Version 1.0
14 *
15 * Copyright (c) 1990 - 2002 The Regents of the University of California,
16 * through Lawrence Berkeley National Laboratory. All rights reserved.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions
20 * are met:
21 *
22 * 1. Redistributions of source code must retain the above copyright
23 * notice, this list of conditions and the following disclaimer.
24 *
25 * 2. Redistributions in binary form must reproduce the above copyright
26 * notice, this list of conditions and the following disclaimer in
27 * the documentation and/or other materials provided with the
28 * distribution.
29 *
30 * 3. The end-user documentation included with the redistribution,
31 * if any, must include the following acknowledgment:
32 * "This product includes Radiance software
33 * (http://radsite.lbl.gov/)
34 * developed by the Lawrence Berkeley National Laboratory
35 * (http://www.lbl.gov/)."
36 * Alternately, this acknowledgment may appear in the software itself,
37 * if and wherever such third-party acknowledgments normally appear.
38 *
39 * 4. The names "Radiance," "Lawrence Berkeley National Laboratory"
40 * and "The Regents of the University of California" must
41 * not be used to endorse or promote products derived from this
42 * software without prior written permission. For written
43 * permission, please contact [email protected].
44 *
45 * 5. Products derived from this software may not be called "Radiance",
46 * nor may "Radiance" appear in their name, without prior written
47 * permission of Lawrence Berkeley National Laboratory.
48 *
49 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
50 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
51 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
52 * DISCLAIMED. IN NO EVENT SHALL Lawrence Berkeley National Laboratory OR
53 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
54 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
55 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
56 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
57 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
58 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
59 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
60 * SUCH DAMAGE.
61 * ====================================================================
62 *
63 * This software consists of voluntary contributions made by many
64 * individuals on behalf of Lawrence Berkeley National Laboratory. For more
65 * information on Lawrence Berkeley National Laboratory, please see
66 * <http://www.lbl.gov/>.
67 */
68
69 #include "ranimove.h"
70 #include <sys/time.h>
71 #include <ctype.h>
72
73 int NVARS = NV_INIT; /* total number of variables */
74
75 VARIABLE vv[] = VV_INIT; /* variable-value pairs */
76
77 extern int nowarn; /* don't report warnings? */
78 int silent = 0; /* run silently? */
79
80 int quickstart = 0; /* time initial frame as well? */
81
82 int nprocs = 1; /* number of rendering processes */
83
84 int rtperfrm = 60; /* seconds to spend per frame */
85
86 double ndthresh = 2.; /* noticeable difference threshold */
87 int ndtset = 0; /* user threshold -- stop when reached? */
88
89 int fbeg = 1; /* starting frame */
90 int fend = 0; /* ending frame */
91 int fcur; /* current frame being rendered */
92
93 char lorendoptf[32]; /* low quality options file */
94 RAYPARAMS lorendparams; /* low quality rendering parameters */
95 char hirendoptf[32]; /* high quality options file */
96 RAYPARAMS hirendparams; /* high quality rendering parameters */
97 RAYPARAMS *curparams; /* current parameter settings */
98 int twolevels; /* low and high quality differ */
99
100 double mblur; /* vflt(MBLUR) */
101 double rate; /* vflt(RATE) */
102
103 char objtmpf[32]; /* object temporary file */
104
105 struct ObjMove *obj_move; /* object movements */
106
107 int haveprio = 0; /* high-level saliency specified */
108
109 int gargc; /* global argc for printargs */
110 char **gargv; /* global argv for printargs */
111
112
113 int
114 main(argc, argv)
115 int argc;
116 char *argv[];
117 {
118 int explicate = 0;
119 char *cfname;
120 int i;
121
122 progname = argv[0]; /* get arguments */
123 gargc = argc;
124 gargv = argv;
125 for (i = 1; i < argc && argv[i][0] == '-'; i++)
126 switch (argv[i][1]) {
127 case 't': /* seconds per frame */
128 rtperfrm = atoi(argv[++i]);
129 break;
130 case 'd': /* noticeable difference */
131 ndthresh = atof(argv[++i]);
132 ndtset = 1;
133 break;
134 case 'e': /* print variables */
135 explicate++;
136 break;
137 case 's': /* silent running */
138 silent++;
139 break;
140 case 'q': /* start quickly */
141 quickstart++;
142 break;
143 case 'w': /* turn off warnings */
144 nowarn++;
145 break;
146 case 'f': /* frame range */
147 switch (sscanf(argv[++i], "%d,%d", &fbeg, &fend)) {
148 case 2:
149 if ((fbeg <= 0 | fend < fbeg))
150 goto userr;
151 break;
152 case 1:
153 if (fbeg <= 0)
154 goto userr;
155 fend = 0;
156 break;
157 default:
158 goto userr;
159 }
160 break;
161 case 'n': /* number of processes */
162 nprocs = atoi(argv[++i]);
163 break;
164 default:
165 goto userr;
166 }
167 if (rtperfrm <= 0) {
168 if (!ndtset)
169 error(USER, "specify -d jnd with -t 0");
170 rtperfrm = 7*24*3600;
171 }
172 if (i != argc-1)
173 goto userr;
174 cfname = argv[i];
175 /* load variables */
176 loadvars(cfname);
177 /* check variables */
178 checkvalues();
179 /* load RIF if any */
180 if (vdef(RIF))
181 getradfile(vval(RIF));
182 /* set defaults */
183 setdefaults();
184 /* print variables */
185 if (explicate)
186 printvars(stdout);
187 /* run animation */
188 if (nprocs > 0)
189 animate();
190 /* all done */
191 if (lorendoptf[0])
192 unlink(lorendoptf);
193 if (hirendoptf[0])
194 unlink(hirendoptf);
195 if (objtmpf[0])
196 unlink(objtmpf);
197 return(0);
198 userr:
199 fprintf(stderr,
200 "Usage: %s [-n nprocs][-f beg,end][-t sec][-d jnd][-s][-w][-e] anim_file\n",
201 progname);
202 quit(1);
203 }
204
205
206 void
207 eputs(s) /* put string to stderr */
208 register char *s;
209 {
210 static int midline = 0;
211
212 if (!*s)
213 return;
214 if (!midline++) {
215 fputs(progname, stderr);
216 fputs(": ", stderr);
217 }
218 fputs(s, stderr);
219 if (s[strlen(s)-1] == '\n') {
220 fflush(stderr);
221 midline = 0;
222 }
223 }
224
225
226 void
227 setdefaults() /* set default values */
228 {
229 int nviews;
230 int decades;
231 char buf[256];
232 int i;
233
234 if (!vdef(OCTREEF)) {
235 sprintf(errmsg, "%s or %s must be defined",
236 vnam(OCTREEF), vnam(RIF));
237 error(USER, errmsg);
238 }
239 if (!vdef(VIEWFILE)) {
240 sprintf(errmsg, "%s must be defined", vnam(VIEWFILE));
241 error(USER, errmsg);
242 }
243 nviews = countviews();
244 if (!nviews)
245 error(USER, "no views in view file");
246 if (!vdef(END)) {
247 if (nviews == 1) {
248 sprintf(errmsg, "%s must be defined for single view",
249 vnam(END));
250 error(USER, errmsg);
251 }
252 sprintf(buf, "%d", nviews);
253 vval(END) = savqstr(buf);
254 vdef(END)++;
255 }
256 if (!fend)
257 fend = vint(END);
258 if (fbeg > fend)
259 error(USER, "begin after end");
260 if (!vdef(BASENAME)) {
261 decades = (int)log10((double)vint(END)) + 1;
262 if (decades < 3) decades = 3;
263 sprintf(buf, "frame%%0%dd", decades);
264 vval(BASENAME) = savqstr(buf);
265 vdef(BASENAME)++;
266 }
267 if (!vdef(RATE)) {
268 vval(RATE) = "8";
269 vdef(RATE)++;
270 }
271 rate = vflt(RATE);
272 if (!vdef(RESOLUTION)) {
273 vval(RESOLUTION) = "640";
274 vdef(RESOLUTION)++;
275 }
276 if (!vdef(MBLUR)) {
277 vval(MBLUR) = "0";
278 vdef(MBLUR)++;
279 }
280 mblur = vflt(MBLUR);
281 if (mblur > 1.)
282 mblur = 1.;
283 /* set up objects */
284 if (vdef(MOVE)) {
285 obj_move = (struct ObjMove *)malloc(
286 sizeof(struct ObjMove)*vdef(MOVE) );
287 if (obj_move == NULL)
288 error(SYSTEM, "out of memory in setdefaults");
289 for (i = 0; i < vdef(MOVE); i++)
290 setmove(&obj_move[i], nvalue(MOVE, i));
291 }
292 /* set up high quality options */
293 setrendparams(hirendoptf, vval(HIGHQ));
294 ray_save(&hirendparams);
295 /* set up low quality options */
296 setrendparams(lorendoptf, vval(LOWQ));
297 ray_save(&lorendparams);
298 curparams = &lorendparams;
299 twolevels = bcmp(&lorendparams, &hirendparams, sizeof(RAYPARAMS));
300 }
301
302
303 void
304 setmove(om, ms) /* assign a move object from spec. */
305 struct ObjMove *om;
306 char *ms;
307 {
308 char parname[128];
309 char *cp;
310
311 ms = nextword(parname, sizeof(parname), ms);
312 if (!parname[0])
313 goto badspec;
314 for (cp = parname; *cp; cp++)
315 if (isspace(*cp))
316 *cp = '_';
317 for (om->parent = (om - obj_move); om->parent--; )
318 if (!strcmp(parname, obj_move[om->parent].name))
319 break;
320 if (om->parent < 0 &&
321 strcmp(parname, ".") && strcmp(parname, VOIDID)) {
322 sprintf(errmsg, "undefined parent object '%s'", parname);
323 error(USER, errmsg);
324 }
325 ms = nextword(om->name, sizeof(om->name), ms);
326 if (!om->name[0])
327 goto badspec;
328 for (cp = om->name; *cp; cp++)
329 if (isspace(*cp))
330 *cp = '_';
331 ms = nextword(om->xf_file, sizeof(om->xf_file), ms);
332 if (!strcmp(om->xf_file, "."))
333 om->xf_file[0] = '\0';
334 if (!om->xf_file[0]) {
335 om->xfs[0] = '\0';
336 } else if (om->xf_file[0] == '-') {
337 strcpy(om->xfs, om->xf_file);
338 om->xf_file[0] = '\0';
339 }
340 ms = nextword(om->spec, sizeof(om->spec), ms);
341 if (om->spec[0]) {
342 if (!strcmp(om->spec, ".") || !strcmp(om->spec, VOIDID))
343 om->spec[0] = '\0';
344 ms = nextword(om->prio_file, sizeof(om->prio_file), ms);
345 } else
346 om->prio_file[0] = '\0';
347 if (om->prio_file[0]) {
348 if (isflt(om->prio_file)) {
349 om->prio = atof(om->prio_file);
350 om->prio_file[0] = '\0';
351 haveprio |= (om->prio < 0.95 | om->prio > 1.05);
352 } else
353 haveprio = 1;
354 } else
355 om->prio = 1.;
356 om->cfm = -1;
357 return;
358 badspec:
359 error(USER, "bad object specification");
360 }
361
362
363 void
364 setrendparams(optf, qval) /* set global rendering parameters */
365 char *optf;
366 char *qval;
367 {
368 char *argv[1024];
369 char **av = argv;
370 int ac, i, rval;
371
372 av[ac=0] = NULL;
373 /* load options from file, first */
374 if (optf != NULL && *optf) {
375 ac = wordfile(av, optf);
376 if (ac < 0) {
377 sprintf(errmsg, "cannot load options file \"%s\"",
378 optf);
379 error(SYSTEM, errmsg);
380 }
381 }
382 /* then from options string */
383 if (qval != NULL && qval[0] == '-')
384 ac += wordstring(av+ac, qval);
385
386 /* start with default parameters */
387 ray_defaults(NULL);
388 /* set what we have */
389 for (i = 0; i < ac; i++) {
390 while ((rval = expandarg(&ac, &av, i)) > 0)
391 ;
392 if (rval < 0) {
393 sprintf(errmsg, "cannot expand '%s'", av[i]);
394 error(SYSTEM, errmsg);
395 }
396 if (!strcmp(av[i], "-w")) {
397 nowarn++;
398 continue;
399 }
400 rval = getrenderopt(ac-i, av+i);
401 if (rval >= 0) {
402 i += rval;
403 continue;
404 }
405 sprintf(errmsg, "bad render option at '%s'", av[i]);
406 error(USER, errmsg);
407 }
408 }
409
410
411 void
412 getradfile(rfargs) /* run rad and get needed variables */
413 char *rfargs;
414 {
415 static short mvar[] = {OCONV,OCTREEF,RESOLUTION,EXPOSURE,-1};
416 char combuf[256];
417 register int i;
418 register char *cp;
419 char *pippt;
420 /* create rad command */
421 strcpy(lorendoptf, "ranim0.opt");
422 sprintf(combuf,
423 "rad -v 0 -s -e -w %s %s oconv=-f OPTFILE=%s | egrep '^[ \t]*(NOMATCH",
424 rfargs,
425 (vdef(LOWQ) && vval(LOWQ)[0]!='-') ? vval(LOWQ) : "",
426 lorendoptf);
427 cp = combuf;
428 while (*cp) {
429 if (*cp == '|') pippt = cp;
430 cp++;
431 } /* match unset variables */
432 for (i = 0; mvar[i] >= 0; i++)
433 if (!vdef(mvar[i])) {
434 *cp++ = '|';
435 strcpy(cp, vnam(mvar[i]));
436 while (*cp) cp++;
437 pippt = NULL;
438 }
439 if (pippt != NULL)
440 strcpy(pippt, "> /dev/null"); /* nothing to match */
441 else {
442 strcpy(cp, ")[ \t]*=' > ranimove.var");
443 cp += 11; /* point to file name */
444 }
445 system(combuf); /* ignore exit code */
446 if (pippt == NULL) { /* load variables and remove file */
447 loadvars(cp);
448 unlink(cp);
449 }
450 if (!vdef(HIGHQ) || vval(HIGHQ)[0]=='-') {
451 strcpy(hirendoptf, lorendoptf);
452 return;
453 }
454 /* get high quality options */
455 strcpy(hirendoptf, "ranim1.opt");
456 sprintf(combuf, "rad -v 0 -s -w %s %s OPTFILE=%s",
457 rfargs, vval(HIGHQ), hirendoptf);
458 system(combuf);
459 }
460
461
462 void
463 animate() /* run through animation */
464 {
465 int rpass;
466
467 if (fbeg > 1) /* synchronize transforms */
468 getoctspec(fbeg-1);
469
470 for (fcur = fbeg; fcur <= fend; fcur++) {
471 if (!silent)
472 printf("Frame %d:\n", fcur);
473 /* base rendering */
474 init_frame();
475 /* refinement */
476 for (rpass = 0; refine_frame(rpass); rpass++)
477 ;
478 /* final filter pass */
479 filter_frame();
480 /* output frame */
481 send_frame();
482 }
483 /* free resources */
484 free_frame();
485 if (nprocs > 1)
486 ray_pdone(1);
487 else
488 ray_done(1);
489 getview(0);
490 getexp(0);
491 }
492
493
494 VIEW *
495 getview(n) /* get view number n */
496 int n;
497 {
498 static FILE *viewfp = NULL; /* view file pointer */
499 static int viewnum = 0; /* current view number */
500 static VIEW curview = STDVIEW; /* current view */
501 char linebuf[256];
502
503 if (n == 0) { /* signal to close file and clean up */
504 if (viewfp != NULL) {
505 fclose(viewfp);
506 viewfp = NULL;
507 viewnum = 0;
508 copystruct(&curview, &stdview);
509 }
510 return(NULL);
511 }
512 if (viewfp == NULL) { /* open file */
513 if ((viewfp = fopen(vval(VIEWFILE), "r")) == NULL) {
514 perror(vval(VIEWFILE));
515 quit(1);
516 }
517 } else if (n > 0 && n < viewnum) { /* rewind file */
518 if (viewnum == 1 && feof(viewfp))
519 return(&curview); /* just one view */
520 if (fseek(viewfp, 0L, 0) == EOF) {
521 perror(vval(VIEWFILE));
522 quit(1);
523 }
524 copystruct(&curview, &stdview);
525 viewnum = 0;
526 }
527 if (n < 0) { /* get next view */
528 register int c = getc(viewfp);
529 if (c == EOF)
530 return(NULL); /* that's it */
531 ungetc(c, viewfp);
532 n = viewnum + 1;
533 }
534 while (n > viewnum) { /* scan to desired view */
535 if (fgets(linebuf, sizeof(linebuf), viewfp) == NULL)
536 return(viewnum==1 ? &curview : (VIEW *)NULL);
537 if (isview(linebuf) && sscanview(&curview, linebuf) > 0)
538 viewnum++;
539 }
540 return(&curview); /* return it */
541 }
542
543
544 int
545 countviews() /* count views in view file */
546 {
547 int n;
548
549 if (getview(n=1) == NULL)
550 return(0);
551 while (getview(-1) != NULL)
552 n++;
553 return(n);
554 }
555
556
557 char *
558 getexp(n) /* get exposure for nth frame */
559 int n;
560 {
561 extern char *fskip();
562 static char expval[32];
563 static FILE *expfp = NULL;
564 static int curfrm = 0;
565 register char *cp;
566
567 if (n == 0) { /* signal to close file */
568 if (expfp != NULL) {
569 fclose(expfp);
570 expfp = NULL;
571 }
572 return(NULL);
573 }
574 if (!vdef(EXPOSURE)) /* no setting (auto) */
575 return(NULL);
576 if (isflt(vval(EXPOSURE))) /* always the same */
577 return(vval(EXPOSURE));
578 if (expfp == NULL) { /* open exposure file */
579 if ((expfp = fopen(vval(EXPOSURE), "r")) == NULL) {
580 sprintf(errmsg, "cannot open exposure file \"%s\"",
581 vval(EXPOSURE));
582 error(SYSTEM, errmsg);
583 }
584 curfrm = 0;
585 }
586 if (curfrm > n) { /* rewind if necessary */
587 rewind(expfp);
588 curfrm = 0;
589 }
590 while (n > curfrm) { /* read to line */
591 if (fgets(expval, sizeof(expval), expfp) == NULL) {
592 sprintf(errmsg, "%s: too few exposures",
593 vval(EXPOSURE));
594 error(USER, errmsg);
595 }
596 if (strlen(expval) == sizeof(expval)-1)
597 goto formerr;
598 curfrm++;
599 }
600 cp = fskip(expval); /* check format */
601 if (cp != NULL)
602 while (isspace(*cp))
603 *cp++ = '\0';
604 if (cp == NULL || *cp)
605 goto formerr;
606 return(expval); /* return value */
607 formerr:
608 sprintf(errmsg, "%s: exposure format error on line %d",
609 vval(EXPOSURE), curfrm);
610 error(USER, errmsg);
611 }
612
613
614 double
615 expspec_val(s) /* get exposure value from spec. */
616 char *s;
617 {
618 double expval;
619
620 if (s == NULL || !*s)
621 return(1.0);
622
623 expval = atof(s);
624 if ((s[0] == '+' | s[0] == '-'))
625 return(pow(2.0, expval));
626 return(expval);
627 }
628
629
630 char *
631 getoctspec(n) /* get octree for the given frame */
632 int n;
633 {
634 static char combuf[1024];
635 int cfm = 0;
636 int uses_inline;
637 FILE *fp;
638 int i;
639 /* is octree static? */
640 if (!vdef(MOVE))
641 return(vval(OCTREEF));
642 /* done already */
643 if (n == cfm)
644 return(combuf);
645 /* else create object file */
646 strcpy(objtmpf, "movinobj.rad");
647 fp = fopen(objtmpf, "w");
648 if (fp == NULL) {
649 sprintf(errmsg, "cannot write to moving objects file '%s'",
650 objtmpf);
651 error(SYSTEM, errmsg);
652 }
653 uses_inline = 0;
654 for (i = 0; i < vdef(MOVE); i++) {
655 int inlc = (obj_move[i].spec[0] == '!');
656 if (!obj_move[i].spec[0])
657 continue;
658 if (inlc)
659 fprintf(fp, "%s %d \\\n\t| xform",
660 obj_move[i].spec, n);
661 else
662 fputs("!xform", fp);
663 fprintf(fp, " -n %s", getobjname(&obj_move[i]));
664 fputs(getxf(&obj_move[i], n), fp);
665 if (!inlc)
666 fprintf(fp, " %s\n", obj_move[i].spec);
667 else
668 fputc('\n', fp);
669 uses_inline |= inlc;
670 }
671 if (fclose(fp) == EOF)
672 error(SYSTEM, "error writing moving objects file");
673 if (uses_inline)
674 sprintf(combuf, "!oconv %s -f -i '%s' %s",
675 vdef(OCONV) ? vval(OCONV) : "",
676 vval(OCTREEF), objtmpf);
677 else
678 sprintf(combuf, "!xform -f %s | oconv -f -i '%s' -",
679 objtmpf, vval(OCTREEF));
680 return(combuf);
681 }
682
683
684 char *
685 getobjname(om) /* get fully qualified object name */
686 register struct ObjMove *om;
687 {
688 static char objName[512];
689 register char *cp = objName;
690
691 strcpy(cp, om->name);
692 while (om->parent >= 0) {
693 while (*cp) cp++;
694 *cp++ = '@';
695 om = &obj_move[om->parent];
696 strcpy(cp, om->name);
697 }
698 return(objName);
699 }
700
701
702 char *
703 getxf(om, n) /* get total transform for object */
704 register struct ObjMove *om;
705 int n;
706 {
707 static char xfsbuf[4096];
708 char *xfp;
709 int framestep = 0;
710 XF oxf;
711 FILE *fp;
712 char abuf[512];
713 char *av[64];
714 int ac;
715 int i;
716 register char *cp;
717 /* get parent transform, first */
718 if (om->parent >= 0)
719 xfp = getxf(&obj_move[om->parent], n);
720 else
721 *(xfp = xfsbuf + sizeof(xfsbuf)-1) = '\0';
722 /* get transform spec. & priority */
723 if (om->cfm != n) {
724 if (om->xf_file[0]) {
725 fp = fopen(om->xf_file, "r");
726 if (fp == NULL) {
727 sprintf(errmsg,
728 "cannot open transform file '%s'",
729 om->xf_file);
730 error(SYSTEM, errmsg);
731 }
732 for (i = 0; i < n; i++)
733 if (fgetline(om->xfs, sizeof(om->xfs), fp)
734 == NULL) {
735 sprintf(errmsg,
736 "too few transforms in file '%s'",
737 om->xf_file);
738 error(USER, errmsg);
739 }
740 fclose(fp);
741 }
742 strcpy(cp=abuf, om->xfs);
743 ac = 0;
744 for ( ; ; ) {
745 while (isspace(*cp))
746 *cp++ = '\0';
747 if (!*cp)
748 break;
749 av[ac++] = cp;
750 while (*++cp && !isspace(*cp))
751 ;
752 }
753 av[ac] = NULL;
754 if (xf(&oxf, ac, av) != ac ||
755 fabs(oxf.sca) <= FTINY) {
756 sprintf(errmsg, "bad transform args: %s",
757 om->xfs);
758 error(USER, errmsg);
759 }
760 copymat4(om->xfm, oxf.xfm);
761 if (om->prio_file[0]) {
762 fp = fopen(om->prio_file, "r");
763 if (fp == NULL) {
764 sprintf(errmsg,
765 "cannot open priority file '%s'",
766 om->prio_file);
767 error(SYSTEM, errmsg);
768 }
769 for (i = 0; i < n; i++)
770 if (fgets(abuf, sizeof(abuf), fp)
771 == NULL) {
772 sprintf(errmsg,
773 "too few priorities in file '%s'",
774 om->prio_file);
775 error(USER, errmsg);
776 }
777 fclose(fp);
778 cp = fskip(abuf);
779 if (cp != NULL)
780 while (isspace(*cp))
781 *cp++ = '\0';
782 if (cp == NULL || *cp) {
783 sprintf(errmsg,
784 "priority '%s' in file '%s' not a number",
785 abuf, om->prio_file);
786 error(USER, errmsg);
787 }
788 om->prio = atof(abuf);
789 }
790 framestep = (n == om->cfm + 1);
791 om->cfm = n;
792 }
793 /* prepend to parent transform */
794 if (om->xfs[0]) {
795 i = strlen(om->xfs);
796 if (xfp - i <= xfsbuf)
797 error(INTERNAL, "transform too long in getxf");
798 cp = om->xfs + i;
799 while (i--)
800 *--xfp = *--cp;
801 *--xfp = ' ';
802 }
803 if (framestep)
804 copymat4(oxf.xfm, om->cxfm);
805 if (om->parent >= 0) {
806 multmat4(om->cxfm, om->xfm, obj_move[om->parent].cxfm);
807 om->cprio = obj_move[om->parent].cprio * om->prio;
808 } else {
809 copymat4(om->cxfm, om->xfm);
810 om->cprio = om->prio;
811 }
812 /* XXX bxfm relies on call order */
813 if (framestep)
814 if (invmat4(om->bxfm, om->cxfm))
815 multmat4(om->bxfm, om->bxfm, oxf.xfm);
816 else
817 setident4(om->bxfm);
818 /* all done */
819 return(xfp);
820 }
821
822
823 int
824 getmove(obj) /* find matching move object */
825 OBJECT obj;
826 {
827 static int lasti;
828 static OBJECT lasto = OVOID;
829 char *onm, *objnm;
830 int len, len2;
831 register int i;
832
833 if (obj == OVOID)
834 return(-1);
835 if (obj == lasto)
836 return(lasti);
837 /* look for matching object */
838 onm = objptr(obj)->oname;
839 for (i = vdef(MOVE); i--; ) {
840 objnm = obj_move[i].name;
841 len = strlen(objnm);
842 if (!strncmp(onm, objnm, len)) {
843 if ((obj_move[i].parent < 0 & onm[len] == '.'))
844 break;
845 objnm = getobjname(&obj_move[i]) + len;
846 len2 = strlen(objnm);
847 if (!strncmp(onm+len, objnm, len2) && onm[len+len2] == '.')
848 break;
849 }
850 }
851 lasto = obj; /* cache what we found */
852 return(lasti = i);
853 }
854
855
856 double
857 obj_prio(obj) /* return priority for object */
858 OBJECT obj;
859 {
860 int moi;
861
862 if (obj == OVOID || (moi = getmove(obj)) < 0)
863 return(1.0);
864 return(obj_move[moi].cprio);
865 }
866
867
868 double
869 getTime() /* get current time (CPU or real) */
870 {
871 struct timeval time_now;
872 /* return CPU time if one process */
873 if (nprocs == 1)
874 return((double)clock()*(1.0/(double)CLOCKS_PER_SEC));
875 /* otherwise, return wall time */
876 gettimeofday(&time_now, NULL);
877 return((double)time_now.tv_sec + 1e-6*(double)time_now.tv_usec);
878 }