ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/rhcopy.c
Revision: 3.40
Committed: Wed Feb 5 23:43:41 2025 UTC (2 months, 3 weeks ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 3.39: +6 -8 lines
Log Message:
perf(rhcopy): Further improvement on last change

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: rhcopy.c,v 3.39 2025/02/05 22:33:51 greg Exp $";
3 #endif
4 /*
5 * Copy data into a holodeck file
6 */
7
8 #include "platform.h"
9 #include "rterror.h"
10 #include "holo.h"
11 #include "view.h"
12
13 #ifndef BKBSIZE
14 #define BKBSIZE 256 /* beam clump size (kilobytes) */
15 #endif
16 /* possible operations */
17 #define FROM_HOLO 1 /* copy between holodecks */
18 #define FROM_PICZ 2 /* copy from HDR + depth to holodeck */
19 #define FROM_STDIN 3 /* copy from stdin to holodeck */
20 #define TO_STDOUT 4 /* copy rays from holodeck to stdout */
21
22 int operation = 0; /* what we are doing */
23 char *rspec = ""; /* ray details for i/o */
24 int checkdepth = 1; /* check depth (!-d option)? */
25 int checkrepeats = 0; /* check for repeats (-u option)? */
26 int nholosects; /* number of original holodeck sections */
27 int iofmt = 'a'; /* input/output format for rays */
28
29 /* holodeck flags */
30 #define H_BADF 01 /* bad format */
31 #define H_OBST 02 /* OBSTRUCTIONS= True */
32 #define H_OBSF 04 /* OBSTRUCTIONS= False */
33 #define H_VDST 010 /* VDISTANCE= True */
34 #define H_SWAP 020 /* byte order is different */
35
36 char *progname; /* global argv[0] */
37
38 struct phead {
39 VIEW vw;
40 double expos;
41 short gotview;
42 short badfmt;
43 short altprims;
44 };
45
46 typedef struct {
47 FVECT ro;
48 FVECT rd;
49 RREAL d;
50 COLR cv;
51 } RAYPAR;
52
53 static int openholo(char *fname, int append);
54 static int addray(RAYPAR *rp);
55 static int readval(RREAL *v, int n, FILE *fp);
56 static void readrays(FILE *fp);
57 static int writeval(RREAL *v, int n, FILE *fp);
58 static int write_ray(RAYPAR *rp, FILE *fp);
59 static void writerays(FILE *fp);
60 static gethfunc holheadline;
61 static int bpcmp(const void *b1p, const void *b2p);
62 static int addclump(HOLO *hp, int *bq, int nb);
63 static void addholo(char *hdf);
64 static gethfunc picheadline;
65 static void addpicz(char *pcf, char *zbf);
66
67
68 int
69 main(
70 int argc,
71 char *argv[]
72 )
73 {
74 int i;
75
76 progname = argv[0];
77 for (i = 2; i < argc && argv[i][0] == '-'; i++)
78 switch (argv[i][1]) {
79 case 'u':
80 checkrepeats = 1;
81 break;
82 case 'd':
83 checkdepth = 0;
84 break;
85 case 'f':
86 iofmt = argv[i][2];
87 if (!strchr("afd", iofmt))
88 error(USER, "-f? i/o format must be 'a', 'f', or 'd'");
89 break;
90 case 'h':
91 operation = FROM_HOLO;
92 break;
93 case 'p':
94 operation = FROM_PICZ;
95 break;
96 case 'i':
97 operation = FROM_STDIN;
98 rspec = argv[i]+2;
99 break;
100 case 'o':
101 operation = TO_STDOUT;
102 rspec = argv[i]+2;
103 break;
104 default:
105 goto userr;
106 }
107 if (!operation | (i > argc-((operation==FROM_HOLO)|(operation==FROM_PICZ))))
108 goto userr;
109 if (operation == FROM_PICZ && (argc-i)%2)
110 goto userr;
111 nholosects = openholo(argv[1], (operation != TO_STDOUT));
112 /* check requested i/o is compatible */
113 if (strchr(rspec, 'l') && !(*(int *)hdlist[0]->priv & H_VDST))
114 error(USER, "i/o parameter 'l' incompatible with VDISTANCE=False");
115 if (strchr(rspec, 'L') && *(int *)hdlist[0]->priv & H_VDST)
116 error(USER, "i/o parameter 'L' incompatible with VDISTANCE=True");
117
118 switch (operation) { /* perform requested operation */
119 case FROM_PICZ:
120 for ( ; i < argc; i += 2)
121 addpicz(argv[i], argv[i+1]);
122 break;
123 case FROM_HOLO:
124 if (BKBSIZE*1024*1.5 > hdcachesize)
125 hdcachesize = BKBSIZE*1024*1.5;
126 for ( ; i < argc; i++)
127 addholo(argv[i]);
128 break;
129 case FROM_STDIN:
130 readrays(stdin);
131 break;
132 case TO_STDOUT:
133 writerays(stdout);
134 break;
135 }
136 quit(0);
137 userr:
138 fprintf(stderr, "Usage: %s dest.hdk [-u][-d] -h inp1.hdk ..\n",
139 progname);
140 fprintf(stderr, " Or: %s dest.hdk [-u][-d] -p inp1.hdr inp1.zbf ..\n",
141 progname);
142 fprintf(stderr, " Or: %s dest.hdk [-f{a|f|d}][-u][-d] -i[odplLv]\n",
143 progname);
144 fprintf(stderr, " Or: %s src.hdk [-f{a|f|d}] -o[odplLv] ..\n",
145 progname);
146 exit(1);
147 }
148
149 static int
150 holheadline( /* check holodeck header line */
151 char *s,
152 void *vhf
153 )
154 {
155 int be;
156 char fmt[MAXFMTLEN];
157 int *hf = (int *)vhf;
158
159 if (formatval(fmt, s)) {
160 if (strcmp(fmt, HOLOFMT))
161 *hf |= H_BADF;
162 else
163 *hf &= ~H_BADF;
164 return(0);
165 }
166 if (!strncmp(s, "OBSTRUCTIONS=", 13)) {
167 s += 13;
168 while (*s == ' ') s++;
169 if ((*s == 't') | (*s == 'T'))
170 *hf |= H_OBST;
171 else if ((*s == 'f') | (*s == 'F'))
172 *hf |= H_OBSF;
173 else
174 error(WARNING, "bad OBSTRUCTIONS value in holodeck");
175 return(0);
176 }
177 if (!strncmp(s, "VDISTANCE=", 10)) {
178 s += 10;
179 while (*s == ' ') s++;
180 if ((*s == 't') | (*s == 'T'))
181 *hf |= H_VDST;
182 else if ((*s != 'f') % (*s != 'F'))
183 error(WARNING, "bad VDISTANCE value in holodeck");
184 return(0);
185 }
186 if ((be = isbigendian(s)) >= 0) {
187 if (be != nativebigendian())
188 *hf |= H_SWAP;
189 return(0);
190 }
191 return(0);
192 }
193
194 int
195 openholo( /* open existing holodeck file for i/o */
196 char *fname,
197 int append
198 )
199 {
200 FILE *fp;
201 int fd;
202 int hflags = 0;
203 int *hfstore;
204 off_t nextloc;
205 int n;
206 /* open holodeck file */
207 if ((fp = fopen(fname, append ? "rb+" : "rb")) == NULL) {
208 sprintf(errmsg, "cannot open \"%s\" for %s", fname,
209 append ? "appending" : "reading");
210 error(SYSTEM, errmsg);
211 }
212 /* check header and magic number */
213 if (getheader(fp, holheadline, &hflags) < 0 ||
214 hflags&(H_BADF|H_SWAP) || getw(fp) != HOLOMAGIC) {
215 sprintf(errmsg, "holodeck \"%s\" not in expected format", fname);
216 error(USER, errmsg);
217 }
218 fd = dup(fileno(fp)); /* dup file handle */
219 nextloc = ftell(fp); /* get stdio position */
220 fclose(fp); /* done with stdio */
221 hfstore = (int *)malloc(sizeof(int)); /* tiny memory leak but who cares? */
222 *hfstore = hflags;
223 for (n = 0; nextloc > 0L; n++) { /* initialize each section */
224 lseek(fd, nextloc, SEEK_SET);
225 read(fd, (char *)&nextloc, sizeof(nextloc));
226 hdinit(fd, NULL)->priv = hfstore;
227 }
228 return(n);
229 }
230
231 int
232 addray( /* add a ray to our output holodeck */
233 RAYPAR *rp
234 )
235 {
236 int sn, bi, n;
237 HOLO *hp;
238 GCOORD gc[2];
239 uby8 rr[2][2];
240 BEAM *bp;
241 double d0, d1;
242 unsigned dc;
243 RAYVAL *rv;
244 int nsects = 0;
245 /* check each output section */
246 for (sn = nholosects; sn--; ) {
247 hp = hdlist[sn];
248 d0 = hdinter(gc, rr, &d1, hp, rp->ro, rp->rd);
249 if (rp->d <= d0 || d1 < -0.001)
250 continue; /* missed section */
251 if (checkdepth) { /* check depth */
252 if (*(int *)hp->priv & H_OBST && d0 < -0.001)
253 continue; /* ray starts too late */
254 if (*(int *)hp->priv & H_OBSF && rp->d < 0.999*d1)
255 continue; /* ray ends too soon */
256 }
257 dc = hdcode(hp, rp->d-d0);
258 bi = hdbindex(hp, gc); /* check for duplicates */
259 if (checkrepeats && (bp = hdgetbeam(hp, bi)) != NULL) {
260 for (n = bp->nrm, rv = hdbray(bp); n--; rv++)
261 if ((rv->d == dc || *(int *)hp->priv & (H_OBST|H_OBSF)) &&
262 rv->r[0][0] == rr[0][0] &&
263 rv->r[0][1] == rr[0][1] &&
264 rv->r[1][0] == rr[1][0] &&
265 rv->r[1][1] == rr[1][1])
266 break;
267 if (n >= 0)
268 continue; /* found a matching ray */
269 }
270 rv = hdnewrays(hp, bi, 1);
271 rv->d = dc;
272 rv->r[0][0] = rr[0][0]; rv->r[0][1] = rr[0][1];
273 rv->r[1][0] = rr[1][0]; rv->r[1][1] = rr[1][1];
274 copycolr(rv->v, rp->cv);
275 ++nsects;
276 }
277 return nsects;
278 }
279
280 /* Read n-vector from file stream */
281 static int
282 readval(RREAL *v, int n, FILE *fp)
283 {
284 int i;
285 #ifdef SMLFLT
286 double vd[3];
287 switch (iofmt) {
288 case 'f':
289 return getbinary(v, sizeof(float), n, fp);
290 case 'd':
291 n = getbinary(vd, sizeof(double), n, fp);
292 for (i = n; i-- > 0; ) v[i] = vd[i];
293 return n;
294 case 'a':
295 for (i = 0; i < n; i++)
296 if (fscanf(fp, "%f ", &v[i]) != 1)
297 break;
298 return i;
299 }
300 #else
301 float vf[3];
302 switch (iofmt) {
303 case 'd':
304 return getbinary(v, sizeof(double), n, fp);
305 case 'f':
306 n = getbinary(vf, sizeof(float), n, fp);
307 for (i = n; i-- > 0; ) v[i] = vf[i];
308 return n;
309 case 'a':
310 for (i = 0; i < n; i++)
311 if (fscanf(fp, "%lf ", &v[i]) != 1)
312 break;
313 return i;
314 }
315 #endif
316 return -1;
317 }
318
319 #define GOT_ORG 0x01
320 #define GOT_DIR 0x02
321 #define GOT_LEN 0x04
322 #define GOT_VAL 0x10
323 #define ALSO_POS 0x20
324 #define BAD_DIR 0x40
325 #define BAD_LEN 0x80
326
327 /* Read rays from stream and add to holodeck */
328 static void
329 readrays(FILE *fp)
330 {
331 unsigned long nread=0, ngood=0;
332
333 if (iofmt != 'a')
334 SET_FILE_BINARY(fp);
335 #ifdef getc_unlocked
336 flockfile(fp);
337 #endif
338 while (!feof(fp)) { /* read entirety of input */
339 RAYPAR ryp;
340 FVECT pos;
341 FVECT col;
342 int flags = 0;
343 int i;
344 for (i = 0; rspec[i]; i++) {
345 switch (rspec[i]) {
346 case 'o': /* ray origin */
347 if (readval(ryp.ro, 3, fp) < 3)
348 break;
349 flags |= GOT_ORG;
350 continue;
351 case 'd': /* ray direction */
352 if (readval(ryp.rd, 3, fp) < 3)
353 break;
354 if (normalize(ryp.rd) == 0)
355 flags |= BAD_DIR;
356 else
357 flags |= GOT_DIR;
358 continue;
359 case 'p': /* ray intersection */
360 if (readval(pos, 3, fp) < 3)
361 break;
362 flags |= ALSO_POS;
363 continue;
364 case 'L': /* ray first length */
365 case 'l': /* ray virtual length */
366 if (readval(&ryp.d, 1, fp) < 1)
367 break;
368 if (ryp.d <= FTINY)
369 flags |= BAD_LEN;
370 else
371 flags |= GOT_LEN;
372 continue;
373 case 'v': /* ray value */
374 if (readval(col, 3, fp) < 3)
375 break;
376 setcolr(ryp.cv, col[0], col[1], col[2]);
377 flags |= GOT_VAL;
378 continue;
379 default:
380 sprintf(errmsg, "unsupported parameter '%c' in -i%s",
381 rspec[i], rspec);
382 error(USER, errmsg);
383 }
384 if (!flags) /* got nothing, so may be normal EOF */
385 return;
386 }
387 ++nread;
388 if (flags & (BAD_DIR|BAD_LEN))
389 continue; /* just a bad ray is all -- skip */
390 if (!(flags & GOT_VAL))
391 goto missingData;
392 if ((flags & (GOT_ORG|GOT_DIR|GOT_LEN)) != (GOT_ORG|GOT_DIR|GOT_LEN)) {
393 if (!(flags & ALSO_POS))
394 goto missingData;
395 if (flags & GOT_ORG) {
396 VSUB(ryp.rd, pos, ryp.ro);
397 ryp.d = normalize(ryp.rd);
398 if (ryp.d == 0)
399 continue;
400 } else if ((flags & (GOT_DIR|GOT_LEN)) == (GOT_DIR|GOT_LEN)) {
401 VSUM(ryp.ro, pos, ryp.rd, -ryp.d);
402 } else
403 goto missingData;
404 }
405 ngood += (addray(&ryp) > 0); /* add our ray to holodeck */
406 }
407 return;
408 missingData:
409 sprintf(errmsg, "insufficient data or read error with -i%s after %lu rays read (%lu used)",
410 rspec, nread, ngood);
411 error(USER, errmsg);
412 }
413
414 /* Write vector value to file stream */
415 static int
416 writeval(RREAL *v, int n, FILE *fp)
417 {
418 int i;
419
420 if (iofmt == 'a') {
421 for (i = 0; i < n; i++)
422 if (fprintf(fp, "\t%.4e", v[i]) < 0)
423 break;
424 return i;
425 }
426 #ifdef SMLFLT
427 if (iofmt == 'd') {
428 double vd[3];
429 for (i = n; i--; ) vd[i] = v[i];
430 return putbinary(vd, sizeof(double), n, fp);
431 }
432 #else
433 if (iofmt == 'f') {
434 float vf[3];
435 for (i = n; i--; ) vf[i] = v[i];
436 return putbinary(vf, sizeof(float), n, fp);
437 }
438 #endif
439 return putbinary(v, sizeof(*v), n, fp);
440 }
441
442 /* Write out an individual ray as requested */
443 static int
444 write_ray(RAYPAR *rp, FILE *fp)
445 {
446 COLOR cval;
447 FVECT v3;
448 char *typ = rspec;
449
450 for ( ; ; ) {
451 switch (*typ++) {
452 case 'o': /* ray origin */
453 if (writeval(rp->ro, 3, fp) < 3)
454 break;
455 continue;
456 case 'd': /* ray direction */
457 if (writeval(rp->rd, 3, fp) < 3)
458 break;
459 continue;
460 case 'p': /* ray intersection */
461 VSUM(v3, rp->ro, rp->rd, rp->d);
462 if (writeval(v3, 3, fp) < 3)
463 break;
464 continue;
465 case 'L': /* ray first length */
466 case 'l': /* ray virtual length */
467 if (writeval(&rp->d, 1, fp) < 1)
468 break;
469 continue;
470 case 'v': /* ray value */
471 colr_color(cval, rp->cv);
472 VCOPY(v3, cval);
473 if (writeval(v3, 3, fp) < 3)
474 break;
475 continue;
476 case '\0': /* end of spec -- success */
477 if (iofmt == 'a')
478 fputc('\n', fp);
479 return(1);
480 default:
481 sprintf(errmsg, "unsupported parameter '%c' in -o%s", typ[-1], rspec);
482 }
483 break; /* land here on error */
484 }
485 return 0; /* write error? */
486 }
487
488 static BEAMI *beamdir;
489
490 static int
491 bpcmp( /* compare beam positions on disk */
492 const void *b1p,
493 const void *b2p
494 )
495 {
496 off_t pdif = beamdir[*(int *)b1p].fo - beamdir[*(int *)b2p].fo;
497
498 if (pdif > 0L) return(1);
499 if (pdif < 0L) return(-1);
500 return(0);
501 }
502
503 /* Write all rays from holodeck to stream */
504 static void
505 writerays(FILE *fp)
506 {
507 int sn, bi, k;
508 GCOORD gc[2];
509 RAYVAL *rv;
510 RAYPAR ryp;
511
512 if (!*rspec) {
513 error(WARNING, "empty -o* output spec, quitting");
514 return;
515 }
516 if (iofmt != 'a')
517 SET_FILE_BINARY(fp);
518 #ifdef getc_unlocked
519 flockfile(fp);
520 #endif
521 for (sn = 0; sn < nholosects; sn++) { /* write each holodeck section */
522 HOLO *hp = hdlist[sn];
523 int nb = nbeams(hp); /* sort beams by file location */
524 int *bq = (int *)malloc(nb*sizeof(int));
525 if (!bq)
526 error(SYSTEM, "out of memory in writerays()");
527 for (bi = nb; bi--; ) bq[bi] = bi+1;
528 beamdir = hp->bi;
529 qsort(bq, nb, sizeof(*bq), bpcmp);
530 for (bi = 0; bi < nb; bi++) {
531 BEAM *bp = hdgetbeam(hp, bq[bi]);
532 if (!bp) /* empty beam? */
533 continue;
534 hdbcoord(gc, hp, bq[bi]);
535 rv = hdbray(bp);
536 for (k = bp->nrm; k--; rv++) {
537 RREAL hitd = hddepth(hp, rv->d);
538 ryp.d = hdray(ryp.ro, ryp.rd, hp, gc, rv->r);
539 if (*(int *)hp->priv & H_OBST) {
540 ryp.d = 0;
541 } else {
542 if (ryp.d > 0.97*hitd)
543 ryp.d = 0.97*hitd;
544 VSUM(ryp.ro, ryp.ro, ryp.rd, ryp.d);
545 }
546 ryp.d = hitd - ryp.d;
547 copycolr(ryp.cv, rv->v);
548 if (!write_ray(&ryp, fp)) {
549 free(bq);
550 goto writError;
551 }
552 }
553 hdfreebeam(hp, bq[bi]);
554 }
555 free(bq);
556 }
557 if (fflush(fp) != EOF)
558 return;
559 writError:
560 error(SYSTEM, "error writing holodeck rays");
561 }
562
563 static int
564 addclump( /* transfer the given clump and free */
565 HOLO *hp,
566 int *bq,
567 int nb
568 )
569 {
570 GCOORD gc[2];
571 RAYPAR ryp;
572 RAYVAL *rv;
573 int i;
574 int k;
575 BEAM *bp;
576 /* sort based on file position */
577 beamdir = hp->bi;
578 qsort(bq, nb, sizeof(*bq), bpcmp);
579 /* transfer each beam */
580 for (i = 0; i < nb; i++) {
581 bp = hdgetbeam(hp, bq[i]);
582 hdbcoord(gc, hp, bq[i]);
583 rv = hdbray(bp); /* add each ray to output */
584 for (k = bp->nrm; k--; rv++) {
585 ryp.d = hdray(ryp.ro, ryp.rd, hp, gc, rv->r);
586 if (*(int *)hp->priv & H_OBSF)
587 VSUM(ryp.ro, ryp.ro, ryp.rd, ryp.d);
588 else
589 ryp.d = 0.;
590 ryp.d = hddepth(hp, rv->d) - ryp.d;
591 copycolr(ryp.cv, rv->v);
592 addray(&ryp);
593 }
594 hdfreebeam(hp, bq[i]); /* free the beam */
595 }
596 return(0);
597 }
598
599
600 void
601 addholo( /* add a holodeck file */
602 char *hdf
603 )
604 {
605 int fd;
606 /* open the holodeck for reading */
607 openholo(hdf, 0);
608 fd = hdlist[nholosects]->fd; /* remember the file handle */
609 while (hdlist[nholosects] != NULL) { /* load each section */
610 /* clump the beams */
611 clumpbeams(hdlist[nholosects], 0, BKBSIZE*1024, addclump);
612 hddone(hdlist[nholosects]); /* free the section */
613 }
614 close(fd); /* close input file */
615 hdflush(NULL); /* flush output */
616 }
617
618
619
620 static int
621 picheadline( /* process picture header line */
622 char *s,
623 void *vph
624 )
625 {
626 char fmt[32];
627 struct phead *ph = (struct phead *)vph;
628
629 if (formatval(fmt, s)) {
630 ph->badfmt = strcmp(fmt, COLRFMT);
631 return(0);
632 }
633 if (isprims(s)) {
634 ph->altprims++; /* don't want to deal with this */
635 return(0);
636 }
637 if (isexpos(s)) {
638 ph->expos *= exposval(s);
639 return(0);
640 }
641 if (isview(s)) {
642 ph->gotview += sscanview(&ph->vw, s);
643 return(0);
644 }
645 return(0);
646 }
647
648
649 void
650 addpicz( /* add a picture + depth-buffer */
651 char *pcf,
652 char *zbf
653 )
654 {
655 FILE *pfp;
656 int zfd;
657 COLR *cscn;
658 float *zscn;
659 struct phead phd;
660 int eshft;
661 double emult;
662 RESOLU prs;
663 RREAL vl[2];
664 RAYPAR ryp;
665 double aftd;
666 int j, i;
667 /* open picture & get header */
668 if ((pfp = fopen(pcf, "rb")) == NULL) {
669 sprintf(errmsg, "cannot open picture file \"%s\"", pcf);
670 error(SYSTEM, pcf);
671 }
672 phd.vw = stdview;
673 phd.expos = 1.0;
674 phd.badfmt = phd.gotview = phd.altprims = 0;
675 if (getheader(pfp, picheadline, &phd) < 0 ||
676 phd.badfmt || !fgetsresolu(&prs, pfp)) {
677 sprintf(errmsg, "bad format for picture file \"%s\"", pcf);
678 error(USER, errmsg);
679 }
680 if (!phd.gotview || setview(&phd.vw) != NULL) {
681 sprintf(errmsg, "missing/illegal view in picture \"%s\"",
682 pcf);
683 error(USER, errmsg);
684 }
685 if (phd.altprims) {
686 sprintf(errmsg, "ignoring color primaries in picture \"%s\"",
687 pcf);
688 error(WARNING, errmsg);
689 }
690 /* open depth buffer */
691 if ((zfd = open_float_depth(zbf, prs.xr*prs.yr)) < 0)
692 quit(1);
693 /* figure out what to do about exposure */
694 if ((phd.expos < 0.99) | (phd.expos > 1.01)) {
695 emult = -log(phd.expos)/log(2.);
696 eshft = emult >= 0. ? emult+.5 : emult-.5;
697 emult -= (double)eshft;
698 if ((emult <= 0.01) & (emult >= -0.01))
699 emult = -1.;
700 else {
701 emult = 1./phd.expos;
702 eshft = 0;
703 }
704 } else {
705 emult = -1.;
706 eshft = 0;
707 }
708 /* allocate buffers */
709 cscn = (COLR *)malloc(scanlen(&prs)*sizeof(COLR));
710 zscn = (float *)malloc(scanlen(&prs)*sizeof(float));
711 if ((cscn == NULL) | (zscn == NULL))
712 error(SYSTEM, "out of memory in addpicz");
713 /* read and process each scanline */
714 for (j = 0; j < numscans(&prs); j++) {
715 i = scanlen(&prs); /* read colrs */
716 if (freadcolrs(cscn, i, pfp) < 0) {
717 sprintf(errmsg, "error reading picture \"%s\"", pcf);
718 error(USER, errmsg);
719 }
720 if (eshft) /* shift exposure */
721 shiftcolrs(cscn, i, eshft);
722 /* read depth */
723 if (read(zfd, zscn, i*sizeof(float)) != i*sizeof(float)) {
724 sprintf(errmsg, "error reading depth file \"%s\"", zbf);
725 error(USER, errmsg);
726 }
727 while (i--) { /* process each pixel */
728 if (zscn[i] <= 0.0)
729 continue; /* illegal depth */
730 pix2loc(vl, &prs, i, j);
731 aftd = viewray(ryp.ro, ryp.rd, &phd.vw, vl[0], vl[1]);
732 if (aftd < -FTINY)
733 continue; /* off view */
734 if (aftd > FTINY && zscn[i] > aftd)
735 continue; /* aft clipped */
736 ryp.d = (RREAL)zscn[i];
737 copycolr(ryp.cv, cscn[i]);
738 if (emult > 0.) { /* whatta pain */
739 COLOR ctmp;
740 colr_color(ctmp, ryp.cv);
741 scalecolor(ctmp, emult);
742 setcolr(ryp.cv, colval(ctmp,RED),
743 colval(ctmp,GRN), colval(ctmp,BLU));
744 }
745 addray(&ryp);
746 }
747 }
748 /* write output and free beams */
749 hdflush(NULL);
750 /* clean up */
751 free((void *)cscn);
752 free((void *)zscn);
753 fclose(pfp);
754 close(zfd);
755 }
756
757
758 void
759 eputs( /* put error message to stderr */
760 const char *s
761 )
762 {
763 static int midline = 0;
764
765 if (!*s)
766 return;
767 if (!midline++) { /* prepend line with program name */
768 fputs(progname, stderr);
769 fputs(": ", stderr);
770 }
771 fputs(s, stderr);
772 if (s[strlen(s)-1] == '\n') {
773 fflush(stderr);
774 midline = 0;
775 }
776 }
777
778
779 void
780 quit( /* exit the program gracefully */
781 int code
782 )
783 {
784 hdsync(NULL, 1); /* write out any buffered data */
785 exit(code);
786 }