ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/glareval.c
Revision: 2.10
Committed: Thu Jul 3 22:41:45 2003 UTC (20 years, 9 months ago) by schorsch
Content type: text/plain
Branch: MAIN
Changes since 2.9: +2 -1 lines
Log Message:
Reduced compile problems on Windows.

File Contents

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