ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/glareval.c
Revision: 1.13
Committed: Thu Apr 18 15:18:25 1991 UTC (32 years, 11 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.12: +12 -3 lines
Log Message:
added format information to headers

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