ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/pinterp.c
Revision: 1.25
Committed: Tue Mar 6 11:14:36 1990 UTC (34 years, 2 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.24: +52 -34 lines
Log Message:
added sampling

File Contents

# User Rev Content
1 greg 1.1 #ifndef lint
2     static char SCCSid[] = "$SunId$ LBL";
3     #endif
4    
5     /*
6     * Interpolate and extrapolate pictures with different view parameters.
7     *
8     * Greg Ward 09Dec89
9     */
10    
11     #include "standard.h"
12    
13 greg 1.24 #include <fcntl.h>
14 greg 1.19
15 greg 1.1 #include "view.h"
16    
17     #include "color.h"
18    
19 greg 1.25 #include "random.h"
20    
21 greg 1.21 #ifndef BSD
22     #define vfork fork
23     #endif
24    
25 greg 1.17 #define pscan(y) (ourpict+(y)*hresolu)
26     #define zscan(y) (ourzbuf+(y)*hresolu)
27 greg 1.1
28 greg 1.25 #define PMASK 0xfffffff /* probability mask */
29     #define sampval(x) (long)((x)*(PMASK+1)+.5)
30     #define samp(p) ((p) > (random()&PMASK))
31    
32 greg 1.13 #define F_FORE 1 /* fill foreground */
33     #define F_BACK 2 /* fill background */
34 greg 1.11
35 greg 1.13 #define PACKSIZ 42 /* calculation packet size */
36    
37 greg 1.25 #define RTCOM "rtrace -h -ovl -fff %s"
38 greg 1.13
39 greg 1.3 #define ABS(x) ((x)>0?(x):-(x))
40    
41 greg 1.15 struct position {int x,y; float z;};
42    
43 greg 1.17 VIEW ourview = STDVIEW; /* desired view */
44     int hresolu = 512; /* horizontal resolution */
45     int vresolu = 512; /* vertical resolution */
46 greg 1.18 double pixaspect = 1.0; /* pixel aspect ratio */
47 greg 1.1
48 greg 1.8 double zeps = .02; /* allowed z epsilon */
49 greg 1.1
50     COLR *ourpict; /* output picture */
51     float *ourzbuf; /* corresponding z-buffer */
52    
53     char *progname;
54    
55 greg 1.25 int fillo = F_FORE|F_BACK; /* selected fill options */
56     long sampprob = 0; /* sample probability */
57 greg 1.14 extern int backfill(), rcalfill(); /* fill functions */
58 greg 1.25 int (*fillfunc)() = backfill; /* selected fill function */
59 greg 1.11 COLR backcolr = BLKCOLR; /* background color */
60 greg 1.13 double backz = 0.0; /* background z value */
61 greg 1.16 int normdist = 1; /* normalized distance? */
62     double ourexp = -1; /* output picture exposure */
63 greg 1.11
64 greg 1.17 VIEW theirview = STDVIEW; /* input view */
65 greg 1.16 int gotview; /* got input view? */
66 greg 1.17 int thresolu, tvresolu; /* input resolution */
67     double theirexp; /* input picture exposure */
68 greg 1.5 double theirs2ours[4][4]; /* transformation matrix */
69 greg 1.1
70 greg 1.14 int childpid = -1; /* id of fill process */
71 greg 1.13 FILE *psend, *precv; /* pipes to/from fill calculation */
72     int queue[PACKSIZ][2]; /* pending pixels */
73     int queuesiz; /* number of pixels pending */
74 greg 1.5
75 greg 1.13
76 greg 1.1 main(argc, argv) /* interpolate pictures */
77     int argc;
78     char *argv[];
79     {
80     #define check(olen,narg) if (argv[i][olen] || narg >= argc-i) goto badopt
81 greg 1.11 extern double atof();
82 greg 1.1 int gotvfile = 0;
83 greg 1.11 char *zfile = NULL;
84 greg 1.1 char *err;
85 greg 1.17 int i, rval;
86 greg 1.1
87     progname = argv[0];
88    
89 greg 1.17 for (i = 1; i < argc && argv[i][0] == '-'; i++) {
90     rval = getviewopt(&ourview, argc-i, argv+i);
91     if (rval >= 0) {
92     i += rval;
93     continue;
94     }
95 greg 1.1 switch (argv[i][1]) {
96     case 't': /* threshold */
97     check(2,1);
98     zeps = atof(argv[++i]);
99     break;
100 greg 1.11 case 'n': /* dist. normalized? */
101 greg 1.10 check(2,0);
102 greg 1.11 normdist = !normdist;
103 greg 1.10 break;
104 greg 1.11 case 'f': /* fill type */
105     switch (argv[i][2]) {
106     case '0': /* none */
107     check(3,0);
108 greg 1.25 fillo = 0;
109 greg 1.11 break;
110     case 'f': /* foreground */
111     check(3,0);
112 greg 1.25 fillo = F_FORE;
113 greg 1.11 break;
114     case 'b': /* background */
115     check(3,0);
116 greg 1.25 fillo = F_BACK;
117 greg 1.11 break;
118     case 'a': /* all */
119     check(3,0);
120 greg 1.25 fillo = F_FORE|F_BACK;
121 greg 1.11 break;
122 greg 1.25 case 's': /* sample */
123     check(3,1);
124     sampprob = sampval(atof(argv[++i]));
125     break;
126 greg 1.11 case 'c': /* color */
127     check(3,3);
128 greg 1.25 fillfunc = backfill;
129 greg 1.11 setcolr(backcolr, atof(argv[i+1]),
130     atof(argv[i+2]), atof(argv[i+3]));
131     i += 3;
132     break;
133 greg 1.13 case 'z': /* z value */
134     check(3,1);
135 greg 1.25 fillfunc = backfill;
136 greg 1.13 backz = atof(argv[++i]);
137     break;
138     case 'r': /* rtrace */
139     check(3,1);
140 greg 1.25 fillfunc = rcalfill;
141 greg 1.13 calstart(RTCOM, argv[++i]);
142     break;
143 greg 1.11 default:
144     goto badopt;
145     }
146     break;
147     case 'z': /* z file */
148     check(2,1);
149     zfile = argv[++i];
150     break;
151 greg 1.6 case 'x': /* x resolution */
152     check(2,1);
153 greg 1.17 hresolu = atoi(argv[++i]);
154 greg 1.6 break;
155     case 'y': /* y resolution */
156     check(2,1);
157 greg 1.17 vresolu = atoi(argv[++i]);
158 greg 1.6 break;
159 greg 1.18 case 'p': /* pixel aspect */
160     check(2,1);
161     pixaspect = atof(argv[++i]);
162     break;
163 greg 1.17 case 'v': /* view file */
164     if (argv[i][2] != 'f')
165 greg 1.1 goto badopt;
166 greg 1.17 check(3,1);
167 greg 1.19 gotvfile = viewfile(argv[++i], &ourview, 0, 0);
168 greg 1.17 if (gotvfile < 0) {
169     perror(argv[i]);
170     exit(1);
171     } else if (gotvfile == 0) {
172     fprintf(stderr, "%s: bad view file\n",
173     argv[i]);
174     exit(1);
175 greg 1.1 }
176     break;
177     default:
178     badopt:
179 greg 1.10 fprintf(stderr, "%s: command line error at '%s'\n",
180 greg 1.1 progname, argv[i]);
181 greg 1.10 goto userr;
182 greg 1.1 }
183 greg 1.17 }
184 greg 1.1 /* check arguments */
185 greg 1.13 if ((argc-i)%2)
186 greg 1.10 goto userr;
187 greg 1.1 /* set view */
188     if (err = setview(&ourview)) {
189     fprintf(stderr, "%s: %s\n", progname, err);
190     exit(1);
191     }
192 greg 1.18 normaspect(viewaspect(&ourview), &pixaspect, &hresolu, &vresolu);
193 greg 1.1 /* allocate frame */
194 greg 1.17 ourpict = (COLR *)malloc(hresolu*vresolu*sizeof(COLR));
195     ourzbuf = (float *)calloc(hresolu*vresolu,sizeof(float));
196 greg 1.15 if (ourpict == NULL || ourzbuf == NULL)
197     syserror();
198 greg 1.1 /* get input */
199     for ( ; i < argc; i += 2)
200     addpicture(argv[i], argv[i+1]);
201     /* fill in spaces */
202 greg 1.25 if (fillo&F_BACK)
203     backpicture(fillfunc, sampprob);
204 greg 1.12 else
205 greg 1.25 fillpicture(fillfunc);
206 greg 1.13 /* close calculation */
207 greg 1.14 caldone();
208 greg 1.1 /* add to header */
209     printargs(argc, argv, stdout);
210     if (gotvfile) {
211 greg 1.25 fputs(VIEWSTR, stdout);
212 greg 1.1 fprintview(&ourview, stdout);
213 greg 1.25 putc('\n', stdout);
214 greg 1.1 }
215 greg 1.18 if (pixaspect < .99 || pixaspect > 1.01)
216     fputaspect(pixaspect, stdout);
217     if (ourexp > 0 && (ourexp < .995 || ourexp > 1.005))
218 greg 1.16 fputexpos(ourexp, stdout);
219 greg 1.25 putc('\n', stdout);
220 greg 1.11 /* write picture */
221 greg 1.1 writepicture();
222 greg 1.11 /* write z file */
223     if (zfile != NULL)
224     writedistance(zfile);
225 greg 1.1
226     exit(0);
227 greg 1.10 userr:
228     fprintf(stderr,
229 greg 1.17 "Usage: %s [view opts][-t eps][-z zout][-fT][-n] pfile zspec ..\n",
230 greg 1.10 progname);
231     exit(1);
232 greg 1.1 #undef check
233     }
234    
235    
236     headline(s) /* process header string */
237     char *s;
238     {
239 greg 1.25 static char *altname[] = {VIEWSTR,"rpict","rview","pinterp",NULL};
240 greg 1.1 register char **an;
241    
242 greg 1.25 putc('\t', stdout);
243     fputs(s, stdout);
244 greg 1.1
245 greg 1.16 if (isexpos(s)) {
246     theirexp *= exposval(s);
247     return;
248     }
249 greg 1.1 for (an = altname; *an != NULL; an++)
250     if (!strncmp(*an, s, strlen(*an))) {
251 greg 1.17 if (sscanview(&theirview, s+strlen(*an)) > 0)
252 greg 1.1 gotview++;
253     break;
254     }
255     }
256    
257    
258 greg 1.10 addpicture(pfile, zspec) /* add picture to output */
259     char *pfile, *zspec;
260 greg 1.1 {
261 greg 1.10 extern double atof();
262 greg 1.19 FILE *pfp;
263     int zfd;
264 greg 1.8 char *err;
265 greg 1.1 COLR *scanin;
266 greg 1.15 float *zin;
267     struct position *plast;
268 greg 1.1 int y;
269 greg 1.10 /* open picture file */
270 greg 1.1 if ((pfp = fopen(pfile, "r")) == NULL) {
271     perror(pfile);
272     exit(1);
273     }
274 greg 1.16 /* get header with exposure and view */
275     theirexp = 1.0;
276     gotview = 0;
277 greg 1.1 printf("%s:\n", pfile);
278     getheader(pfp, headline);
279 greg 1.17 if (!gotview || fgetresolu(&thresolu, &tvresolu, pfp)
280 greg 1.9 != (YMAJOR|YDECR)) {
281 greg 1.1 fprintf(stderr, "%s: picture view error\n", pfile);
282     exit(1);
283     }
284 greg 1.16 if (ourexp <= 0)
285     ourexp = theirexp;
286     else if (ABS(theirexp-ourexp) > .01*ourexp)
287     fprintf(stderr, "%s: different exposure (warning)\n", pfile);
288 greg 1.1 if (err = setview(&theirview)) {
289     fprintf(stderr, "%s: %s\n", pfile, err);
290     exit(1);
291     }
292 greg 1.5 /* compute transformation */
293     pixform(theirs2ours, &theirview, &ourview);
294 greg 1.1 /* allocate scanlines */
295 greg 1.17 scanin = (COLR *)malloc(thresolu*sizeof(COLR));
296     zin = (float *)malloc(thresolu*sizeof(float));
297     plast = (struct position *)calloc(thresolu, sizeof(struct position));
298 greg 1.15 if (scanin == NULL || zin == NULL || plast == NULL)
299     syserror();
300 greg 1.10 /* get z specification or file */
301 greg 1.19 if ((zfd = open(zspec, O_RDONLY)) == -1) {
302 greg 1.10 double zvalue;
303     register int x;
304     if (!isfloat(zspec) || (zvalue = atof(zspec)) <= 0.0) {
305     perror(zspec);
306     exit(1);
307     }
308 greg 1.17 for (x = 0; x < thresolu; x++)
309 greg 1.10 zin[x] = zvalue;
310     }
311 greg 1.1 /* load image */
312 greg 1.17 for (y = tvresolu-1; y >= 0; y--) {
313     if (freadcolrs(scanin, thresolu, pfp) < 0) {
314 greg 1.1 fprintf(stderr, "%s: read error\n", pfile);
315     exit(1);
316     }
317 greg 1.23 if (zfd != -1 && read(zfd,(char *)zin,thresolu*sizeof(float))
318 greg 1.19 < thresolu*sizeof(float)) {
319 greg 1.10 fprintf(stderr, "%s: read error\n", zspec);
320 greg 1.1 exit(1);
321     }
322 greg 1.15 addscanline(y, scanin, zin, plast);
323 greg 1.1 }
324     /* clean up */
325     free((char *)scanin);
326     free((char *)zin);
327 greg 1.9 free((char *)plast);
328 greg 1.1 fclose(pfp);
329 greg 1.19 if (zfd != -1)
330     close(zfd);
331 greg 1.1 }
332    
333    
334 greg 1.5 pixform(xfmat, vw1, vw2) /* compute view1 to view2 matrix */
335     register double xfmat[4][4];
336     register VIEW *vw1, *vw2;
337     {
338     double m4t[4][4];
339    
340     setident4(xfmat);
341 greg 1.17 xfmat[0][0] = vw1->hvec[0];
342     xfmat[0][1] = vw1->hvec[1];
343     xfmat[0][2] = vw1->hvec[2];
344     xfmat[1][0] = vw1->vvec[0];
345     xfmat[1][1] = vw1->vvec[1];
346     xfmat[1][2] = vw1->vvec[2];
347 greg 1.5 xfmat[2][0] = vw1->vdir[0];
348     xfmat[2][1] = vw1->vdir[1];
349     xfmat[2][2] = vw1->vdir[2];
350     xfmat[3][0] = vw1->vp[0];
351     xfmat[3][1] = vw1->vp[1];
352     xfmat[3][2] = vw1->vp[2];
353     setident4(m4t);
354 greg 1.17 m4t[0][0] = vw2->hvec[0]/vw2->hn2;
355     m4t[1][0] = vw2->hvec[1]/vw2->hn2;
356     m4t[2][0] = vw2->hvec[2]/vw2->hn2;
357     m4t[3][0] = -DOT(vw2->vp,vw2->hvec)/vw2->hn2;
358     m4t[0][1] = vw2->vvec[0]/vw2->vn2;
359     m4t[1][1] = vw2->vvec[1]/vw2->vn2;
360     m4t[2][1] = vw2->vvec[2]/vw2->vn2;
361     m4t[3][1] = -DOT(vw2->vp,vw2->vvec)/vw2->vn2;
362 greg 1.5 m4t[0][2] = vw2->vdir[0];
363     m4t[1][2] = vw2->vdir[1];
364     m4t[2][2] = vw2->vdir[2];
365     m4t[3][2] = -DOT(vw2->vp,vw2->vdir);
366     multmat4(xfmat, xfmat, m4t);
367     }
368    
369    
370 greg 1.15 addscanline(y, pline, zline, lasty) /* add scanline to output */
371 greg 1.1 int y;
372     COLR *pline;
373     float *zline;
374 greg 1.15 struct position *lasty; /* input/output */
375 greg 1.1 {
376 greg 1.11 extern double sqrt();
377 greg 1.5 double pos[3];
378 greg 1.15 struct position lastx, newpos;
379 greg 1.1 register int x;
380    
381 greg 1.20 lastx.z = 0;
382 greg 1.17 for (x = thresolu-1; x >= 0; x--) {
383     pos[0] = (x+.5)/thresolu + theirview.hoff - .5;
384     pos[1] = (y+.5)/tvresolu + theirview.voff - .5;
385 greg 1.5 pos[2] = zline[x];
386     if (theirview.type == VT_PER) {
387 greg 1.11 if (normdist) /* adjust for eye-ray distance */
388 greg 1.10 pos[2] /= sqrt( 1.
389 greg 1.17 + pos[0]*pos[0]*theirview.hn2
390     + pos[1]*pos[1]*theirview.vn2 );
391 greg 1.5 pos[0] *= pos[2];
392     pos[1] *= pos[2];
393     }
394     multp3(pos, pos, theirs2ours);
395 greg 1.15 if (pos[2] <= 0) {
396     lasty[x].z = lastx.z = 0; /* mark invalid */
397 greg 1.1 continue;
398 greg 1.15 }
399 greg 1.5 if (ourview.type == VT_PER) {
400     pos[0] /= pos[2];
401     pos[1] /= pos[2];
402     }
403 greg 1.17 pos[0] += .5 - ourview.hoff;
404     pos[1] += .5 - ourview.voff;
405     newpos.x = pos[0] * hresolu;
406     newpos.y = pos[1] * vresolu;
407 greg 1.15 newpos.z = zline[x];
408 greg 1.8 /* add pixel to our image */
409 greg 1.17 if (pos[0] >= 0 && newpos.x < hresolu
410     && pos[1] >= 0 && newpos.y < vresolu) {
411 greg 1.15 addpixel(&newpos, &lastx, &lasty[x], pline[x], pos[2]);
412     lasty[x].x = lastx.x = newpos.x;
413     lasty[x].y = lastx.y = newpos.y;
414     lasty[x].z = lastx.z = newpos.z;
415     } else
416     lasty[x].z = lastx.z = 0; /* mark invalid */
417 greg 1.1 }
418     }
419    
420    
421 greg 1.15 addpixel(p0, p1, p2, pix, z) /* fill in pixel parallelogram */
422     struct position *p0, *p1, *p2;
423 greg 1.8 COLR pix;
424     double z;
425     {
426 greg 1.15 double zt = 2.*zeps*p0->z; /* threshold */
427     int s1x, s1y, s2x, s2y; /* step sizes */
428     int l1, l2, c1, c2; /* side lengths and counters */
429     int p1isy; /* p0p1 along y? */
430     int x1, y1; /* p1 position */
431     register int x, y; /* final position */
432    
433     /* compute vector p0p1 */
434 greg 1.25 if (fillo&F_FORE && ABS(p1->z-p0->z) <= zt) {
435 greg 1.15 s1x = p1->x - p0->x;
436     s1y = p1->y - p0->y;
437     l1 = ABS(s1x);
438     if (p1isy = (ABS(s1y) > l1))
439     l1 = ABS(s1y);
440     } else {
441     l1 = s1x = s1y = 1;
442     p1isy = -1;
443     }
444     /* compute vector p0p2 */
445 greg 1.25 if (fillo&F_FORE && ABS(p2->z-p0->z) <= zt) {
446 greg 1.15 s2x = p2->x - p0->x;
447     s2y = p2->y - p0->y;
448     if (p1isy == 1)
449     l2 = ABS(s2x);
450     else {
451     l2 = ABS(s2y);
452     if (p1isy != 0 && ABS(s2x) > l2)
453     l2 = ABS(s2x);
454     }
455     } else
456     l2 = s2x = s2y = 1;
457     /* fill the parallelogram */
458     for (c1 = l1; c1-- > 0; ) {
459     x1 = p0->x + c1*s1x/l1;
460     y1 = p0->y + c1*s1y/l1;
461     for (c2 = l2; c2-- > 0; ) {
462     x = x1 + c2*s2x/l2;
463     y = y1 + c2*s2y/l2;
464     if (zscan(y)[x] <= 0 || zscan(y)[x]-z
465     > zeps*zscan(y)[x]) {
466 greg 1.8 zscan(y)[x] = z;
467     copycolr(pscan(y)[x], pix);
468     }
469 greg 1.15 }
470     }
471 greg 1.8 }
472    
473    
474 greg 1.25 backpicture(fill, prob) /* background fill algorithm */
475     int (*fill)();
476     long prob;
477 greg 1.1 {
478 greg 1.2 int *yback, xback;
479 greg 1.1 int y;
480 greg 1.2 COLR pfill;
481     register int x, i;
482     /* get back buffer */
483 greg 1.17 yback = (int *)malloc(hresolu*sizeof(int));
484 greg 1.15 if (yback == NULL)
485     syserror();
486 greg 1.17 for (x = 0; x < hresolu; x++)
487 greg 1.4 yback[x] = -2;
488 greg 1.7 /*
489     * Xback and yback are the pixel locations of suitable
490     * background values in each direction.
491     * A value of -2 means unassigned, and -1 means
492     * that there is no suitable background in this direction.
493     */
494 greg 1.2 /* fill image */
495 greg 1.17 for (y = 0; y < vresolu; y++) {
496 greg 1.4 xback = -2;
497 greg 1.17 for (x = 0; x < hresolu; x++)
498 greg 1.8 if (zscan(y)[x] <= 0) { /* empty pixel */
499 greg 1.7 /*
500     * First, find background from above or below.
501     * (farthest assigned pixel)
502     */
503 greg 1.4 if (yback[x] == -2) {
504 greg 1.17 for (i = y+1; i < vresolu; i++)
505 greg 1.8 if (zscan(i)[x] > 0)
506 greg 1.4 break;
507 greg 1.17 if (i < vresolu
508 greg 1.2 && (y <= 0 || zscan(y-1)[x] < zscan(i)[x]))
509 greg 1.4 yback[x] = i;
510     else
511     yback[x] = y-1;
512 greg 1.2 }
513 greg 1.7 /*
514     * Next, find background from left or right.
515     */
516 greg 1.4 if (xback == -2) {
517 greg 1.17 for (i = x+1; i < hresolu; i++)
518 greg 1.8 if (zscan(y)[i] > 0)
519 greg 1.4 break;
520 greg 1.17 if (i < hresolu
521 greg 1.4 && (x <= 0 || zscan(y)[x-1] < zscan(y)[i]))
522     xback = i;
523     else
524     xback = x-1;
525     }
526 greg 1.7 /*
527 greg 1.11 * Check to see if we have no background for
528 greg 1.25 * this pixel. If not, or sampling was
529     * requested, use the given fill function.
530 greg 1.11 */
531 greg 1.25 if ((xback < 0 && yback[x] < 0) || samp(prob)) {
532     (*fill)(x,y);
533 greg 1.11 continue;
534     }
535     /*
536 greg 1.7 * Compare, and use the background that is
537     * farther, unless one of them is next to us.
538     */
539 greg 1.11 if ( yback[x] < 0
540     || (xback >= 0 && ABS(x-xback) <= 1)
541 greg 1.4 || ( ABS(y-yback[x]) > 1
542 greg 1.11 && zscan(yback[x])[x]
543 greg 1.13 < zscan(y)[xback] ) ) {
544 greg 1.4 copycolr(pscan(y)[x],pscan(y)[xback]);
545 greg 1.13 zscan(y)[x] = zscan(y)[xback];
546     } else {
547 greg 1.4 copycolr(pscan(y)[x],pscan(yback[x])[x]);
548 greg 1.13 zscan(y)[x] = zscan(yback[x])[x];
549     }
550 greg 1.4 } else { /* full pixel */
551     yback[x] = -2;
552     xback = -2;
553     }
554     }
555 greg 1.2 free((char *)yback);
556 greg 1.1 }
557    
558    
559 greg 1.25 fillpicture(fill) /* paint in empty pixels using fill */
560     int (*fill)();
561 greg 1.11 {
562     register int x, y;
563    
564 greg 1.17 for (y = 0; y < vresolu; y++)
565     for (x = 0; x < hresolu; x++)
566 greg 1.11 if (zscan(y)[x] <= 0)
567 greg 1.25 (*fill)(x,y);
568 greg 1.11 }
569    
570    
571 greg 1.1 writepicture() /* write out picture */
572     {
573     int y;
574    
575 greg 1.17 fputresolu(YMAJOR|YDECR, hresolu, vresolu, stdout);
576     for (y = vresolu-1; y >= 0; y--)
577     if (fwritecolrs(pscan(y), hresolu, stdout) < 0)
578 greg 1.15 syserror();
579 greg 1.11 }
580    
581    
582     writedistance(fname) /* write out z file */
583     char *fname;
584     {
585     extern double sqrt();
586     int donorm = normdist && ourview.type == VT_PER;
587 greg 1.19 int fd;
588 greg 1.11 int y;
589     float *zout;
590    
591 greg 1.19 if ((fd = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) == -1) {
592 greg 1.11 perror(fname);
593     exit(1);
594     }
595     if (donorm
596 greg 1.17 && (zout = (float *)malloc(hresolu*sizeof(float))) == NULL)
597 greg 1.15 syserror();
598 greg 1.17 for (y = vresolu-1; y >= 0; y--) {
599 greg 1.11 if (donorm) {
600     double vx, yzn2;
601     register int x;
602 greg 1.17 yzn2 = y - .5*(vresolu-1);
603     yzn2 = 1. + yzn2*yzn2*ourview.vn2;
604     for (x = 0; x < hresolu; x++) {
605     vx = x - .5*(hresolu-1);
606 greg 1.11 zout[x] = zscan(y)[x]
607 greg 1.17 * sqrt(vx*vx*ourview.hn2 + yzn2);
608 greg 1.11 }
609     } else
610     zout = zscan(y);
611 greg 1.23 if (write(fd, (char *)zout, hresolu*sizeof(float))
612 greg 1.19 < hresolu*sizeof(float)) {
613 greg 1.11 perror(fname);
614     exit(1);
615     }
616     }
617     if (donorm)
618     free((char *)zout);
619 greg 1.19 close(fd);
620 greg 1.10 }
621    
622    
623     isfloat(s) /* see if string is floating number */
624     register char *s;
625     {
626     for ( ; *s; s++)
627     if ((*s < '0' || *s > '9') && *s != '.' && *s != '-'
628     && *s != 'e' && *s != 'E' && *s != '+')
629     return(0);
630     return(1);
631 greg 1.12 }
632    
633    
634     backfill(x, y) /* fill pixel with background */
635     int x, y;
636     {
637     register BYTE *dest = pscan(y)[x];
638    
639     copycolr(dest, backcolr);
640 greg 1.13 zscan(y)[x] = backz;
641     }
642    
643    
644     calstart(prog, args) /* start fill calculation */
645     char *prog, *args;
646     {
647     char combuf[512];
648     int p0[2], p1[2];
649    
650 greg 1.14 if (childpid != -1) {
651     fprintf(stderr, "%s: too many calculations\n", progname);
652     exit(1);
653     }
654 greg 1.25 sprintf(combuf, prog, args);
655 greg 1.13 if (pipe(p0) < 0 || pipe(p1) < 0)
656 greg 1.14 syserror();
657 greg 1.13 if ((childpid = vfork()) == 0) { /* fork calculation */
658     close(p0[1]);
659     close(p1[0]);
660     if (p0[0] != 0) {
661     dup2(p0[0], 0);
662     close(p0[0]);
663     }
664     if (p1[1] != 1) {
665     dup2(p1[1], 1);
666     close(p1[1]);
667     }
668     execl("/bin/sh", "sh", "-c", combuf, 0);
669     perror("/bin/sh");
670     _exit(127);
671     }
672 greg 1.14 if (childpid == -1)
673     syserror();
674 greg 1.13 close(p0[0]);
675     close(p1[1]);
676     if ((psend = fdopen(p0[1], "w")) == NULL)
677 greg 1.14 syserror();
678 greg 1.13 if ((precv = fdopen(p1[0], "r")) == NULL)
679 greg 1.14 syserror();
680 greg 1.13 queuesiz = 0;
681     }
682    
683    
684     caldone() /* done with calculation */
685     {
686     int pid;
687    
688 greg 1.14 if (childpid == -1)
689     return;
690 greg 1.25 clearqueue();
691     fclose(psend);
692     fclose(precv);
693 greg 1.13 while ((pid = wait(0)) != -1 && pid != childpid)
694     ;
695 greg 1.14 childpid = -1;
696 greg 1.13 }
697    
698    
699 greg 1.14 rcalfill(x, y) /* fill with ray-calculated pixel */
700 greg 1.13 int x, y;
701     {
702 greg 1.22 if (queuesiz >= PACKSIZ) /* flush queue if needed */
703 greg 1.25 clearqueue();
704 greg 1.22 /* add position to queue */
705 greg 1.13 queue[queuesiz][0] = x;
706     queue[queuesiz][1] = y;
707     queuesiz++;
708     }
709    
710    
711 greg 1.25 clearqueue() /* process queue */
712 greg 1.13 {
713 greg 1.22 FVECT orig, dir;
714     float fbuf[6];
715 greg 1.13 register int i;
716    
717     for (i = 0; i < queuesiz; i++) {
718 greg 1.22 viewray(orig, dir, &ourview,
719     (queue[i][0]+.5)/hresolu,
720     (queue[i][1]+.5)/vresolu);
721     fbuf[0] = orig[0]; fbuf[1] = orig[1]; fbuf[2] = orig[2];
722     fbuf[3] = dir[0]; fbuf[4] = dir[1]; fbuf[5] = dir[2];
723 greg 1.23 fwrite((char *)fbuf, sizeof(float), 6, psend);
724 greg 1.22 }
725 greg 1.25 /* flush output and get results */
726     fbuf[3] = fbuf[4] = fbuf[5] = 0.0; /* mark */
727     fwrite((char *)fbuf, sizeof(float), 6, psend);
728     if (fflush(psend) == EOF)
729 greg 1.22 syserror();
730     for (i = 0; i < queuesiz; i++) {
731 greg 1.23 if (fread((char *)fbuf, sizeof(float), 4, precv) < 4) {
732 greg 1.14 fprintf(stderr, "%s: read error in clearqueue\n",
733     progname);
734     exit(1);
735 greg 1.16 }
736     if (ourexp > 0 && ourexp != 1.0) {
737 greg 1.22 fbuf[0] *= ourexp;
738     fbuf[1] *= ourexp;
739     fbuf[2] *= ourexp;
740 greg 1.14 }
741 greg 1.13 setcolr(pscan(queue[i][1])[queue[i][0]],
742 greg 1.22 fbuf[0], fbuf[1], fbuf[2]);
743     zscan(queue[i][1])[queue[i][0]] = fbuf[3];
744 greg 1.13 }
745     queuesiz = 0;
746 greg 1.14 }
747    
748    
749     syserror() /* report error and exit */
750     {
751     perror(progname);
752     exit(1);
753 greg 1.1 }