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 (33 years 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

# Content
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 #define MAXSBUF 524268 /* maximum total size of scanline buffer */
24 #define HSIZE 317 /* size of scanline hash table */
25 #define NRETIRE 16 /* number of scanlines to retire at once */
26
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
34 static int curpos; /* current scanline */
35 static long *scanpos; /* scanline positions */
36
37 typedef struct scan {
38 int y; /* scanline position */
39 long lused; /* for LRU replacement */
40 struct scan *next; /* next in this hash or free list */
41 /* followed by the scanline data */
42 } SCAN; /* buffered scanline */
43
44 #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 static long ncall = 0L; /* number of calls to getpictscan */
51 static long nread = 0L; /* number of scanlines read */
52
53 SCAN *scanretire();
54
55 extern long ftell();
56
57
58 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 #ifdef DEBUG
79 if (verbose)
80 fprintf(stderr,
81 "%s: scanline %d reclaimed\n",
82 progname, y);
83 #endif
84 }
85 return(sl);
86 }
87 return(scanretire()); /* need more free scanlines */
88 }
89
90
91 COLR *
92 getpictscan(y) /* get picture scanline */
93 int y;
94 {
95 register SCAN *sl;
96 register int i;
97 /* first check our buffers */
98 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 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 scanpos[curpos] = ftell(pictfp);
115 if (freadcolrs(scandata(sl), pxsiz, pictfp) < 0)
116 goto readerr;
117 nread++;
118 curpos--;
119 }
120 } else {
121 if (curpos != y && fseek(pictfp, scanpos[y], 0) < 0)
122 goto seekerr;
123 if (freadcolrs(scandata(sl), pxsiz, pictfp) < 0)
124 goto readerr;
125 nread++;
126 curpos = y-1;
127 }
128 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 readerr:
134 fprintf(stderr, "%s: picture read error\n", progname);
135 exit(1);
136 seekerr:
137 fprintf(stderr, "%s: picture seek error\n", progname);
138 exit(1);
139 }
140
141
142 #ifdef DEBUG
143 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 fprintf(stderr, "%s: %ld scanlines read in %ld calls\n",
151 progname, nread-lastread, ncall-lastcall);
152 lastcall = ncall;
153 lastread = nread;
154 }
155 #endif
156
157
158 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 getviewpix(vh, vv, se) /* compute single view pixel */
181 int vh, vv;
182 SPANERR *se;
183 {
184 FVECT dir;
185 float rt_buf[6];
186 double res;
187
188 if (compdir(dir, vh, vv, se) < 0)
189 return(-1.0);
190 npixinvw++;
191 if ((res = pict_val(dir)) >= 0.0)
192 return(res);
193 if (rt_pid == -1) {
194 npixmiss++;
195 return(-1.0);
196 }
197 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 register int n; /* number of pixels in buffer */
214 short buf_vh[MAXPIX]; /* pixel positions */
215 SPANERR sperr;
216 FVECT dir;
217 register int vh;
218
219 #ifdef DEBUG
220 if (verbose)
221 fprintf(stderr, "%s: computing view span at %d...\n",
222 progname, vv);
223 #endif
224 setspanerr(&sperr, vv);
225 n = 0;
226 for (vh = -hsize; vh <= hsize; vh++) {
227 if (compdir(dir, vh, vv, &sperr) < 0) { /* not in view */
228 vb[vh+hsize] = -1.0;
229 continue;
230 }
231 npixinvw++;
232 if ((vb[vh+hsize] = pict_val(dir)) >= 0.0)
233 continue;
234 if (rt_pid == -1) { /* missing information */
235 npixmiss++;
236 continue;
237 }
238 /* send to rtrace */
239 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 }
244 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 }
252 #ifdef DEBUG
253 if (verbose)
254 pict_stats();
255 #endif
256 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 }
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 #ifdef DEBUG
271 if (verbose && np > 1)
272 fprintf(stderr, "%s: sending %d samples to rtrace...\n",
273 progname, np);
274 #endif
275 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 initscans();
312 }
313
314
315 close_pict() /* done with picture */
316 {
317 if (pictfp == NULL)
318 return;
319 fclose(pictfp);
320 donescans();
321 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 close(p0[0]);
354 close(p1[1]);
355 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 }
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 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 sold[i] = sold[i-1];
429 if (i < NRETIRE) {
430 sold[i] = sl;
431 if (n < NRETIRE) /* grow list */
432 n++;
433 }
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 sl = sl->next;
444 sl->next = sold[i]->next;
445 }
446 if (i > 0) { /* save oldest as return value */
447 sold[i]->next = freelist;
448 freelist = sold[i];
449 }
450 }
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 }