home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / vectoper.zip / RTAlgOps.cpp < prev    next >
C/C++ Source or Header  |  1996-09-19  |  36KB  |  1,239 lines

  1.  
  2.  
  3. #include <stdio.h>
  4. #include <math.h>
  5.  
  6. #include "RTTypes.h"
  7. #include "RTMatMac.h"
  8. #include "RTVecOps.h"
  9.  
  10. #include "RTScreen.h"
  11. #include "RTObjOps.h"
  12. #include "RTIMOps.h"
  13. #include "RayTrace.h"
  14. #include "RTIntOps.h"
  15.  
  16. #include "calypso.H"
  17.  
  18.  
  19.  
  20.  
  21.  
  22. extern int RT_sd;         // Socket descriptor for display client connection requests 
  23.  
  24.  
  25.  
  26. /*
  27.  *******************************************************************************
  28.  *
  29.  *  Name:  RT_Trace
  30.  *
  31.  *  Purpose:  this routine is responsible for determining the closest int-
  32.  *            ersection (if any) between the ray currently being traced and
  33.  *            any objects.  If an intersection is found, that point is passed
  34.  *            to "RT_Shade" for shading.  RT_Trace returns the color deter-
  35.  *            mined by RT_Shade if an intersection was found, or a background
  36.  *            color if not.
  37.  *
  38.  *
  39.  *
  40.  *  Input Parameters
  41.  *
  42.  *     i_ray - ray currently being traced
  43.  *     n_i - index of refraction of medium that ray is passing through
  44.  *     depth - level of recursion
  45.  *
  46.  *
  47.  *  Output Parameters
  48.  *
  49.  *     none
  50.  *
  51.  *******************************************************************************
  52.  */
  53. Vector
  54.    RT_Trace( Ray i_ray, float n_i, int depth)
  55.       {
  56.        Vector I_pt;
  57.        Vector Pt_int;
  58.        Vector Pt_norm;
  59.        Vector patch_norm;
  60.  
  61.        Boolean int_flg;
  62.  
  63.        int obj_no;
  64.  
  65. /*
  66.  *     determine nearest intersection
  67.  */
  68.        int_flg = nearest_int(i_ray, &obj_no, &Pt_int, &Pt_norm, &patch_norm);
  69.  
  70.  
  71. /*
  72.  *     if there is an intersection -- shade surface
  73.  */
  74.        if (int_flg)  {
  75.            I_pt = RT_Shade(Pt_int, Pt_norm, patch_norm, i_ray,
  76.                            &shared->obj_list[obj_no], &shared->obj_props[obj_no], 
  77.                                                                   depth, n_i);
  78.           }
  79.  
  80. /*
  81.  *     if no intersection & we're at top level -- set a nice background color
  82.  */
  83.        else if (depth == 1)
  84.            vset(&I_pt,  (float) 0.0,  (float) 0.0,  (float) 0.0);
  85.  
  86. /*
  87.  *     if no intersection & we're NOT at top level -- set black background
  88.  */
  89.        else
  90.            vset(&I_pt, (float) 0.0,  (float) 0.0,  (float) 0.0);
  91.  
  92.  
  93.        return (I_pt);
  94.       }
  95.  
  96.  
  97. /*
  98.  *******************************************************************************
  99.  *
  100.  *  Name:  RT_Shade
  101.  *
  102.  *  Purpose:  this routine applies Whitted's illumination equation
  103.  *            [eq. 16.55, p. 778 in Computer Graphics (Principles and
  104.  *            Practice)] to a specified point.  In order to accomplish
  105.  *            this, it applies the Warn Lighting Model at the point.
  106.  *            It then spawns reflected & refracted rays from the point
  107.  *            if needed (Ks > 0.2 or Kt > 0.2).  The intensities from
  108.  *            these two rays are then factored into the intensity at
  109.  *            the point.
  110.  *
  111.  *
  112.  *
  113.  *  Input Parameters
  114.  *
  115.  *     RT_pt - point to be shaded
  116.  *     Pt_norm - normal at point to be shaded
  117.  *     patch_norm - normal of patch containg point to be shaded
  118.  *     RT_Iray - incident ray at point to be shaded
  119.  *     obj_ptr - ptr to object containing point to be shaded
  120.  *     prop_ptr - ptr to structure containing objects optical properties
  121.  *     depth - level of recursion
  122.  *     n_i - index pf refraction for medium containg incident ray
  123.  *
  124.  *
  125.  *  Output Parameters
  126.  *
  127.  *     none
  128.  *
  129.  *******************************************************************************
  130.  */
  131. Vector
  132.    RT_Shade( Vector RT_pt, Vector Pt_norm, Vector patch_norm, Ray RT_Iray,
  133.              Obj *obj_ptr, Obj_Props *prop_ptr, int depth, float n_i)
  134.       {
  135.        Vector I;
  136.        Vector Ir, It;
  137.        Vector U, V;
  138.  
  139.        Vector View_vec;
  140.        Vector I_vec;
  141.        Vector illum_norm;
  142.        Vector Od;
  143.  
  144.        Ray r_ray, t_ray;
  145.  
  146.        float N_dot_I;
  147.        float cos_fee;
  148.        float n_t;
  149.  
  150.  
  151. /*
  152.  *     initialization
  153.  */
  154.        vset (&I,  (float) 0.0,  (float) 0.0,  (float) 0.0);
  155.        vset (&Ir, (float) 0.0,  (float) 0.0,  (float) 0.0);
  156.        vset (&It, (float) 0.0,  (float) 0.0,  (float) 0.0);
  157.  
  158.  
  159. /*
  160.  *******************************************************************************
  161.  *
  162.  *  illuminate specified point
  163.  *
  164.  *******************************************************************************
  165.  * 
  166.  *     initialize input for illumination model
  167.  */
  168.        vset (&View_vec, -(RT_Iray.dir.x), -(RT_Iray.dir.y), -(RT_Iray.dir.z) );
  169.        View_vec = VectorScaler_Division( &View_vec, vector_len(&View_vec) );
  170.        I_vec = VectorScaler_Division( &RT_Iray.dir, vector_len(&RT_Iray.dir) );
  171.  
  172.        vset (&illum_norm, Pt_norm.x, Pt_norm.y, Pt_norm.z);
  173.        Vector saveN = illum_norm;
  174.  
  175.        Od = prop_ptr->Od_out;
  176.  
  177.  
  178. /* 
  179.  *     handle case where inside of patch is showing
  180.  */
  181.        cos_fee = Dot_Product(&View_vec, &patch_norm);
  182.  
  183.        if (cos_fee <= 0.0)  {
  184.            vset (&illum_norm, -(illum_norm.x), -(illum_norm.y), -(illum_norm.z));
  185.            Od = prop_ptr->Od_in;
  186.           }
  187.  
  188.  
  189. /* 
  190.  *     if the object is to be texture mapped get texture map color for point
  191.  */
  192.        if (prop_ptr->txt_flg)
  193.           RT_TextureMap(RT_pt, obj_ptr, &Od);
  194.  
  195. /* 
  196.  *     apply illumination model - sum diffuse & specular components
  197.  */
  198.       Illumination_Model(RT_pt, &illum_norm, &View_vec,
  199.                          &Od, &prop_ptr->Os,
  200.                          prop_ptr->Ka, prop_ptr->Kd, prop_ptr->Ks,
  201.                          &U, &V);
  202.  
  203.        I = Vector_Sum (&I, &U);
  204.        I = Vector_Sum (&I, &V);
  205.  
  206.  
  207. /*
  208.  *******************************************************************************
  209.  *
  210.  *  spawn reflection and transmission rays if needed
  211.  *
  212.  *******************************************************************************
  213.  */
  214.       if (depth < shared->depth_limit)  {
  215.  
  216.  
  217.  
  218. /*
  219.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  220.  +  spawn reflection ray if object is reflective
  221.  +  (r_ray.dir = 2.0*N * (NdotL) - View_vector)
  222.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  223.  */
  224.           if (prop_ptr->Ks > 0.2)  {
  225.  
  226. /*
  227.  *            setup reflected ray
  228.  */
  229.               N_dot_I =  Dot_Product(&illum_norm, &I_vec);
  230.               r_ray.origin = RT_pt;
  231.  
  232.               r_ray.dir = VectorScaler_Product(&illum_norm, ((float)2.0)*N_dot_I);
  233.               r_ray.dir = Vector_Difference(&I_vec, &r_ray.dir);
  234.               r_ray.dir = VectorScaler_Division(&r_ray.dir, vector_len(&r_ray.dir));
  235.  
  236.  
  237. /*
  238.  *            determine intensity contribution from reflected ray
  239.  */
  240.               Ir = RT_Trace (r_ray, (float)-1.0, depth+1);
  241.               Ir = VectorScaler_Product(&Ir, prop_ptr->Ks);
  242.              }
  243.  
  244. /*
  245.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  246.  +  spawn refracted ray if object is transparent
  247.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  248.  */
  249.           if (prop_ptr->Kt > 0.2)  {
  250.  
  251. /*
  252.  *            determine indices of refraction at interface
  253.  */
  254.               if (n_i < 0)  {
  255.                   n_i = (float)1.0;
  256.                   n_t = prop_ptr->n;
  257.                  }
  258.               else
  259.                   n_t = (float)1.0;
  260.  
  261. /*
  262.  *            setup refracted ray
  263.  */
  264.               t_ray.origin = RT_pt;
  265.               t_ray.dir = RT_RefractionDirection(View_vec,illum_norm,n_i,n_t);
  266.  
  267. /*
  268.  *            determine intensity contribution from refracted ray
  269.  */
  270.               It = RT_Trace (t_ray, n_t, depth+1);
  271.               It = VectorScaler_Product(&It, prop_ptr->Kt);
  272.              }
  273. /*
  274.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  275.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  276.  */
  277.  
  278. /*
  279.  *        add reflected & refracted contributions to intensity for point
  280.  */
  281.           I = Vector_Sum(&I, &Ir);
  282.           I = Vector_Sum(&I, &It);
  283.  
  284.          }  /* end - if (depth < MAX_DEPTH) */
  285.  
  286. /*
  287.  *******************************************************************************
  288.  *******************************************************************************
  289.  */
  290.  
  291.        return(I);
  292.       }
  293.  
  294.  
  295.  
  296. /*
  297.  *******************************************************************************
  298.  *
  299.  *  Name:  RT_SetViewParams
  300.  *
  301.  *  Purpose:  this routine determines the three parameters that define the
  302.  *            ray tracing view plane:
  303.  *
  304.  *               - the vector pointing along the AF axis to the origin 
  305.  *                 of the view plane  (d_AF)
  306.  *
  307.  *               - the vector representing the horizontal axis of the
  308.  *                 view plane  (X_bar) 
  309.  *
  310.  *               - the vector representing the vertical axis of the view
  311.  *                 plane  (Y_bar) 
  312.  *
  313.  *            These values are stored in global variables because of their
  314.  *            importance in ray tracing (especially during debugging).
  315.  *
  316.  *
  317.  *
  318.  *  Input Parameters
  319.  *
  320.  *     none
  321.  *
  322.  *
  323.  *  Output Parameters
  324.  *
  325.  *     none
  326.  *
  327.  *******************************************************************************
  328.  */
  329. void
  330.    RT_SetViewParams()
  331.       {
  332.        Vector AF;
  333.        float Vrad;
  334.        float d;
  335.  
  336.  
  337. /*
  338.  *     determine number of scan lines & pixels / scan line
  339.  *     (if running batch mode -- put this info in the output file)
  340.  */
  341.        npix =   shared->vp.scr_reg.max_pt.x - shared->vp.scr_reg.min_pt.x + 1;
  342.        nscan =  shared->vp.scr_reg.max_pt.y - shared->vp.scr_reg.min_pt.y + 1;
  343.        shared->npix = npix;
  344.        shared->nscan = nscan;
  345.  
  346.        if (WritePixelsFlag)  {
  347.            fwrite (&nscan, sizeof(int), 1, ofp);
  348.            fwrite (&npix, sizeof(int), 1, ofp);
  349.           }
  350.  
  351.  
  352.  
  353. /*
  354.  *     determine vector to origin of view plane (d_AF)
  355.  */
  356.        AF = Vector_Difference(&shared->vp.A, &shared->vp.F);
  357.        Vrad = (shared->vp.v/180) * M_PI;
  358.        d = ((float)1.0) / tan(Vrad/2);
  359.  
  360.        shared->d_AF = VectorScaler_Division( &AF, vector_len(&AF) );
  361.        shared->d_AF = VectorScaler_Product( &shared->d_AF, d);
  362.  
  363.  
  364. /*
  365.  *     determine orthogonal axis vectors of view plane (X_bar & Y_bar)
  366.  */
  367.        Cross_Product (&AF, &shared->vp.U, &shared->X_bar);
  368.        shared->X_bar = VectorScaler_Division(&shared->X_bar,
  369.                                                      vector_len(&shared->X_bar));
  370.  
  371.        Cross_Product (&AF, &shared->X_bar, &shared->Y_bar);
  372.        shared->Y_bar = VectorScaler_Division(&shared->Y_bar, 
  373.                                                      vector_len(&shared->Y_bar));
  374.       }
  375.  
  376.  
  377.  
  378. /*
  379.  *******************************************************************************
  380.  *
  381.  *  Name:  RT_RefractionDirection
  382.  *
  383.  *  Purpose:  this routine calculates the direction of the refracted ray
  384.  *            for a incident ray that reaches the interface between two
  385.  *            media with different refractive indices.  The calculation
  386.  *            is based on eq. 16.31 (p757) in: 
  387.  *                    Computer Graphics (Principles and Practice)
  388.  *
  389.  *
  390.  *
  391.  *  Input Parameters
  392.  *
  393.  *     I - incident ray direction
  394.  *     N - normal at medium interface
  395.  *     n_i -index of refraction for medium containing incident ray
  396.  *     n_t -index of refraction for medium containing transmitted ray
  397.  *
  398.  *
  399.  *  Output Parameters
  400.  *
  401.  *     none
  402.  *
  403.  *******************************************************************************
  404.  */
  405. Vector
  406.    RT_RefractionDirection(Vector I, Vector N, float n_i, float n_t)
  407.       {
  408.        Vector T_vec;
  409.        Vector nr_I;
  410.  
  411.        float n_r, nr_sq;
  412.  
  413.        float cos_theta_i;
  414.        float cos_theta_i_sq;
  415.        float cos_theta_t;
  416.  
  417.  
  418.        n_r = n_i / n_t;
  419.        nr_sq = n_r * n_r;
  420.  
  421.        cos_theta_i = Dot_Product(&N, &I);
  422.        cos_theta_i_sq  = cos_theta_i * cos_theta_i;
  423.  
  424.        cos_theta_t = sqrt(1 - nr_sq * (1 - cos_theta_i_sq) );
  425.  
  426.        nr_I = VectorScaler_Product(&I, n_r);
  427.  
  428.        T_vec = VectorScaler_Product(&N, n_r*cos_theta_i - cos_theta_t);
  429.        T_vec = Vector_Difference(&T_vec, &nr_I);
  430.        return(T_vec);
  431.       }
  432.  
  433.  
  434.  
  435. /*
  436.  *******************************************************************************
  437.  *
  438.  *  Name:  RT_DirectionVector
  439.  *
  440.  *  Purpose:  this routine determines the direction vectors for rays cast  
  441.  *            through the ray tracing view plane from the center of pro-
  442.  *            jection.  This is done by translating from pixel edge co-
  443.  *            ordinate space to the u-v space of the view plane and
  444.  *            adding together the following three components:
  445.  *
  446.  *               - distance along AF axis to view plane origin (d_AF)
  447.  *
  448.  *               - distance from view plane origin to pixel edge in X_bar
  449.  *                 direction (u)
  450.  *
  451.  *               - distance from view plane origin to pixel edge in Y_bar
  452.  *                 direction (v)
  453.  *
  454.  *
  455.  *
  456.  *  Input Parameters
  457.  *
  458.  *     pix - number of pixel 
  459.  *     scan - number of scan line containing pixel 
  460.  *
  461.  *
  462.  *  Output Parameters
  463.  *
  464.  *     none
  465.  *
  466.  *******************************************************************************
  467.  */
  468. Vector
  469.    RT_DirectionVector(float pix, float scan)
  470.       {
  471.        PT_uv Puv;
  472.        Vector dir, vec;
  473.  
  474.        float x_diff, y_diff;
  475.  
  476.  
  477. /*
  478.  *     determine pixel edge in pixel edge coordinates
  479.  */
  480.        x_diff = (float)(shared->vp.scr_reg.max_pt.x - shared->vp.scr_reg.min_pt.x + 1);
  481.        y_diff = (float)(shared->vp.scr_reg.max_pt.y - shared->vp.scr_reg.min_pt.y + 1);
  482.  
  483.  
  484. /*
  485.  *     translate coordinates to uv space of view plane
  486.  */
  487.        Puv.u = (pix - (x_diff / 2)) / (x_diff / 2);
  488.        Puv.v = (scan - (y_diff / 2)) / (y_diff / 2);
  489.  
  490.  
  491. /*
  492.  *     determine direction vector for ray through point on view plane
  493.  */
  494.        dir = shared->d_AF;
  495.  
  496.        vec = VectorScaler_Product( &shared->X_bar, Puv.u);
  497.        dir = Vector_Sum(&dir, &vec);
  498.  
  499.        vec = VectorScaler_Product( &shared->Y_bar, Puv.v);
  500.        dir = Vector_Sum(&dir, &vec);
  501.  
  502.  
  503.        return(dir);
  504.       }
  505.  
  506.  
  507.  
  508. /*
  509.  *******************************************************************************
  510.  *
  511.  *  Name:  RT_SetPixels
  512.  *
  513.  *  Purpose:  this routine converts pixel intensity values (for a given
  514.  *            scan line) to RGB values and writes out these values accord-
  515.  *            based on flagged cases:
  516.  *
  517.  *               - interactive case:  (debug_flag & batch_flag = FALSE)
  518.  *                    ray tracing is being run interactively and the output
  519.  *                    is displayed directly on the screen in RGB mode.
  520.  *
  521.  *               - debug case:  (debug_flag = TRUE)
  522.  *                    ray tracing is being run interactively in debug mode
  523.  *                    and the output is displayed on the display screen as
  524.  *                    integer RGB values.
  525.  *
  526.  *               - batch case:  (batch_flag = TRUE)
  527.  *                    ray tracing is being run in batch mode and the output
  528.  *                    is written to a data file for later display
  529.  *
  530.  *
  531.  *
  532.  *  Input Parameters
  533.  *
  534.  *     Ipix - array of pixel intensity values to be displayed
  535.  *     scan - scan line number for array of pixel intensity values
  536.  *     npix - number of pixel intensity values in pixel array (Ipix)
  537.  *
  538.  *
  539.  *  Output Parameters
  540.  *
  541.  *     none
  542.  *
  543.  *******************************************************************************
  544.  */
  545. void
  546.    RT_SetPixels (Vector Ipix[], int scan, int npix)
  547.       {
  548.        short XmitBuffer[5000]; 
  549.  
  550.        short red_i, green_i, blue_i;
  551.        short i, n;
  552.        int XB_next = 0;
  553.  
  554.   
  555.        n = (short) npix;
  556.  
  557.        if (debug_flag)
  558.            printf ("\n\n scan: %d --  of nscan\n", scan);
  559.  
  560. /*
  561.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  562.  +  write out pixel values
  563.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  564.  */
  565.        for (i=0; i<n; i++)  {
  566.  
  567. /*
  568.  *         calculate pixel values from intensity values
  569.  */
  570.            red_i =   (short) MIN(  (( 255.0 * (Ipix[i].x) ) + 0.5), 255.0  );
  571.            green_i = (short) MIN(  (( 255.0 * (Ipix[i].y) ) + 0.5), 255.0  );
  572.            blue_i =  (short) MIN(  (( 255.0 * (Ipix[i].z) ) + 0.5), 255.0  );
  573.  
  574.  
  575. /*
  576.  *         handle case where pixel values are written to a file as RGB values
  577.  */
  578.            if (! debug_flag)  {
  579.                if (WritePixelsFlag)  {
  580.                    fwrite ( (char *) &red_i, sizeof(short), 1, ofp);
  581.                    fwrite ( (char *) &green_i, sizeof(short), 1, ofp);
  582.                    fwrite ( (char *) &blue_i, sizeof(short), 1, ofp);
  583.                    }
  584.  
  585.                if (XmitPixelsFlag)  {
  586.                     XmitBuffer[XB_next++] = red_i;
  587.                     XmitBuffer[XB_next++] = green_i;
  588.                     XmitBuffer[XB_next++] = blue_i;
  589.                    }
  590.  
  591.  
  592.               }
  593.  
  594.  
  595. /*
  596.  *  handle case where pixel values are written to screen as RGB values
  597.  */
  598.            else
  599.               printf ("I: (%f,%f, %f)     RGB: (%d, %d, %d)\n",
  600.                                                Ipix[i].x, Ipix[i].y, Ipix[i].z,
  601.                                                red_i, green_i, blue_i);
  602.  
  603.  
  604.           }  /* end -- for loop */
  605.  
  606.        if (XmitPixelsFlag)  {
  607.            RT_XmitPixels(XmitBuffer, scan, npix);
  608.            if (scan == shared->ScanLimit-1)
  609.                RT_XmitPixels(NULL, -1, -1);
  610.           }
  611.        
  612.  
  613.       }
  614.  
  615.  
  616.  
  617.  
  618. /*
  619.  *******************************************************************************
  620.  *
  621.  *  Name:  RT_XmitPixels
  622.  *
  623.  *  Purpose:  this routine is responsible for transmitting a specified (buffer)
  624.  *            scan line to any interested clients.
  625.  *            TECHNICAL NOTE:
  626.  *                 Because of limitations of the SetPixel routine in Windows NT
  627.  *            clients will not attempt to display their data until they are told
  628.  *            that a parallel step has been completed.  This routine will send a
  629.  *            sentinel value indicating this fact to all clients if it determines
  630.  *            that the pointer to buffer is NULL.
  631.  *
  632.  *
  633.  *  Input Parameters
  634.  *
  635.  *     buffer - array of pixel intensity values to be transmitted
  636.  *     scan_no - scan line number for array of pixel intensity values
  637.  *     npix - number of pixel intensity values in pixel array (buffer)
  638.  *
  639.  *
  640.  *  Output Parameters
  641.  *
  642.  *     none
  643.  *
  644.  *******************************************************************************
  645.  */
  646. void
  647.    RT_XmitPixels (short buffer[], int scan_no, int npix)
  648.       {
  649.        static int RT_DC[100];
  650.        static int num_clients = 0;
  651.  
  652.        struct timeval TimeOut;
  653.        fd_set mask;
  654.        int scanpix[2];
  655.        int nclients;
  656.        int i;
  657.  
  658. /*
  659.  +++++++++++++++++++++++++++++++++++++++++++++++++
  660.  +     setup pending connections and send new
  661.  +     client and inform it of image size
  662.  +++++++++++++++++++++++++++++++++++++++++++++++++
  663.  */
  664.  
  665.        FD_ZERO(&mask);
  666.        FD_SET(RT_sd, &mask);
  667.  
  668.        TimeOut.tv_sec = 0;
  669.        TimeOut.tv_usec = 0;
  670.  
  671.  
  672.        scanpix[0] = shared->nscan;
  673.        scanpix[1] = shared->npix;
  674.  
  675.        if ((nclients = select(FD_SETSIZE, &mask, NULL, NULL, &TimeOut)) == SOCKET_ERROR)  {
  676.            perror("Select Error:  ");
  677.            exit(0);
  678.            }
  679.  
  680.        for (i=0; i<nclients; i++) {
  681.            RT_DC[num_clients] = accept(RT_sd, 0, 0);
  682.  
  683.            if (RT_Send(RT_DC[num_clients++], (char *) scanpix, 2*sizeof(int)) != 8)  {
  684.                printf ("Error:  Scan Prefix wrong length. -- EXITING\n");
  685.                exit(1);
  686.               }
  687.           }
  688.  
  689. /*
  690.  +++++++++++++++++++++++++++++++++++++++++++++++++
  691.  +     send pixels to all connected clients 
  692.  +++++++++++++++++++++++++++++++++++++++++++++++++
  693.  */
  694.  
  695.        if (num_clients == 0)  {
  696.            printf("Warning:  For Scanline %d No Clients Listening -- Data Tranmission NOT Performed\n", scan_no);
  697.            return;
  698.           
  699.           }
  700.  
  701.  
  702.        for (i=0; i<num_clients; i++)  {
  703.  
  704. //
  705. //         if there is  data buffer -- send scan no. and data to client
  706. //
  707.            if (buffer != NULL)  {
  708.  
  709.                if (RT_Send(RT_DC[i], (char *) &scan_no, sizeof(int)) != 4)  {
  710.                    printf ("Error:  Scan Prefix wrong length. -- EXITING\n");
  711.                    exit(1);
  712.                   }
  713.                
  714.                if (RT_Send(RT_DC[i], (char *) buffer, 3*npix*sizeof(short)) != 3*npix*sizeof(short))  {
  715.                    printf ("Error:  Scan Data wrong length. -- EXITING\n");
  716.                    exit(1);
  717.                   }
  718.                   
  719.               }  /* end -- if buffer is NULL */ 
  720.  
  721. //
  722. //         if there is no data buffer -- send sentinal to client
  723. //
  724.            else  {
  725.                if (RT_Send(RT_DC[i], (char *) &scan_no, sizeof(int)) != 4)  {
  726.                    printf ("Error:  Scan Prefix wrong length. -- EXITING\n");
  727.                    exit(1);
  728.                   }
  729.               }  /* end -- else buffer is NOT NULL */
  730.  
  731.           }  /* end -- for num_clients */
  732.  
  733.       }
  734.  
  735.  
  736.  
  737. /*
  738.  *******************************************************************************
  739.  *
  740.  *  Name:  RT_Send
  741.  *
  742.  *  Purpose:  this routine contains the low level system calls needed to send
  743.  *            data to a client.   
  744.  *
  745.  *
  746.  *
  747.  *  Input Parameters
  748.  *
  749.  *     sd -    socket descriptor
  750.  *     buf - buffer containing data to be send
  751.  *     bytes - number of data bytes in buffer
  752.  *
  753.  *
  754.  *  Output Parameters
  755.  *
  756.  *     none
  757.  *
  758.  *******************************************************************************
  759.  */
  760. int
  761.    RT_Send (int sd, char buf[], int bytes)
  762.       {
  763.        int size, SendSize;
  764.        char *cPtr;
  765.  
  766.        cPtr =  buf;
  767.        size = bytes;
  768.  
  769.  
  770.        while (size > 0)  {
  771.     
  772.            if ((SendSize = send(sd, cPtr, size, 0)) == -1)  {
  773.                perror("Xmit Error:  ");
  774.                exit(1);
  775.               }
  776.            else if (SendSize == 0)  
  777.                return(0);
  778.  
  779.            cPtr += SendSize;
  780.            size -= SendSize;
  781.           }
  782.  
  783.     return(bytes);
  784.    }
  785.  
  786.  
  787.  
  788. /*
  789.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  790.   File:  texture_map.c
  791.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  792.  */
  793.  
  794.  
  795. /*
  796.  *******************************************************************************
  797.  *
  798.  *  Name:  RT_TextureMap
  799.  *
  800.  *  Purpose:  this routine was designed to be a general texture mapping 
  801.  *            routine for spheres, triangles, & rectangles.  However, it 
  802.  *            is currently hardwired to map a checkerboard onto a plane.
  803.  *
  804.  *
  805.  *
  806.  *  Input Parameters
  807.  *
  808.  *     pt - point to mapped into texture map
  809.  *     obj_ptr - pointer to object containing pt
  810.  *
  811.  *
  812.  *  Output Parameters
  813.  *
  814.  *     Od - texture map color for point
  815.  *
  816.  *
  817.  *******************************************************************************
  818.  */
  819. void
  820.    RT_TextureMap(Vector pt, Obj *obj_ptr, Vector *Od)
  821.       {
  822.        Rect_Obj *r_ptr;
  823.  
  824.        Point Pt;
  825.  
  826.        float Xmax, Xmin;
  827.        float Ymax, Ymin;
  828.  
  829.        float Umin = (float)0.0, Umax = (float)1.0;
  830.        float Vmin = (float)0.0, Vmax = (float)1.0;
  831.  
  832.        float u, v;
  833.  
  834.        int u_val, v_val;
  835.        int M = 12;
  836.  
  837.  
  838.        switch (obj_ptr->label)  {
  839.  
  840.            case SPHERE:
  841.                break;
  842.  
  843.            case TRIANGLE:
  844.                break;
  845.  
  846.            case RECTANGLE:
  847.  
  848.                r_ptr = (Rect_Obj *) obj_ptr->ptr;
  849.  
  850. /*
  851.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  852.  +  map rectangle to 2D space
  853.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  854.  */
  855.                switch(r_ptr->normal)  {
  856.  
  857. /*
  858.  *                 handle case where rectangle || to y-z plane
  859.  */
  860.                    case X_AXIS:
  861.                        Pt.x = pt.y;
  862.                        Pt.y = pt.z;
  863.  
  864.                        Xmax = r_ptr->max_pt.y;
  865.                        Xmin = r_ptr->min_pt.y;
  866.  
  867.                        Ymax = r_ptr->max_pt.z;
  868.                        Ymin = r_ptr->min_pt.z;
  869.                        break;
  870.  
  871. /*
  872.  *                 handle case where rectangle || to x-z plane
  873.  */
  874.                    case Y_AXIS:
  875.                        Pt.x = pt.x;
  876.                        Pt.y = pt.z;
  877.  
  878.                        Xmax = r_ptr->max_pt.x;
  879.                        Xmin = r_ptr->min_pt.x;
  880.  
  881.                        Ymax = r_ptr->max_pt.z;
  882.                        Ymin = r_ptr->min_pt.z;
  883.                        break;
  884.  
  885. /*
  886.  *                 handle case where rectangle || to x-y plane
  887.  */
  888.                    case Z_AXIS:
  889.                        Pt.x = pt.x;
  890.                        Pt.y = pt.y;
  891.  
  892.                        Xmax = r_ptr->max_pt.x;
  893.                        Xmin = r_ptr->min_pt.x;
  894.  
  895.                        Ymax = r_ptr->max_pt.y;
  896.                        Ymin = r_ptr->min_pt.y;
  897.                        break;
  898.                   }
  899.  
  900.  
  901. /*
  902.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  903.  +  determine texture at point
  904.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  905.  * 
  906.  *             map rectangle to uv space
  907.  */
  908.                u = ( (Pt.x - Xmin) * (Umax-Umin) / (Xmax-Xmin) ) + Umin;
  909.                v = ( (Pt.y - Ymin) * (Vmax-Vmin) / (Ymax-Ymin) ) + Vmin;
  910.  
  911. /* 
  912.  *             determine Od for checkerboard texture
  913.  */
  914.                u_val = (int) (u * (float) M) % 2;
  915.                v_val = (int) (v * (float) M) % 2;
  916.  
  917.                if (u_val == v_val)
  918.                    vset(Od, (float) 1.0, (float) 1.0, (float) 0.0);
  919.                else
  920.                    vset(Od, (float) 1.0, (float) 0.0, (float) 0.0);
  921.  
  922.                break;
  923.           }
  924.       }
  925.  
  926.  
  927.  
  928.  
  929.  
  930. /*
  931.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  932.   File:  configure.c
  933.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  934.  */
  935.  
  936.  
  937. extern FILE *ofp;
  938.  
  939. /*
  940.  *******************************************************************************
  941.  *
  942.  *  Name:  RT_Configure
  943.  *
  944.  *  Purpose:  this routine sets the scene configuration from an input file
  945.  *            specified by the input parameter "config_file"
  946.  *
  947.  *
  948.  *
  949.  *  Input Parameters
  950.  *
  951.  *     config_file - input data file that specified scene parameters
  952.  *
  953.  *
  954.  *  Output Parameters
  955.  *
  956.  *     none
  957.  *
  958.  *******************************************************************************
  959.  */
  960. void
  961.    RT_Configure(char *config_file)
  962.       {
  963.        Obj_Props *p_ptr;
  964.        Light *l_ptr;
  965.  
  966.        Vector Od_in, Od_out, Os;
  967.        float Ka, Kd, Ks, Kt;
  968.        float refract_index;
  969.        int txt_flg;
  970.  
  971.        FILE *cntl_fp;
  972.        FILE *obj_fp;
  973.  
  974.        Boolean init_objects = TRUE;
  975.        Boolean viewport_flag = FALSE;
  976.        Boolean objects_flag = FALSE;
  977.  
  978.        char cntl_str[20];
  979.        char file_str[50];
  980.        char lite_str[50];
  981.  
  982.        int obj_cnt = 0, lite_cnt = 0;
  983.        int num_obj;
  984.        int x_res, y_res;
  985.        int i;
  986.        int junk;
  987.  
  988.  
  989.        if ((cntl_fp = fopen(config_file, "r")) == NULL)  {
  990.            printf ("***** Error:  Batch Configuration File Open Failed");
  991.            printf (" -- EXITING *****\n");
  992.            perror("File Error Was:  ");
  993.            printf("Configuration File Name Was: %s\n", config_file);
  994.            exit(1);
  995.           }
  996.  
  997.  
  998.        fscanf (cntl_fp, "%s\n", cntl_str);
  999.  
  1000. /*
  1001.  *******************************************************************************
  1002.  *
  1003.  *  interpret configuration commands
  1004.  *
  1005.  *******************************************************************************
  1006.  */
  1007.        while (strcmp("#end", cntl_str) != 0)  {
  1008.  
  1009. /*
  1010.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1011.  *  handle command to open batch output data file
  1012.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1013.  */
  1014.            if (strcmp("#output", cntl_str) == 0)  {
  1015.  
  1016.                fscanf (cntl_fp, "%s", file_str);
  1017.  
  1018.                if ((ofp = fopen(file_str, "wb")) == NULL)  {
  1019.                       printf ("***** Error:  Output File Open Failed");
  1020.                    printf (" -- EXITING *****\n");
  1021.                    perror("File Error Was:  ");
  1022.                    exit(1);
  1023.                   }
  1024.  
  1025.                WritePixelsFlag = TRUE;
  1026.               }
  1027.  
  1028. /*
  1029.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1030.  *  handle command to read object data file
  1031.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1032.  */
  1033.            else if (strcmp("#obj", cntl_str) == 0)  {
  1034.  
  1035.                if (viewport_flag)  {
  1036.                   printf ("***** Error:  Viewport Has been Specified *****\n");
  1037.                   printf ("     All objects must be specified before a");
  1038.                   printf ("     Viewport control card is seen -- EXITING\n");
  1039.                   exit (1);
  1040.                  }
  1041.  
  1042.                fscanf (cntl_fp, "%s", file_str);
  1043.  
  1044.                if ((obj_fp = fopen(file_str, "r")) == NULL)  {
  1045.                       printf ("***** Error:  Input Object Data File Open Failed");
  1046.                    printf (" -- EXITING *****\n");
  1047.                    perror("File Error Was:  ");
  1048.                    exit(1);
  1049.                   }
  1050.                fscanf (cntl_fp, "%f %f %f\n", &Od_in.x, &Od_in.y,   &Od_in.z);
  1051.                fscanf (cntl_fp, "%f %f %f\n", &Od_out.x, &Od_out.y, &Od_out.z);
  1052.                fscanf (cntl_fp, "%f %f %f\n", &Os.x,     &Os.y,     &Os.z);
  1053.  
  1054.                fscanf (cntl_fp, "%f %f %f %f %d\n", &Ka, &Kd, &Ks, &Kt,
  1055.                                                     &txt_flg);
  1056.                fscanf (cntl_fp, "%f\n", &refract_index);
  1057.  
  1058.                fscanf (obj_fp, "%d\n", &num_obj);
  1059.  
  1060.                for (i=0; i<num_obj; i++)  {
  1061.  
  1062.                    build_object(obj_fp, init_objects);
  1063.                    init_objects = FALSE;
  1064.                    p_ptr = &shared->obj_props[obj_cnt];
  1065.  
  1066.                    p_ptr->Od_in  =  Od_in;
  1067.                    p_ptr->Od_out =  Od_out;
  1068.                    p_ptr->Os     =  Os;
  1069.  
  1070.                    p_ptr->Ka = Ka;
  1071.                    p_ptr->Kd = Kd;
  1072.                    p_ptr->Ks = Ks;
  1073.                    p_ptr->Kt = Kt;
  1074.  
  1075.                    p_ptr->txt_flg = txt_flg;
  1076.                    p_ptr->n = refract_index;
  1077.  
  1078.                    obj_cnt++;
  1079.                   }  /* end for loop */
  1080.  
  1081.  
  1082.                objects_flag = TRUE;
  1083.                fclose(obj_fp);
  1084.               }
  1085.  
  1086. /*
  1087.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1088.  *  handle command to set phong constant
  1089.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1090.  */
  1091.            else if (strcmp("#phong_constant", cntl_str) == 0)  {
  1092.                fscanf (cntl_fp, "%f\n", &shared->PhongConst);
  1093.               }
  1094.  
  1095. /*
  1096.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1097.  *  handle command to set manimum recurrsive depth
  1098.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1099.  */
  1100.            else if (strcmp("#depth_limit", cntl_str) == 0)  {
  1101.                fscanf (cntl_fp, "%d\n", &shared->depth_limit);
  1102.               }
  1103.  
  1104. /*
  1105.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1106.  *  handle command to set manimum recurrsive depth
  1107.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1108.  */
  1109.            else if (strcmp("#scan_set_count", cntl_str) == 0)  {
  1110.                fscanf (cntl_fp, "%d\n", &nIter);
  1111.               }
  1112.  
  1113. /*
  1114.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1115.  *  handle command to set number of thread segments
  1116.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1117.  */
  1118.            else if (strcmp("#thread_segments", cntl_str) == 0)  {
  1119.  
  1120.                if ( num_T <= 0)  {
  1121.                    if (! viewport_flag)  {
  1122.                       printf ("***** Error:  Viewport has NOT been Specified ");
  1123.                       printf ("*****\n");
  1124.                       printf ("     The thread count cannot be specified before a");
  1125.                       printf ("     Viewport control card is seen -- EXITING\n");
  1126.                       exit (1);
  1127.                      }
  1128.  
  1129.                    fscanf (cntl_fp, "%d\n", &num_T);
  1130.  
  1131.                     if (num_T <= 0)  {
  1132.                         printf (" ***** Error:  Thread Count MUST be greater than ");
  1133.                         printf ("0 -- EXITING *****\n");
  1134.                         exit(0);
  1135.                        }
  1136.  
  1137.                   }
  1138.                else
  1139.                   fscanf (cntl_fp, "%d\n", &junk);
  1140.  
  1141.  
  1142.               }
  1143. /*
  1144.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1145.  *  handle command to set viewport size
  1146.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1147.  */
  1148.            else if (strcmp("#viewport", cntl_str) == 0)  {
  1149.  
  1150.                if (! objects_flag)  {
  1151.                    printf ("***** Error -- No Objects Specified *****\n");
  1152.                    printf ("     All objects must be specified before a");
  1153.                    printf ("     Viewport control card is seen -- EXITING\n");
  1154.                    exit (1);
  1155.                   }
  1156.  
  1157.                fscanf (cntl_fp, "%d %d\n", &x_res, &y_res);
  1158.  
  1159.                shared->vp.scr_reg.min_pt.x = work_reg.min_pt.x;
  1160.                shared->vp.scr_reg.max_pt.x = shared->vp.scr_reg.min_pt.x+x_res-1;
  1161.  
  1162.                shared->vp.scr_reg.max_pt.y = work_reg.max_pt.y;
  1163.                shared->vp.scr_reg.min_pt.y = shared->vp.scr_reg.max_pt.y-y_res+1;
  1164.  
  1165.                fscanf (cntl_fp, "%f %f %f\n", &shared->vp.F.x, &shared->vp.F.y,
  1166.                                                               &shared->vp.F.z);
  1167.  
  1168.                fscanf (cntl_fp, "%f %f %f\n", &shared->vp.A.x, &shared->vp.A.y,
  1169.                                                               &shared->vp.A.z);
  1170.  
  1171.                fscanf (cntl_fp, "%f %f %f\n", &shared->vp.U.x, &shared->vp.U.y,
  1172.                                                               &shared->vp.U.z);
  1173.  
  1174.                fscanf (cntl_fp, "%f\n", &shared->vp.v);
  1175.  
  1176.  
  1177.                shared->vp.F = (vector_len(&shared->vp.F) != 0.0)?
  1178.                                                   shared->vp.F : obj_defaults.F;
  1179.  
  1180.                shared->vp.A = (vector_len(&shared->vp.A) != 0.0)?
  1181.                                                   shared->vp.A : obj_defaults.A;
  1182.  
  1183.                shared->vp.U = (vector_len(&shared->vp.U) != 0.0)?
  1184.                                                   shared->vp.U : obj_defaults.U;
  1185.  
  1186.                shared->vp.v = (shared->vp.v != 0.0)? shared->vp.v : obj_defaults.v;
  1187.  
  1188.                viewport_flag = TRUE;
  1189.               }
  1190.  
  1191. /*
  1192.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1193.  *  handle command to set light source
  1194.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1195.  */
  1196.            else if (strcmp("#light_source", cntl_str) == 0)  {
  1197.                l_ptr = &shared->lights[lite_cnt];
  1198.  
  1199.                l_ptr->on = TRUE;
  1200.  
  1201.                fscanf (cntl_fp, "%f %f %f\n",&l_ptr->L_pt.x, &l_ptr->L_pt.y,
  1202.                                              &l_ptr->L_pt.z);
  1203.  
  1204.                fscanf (cntl_fp, "%f %f %f\n",&l_ptr->I.x, &l_ptr->I.y,
  1205.                                              &l_ptr->I.z);
  1206.  
  1207.                l_ptr->L_pt = (vector_len(&l_ptr->L_pt) != 0.0)?
  1208.                                                   l_ptr->L_pt : obj_defaults.F;
  1209.                fscanf (cntl_fp, "%s\n", lite_str);
  1210.  
  1211.                if (strcmp("directed", lite_str) == 0)  {
  1212.                    l_ptr->directed = TRUE;
  1213.                    fscanf (cntl_fp, "%f %f %f\n",&l_ptr->L_a.x, &l_ptr->L_a.y,
  1214.                                                  &l_ptr->L_a.z);
  1215.  
  1216.                    fscanf (cntl_fp, "%f",&l_ptr->ro);
  1217.                    fscanf (cntl_fp, "%f\n",&l_ptr->cos_delta);
  1218.                   }
  1219.  
  1220.                else  {
  1221.                    l_ptr->directed = FALSE;
  1222.                    vset(&l_ptr->L_a,  (float) 0.0,  (float) 0.0,  (float) 0.0);
  1223.  
  1224.                    l_ptr->ro = (float) 0.0;
  1225.                    l_ptr->cos_delta = (float) 0.0;
  1226.                   }
  1227.  
  1228.                lite_cnt++;
  1229.               }
  1230. /*
  1231.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1232.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1233.  */
  1234.            fscanf (cntl_fp, "%s\n", cntl_str);
  1235.  
  1236.           }  /* end while */
  1237.  
  1238.       }
  1239.