ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/rhcopy.c
Revision: 3.39
Committed: Wed Feb 5 22:33:51 2025 UTC (2 months, 3 weeks ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 3.38: +10 -4 lines
Log Message:
fix(rhcopy): Made output of ray origin in case of uset OBSTRUCTIONS reliable

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: rhcopy.c,v 3.38 2023/12/19 20:49:05 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_OBSF)
540 VSUM(ryp.ro, ryp.ro, ryp.rd, ryp.d);
541 else if (*(int *)hp->priv & H_OBST)
542 ryp.d = 0;
543 else if (hitd < ryp.d) {
544 ryp.d = 0.97*hitd;
545 VSUM(ryp.ro, ryp.ro, ryp.rd, ryp.d);
546 } else
547 ryp.d = 0;
548 ryp.d = hitd - ryp.d;
549 copycolr(ryp.cv, rv->v);
550 if (!write_ray(&ryp, fp)) {
551 free(bq);
552 goto writError;
553 }
554 }
555 hdfreebeam(hp, bq[bi]);
556 }
557 free(bq);
558 }
559 if (fflush(fp) != EOF)
560 return;
561 writError:
562 error(SYSTEM, "error writing holodeck rays");
563 }
564
565 static int
566 addclump( /* transfer the given clump and free */
567 HOLO *hp,
568 int *bq,
569 int nb
570 )
571 {
572 GCOORD gc[2];
573 RAYPAR ryp;
574 RAYVAL *rv;
575 int i;
576 int k;
577 BEAM *bp;
578 /* sort based on file position */
579 beamdir = hp->bi;
580 qsort(bq, nb, sizeof(*bq), bpcmp);
581 /* transfer each beam */
582 for (i = 0; i < nb; i++) {
583 bp = hdgetbeam(hp, bq[i]);
584 hdbcoord(gc, hp, bq[i]);
585 rv = hdbray(bp); /* add each ray to output */
586 for (k = bp->nrm; k--; rv++) {
587 ryp.d = hdray(ryp.ro, ryp.rd, hp, gc, rv->r);
588 if (*(int *)hp->priv & H_OBSF)
589 VSUM(ryp.ro, ryp.ro, ryp.rd, ryp.d);
590 else
591 ryp.d = 0.;
592 ryp.d = hddepth(hp, rv->d) - ryp.d;
593 copycolr(ryp.cv, rv->v);
594 addray(&ryp);
595 }
596 hdfreebeam(hp, bq[i]); /* free the beam */
597 }
598 return(0);
599 }
600
601
602 void
603 addholo( /* add a holodeck file */
604 char *hdf
605 )
606 {
607 int fd;
608 /* open the holodeck for reading */
609 openholo(hdf, 0);
610 fd = hdlist[nholosects]->fd; /* remember the file handle */
611 while (hdlist[nholosects] != NULL) { /* load each section */
612 /* clump the beams */
613 clumpbeams(hdlist[nholosects], 0, BKBSIZE*1024, addclump);
614 hddone(hdlist[nholosects]); /* free the section */
615 }
616 close(fd); /* close input file */
617 hdflush(NULL); /* flush output */
618 }
619
620
621
622 static int
623 picheadline( /* process picture header line */
624 char *s,
625 void *vph
626 )
627 {
628 char fmt[32];
629 struct phead *ph = (struct phead *)vph;
630
631 if (formatval(fmt, s)) {
632 ph->badfmt = strcmp(fmt, COLRFMT);
633 return(0);
634 }
635 if (isprims(s)) {
636 ph->altprims++; /* don't want to deal with this */
637 return(0);
638 }
639 if (isexpos(s)) {
640 ph->expos *= exposval(s);
641 return(0);
642 }
643 if (isview(s)) {
644 ph->gotview += sscanview(&ph->vw, s);
645 return(0);
646 }
647 return(0);
648 }
649
650
651 void
652 addpicz( /* add a picture + depth-buffer */
653 char *pcf,
654 char *zbf
655 )
656 {
657 FILE *pfp;
658 int zfd;
659 COLR *cscn;
660 float *zscn;
661 struct phead phd;
662 int eshft;
663 double emult;
664 RESOLU prs;
665 RREAL vl[2];
666 RAYPAR ryp;
667 double aftd;
668 int j, i;
669 /* open picture & get header */
670 if ((pfp = fopen(pcf, "rb")) == NULL) {
671 sprintf(errmsg, "cannot open picture file \"%s\"", pcf);
672 error(SYSTEM, pcf);
673 }
674 phd.vw = stdview;
675 phd.expos = 1.0;
676 phd.badfmt = phd.gotview = phd.altprims = 0;
677 if (getheader(pfp, picheadline, &phd) < 0 ||
678 phd.badfmt || !fgetsresolu(&prs, pfp)) {
679 sprintf(errmsg, "bad format for picture file \"%s\"", pcf);
680 error(USER, errmsg);
681 }
682 if (!phd.gotview || setview(&phd.vw) != NULL) {
683 sprintf(errmsg, "missing/illegal view in picture \"%s\"",
684 pcf);
685 error(USER, errmsg);
686 }
687 if (phd.altprims) {
688 sprintf(errmsg, "ignoring color primaries in picture \"%s\"",
689 pcf);
690 error(WARNING, errmsg);
691 }
692 /* open depth buffer */
693 if ((zfd = open_float_depth(zbf, prs.xr*prs.yr)) < 0)
694 quit(1);
695 /* figure out what to do about exposure */
696 if ((phd.expos < 0.99) | (phd.expos > 1.01)) {
697 emult = -log(phd.expos)/log(2.);
698 eshft = emult >= 0. ? emult+.5 : emult-.5;
699 emult -= (double)eshft;
700 if ((emult <= 0.01) & (emult >= -0.01))
701 emult = -1.;
702 else {
703 emult = 1./phd.expos;
704 eshft = 0;
705 }
706 } else {
707 emult = -1.;
708 eshft = 0;
709 }
710 /* allocate buffers */
711 cscn = (COLR *)malloc(scanlen(&prs)*sizeof(COLR));
712 zscn = (float *)malloc(scanlen(&prs)*sizeof(float));
713 if ((cscn == NULL) | (zscn == NULL))
714 error(SYSTEM, "out of memory in addpicz");
715 /* read and process each scanline */
716 for (j = 0; j < numscans(&prs); j++) {
717 i = scanlen(&prs); /* read colrs */
718 if (freadcolrs(cscn, i, pfp) < 0) {
719 sprintf(errmsg, "error reading picture \"%s\"", pcf);
720 error(USER, errmsg);
721 }
722 if (eshft) /* shift exposure */
723 shiftcolrs(cscn, i, eshft);
724 /* read depth */
725 if (read(zfd, zscn, i*sizeof(float)) != i*sizeof(float)) {
726 sprintf(errmsg, "error reading depth file \"%s\"", zbf);
727 error(USER, errmsg);
728 }
729 while (i--) { /* process each pixel */
730 if (zscn[i] <= 0.0)
731 continue; /* illegal depth */
732 pix2loc(vl, &prs, i, j);
733 aftd = viewray(ryp.ro, ryp.rd, &phd.vw, vl[0], vl[1]);
734 if (aftd < -FTINY)
735 continue; /* off view */
736 if (aftd > FTINY && zscn[i] > aftd)
737 continue; /* aft clipped */
738 ryp.d = (RREAL)zscn[i];
739 copycolr(ryp.cv, cscn[i]);
740 if (emult > 0.) { /* whatta pain */
741 COLOR ctmp;
742 colr_color(ctmp, ryp.cv);
743 scalecolor(ctmp, emult);
744 setcolr(ryp.cv, colval(ctmp,RED),
745 colval(ctmp,GRN), colval(ctmp,BLU));
746 }
747 addray(&ryp);
748 }
749 }
750 /* write output and free beams */
751 hdflush(NULL);
752 /* clean up */
753 free((void *)cscn);
754 free((void *)zscn);
755 fclose(pfp);
756 close(zfd);
757 }
758
759
760 void
761 eputs( /* put error message to stderr */
762 const char *s
763 )
764 {
765 static int midline = 0;
766
767 if (!*s)
768 return;
769 if (!midline++) { /* prepend line with program name */
770 fputs(progname, stderr);
771 fputs(": ", stderr);
772 }
773 fputs(s, stderr);
774 if (s[strlen(s)-1] == '\n') {
775 fflush(stderr);
776 midline = 0;
777 }
778 }
779
780
781 void
782 quit( /* exit the program gracefully */
783 int code
784 )
785 {
786 hdsync(NULL, 1); /* write out any buffered data */
787 exit(code);
788 }