ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/glareval.c
Revision: 1.12
Committed: Fri Apr 12 10:28:34 1991 UTC (32 years, 11 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.11: +6 -7 lines
Log Message:
minor changes and bug fixes

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