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

  1.  
  2.  
  3. #include <stdio.h>
  4. #include <math.h>
  5.  
  6. #include "RTTypes.h"
  7. #include "RTVecOps.h"
  8.  
  9. #include "RTScreen.h"
  10. #include "RTObjOps.h"
  11. #include "RTIMOps.h"
  12. #include "RayTrace.h"
  13.  
  14. #include "RTIntOps.h"
  15.  
  16.  
  17.  
  18.  
  19.  
  20. /*
  21.  *******************************************************************************
  22.  *
  23.  *  Name:  Illumination_model
  24.  *
  25.  *  Purpose:  this routine implements the warn lighting model.  It sums
  26.  *            intensities through multiple light sources and ammends the
  27.  *            the each intensity if it is specified to be a directed light
  28.  *            source.  In additions, shadows are handled through the use
  29.  *            of a "light (shadow) feeler".  It is extended to the light
  30.  *            source and determines a filter value "Si" that is applied
  31.  *            to each light source based on the objects that lie in the
  32.  *            path between the point being illuminated and the illumina-
  33.  *            tion source.
  34.  *
  35.  *
  36.  *
  37.  *  Input Parameters
  38.  *
  39.  *     pt - point to be illuminated
  40.  *     N_vec - normal vector at point
  41.  *     View_vec - view vector at point
  42.  *
  43.  *     Od - diffuse color at point
  44.  *     Os - specular color at point
  45.  *
  46.  *     Ka - ambient reflection constant at point
  47.  *     Kd - diffuse reflection constant at point
  48.  *     Ks - specular reflection constant at point
  49.  *
  50.  *     n - phong constant
  51.  *
  52.  *
  53.  *  Output Parameters
  54.  *
  55.  *     U - diffuse component of illumination
  56.  *     V - specular component of illumination
  57.  *
  58.  *******************************************************************************
  59.  */
  60.  
  61. void
  62.    Illumination_Model(Vector pt, Vector *N_vec, Vector *View_vec,
  63.                       Vector *Od, Vector *Os,
  64.                       float Ka, float Kd, float Ks,
  65.                       Vector *U, Vector *V)
  66.       {
  67.        Vector L_vec, negL_vec, Lp;
  68.        Vector R_vec;
  69.        Vector U_vec, V_vec;
  70.  
  71.        float N_dot_L;
  72.        float cos_theta, cos_alpha, cos_gama;
  73.        float Si;
  74.        float t, s;
  75.  
  76.        int i;
  77.  
  78.  
  79. /*
  80.  *     initialize light component variables
  81.  */
  82.        vset (U, (float) 0.0,  (float) 0.0,  (float) 0.0);
  83.        vset (V, (float) 0.0,  (float) 0.0,  (float) 0.0);
  84.  
  85.        vset (&U_vec, (float) 0.0,  (float) 0.0,  (float) 0.0);
  86.        vset (&V_vec, (float) 0.0,  (float) 0.0,  (float) 0.0);
  87.  
  88. /*
  89.  *******************************************************************************
  90.  *
  91.  *  loop through all light specifications & calculate intensity if they are on
  92.  *
  93.  *******************************************************************************
  94.  */
  95.   
  96.        for (i=0; i<LIGHTS_MAX; i++)  {
  97.  
  98.  
  99.            if (shared->lights[i].on)  {
  100. /*
  101.  *             initialize lighting model
  102.  */
  103.                L_vec = Vector_Difference(&shared->lights[i].L_pt, &pt);
  104.                L_vec = VectorScaler_Division(&L_vec, vector_len(&L_vec) );
  105.  
  106.                N_dot_L = Dot_Product(N_vec, &L_vec);
  107.                cos_theta = N_dot_L;
  108.  
  109.                t = (float) 0.0;
  110.                s = (float) 0.0;
  111.  
  112. /*
  113.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  114.  *  apply lighting model if light source is in front of obj
  115.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  116.  */
  117.                if (cos_theta > 0.0)  {
  118.  
  119. /*
  120.  *                 apply basic lighting model
  121.  */
  122.                    R_vec = VectorScaler_Product(N_vec, ((float)2.0) * N_dot_L);
  123.                    R_vec = Vector_Difference(&R_vec, &L_vec);
  124.                    R_vec = VectorScaler_Division(&R_vec, vector_len(&R_vec) );
  125.  
  126.                    cos_alpha = Dot_Product(&R_vec, View_vec);
  127.  
  128.                    if (cos_alpha > 0)
  129.                        cos_alpha = cos_alpha;
  130.                    else
  131.                        cos_alpha = (float) 0.0;
  132.  
  133.  
  134.                    t = Ka + (Kd * cos_theta);
  135.                    s = Ks * pow(cos_alpha, shared->PhongConst);
  136.  
  137. /*
  138.  *                 if light source directed -- modify result
  139.  */
  140.                    if (shared->lights[i].directed)  {
  141.                        vset (&negL_vec, -L_vec.x, -L_vec.y, -L_vec.z);
  142.  
  143.                        Lp = Vector_Difference(&shared->lights[i].L_a, 
  144.                                                        &shared->lights[i].L_pt);
  145.                        Lp = VectorScaler_Division(&Lp, vector_len(&Lp) );
  146.  
  147.                        cos_gama = Dot_Product(&negL_vec, &Lp);
  148.  
  149.                        if (cos_gama > shared->lights[i].cos_delta)  {
  150.                            t = t * pow(cos_gama, shared->lights[i].ro);
  151.                            s = s * pow(cos_gama, shared->lights[i].ro);
  152.                           }
  153.                        else  {
  154.                            t = (float) 0.0;
  155.                            s = (float) 0.0;
  156.                           }
  157.  
  158.                       }  /* end - if (shared->lights[i].directed) */
  159.  
  160.                   }  /* end - if (cos_theta > 0.0) */
  161. /*
  162.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  163.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  164.  */
  165.  
  166. /*
  167.  *             extend light feeler if necessary
  168.  */
  169.                if (t > 0.0 || s > 0.0)
  170.                    Si = Light_Feeler(pt, shared->lights[i].L_pt);
  171.  
  172. /*
  173.  *             calculate diffuse illumination
  174.  */
  175.                if (t > 0.0)  {
  176.                    U_vec = vproduct(Od, &shared->lights[i].I);
  177.                    U_vec = VectorScaler_Product(&U_vec, t);
  178.                    U_vec = VectorScaler_Product(&U_vec, Si);
  179.                    *U =     Vector_Sum(U, &U_vec);
  180.                   }
  181.  
  182. /*
  183.  *             calculate specular illumination
  184.  */
  185.                if (s > 0.0)  {
  186.                    V_vec = vproduct(Os, &shared->lights[i].I);
  187.                    V_vec = VectorScaler_Product(&V_vec, s);
  188.                    V_vec = VectorScaler_Product(&V_vec, Si);
  189.                    *V =     Vector_Sum(V, &V_vec);
  190.                   }
  191.  
  192.               }  /* end -- if (shared->lights[i].on) */
  193.  
  194.           }  /* end -- for i */
  195.  
  196.       }
  197.  
  198.  
  199.  
  200. /*
  201.  *******************************************************************************
  202.  *
  203.  *  Name:  Light_Feeler
  204.  *
  205.  *  Purpose:  this routine determines if a ray from a given point to a light
  206.  *            source intersects any objects along its length.  If intersec-
  207.  *            tions are found, the transparency constant for each object 
  208.  *            intersected are multiplied into a running product.  This value
  209.  *            is returned as the filter value for that light source.
  210.  *
  211.  *            NOTE:  the ray is parameterized so that the ray parameter value
  212.  *                   't' varies from 0.0 (point) to 1.0 (light source).
  213.  *
  214.  *            NOTE:  the function "poly_mesh_int" is called with the parameter
  215.  *                   "LF".  This parameter is used to tell the function to
  216.  *                   return after the first intersection is found rather than
  217.  *                   the closest intersection.  (an optimization)
  218.  *
  219.  *
  220.  *
  221.  *  Input Parameters
  222.  *
  223.  *     pt - specified point to be illuminated
  224.  *     light_pt - specified origin of light source
  225.  *
  226.  *
  227.  *  Output Parameters
  228.  *
  229.  *     none
  230.  *
  231.  *******************************************************************************
  232.  */
  233. float
  234.    Light_Feeler( Vector pt, Vector light_pt)
  235.       {
  236.        Vector int_pt;
  237.  
  238.        Sphere_Obj    *sphere_ptr;
  239.        Poly_Mesh_Obj *poly_ptr;
  240.        Rect_Obj      *rec_ptr;
  241.  
  242.        Ray ray;
  243.        Boolean norm_flg = FALSE;
  244.        Boolean int_flg = FALSE;
  245.  
  246.        float S = (float) 1.0;
  247.        float t;
  248.  
  249.        int i;
  250.  
  251.  
  252. /*
  253.  *     initialize ray from point to light source
  254.  */
  255.        ray.origin = pt;
  256.        ray.dir = Vector_Difference(&light_pt, &pt);
  257.        ray.dir = VectorScaler_Division(&ray.dir, vector_len(&ray.dir));
  258.  
  259. /*
  260.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  261.  +  determine if any objects intersect ray
  262.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  263.  */
  264.        for (i=0; i<shared->obj_num && S > 0.0; i++)  {
  265.  
  266.            int_flg = 0;
  267.  
  268.            switch (shared->obj_list[i].label)  {
  269. /*
  270.  *             handle sphere objects
  271.  */
  272.                case SPHERE:
  273.                   sphere_ptr = (Sphere_Obj *) shared->obj_list[i].ptr;
  274.                   int_flg = sphere_int(ray, sphere_ptr, norm_flg, &int_pt,
  275.                                                               NULL, NULL, &t);
  276.                   break;
  277. /*
  278.  *             handle polygon mesh objects
  279.  */
  280.                case POLY_MESH:
  281.                   poly_ptr = (Poly_Mesh_Obj *) shared->obj_list[i].ptr;
  282.                   int_flg = poly_mesh_int(ray, poly_ptr, norm_flg, LF, &t,
  283.                                                          &int_pt, NULL, NULL);
  284.                   break;
  285.  
  286. /*
  287.  *             handle rectangle objects
  288.  */
  289.                case RECTANGLE:
  290.                   rec_ptr = (Rect_Obj *) shared->obj_list[i].ptr;
  291.                   int_flg = rect_int(ray, rec_ptr, norm_flg, &t, &int_pt, NULL);
  292.                   break;
  293.               }
  294.  
  295. /*
  296.  *         multiply in Kt for intersected object if:
  297.  *            - there was an intersection (int_flag)
  298.  *            - the intersection is not at the ray origin (t > 0.01)
  299.  *            - the intersection is not beyond light source (t < || P -Lf)
  300.  */
  301.            Vector Lf_P_dist = Vector_Difference(&light_pt, &pt);
  302.            t = t / vector_len(&Lf_P_dist);;
  303.  
  304.            
  305.            if ( (int_flg) && (t > 0.001) && (t < 1.0) )  {
  306.                S = S * shared->obj_props[i].Kt;
  307.               }
  308.  
  309.           }
  310. /*
  311.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  312.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  313.  */
  314.  
  315.        return(S);
  316.       }
  317.  
  318.  
  319.  
  320.