ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/glareval.c
Revision: 1.13
Committed: Thu Apr 18 15:18:25 1991 UTC (33 years ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.12: +12 -3 lines
Log Message:
added format information to headers

File Contents

# User Rev Content
1 greg 1.1 /* Copyright (c) 1991 Regents of the University of California */
2    
3     #ifndef lint
4     static char SCCSid[] = "$SunId$ LBL";
5     #endif
6    
7     /*
8     * Compute pixels for glare calculation
9     */
10    
11     #include "glare.h"
12     #include <sys/param.h>
13     /* compute rtrace buffer size */
14     #ifndef PIPE_BUF
15     #define PIPE_BUF 512 /* hyperconservative */
16     #endif
17     #define MAXPIX (PIPE_BUF/(6*sizeof(float)) - 1)
18    
19     #ifndef BSD
20     #define vfork fork
21     #endif
22    
23 greg 1.11 #define MAXSBUF 524268 /* maximum total size of scanline buffer */
24 greg 1.9 #define HSIZE 317 /* size of scanline hash table */
25 greg 1.8 #define NRETIRE 16 /* number of scanlines to retire at once */
26 greg 1.1
27     int rt_pid = -1; /* process id for rtrace */
28     int fd_tort, fd_fromrt; /* pipe descriptors */
29    
30     FILE *pictfp = NULL; /* picture file pointer */
31     double exposure; /* picture exposure */
32     int pxsiz, pysiz; /* picture dimensions */
33 greg 1.8
34     static int curpos; /* current scanline */
35     static long *scanpos; /* scanline positions */
36    
37     typedef struct scan {
38     int y; /* scanline position */
39 greg 1.1 long lused; /* for LRU replacement */
40 greg 1.8 struct scan *next; /* next in this hash or free list */
41     /* followed by the scanline data */
42     } SCAN; /* buffered scanline */
43 greg 1.1
44 greg 1.8 #define scandata(sl) ((COLR *)((sl)+1))
45     #define shash(y) ((y)%HSIZE)
46    
47     static SCAN *freelist; /* scanline free list */
48     static SCAN *hashtab[HSIZE]; /* scanline hash table */
49    
50 greg 1.2 static long ncall = 0L; /* number of calls to getpictscan */
51     static long nread = 0L; /* number of scanlines read */
52 greg 1.1
53 greg 1.13 static int wrongformat = 0;
54    
55 greg 1.8 SCAN *scanretire();
56    
57 greg 1.5 extern long ftell();
58 greg 1.2
59 greg 1.5
60 greg 1.8 SCAN *
61     claimscan(y) /* claim scanline from buffers */
62     int y;
63     {
64     int hi = shash(y);
65     SCAN *slast;
66     register SCAN *sl;
67    
68     for (sl = hashtab[hi]; sl != NULL; sl = sl->next)
69     if (sl->y == y) /* active scanline */
70     return(sl);
71     for (slast = NULL, sl = freelist; sl != NULL; slast = sl, sl = sl->next)
72     if (sl->y == -1 || sl->y == y || sl->next == NULL) {
73     if (slast == NULL) /* remove from free */
74     freelist = sl->next;
75     else
76     slast->next = sl->next;
77     if (sl->y == y) { /* reclaim */
78     sl->next = hashtab[hi];
79     hashtab[hi] = sl;
80 greg 1.11 #ifdef DEBUG
81     if (verbose)
82     fprintf(stderr,
83     "%s: scanline %d reclaimed\n",
84     progname, y);
85     #endif
86 greg 1.8 }
87     return(sl);
88     }
89     return(scanretire()); /* need more free scanlines */
90     }
91    
92    
93 greg 1.1 COLR *
94     getpictscan(y) /* get picture scanline */
95     int y;
96     {
97 greg 1.8 register SCAN *sl;
98 greg 1.1 register int i;
99     /* first check our buffers */
100 greg 1.8 sl = claimscan(y);
101     if (sl == NULL)
102     memerr("claimscan()");
103     sl->lused = ncall++;
104     if (sl->y == y) /* scan hit */
105     return(scandata(sl));
106     /* else read in replacement */
107 greg 1.5 if (scanpos[y] < 0) { /* need to search */
108     for (i = y+1; i < curpos; i++)
109     if (scanpos[i] >= 0) {
110     if (fseek(pictfp, scanpos[i], 0) < 0)
111     goto seekerr;
112     curpos = i;
113     break;
114     }
115     while (curpos >= y) {
116 greg 1.1 scanpos[curpos] = ftell(pictfp);
117 greg 1.8 if (freadcolrs(scandata(sl), pxsiz, pictfp) < 0)
118 greg 1.1 goto readerr;
119 greg 1.5 nread++;
120 greg 1.1 curpos--;
121     }
122 greg 1.5 } else {
123     if (curpos != y && fseek(pictfp, scanpos[y], 0) < 0)
124     goto seekerr;
125 greg 1.8 if (freadcolrs(scandata(sl), pxsiz, pictfp) < 0)
126 greg 1.5 goto readerr;
127     nread++;
128     curpos = y-1;
129 greg 1.1 }
130 greg 1.8 sl->y = y;
131     i = shash(y); /* add to hash list */
132     sl->next = hashtab[i];
133     hashtab[i] = sl;
134     return(scandata(sl));
135 greg 1.1 readerr:
136     fprintf(stderr, "%s: picture read error\n", progname);
137     exit(1);
138 greg 1.5 seekerr:
139     fprintf(stderr, "%s: picture seek error\n", progname);
140     exit(1);
141 greg 1.1 }
142    
143    
144 greg 1.6 #ifdef DEBUG
145 greg 1.2 pict_stats() /* print out picture read statistics */
146     {
147     static long lastcall = 0L; /* ncall at last report */
148     static long lastread = 0L; /* nread at last report */
149    
150     if (ncall == lastcall)
151     return;
152 greg 1.6 fprintf(stderr, "%s: %ld scanlines read in %ld calls\n",
153     progname, nread-lastread, ncall-lastcall);
154 greg 1.2 lastcall = ncall;
155     lastread = nread;
156     }
157 greg 1.6 #endif
158 greg 1.2
159    
160 greg 1.1 double
161     pict_val(vd) /* find picture value for view direction */
162     FVECT vd;
163     {
164     FVECT pp;
165     double vpx, vpy, vpz;
166     COLOR res;
167    
168     if (pictfp == NULL)
169     return(-1.0);
170     pp[0] = pictview.vp[0] + vd[0];
171     pp[1] = pictview.vp[1] + vd[1];
172     pp[2] = pictview.vp[2] + vd[2];
173     viewpixel(&vpx, &vpy, &vpz, &pictview, pp);
174     if (vpz <= FTINY || vpx < 0. || vpx >= 1. || vpy < 0. || vpy >= 1.)
175     return(-1.0);
176     colr_color(res, getpictscan((int)(vpy*pysiz))[(int)(vpx*pxsiz)]);
177     return(luminance(res)/exposure);
178     }
179    
180    
181     double
182 greg 1.12 getviewpix(vh, vv, se) /* compute single view pixel */
183 greg 1.1 int vh, vv;
184 greg 1.12 SPANERR *se;
185 greg 1.1 {
186     FVECT dir;
187     float rt_buf[6];
188     double res;
189    
190 greg 1.12 if (compdir(dir, vh, vv, se) < 0)
191 greg 1.1 return(-1.0);
192 greg 1.7 npixinvw++;
193 greg 1.1 if ((res = pict_val(dir)) >= 0.0)
194     return(res);
195 greg 1.7 if (rt_pid == -1) {
196     npixmiss++;
197 greg 1.1 return(-1.0);
198 greg 1.7 }
199 greg 1.1 rt_buf[0] = ourview.vp[0];
200     rt_buf[1] = ourview.vp[1];
201     rt_buf[2] = ourview.vp[2];
202     rt_buf[3] = dir[0];
203     rt_buf[4] = dir[1];
204     rt_buf[5] = dir[2];
205     rt_compute(rt_buf, 1);
206     return(luminance(rt_buf));
207     }
208    
209    
210     getviewspan(vv, vb) /* compute a span of view pixels */
211     int vv;
212     float *vb;
213     {
214     float rt_buf[6*MAXPIX]; /* rtrace send/receive buffer */
215 greg 1.3 register int n; /* number of pixels in buffer */
216 greg 1.1 short buf_vh[MAXPIX]; /* pixel positions */
217 greg 1.12 SPANERR sperr;
218 greg 1.1 FVECT dir;
219     register int vh;
220    
221 greg 1.4 #ifdef DEBUG
222 greg 1.1 if (verbose)
223     fprintf(stderr, "%s: computing view span at %d...\n",
224     progname, vv);
225 greg 1.4 #endif
226 greg 1.12 setspanerr(&sperr, vv);
227 greg 1.3 n = 0;
228 greg 1.1 for (vh = -hsize; vh <= hsize; vh++) {
229 greg 1.12 if (compdir(dir, vh, vv, &sperr) < 0) { /* not in view */
230 greg 1.1 vb[vh+hsize] = -1.0;
231     continue;
232     }
233 greg 1.7 npixinvw++;
234 greg 1.1 if ((vb[vh+hsize] = pict_val(dir)) >= 0.0)
235     continue;
236 greg 1.7 if (rt_pid == -1) { /* missing information */
237     npixmiss++;
238 greg 1.1 continue;
239 greg 1.7 }
240 greg 1.1 /* send to rtrace */
241 greg 1.3 if (n >= MAXPIX) { /* flush */
242     rt_compute(rt_buf, n);
243     while (n-- > 0)
244     vb[buf_vh[n]+hsize] = luminance(rt_buf+3*n);
245 greg 1.1 }
246 greg 1.3 rt_buf[6*n] = ourview.vp[0];
247     rt_buf[6*n+1] = ourview.vp[1];
248     rt_buf[6*n+2] = ourview.vp[2];
249     rt_buf[6*n+3] = dir[0];
250     rt_buf[6*n+4] = dir[1];
251     rt_buf[6*n+5] = dir[2];
252     buf_vh[n++] = vh;
253 greg 1.1 }
254 greg 1.4 #ifdef DEBUG
255 greg 1.2 if (verbose)
256     pict_stats();
257 greg 1.4 #endif
258 greg 1.3 if (n > 0) { /* process pending buffer */
259     rt_compute(rt_buf, n);
260     while (n-- > 0)
261     vb[buf_vh[n]+hsize] = luminance(rt_buf+3*n);
262     }
263 greg 1.1 }
264    
265    
266     rt_compute(pb, np) /* process buffer through rtrace */
267     float *pb;
268     int np;
269     {
270     static float nbuf[6] = {0.,0.,0.,0.,0.,0.};
271    
272 greg 1.4 #ifdef DEBUG
273 greg 1.1 if (verbose && np > 1)
274     fprintf(stderr, "%s: sending %d samples to rtrace...\n",
275     progname, np);
276 greg 1.4 #endif
277 greg 1.1 if (writebuf(fd_tort,(char *)pb,6*sizeof(float)*np) < 6*sizeof(float)*np
278     || writebuf(fd_tort,(char *)nbuf,sizeof(nbuf)) < sizeof(nbuf)) {
279     fprintf(stderr, "%s: error writing to rtrace process\n",
280     progname);
281     exit(1);
282     }
283     if (readbuf(fd_fromrt, (char *)pb, 3*sizeof(float)*np)
284     < 3*sizeof(float)*np) {
285     fprintf(stderr, "%s: error reading from rtrace process\n",
286     progname);
287     exit(1);
288     }
289     }
290    
291    
292     getexpos(s) /* get exposure from header line */
293     char *s;
294     {
295 greg 1.13 char fmt[32];
296    
297 greg 1.1 if (isexpos(s))
298     exposure *= exposval(s);
299 greg 1.13 else if (isformat(s)) {
300     formatval(fmt, s);
301     wrongformat = strcmp(fmt, COLRFMT);
302     }
303 greg 1.1 }
304    
305    
306     open_pict(fn) /* open picture file */
307     char *fn;
308     {
309     if ((pictfp = fopen(fn, "r")) == NULL) {
310     fprintf("%s: cannot open\n", fn);
311     exit(1);
312     }
313     exposure = 1.0;
314 greg 1.13 getheader(pictfp, getexpos, NULL);
315     if (wrongformat ||
316     fgetresolu(&pxsiz, &pysiz, pictfp) != (YMAJOR|YDECR)) {
317     fprintf("%s: bad picture format\n", fn);
318 greg 1.1 exit(1);
319     }
320 greg 1.8 initscans();
321 greg 1.1 }
322    
323    
324     close_pict() /* done with picture */
325     {
326     if (pictfp == NULL)
327     return;
328     fclose(pictfp);
329 greg 1.8 donescans();
330 greg 1.1 pictfp = NULL;
331     }
332    
333    
334     fork_rtrace(av) /* open pipe and start rtrace */
335     char *av[];
336     {
337     int p0[2], p1[2];
338    
339     if (pipe(p0) < 0 || pipe(p1) < 0) {
340     perror(progname);
341     exit(1);
342     }
343     if ((rt_pid = vfork()) == 0) { /* if child */
344     close(p0[1]);
345     close(p1[0]);
346     if (p0[0] != 0) { /* connect p0 to stdin */
347     dup2(p0[0], 0);
348     close(p0[0]);
349     }
350     if (p1[1] != 0) { /* connect p1 to stdout */
351     dup2(p1[1], 1);
352     close(p1[1]);
353     }
354     execvp(av[0], av);
355     perror(av[0]);
356     _exit(127);
357     }
358     if (rt_pid == -1) {
359     perror(progname);
360     exit(1);
361     }
362 greg 1.3 close(p0[0]);
363     close(p1[1]);
364 greg 1.1 fd_tort = p0[1];
365     fd_fromrt = p1[0];
366     }
367    
368    
369     done_rtrace() /* wait for rtrace to finish */
370     {
371     int pid, status;
372    
373     if (rt_pid == -1)
374     return;
375     close(fd_tort);
376     close(fd_fromrt);
377     while ((pid = wait(&status)) != -1 && pid != rt_pid)
378     ;
379     if (pid == rt_pid && status != 0) {
380     fprintf(stderr, "%s: bad status (%d) from rtrace\n",
381     progname, status);
382     exit(1);
383     }
384     rt_pid = -1;
385     }
386    
387    
388     int
389     readbuf(fd, bpos, siz)
390     int fd;
391     char *bpos;
392     int siz;
393     {
394     register int cc, nrem = siz;
395    
396     while (nrem > 0 && (cc = read(fd, bpos, nrem)) > 0) {
397     bpos += cc;
398     nrem -= cc;
399     }
400     if (cc < 0)
401     return(cc);
402     return(siz-nrem);
403     }
404    
405    
406     int
407     writebuf(fd, bpos, siz)
408     char *bpos;
409     int siz;
410     {
411     register int cc, nrem = siz;
412    
413     while (nrem > 0 && (cc = write(fd, bpos, nrem)) > 0) {
414     bpos += cc;
415     nrem -= cc;
416     }
417     if (cc < 0)
418     return(cc);
419     return(siz-nrem);
420 greg 1.8 }
421    
422    
423     SCAN *
424     scanretire() /* retire old scanlines to free list */
425     {
426     SCAN *sold[NRETIRE];
427     int n;
428     int h;
429     register SCAN *sl;
430     register int i;
431     /* grab the NRETIRE oldest scanlines */
432     sold[n = 0] = NULL;
433 greg 1.10 for (h = 0; h < HSIZE; h++)
434     for (sl = hashtab[h]; sl != NULL; sl = sl->next) {
435     for (i = n; i && sold[i-1]->lused > sl->lused; i--)
436     if (i < NRETIRE)
437 greg 1.8 sold[i] = sold[i-1];
438     if (i < NRETIRE) {
439 greg 1.10 sold[i] = sl;
440 greg 1.8 if (n < NRETIRE) /* grow list */
441     n++;
442 greg 1.10 }
443     }
444     /* put scanlines into free list */
445     for (i = 0; i < n; i++) {
446     h = shash(sold[i]->y);
447     sl = hashtab[h];
448     if (sl == sold[i])
449     hashtab[h] = sl->next;
450     else {
451     while (sl->next != sold[i]) /* IS in list */
452 greg 1.8 sl = sl->next;
453 greg 1.10 sl->next = sold[i]->next;
454 greg 1.8 }
455 greg 1.10 if (i > 0) { /* save oldest as return value */
456     sold[i]->next = freelist;
457     freelist = sold[i];
458     }
459 greg 1.8 }
460     return(sold[0]);
461     }
462    
463    
464     static char *scan_buf;
465    
466    
467     initscans() /* initialize scanline buffers */
468     {
469     int scansize;
470     register SCAN *ptr;
471     register int i;
472     /* initialize positions */
473     scanpos = (long *)malloc(pysiz*sizeof(long));
474     if (scanpos == NULL)
475     memerr("scanline positions");
476     for (i = pysiz-1; i >= 0; i--)
477     scanpos[i] = -1L;
478     curpos = pysiz-1;
479     /* clear hash table */
480     for (i = 0; i < HSIZE; i++)
481     hashtab[i] = NULL;
482     /* allocate scanline buffers */
483     scansize = sizeof(SCAN) + pxsiz*sizeof(COLR);
484     #ifdef ALIGN
485     scansize = scansize+(sizeof(ALIGN)-1)) & ~(sizeof(ALIGN)-1);
486     #endif
487     i = MAXSBUF / scansize; /* compute number to allocate */
488     if (i > HSIZE)
489     i = HSIZE;
490     scan_buf = malloc(i*scansize); /* get in one big chunk */
491     if (scan_buf == NULL)
492     memerr("scanline buffers");
493     ptr = (SCAN *)scan_buf;
494     freelist = NULL; /* build our free list */
495     while (i-- > 0) {
496     ptr->y = -1;
497     ptr->lused = -1;
498     ptr->next = freelist;
499     freelist = ptr;
500     ptr = (SCAN *)((char *)ptr + scansize); /* beware of C bugs */
501     }
502     }
503    
504    
505     donescans() /* free up scanlines */
506     {
507     free(scan_buf);
508     free((char *)scanpos);
509 greg 1.1 }