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 (3 months, 2 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

# User Rev Content
1 gregl 3.1 #ifndef lint
2 greg 3.39 static const char RCSid[] = "$Id: rhcopy.c,v 3.38 2023/12/19 20:49:05 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     char *progname; /* global argv[0] */
37    
38 schorsch 3.22 struct phead {
39     VIEW vw;
40     double expos;
41     short gotview;
42     short badfmt;
43     short altprims;
44     };
45 greg 3.34
46     typedef struct {
47     FVECT ro;
48     FVECT rd;
49     RREAL d;
50     COLR cv;
51     } RAYPAR;
52    
53 schorsch 3.22 static int openholo(char *fname, int append);
54 greg 3.38 static int addray(RAYPAR *rp);
55 greg 3.34 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 schorsch 3.23 static gethfunc holheadline;
61 schorsch 3.22 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 schorsch 3.23 static gethfunc picheadline;
65 schorsch 3.22 static void addpicz(char *pcf, char *zbf);
66    
67    
68     int
69     main(
70     int argc,
71     char *argv[]
72     )
73 gregl 3.1 {
74     int i;
75    
76     progname = argv[0];
77 gregl 3.5 for (i = 2; i < argc && argv[i][0] == '-'; i++)
78     switch (argv[i][1]) {
79 gregl 3.8 case 'u':
80 gregl 3.5 checkrepeats = 1;
81     break;
82 gregl 3.8 case 'd':
83 gregl 3.5 checkdepth = 0;
84     break;
85 greg 3.34 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 gregl 3.5 case 'h':
91 greg 3.34 operation = FROM_HOLO;
92 gregl 3.5 break;
93     case 'p':
94 greg 3.34 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 gregl 3.5 break;
104     default:
105     goto userr;
106     }
107 greg 3.34 if (!operation | (i > argc-((operation==FROM_HOLO)|(operation==FROM_PICZ))))
108 gregl 3.1 goto userr;
109 greg 3.34 if (operation == FROM_PICZ && (argc-i)%2)
110 gregl 3.1 goto userr;
111 greg 3.34 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 gregl 3.5 for ( ; i < argc; i += 2)
121 gregl 3.1 addpicz(argv[i], argv[i+1]);
122 greg 3.34 break;
123     case FROM_HOLO:
124 gwlarson 3.10 if (BKBSIZE*1024*1.5 > hdcachesize)
125     hdcachesize = BKBSIZE*1024*1.5;
126 gregl 3.5 for ( ; i < argc; i++)
127 gregl 3.1 addholo(argv[i]);
128 greg 3.34 break;
129     case FROM_STDIN:
130     readrays(stdin);
131     break;
132     case TO_STDOUT:
133     writerays(stdout);
134     break;
135 gwlarson 3.10 }
136 gregl 3.1 quit(0);
137     userr:
138 greg 3.34 fprintf(stderr, "Usage: %s dest.hdk [-u][-d] -h inp1.hdk ..\n",
139 gregl 3.1 progname);
140 greg 3.34 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 gregl 3.5 progname);
146 gregl 3.1 exit(1);
147     }
148    
149 schorsch 3.23 static int
150 schorsch 3.22 holheadline( /* check holodeck header line */
151 greg 3.31 char *s,
152 schorsch 3.23 void *vhf
153 schorsch 3.22 )
154 gregl 3.1 {
155 greg 3.33 int be;
156 greg 3.30 char fmt[MAXFMTLEN];
157 greg 3.34 int *hf = (int *)vhf;
158 gregl 3.1
159     if (formatval(fmt, s)) {
160 gregl 3.2 if (strcmp(fmt, HOLOFMT))
161     *hf |= H_BADF;
162     else
163     *hf &= ~H_BADF;
164 gwlarson 3.9 return(0);
165 gregl 3.1 }
166     if (!strncmp(s, "OBSTRUCTIONS=", 13)) {
167     s += 13;
168     while (*s == ' ') s++;
169 schorsch 3.19 if ((*s == 't') | (*s == 'T'))
170 gregl 3.2 *hf |= H_OBST;
171 schorsch 3.19 else if ((*s == 'f') | (*s == 'F'))
172 gregl 3.2 *hf |= H_OBSF;
173 gregl 3.1 else
174     error(WARNING, "bad OBSTRUCTIONS value in holodeck");
175 gwlarson 3.9 return(0);
176 gregl 3.1 }
177 greg 3.34 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 greg 3.33 if ((be = isbigendian(s)) >= 0) {
187     if (be != nativebigendian())
188     *hf |= H_SWAP;
189 greg 3.34 return(0);
190 greg 3.33 }
191 gwlarson 3.9 return(0);
192 gregl 3.1 }
193    
194     int
195 schorsch 3.22 openholo( /* open existing holodeck file for i/o */
196     char *fname,
197     int append
198     )
199 gregl 3.1 {
200     FILE *fp;
201     int fd;
202 gregl 3.2 int hflags = 0;
203 greg 3.34 int *hfstore;
204 greg 3.26 off_t nextloc;
205 gregl 3.1 int n;
206     /* open holodeck file */
207 greg 3.32 if ((fp = fopen(fname, append ? "rb+" : "rb")) == NULL) {
208 gregl 3.1 sprintf(errmsg, "cannot open \"%s\" for %s", fname,
209     append ? "appending" : "reading");
210     error(SYSTEM, errmsg);
211     }
212     /* check header and magic number */
213 schorsch 3.23 if (getheader(fp, holheadline, &hflags) < 0 ||
214 greg 3.33 hflags&(H_BADF|H_SWAP) || getw(fp) != HOLOMAGIC) {
215     sprintf(errmsg, "holodeck \"%s\" not in expected format", fname);
216 gregl 3.1 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 greg 3.34 hfstore = (int *)malloc(sizeof(int)); /* tiny memory leak but who cares? */
222     *hfstore = hflags;
223 gregl 3.1 for (n = 0; nextloc > 0L; n++) { /* initialize each section */
224 greg 3.26 lseek(fd, nextloc, SEEK_SET);
225 gregl 3.1 read(fd, (char *)&nextloc, sizeof(nextloc));
226 greg 3.34 hdinit(fd, NULL)->priv = hfstore;
227 gregl 3.1 }
228     return(n);
229     }
230    
231 greg 3.38 int
232 schorsch 3.22 addray( /* add a ray to our output holodeck */
233 greg 3.34 RAYPAR *rp
234 schorsch 3.22 )
235 gregl 3.1 {
236 gregl 3.5 int sn, bi, n;
237 greg 3.31 HOLO *hp;
238 gregl 3.1 GCOORD gc[2];
239 greg 3.27 uby8 rr[2][2];
240 gregl 3.5 BEAM *bp;
241 gregl 3.1 double d0, d1;
242 gregl 3.5 unsigned dc;
243 greg 3.31 RAYVAL *rv;
244 greg 3.38 int nsects = 0;
245 gregl 3.1 /* check each output section */
246 greg 3.34 for (sn = nholosects; sn--; ) {
247 gregl 3.1 hp = hdlist[sn];
248 greg 3.34 d0 = hdinter(gc, rr, &d1, hp, rp->ro, rp->rd);
249     if (rp->d <= d0 || d1 < -0.001)
250 gregl 3.1 continue; /* missed section */
251 gregl 3.5 if (checkdepth) { /* check depth */
252 greg 3.34 if (*(int *)hp->priv & H_OBST && d0 < -0.001)
253 gregl 3.5 continue; /* ray starts too late */
254 greg 3.34 if (*(int *)hp->priv & H_OBSF && rp->d < 0.999*d1)
255 gregl 3.5 continue; /* ray ends too soon */
256     }
257 greg 3.34 dc = hdcode(hp, rp->d-d0);
258 gregl 3.5 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 greg 3.34 if ((rv->d == dc || *(int *)hp->priv & (H_OBST|H_OBSF)) &&
262 gregl 3.5 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 gregl 3.1 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 greg 3.34 copycolr(rv->v, rp->cv);
275 greg 3.38 ++nsects;
276 greg 3.34 }
277 greg 3.38 return nsects;
278 greg 3.34 }
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 greg 3.38 unsigned long nread=0, ngood=0;
332    
333 greg 3.34 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 greg 3.38 ++nread;
388 greg 3.34 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 greg 3.38 ngood += (addray(&ryp) > 0); /* add our ray to holodeck */
406 greg 3.34 }
407     return;
408     missingData:
409 greg 3.38 sprintf(errmsg, "insufficient data or read error with -i%s after %lu rays read (%lu used)",
410     rspec, nread, ngood);
411 greg 3.34 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 gregl 3.1 }
438 greg 3.34 #endif
439     return putbinary(v, sizeof(*v), n, fp);
440 gregl 3.1 }
441    
442 greg 3.34 /* 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 greg 3.35 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 greg 3.34 /* 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 greg 3.35 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 greg 3.34 if (!bp) /* empty beam? */
533     continue;
534 greg 3.35 hdbcoord(gc, hp, bq[bi]);
535 greg 3.34 rv = hdbray(bp);
536     for (k = bp->nrm; k--; rv++) {
537 greg 3.39 RREAL hitd = hddepth(hp, rv->d);
538 greg 3.34 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 greg 3.39 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 greg 3.34 copycolr(ryp.cv, rv->v);
550 greg 3.35 if (!write_ray(&ryp, fp)) {
551     free(bq);
552 greg 3.34 goto writError;
553 greg 3.35 }
554 greg 3.34 }
555 greg 3.35 hdfreebeam(hp, bq[bi]);
556 greg 3.34 }
557 greg 3.35 free(bq);
558 greg 3.34 }
559     if (fflush(fp) != EOF)
560     return;
561     writError:
562     error(SYSTEM, "error writing holodeck rays");
563     }
564 gregl 3.1
565 gwlarson 3.11 static int
566 schorsch 3.22 addclump( /* transfer the given clump and free */
567     HOLO *hp,
568     int *bq,
569     int nb
570     )
571 gwlarson 3.11 {
572 gregl 3.1 GCOORD gc[2];
573 greg 3.34 RAYPAR ryp;
574     RAYVAL *rv;
575 gwlarson 3.11 int i;
576 greg 3.31 int k;
577     BEAM *bp;
578 gwlarson 3.11 /* sort based on file position */
579     beamdir = hp->bi;
580 greg 3.35 qsort(bq, nb, sizeof(*bq), bpcmp);
581 gwlarson 3.11 /* transfer each beam */
582     for (i = 0; i < nb; i++) {
583     bp = hdgetbeam(hp, bq[i]);
584     hdbcoord(gc, hp, bq[i]);
585 greg 3.34 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 gwlarson 3.11 else
591 greg 3.34 ryp.d = 0.;
592     ryp.d = hddepth(hp, rv->d) - ryp.d;
593     copycolr(ryp.cv, rv->v);
594     addray(&ryp);
595 gwlarson 3.11 }
596     hdfreebeam(hp, bq[i]); /* free the beam */
597 gwlarson 3.10 }
598 gwlarson 3.11 return(0);
599 gwlarson 3.10 }
600    
601 schorsch 3.22
602     void
603     addholo( /* add a holodeck file */
604     char *hdf
605     )
606 gwlarson 3.10 {
607     int fd;
608 gregl 3.4 /* open the holodeck for reading */
609     openholo(hdf, 0);
610 greg 3.34 fd = hdlist[nholosects]->fd; /* remember the file handle */
611     while (hdlist[nholosects] != NULL) { /* load each section */
612 gwlarson 3.10 /* clump the beams */
613 greg 3.34 clumpbeams(hdlist[nholosects], 0, BKBSIZE*1024, addclump);
614     hddone(hdlist[nholosects]); /* free the section */
615 gregl 3.1 }
616 gwlarson 3.10 close(fd); /* close input file */
617 gwlarson 3.13 hdflush(NULL); /* flush output */
618 gregl 3.1 }
619    
620    
621    
622 schorsch 3.23 static int
623 schorsch 3.22 picheadline( /* process picture header line */
624     char *s,
625 schorsch 3.23 void *vph
626 schorsch 3.22 )
627 gregl 3.1 {
628     char fmt[32];
629 greg 3.34 struct phead *ph = (struct phead *)vph;
630 gregl 3.1
631     if (formatval(fmt, s)) {
632     ph->badfmt = strcmp(fmt, COLRFMT);
633 gwlarson 3.9 return(0);
634 gregl 3.1 }
635     if (isprims(s)) {
636     ph->altprims++; /* don't want to deal with this */
637 gwlarson 3.9 return(0);
638 gregl 3.1 }
639     if (isexpos(s)) {
640     ph->expos *= exposval(s);
641 gwlarson 3.9 return(0);
642 gregl 3.1 }
643     if (isview(s)) {
644     ph->gotview += sscanview(&ph->vw, s);
645 gwlarson 3.9 return(0);
646 gregl 3.1 }
647 gwlarson 3.9 return(0);
648 gregl 3.1 }
649    
650    
651 schorsch 3.22 void
652     addpicz( /* add a picture + depth-buffer */
653     char *pcf,
654     char *zbf
655     )
656 gregl 3.1 {
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 schorsch 3.17 RREAL vl[2];
666 greg 3.34 RAYPAR ryp;
667 gregl 3.1 double aftd;
668 greg 3.34 int j, i;
669     /* open picture & get header */
670 greg 3.32 if ((pfp = fopen(pcf, "rb")) == NULL) {
671 gregl 3.1 sprintf(errmsg, "cannot open picture file \"%s\"", pcf);
672     error(SYSTEM, pcf);
673     }
674 schorsch 3.18 phd.vw = stdview;
675 gregl 3.1 phd.expos = 1.0;
676     phd.badfmt = phd.gotview = phd.altprims = 0;
677 schorsch 3.23 if (getheader(pfp, picheadline, &phd) < 0 ||
678 gregl 3.1 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 greg 3.28 sprintf(errmsg, "ignoring color primaries in picture \"%s\"",
689 gregl 3.1 pcf);
690     error(WARNING, errmsg);
691     }
692 greg 3.34 /* open depth buffer */
693     if ((zfd = open_float_depth(zbf, prs.xr*prs.yr)) < 0)
694     quit(1);
695 gregl 3.1 /* figure out what to do about exposure */
696 schorsch 3.19 if ((phd.expos < 0.99) | (phd.expos > 1.01)) {
697 gregl 3.1 emult = -log(phd.expos)/log(2.);
698     eshft = emult >= 0. ? emult+.5 : emult-.5;
699     emult -= (double)eshft;
700 schorsch 3.19 if ((emult <= 0.01) & (emult >= -0.01))
701 gregl 3.1 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 schorsch 3.19 if ((cscn == NULL) | (zscn == NULL))
714 gregl 3.1 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 greg 3.32 /* read depth */
725     if (read(zfd, zscn, i*sizeof(float)) != i*sizeof(float)) {
726 gregl 3.1 sprintf(errmsg, "error reading depth file \"%s\"", zbf);
727     error(USER, errmsg);
728     }
729 greg 3.32 while (i--) { /* process each pixel */
730 greg 3.29 if (zscn[i] <= 0.0)
731     continue; /* illegal depth */
732 gregl 3.1 pix2loc(vl, &prs, i, j);
733 greg 3.34 aftd = viewray(ryp.ro, ryp.rd, &phd.vw, vl[0], vl[1]);
734 gregl 3.1 if (aftd < -FTINY)
735     continue; /* off view */
736     if (aftd > FTINY && zscn[i] > aftd)
737     continue; /* aft clipped */
738 greg 3.34 ryp.d = (RREAL)zscn[i];
739     copycolr(ryp.cv, cscn[i]);
740 gregl 3.1 if (emult > 0.) { /* whatta pain */
741 greg 3.34 COLOR ctmp;
742     colr_color(ctmp, ryp.cv);
743 gregl 3.1 scalecolor(ctmp, emult);
744 greg 3.34 setcolr(ryp.cv, colval(ctmp,RED),
745 gregl 3.1 colval(ctmp,GRN), colval(ctmp,BLU));
746     }
747 greg 3.34 addray(&ryp);
748 gregl 3.1 }
749     }
750 gwlarson 3.11 /* write output and free beams */
751     hdflush(NULL);
752 gregl 3.1 /* clean up */
753 greg 3.15 free((void *)cscn);
754     free((void *)zscn);
755 gregl 3.1 fclose(pfp);
756     close(zfd);
757     }
758    
759    
760 greg 3.15 void
761 schorsch 3.22 eputs( /* put error message to stderr */
762 greg 3.36 const char *s
763 schorsch 3.22 )
764 gregl 3.1 {
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 greg 3.15 void
782 schorsch 3.22 quit( /* exit the program gracefully */
783     int code
784     )
785 gregl 3.1 {
786     hdsync(NULL, 1); /* write out any buffered data */
787     exit(code);
788     }