ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/rhcopy.c
Revision: 3.41
Committed: Thu Jun 5 19:10:31 2025 UTC (43 hours, 36 minutes ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 3.40: +2 -4 lines
Log Message:
refactor: Made progname declarations more consistent

File Contents

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