ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/glareval.c
Revision: 2.6
Committed: Sat Feb 22 02:07:30 2003 UTC (21 years, 1 month ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R5
Changes since 2.5: +2 -6 lines
Log Message:
Changes and check-in for 3.5 release
Includes new source files and modifications not recorded for many years
See ray/doc/notes/ReleaseNotes for notes between 3.1 and 3.5 release

File Contents

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