ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/pinterp.c
Revision: 1.19
Committed: Tue Jan 16 11:29:14 1990 UTC (34 years, 3 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.18: +15 -11 lines
Log Message:
changed reading and writing of z-files and viewfiles

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.17 for (x = thresolu-1; x >= 0; x--) {
366     pos[0] = (x+.5)/thresolu + theirview.hoff - .5;
367     pos[1] = (y+.5)/tvresolu + theirview.voff - .5;
368 greg 1.5 pos[2] = zline[x];
369     if (theirview.type == VT_PER) {
370 greg 1.11 if (normdist) /* adjust for eye-ray distance */
371 greg 1.10 pos[2] /= sqrt( 1.
372 greg 1.17 + pos[0]*pos[0]*theirview.hn2
373     + pos[1]*pos[1]*theirview.vn2 );
374 greg 1.5 pos[0] *= pos[2];
375     pos[1] *= pos[2];
376     }
377     multp3(pos, pos, theirs2ours);
378 greg 1.15 if (pos[2] <= 0) {
379     lasty[x].z = lastx.z = 0; /* mark invalid */
380 greg 1.1 continue;
381 greg 1.15 }
382 greg 1.5 if (ourview.type == VT_PER) {
383     pos[0] /= pos[2];
384     pos[1] /= pos[2];
385     }
386 greg 1.17 pos[0] += .5 - ourview.hoff;
387     pos[1] += .5 - ourview.voff;
388     newpos.x = pos[0] * hresolu;
389     newpos.y = pos[1] * vresolu;
390 greg 1.15 newpos.z = zline[x];
391 greg 1.8 /* add pixel to our image */
392 greg 1.17 if (pos[0] >= 0 && newpos.x < hresolu
393     && pos[1] >= 0 && newpos.y < vresolu) {
394 greg 1.15 addpixel(&newpos, &lastx, &lasty[x], pline[x], pos[2]);
395     lasty[x].x = lastx.x = newpos.x;
396     lasty[x].y = lastx.y = newpos.y;
397     lasty[x].z = lastx.z = newpos.z;
398     } else
399     lasty[x].z = lastx.z = 0; /* mark invalid */
400 greg 1.1 }
401     }
402    
403    
404 greg 1.15 addpixel(p0, p1, p2, pix, z) /* fill in pixel parallelogram */
405     struct position *p0, *p1, *p2;
406 greg 1.8 COLR pix;
407     double z;
408     {
409 greg 1.15 double zt = 2.*zeps*p0->z; /* threshold */
410     int s1x, s1y, s2x, s2y; /* step sizes */
411     int l1, l2, c1, c2; /* side lengths and counters */
412     int p1isy; /* p0p1 along y? */
413     int x1, y1; /* p1 position */
414     register int x, y; /* final position */
415    
416     /* compute vector p0p1 */
417     if (fill&F_FORE && ABS(p1->z-p0->z) <= zt) {
418     s1x = p1->x - p0->x;
419     s1y = p1->y - p0->y;
420     l1 = ABS(s1x);
421     if (p1isy = (ABS(s1y) > l1))
422     l1 = ABS(s1y);
423     } else {
424     l1 = s1x = s1y = 1;
425     p1isy = -1;
426     }
427     /* compute vector p0p2 */
428     if (fill&F_FORE && ABS(p2->z-p0->z) <= zt) {
429     s2x = p2->x - p0->x;
430     s2y = p2->y - p0->y;
431     if (p1isy == 1)
432     l2 = ABS(s2x);
433     else {
434     l2 = ABS(s2y);
435     if (p1isy != 0 && ABS(s2x) > l2)
436     l2 = ABS(s2x);
437     }
438     } else
439     l2 = s2x = s2y = 1;
440     /* fill the parallelogram */
441     for (c1 = l1; c1-- > 0; ) {
442     x1 = p0->x + c1*s1x/l1;
443     y1 = p0->y + c1*s1y/l1;
444     for (c2 = l2; c2-- > 0; ) {
445     x = x1 + c2*s2x/l2;
446     y = y1 + c2*s2y/l2;
447     if (zscan(y)[x] <= 0 || zscan(y)[x]-z
448     > zeps*zscan(y)[x]) {
449 greg 1.8 zscan(y)[x] = z;
450     copycolr(pscan(y)[x], pix);
451     }
452 greg 1.15 }
453     }
454 greg 1.8 }
455    
456    
457 greg 1.12 backpicture() /* background fill algorithm */
458 greg 1.1 {
459 greg 1.2 int *yback, xback;
460 greg 1.1 int y;
461 greg 1.2 COLR pfill;
462     register int x, i;
463     /* get back buffer */
464 greg 1.17 yback = (int *)malloc(hresolu*sizeof(int));
465 greg 1.15 if (yback == NULL)
466     syserror();
467 greg 1.17 for (x = 0; x < hresolu; x++)
468 greg 1.4 yback[x] = -2;
469 greg 1.7 /*
470     * Xback and yback are the pixel locations of suitable
471     * background values in each direction.
472     * A value of -2 means unassigned, and -1 means
473     * that there is no suitable background in this direction.
474     */
475 greg 1.2 /* fill image */
476 greg 1.17 for (y = 0; y < vresolu; y++) {
477 greg 1.4 xback = -2;
478 greg 1.17 for (x = 0; x < hresolu; x++)
479 greg 1.8 if (zscan(y)[x] <= 0) { /* empty pixel */
480 greg 1.7 /*
481     * First, find background from above or below.
482     * (farthest assigned pixel)
483     */
484 greg 1.4 if (yback[x] == -2) {
485 greg 1.17 for (i = y+1; i < vresolu; i++)
486 greg 1.8 if (zscan(i)[x] > 0)
487 greg 1.4 break;
488 greg 1.17 if (i < vresolu
489 greg 1.2 && (y <= 0 || zscan(y-1)[x] < zscan(i)[x]))
490 greg 1.4 yback[x] = i;
491     else
492     yback[x] = y-1;
493 greg 1.2 }
494 greg 1.7 /*
495     * Next, find background from left or right.
496     */
497 greg 1.4 if (xback == -2) {
498 greg 1.17 for (i = x+1; i < hresolu; i++)
499 greg 1.8 if (zscan(y)[i] > 0)
500 greg 1.4 break;
501 greg 1.17 if (i < hresolu
502 greg 1.4 && (x <= 0 || zscan(y)[x-1] < zscan(y)[i]))
503     xback = i;
504     else
505     xback = x-1;
506     }
507 greg 1.7 /*
508 greg 1.11 * Check to see if we have no background for
509     * this pixel. If not, use background color.
510     */
511     if (xback < 0 && yback[x] < 0) {
512 greg 1.12 (*deffill)(x,y);
513 greg 1.11 continue;
514     }
515     /*
516 greg 1.7 * Compare, and use the background that is
517     * farther, unless one of them is next to us.
518     */
519 greg 1.11 if ( yback[x] < 0
520     || (xback >= 0 && ABS(x-xback) <= 1)
521 greg 1.4 || ( ABS(y-yback[x]) > 1
522 greg 1.11 && zscan(yback[x])[x]
523 greg 1.13 < zscan(y)[xback] ) ) {
524 greg 1.4 copycolr(pscan(y)[x],pscan(y)[xback]);
525 greg 1.13 zscan(y)[x] = zscan(y)[xback];
526     } else {
527 greg 1.4 copycolr(pscan(y)[x],pscan(yback[x])[x]);
528 greg 1.13 zscan(y)[x] = zscan(yback[x])[x];
529     }
530 greg 1.4 } else { /* full pixel */
531     yback[x] = -2;
532     xback = -2;
533     }
534     }
535 greg 1.2 free((char *)yback);
536 greg 1.1 }
537    
538    
539 greg 1.12 fillpicture() /* paint in empty pixels with default */
540 greg 1.11 {
541     register int x, y;
542    
543 greg 1.17 for (y = 0; y < vresolu; y++)
544     for (x = 0; x < hresolu; x++)
545 greg 1.11 if (zscan(y)[x] <= 0)
546 greg 1.12 (*deffill)(x,y);
547 greg 1.11 }
548    
549    
550 greg 1.1 writepicture() /* write out picture */
551     {
552     int y;
553    
554 greg 1.17 fputresolu(YMAJOR|YDECR, hresolu, vresolu, stdout);
555     for (y = vresolu-1; y >= 0; y--)
556     if (fwritecolrs(pscan(y), hresolu, stdout) < 0)
557 greg 1.15 syserror();
558 greg 1.11 }
559    
560    
561     writedistance(fname) /* write out z file */
562     char *fname;
563     {
564     extern double sqrt();
565     int donorm = normdist && ourview.type == VT_PER;
566 greg 1.19 int fd;
567 greg 1.11 int y;
568     float *zout;
569    
570 greg 1.19 if ((fd = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) == -1) {
571 greg 1.11 perror(fname);
572     exit(1);
573     }
574     if (donorm
575 greg 1.17 && (zout = (float *)malloc(hresolu*sizeof(float))) == NULL)
576 greg 1.15 syserror();
577 greg 1.17 for (y = vresolu-1; y >= 0; y--) {
578 greg 1.11 if (donorm) {
579     double vx, yzn2;
580     register int x;
581 greg 1.17 yzn2 = y - .5*(vresolu-1);
582     yzn2 = 1. + yzn2*yzn2*ourview.vn2;
583     for (x = 0; x < hresolu; x++) {
584     vx = x - .5*(hresolu-1);
585 greg 1.11 zout[x] = zscan(y)[x]
586 greg 1.17 * sqrt(vx*vx*ourview.hn2 + yzn2);
587 greg 1.11 }
588     } else
589     zout = zscan(y);
590 greg 1.19 if (write(fd, zout, hresolu*sizeof(float))
591     < hresolu*sizeof(float)) {
592 greg 1.11 perror(fname);
593     exit(1);
594     }
595     }
596     if (donorm)
597     free((char *)zout);
598 greg 1.19 close(fd);
599 greg 1.10 }
600    
601    
602     isfloat(s) /* see if string is floating number */
603     register char *s;
604     {
605     for ( ; *s; s++)
606     if ((*s < '0' || *s > '9') && *s != '.' && *s != '-'
607     && *s != 'e' && *s != 'E' && *s != '+')
608     return(0);
609     return(1);
610 greg 1.12 }
611    
612    
613     backfill(x, y) /* fill pixel with background */
614     int x, y;
615     {
616     register BYTE *dest = pscan(y)[x];
617    
618     copycolr(dest, backcolr);
619 greg 1.13 zscan(y)[x] = backz;
620     }
621    
622    
623     calstart(prog, args) /* start fill calculation */
624     char *prog, *args;
625     {
626     char combuf[512];
627     int p0[2], p1[2];
628    
629 greg 1.14 if (childpid != -1) {
630     fprintf(stderr, "%s: too many calculations\n", progname);
631     exit(1);
632     }
633 greg 1.13 sprintf(combuf, prog, PACKSIZ, args);
634     if (pipe(p0) < 0 || pipe(p1) < 0)
635 greg 1.14 syserror();
636 greg 1.13 if ((childpid = vfork()) == 0) { /* fork calculation */
637     close(p0[1]);
638     close(p1[0]);
639     if (p0[0] != 0) {
640     dup2(p0[0], 0);
641     close(p0[0]);
642     }
643     if (p1[1] != 1) {
644     dup2(p1[1], 1);
645     close(p1[1]);
646     }
647     execl("/bin/sh", "sh", "-c", combuf, 0);
648     perror("/bin/sh");
649     _exit(127);
650     }
651 greg 1.14 if (childpid == -1)
652     syserror();
653 greg 1.13 close(p0[0]);
654     close(p1[1]);
655     if ((psend = fdopen(p0[1], "w")) == NULL)
656 greg 1.14 syserror();
657 greg 1.13 if ((precv = fdopen(p1[0], "r")) == NULL)
658 greg 1.14 syserror();
659 greg 1.13 queuesiz = 0;
660     }
661    
662    
663     caldone() /* done with calculation */
664     {
665     int pid;
666    
667 greg 1.14 if (childpid == -1)
668     return;
669     if (fclose(psend) == EOF)
670     syserror();
671 greg 1.13 clearqueue();
672     fclose(precv);
673     while ((pid = wait(0)) != -1 && pid != childpid)
674     ;
675 greg 1.14 childpid = -1;
676 greg 1.13 }
677    
678    
679 greg 1.14 rcalfill(x, y) /* fill with ray-calculated pixel */
680 greg 1.13 int x, y;
681     {
682     FVECT orig, dir;
683     float outbuf[6];
684    
685     if (queuesiz >= PACKSIZ) { /* flush queue */
686 greg 1.14 if (fflush(psend) == EOF)
687     syserror();
688 greg 1.13 clearqueue();
689     }
690     /* send new ray */
691 greg 1.17 viewray(orig, dir, &ourview, (x+.5)/hresolu, (y+.5)/vresolu);
692 greg 1.13 outbuf[0] = orig[0]; outbuf[1] = orig[1]; outbuf[2] = orig[2];
693     outbuf[3] = dir[0]; outbuf[4] = dir[1]; outbuf[5] = dir[2];
694 greg 1.14 if (fwrite(outbuf, sizeof(float), 6, psend) < 6)
695     syserror();
696 greg 1.13 /* remember it */
697     queue[queuesiz][0] = x;
698     queue[queuesiz][1] = y;
699     queuesiz++;
700     }
701    
702    
703     clearqueue() /* get results from queue */
704     {
705     float inbuf[4];
706     register int i;
707    
708     for (i = 0; i < queuesiz; i++) {
709 greg 1.14 if (fread(inbuf, sizeof(float), 4, precv) < 4) {
710     fprintf(stderr, "%s: read error in clearqueue\n",
711     progname);
712     exit(1);
713 greg 1.16 }
714     if (ourexp > 0 && ourexp != 1.0) {
715     inbuf[0] *= ourexp;
716     inbuf[1] *= ourexp;
717     inbuf[2] *= ourexp;
718 greg 1.14 }
719 greg 1.13 setcolr(pscan(queue[i][1])[queue[i][0]],
720     inbuf[0], inbuf[1], inbuf[2]);
721     zscan(queue[i][1])[queue[i][0]] = inbuf[3];
722     }
723     queuesiz = 0;
724 greg 1.14 }
725    
726    
727     syserror() /* report error and exit */
728     {
729     perror(progname);
730     exit(1);
731 greg 1.1 }