ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/glareval.c
Revision: 1.14
Committed: Fri Apr 19 17:41:06 1991 UTC (33 years ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.13: +3 -6 lines
Log Message:
fixed computation of solid angle changed compdir()

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) /* compute single view pixel */
183 int vh, vv;
184 {
185 FVECT dir;
186 float rt_buf[6];
187 double res;
188
189 if (compdir(dir, vh, vv) < 0)
190 return(-1.0);
191 npixinvw++;
192 if ((res = pict_val(dir)) >= 0.0)
193 return(res);
194 if (rt_pid == -1) {
195 npixmiss++;
196 return(-1.0);
197 }
198 rt_buf[0] = ourview.vp[0];
199 rt_buf[1] = ourview.vp[1];
200 rt_buf[2] = ourview.vp[2];
201 rt_buf[3] = dir[0];
202 rt_buf[4] = dir[1];
203 rt_buf[5] = dir[2];
204 rt_compute(rt_buf, 1);
205 return(luminance(rt_buf));
206 }
207
208
209 getviewspan(vv, vb) /* compute a span of view pixels */
210 int vv;
211 float *vb;
212 {
213 float rt_buf[6*MAXPIX]; /* rtrace send/receive buffer */
214 register int n; /* number of pixels in buffer */
215 short buf_vh[MAXPIX]; /* pixel positions */
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 n = 0;
225 for (vh = -hsize; vh <= hsize; vh++) {
226 if (compdir(dir, vh, vv) < 0) { /* not in view */
227 vb[vh+hsize] = -1.0;
228 continue;
229 }
230 npixinvw++;
231 if ((vb[vh+hsize] = pict_val(dir)) >= 0.0)
232 continue;
233 if (rt_pid == -1) { /* missing information */
234 npixmiss++;
235 continue;
236 }
237 /* send to rtrace */
238 if (n >= MAXPIX) { /* flush */
239 rt_compute(rt_buf, n);
240 while (n-- > 0)
241 vb[buf_vh[n]+hsize] = luminance(rt_buf+3*n);
242 }
243 rt_buf[6*n] = ourview.vp[0];
244 rt_buf[6*n+1] = ourview.vp[1];
245 rt_buf[6*n+2] = ourview.vp[2];
246 rt_buf[6*n+3] = dir[0];
247 rt_buf[6*n+4] = dir[1];
248 rt_buf[6*n+5] = dir[2];
249 buf_vh[n++] = vh;
250 }
251 #ifdef DEBUG
252 if (verbose)
253 pict_stats();
254 #endif
255 if (n > 0) { /* process pending buffer */
256 rt_compute(rt_buf, n);
257 while (n-- > 0)
258 vb[buf_vh[n]+hsize] = luminance(rt_buf+3*n);
259 }
260 }
261
262
263 rt_compute(pb, np) /* process buffer through rtrace */
264 float *pb;
265 int np;
266 {
267 static float nbuf[6] = {0.,0.,0.,0.,0.,0.};
268
269 #ifdef DEBUG
270 if (verbose && np > 1)
271 fprintf(stderr, "%s: sending %d samples to rtrace...\n",
272 progname, np);
273 #endif
274 if (writebuf(fd_tort,(char *)pb,6*sizeof(float)*np) < 6*sizeof(float)*np
275 || writebuf(fd_tort,(char *)nbuf,sizeof(nbuf)) < sizeof(nbuf)) {
276 fprintf(stderr, "%s: error writing to rtrace process\n",
277 progname);
278 exit(1);
279 }
280 if (readbuf(fd_fromrt, (char *)pb, 3*sizeof(float)*np)
281 < 3*sizeof(float)*np) {
282 fprintf(stderr, "%s: error reading from rtrace process\n",
283 progname);
284 exit(1);
285 }
286 }
287
288
289 getexpos(s) /* get exposure from header line */
290 char *s;
291 {
292 char fmt[32];
293
294 if (isexpos(s))
295 exposure *= exposval(s);
296 else if (isformat(s)) {
297 formatval(fmt, s);
298 wrongformat = strcmp(fmt, COLRFMT);
299 }
300 }
301
302
303 open_pict(fn) /* open picture file */
304 char *fn;
305 {
306 if ((pictfp = fopen(fn, "r")) == NULL) {
307 fprintf("%s: cannot open\n", fn);
308 exit(1);
309 }
310 exposure = 1.0;
311 getheader(pictfp, getexpos, NULL);
312 if (wrongformat ||
313 fgetresolu(&pxsiz, &pysiz, pictfp) != (YMAJOR|YDECR)) {
314 fprintf("%s: bad picture format\n", fn);
315 exit(1);
316 }
317 initscans();
318 }
319
320
321 close_pict() /* done with picture */
322 {
323 if (pictfp == NULL)
324 return;
325 fclose(pictfp);
326 donescans();
327 pictfp = NULL;
328 }
329
330
331 fork_rtrace(av) /* open pipe and start rtrace */
332 char *av[];
333 {
334 int p0[2], p1[2];
335
336 if (pipe(p0) < 0 || pipe(p1) < 0) {
337 perror(progname);
338 exit(1);
339 }
340 if ((rt_pid = vfork()) == 0) { /* if child */
341 close(p0[1]);
342 close(p1[0]);
343 if (p0[0] != 0) { /* connect p0 to stdin */
344 dup2(p0[0], 0);
345 close(p0[0]);
346 }
347 if (p1[1] != 0) { /* connect p1 to stdout */
348 dup2(p1[1], 1);
349 close(p1[1]);
350 }
351 execvp(av[0], av);
352 perror(av[0]);
353 _exit(127);
354 }
355 if (rt_pid == -1) {
356 perror(progname);
357 exit(1);
358 }
359 close(p0[0]);
360 close(p1[1]);
361 fd_tort = p0[1];
362 fd_fromrt = p1[0];
363 }
364
365
366 done_rtrace() /* wait for rtrace to finish */
367 {
368 int pid, status;
369
370 if (rt_pid == -1)
371 return;
372 close(fd_tort);
373 close(fd_fromrt);
374 while ((pid = wait(&status)) != -1 && pid != rt_pid)
375 ;
376 if (pid == rt_pid && status != 0) {
377 fprintf(stderr, "%s: bad status (%d) from rtrace\n",
378 progname, status);
379 exit(1);
380 }
381 rt_pid = -1;
382 }
383
384
385 int
386 readbuf(fd, bpos, siz)
387 int fd;
388 char *bpos;
389 int siz;
390 {
391 register int cc, nrem = siz;
392
393 while (nrem > 0 && (cc = read(fd, bpos, nrem)) > 0) {
394 bpos += cc;
395 nrem -= cc;
396 }
397 if (cc < 0)
398 return(cc);
399 return(siz-nrem);
400 }
401
402
403 int
404 writebuf(fd, bpos, siz)
405 char *bpos;
406 int siz;
407 {
408 register int cc, nrem = siz;
409
410 while (nrem > 0 && (cc = write(fd, bpos, nrem)) > 0) {
411 bpos += cc;
412 nrem -= cc;
413 }
414 if (cc < 0)
415 return(cc);
416 return(siz-nrem);
417 }
418
419
420 SCAN *
421 scanretire() /* retire old scanlines to free list */
422 {
423 SCAN *sold[NRETIRE];
424 int n;
425 int h;
426 register SCAN *sl;
427 register int i;
428 /* grab the NRETIRE oldest scanlines */
429 sold[n = 0] = NULL;
430 for (h = 0; h < HSIZE; h++)
431 for (sl = hashtab[h]; sl != NULL; sl = sl->next) {
432 for (i = n; i && sold[i-1]->lused > sl->lused; i--)
433 if (i < NRETIRE)
434 sold[i] = sold[i-1];
435 if (i < NRETIRE) {
436 sold[i] = sl;
437 if (n < NRETIRE) /* grow list */
438 n++;
439 }
440 }
441 /* put scanlines into free list */
442 for (i = 0; i < n; i++) {
443 h = shash(sold[i]->y);
444 sl = hashtab[h];
445 if (sl == sold[i])
446 hashtab[h] = sl->next;
447 else {
448 while (sl->next != sold[i]) /* IS in list */
449 sl = sl->next;
450 sl->next = sold[i]->next;
451 }
452 if (i > 0) { /* save oldest as return value */
453 sold[i]->next = freelist;
454 freelist = sold[i];
455 }
456 }
457 return(sold[0]);
458 }
459
460
461 static char *scan_buf;
462
463
464 initscans() /* initialize scanline buffers */
465 {
466 int scansize;
467 register SCAN *ptr;
468 register int i;
469 /* initialize positions */
470 scanpos = (long *)malloc(pysiz*sizeof(long));
471 if (scanpos == NULL)
472 memerr("scanline positions");
473 for (i = pysiz-1; i >= 0; i--)
474 scanpos[i] = -1L;
475 curpos = pysiz-1;
476 /* clear hash table */
477 for (i = 0; i < HSIZE; i++)
478 hashtab[i] = NULL;
479 /* allocate scanline buffers */
480 scansize = sizeof(SCAN) + pxsiz*sizeof(COLR);
481 #ifdef ALIGN
482 scansize = scansize+(sizeof(ALIGN)-1)) & ~(sizeof(ALIGN)-1);
483 #endif
484 i = MAXSBUF / scansize; /* compute number to allocate */
485 if (i > HSIZE)
486 i = HSIZE;
487 scan_buf = malloc(i*scansize); /* get in one big chunk */
488 if (scan_buf == NULL)
489 memerr("scanline buffers");
490 ptr = (SCAN *)scan_buf;
491 freelist = NULL; /* build our free list */
492 while (i-- > 0) {
493 ptr->y = -1;
494 ptr->lused = -1;
495 ptr->next = freelist;
496 freelist = ptr;
497 ptr = (SCAN *)((char *)ptr + scansize); /* beware of C bugs */
498 }
499 }
500
501
502 donescans() /* free up scanlines */
503 {
504 free(scan_buf);
505 free((char *)scanpos);
506 }