ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/glareval.c
Revision: 1.10
Committed: Fri Apr 5 14:41:55 1991 UTC (33 years ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.9: +20 -26 lines
Log Message:
improved and debugged retirescans()

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 1023980 /* 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 }
79 return(sl);
80 }
81 return(scanretire()); /* need more free scanlines */
82 }
83
84
85 COLR *
86 getpictscan(y) /* get picture scanline */
87 int y;
88 {
89 register SCAN *sl;
90 register int i;
91 /* first check our buffers */
92 sl = claimscan(y);
93 if (sl == NULL)
94 memerr("claimscan()");
95 sl->lused = ncall++;
96 if (sl->y == y) /* scan hit */
97 return(scandata(sl));
98 /* else read in replacement */
99 if (scanpos[y] < 0) { /* need to search */
100 for (i = y+1; i < curpos; i++)
101 if (scanpos[i] >= 0) {
102 if (fseek(pictfp, scanpos[i], 0) < 0)
103 goto seekerr;
104 curpos = i;
105 break;
106 }
107 while (curpos >= y) {
108 scanpos[curpos] = ftell(pictfp);
109 if (freadcolrs(scandata(sl), pxsiz, pictfp) < 0)
110 goto readerr;
111 nread++;
112 curpos--;
113 }
114 } else {
115 if (curpos != y && fseek(pictfp, scanpos[y], 0) < 0)
116 goto seekerr;
117 if (freadcolrs(scandata(sl), pxsiz, pictfp) < 0)
118 goto readerr;
119 nread++;
120 curpos = y-1;
121 }
122 sl->y = y;
123 i = shash(y); /* add to hash list */
124 sl->next = hashtab[i];
125 hashtab[i] = sl;
126 return(scandata(sl));
127 readerr:
128 fprintf(stderr, "%s: picture read error\n", progname);
129 exit(1);
130 seekerr:
131 fprintf(stderr, "%s: picture seek error\n", progname);
132 exit(1);
133 }
134
135
136 #ifdef DEBUG
137 pict_stats() /* print out picture read statistics */
138 {
139 static long lastcall = 0L; /* ncall at last report */
140 static long lastread = 0L; /* nread at last report */
141
142 if (ncall == lastcall)
143 return;
144 fprintf(stderr, "%s: %ld scanlines read in %ld calls\n",
145 progname, nread-lastread, ncall-lastcall);
146 lastcall = ncall;
147 lastread = nread;
148 }
149 #endif
150
151
152 double
153 pict_val(vd) /* find picture value for view direction */
154 FVECT vd;
155 {
156 FVECT pp;
157 double vpx, vpy, vpz;
158 COLOR res;
159
160 if (pictfp == NULL)
161 return(-1.0);
162 pp[0] = pictview.vp[0] + vd[0];
163 pp[1] = pictview.vp[1] + vd[1];
164 pp[2] = pictview.vp[2] + vd[2];
165 viewpixel(&vpx, &vpy, &vpz, &pictview, pp);
166 if (vpz <= FTINY || vpx < 0. || vpx >= 1. || vpy < 0. || vpy >= 1.)
167 return(-1.0);
168 colr_color(res, getpictscan((int)(vpy*pysiz))[(int)(vpx*pxsiz)]);
169 return(luminance(res)/exposure);
170 }
171
172
173 double
174 getviewpix(vh, vv) /* compute single view pixel */
175 int vh, vv;
176 {
177 FVECT dir;
178 float rt_buf[6];
179 double res;
180
181 if (compdir(dir, vh, vv) < 0)
182 return(-1.0);
183 npixinvw++;
184 if ((res = pict_val(dir)) >= 0.0)
185 return(res);
186 if (rt_pid == -1) {
187 npixmiss++;
188 return(-1.0);
189 }
190 rt_buf[0] = ourview.vp[0];
191 rt_buf[1] = ourview.vp[1];
192 rt_buf[2] = ourview.vp[2];
193 rt_buf[3] = dir[0];
194 rt_buf[4] = dir[1];
195 rt_buf[5] = dir[2];
196 rt_compute(rt_buf, 1);
197 return(luminance(rt_buf));
198 }
199
200
201 getviewspan(vv, vb) /* compute a span of view pixels */
202 int vv;
203 float *vb;
204 {
205 float rt_buf[6*MAXPIX]; /* rtrace send/receive buffer */
206 register int n; /* number of pixels in buffer */
207 short buf_vh[MAXPIX]; /* pixel positions */
208 FVECT dir;
209 register int vh;
210
211 #ifdef DEBUG
212 if (verbose)
213 fprintf(stderr, "%s: computing view span at %d...\n",
214 progname, vv);
215 #endif
216 n = 0;
217 for (vh = -hsize; vh <= hsize; vh++) {
218 if (compdir(dir, vh, vv) < 0) { /* off viewable region */
219 vb[vh+hsize] = -1.0;
220 continue;
221 }
222 npixinvw++;
223 if ((vb[vh+hsize] = pict_val(dir)) >= 0.0)
224 continue;
225 if (rt_pid == -1) { /* missing information */
226 npixmiss++;
227 continue;
228 }
229 /* send to rtrace */
230 if (n >= MAXPIX) { /* flush */
231 rt_compute(rt_buf, n);
232 while (n-- > 0)
233 vb[buf_vh[n]+hsize] = luminance(rt_buf+3*n);
234 }
235 rt_buf[6*n] = ourview.vp[0];
236 rt_buf[6*n+1] = ourview.vp[1];
237 rt_buf[6*n+2] = ourview.vp[2];
238 rt_buf[6*n+3] = dir[0];
239 rt_buf[6*n+4] = dir[1];
240 rt_buf[6*n+5] = dir[2];
241 buf_vh[n++] = vh;
242 }
243 #ifdef DEBUG
244 if (verbose)
245 pict_stats();
246 #endif
247 if (n > 0) { /* process pending buffer */
248 rt_compute(rt_buf, n);
249 while (n-- > 0)
250 vb[buf_vh[n]+hsize] = luminance(rt_buf+3*n);
251 }
252 }
253
254
255 rt_compute(pb, np) /* process buffer through rtrace */
256 float *pb;
257 int np;
258 {
259 static float nbuf[6] = {0.,0.,0.,0.,0.,0.};
260
261 #ifdef DEBUG
262 if (verbose && np > 1)
263 fprintf(stderr, "%s: sending %d samples to rtrace...\n",
264 progname, np);
265 #endif
266 if (writebuf(fd_tort,(char *)pb,6*sizeof(float)*np) < 6*sizeof(float)*np
267 || writebuf(fd_tort,(char *)nbuf,sizeof(nbuf)) < sizeof(nbuf)) {
268 fprintf(stderr, "%s: error writing to rtrace process\n",
269 progname);
270 exit(1);
271 }
272 if (readbuf(fd_fromrt, (char *)pb, 3*sizeof(float)*np)
273 < 3*sizeof(float)*np) {
274 fprintf(stderr, "%s: error reading from rtrace process\n",
275 progname);
276 exit(1);
277 }
278 }
279
280
281 getexpos(s) /* get exposure from header line */
282 char *s;
283 {
284 if (isexpos(s))
285 exposure *= exposval(s);
286 }
287
288
289 open_pict(fn) /* open picture file */
290 char *fn;
291 {
292 register int i;
293
294 if ((pictfp = fopen(fn, "r")) == NULL) {
295 fprintf("%s: cannot open\n", fn);
296 exit(1);
297 }
298 exposure = 1.0;
299 getheader(pictfp, getexpos);
300 if (fgetresolu(&pxsiz, &pysiz, pictfp) != (YMAJOR|YDECR)) {
301 fprintf("%s: bad picture resolution\n", fn);
302 exit(1);
303 }
304 initscans();
305 }
306
307
308 close_pict() /* done with picture */
309 {
310 register int i;
311
312 if (pictfp == NULL)
313 return;
314 fclose(pictfp);
315 donescans();
316 pictfp = NULL;
317 }
318
319
320 fork_rtrace(av) /* open pipe and start rtrace */
321 char *av[];
322 {
323 int p0[2], p1[2];
324
325 if (pipe(p0) < 0 || pipe(p1) < 0) {
326 perror(progname);
327 exit(1);
328 }
329 if ((rt_pid = vfork()) == 0) { /* if child */
330 close(p0[1]);
331 close(p1[0]);
332 if (p0[0] != 0) { /* connect p0 to stdin */
333 dup2(p0[0], 0);
334 close(p0[0]);
335 }
336 if (p1[1] != 0) { /* connect p1 to stdout */
337 dup2(p1[1], 1);
338 close(p1[1]);
339 }
340 execvp(av[0], av);
341 perror(av[0]);
342 _exit(127);
343 }
344 if (rt_pid == -1) {
345 perror(progname);
346 exit(1);
347 }
348 close(p0[0]);
349 close(p1[1]);
350 fd_tort = p0[1];
351 fd_fromrt = p1[0];
352 }
353
354
355 done_rtrace() /* wait for rtrace to finish */
356 {
357 int pid, status;
358
359 if (rt_pid == -1)
360 return;
361 close(fd_tort);
362 close(fd_fromrt);
363 while ((pid = wait(&status)) != -1 && pid != rt_pid)
364 ;
365 if (pid == rt_pid && status != 0) {
366 fprintf(stderr, "%s: bad status (%d) from rtrace\n",
367 progname, status);
368 exit(1);
369 }
370 rt_pid = -1;
371 }
372
373
374 int
375 readbuf(fd, bpos, siz)
376 int fd;
377 char *bpos;
378 int siz;
379 {
380 register int cc, nrem = siz;
381
382 while (nrem > 0 && (cc = read(fd, bpos, nrem)) > 0) {
383 bpos += cc;
384 nrem -= cc;
385 }
386 if (cc < 0)
387 return(cc);
388 return(siz-nrem);
389 }
390
391
392 int
393 writebuf(fd, bpos, siz)
394 char *bpos;
395 int siz;
396 {
397 register int cc, nrem = siz;
398
399 while (nrem > 0 && (cc = write(fd, bpos, nrem)) > 0) {
400 bpos += cc;
401 nrem -= cc;
402 }
403 if (cc < 0)
404 return(cc);
405 return(siz-nrem);
406 }
407
408
409 SCAN *
410 scanretire() /* retire old scanlines to free list */
411 {
412 SCAN *sold[NRETIRE];
413 int n;
414 int h;
415 register SCAN *sl;
416 register int i;
417 /* grab the NRETIRE oldest scanlines */
418 sold[n = 0] = NULL;
419 for (h = 0; h < HSIZE; h++)
420 for (sl = hashtab[h]; sl != NULL; sl = sl->next) {
421 for (i = n; i && sold[i-1]->lused > sl->lused; i--)
422 if (i < NRETIRE)
423 sold[i] = sold[i-1];
424 if (i < NRETIRE) {
425 sold[i] = sl;
426 if (n < NRETIRE) /* grow list */
427 n++;
428 }
429 }
430 /* put scanlines into free list */
431 for (i = 0; i < n; i++) {
432 h = shash(sold[i]->y);
433 sl = hashtab[h];
434 if (sl == sold[i])
435 hashtab[h] = sl->next;
436 else {
437 while (sl->next != sold[i]) /* IS in list */
438 sl = sl->next;
439 sl->next = sold[i]->next;
440 }
441 if (i > 0) { /* save oldest as return value */
442 sold[i]->next = freelist;
443 freelist = sold[i];
444 }
445 }
446 return(sold[0]);
447 }
448
449
450 static char *scan_buf;
451
452
453 initscans() /* initialize scanline buffers */
454 {
455 int scansize;
456 register SCAN *ptr;
457 register int i;
458 /* initialize positions */
459 scanpos = (long *)malloc(pysiz*sizeof(long));
460 if (scanpos == NULL)
461 memerr("scanline positions");
462 for (i = pysiz-1; i >= 0; i--)
463 scanpos[i] = -1L;
464 curpos = pysiz-1;
465 /* clear hash table */
466 for (i = 0; i < HSIZE; i++)
467 hashtab[i] = NULL;
468 /* allocate scanline buffers */
469 scansize = sizeof(SCAN) + pxsiz*sizeof(COLR);
470 #ifdef ALIGN
471 scansize = scansize+(sizeof(ALIGN)-1)) & ~(sizeof(ALIGN)-1);
472 #endif
473 i = MAXSBUF / scansize; /* compute number to allocate */
474 if (i > HSIZE)
475 i = HSIZE;
476 scan_buf = malloc(i*scansize); /* get in one big chunk */
477 if (scan_buf == NULL)
478 memerr("scanline buffers");
479 ptr = (SCAN *)scan_buf;
480 freelist = NULL; /* build our free list */
481 while (i-- > 0) {
482 ptr->y = -1;
483 ptr->lused = -1;
484 ptr->next = freelist;
485 freelist = ptr;
486 ptr = (SCAN *)((char *)ptr + scansize); /* beware of C bugs */
487 }
488 }
489
490
491 donescans() /* free up scanlines */
492 {
493 free(scan_buf);
494 free((char *)scanpos);
495 }