home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / vectoper.zip / RTIntOps.cpp < prev    next >
C/C++ Source or Header  |  1996-09-19  |  27KB  |  902 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 "RTObjOps.h"
  11. #include "RTIMOps.h"
  12. #include "RayTrace.h"
  13. #include "RTIntOps.h"
  14.  
  15.  
  16.  
  17. /*
  18.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  19.   File:  nearest_int.c
  20.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  21.  */
  22.  
  23.  
  24. /*
  25.  *******************************************************************************
  26.  *
  27.  *  Name:  nearest_int
  28.  *
  29.  *  Purpose:  this routine determines which objects the specified ray in-
  30.  *            tersects.  It then chooses the intersection closest to the
  31.  *            origin of the ray and returns the parameters associated with
  32.  *            this intersection.
  33.  *
  34.  *            NOTE:  this routine uses a tolerance factor in order to
  35.  *                   screen out the intersection between a ray and its
  36.  *                   origin point.
  37.  *
  38.  *
  39.  *
  40.  *  Input Parameters
  41.  *
  42.  *     i_ray - ray currently being traced
  43.  *
  44.  *
  45.  *  Output Parameters
  46.  *
  47.  *     obj_no - index of intersected object in array of objects
  48.  *     int_val - point of intersection in object
  49.  *     Pt_norm -  normal at point
  50.  *     patch_norm -normal of patch containing point
  51.  *
  52.  *******************************************************************************
  53.  */
  54. Boolean
  55.    nearest_int(Ray i_ray, int *obj_no, Vector *int_val, Vector *Pt_norm, Vector *patch_norm)
  56.       {
  57.        Sphere_Obj *s_ptr;
  58.        Poly_Mesh_Obj *poly_ptr;
  59.        Rect_Obj *rect_ptr;
  60.  
  61.        Vector int_pt;
  62.        Vector int_norm, norm;
  63.  
  64.        Boolean norm_flg = TRUE;
  65.        Boolean int_flg = FALSE;
  66.        Boolean return_int_flg = FALSE;
  67.  
  68.        float t, t_near = (float)99999.0;
  69.  
  70.        int i;
  71.  
  72.  
  73. /*
  74.  +++++++++++++++++++++++++++++++++++++++++++++++++
  75.  * determine nearest intersection
  76.  +++++++++++++++++++++++++++++++++++++++++++++++++
  77.  */
  78.        for (i=0; i<shared->obj_num; i++)  {
  79.  
  80.            switch (shared->obj_list[i].label)  {
  81.  
  82. /*
  83.  *             handle case of sphere object
  84.  */
  85.                case SPHERE:
  86.                    s_ptr = (Sphere_Obj *) shared->obj_list[i].ptr;
  87.  
  88.                    int_flg = sphere_int(i_ray, s_ptr, norm_flg, &int_pt,
  89.                                         &int_norm, &norm, &t);
  90.                    break;
  91.  
  92. /*
  93.  *             handle case of polygon mesh object
  94.  */
  95.                case POLY_MESH:
  96.                    poly_ptr = (Poly_Mesh_Obj *) shared->obj_list[i].ptr;
  97.                    int_flg = poly_mesh_int(i_ray, poly_ptr, norm_flg, NEAREST,
  98.                                            &t, &int_pt, &int_norm, &norm);
  99.                    break;
  100.  
  101. /*
  102.  *             handle case of rectangle object
  103.  */
  104.                case RECTANGLE:
  105.                    rect_ptr = (Rect_Obj *) shared->obj_list[i].ptr;
  106.                    int_flg = rect_int(i_ray, rect_ptr, norm_flg, &t, &int_pt,
  107.                                       &int_norm);
  108.                    norm = int_norm;
  109.                    break;
  110.               }
  111.  
  112.  
  113. /*
  114.  *         record this intersection if:
  115.  *            - there is an intersection   (int_flg)
  116.  *            - the intersection is not at the origin of ray   (t > 0.1)
  117.  *            - the intersection is the nearest so far   (t < t_near)
  118.  */
  119.  
  120.            if ( int_flg && (t > 0.001) && (t < t_near) )  {
  121.                t_near = t;
  122.                *obj_no = i;
  123.                *int_val = int_pt;
  124.                *Pt_norm = int_norm;
  125.                *patch_norm = norm;
  126.                return_int_flg = TRUE;
  127.               }
  128.  
  129.           }
  130.  
  131. /*
  132.  +++++++++++++++++++++++++++++++++++++++++++++++++
  133.  +++++++++++++++++++++++++++++++++++++++++++++++++
  134.  */
  135.  
  136.        return(return_int_flg);
  137.       }
  138.  
  139.  
  140.  
  141. /*
  142.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  143.   File:  sphere_int.c
  144.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  145.  */
  146.  
  147.  
  148.  
  149. /*
  150.  *******************************************************************************
  151.  *
  152.  *  Name:  sphere_int
  153.  *
  154.  *  Purpose:  this routine determines the intersection between the specified
  155.  *            ray and sphere by solving the quadratic equation representing
  156.  *            their intersection.  It at least one intersection exists, the
  157.  *            closest one is returned along with the ray "t" value at the
  158.  *            point of intersection.
  159.  *
  160.  *            NOTE:  the sphere normal is only returned if the "norm_flag" 
  161.  *                   is set to TRUE.
  162.  *
  163.  *
  164.  *
  165.  *  Input Parameters
  166.  *
  167.  *     ray - specified ray
  168.  *     s_ptr - ptr to sphere object
  169.  *     norm_flg - flag indicating whether normal should be returned
  170.  *
  171.  *
  172.  *  Output Parameters
  173.  *
  174.  *     int_pt - point of intersection between sphere & ray
  175.  *     pt_norm - normal at point
  176.  *     norm - normal of sphere
  177.  *     t - distance along ray where intersection occures
  178.  *
  179.  *******************************************************************************
  180.  */
  181. Boolean
  182.    sphere_int (Ray ray, Sphere_Obj *s_ptr, Boolean norm_flg,
  183.                Vector *int_pt, Vector *pt_norm, Vector *norm, float *t)
  184.       {
  185.        Vector tmp_vec;
  186.        Boolean int_flg;
  187.  
  188.        float A, B, C;
  189.        float Bsq_4AC;
  190.        float t1, t2;
  191.        float r_sq;
  192.  
  193.  
  194. /*
  195.  *     initialization - calculate squared radius of sphere
  196.  */
  197.        r_sq = SQR(s_ptr->center_pt.x - s_ptr->radius_pt.x) + 
  198.               SQR(s_ptr->center_pt.y - s_ptr->radius_pt.y) + 
  199.               SQR(s_ptr->center_pt.z - s_ptr->radius_pt.z);
  200.  
  201. /*
  202.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  203.  +  calculate elements of quadratic formula
  204.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  205.  */
  206.        A = SQR(ray.dir.x) + SQR(ray.dir.y) + SQR(ray.dir.z);
  207.  
  208.        B = 2 * (  (ray.dir.x * (ray.origin.x - s_ptr->center_pt.x))  +
  209.                   (ray.dir.y * (ray.origin.y - s_ptr->center_pt.y))  +
  210.                   (ray.dir.z * (ray.origin.z - s_ptr->center_pt.z))     );
  211.  
  212.        C = SQR(ray.origin.x - s_ptr->center_pt.x)  +
  213.            SQR(ray.origin.y - s_ptr->center_pt.y)  +
  214.            SQR(ray.origin.z - s_ptr->center_pt.z)  - 
  215.            r_sq;
  216.  
  217.        Bsq_4AC = (B*B) - ( ((float)4.0) * A * C);
  218.  
  219. /*
  220.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  221.  +  determine solutions of quadratic formula
  222.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  223.  *
  224.  *     two imaginary solutions - no intersection
  225.  */
  226.        if (Bsq_4AC < 0.0)  {
  227.            int_flg = FALSE;
  228.           }
  229.  
  230. /* 
  231.  *     one real solution - one intersection
  232.  */
  233.        else if (Bsq_4AC == 0.0)  {
  234.            int_flg = TRUE;
  235.            *t = B / ( ((float)2.0) * A);
  236.  
  237.            *int_pt = ray.origin;
  238.            tmp_vec = VectorScaler_Product(&ray.dir, *t);
  239.            *int_pt = Vector_Sum(int_pt, &tmp_vec);
  240.           }
  241.  
  242. /* 
  243.  *     two real solutions - two intersections
  244.  */
  245.        else if (Bsq_4AC > 0.0)  {
  246.            int_flg = TRUE;
  247.            t1 = ( (-B) + sqrt(Bsq_4AC) ) / ( ((float)2.0) * A);
  248.            t2 = ( (-B) - sqrt(Bsq_4AC) ) / ( ((float)2.0) * A);
  249.  
  250.            if (t1 < 0.001)
  251.               *t = t2;
  252.            else if (t2 < 0.001)
  253.               *t = t1;
  254.            else
  255.               *t = (fabs(t1) < fabs(t2))? t1 : t2;
  256.  
  257.            *int_pt = ray.origin;
  258.            tmp_vec = VectorScaler_Product(&ray.dir, *t);
  259.            *int_pt = Vector_Sum(int_pt, &tmp_vec);
  260.           }
  261.  
  262. /*
  263.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  264.  +  determine sphere normal if needed
  265.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  266.  */
  267.        if (int_flg && norm_flg)  {
  268.            pt_norm->x = (int_pt->x - s_ptr->center_pt.x);
  269.            pt_norm->y = (int_pt->y - s_ptr->center_pt.y);
  270.            pt_norm->z = (int_pt->z - s_ptr->center_pt.z);
  271.  
  272.            *pt_norm = VectorScaler_Division(pt_norm, vector_len(pt_norm));
  273.            *norm = *pt_norm;
  274.           }
  275. /*
  276.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  277.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  278.  */
  279.  
  280.        return (int_flg);
  281.       }
  282.  
  283.  
  284.  
  285. /*
  286.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  287.   File:  triang_int.c
  288.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  289.  */
  290.  
  291.  
  292.  
  293. int triang_int(Ray ray, Triangle *tptr, Vector tdata[], Vector *nptr,
  294.               Boolean norm_flg, Vector *Pint, Vector *p_norm, float *t);
  295.  
  296. void project_2D (Triangle *tptr, Vector tdata[], Vector Pi,
  297.                  Point t_pr[], Point *Ppr);
  298.  
  299. float tri_area_x2 (Point pt_a, Point pt_b, Point pt_c);
  300.  
  301.  
  302.  
  303. /*
  304.  *******************************************************************************
  305.  *
  306.  *  Name:  poly_mesh_int
  307.  *
  308.  *  Purpose:  this routine cycles through the triangles in a polygon mesh
  309.  *            looking for an intersection with the specified ray.  In order
  310.  *            to minimize cost it handles two different cases based on the
  311.  *            parameter "type":
  312.  *
  313.  *               - case LF: Light (Shadow) Feeler
  314.  *                   the ray is a light (shadow) feeler and therefore any
  315.  *                   intersection will be sufficient.  The routine returns
  316.  *                   with the first intersection found.
  317.  *
  318.  *               - case NEAREST: Nearest Intersection
  319.  *                   the ray is not a light (shadow) feeler and therefore
  320.  *                   the nearest intersection is being sought.  All tri-
  321.  *                   angles are examined in order to insure that the inter-
  322.  *                   section closest to the ray origin is returned.
  323.  *
  324.  *
  325.  *
  326.  *  Input Parameters
  327.  *
  328.  *     ray - specified ray
  329.  *     obj_ptr - pointer to polygon mesh object
  330.  *     norm_flg - flag indicating whether the normals should be returned
  331.  *     type - param indicating whether first or closest int should be returned
  332.  *
  333.  *
  334.  *  Output Parameters
  335.  *
  336.  *     t_val - distance along ray of intersection
  337.  *     int_val - intersection point
  338.  *     Pt_norm - interpolated normal at intersection
  339.  *     t_norm - normal of triangle containing intersection point
  340.  *
  341.  *******************************************************************************
  342.  */
  343. Boolean
  344.    poly_mesh_int(Ray ray, Poly_Mesh_Obj *obj_ptr, Boolean norm_flg,
  345.                  int type, float *t_val,
  346.                  Vector *int_val, Vector *Pt_norm, Vector *t_norm)
  347.       {
  348.        Sphere_Obj *s_ptr;
  349.  
  350.        Vector tdata[3];
  351.        Vector new_int;
  352.  
  353.        Vector *nptr;
  354.  
  355.        Vector p_norm, norm;
  356.  
  357.        Boolean done = FALSE;
  358.        Boolean int_flg = FALSE;
  359.        Boolean return_int_flg = FALSE;
  360.  
  361.        float t;
  362.  
  363.        Surface *sptr;
  364.        Triangle *tptr;
  365.  
  366.        int i, j, k;
  367.  
  368.  
  369.        *t_val = (float) 9999.0;
  370.  
  371.  
  372.  
  373. /*
  374.  *     run quick rejection test on object's bounding sphere 
  375.  */
  376.        //s_ptr = (Sphere_Obj *) &obj_ptr->b_sph;
  377.        //int_flg = sphere_int(ray, s_ptr, FALSE, &new_int, NULL, NULL, &t);
  378.  
  379.        //if ( (! int_flg) || (t < 0.001) )
  380.        //    return(FALSE);
  381.  
  382.  
  383.        int_flg = FALSE;
  384.  
  385.  
  386. /*
  387.  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  388.  *  cycle through triangles in polygon mesh object
  389.  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  390.  */
  391.        for (i=0; i<obj_ptr->num_surf && !done; i++)  { 
  392.            sptr = &obj_ptr->surfs[i];
  393.            nptr = obj_ptr->surf_norms[i];
  394.  
  395.            for (j=0; j<sptr->num_triang && ! done; j++)  {
  396.                tptr = &sptr->triangs[j];
  397.  
  398. /*
  399.  *             put triangle vertices in more convienent sructure
  400.  */
  401.                for (k=0; k<3; k++)
  402.                    tdata[k] = obj_ptr->data[ tptr->v[k] ];
  403.  
  404. /*
  405.  *             determine intersection
  406.  */
  407.                int_flg = triang_int(ray, tptr, tdata, nptr, norm_flg, &new_int,
  408.                                                                   &p_norm, &t);
  409.                switch (type)  {
  410.  
  411. /*
  412.  *                 if Light Feeler - prepare to stop if intersection
  413.  */
  414.                    case LF:
  415.                       if ( (int_flg) && (t < *t_val) && (t > 0.001) ) {
  416.                           done = int_flg;
  417.                           return_int_flg = int_flg;
  418.                           *int_val = new_int;
  419.                           *t_val = t;
  420.                          }
  421.                       break;
  422.  
  423. /*
  424.  *                 if Nearest Intersection - record int. info and continue
  425.  */
  426.                    case NEAREST:
  427.                       if ( (int_flg) && (t < *t_val) && (t > 0.001) ) {
  428.                           return_int_flg = int_flg;
  429.                           *int_val = new_int;
  430.                           *t_val = t;
  431.                           if (norm_flg)  {
  432.                               *Pt_norm = p_norm;
  433.                               *t_norm = tptr->normal;
  434.                              }
  435.                          }
  436.                       break;
  437.                   }  /* end -- switch */
  438.  
  439.               }  /* end -- for each triangle in surface*/
  440.           }  /* end -- outer for each surface in poly mesh*/
  441. /*
  442.  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  443.  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  444.  */
  445.        return(return_int_flg);
  446.       }
  447.  
  448.  
  449.  
  450. /*
  451.  *******************************************************************************
  452.  *
  453.  *  Name:  triang_int
  454.  *
  455.  *  Purpose:  this routine determines if a ray intersects a triangle using
  456.  *            a three step algorithm.  Steps two and three are performed
  457.  *            ONLY if step one determines that some intersection has
  458.  *            occured:
  459.  *
  460.  *               1. Determine equation of plane containing containing
  461.  *                  triangle using normal of triangle patch.  Then deter-
  462.  *                  mine if ray intersects this plane.
  463.  *
  464.  *               2. Project intersection of point & triangle into 2D space
  465.  *                  along coordinate axis parallel to largest normal com-
  466.  *                  ponent.
  467.  *
  468.  *               3. Determine barycentric coordinates of triangle projec-
  469.  *                  tion.  Ray intersects triangle if all three barycen-
  470.  *                  centric coordinates are >= zero.
  471.  *
  472.  *
  473.  *
  474.  *  Input Parameters
  475.  *
  476.  *     ray - specified ray
  477.  *     tptr - pointer to specified triangle
  478.  *     tdata - array containing data points for triangle vertices
  479.  *     nptr - pointer to normals list containing normals at triangle vertices
  480.  *     norm_flg - flag indicating whether triangle normals should be returned
  481.  *
  482.  *
  483.  *  Output Parameters
  484.  *
  485.  *     Pint - point of intersection between ray and triangle
  486.  *     p_norm - interpolated normal at point of intersection
  487.  *     t - distance along ray of intersection
  488.  *
  489.  *******************************************************************************
  490.  */
  491. int
  492.    triang_int(Ray ray, Triangle *tptr, Vector tdata[], Vector *nptr,
  493.               Boolean norm_flg, Vector *Pint, Vector *p_norm, float *t)
  494.       {
  495.        Vector nfrac;
  496.        Point T_pr[3];
  497.  
  498.        Point P_pr;
  499.  
  500.        Boolean int_flg = FALSE;
  501.  
  502.        float A, B, C, D;
  503.        float numer, denom;
  504.        float T_area;
  505.        float u, v, w;
  506.  
  507.  
  508. /*
  509.  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  510.  *  determine if ray intersects plane containing triangle
  511.  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  512.  */
  513.        A = tptr->normal.x;
  514.        B = tptr->normal.y;
  515.        C = tptr->normal.z;
  516.  
  517.        D = ((-A) * tdata[0].x) + ((-B) * tdata[0].y) + ((-C) * tdata[0].z);
  518.  
  519.        numer = (A * ray.origin.x) + (B * ray.origin.y) + (C * ray.origin.z) + D;
  520.  
  521.        denom = (A * ray.dir.x) + (B * ray.dir.y) + (C * ray.dir.z);
  522.  
  523.        *t = (denom != 0.0)? -(numer / denom): (float)0.0;
  524.  
  525. /*
  526.  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  527.  *  determine if intersection (if any) is within triangle
  528.  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  529.  */
  530.        if ( (numer == 0.0) || (denom == 0.0) || (*t <= 0.0) )  {
  531.            int_flg = FALSE;
  532.           }
  533.  
  534.  
  535.        else  {
  536. /*
  537.  *         determine intersection point and project to 2D space
  538.  */
  539.            *Pint = VectorScaler_Product(&ray.dir, *t);
  540.            *Pint = Vector_Sum(&ray.origin, Pint);
  541.  
  542.            project_2D (tptr, tdata, *Pint, T_pr, &P_pr);
  543.  
  544. /*
  545.  *         use barycentric coordinates to determine if triangle contains int
  546.  */
  547.            T_area = tri_area_x2(T_pr[0], T_pr[1], T_pr[2]);
  548.            u = tri_area_x2(P_pr, T_pr[1], T_pr[2]) / T_area;
  549.  
  550.            if (u >= 0.0)  {
  551.                v = tri_area_x2(T_pr[0], P_pr, T_pr[2]) / T_area;
  552.  
  553.                if (v >= 0.0)  {
  554.                    w = tri_area_x2(T_pr[0], T_pr[1], P_pr) / T_area;
  555.                    int_flg = (w >= 0)? TRUE : FALSE;
  556.                   }
  557.               }
  558.           }
  559. /*
  560.  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  561.  *  calculate interpolated normal at point - if necessary
  562.  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  563.  */
  564.        if (int_flg && norm_flg)  {
  565.  
  566.            vset(p_norm,  (float) 0.0,  (float) 0.0,  (float) 0.0);
  567.  
  568.            nfrac = VectorScaler_Product(&nptr[ tptr->v[0] ], u);    // u
  569.            *p_norm = Vector_Sum(p_norm, &nfrac);
  570.  
  571.            nfrac = VectorScaler_Product(&nptr[ tptr->v[1] ], v);    // v
  572.            *p_norm = Vector_Sum(p_norm, &nfrac);
  573.  
  574.            nfrac = VectorScaler_Product(&nptr[ tptr->v[2] ], w);    // w
  575.            *p_norm = Vector_Sum(p_norm, &nfrac);
  576.  
  577.  
  578.            *p_norm = VectorScaler_Division(p_norm, vector_len(p_norm));
  579.           }
  580. /*
  581.  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  582.  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  583.  */
  584.  
  585.        return(int_flg);
  586.       }
  587.  
  588.  
  589.  
  590. /*
  591.  *******************************************************************************
  592.  *
  593.  *  Name:  project_2D
  594.  *
  595.  *  Purpose:  this routine projects points on to the two dimensional co-
  596.  *            ordinate plane that is perpendicular to the largest compo-
  597.  *            nent of the normal for the specified triangle.
  598.  *           
  599.  *
  600.  *
  601.  *
  602.  *  Input Parameters
  603.  *
  604.  *     tptr - pointer to triangle in 3D space
  605.  *     tdata - triangle points in 3D space
  606.  *     Pi - intersection point in 3D space
  607.  *
  608.  *
  609.  *  Output Parameters
  610.  *
  611.  *     t_pr - triangle points in 2D space
  612.  *     Ppr - intersection point in 2D space
  613.  *
  614.  *******************************************************************************
  615.  */
  616. void
  617.    project_2D (Triangle *tptr, Vector tdata[], Vector Pi,
  618.                Point t_pr[], Point *Ppr)
  619.       {
  620.        Boolean ProjectionFlag = FALSE;
  621.        float Nx, Ny, Nz;
  622.        int i;
  623.  
  624.  
  625.        Nx = tptr->normal.x;
  626.        Ny = tptr->normal.y;
  627.        Nz = tptr->normal.z;
  628.  
  629. /*
  630.  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  631.  *  project || to z-axis if Nz is largest normal component
  632.  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  633.  */
  634.        if (  ( fabs(Nz) >= fabs(Nx) )  &&  ( fabs(Nz) >= fabs(Ny) )  )  {
  635.            ProjectionFlag = TRUE;
  636.            Ppr->x = Pi.x;
  637.            Ppr->y = Pi.y;
  638.  
  639.            for (i=0; i<3; i++)  {
  640.               t_pr[i].x = tdata[i].x;
  641.               t_pr[i].y = tdata[i].y;
  642.              }
  643.           }
  644.  
  645. /*
  646.  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  647.  *  project || to y-axis if Ny is largest normal component
  648.  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  649.  */
  650.        else if (  ( fabs(Ny) >= fabs(Nx) )  &&  ( fabs(Ny) >= fabs(Nz) )  )  {
  651.            ProjectionFlag = TRUE;
  652.            Ppr->x = Pi.x;
  653.            Ppr->y = Pi.z;
  654.  
  655.            for (i=0; i<3; i++)  {
  656.               t_pr[i].x = tdata[i].x;
  657.               t_pr[i].y = tdata[i].z;
  658.              }
  659.           }
  660.  
  661. /*
  662.  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  663.  *  project || to x-axis if Nx is largest normal component
  664.  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  665.  */
  666.        else if (  ( fabs(Nx) >= fabs(Ny) )  &&  ( fabs(Nx) >= fabs(Nz) )  )  {
  667.            ProjectionFlag = TRUE;
  668.            Ppr->x = Pi.y;
  669.            Ppr->y = Pi.z;
  670.  
  671.            for (i=0; i<3; i++)  {
  672.               t_pr[i].x = tdata[i].y;
  673.               t_pr[i].y = tdata[i].z;
  674.              }
  675.           }
  676. /*
  677.  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  678.  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  679.  */
  680.        if (!ProjectionFlag)  {
  681.            printf ("No Projection Made...   Exiting\n");
  682.            getchar();
  683.           }
  684.  
  685.  
  686.  
  687.       }
  688.  
  689.  
  690.  
  691. /*
  692.  *******************************************************************************
  693.  *
  694.  *  Name:  tri_area_x2
  695.  *
  696.  *  Purpose:  this routine calculates the area of a triangle using Cramer's
  697.  *            Rule.
  698.  *
  699.  *
  700.  *
  701.  *  Input Parameters
  702.  *
  703.  *     pt_a, pt_b, pt_c - vertices of triangle in x-y space
  704.  *
  705.  *
  706.  *  Output Parameters
  707.  *
  708.  *     none
  709.  *
  710.  *******************************************************************************
  711.  */
  712. float
  713.    tri_area_x2 (Point pt_a, Point pt_b, Point pt_c)
  714.       {
  715.        float result;
  716.        
  717.        result = (pt_a.x * pt_b.y) -
  718.                 (pt_a.x * pt_c.y) -
  719.                 (pt_b.x * pt_a.y) + 
  720.                 (pt_b.x * pt_c.y) +
  721.                 (pt_c.x * pt_a.y) - 
  722.                 (pt_c.x * pt_b.y);
  723.  
  724.        return (result);
  725.       }            
  726.  
  727.  
  728. /*
  729.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  730.   File:  rect_int.c
  731.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  732.  */
  733.  
  734.  
  735.  
  736. /*
  737.  *******************************************************************************
  738.  *
  739.  *  Name:  rect_int
  740.  *
  741.  *  Purpose:  this routine determines the intersection (if any) between a
  742.  *            ray and rectangle that is parallel to one of the coordinate
  743.  *            axis planes.  It does this by finding the equation of the
  744.  *            plane that contains the rectangle and determining if the
  745.  *            ray intersects this plane.  If it does, a simple bounds test
  746.  *            is used to determine if the intersection is within the rect-
  747.  *            angle.
  748.  *
  749.  *            This routine returns the value TRUE if there the ray inter-
  750.  *            sects the rectangle.  If a value of FALSE is returned, the
  751.  *            values of the output parameters are undefined.
  752.  *
  753.  *            NOTE:  the normal of the rectangle will only be returned if
  754.  *                   "norm_flg" is set to TRUE.
  755.  *
  756.  *
  757.  *
  758.  *  Input Parameters
  759.  *
  760.  *     ray - specified ray
  761.  *     r_ptr - specified rectangle
  762.  *     norm_flg - flag indicating whether the normal to plane is desired
  763.  *
  764.  *
  765.  *  Output Parameters
  766.  *
  767.  *     t - ray parameter value at point of intersection
  768.  *     Pint - point of intersection on rectangle
  769.  *     r_norm - normal to rectangle surface (if norm_flg is set)
  770.  *
  771.  *******************************************************************************
  772.  */
  773. Boolean
  774.    rect_int(Ray ray, Rect_Obj *r_ptr, Boolean norm_flg,
  775.             float *t, Vector *Pint, Vector *r_norm)
  776.       {
  777.        Sphere_Obj *s_ptr;
  778.        Boolean int_flg = FALSE;
  779.  
  780.        float A = (float)0.0, B = (float)0.0, C = (float)0.0, D = (float)0.0;
  781.        float numer, denom;
  782.        Vector s_int;
  783.  
  784.  
  785. /*
  786.  *     run quick rejection test on object's bounding sphere 
  787.  */
  788.        s_ptr = (Sphere_Obj *) &r_ptr->b_sph;
  789.        int_flg = sphere_int(ray, s_ptr, FALSE, &s_int, NULL, NULL, t);
  790.  
  791.        if ( (! int_flg) || (*t < 0.001) )
  792.            return(FALSE);
  793.  
  794.  
  795.        int_flg = FALSE;
  796.  
  797. /*
  798.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  799.  +  handle rectangle parallel to yz coordinate plane
  800.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  801.  */
  802.        if (r_ptr->normal == X_AXIS)  {
  803.  
  804. /*
  805.  *         determine value for intersection
  806.  */
  807.            D = -(r_ptr->corners[0].x);
  808.  
  809.            numer = ray.origin.x + D;
  810.            denom = ray.dir.x;
  811.            *t = (denom != 0.0)? -(numer / denom): (float)0.0;
  812.  
  813. /*
  814.  *         if intersection - determine if its in rectangle
  815.  */
  816.            if ((numer != 0.0) || (denom != 0.0) || (*t > 0.0) )  {
  817.                *Pint = VectorScaler_Product(&ray.dir, *t);
  818.                *Pint = Vector_Sum(&ray.origin, Pint);
  819.  
  820.                if (norm_flg)
  821.                    vset(r_norm,  (float) 1.0,  (float) 0.0,  (float) 0.0);
  822.  
  823.                if (Pint->y <= r_ptr->max_pt.y && Pint->y >= r_ptr->min_pt.y &&
  824.                    Pint->z <= r_ptr->max_pt.z && Pint->z >= r_ptr->min_pt.z)
  825.                    int_flg = TRUE;
  826.               }
  827.           }
  828.  
  829. /*
  830.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  831.  +  handle rectangle parallel to xz coordinate plane
  832.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  833.  */
  834.        else if (r_ptr->normal == Y_AXIS)  {
  835.  
  836. /*
  837.  *         determine value for intersection
  838.  */
  839.            D = -(r_ptr->corners[0].y);
  840.  
  841.            numer = ray.origin.y + D;
  842.            denom = ray.dir.y;
  843.            *t = (denom != 0.0)? -(numer / denom): (float)0.0;
  844.  
  845. /*
  846.  *         if intersection - determine if its in rectangle
  847.  */
  848.            if ((numer != 0.0) || (denom != 0.0) || (*t > 0.0) )  {
  849.                *Pint = VectorScaler_Product(&ray.dir, *t);
  850.                *Pint = Vector_Sum(&ray.origin, Pint);
  851.                if (norm_flg)
  852.                    vset(r_norm,  (float) 0.0,  (float) 1.0,  (float) 0.0);
  853.  
  854.                if (Pint->x <= r_ptr->max_pt.x && Pint->x >= r_ptr->min_pt.x &&
  855.                    Pint->z <= r_ptr->max_pt.z && Pint->z >= r_ptr->min_pt.z)
  856.                    int_flg = TRUE;
  857.               }
  858.  
  859.           }
  860.  
  861. /*
  862.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  863.  +  handle rectangle parallel to xy coordinate plane
  864.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  865.  */
  866.        else if (r_ptr->normal == Z_AXIS)  {
  867.  
  868. /*
  869.  *         determine value for intersection
  870.  */
  871.            D = -(r_ptr->corners[0].z);
  872.  
  873.            numer = ray.origin.z + D;
  874.            denom = ray.dir.z;
  875.            *t = (denom != 0.0)? -(numer / denom): (float)0.0;
  876.  
  877. /*
  878.  *         if intersection - determine if its in rectangle
  879.  */
  880.            if ((numer != 0.0) || (denom != 0.0) || (*t > 0.0) )  {
  881.                *Pint = VectorScaler_Product(&ray.dir, *t);
  882.                *Pint = Vector_Sum(&ray.origin, Pint);
  883.                if (norm_flg)
  884.                    vset(r_norm,  (float) 0.0,  (float) 0.0,  (float) 1.0);
  885.  
  886.                if (Pint->x <= r_ptr->max_pt.x && Pint->x >= r_ptr->min_pt.x &&
  887.                    Pint->y <= r_ptr->max_pt.y && Pint->y >= r_ptr->min_pt.y)
  888.                    int_flg = TRUE;
  889.               }
  890.           }
  891. /*
  892.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  893.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  894.  */
  895.  
  896.        return (int_flg);
  897.       }
  898.  
  899.  
  900.  
  901.  
  902.