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, 2 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

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: glareval.c,v 2.10 2003/07/03 22:41:45 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 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
64
65 static SCAN *
66 claimscan( /* claim scanline from buffers */
67 int y
68 )
69 {
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 nrecl++;
87 }
88 return(sl);
89 }
90 return(scanretire()); /* need more free scanlines */
91 }
92
93
94 static COLR *
95 getpictscan( /* get picture scanline */
96 int y
97 )
98 {
99 register SCAN *sl;
100 register int i;
101 /* first check our buffers */
102 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 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 scanpos[curpos] = ftell(pictfp);
119 if (freadcolrs(scandata(sl), pxsiz, pictfp) < 0)
120 goto readerr;
121 nread++;
122 curpos--;
123 }
124 } else {
125 if (curpos != y && fseek(pictfp, scanpos[y], 0) < 0)
126 goto seekerr;
127 if (freadcolrs(scandata(sl), pxsiz, pictfp) < 0)
128 goto readerr;
129 nread++;
130 curpos = y-1;
131 }
132 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 readerr:
138 fprintf(stderr, "%s: picture read error\n", progname);
139 exit(1);
140 seekerr:
141 fprintf(stderr, "%s: picture seek error\n", progname);
142 exit(1);
143 }
144
145
146 #ifdef DEBUG
147 static void
148 pict_stats(void) /* print out picture read statistics */
149 {
150 static long lastcall = 0L; /* ncall at last report */
151 static long lastread = 0L; /* nread at last report */
152 static long lastrecl = 0L; /* nrecl at last report */
153
154 if (ncall == lastcall)
155 return;
156 fprintf(stderr, "%s: %ld scanlines read (%ld reclaimed) in %ld calls\n",
157 progname, nread-lastread, nrecl-lastrecl, ncall-lastcall);
158 lastcall = ncall;
159 lastread = nread;
160 lastrecl = nrecl;
161 }
162 #endif
163
164
165 static double
166 pict_val( /* find picture value for view direction */
167 FVECT vd
168 )
169 {
170 FVECT pp;
171 FVECT ip;
172 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 viewloc(ip, &pictview, pp);
180 if (ip[2] <= FTINY || ip[0] < 0. || ip[0] >= 1. ||
181 ip[1] < 0. || ip[1] >= 1.)
182 return(-1.0);
183 colr_color(res, getpictscan((int)(ip[1]*pysiz))[(int)(ip[0]*pxsiz)]);
184 return(luminance(res)/exposure);
185 }
186
187
188 extern double
189 getviewpix( /* compute single view pixel */
190 int vh,
191 int vv
192 )
193 {
194 FVECT dir;
195 float rt_buf[12];
196 double res;
197
198 if (compdir(dir, vh, vv) < 0)
199 return(-1.0);
200 npixinvw++;
201 if ((res = pict_val(dir)) >= 0.0)
202 return(res);
203 if (rt_pd.r == -1) {
204 npixmiss++;
205 return(-1.0);
206 }
207 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 extern void
219 getviewspan( /* compute a span of view pixels */
220 int vv,
221 float *vb
222 )
223 {
224 float rt_buf[6*MAXPIX]; /* rtrace send/receive buffer */
225 register int n; /* number of pixels in buffer */
226 short buf_vh[MAXPIX]; /* pixel positions */
227 FVECT dir;
228 register int vh;
229
230 #ifdef DEBUG
231 if (verbose)
232 fprintf(stderr, "%s: computing view span at %d...\n",
233 progname, vv);
234 #endif
235 n = 0;
236 for (vh = -hsize; vh <= hsize; vh++) {
237 if (compdir(dir, vh, vv) < 0) { /* not in view */
238 vb[vh+hsize] = -1.0;
239 continue;
240 }
241 npixinvw++;
242 if ((vb[vh+hsize] = pict_val(dir)) >= 0.0)
243 continue;
244 if (rt_pd.r == -1) { /* missing information */
245 npixmiss++;
246 continue;
247 }
248 /* send to rtrace */
249 if (n >= maxpix) { /* flush */
250 rt_compute(rt_buf, n);
251 while (n-- > 0)
252 vb[buf_vh[n]+hsize] = luminance(rt_buf+3*n);
253 }
254 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 }
262 #ifdef DEBUG
263 if (verbose)
264 pict_stats();
265 #endif
266 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 }
272
273
274 static void
275 rt_compute( /* process buffer through rtrace */
276 float *pb,
277 int np
278 )
279 {
280 #ifdef DEBUG
281 if (verbose && np > 1)
282 fprintf(stderr, "%s: sending %d samples to rtrace...\n",
283 progname, np);
284 #endif
285 memset(pb+6*np, '\0', 6*sizeof(float));
286 if (process(&rt_pd, (char *)pb, (char *)pb, 3*sizeof(float)*(np+1),
287 6*sizeof(float)*(np+1)) < 3*sizeof(float)*(np+1)) {
288 fprintf(stderr, "%s: rtrace communication error\n",
289 progname);
290 exit(1);
291 }
292 }
293
294
295 static int
296 getexpos( /* get exposure from header line */
297 char *s,
298 void *p
299 )
300 {
301 char fmt[32];
302
303 if (isexpos(s))
304 exposure *= exposval(s);
305 else if (isformat(s)) {
306 formatval(fmt, s);
307 wrongformat = strcmp(fmt, COLRFMT);
308 }
309 return(0);
310 }
311
312
313 extern void
314 open_pict( /* open picture file */
315 char *fn
316 )
317 {
318 if ((pictfp = fopen(fn, "r")) == NULL) {
319 fprintf(stderr, "%s: cannot open\n", fn);
320 exit(1);
321 }
322 exposure = 1.0;
323 getheader(pictfp, getexpos, NULL);
324 if (wrongformat || !fscnresolu(&pxsiz, &pysiz, pictfp)) {
325 fprintf(stderr, "%s: incompatible picture format\n", fn);
326 exit(1);
327 }
328 initscans();
329 }
330
331
332 extern void
333 close_pict(void) /* done with picture */
334 {
335 if (pictfp == NULL)
336 return;
337 fclose(pictfp);
338 donescans();
339 pictfp = NULL;
340 }
341
342
343 extern void
344 fork_rtrace( /* open pipe and start rtrace */
345 char *av[]
346 )
347 {
348 int rval;
349
350 rval = open_process(&rt_pd, av);
351 if (rval < 0) {
352 perror(progname);
353 exit(1);
354 }
355 if (rval == 0) {
356 fprintf(stderr, "%s: command not found\n", av[0]);
357 exit(1);
358 }
359 maxpix = rval/(6*sizeof(float));
360 if (maxpix > MAXPIX)
361 maxpix = MAXPIX;
362 maxpix--;
363 }
364
365
366 extern void
367 done_rtrace(void) /* wait for rtrace to finish */
368 {
369 int status;
370
371 status = close_process(&rt_pd);
372 if (status > 0) {
373 fprintf(stderr, "%s: bad status (%d) from rtrace\n",
374 progname, status);
375 exit(1);
376 }
377 rt_pd.r = -1;
378 }
379
380
381 static SCAN *
382 scanretire(void) /* retire old scanlines to free list */
383 {
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 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 sold[i] = sold[i-1];
396 if (i < NRETIRE) {
397 sold[i] = sl;
398 if (n < NRETIRE) /* grow list */
399 n++;
400 }
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 sl = sl->next;
411 sl->next = sold[i]->next;
412 }
413 if (i > 0) { /* save oldest as return value */
414 sold[i]->next = freelist;
415 freelist = sold[i];
416 }
417 }
418 return(sold[0]);
419 }
420
421
422 static char *scan_buf;
423
424
425 static void
426 initscans(void) /* initialize scanline buffers */
427 {
428 int scansize;
429 register SCAN *ptr;
430 register int i;
431 /* initialize positions */
432 scanpos = (long *)bmalloc(pysiz*sizeof(long));
433 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 #ifdef ALIGNT
444 scansize = scansize+(sizeof(ALIGNT)-1) & ~(sizeof(ALIGNT)-1);
445 #endif
446 i = MAXSBUF / scansize; /* compute number to allocate */
447 if (i > HSIZE)
448 i = HSIZE;
449 scanbufsiz = i*scansize;
450 scan_buf = bmalloc(scanbufsiz); /* get in one big chunk */
451 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 static void
466 donescans(void) /* free up scanlines */
467 {
468 bfree(scan_buf, scanbufsiz);
469 bfree((char *)scanpos, pysiz*sizeof(long));
470 }