ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/pinterp.c
Revision: 1.20
Committed: Tue Jan 16 16:10:57 1990 UTC (34 years, 3 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.19: +1 -0 lines
Log Message:
added initialization in addscanline()

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