home *** CD-ROM | disk | FTP | other *** search
/ Stars of Shareware: Raytrace & Morphing / SOS-RAYTRACE.ISO / programm / source / radsrc22 / src / px / pinterp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-10-02  |  18.8 KB  |  801 lines

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