ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/glareval.c
Revision: 2.11
Committed: Fri Jan 2 12:48:36 2004 UTC (20 years, 3 months ago) by schorsch
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R7P2, rad3R7P1, rad3R6, rad3R6P1
Changes since 2.10: +61 -36 lines
Log Message:
Ansification and fixed typing/prototype of getheader() and its callback.

File Contents

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