| 1 | greg | 2.1 | #ifndef lint | 
| 2 | greg | 2.49 | static const char RCSid[] = "$Id: ranimate.c,v 2.48 2005/01/18 03:59:41 greg Exp $"; | 
| 3 | greg | 2.1 | #endif | 
| 4 |  |  | /* | 
| 5 |  |  | * Radiance animation control program | 
| 6 | greg | 2.29 | * | 
| 7 |  |  | * The main difference between this program and ranimove is that | 
| 8 |  |  | * we have many optimizations here for camera motion in static | 
| 9 |  |  | * environments, calling rpict and pinterp on multiple processors, | 
| 10 |  |  | * where ranimove puts its emphasis on object motion, and does | 
| 11 |  |  | * not use any external programs for image generation. | 
| 12 |  |  | * | 
| 13 |  |  | * See the ranimate(1) man page for further details. | 
| 14 |  |  | */ | 
| 15 |  |  |  | 
| 16 | greg | 2.31 | #include "copyright.h" | 
| 17 | greg | 2.1 |  | 
| 18 | schorsch | 2.43 | #include <stdio.h> | 
| 19 | greg | 2.2 | #include <ctype.h> | 
| 20 | greg | 2.1 | #include <sys/stat.h> | 
| 21 | schorsch | 2.43 | #include <time.h> | 
| 22 | schorsch | 2.46 | #include <signal.h> | 
| 23 | schorsch | 2.39 |  | 
| 24 | schorsch | 2.43 | #include "platform.h" | 
| 25 | schorsch | 2.39 | #include "paths.h" | 
| 26 | greg | 2.47 | #include "standard.h" | 
| 27 | greg | 2.1 | #include "view.h" | 
| 28 |  |  | #include "vars.h" | 
| 29 | greg | 2.2 | #include "netproc.h" | 
| 30 | greg | 2.29 | /* default blur samples */ | 
| 31 |  |  | #ifndef DEF_NBLUR | 
| 32 |  |  | #define DEF_NBLUR       5 | 
| 33 |  |  | #endif | 
| 34 | greg | 2.10 | /* default remote shell */ | 
| 35 | greg | 2.49 | #ifndef REMSH | 
| 36 |  |  | #define REMSH           "ssh" | 
| 37 |  |  | #endif | 
| 38 | gwlarson | 2.27 | /* input variables (alphabetical by name) */ | 
| 39 |  |  | #define ANIMATE         0               /* animation command */ | 
| 40 |  |  | #define ARCHIVE         1               /* archiving command */ | 
| 41 |  |  | #define BASENAME        2               /* output image base name */ | 
| 42 | greg | 2.48 | #define DBLUR           3               /* depth of field blur */ | 
| 43 |  |  | #define DIRECTORY       4               /* working (sub)directory */ | 
| 44 |  |  | #define DISKSPACE       5               /* how much disk space to use */ | 
| 45 |  |  | #define END             6               /* ending frame number */ | 
| 46 |  |  | #define EXPOSURE        7               /* how to compute exposure */ | 
| 47 |  |  | #define HOST            8               /* rendering host machine */ | 
| 48 |  |  | #define INTERP          9               /* # frames to interpolate */ | 
| 49 |  |  | #define MBLUR           10              /* motion blur parameters */ | 
| 50 |  |  | #define NEXTANIM        11              /* next animation file */ | 
| 51 |  |  | #define OCTREE          12              /* octree file name */ | 
| 52 |  |  | #define OVERSAMP        13              /* # times to oversample image */ | 
| 53 |  |  | #define PFILT           14              /* pfilt options */ | 
| 54 |  |  | #define PINTERP         15              /* pinterp options */ | 
| 55 |  |  | #define RENDER          16              /* rendering options */ | 
| 56 |  |  | #define RESOLUTION      17              /* desired final resolution */ | 
| 57 |  |  | #define RIF             18              /* rad input file */ | 
| 58 |  |  | #define RSH             19              /* remote shell script or program */ | 
| 59 |  |  | #define RTRACE          20              /* use rtrace with pinterp? */ | 
| 60 |  |  | #define START           21              /* starting frame number */ | 
| 61 |  |  | #define TRANSFER        22              /* frame transfer command */ | 
| 62 |  |  | #define VIEWFILE        23              /* animation frame views */ | 
| 63 | greg | 2.1 |  | 
| 64 | greg | 2.48 | int     NVARS = 24;             /* total number of variables */ | 
| 65 | greg | 2.1 |  | 
| 66 |  |  | VARIABLE        vv[] = {                /* variable-value pairs */ | 
| 67 | gwlarson | 2.27 | {"ANIMATE",     2,      0,      NULL,   onevalue}, | 
| 68 |  |  | {"ARCHIVE",     2,      0,      NULL,   onevalue}, | 
| 69 |  |  | {"BASENAME",    3,      0,      NULL,   onevalue}, | 
| 70 | greg | 2.48 | {"DBLUR",       2,      0,      NULL,   onevalue}, | 
| 71 | greg | 2.1 | {"DIRECTORY",   3,      0,      NULL,   onevalue}, | 
| 72 | gwlarson | 2.27 | {"DISKSPACE",   3,      0,      NULL,   fltvalue}, | 
| 73 | greg | 2.1 | {"END",         2,      0,      NULL,   intvalue}, | 
| 74 | gwlarson | 2.27 | {"EXPOSURE",    3,      0,      NULL,   onevalue}, | 
| 75 |  |  | {"host",        4,      0,      NULL,   NULL}, | 
| 76 |  |  | {"INTERPOLATE", 3,      0,      NULL,   intvalue}, | 
| 77 |  |  | {"MBLUR",       2,      0,      NULL,   onevalue}, | 
| 78 | greg | 2.1 | {"NEXTANIM",    3,      0,      NULL,   onevalue}, | 
| 79 | gwlarson | 2.27 | {"OCTREE",      3,      0,      NULL,   onevalue}, | 
| 80 | greg | 2.5 | {"OVERSAMPLE",  2,      0,      NULL,   fltvalue}, | 
| 81 | gwlarson | 2.27 | {"pfilt",       2,      0,      NULL,   catvalues}, | 
| 82 |  |  | {"pinterp",     2,      0,      NULL,   catvalues}, | 
| 83 |  |  | {"render",      3,      0,      NULL,   catvalues}, | 
| 84 | greg | 2.1 | {"RESOLUTION",  3,      0,      NULL,   onevalue}, | 
| 85 | gwlarson | 2.27 | {"RIF",         3,      0,      NULL,   onevalue}, | 
| 86 | greg | 2.10 | {"RSH",         3,      0,      NULL,   onevalue}, | 
| 87 | gwlarson | 2.27 | {"RTRACE",      2,      0,      NULL,   boolvalue}, | 
| 88 |  |  | {"START",       2,      0,      NULL,   intvalue}, | 
| 89 |  |  | {"TRANSFER",    2,      0,      NULL,   onevalue}, | 
| 90 |  |  | {"VIEWFILE",    2,      0,      NULL,   onevalue}, | 
| 91 | greg | 2.1 | }; | 
| 92 |  |  |  | 
| 93 |  |  | #define SFNAME  "STATUS"                /* status file name */ | 
| 94 |  |  |  | 
| 95 |  |  | struct { | 
| 96 |  |  | char    host[64];               /* control host name */ | 
| 97 |  |  | int     pid;                    /* control process id */ | 
| 98 |  |  | char    cfname[128];            /* control file name */ | 
| 99 |  |  | int     rnext;                  /* next frame to render */ | 
| 100 |  |  | int     fnext;                  /* next frame to filter */ | 
| 101 |  |  | int     tnext;                  /* next frame to transfer */ | 
| 102 |  |  | }       astat;                  /* animation status */ | 
| 103 |  |  |  | 
| 104 |  |  | char    *progname;              /* our program name */ | 
| 105 |  |  | char    *cfname;                /* our control file name */ | 
| 106 |  |  |  | 
| 107 |  |  | int     nowarn = 0;             /* turn warnings off? */ | 
| 108 |  |  | int     silent = 0;             /* silent mode? */ | 
| 109 |  |  | int     noaction = 0;           /* take no action? */ | 
| 110 |  |  |  | 
| 111 | greg | 2.10 | char    *remsh;                 /* remote shell program/script */ | 
| 112 | greg | 2.21 | char    rendopt[2048];          /* rendering options */ | 
| 113 | greg | 2.1 | char    rresopt[32];            /* rendering resolution options */ | 
| 114 |  |  | char    fresopt[32];            /* filter resolution options */ | 
| 115 |  |  | int     pfiltalways;            /* always use pfilt? */ | 
| 116 |  |  |  | 
| 117 | greg | 2.7 | char    arcargs[10240];         /* files to archive */ | 
| 118 |  |  | char    *arcfirst, *arcnext;    /* pointers to first and next argument */ | 
| 119 |  |  |  | 
| 120 | greg | 2.2 | struct pslot { | 
| 121 |  |  | int     pid;                    /* process ID (0 if empty) */ | 
| 122 |  |  | int     fout;                   /* output frame number */ | 
| 123 |  |  | int     (*rcvf)();              /* recover function */ | 
| 124 |  |  | }       *pslot;                 /* process slots */ | 
| 125 |  |  | int     npslots;                /* number of process slots */ | 
| 126 |  |  |  | 
| 127 | greg | 2.4 | #define phostname(ps)   ((ps)->hostname[0] ? (ps)->hostname : astat.host) | 
| 128 | greg | 2.18 | PSERVER *lastpserver;           /* last process server with error */ | 
| 129 |  |  |  | 
| 130 | schorsch | 2.43 | static struct pslot * findpslot(int pid); | 
| 131 |  |  | static void checkdir(void); | 
| 132 |  |  | static VIEW * getview(int n); | 
| 133 |  |  |  | 
| 134 |  |  | static char * dirfile(char *df, register char *path); | 
| 135 |  |  | static char * getexp(int n); | 
| 136 | greg | 2.48 | static int getblur(double *mbf, double *dbf); | 
| 137 | schorsch | 2.43 | static int getastat(void); | 
| 138 |  |  | static void getradfile(char *rfargs); | 
| 139 |  |  | static void badvalue(int vc); | 
| 140 |  |  | static int rmfile(char *fn); | 
| 141 |  |  | static int runcom(char *cs); | 
| 142 |  |  | static int pruncom(char *com, char *ppins, int maxcopies); | 
| 143 |  |  | static void bwait(int ncoms); | 
| 144 |  |  | static int bruncom(char *com, int fout, int (*rf)()); | 
| 145 |  |  | static int serverdown(void); | 
| 146 | schorsch | 2.46 | static pscompfunc donecom; | 
| 147 | schorsch | 2.43 | static int countviews(void); | 
| 148 |  |  | static int dofilt(int frame, int rvr); | 
| 149 |  |  | static void archive(void); | 
| 150 |  |  | static int frecover(int frame); | 
| 151 |  |  | static int recover(int frame); | 
| 152 |  |  | static void sethosts(void); | 
| 153 |  |  | static void walkwait(int first, int last, char *vfn); | 
| 154 |  |  | static void animrend(int frame, VIEW *vp); | 
| 155 |  |  | static void transferframes(void); | 
| 156 |  |  | static void filterframes(void); | 
| 157 |  |  | static void renderframes(int nframes); | 
| 158 |  |  | static void animate(void); | 
| 159 |  |  | static void setdefaults(void); | 
| 160 |  |  | static void putastat(void); | 
| 161 | greg | 2.1 |  | 
| 162 | greg | 2.12 |  | 
| 163 | schorsch | 2.46 | int | 
| 164 |  |  | main( | 
| 165 |  |  | int     argc, | 
| 166 |  |  | char    *argv[] | 
| 167 |  |  | ) | 
| 168 | greg | 2.1 | { | 
| 169 |  |  | int     explicate = 0; | 
| 170 |  |  | int     i; | 
| 171 |  |  |  | 
| 172 |  |  | progname = argv[0];                     /* get arguments */ | 
| 173 |  |  | for (i = 1; i < argc && argv[i][0] == '-'; i++) | 
| 174 |  |  | switch (argv[i][1]) { | 
| 175 |  |  | case 'e':                       /* print variables */ | 
| 176 |  |  | explicate++; | 
| 177 |  |  | break; | 
| 178 |  |  | case 'w':                       /* turn off warnings */ | 
| 179 |  |  | nowarn++; | 
| 180 |  |  | break; | 
| 181 |  |  | case 's':                       /* silent mode */ | 
| 182 |  |  | silent++; | 
| 183 |  |  | break; | 
| 184 |  |  | case 'n':                       /* take no action */ | 
| 185 |  |  | noaction++; | 
| 186 |  |  | break; | 
| 187 |  |  | default: | 
| 188 |  |  | goto userr; | 
| 189 |  |  | } | 
| 190 |  |  | if (i != argc-1) | 
| 191 |  |  | goto userr; | 
| 192 |  |  | cfname = argv[i]; | 
| 193 |  |  | /* load variables */ | 
| 194 |  |  | loadvars(cfname); | 
| 195 | greg | 2.22 | /* check variables */ | 
| 196 |  |  | checkvalues(); | 
| 197 | greg | 2.1 | /* did we get DIRECTORY? */ | 
| 198 |  |  | checkdir(); | 
| 199 |  |  | /* check status */ | 
| 200 |  |  | if (getastat() < 0) { | 
| 201 |  |  | fprintf(stderr, "%s: exiting\n", progname); | 
| 202 |  |  | quit(1); | 
| 203 |  |  | } | 
| 204 |  |  | /* pfilt always if options given */ | 
| 205 |  |  | pfiltalways = vdef(PFILT); | 
| 206 |  |  | /* load RIF if any */ | 
| 207 |  |  | if (vdef(RIF)) | 
| 208 |  |  | getradfile(vval(RIF)); | 
| 209 |  |  | /* set defaults */ | 
| 210 |  |  | setdefaults(); | 
| 211 |  |  | /* print variables */ | 
| 212 |  |  | if (explicate) | 
| 213 |  |  | printvars(stdout); | 
| 214 | greg | 2.2 | /* set up process servers */ | 
| 215 |  |  | sethosts(); | 
| 216 | greg | 2.1 | /* run animation */ | 
| 217 |  |  | animate(); | 
| 218 |  |  | /* all done */ | 
| 219 |  |  | if (vdef(NEXTANIM)) { | 
| 220 |  |  | argv[i] = vval(NEXTANIM);       /* just change input file */ | 
| 221 |  |  | if (!silent) | 
| 222 |  |  | printargs(argc, argv, stdout); | 
| 223 | greg | 2.11 | if ((argv[0] = getpath(progname,getenv("PATH"),X_OK)) == NULL) | 
| 224 |  |  | fprintf(stderr, "%s: command not found\n", progname); | 
| 225 |  |  | else | 
| 226 |  |  | execv(progname, argv); | 
| 227 |  |  | quit(1); | 
| 228 | greg | 2.1 | } | 
| 229 |  |  | quit(0); | 
| 230 | schorsch | 2.46 | return 0; /* pro forma return */ | 
| 231 | greg | 2.1 | userr: | 
| 232 |  |  | fprintf(stderr, "Usage: %s [-s][-n][-w][-e] anim_file\n", progname); | 
| 233 |  |  | quit(1); | 
| 234 | schorsch | 2.46 | return 1; /* pro forma return */ | 
| 235 | greg | 2.1 | } | 
| 236 |  |  |  | 
| 237 |  |  |  | 
| 238 | schorsch | 2.43 | static int | 
| 239 |  |  | getastat(void)                  /* check/set animation status */ | 
| 240 | greg | 2.1 | { | 
| 241 | greg | 2.12 | char    sfname[256]; | 
| 242 | greg | 2.1 | FILE    *fp; | 
| 243 |  |  |  | 
| 244 | greg | 2.12 | sprintf(sfname, "%s/%s", vval(DIRECTORY), SFNAME); | 
| 245 |  |  | if ((fp = fopen(sfname, "r")) == NULL) { | 
| 246 | greg | 2.1 | if (errno != ENOENT) { | 
| 247 | greg | 2.12 | perror(sfname); | 
| 248 | greg | 2.1 | return(-1); | 
| 249 |  |  | } | 
| 250 |  |  | astat.rnext = astat.fnext = astat.tnext = 0; | 
| 251 |  |  | goto setours; | 
| 252 |  |  | } | 
| 253 |  |  | if (fscanf(fp, "Control host: %s\n", astat.host) != 1) | 
| 254 |  |  | goto fmterr; | 
| 255 |  |  | if (fscanf(fp, "Control PID: %d\n", &astat.pid) != 1) | 
| 256 |  |  | goto fmterr; | 
| 257 |  |  | if (fscanf(fp, "Control file: %s\n", astat.cfname) != 1) | 
| 258 |  |  | goto fmterr; | 
| 259 |  |  | if (fscanf(fp, "Next render: %d\n", &astat.rnext) != 1) | 
| 260 |  |  | goto fmterr; | 
| 261 |  |  | if (fscanf(fp, "Next filter: %d\n", &astat.fnext) != 1) | 
| 262 |  |  | goto fmterr; | 
| 263 |  |  | if (fscanf(fp, "Next transfer: %d\n", &astat.tnext) != 1) | 
| 264 |  |  | goto fmterr; | 
| 265 |  |  | fclose(fp); | 
| 266 |  |  | if (astat.pid != 0) {                   /* thinks it's still running */ | 
| 267 | greg | 2.9 | if (strcmp(myhostname(), astat.host)) { | 
| 268 | greg | 2.1 | fprintf(stderr, | 
| 269 |  |  | "%s: process %d may still be running on host %s\n", | 
| 270 |  |  | progname, astat.pid, astat.host); | 
| 271 |  |  | return(-1); | 
| 272 |  |  | } | 
| 273 |  |  | if (kill(astat.pid, 0) != -1 || errno != ESRCH) { | 
| 274 |  |  | fprintf(stderr, "%s: process %d is still running\n", | 
| 275 |  |  | progname, astat.pid); | 
| 276 |  |  | return(-1); | 
| 277 |  |  | } | 
| 278 |  |  | /* assume it is dead */ | 
| 279 |  |  | } | 
| 280 | greg | 2.20 | if (strcmp(cfname, astat.cfname) && astat.pid != 0) {   /* other's */ | 
| 281 | greg | 2.1 | fprintf(stderr, "%s: unfinished job \"%s\"\n", | 
| 282 |  |  | progname, astat.cfname); | 
| 283 |  |  | return(-1); | 
| 284 |  |  | } | 
| 285 | greg | 2.12 | /* check control file mods. */ | 
| 286 |  |  | if (!nowarn && fdate(cfname) > fdate(sfname)) | 
| 287 |  |  | fprintf(stderr, | 
| 288 |  |  | "%s: warning - control file modified since last run\n", | 
| 289 |  |  | progname); | 
| 290 | greg | 2.1 | setours:                                        /* set our values */ | 
| 291 | greg | 2.9 | strcpy(astat.host, myhostname()); | 
| 292 | greg | 2.1 | astat.pid = getpid(); | 
| 293 |  |  | strcpy(astat.cfname, cfname); | 
| 294 |  |  | return(0); | 
| 295 |  |  | fmterr: | 
| 296 |  |  | fprintf(stderr, "%s: format error in status file \"%s\"\n", | 
| 297 | greg | 2.12 | progname, sfname); | 
| 298 | greg | 2.1 | fclose(fp); | 
| 299 |  |  | return(-1); | 
| 300 |  |  | } | 
| 301 |  |  |  | 
| 302 |  |  |  | 
| 303 | schorsch | 2.43 | static void | 
| 304 |  |  | putastat(void)                  /* put out current status */ | 
| 305 | greg | 2.1 | { | 
| 306 |  |  | char    buf[256]; | 
| 307 |  |  | FILE    *fp; | 
| 308 |  |  |  | 
| 309 | greg | 2.2 | if (noaction) | 
| 310 |  |  | return; | 
| 311 | greg | 2.1 | sprintf(buf, "%s/%s", vval(DIRECTORY), SFNAME); | 
| 312 |  |  | if ((fp = fopen(buf, "w")) == NULL) { | 
| 313 |  |  | perror(buf); | 
| 314 |  |  | quit(1); | 
| 315 |  |  | } | 
| 316 |  |  | fprintf(fp, "Control host: %s\n", astat.host); | 
| 317 |  |  | fprintf(fp, "Control PID: %d\n", astat.pid); | 
| 318 |  |  | fprintf(fp, "Control file: %s\n", astat.cfname); | 
| 319 |  |  | fprintf(fp, "Next render: %d\n", astat.rnext); | 
| 320 |  |  | fprintf(fp, "Next filter: %d\n", astat.fnext); | 
| 321 |  |  | fprintf(fp, "Next transfer: %d\n", astat.tnext); | 
| 322 |  |  | fclose(fp); | 
| 323 |  |  | } | 
| 324 |  |  |  | 
| 325 |  |  |  | 
| 326 | schorsch | 2.43 | static void | 
| 327 |  |  | checkdir(void)                  /* make sure we have our directory */ | 
| 328 | greg | 2.1 | { | 
| 329 |  |  | struct stat     stb; | 
| 330 |  |  |  | 
| 331 |  |  | if (!vdef(DIRECTORY)) { | 
| 332 |  |  | fprintf(stderr, "%s: %s undefined\n", | 
| 333 |  |  | progname, vnam(DIRECTORY)); | 
| 334 |  |  | quit(1); | 
| 335 |  |  | } | 
| 336 |  |  | if (stat(vval(DIRECTORY), &stb) == -1) { | 
| 337 |  |  | if (errno == ENOENT && mkdir(vval(DIRECTORY), 0777) == 0) | 
| 338 |  |  | return; | 
| 339 |  |  | perror(vval(DIRECTORY)); | 
| 340 |  |  | quit(1); | 
| 341 |  |  | } | 
| 342 |  |  | if (!(stb.st_mode & S_IFDIR)) { | 
| 343 |  |  | fprintf(stderr, "%s: not a directory\n", vval(DIRECTORY)); | 
| 344 |  |  | quit(1); | 
| 345 |  |  | } | 
| 346 |  |  | } | 
| 347 |  |  |  | 
| 348 |  |  |  | 
| 349 | schorsch | 2.43 | static void | 
| 350 |  |  | setdefaults(void)                       /* set default values */ | 
| 351 | greg | 2.1 | { | 
| 352 | greg | 2.10 | extern char     *atos(); | 
| 353 | greg | 2.19 | int     decades; | 
| 354 | greg | 2.1 | char    buf[256]; | 
| 355 |  |  |  | 
| 356 | greg | 2.2 | if (vdef(ANIMATE)) { | 
| 357 |  |  | vval(OCTREE) = NULL; | 
| 358 |  |  | vdef(OCTREE) = 0; | 
| 359 |  |  | } else if (!vdef(OCTREE)) { | 
| 360 | greg | 2.1 | fprintf(stderr, "%s: either %s or %s must be defined\n", | 
| 361 |  |  | progname, vnam(OCTREE), vnam(ANIMATE)); | 
| 362 |  |  | quit(1); | 
| 363 |  |  | } | 
| 364 |  |  | if (!vdef(VIEWFILE)) { | 
| 365 |  |  | fprintf(stderr, "%s: %s undefined\n", progname, vnam(VIEWFILE)); | 
| 366 |  |  | quit(1); | 
| 367 |  |  | } | 
| 368 | greg | 2.2 | if (!vdef(HOST)) { | 
| 369 |  |  | vval(HOST) = LHOSTNAME; | 
| 370 |  |  | vdef(HOST)++; | 
| 371 |  |  | } | 
| 372 | greg | 2.1 | if (!vdef(START)) { | 
| 373 |  |  | vval(START) = "1"; | 
| 374 |  |  | vdef(START)++; | 
| 375 |  |  | } | 
| 376 |  |  | if (!vdef(END)) { | 
| 377 | greg | 2.5 | sprintf(buf, "%d", countviews()+vint(START)-1); | 
| 378 | greg | 2.1 | vval(END) = savqstr(buf); | 
| 379 |  |  | vdef(END)++; | 
| 380 |  |  | } | 
| 381 | greg | 2.5 | if (vint(END) < vint(START)) { | 
| 382 |  |  | fprintf(stderr, "%s: ending frame less than starting frame\n", | 
| 383 |  |  | progname); | 
| 384 |  |  | quit(1); | 
| 385 |  |  | } | 
| 386 | greg | 2.1 | if (!vdef(BASENAME)) { | 
| 387 | greg | 2.19 | decades = (int)log10((double)vint(END)) + 1; | 
| 388 |  |  | if (decades < 3) decades = 3; | 
| 389 |  |  | sprintf(buf, "%s/frame%%0%dd", vval(DIRECTORY), decades); | 
| 390 | greg | 2.1 | vval(BASENAME) = savqstr(buf); | 
| 391 |  |  | vdef(BASENAME)++; | 
| 392 |  |  | } | 
| 393 |  |  | if (!vdef(RESOLUTION)) { | 
| 394 |  |  | vval(RESOLUTION) = "640"; | 
| 395 |  |  | vdef(RESOLUTION)++; | 
| 396 |  |  | } | 
| 397 |  |  | if (!vdef(OVERSAMP)) { | 
| 398 |  |  | vval(OVERSAMP) = "2"; | 
| 399 |  |  | vdef(OVERSAMP)++; | 
| 400 |  |  | } | 
| 401 |  |  | if (!vdef(INTERP)) { | 
| 402 |  |  | vval(INTERP) = "0"; | 
| 403 |  |  | vdef(INTERP)++; | 
| 404 |  |  | } | 
| 405 |  |  | if (!vdef(MBLUR)) { | 
| 406 |  |  | vval(MBLUR) = "0"; | 
| 407 |  |  | vdef(MBLUR)++; | 
| 408 |  |  | } | 
| 409 |  |  | if (!vdef(RTRACE)) { | 
| 410 |  |  | vval(RTRACE) = "F"; | 
| 411 |  |  | vdef(RTRACE)++; | 
| 412 |  |  | } | 
| 413 |  |  | if (!vdef(DISKSPACE)) { | 
| 414 |  |  | if (!nowarn) | 
| 415 |  |  | fprintf(stderr, | 
| 416 |  |  | "%s: warning - no %s setting, assuming 100 Mbytes available\n", | 
| 417 |  |  | progname, vnam(DISKSPACE)); | 
| 418 |  |  | vval(DISKSPACE) = "100"; | 
| 419 |  |  | vdef(DISKSPACE)++; | 
| 420 |  |  | } | 
| 421 | greg | 2.10 | if (!vdef(RSH)) { | 
| 422 |  |  | vval(RSH) = REMSH; | 
| 423 |  |  | vdef(RSH)++; | 
| 424 |  |  | } | 
| 425 |  |  | /* locate remote shell program */ | 
| 426 |  |  | atos(buf, sizeof(buf), vval(RSH)); | 
| 427 |  |  | if ((remsh = getpath(buf, getenv("PATH"), X_OK)) != NULL) | 
| 428 |  |  | remsh = savqstr(remsh); | 
| 429 |  |  | else | 
| 430 |  |  | remsh = vval(RSH);      /* will generate error if used */ | 
| 431 |  |  |  | 
| 432 | greg | 2.1 | /* append rendering options */ | 
| 433 |  |  | if (vdef(RENDER)) | 
| 434 |  |  | sprintf(rendopt+strlen(rendopt), " %s", vval(RENDER)); | 
| 435 |  |  | } | 
| 436 |  |  |  | 
| 437 |  |  |  | 
| 438 | schorsch | 2.43 | static void | 
| 439 |  |  | sethosts(void)                  /* set up process servers */ | 
| 440 | greg | 2.2 | { | 
| 441 |  |  | extern char     *iskip(); | 
| 442 |  |  | char    buf[256], *dir, *uname; | 
| 443 |  |  | int     np; | 
| 444 |  |  | register char   *cp; | 
| 445 |  |  | int     i; | 
| 446 |  |  |  | 
| 447 |  |  | npslots = 0; | 
| 448 |  |  | if (noaction) | 
| 449 |  |  | return; | 
| 450 |  |  | for (i = 0; i < vdef(HOST); i++) {      /* add each host */ | 
| 451 |  |  | dir = uname = NULL; | 
| 452 |  |  | np = 1; | 
| 453 |  |  | strcpy(cp=buf, nvalue(HOST, i));        /* copy to buffer */ | 
| 454 |  |  | cp = sskip(cp);                         /* skip host name */ | 
| 455 |  |  | while (isspace(*cp)) | 
| 456 |  |  | *cp++ = '\0'; | 
| 457 |  |  | if (*cp) {                              /* has # processes? */ | 
| 458 |  |  | np = atoi(cp); | 
| 459 |  |  | if ((cp = iskip(cp)) == NULL || (*cp && !isspace(*cp))) | 
| 460 |  |  | badvalue(HOST); | 
| 461 |  |  | while (isspace(*cp)) | 
| 462 |  |  | cp++; | 
| 463 |  |  | if (*cp) {                      /* has directory? */ | 
| 464 |  |  | dir = cp; | 
| 465 |  |  | cp = sskip(cp);                 /* skip dir. */ | 
| 466 |  |  | while (isspace(*cp)) | 
| 467 |  |  | *cp++ = '\0'; | 
| 468 |  |  | if (*cp) {                      /* has user? */ | 
| 469 |  |  | uname = cp; | 
| 470 |  |  | if (*sskip(cp)) | 
| 471 |  |  | badvalue(HOST); | 
| 472 |  |  | } | 
| 473 |  |  | } | 
| 474 |  |  | } | 
| 475 |  |  | if (addpserver(buf, dir, uname, np) == NULL) { | 
| 476 |  |  | if (!nowarn) | 
| 477 |  |  | fprintf(stderr, | 
| 478 |  |  | "%s: cannot execute on host \"%s\"\n", | 
| 479 |  |  | progname, buf); | 
| 480 |  |  | } else | 
| 481 |  |  | npslots += np; | 
| 482 |  |  | } | 
| 483 |  |  | if (npslots == 0) { | 
| 484 |  |  | fprintf(stderr, "%s: no working process servers\n", progname); | 
| 485 |  |  | quit(1); | 
| 486 |  |  | } | 
| 487 |  |  | pslot = (struct pslot *)calloc(npslots, sizeof(struct pslot)); | 
| 488 |  |  | if (pslot == NULL) { | 
| 489 |  |  | perror("malloc"); | 
| 490 |  |  | quit(1); | 
| 491 |  |  | } | 
| 492 |  |  | } | 
| 493 |  |  |  | 
| 494 | schorsch | 2.43 | static void | 
| 495 |  |  | getradfile(char *rfargs)                /* run rad and get needed variables */ | 
| 496 | greg | 2.1 | { | 
| 497 |  |  | static short    mvar[] = {OCTREE,PFILT,RESOLUTION,EXPOSURE,-1}; | 
| 498 |  |  | char    combuf[256]; | 
| 499 |  |  | register int    i; | 
| 500 |  |  | register char   *cp; | 
| 501 | schorsch | 2.46 | char    *pippt = NULL; | 
| 502 | greg | 2.1 | /* create rad command */ | 
| 503 |  |  | sprintf(rendopt, " @%s/render.opt", vval(DIRECTORY)); | 
| 504 |  |  | sprintf(combuf, | 
| 505 |  |  | "rad -v 0 -s -e -w %s OPTFILE=%s | egrep '^[ \t]*(NOMATCH", | 
| 506 | greg | 2.7 | rfargs, rendopt+2); | 
| 507 | greg | 2.1 | cp = combuf; | 
| 508 | gregl | 2.23 | while (*cp) { | 
| 509 |  |  | if (*cp == '|') pippt = cp; | 
| 510 |  |  | cp++; | 
| 511 |  |  | }                               /* match unset variables */ | 
| 512 | greg | 2.1 | for (i = 0; mvar[i] >= 0; i++) | 
| 513 |  |  | if (!vdef(mvar[i])) { | 
| 514 |  |  | *cp++ = '|'; | 
| 515 |  |  | strcpy(cp, vnam(mvar[i])); | 
| 516 |  |  | while (*cp) cp++; | 
| 517 | gregl | 2.23 | pippt = NULL; | 
| 518 | greg | 2.1 | } | 
| 519 | gregl | 2.23 | if (pippt != NULL) | 
| 520 | schorsch | 2.39 | strcpy(pippt, "> " NULL_DEVICE);        /* nothing to match */ | 
| 521 | gregl | 2.23 | else { | 
| 522 |  |  | sprintf(cp, ")[ \t]*=' > %s/radset.var", vval(DIRECTORY)); | 
| 523 |  |  | cp += 11;               /* point to file name */ | 
| 524 |  |  | } | 
| 525 | gwlarson | 2.28 | system(combuf);                 /* ignore exit code */ | 
| 526 | gregl | 2.23 | if (pippt == NULL) {            /* load variables and remove file */ | 
| 527 |  |  | loadvars(cp); | 
| 528 |  |  | unlink(cp); | 
| 529 |  |  | } | 
| 530 | greg | 2.1 | } | 
| 531 |  |  |  | 
| 532 |  |  |  | 
| 533 | schorsch | 2.43 | static void | 
| 534 |  |  | animate(void)                   /* run animation */ | 
| 535 | greg | 2.1 | { | 
| 536 |  |  | int     xres, yres; | 
| 537 |  |  | float   pa, mult; | 
| 538 |  |  | int     frames_batch; | 
| 539 |  |  | register int    i; | 
| 540 |  |  | double  d1, d2; | 
| 541 |  |  | /* compute rpict resolution */ | 
| 542 |  |  | i = sscanf(vval(RESOLUTION), "%d %d %f", &xres, &yres, &pa); | 
| 543 |  |  | mult = vflt(OVERSAMP); | 
| 544 |  |  | if (i == 3) { | 
| 545 | greg | 2.16 | sprintf(rresopt, "-x %d -y %d -pa %.3f", (int)(mult*xres), | 
| 546 | greg | 2.1 | (int)(mult*yres), pa); | 
| 547 | greg | 2.16 | sprintf(fresopt, "-x %d -y %d -pa %.3f", xres, yres, pa); | 
| 548 | greg | 2.1 | } else if (i) { | 
| 549 |  |  | if (i == 1) yres = xres; | 
| 550 |  |  | sprintf(rresopt, "-x %d -y %d", (int)(mult*xres), | 
| 551 |  |  | (int)(mult*yres)); | 
| 552 |  |  | sprintf(fresopt, "-x %d -y %d -pa 1", xres, yres); | 
| 553 |  |  | } else | 
| 554 |  |  | badvalue(RESOLUTION); | 
| 555 |  |  | /* consistency checks */ | 
| 556 |  |  | if (vdef(ANIMATE)) { | 
| 557 |  |  | if (vint(INTERP)) { | 
| 558 |  |  | if (!nowarn) | 
| 559 |  |  | fprintf(stderr, | 
| 560 |  |  | "%s: resetting %s=0 for animation\n", | 
| 561 |  |  | progname, vnam(INTERP)); | 
| 562 |  |  | vval(INTERP) = "0"; | 
| 563 |  |  | } | 
| 564 | greg | 2.29 | if (strcmp(vval(MBLUR),"0")) {  /* can't handle this */ | 
| 565 | greg | 2.1 | if (!nowarn) | 
| 566 |  |  | fprintf(stderr, | 
| 567 |  |  | "%s: resetting %s=0 for animation\n", | 
| 568 |  |  | progname, vnam(MBLUR)); | 
| 569 |  |  | vval(MBLUR) = "0"; | 
| 570 |  |  | } | 
| 571 |  |  | } | 
| 572 |  |  | /* figure # frames per batch */ | 
| 573 |  |  | d1 = mult*xres*mult*yres*4;             /* space for orig. picture */ | 
| 574 | greg | 2.48 | if ((i=vint(INTERP)) || getblur(NULL, NULL) > 1) | 
| 575 | greg | 2.13 | d1 += mult*xres*mult*yres*sizeof(float);        /* Z-buffer */ | 
| 576 | greg | 2.1 | d2 = xres*yres*4;                       /* space for final picture */ | 
| 577 |  |  | frames_batch = (i+1)*(vflt(DISKSPACE)*1048576.-d1)/(d1+i*d2); | 
| 578 |  |  | if (frames_batch < i+2) { | 
| 579 |  |  | fprintf(stderr, "%s: insufficient disk space allocated\n", | 
| 580 |  |  | progname); | 
| 581 |  |  | quit(1); | 
| 582 |  |  | } | 
| 583 | greg | 2.7 | /* initialize archive argument list */ | 
| 584 | gwlarson | 2.25 | i = vdef(ARCHIVE) ? strlen(vval(ARCHIVE))+132 : 132; | 
| 585 | greg | 2.7 | arcnext = arcfirst = arcargs + i; | 
| 586 | greg | 2.1 | /* initialize status file */ | 
| 587 |  |  | if (astat.rnext == 0) | 
| 588 |  |  | astat.rnext = astat.fnext = astat.tnext = vint(START); | 
| 589 |  |  | putastat(); | 
| 590 |  |  | /* render in batches */ | 
| 591 | greg | 2.2 | while (astat.tnext <= vint(END)) { | 
| 592 | greg | 2.1 | renderframes(frames_batch); | 
| 593 |  |  | filterframes(); | 
| 594 |  |  | transferframes(); | 
| 595 |  |  | } | 
| 596 |  |  | /* mark status as finished */ | 
| 597 |  |  | astat.pid = 0; | 
| 598 |  |  | putastat(); | 
| 599 |  |  | /* close open files */ | 
| 600 |  |  | getview(0); | 
| 601 |  |  | getexp(0); | 
| 602 |  |  | } | 
| 603 |  |  |  | 
| 604 |  |  |  | 
| 605 | schorsch | 2.43 | static void | 
| 606 |  |  | renderframes(int nframes)               /* render next nframes frames */ | 
| 607 | greg | 2.1 | { | 
| 608 |  |  | static char     vendbuf[16]; | 
| 609 |  |  | VIEW    *vp; | 
| 610 |  |  | FILE    *fp = NULL; | 
| 611 |  |  | char    vfname[128]; | 
| 612 |  |  | int     lastframe; | 
| 613 |  |  | register int    i; | 
| 614 |  |  |  | 
| 615 |  |  | if (astat.tnext < astat.rnext)  /* other work to do first */ | 
| 616 |  |  | return; | 
| 617 |  |  | /* create batch view file */ | 
| 618 |  |  | if (!vdef(ANIMATE)) { | 
| 619 |  |  | sprintf(vfname, "%s/anim.vf", vval(DIRECTORY)); | 
| 620 |  |  | if ((fp = fopen(vfname, "w")) == NULL) { | 
| 621 |  |  | perror(vfname); | 
| 622 |  |  | quit(1); | 
| 623 |  |  | } | 
| 624 |  |  | } | 
| 625 |  |  | /* bound batch properly */ | 
| 626 |  |  | lastframe = astat.rnext + nframes - 1; | 
| 627 |  |  | if ((lastframe-1) % (vint(INTERP)+1))   /* need even interval */ | 
| 628 |  |  | lastframe += vint(INTERP)+1 - ((lastframe-1)%(vint(INTERP)+1)); | 
| 629 |  |  | if (lastframe > vint(END))              /* check for end */ | 
| 630 |  |  | lastframe = vint(END); | 
| 631 |  |  | /* render each view */ | 
| 632 |  |  | for (i = astat.rnext; i <= lastframe; i++) { | 
| 633 |  |  | if ((vp = getview(i)) == NULL) { | 
| 634 |  |  | if (!nowarn) | 
| 635 |  |  | fprintf(stderr, | 
| 636 |  |  | "%s: ran out of views before last frame\n", | 
| 637 |  |  | progname); | 
| 638 |  |  | sprintf(vval(END)=vendbuf, "%d", i-1); | 
| 639 |  |  | lastframe = i - 1; | 
| 640 |  |  | break; | 
| 641 |  |  | } | 
| 642 |  |  | if (vdef(ANIMATE))              /* animate frame */ | 
| 643 |  |  | animrend(i, vp); | 
| 644 |  |  | else {                          /* else record it */ | 
| 645 |  |  | fputs(VIEWSTR, fp); | 
| 646 |  |  | fprintview(vp, fp); | 
| 647 |  |  | putc('\n', fp); | 
| 648 |  |  | } | 
| 649 |  |  | } | 
| 650 |  |  | if (vdef(ANIMATE))              /* wait for renderings to finish */ | 
| 651 | greg | 2.2 | bwait(0); | 
| 652 | greg | 2.1 | else {                          /* else if walk-through */ | 
| 653 |  |  | fclose(fp);             /* close view file */ | 
| 654 |  |  | walkwait(astat.rnext, lastframe, vfname);       /* walk it */ | 
| 655 |  |  | unlink(vfname);         /* remove view file */ | 
| 656 |  |  | } | 
| 657 |  |  | astat.rnext = i;                /* update status */ | 
| 658 |  |  | putastat(); | 
| 659 |  |  | } | 
| 660 |  |  |  | 
| 661 |  |  |  | 
| 662 | schorsch | 2.43 | static void | 
| 663 |  |  | filterframes(void)                              /* catch up with filtering */ | 
| 664 | greg | 2.1 | { | 
| 665 |  |  | register int    i; | 
| 666 |  |  |  | 
| 667 |  |  | if (astat.tnext < astat.fnext)  /* other work to do first */ | 
| 668 |  |  | return; | 
| 669 |  |  | /* filter each view */ | 
| 670 | greg | 2.38 | for (i = astat.fnext; i < astat.rnext; i++) | 
| 671 |  |  | dofilt(i, 0); | 
| 672 |  |  |  | 
| 673 | greg | 2.2 | bwait(0);                       /* wait for filter processes */ | 
| 674 | greg | 2.7 | archive();                      /* archive originals */ | 
| 675 | greg | 2.1 | astat.fnext = i;                /* update status */ | 
| 676 |  |  | putastat(); | 
| 677 |  |  | } | 
| 678 |  |  |  | 
| 679 |  |  |  | 
| 680 | schorsch | 2.43 | static void | 
| 681 |  |  | transferframes(void)                    /* catch up with picture transfers */ | 
| 682 | greg | 2.1 | { | 
| 683 | gwlarson | 2.25 | char    combuf[10240], *fbase; | 
| 684 | greg | 2.1 | register char   *cp; | 
| 685 |  |  | register int    i; | 
| 686 |  |  |  | 
| 687 |  |  | if (astat.tnext >= astat.fnext) /* nothing to do, yet */ | 
| 688 |  |  | return; | 
| 689 |  |  | if (!vdef(TRANSFER)) {          /* no transfer function -- leave 'em */ | 
| 690 |  |  | astat.tnext = astat.fnext; | 
| 691 |  |  | putastat();             /* update status */ | 
| 692 |  |  | return; | 
| 693 |  |  | } | 
| 694 | gwlarson | 2.25 | strcpy(combuf, "cd ");          /* start transfer command */ | 
| 695 |  |  | fbase = dirfile(cp = combuf+3, vval(BASENAME)); | 
| 696 |  |  | if (*cp) { | 
| 697 |  |  | while (*++cp) ; | 
| 698 |  |  | *cp++ = ';'; *cp++ = ' '; | 
| 699 |  |  | } else | 
| 700 |  |  | cp = combuf; | 
| 701 |  |  | strcpy(cp, vval(TRANSFER)); | 
| 702 |  |  | while (*cp) cp++; | 
| 703 | greg | 2.1 | /* make argument list */ | 
| 704 |  |  | for (i = astat.tnext; i < astat.fnext; i++) { | 
| 705 |  |  | *cp++ = ' '; | 
| 706 | gwlarson | 2.25 | sprintf(cp, fbase, i); | 
| 707 | greg | 2.1 | while (*cp) cp++; | 
| 708 |  |  | strcpy(cp, ".pic"); | 
| 709 |  |  | cp += 4; | 
| 710 |  |  | } | 
| 711 |  |  | if (runcom(combuf)) {           /* transfer frames */ | 
| 712 |  |  | fprintf(stderr, "%s: error running transfer command\n", | 
| 713 |  |  | progname); | 
| 714 |  |  | quit(1); | 
| 715 |  |  | } | 
| 716 |  |  | astat.tnext = i;                /* update status */ | 
| 717 |  |  | putastat(); | 
| 718 |  |  | } | 
| 719 |  |  |  | 
| 720 |  |  |  | 
| 721 | schorsch | 2.43 | static void | 
| 722 |  |  | animrend(                       /* start animation frame */ | 
| 723 |  |  | int     frame, | 
| 724 |  |  | VIEW    *vp | 
| 725 |  |  | ) | 
| 726 | greg | 2.1 | { | 
| 727 |  |  | char    combuf[2048]; | 
| 728 |  |  | char    fname[128]; | 
| 729 |  |  |  | 
| 730 |  |  | sprintf(fname, vval(BASENAME), frame); | 
| 731 |  |  | strcat(fname, ".unf"); | 
| 732 |  |  | if (access(fname, F_OK) == 0) | 
| 733 |  |  | return; | 
| 734 | greg | 2.2 | sprintf(combuf, "%s %d | rpict%s%s -w0 %s > %s", vval(ANIMATE), frame, | 
| 735 | greg | 2.1 | rendopt, viewopt(vp), rresopt, fname); | 
| 736 | greg | 2.2 | bruncom(combuf, frame, recover);        /* run in background */ | 
| 737 | greg | 2.1 | } | 
| 738 |  |  |  | 
| 739 |  |  |  | 
| 740 | schorsch | 2.43 | static void | 
| 741 |  |  | walkwait(               /* walk-through frames */ | 
| 742 |  |  | int     first, | 
| 743 |  |  | int last, | 
| 744 |  |  | char    *vfn | 
| 745 |  |  | ) | 
| 746 | greg | 2.1 | { | 
| 747 | greg | 2.48 | double  mblurf, dblurf; | 
| 748 |  |  | int     nblur = getblur(&mblurf, &dblurf); | 
| 749 | greg | 2.1 | char    combuf[2048]; | 
| 750 | greg | 2.29 | register char   *inspoint; | 
| 751 | greg | 2.1 | register int    i; | 
| 752 |  |  |  | 
| 753 |  |  | if (!noaction && vint(INTERP))          /* create dummy frames */ | 
| 754 |  |  | for (i = first; i <= last; i++) | 
| 755 |  |  | if (i < vint(END) && (i-1) % (vint(INTERP)+1)) { | 
| 756 |  |  | sprintf(combuf, vval(BASENAME), i); | 
| 757 |  |  | strcat(combuf, ".unf"); | 
| 758 |  |  | close(open(combuf, O_RDONLY|O_CREAT, 0666)); | 
| 759 |  |  | } | 
| 760 |  |  | /* create command */ | 
| 761 | greg | 2.35 | sprintf(combuf, "rpict%s%s -w0", rendopt, | 
| 762 |  |  | viewopt(getview(first>1 ? first-1 : 1))); | 
| 763 | greg | 2.29 | inspoint = combuf; | 
| 764 |  |  | while (*inspoint) inspoint++; | 
| 765 |  |  | if (nblur) { | 
| 766 | greg | 2.48 | sprintf(inspoint, " -pm %.3f", mblurf/nblur); | 
| 767 |  |  | while (*inspoint) inspoint++; | 
| 768 |  |  | sprintf(inspoint, " -pd %.3f", dblurf/nblur); | 
| 769 | greg | 2.29 | while (*inspoint) inspoint++; | 
| 770 |  |  | } | 
| 771 |  |  | if (nblur > 1 || vint(INTERP)) { | 
| 772 |  |  | sprintf(inspoint, " -z %s.zbf", vval(BASENAME)); | 
| 773 |  |  | while (*inspoint) inspoint++; | 
| 774 |  |  | } | 
| 775 |  |  | sprintf(inspoint, " -o %s.unf %s -S %d", | 
| 776 | greg | 2.4 | vval(BASENAME), rresopt, first); | 
| 777 | greg | 2.29 | while (*inspoint) inspoint++; | 
| 778 | greg | 2.4 | sprintf(inspoint, " %s < %s", vval(OCTREE), vfn); | 
| 779 | greg | 2.2 | /* run in parallel */ | 
| 780 | greg | 2.7 | i = (last-first+1)/(vint(INTERP)+1); | 
| 781 |  |  | if (i < 1) i = 1; | 
| 782 |  |  | if (pruncom(combuf, inspoint, i)) { | 
| 783 | greg | 2.2 | fprintf(stderr, "%s: error rendering frames %d through %d\n", | 
| 784 | greg | 2.1 | progname, first, last); | 
| 785 |  |  | quit(1); | 
| 786 |  |  | } | 
| 787 |  |  | if (!noaction && vint(INTERP))          /* remove dummy frames */ | 
| 788 |  |  | for (i = first; i <= last; i++) | 
| 789 |  |  | if (i < vint(END) && (i-1) % (vint(INTERP)+1)) { | 
| 790 |  |  | sprintf(combuf, vval(BASENAME), i); | 
| 791 |  |  | strcat(combuf, ".unf"); | 
| 792 |  |  | unlink(combuf); | 
| 793 |  |  | } | 
| 794 |  |  | } | 
| 795 |  |  |  | 
| 796 |  |  |  | 
| 797 | schorsch | 2.43 | static int | 
| 798 | greg | 2.44 | recover(int frame)                      /* recover the specified frame */ | 
| 799 | greg | 2.1 | { | 
| 800 | greg | 2.2 | static int      *rfrm;          /* list of recovered frames */ | 
| 801 |  |  | static int      nrfrms = 0; | 
| 802 | greg | 2.48 | double  mblurf, dblurf; | 
| 803 |  |  | int     nblur = getblur(&mblurf, &dblurf); | 
| 804 | greg | 2.1 | char    combuf[2048]; | 
| 805 |  |  | char    fname[128]; | 
| 806 |  |  | register char   *cp; | 
| 807 | greg | 2.2 | register int    i; | 
| 808 |  |  | /* check to see if recovered already */ | 
| 809 |  |  | for (i = nrfrms; i--; ) | 
| 810 |  |  | if (rfrm[i] == frame) | 
| 811 |  |  | return(0); | 
| 812 |  |  | /* build command */ | 
| 813 | greg | 2.1 | sprintf(fname, vval(BASENAME), frame); | 
| 814 |  |  | if (vdef(ANIMATE)) | 
| 815 | greg | 2.2 | sprintf(combuf, "%s %d | rpict%s -w0", | 
| 816 | greg | 2.1 | vval(ANIMATE), frame, rendopt); | 
| 817 |  |  | else | 
| 818 | greg | 2.2 | sprintf(combuf, "rpict%s -w0", rendopt); | 
| 819 | greg | 2.29 | cp = combuf; | 
| 820 |  |  | while (*cp) cp++; | 
| 821 |  |  | if (nblur) { | 
| 822 | greg | 2.48 | sprintf(cp, " -pm %.3f", mblurf/nblur); | 
| 823 |  |  | while (*cp) cp++; | 
| 824 |  |  | sprintf(cp, " -pd %.3f", dblurf/nblur); | 
| 825 | greg | 2.29 | while (*cp) cp++; | 
| 826 |  |  | } | 
| 827 |  |  | if (nblur > 1 || vint(INTERP)) { | 
| 828 | greg | 2.1 | sprintf(cp, " -z %s.zbf", fname); | 
| 829 |  |  | while (*cp) cp++; | 
| 830 |  |  | } | 
| 831 |  |  | sprintf(cp, " -ro %s.unf", fname); | 
| 832 |  |  | while (*cp) cp++; | 
| 833 |  |  | if (!vdef(ANIMATE)) { | 
| 834 |  |  | *cp++ = ' '; | 
| 835 |  |  | strcpy(cp, vval(OCTREE)); | 
| 836 |  |  | } | 
| 837 | greg | 2.2 | if (runcom(combuf))             /* run command */ | 
| 838 |  |  | return(1); | 
| 839 |  |  | /* add frame to recovered list */ | 
| 840 |  |  | if (nrfrms) | 
| 841 | greg | 2.32 | rfrm = (int *)realloc((void *)rfrm, (nrfrms+1)*sizeof(int)); | 
| 842 | greg | 2.2 | else | 
| 843 |  |  | rfrm = (int *)malloc(sizeof(int)); | 
| 844 |  |  | if (rfrm == NULL) { | 
| 845 |  |  | perror("malloc"); | 
| 846 | greg | 2.1 | quit(1); | 
| 847 |  |  | } | 
| 848 | greg | 2.2 | rfrm[nrfrms++] = frame; | 
| 849 |  |  | return(0); | 
| 850 | greg | 2.1 | } | 
| 851 |  |  |  | 
| 852 |  |  |  | 
| 853 | schorsch | 2.43 | static int | 
| 854 |  |  | frecover(int frame)                             /* recover filtered frame */ | 
| 855 | greg | 2.2 | { | 
| 856 | greg | 2.38 | if (dofilt(frame, 2) && dofilt(frame, 1)) | 
| 857 | greg | 2.2 | return(1); | 
| 858 |  |  | return(0); | 
| 859 |  |  | } | 
| 860 |  |  |  | 
| 861 |  |  |  | 
| 862 | schorsch | 2.43 | static void | 
| 863 |  |  | archive(void)                   /* archive and remove renderings */ | 
| 864 | greg | 2.1 | { | 
| 865 | greg | 2.2 | #define RMCOML  (sizeof(rmcom)-1) | 
| 866 |  |  | static char     rmcom[] = "rm -f"; | 
| 867 | gwlarson | 2.25 | char    basedir[128]; | 
| 868 |  |  | int     dlen, alen; | 
| 869 |  |  | register int    j; | 
| 870 | greg | 2.1 |  | 
| 871 | greg | 2.7 | if (arcnext == arcfirst) | 
| 872 |  |  | return;                         /* nothing to do */ | 
| 873 | gwlarson | 2.25 | dirfile(basedir, vval(BASENAME)); | 
| 874 |  |  | dlen = strlen(basedir); | 
| 875 | greg | 2.2 | if (vdef(ARCHIVE)) {                    /* run archive command */ | 
| 876 | gwlarson | 2.25 | alen = strlen(vval(ARCHIVE)); | 
| 877 |  |  | if (dlen) { | 
| 878 |  |  | j = alen + dlen + 5; | 
| 879 |  |  | strncpy(arcfirst-j, "cd ", 3); | 
| 880 |  |  | strncpy(arcfirst-j+3, basedir, dlen); | 
| 881 |  |  | (arcfirst-j)[dlen+3] = ';'; (arcfirst-j)[dlen+4] = ' '; | 
| 882 |  |  | } else | 
| 883 |  |  | j = alen; | 
| 884 |  |  | strncpy(arcfirst-alen, vval(ARCHIVE), alen); | 
| 885 |  |  | if (runcom(arcfirst-j)) { | 
| 886 | greg | 2.7 | fprintf(stderr, "%s: error running archive command\n", | 
| 887 |  |  | progname); | 
| 888 | greg | 2.2 | quit(1); | 
| 889 |  |  | } | 
| 890 | greg | 2.1 | } | 
| 891 | gwlarson | 2.25 | if (dlen) { | 
| 892 |  |  | j = RMCOML + dlen + 5; | 
| 893 |  |  | strncpy(arcfirst-j, "cd ", 3); | 
| 894 |  |  | strncpy(arcfirst-j+3, basedir, dlen); | 
| 895 |  |  | (arcfirst-j)[dlen+3] = ';'; (arcfirst-j)[dlen+4] = ' '; | 
| 896 |  |  | } else | 
| 897 |  |  | j = RMCOML; | 
| 898 | greg | 2.2 | /* run remove command */ | 
| 899 | greg | 2.7 | strncpy(arcfirst-RMCOML, rmcom, RMCOML); | 
| 900 | gwlarson | 2.25 | runcom(arcfirst-j); | 
| 901 | greg | 2.7 | arcnext = arcfirst;                     /* reset argument list */ | 
| 902 | greg | 2.2 | #undef RMCOML | 
| 903 | greg | 2.1 | } | 
| 904 |  |  |  | 
| 905 |  |  |  | 
| 906 | schorsch | 2.43 | static int | 
| 907 |  |  | dofilt(                         /* filter frame */ | 
| 908 |  |  | int     frame, | 
| 909 |  |  | int     rvr | 
| 910 |  |  | ) | 
| 911 | greg | 2.1 | { | 
| 912 | greg | 2.6 | static int      iter = 0; | 
| 913 | greg | 2.48 | double  mblurf, dblurf; | 
| 914 |  |  | int     nblur = getblur(&mblurf, &dblurf); | 
| 915 | greg | 2.38 | VIEW    *vp = getview(frame); | 
| 916 |  |  | char    *ep = getexp(frame); | 
| 917 | gwlarson | 2.25 | char    fnbefore[128], fnafter[128], *fbase; | 
| 918 | greg | 2.6 | char    combuf[1024], fname0[128], fname1[128]; | 
| 919 | greg | 2.7 | int     usepinterp, usepfilt, nora_rgbe; | 
| 920 | greg | 2.2 | int     frseq[2]; | 
| 921 | greg | 2.1 | /* check what is needed */ | 
| 922 | greg | 2.38 | if (vp == NULL) { | 
| 923 |  |  | fprintf(stderr, | 
| 924 |  |  | "%s: unexpected error reading view for frame %d\n", | 
| 925 |  |  | progname, frame); | 
| 926 |  |  | quit(1); | 
| 927 |  |  | } | 
| 928 | greg | 2.29 | usepinterp = (nblur > 1); | 
| 929 | schorsch | 2.41 | usepfilt = pfiltalways | (ep==NULL); | 
| 930 | greg | 2.7 | if (ep != NULL && !strcmp(ep, "1")) | 
| 931 |  |  | ep = "+0"; | 
| 932 |  |  | nora_rgbe = strcmp(vval(OVERSAMP),"1") || ep==NULL || | 
| 933 |  |  | *ep != '+' || *ep != '-' || !isint(ep); | 
| 934 | greg | 2.1 | /* compute rendered views */ | 
| 935 | greg | 2.2 | frseq[0] = frame - ((frame-1) % (vint(INTERP)+1)); | 
| 936 |  |  | frseq[1] = frseq[0] + vint(INTERP) + 1; | 
| 937 | gwlarson | 2.25 | fbase = dirfile(NULL, vval(BASENAME)); | 
| 938 | greg | 2.2 | if (frseq[1] > vint(END)) | 
| 939 |  |  | frseq[1] = vint(END); | 
| 940 |  |  | if (frseq[1] == frame) {                        /* pfilt only */ | 
| 941 |  |  | frseq[0] = frseq[1]; | 
| 942 | greg | 2.1 | usepinterp = 0;                 /* update what's needed */ | 
| 943 | greg | 2.7 | usepfilt |= nora_rgbe; | 
| 944 |  |  | } else if (frseq[0] == frame) {         /* no interpolation needed */ | 
| 945 |  |  | if (!rvr && frame > 1+vint(INTERP)) {   /* archive previous */ | 
| 946 |  |  | *arcnext++ = ' '; | 
| 947 | gwlarson | 2.25 | sprintf(arcnext, fbase, frame-vint(INTERP)-1); | 
| 948 | greg | 2.7 | while (*arcnext) arcnext++; | 
| 949 |  |  | strcpy(arcnext, ".unf"); | 
| 950 |  |  | arcnext += 4; | 
| 951 | greg | 2.13 | if (usepinterp || vint(INTERP)) {       /* and Z-buf */ | 
| 952 | greg | 2.7 | *arcnext++ = ' '; | 
| 953 | gwlarson | 2.25 | sprintf(arcnext, fbase, frame-vint(INTERP)-1); | 
| 954 | greg | 2.7 | while (*arcnext) arcnext++; | 
| 955 |  |  | strcpy(arcnext, ".zbf"); | 
| 956 |  |  | arcnext += 4; | 
| 957 |  |  | } | 
| 958 |  |  | } | 
| 959 |  |  | if (!usepinterp)                /* update what's needed */ | 
| 960 |  |  | usepfilt |= nora_rgbe; | 
| 961 | greg | 2.2 | } else                                  /* interpolation needed */ | 
| 962 | greg | 2.1 | usepinterp++; | 
| 963 | greg | 2.2 | if (frseq[1] >= astat.rnext)            /* next batch unavailable */ | 
| 964 |  |  | frseq[1] = frseq[0]; | 
| 965 |  |  | sprintf(fnbefore, vval(BASENAME), frseq[0]); | 
| 966 |  |  | sprintf(fnafter, vval(BASENAME), frseq[1]); | 
| 967 |  |  | if (rvr == 1 && recover(frseq[0]))      /* recover before frame? */ | 
| 968 |  |  | return(1); | 
| 969 |  |  | /* generate command */ | 
| 970 | greg | 2.1 | if (usepinterp) {                       /* using pinterp */ | 
| 971 | greg | 2.2 | if (rvr == 2 && recover(frseq[1]))      /* recover after? */ | 
| 972 |  |  | return(1); | 
| 973 | greg | 2.48 | if (nblur > 1) {                /* with pdmblur */ | 
| 974 | greg | 2.6 | sprintf(fname0, "%s/vw0%c", vval(DIRECTORY), | 
| 975 |  |  | 'a'+(iter%26)); | 
| 976 |  |  | sprintf(fname1, "%s/vw1%c", vval(DIRECTORY), | 
| 977 |  |  | 'a'+(iter%26)); | 
| 978 | gwlarson | 2.25 | if (!noaction) { | 
| 979 |  |  | FILE    *fp;            /* motion blurring */ | 
| 980 |  |  | if ((fp = fopen(fname0, "w")) == NULL) { | 
| 981 |  |  | perror(fname0); quit(1); | 
| 982 |  |  | } | 
| 983 |  |  | fputs(VIEWSTR, fp); | 
| 984 |  |  | fprintview(vp, fp); | 
| 985 |  |  | putc('\n', fp); fclose(fp); | 
| 986 |  |  | if ((vp = getview(frame+1)) == NULL) { | 
| 987 |  |  | fprintf(stderr, | 
| 988 |  |  | "%s: unexpected error reading view for frame %d\n", | 
| 989 |  |  | progname, frame+1); | 
| 990 |  |  | quit(1); | 
| 991 |  |  | } | 
| 992 |  |  | if ((fp = fopen(fname1, "w")) == NULL) { | 
| 993 |  |  | perror(fname1); quit(1); | 
| 994 |  |  | } | 
| 995 |  |  | fputs(VIEWSTR, fp); | 
| 996 |  |  | fprintview(vp, fp); | 
| 997 |  |  | putc('\n', fp); fclose(fp); | 
| 998 | greg | 2.1 | } | 
| 999 |  |  | sprintf(combuf, | 
| 1000 | greg | 2.48 | "(pmdblur %.3f %.3f %d %s %s; rm -f %s %s) | pinterp -B -a", | 
| 1001 |  |  | mblurf, dblurf, nblur, | 
| 1002 | greg | 2.6 | fname0, fname1, fname0, fname1); | 
| 1003 |  |  | iter++; | 
| 1004 | greg | 2.1 | } else                          /* no blurring */ | 
| 1005 |  |  | strcpy(combuf, "pinterp"); | 
| 1006 |  |  | strcat(combuf, viewopt(vp)); | 
| 1007 |  |  | if (vbool(RTRACE)) | 
| 1008 | greg | 2.2 | sprintf(combuf+strlen(combuf), " -ff -fr '%s -w0 %s'", | 
| 1009 | greg | 2.21 | rendopt+1, vval(OCTREE)); | 
| 1010 | greg | 2.1 | if (vdef(PINTERP)) | 
| 1011 |  |  | sprintf(combuf+strlen(combuf), " %s", vval(PINTERP)); | 
| 1012 |  |  | if (usepfilt) | 
| 1013 |  |  | sprintf(combuf+strlen(combuf), " %s", rresopt); | 
| 1014 |  |  | else | 
| 1015 | greg | 2.33 | sprintf(combuf+strlen(combuf), " -a %s -e %s", | 
| 1016 | greg | 2.1 | fresopt, ep); | 
| 1017 |  |  | sprintf(combuf+strlen(combuf), " %s.unf %s.zbf", | 
| 1018 |  |  | fnbefore, fnbefore); | 
| 1019 | greg | 2.2 | if (frseq[1] != frseq[0]) | 
| 1020 | greg | 2.1 | sprintf(combuf+strlen(combuf), " %s.unf %s.zbf", | 
| 1021 |  |  | fnafter, fnafter); | 
| 1022 |  |  | if (usepfilt) {                 /* also pfilt */ | 
| 1023 |  |  | if (vdef(PFILT)) | 
| 1024 |  |  | sprintf(combuf+strlen(combuf), " | pfilt %s", | 
| 1025 |  |  | vval(PFILT)); | 
| 1026 |  |  | else | 
| 1027 |  |  | strcat(combuf, " | pfilt"); | 
| 1028 |  |  | if (ep != NULL) | 
| 1029 |  |  | sprintf(combuf+strlen(combuf), " -1 -e %s %s", | 
| 1030 |  |  | ep, fresopt); | 
| 1031 |  |  | else | 
| 1032 |  |  | sprintf(combuf+strlen(combuf), " %s", fresopt); | 
| 1033 |  |  | } | 
| 1034 |  |  | } else if (usepfilt) {                  /* pfilt only */ | 
| 1035 | greg | 2.2 | if (rvr == 2) | 
| 1036 |  |  | return(1); | 
| 1037 | greg | 2.1 | if (vdef(PFILT)) | 
| 1038 |  |  | sprintf(combuf, "pfilt %s", vval(PFILT)); | 
| 1039 |  |  | else | 
| 1040 |  |  | strcpy(combuf, "pfilt"); | 
| 1041 |  |  | if (ep != NULL) | 
| 1042 |  |  | sprintf(combuf+strlen(combuf), " -1 -e %s %s %s.unf", | 
| 1043 |  |  | ep, fresopt, fnbefore); | 
| 1044 |  |  | else | 
| 1045 |  |  | sprintf(combuf+strlen(combuf), " %s %s.unf", | 
| 1046 |  |  | fresopt, fnbefore); | 
| 1047 |  |  | } else {                                /* else just check it */ | 
| 1048 | greg | 2.2 | if (rvr == 2) | 
| 1049 |  |  | return(1); | 
| 1050 | greg | 2.7 | sprintf(combuf, "ra_rgbe -e %s -r %s.unf", ep, fnbefore); | 
| 1051 | greg | 2.1 | } | 
| 1052 |  |  | /* output file name */ | 
| 1053 | greg | 2.6 | sprintf(fname0, vval(BASENAME), frame); | 
| 1054 |  |  | sprintf(combuf+strlen(combuf), " > %s.pic", fname0); | 
| 1055 | greg | 2.2 | if (rvr)                                /* in recovery */ | 
| 1056 |  |  | return(runcom(combuf)); | 
| 1057 |  |  | bruncom(combuf, frame, frecover);       /* else run in background */ | 
| 1058 |  |  | return(0); | 
| 1059 | greg | 2.1 | } | 
| 1060 |  |  |  | 
| 1061 |  |  |  | 
| 1062 | schorsch | 2.43 | static VIEW * | 
| 1063 |  |  | getview(int n)                  /* get view number n */ | 
| 1064 | greg | 2.1 | { | 
| 1065 |  |  | static FILE     *viewfp = NULL;         /* view file pointer */ | 
| 1066 |  |  | static int      viewnum = 0;            /* current view number */ | 
| 1067 |  |  | static VIEW     curview = STDVIEW;      /* current view */ | 
| 1068 |  |  | char    linebuf[256]; | 
| 1069 |  |  |  | 
| 1070 |  |  | if (n == 0) {                   /* signal to close file and clean up */ | 
| 1071 |  |  | if (viewfp != NULL) { | 
| 1072 |  |  | fclose(viewfp); | 
| 1073 |  |  | viewfp = NULL; | 
| 1074 |  |  | viewnum = 0; | 
| 1075 | schorsch | 2.40 | curview = stdview; | 
| 1076 | greg | 2.1 | } | 
| 1077 |  |  | return(NULL); | 
| 1078 |  |  | } | 
| 1079 | gwlarson | 2.24 | if (viewfp == NULL) {                   /* open file */ | 
| 1080 | greg | 2.1 | if ((viewfp = fopen(vval(VIEWFILE), "r")) == NULL) { | 
| 1081 |  |  | perror(vval(VIEWFILE)); | 
| 1082 |  |  | quit(1); | 
| 1083 |  |  | } | 
| 1084 | gwlarson | 2.24 | } else if (n > 0 && n < viewnum) {      /* rewind file */ | 
| 1085 | greg | 2.8 | if (viewnum == 1 && feof(viewfp)) | 
| 1086 |  |  | return(&curview);               /* just one view */ | 
| 1087 | greg | 2.1 | if (fseek(viewfp, 0L, 0) == EOF) { | 
| 1088 |  |  | perror(vval(VIEWFILE)); | 
| 1089 |  |  | quit(1); | 
| 1090 |  |  | } | 
| 1091 | schorsch | 2.40 | curview = stdview; | 
| 1092 | greg | 2.1 | viewnum = 0; | 
| 1093 |  |  | } | 
| 1094 | gwlarson | 2.24 | if (n < 0) {                            /* get next view */ | 
| 1095 |  |  | register int    c = getc(viewfp); | 
| 1096 |  |  | if (c == EOF) | 
| 1097 |  |  | return((VIEW *)NULL);           /* that's it */ | 
| 1098 |  |  | ungetc(c, viewfp); | 
| 1099 |  |  | n = viewnum + 1; | 
| 1100 |  |  | } | 
| 1101 | greg | 2.1 | while (n > viewnum) {           /* scan to desired view */ | 
| 1102 |  |  | if (fgets(linebuf, sizeof(linebuf), viewfp) == NULL) | 
| 1103 | greg | 2.15 | return(viewnum==1 ? &curview : (VIEW *)NULL); | 
| 1104 | greg | 2.1 | if (isview(linebuf) && sscanview(&curview, linebuf) > 0) | 
| 1105 |  |  | viewnum++; | 
| 1106 |  |  | } | 
| 1107 |  |  | return(&curview);               /* return it */ | 
| 1108 |  |  | } | 
| 1109 |  |  |  | 
| 1110 |  |  |  | 
| 1111 | schorsch | 2.43 | static int | 
| 1112 |  |  | countviews(void)                        /* count views in view file */ | 
| 1113 | greg | 2.1 | { | 
| 1114 | gwlarson | 2.24 | int     n; | 
| 1115 | greg | 2.1 |  | 
| 1116 | gwlarson | 2.24 | if (getview(n=1) == NULL) | 
| 1117 |  |  | return(0); | 
| 1118 |  |  | while (getview(-1) != NULL) | 
| 1119 | greg | 2.1 | n++; | 
| 1120 |  |  | return(n); | 
| 1121 |  |  | } | 
| 1122 |  |  |  | 
| 1123 |  |  |  | 
| 1124 | schorsch | 2.43 | static char * | 
| 1125 |  |  | getexp(int n)                   /* get exposure for nth frame */ | 
| 1126 | greg | 2.1 | { | 
| 1127 |  |  | extern char     *fskip(); | 
| 1128 |  |  | static char     expval[32]; | 
| 1129 |  |  | static FILE     *expfp = NULL; | 
| 1130 |  |  | static long     *exppos; | 
| 1131 |  |  | static int      curfrm; | 
| 1132 |  |  | register char   *cp; | 
| 1133 |  |  |  | 
| 1134 |  |  | if (n == 0) {                           /* signal to close file */ | 
| 1135 |  |  | if (expfp != NULL) { | 
| 1136 |  |  | fclose(expfp); | 
| 1137 | greg | 2.29 | free((void *)exppos); | 
| 1138 | greg | 2.1 | expfp = NULL; | 
| 1139 |  |  | } | 
| 1140 |  |  | return(NULL); | 
| 1141 | greg | 2.14 | } else if (n > vint(END))               /* request past end (error?) */ | 
| 1142 |  |  | return(NULL); | 
| 1143 | greg | 2.1 | if (!vdef(EXPOSURE))                    /* no setting (auto) */ | 
| 1144 |  |  | return(NULL); | 
| 1145 |  |  | if (isflt(vval(EXPOSURE)))              /* always the same */ | 
| 1146 |  |  | return(vval(EXPOSURE)); | 
| 1147 |  |  | if (expfp == NULL) {                    /* open exposure file */ | 
| 1148 |  |  | if ((expfp = fopen(vval(EXPOSURE), "r")) == NULL) { | 
| 1149 |  |  | fprintf(stderr, | 
| 1150 |  |  | "%s: cannot open exposure file \"%s\"\n", | 
| 1151 |  |  | progname, vval(EXPOSURE)); | 
| 1152 |  |  | quit(1); | 
| 1153 |  |  | } | 
| 1154 |  |  | curfrm = vint(END) + 1;         /* init lookup tab. */ | 
| 1155 |  |  | exppos = (long *)malloc(curfrm*sizeof(long *)); | 
| 1156 |  |  | if (exppos == NULL) { | 
| 1157 |  |  | perror(progname); | 
| 1158 |  |  | quit(1); | 
| 1159 |  |  | } | 
| 1160 |  |  | while (curfrm--) | 
| 1161 |  |  | exppos[curfrm] = -1L; | 
| 1162 |  |  | curfrm = 0; | 
| 1163 |  |  | } | 
| 1164 |  |  | /* find position in file */ | 
| 1165 |  |  | if (n-1 != curfrm && n != curfrm && exppos[n-1] >= 0 && | 
| 1166 |  |  | fseek(expfp, exppos[curfrm=n-1], 0) == EOF) { | 
| 1167 |  |  | fprintf(stderr, "%s: seek error on exposure file\n", progname); | 
| 1168 |  |  | quit(1); | 
| 1169 |  |  | } | 
| 1170 |  |  | while (n > curfrm) {                    /* read exposure */ | 
| 1171 |  |  | if (exppos[curfrm] < 0) | 
| 1172 |  |  | exppos[curfrm] = ftell(expfp); | 
| 1173 |  |  | if (fgets(expval, sizeof(expval), expfp) == NULL) { | 
| 1174 |  |  | fprintf(stderr, "%s: too few exposures\n", | 
| 1175 |  |  | vval(EXPOSURE)); | 
| 1176 |  |  | quit(1); | 
| 1177 |  |  | } | 
| 1178 |  |  | curfrm++; | 
| 1179 |  |  | cp = fskip(expval);                     /* check format */ | 
| 1180 | greg | 2.14 | if (cp != NULL) | 
| 1181 |  |  | while (isspace(*cp)) | 
| 1182 |  |  | *cp++ = '\0'; | 
| 1183 |  |  | if (cp == NULL || *cp) { | 
| 1184 | greg | 2.1 | fprintf(stderr, | 
| 1185 |  |  | "%s: exposure format error on line %d\n", | 
| 1186 |  |  | vval(EXPOSURE), curfrm); | 
| 1187 |  |  | quit(1); | 
| 1188 |  |  | } | 
| 1189 |  |  | } | 
| 1190 |  |  | return(expval);                         /* return value */ | 
| 1191 |  |  | } | 
| 1192 |  |  |  | 
| 1193 |  |  |  | 
| 1194 | schorsch | 2.43 | static struct pslot * | 
| 1195 |  |  | findpslot(int pid)                      /* find or allocate a process slot */ | 
| 1196 | greg | 2.2 | { | 
| 1197 |  |  | register struct pslot   *psempty = NULL; | 
| 1198 |  |  | register int    i; | 
| 1199 |  |  |  | 
| 1200 |  |  | for (i = 0; i < npslots; i++) {         /* look for match */ | 
| 1201 |  |  | if (pslot[i].pid == pid) | 
| 1202 |  |  | return(pslot+i); | 
| 1203 |  |  | if (psempty == NULL && pslot[i].pid == 0) | 
| 1204 |  |  | psempty = pslot+i; | 
| 1205 |  |  | } | 
| 1206 |  |  | return(psempty);                /* return emtpy slot (error if NULL) */ | 
| 1207 |  |  | } | 
| 1208 |  |  |  | 
| 1209 |  |  |  | 
| 1210 | schorsch | 2.43 | static int | 
| 1211 |  |  | donecom(                /* clean up after finished process */ | 
| 1212 | schorsch | 2.46 | PSERVER *ps, | 
| 1213 |  |  | int     pn, | 
| 1214 |  |  | int     status | 
| 1215 | schorsch | 2.43 | ) | 
| 1216 | greg | 2.2 | { | 
| 1217 | schorsch | 2.43 | register NETPROC        *pp; | 
| 1218 | greg | 2.18 | register struct pslot   *psl; | 
| 1219 | greg | 2.2 |  | 
| 1220 |  |  | pp = ps->proc + pn; | 
| 1221 | greg | 2.3 | if (pp->elen) {                 /* pass errors */ | 
| 1222 | greg | 2.2 | if (ps->hostname[0]) | 
| 1223 | greg | 2.3 | fprintf(stderr, "%s: ", ps->hostname); | 
| 1224 |  |  | fprintf(stderr, "Error output from: %s\n", pp->com); | 
| 1225 | greg | 2.2 | fputs(pp->errs, stderr); | 
| 1226 |  |  | fflush(stderr); | 
| 1227 |  |  | if (ps->hostname[0]) | 
| 1228 |  |  | status = 1;     /* because rsh doesn't return status */ | 
| 1229 |  |  | } | 
| 1230 | greg | 2.18 | lastpserver = NULL; | 
| 1231 |  |  | psl = findpslot(pp->pid);       /* check for bruncom() slot */ | 
| 1232 |  |  | if (psl->pid) { | 
| 1233 |  |  | if (status) { | 
| 1234 |  |  | if (psl->rcvf != NULL)  /* attempt recovery */ | 
| 1235 |  |  | status = (*psl->rcvf)(psl->fout); | 
| 1236 |  |  | if (status) { | 
| 1237 |  |  | fprintf(stderr, | 
| 1238 |  |  | "%s: error rendering frame %d\n", | 
| 1239 |  |  | progname, psl->fout); | 
| 1240 |  |  | quit(1); | 
| 1241 |  |  | } | 
| 1242 |  |  | lastpserver = ps; | 
| 1243 |  |  | } | 
| 1244 |  |  | psl->pid = 0;                   /* free process slot */ | 
| 1245 |  |  | } else if (status) | 
| 1246 |  |  | lastpserver = ps; | 
| 1247 | greg | 2.2 | freestr(pp->com);               /* free command string */ | 
| 1248 |  |  | return(status); | 
| 1249 |  |  | } | 
| 1250 |  |  |  | 
| 1251 |  |  |  | 
| 1252 | schorsch | 2.43 | static int | 
| 1253 |  |  | serverdown(void)                        /* check status of last process server */ | 
| 1254 | greg | 2.2 | { | 
| 1255 | greg | 2.18 | if (lastpserver == NULL || !lastpserver->hostname[0]) | 
| 1256 |  |  | return(0); | 
| 1257 | greg | 2.2 | if (pserverOK(lastpserver))     /* server still up? */ | 
| 1258 |  |  | return(0); | 
| 1259 |  |  | delpserver(lastpserver);        /* else delete it */ | 
| 1260 |  |  | if (pslist == NULL) { | 
| 1261 |  |  | fprintf(stderr, "%s: all process servers are down\n", | 
| 1262 |  |  | progname); | 
| 1263 |  |  | quit(1); | 
| 1264 |  |  | } | 
| 1265 |  |  | return(1); | 
| 1266 |  |  | } | 
| 1267 |  |  |  | 
| 1268 |  |  |  | 
| 1269 | schorsch | 2.43 | static int | 
| 1270 |  |  | bruncom(                /* run a command in the background */ | 
| 1271 |  |  | char    *com, | 
| 1272 |  |  | int     fout, | 
| 1273 |  |  | int     (*rf)() | 
| 1274 |  |  | ) | 
| 1275 | greg | 2.2 | { | 
| 1276 |  |  | int     pid; | 
| 1277 |  |  | register struct pslot   *psl; | 
| 1278 |  |  |  | 
| 1279 | greg | 2.5 | if (noaction) { | 
| 1280 |  |  | if (!silent) | 
| 1281 |  |  | printf("\t%s\n", com);  /* echo command */ | 
| 1282 | greg | 2.2 | return(0); | 
| 1283 | greg | 2.5 | } | 
| 1284 | greg | 2.18 | com = savestr(com);             /* else start it when we can */ | 
| 1285 |  |  | while ((pid = startjob(NULL, com, donecom)) == -1) | 
| 1286 | greg | 2.2 | bwait(1); | 
| 1287 | greg | 2.5 | if (!silent) {                          /* echo command */ | 
| 1288 | greg | 2.3 | PSERVER *ps; | 
| 1289 |  |  | int     psn = pid; | 
| 1290 | greg | 2.4 | ps = findjob(&psn); | 
| 1291 | greg | 2.5 | printf("\t%s\n", com); | 
| 1292 | greg | 2.4 | printf("\tProcess started on %s\n", phostname(ps)); | 
| 1293 | greg | 2.3 | fflush(stdout); | 
| 1294 |  |  | } | 
| 1295 | greg | 2.2 | psl = findpslot(pid);           /* record info. in appropriate slot */ | 
| 1296 |  |  | psl->pid = pid; | 
| 1297 |  |  | psl->fout = fout; | 
| 1298 |  |  | psl->rcvf = rf; | 
| 1299 |  |  | return(pid); | 
| 1300 |  |  | } | 
| 1301 |  |  |  | 
| 1302 |  |  |  | 
| 1303 | schorsch | 2.43 | static void | 
| 1304 |  |  | bwait(int ncoms)                                /* wait for batch job(s) to finish */ | 
| 1305 | greg | 2.2 | { | 
| 1306 |  |  | int     status; | 
| 1307 |  |  |  | 
| 1308 |  |  | if (noaction) | 
| 1309 |  |  | return; | 
| 1310 |  |  | while ((status = wait4job(NULL, -1)) != -1) { | 
| 1311 | greg | 2.18 | serverdown();           /* update server status */ | 
| 1312 |  |  | if (--ncoms == 0) | 
| 1313 |  |  | break;          /* done enough */ | 
| 1314 | greg | 2.2 | } | 
| 1315 |  |  | } | 
| 1316 |  |  |  | 
| 1317 |  |  |  | 
| 1318 | schorsch | 2.43 | static int | 
| 1319 |  |  | pruncom(        /* run a command in parallel over network */ | 
| 1320 |  |  | char    *com, | 
| 1321 |  |  | char    *ppins, | 
| 1322 |  |  | int     maxcopies | 
| 1323 |  |  | ) | 
| 1324 | greg | 2.2 | { | 
| 1325 |  |  | int     retstatus = 0; | 
| 1326 | greg | 2.3 | int     hostcopies; | 
| 1327 | greg | 2.18 | char    buf[10240], *com1, *s; | 
| 1328 | greg | 2.2 | int     status; | 
| 1329 | greg | 2.17 | int     pfd; | 
| 1330 |  |  | register int    n; | 
| 1331 | greg | 2.2 | register PSERVER        *ps; | 
| 1332 |  |  |  | 
| 1333 | greg | 2.3 | if (!silent) | 
| 1334 | greg | 2.6 | printf("\t%s\n", com);  /* echo command */ | 
| 1335 | greg | 2.3 | if (noaction) | 
| 1336 | greg | 2.2 | return(0); | 
| 1337 | greg | 2.3 | fflush(stdout); | 
| 1338 | greg | 2.2 | /* start jobs on each server */ | 
| 1339 | greg | 2.3 | for (ps = pslist; ps != NULL; ps = ps->next) { | 
| 1340 |  |  | hostcopies = 0; | 
| 1341 | greg | 2.4 | if (maxcopies > 1 && ps->nprocs > 1 && ppins != NULL) { | 
| 1342 | greg | 2.17 | strcpy(com1=buf, com);  /* build -PP command */ | 
| 1343 | greg | 2.4 | sprintf(com1+(ppins-com), " -PP %s/%s.persist", | 
| 1344 |  |  | vval(DIRECTORY), phostname(ps)); | 
| 1345 | greg | 2.36 | unlink(com1+(ppins-com)+5); | 
| 1346 | greg | 2.4 | strcat(com1, ppins); | 
| 1347 | greg | 2.17 | } else | 
| 1348 | greg | 2.4 | com1 = com; | 
| 1349 | greg | 2.18 | while (maxcopies > 0) { | 
| 1350 |  |  | s = savestr(com1); | 
| 1351 |  |  | if (startjob(ps, s, donecom) != -1) { | 
| 1352 |  |  | sleep(20); | 
| 1353 |  |  | hostcopies++; | 
| 1354 |  |  | maxcopies--; | 
| 1355 |  |  | } else { | 
| 1356 |  |  | freestr(s); | 
| 1357 |  |  | break; | 
| 1358 |  |  | } | 
| 1359 | greg | 2.2 | } | 
| 1360 | greg | 2.3 | if (!silent && hostcopies) { | 
| 1361 |  |  | if (hostcopies > 1) | 
| 1362 |  |  | printf("\t%d duplicate processes", hostcopies); | 
| 1363 |  |  | else | 
| 1364 |  |  | printf("\tProcess"); | 
| 1365 | greg | 2.4 | printf(" started on %s\n", phostname(ps)); | 
| 1366 | greg | 2.3 | fflush(stdout); | 
| 1367 |  |  | } | 
| 1368 |  |  | } | 
| 1369 | greg | 2.2 | /* wait for jobs to finish */ | 
| 1370 |  |  | while ((status = wait4job(NULL, -1)) != -1) | 
| 1371 | greg | 2.18 | retstatus += status && !serverdown(); | 
| 1372 | greg | 2.17 | /* terminate parallel rpict's */ | 
| 1373 | greg | 2.18 | for (ps = pslist; ps != NULL; ps = ps->next) { | 
| 1374 |  |  | sprintf(buf, "%s/%s.persist", vval(DIRECTORY), phostname(ps)); | 
| 1375 | greg | 2.17 | if ((pfd = open(buf, O_RDONLY)) >= 0) { | 
| 1376 |  |  | n = read(pfd, buf, sizeof(buf)-1);      /* get PID */ | 
| 1377 |  |  | buf[n] = '\0'; | 
| 1378 |  |  | close(pfd); | 
| 1379 |  |  | for (n = 0; buf[n] && !isspace(buf[n]); n++) | 
| 1380 |  |  | ; | 
| 1381 |  |  | /* terminate */ | 
| 1382 |  |  | sprintf(buf, "kill -ALRM %d", atoi(buf+n)); | 
| 1383 | greg | 2.18 | wait4job(ps, startjob(ps, buf, NULL)); | 
| 1384 | greg | 2.17 | } | 
| 1385 |  |  | } | 
| 1386 | greg | 2.2 | return(retstatus); | 
| 1387 |  |  | } | 
| 1388 |  |  |  | 
| 1389 |  |  |  | 
| 1390 | schorsch | 2.43 | static int | 
| 1391 |  |  | runcom(char *cs)                        /* run a command locally and wait for it */ | 
| 1392 | greg | 2.1 | { | 
| 1393 |  |  | if (!silent)            /* echo it */ | 
| 1394 |  |  | printf("\t%s\n", cs); | 
| 1395 |  |  | if (noaction) | 
| 1396 |  |  | return(0); | 
| 1397 |  |  | fflush(stdout);         /* flush output and pass to shell */ | 
| 1398 |  |  | return(system(cs)); | 
| 1399 |  |  | } | 
| 1400 |  |  |  | 
| 1401 |  |  |  | 
| 1402 | schorsch | 2.43 | static int | 
| 1403 |  |  | rmfile(char *fn)                        /* remove a file */ | 
| 1404 | greg | 2.1 | { | 
| 1405 |  |  | if (!silent) | 
| 1406 | schorsch | 2.37 | #ifdef _WIN32 | 
| 1407 | greg | 2.1 | printf("\tdel %s\n", fn); | 
| 1408 |  |  | #else | 
| 1409 |  |  | printf("\trm -f %s\n", fn); | 
| 1410 |  |  | #endif | 
| 1411 |  |  | if (noaction) | 
| 1412 |  |  | return(0); | 
| 1413 |  |  | return(unlink(fn)); | 
| 1414 |  |  | } | 
| 1415 |  |  |  | 
| 1416 |  |  |  | 
| 1417 | schorsch | 2.43 | static void | 
| 1418 |  |  | badvalue(int vc)                        /* report bad variable value and exit */ | 
| 1419 | greg | 2.1 | { | 
| 1420 |  |  | fprintf(stderr, "%s: bad value for variable '%s'\n", | 
| 1421 |  |  | progname, vnam(vc)); | 
| 1422 |  |  | quit(1); | 
| 1423 | gwlarson | 2.25 | } | 
| 1424 |  |  |  | 
| 1425 |  |  |  | 
| 1426 | schorsch | 2.43 | static char * | 
| 1427 |  |  | dirfile(                /* separate path into directory and file */ | 
| 1428 |  |  | char    *df, | 
| 1429 |  |  | register char   *path | 
| 1430 |  |  | ) | 
| 1431 | gwlarson | 2.25 | { | 
| 1432 |  |  | register int    i; | 
| 1433 |  |  | int     psep; | 
| 1434 |  |  |  | 
| 1435 |  |  | for (i = 0, psep = -1; path[i]; i++) | 
| 1436 |  |  | if (path[i] == '/') | 
| 1437 |  |  | psep = i; | 
| 1438 | schorsch | 2.40 | if (df != NULL) { | 
| 1439 | gwlarson | 2.25 | if (psep == 0) { | 
| 1440 |  |  | df[0] = '/'; | 
| 1441 |  |  | df[1] = '\0'; | 
| 1442 |  |  | } else if (psep > 0) { | 
| 1443 |  |  | strncpy(df, path, psep); | 
| 1444 |  |  | df[psep] = '\0'; | 
| 1445 |  |  | } else | 
| 1446 |  |  | df[0] = '\0'; | 
| 1447 | schorsch | 2.40 | } | 
| 1448 | gwlarson | 2.25 | return(path+psep+1); | 
| 1449 | greg | 2.29 | } | 
| 1450 |  |  |  | 
| 1451 |  |  |  | 
| 1452 | schorsch | 2.43 | static int | 
| 1453 | greg | 2.48 | getblur(double *mbf, double *dbf)       /* get # blur samples (and fraction) */ | 
| 1454 | greg | 2.29 | { | 
| 1455 | greg | 2.48 | double  mblurf, dblurf; | 
| 1456 |  |  | int     nmblur, ndblur; | 
| 1457 | greg | 2.29 | char    *s; | 
| 1458 | greg | 2.48 | /* get motion blur */ | 
| 1459 |  |  | if (!vdef(MBLUR) || (mblurf = atof(vval(MBLUR))) < 0.0) | 
| 1460 |  |  | mblurf = 0.0; | 
| 1461 |  |  | if (mbf != NULL) | 
| 1462 |  |  | *mbf = mblurf; | 
| 1463 |  |  | if (mblurf <= FTINY) | 
| 1464 |  |  | nmblur = 0; | 
| 1465 |  |  | else if (!*(s = sskip(vval(MBLUR)))) | 
| 1466 |  |  | nmblur = DEF_NBLUR; | 
| 1467 |  |  | else if ((nmblur = atoi(s)) <= 0) | 
| 1468 |  |  | nmblur = 1; | 
| 1469 |  |  | /* get depth-of-field blur */ | 
| 1470 |  |  | if (!vdef(DBLUR) || (dblurf = atof(vval(DBLUR))) < 0.0) | 
| 1471 |  |  | dblurf = 0.0; | 
| 1472 |  |  | if (dbf != NULL) | 
| 1473 |  |  | *dbf = dblurf; | 
| 1474 |  |  | if (dblurf <= FTINY) | 
| 1475 |  |  | ndblur = 0; | 
| 1476 |  |  | else if (!*(s = sskip(vval(DBLUR)))) | 
| 1477 |  |  | ndblur = DEF_NBLUR; | 
| 1478 |  |  | else if ((ndblur = atoi(s)) <= 0) | 
| 1479 |  |  | ndblur = 1; | 
| 1480 |  |  | if ((nmblur == 1) & (ndblur == 1)) | 
| 1481 | greg | 2.29 | return(1); | 
| 1482 | greg | 2.48 | /* return combined samples */ | 
| 1483 |  |  | return(nmblur + ndblur); | 
| 1484 | greg | 2.1 | } |