home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / developm / source / povsrc.sit / SOURCE / LIGHTING.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-07-03  |  29.7 KB  |  927 lines

  1. /****************************************************************************
  2. *                   lighting.c
  3. *
  4. *  This module calculates lighting properties like ambient, diffuse, specular,
  5. *  reflection, refraction, etc.
  6. *
  7. *  from Persistence of Vision Raytracer 
  8. *  Copyright 1992 Persistence of Vision Team
  9. *---------------------------------------------------------------------------
  10. *  Copying, distribution and legal info is in the file povlegal.doc which
  11. *  should be distributed with this file. If povlegal.doc is not available
  12. *  or for more info please contact:
  13. *
  14. *       Drew Wells [POV-Team Leader] 
  15. *       CIS: 73767,1244  Internet: 73767.1244@compuserve.com
  16. *       Phone: (213) 254-4041
  17. * This program is based on the popular DKB raytracer version 2.12.
  18. * DKBTrace was originally written by David K. Buck.
  19. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  20. *
  21. *****************************************************************************/
  22. #include "frame.h"
  23. #include "vector.h"
  24. #include "povproto.h"
  25.  
  26. extern int Trace_Level;
  27. extern FRAME Frame;
  28. extern unsigned int Options;
  29. extern int Quality;
  30. extern int Shadow_Test_Flag;
  31. extern long Shadow_Ray_Tests, Shadow_Rays_Succeeded;
  32. extern long Reflected_Rays_Traced, Refracted_Rays_Traced;
  33. extern long Transmitted_Rays_Traced;
  34.  
  35.  
  36.  
  37. #define COORDINATE_LIMIT 1.0e17
  38.  
  39. /* "Small_Tolerance" is just too tight for higher order polynomial equations.
  40.    this value should probably be a variable of some sort, but for now just
  41.    use a reasonably small value.  If people render real small objects real 
  42.    close to each other then there may be some shading problems.  Otherwise
  43.    having SHADOW_TOLERANCE as large as this won't affect images. */
  44. #define SHADOW_TOLERANCE 0.05
  45.  
  46. static void do_light PARAMS((LIGHT_SHAPE *Light_Source, DBL *Light_Source_Depth,
  47. RAY *Light_Source_Ray, VECTOR *Intersection_Point, COLOUR *Light_Colour));
  48. static int do_blocking PARAMS((INTERSECTION *Local_Intersection, 
  49. COLOUR *Light_Colour, PRIOQ *Local_Queue));
  50. static void do_phong PARAMS((TEXTURE *Texture, RAY *Light_Source_Ray,
  51. VECTOR Eye, VECTOR *Surface_Normal, COLOUR *Colour, COLOUR *Light_Colour,
  52. COLOUR *Surface_Colour));
  53. static void do_specular PARAMS((TEXTURE *Texture, RAY *Light_Source_Ray,
  54. VECTOR REye, VECTOR *Surface_Normal, COLOUR *Colour, COLOUR *Light_Colour,
  55. COLOUR *Surface_Colour));
  56. static void do_diffuse PARAMS((TEXTURE *Texture, RAY *Light_Source_Ray,
  57. VECTOR *Surface_Normal, COLOUR *Colour, COLOUR *Light_Colour,
  58. COLOUR *Surface_Colour, DBL Attenuation));
  59.  
  60.  
  61.  
  62.  
  63. void Colour_At (Colour, Texture, Intersection_Point)
  64. COLOUR *Colour;
  65. TEXTURE *Texture;
  66. VECTOR *Intersection_Point;
  67. {
  68.    register DBL x, y, z;
  69.    VECTOR Transformed_Point;
  70.  
  71.  
  72.    if ((Intersection_Point->x > COORDINATE_LIMIT) ||
  73.       (Intersection_Point->y > COORDINATE_LIMIT) ||
  74.       (Intersection_Point->z > COORDINATE_LIMIT) ||
  75.       (Intersection_Point->x < -COORDINATE_LIMIT) ||
  76.       (Intersection_Point->y < -COORDINATE_LIMIT) ||
  77.       (Intersection_Point->z < -COORDINATE_LIMIT))
  78.    {
  79.       Make_Vector (&Transformed_Point, 0.0, 0.0, 0.0);
  80.    }
  81.    else
  82.       if (Texture->Texture_Transformation) {
  83.          MInverseTransformVector (&Transformed_Point,
  84.             Intersection_Point,
  85.             Texture->Texture_Transformation);
  86.       }
  87.       else {
  88.          Transformed_Point = *Intersection_Point;
  89.       }
  90.  
  91.       x = Transformed_Point.x;
  92.    y = Transformed_Point.y;
  93.    z = Transformed_Point.z;
  94.  
  95.    switch (Texture->Texture_Number) {
  96.    case NO_TEXTURE:
  97.       /* No colouring texture has been specified - make it black. */
  98.       Make_Colour (Colour, 0.0, 0.0, 0.0);
  99.       Colour -> Alpha  = 0.0;
  100.       break;
  101.  
  102.    case COLOUR_TEXTURE:
  103.       Colour -> Red += Texture->Colour1->Red;
  104.       Colour -> Green += Texture->Colour1->Green;
  105.       Colour -> Blue += Texture->Colour1->Blue;
  106.       Colour -> Alpha += Texture->Colour1->Alpha;
  107.       break;
  108.  
  109.    case BOZO_TEXTURE: 
  110.       bozo (x, y, z, Texture, Colour);
  111.       break;
  112.  
  113.    case MARBLE_TEXTURE:
  114.       marble (x, y, z, Texture, Colour);
  115.       break;
  116.  
  117.    case WOOD_TEXTURE:
  118.       wood (x, y, z, Texture, Colour);
  119.       break;
  120.  
  121.    case BRICK_TEXTURE:
  122.       brick (x, y, z, Texture, Colour);
  123.       break;
  124.  
  125.    case CHECKER_TEXTURE:
  126.       checker (x, y, z, Texture, Colour);
  127.       break;
  128.  
  129.    case CHECKER_TEXTURE_TEXTURE:
  130.       checker_texture (x, y, z, Texture, Colour);
  131.       break;
  132.  
  133.    case SPOTTED_TEXTURE:
  134.       spotted (x, y, z, Texture, Colour);
  135.       break;
  136.  
  137.    case AGATE_TEXTURE:
  138.       agate (x, y, z, Texture, Colour);
  139.       break;
  140.  
  141.    case GRANITE_TEXTURE:
  142.       granite (x, y, z, Texture, Colour);
  143.       break;
  144.  
  145.    case GRADIENT_TEXTURE:
  146.       gradient (x, y, z, Texture, Colour);
  147.       break;
  148.  
  149.    case IMAGEMAP_TEXTURE:
  150.       image_map (x, y, z, Texture, Colour);
  151.       break;
  152.  
  153.    case ONION_TEXTURE:
  154.       onion (x, y, z, Texture, Colour);
  155.       break;
  156.  
  157.    case LEOPARD_TEXTURE:
  158.       leopard (x, y, z, Texture, Colour);
  159.       break;
  160.  
  161.    case PAINTED1_TEXTURE:
  162.       painted1 (x, y, z, Texture, Colour);
  163.       break;
  164.  
  165.    case PAINTED2_TEXTURE:
  166.       painted2 (x, y, z, Texture, Colour);
  167.       break;
  168.  
  169.    case PAINTED3_TEXTURE:
  170.       painted3 (x, y, z, Texture, Colour);
  171.       break;
  172.    }
  173. }
  174.  
  175.  
  176. void Perturb_Normal(New_Normal, Texture, Intersection_Point, Surface_Normal)
  177. VECTOR *New_Normal, *Intersection_Point, *Surface_Normal;
  178. TEXTURE *Texture;
  179. {
  180.    VECTOR Transformed_Point;
  181.    register DBL x, y, z;
  182.  
  183.    if (Texture->Bump_Number == NO_BUMPS) {
  184.       *New_Normal = *Surface_Normal;
  185.       return;
  186.    }
  187.  
  188.    if (Texture->Texture_Transformation)
  189.       MInverseTransformVector (&Transformed_Point,
  190.          Intersection_Point,
  191.          Texture->Texture_Transformation);
  192.    else
  193.       Transformed_Point = *Intersection_Point;
  194.  
  195.    x = Transformed_Point.x;
  196.    y = Transformed_Point.y;
  197.    z = Transformed_Point.z;
  198.  
  199.    switch (Texture->Bump_Number) {
  200.  
  201.    case WAVES: 
  202.       waves (x, y, z, Texture, New_Normal);
  203.       break;
  204.  
  205.    case RIPPLES: 
  206.       ripples (x, y, z, Texture, New_Normal);
  207.       break;
  208.  
  209.    case WRINKLES: 
  210.       wrinkles (x, y, z, Texture, New_Normal);
  211.       break;
  212.  
  213.    case BUMPS: 
  214.       bumps (x, y, z, Texture, New_Normal);
  215.       break;
  216.  
  217.    case DENTS: 
  218.       dents (x, y, z, Texture, New_Normal);
  219.       break; 
  220.  
  221.    case BUMPY1: 
  222.       bumpy1 (x, y, z, Texture, New_Normal);
  223.       break;
  224.  
  225.    case BUMPY2: 
  226.       bumpy2 (x, y, z, Texture, New_Normal);
  227.       break;
  228.  
  229.    case BUMPY3: 
  230.       bumpy3 (x, y, z, Texture, New_Normal);
  231.       break;
  232.  
  233.    case BUMPMAP: 
  234.       bump_map (x, y, z, Texture, New_Normal);
  235.       break;
  236.  
  237.    }
  238.    return;
  239. }
  240.  
  241. void Ambient (Texture, Surface_Colour, Colour, Attenuation)
  242. TEXTURE *Texture;
  243. COLOUR *Surface_Colour;
  244. COLOUR *Colour;
  245. DBL    Attenuation;
  246. {
  247.    if (Texture -> Object_Ambient == 0.0)
  248.       return;
  249.  
  250.    Colour->Red += Surface_Colour->Red * Texture->Object_Ambient * Attenuation;
  251.    Colour->Green += Surface_Colour->Green * Texture->Object_Ambient * Attenuation;
  252.    Colour->Blue += Surface_Colour->Blue * Texture->Object_Ambient * Attenuation;
  253.    return;
  254. }
  255.  
  256.  
  257. void Diffuse (Texture, Intersection_Point, Eye, Surface_Normal, Surface_Colour, Colour, Attenuation)
  258. TEXTURE *Texture;
  259. VECTOR *Intersection_Point, *Surface_Normal;
  260. COLOUR *Surface_Colour;
  261. COLOUR *Colour;
  262. RAY    *Eye;
  263. DBL    Attenuation;
  264. {
  265.    DBL Light_Source_Depth;
  266.    RAY Light_Source_Ray;
  267.    LIGHT_SHAPE *Light_Source;
  268.    OBJECT *Blocking_Object;
  269.    int Intersection_Found;
  270.    INTERSECTION *Local_Intersection;
  271.    VECTOR REye;
  272.    COLOUR Light_Colour;
  273.    PRIOQ *Local_Queue;
  274.  
  275.    if ((Texture -> Object_Diffuse == 0.0) &&
  276.       (Texture -> Object_Specular == 0.0) &&
  277.       (Texture -> Object_Phong == 0.0))
  278.       return;
  279.  
  280.    if (Texture -> Object_Specular != 0.0)
  281.    {
  282.       REye.x = -Eye->Direction.x;
  283.       REye.y = -Eye->Direction.y;
  284.       REye.z = -Eye->Direction.z;
  285.    }
  286.  
  287.    Local_Queue = pq_new (128);
  288.  
  289.    for (Light_Source = Frame.Light_Sources ; 
  290.           Light_Source != NULL;
  291.           Light_Source = Light_Source -> Next_Light_Source)
  292.    {
  293.       Intersection_Found = FALSE;
  294.  
  295.       do_light(Light_Source, &Light_Source_Depth, &Light_Source_Ray, Intersection_Point, &Light_Colour);
  296.  
  297.       /* What objects does this ray intersect? */
  298.       if (Quality > 3) {
  299.          Shadow_Test_Flag = TRUE;
  300.          for (Blocking_Object = Frame.Objects ; 
  301.                       Blocking_Object != NULL ;
  302.                       Blocking_Object = Blocking_Object -> Next_Object) {
  303.  
  304.             Shadow_Ray_Tests++;
  305.             for (All_Intersections (Blocking_Object, &Light_Source_Ray, Local_Queue) ;
  306.                         (Local_Intersection = pq_get_highest(Local_Queue)) != NULL ;
  307.                         pq_delete_highest(Local_Queue)) {
  308.  
  309.                if ((Local_Intersection -> Depth < Light_Source_Depth-Small_Tolerance)
  310.                   && (Local_Intersection -> Depth > SHADOW_TOLERANCE))
  311.  
  312.                   /* Does the object not cast a shadow? */
  313.                   if (!Local_Intersection -> Object -> No_Shadow_Flag)
  314.                      if (do_blocking(Local_Intersection, &Light_Colour, Local_Queue)) {
  315.                         Intersection_Found = TRUE;
  316.                         break;
  317.                      }
  318.             }
  319.             if (Intersection_Found)
  320.                break;
  321.          }
  322.          Shadow_Test_Flag = FALSE;
  323.       }
  324.  
  325.       /* If light source was not blocked by any intervening object, then
  326.        calculate it's contribution to the object's overall illumination */
  327.  
  328.       if (!Intersection_Found) {
  329.          if (Texture->Object_Phong >0.0) /* Phong Hilite */
  330.             do_phong(Texture,&Light_Source_Ray,Eye->Direction,Surface_Normal,Colour,&Light_Colour, Surface_Colour);
  331.  
  332.          if (Texture->Object_Specular >0.0) /* Specular Hilite */
  333.             do_specular(Texture,&Light_Source_Ray,REye,Surface_Normal,Colour,&Light_Colour, Surface_Colour);
  334.  
  335.          if (Texture->Object_Diffuse > 0.0) /* Normal Diffuse Illum. */
  336.             do_diffuse(Texture,&Light_Source_Ray,Surface_Normal,Colour,&Light_Colour,Surface_Colour, Attenuation);
  337.       }
  338.    }
  339.    pq_free (Local_Queue);
  340.    return;
  341. }
  342.  
  343.  
  344. static void do_light(Light_Source, Light_Source_Depth, Light_Source_Ray, Intersection_Point, Light_Colour)
  345. LIGHT_SHAPE *Light_Source;
  346. DBL *Light_Source_Depth;
  347. RAY *Light_Source_Ray;
  348. VECTOR *Intersection_Point;
  349. COLOUR *Light_Colour;
  350. {
  351.    DBL Attenuation = 1.0;
  352.  
  353.    /* Get the light source colour. */
  354.    if (Light_Source->Shape_Colour == NULL) {
  355.       Make_Colour (Light_Colour, 1.0, 1.0, 1.0);
  356.    }
  357.    else
  358.       *Light_Colour = *Light_Source->Shape_Colour;
  359.  
  360.    Light_Source_Ray->Initial = *Intersection_Point;
  361.    Light_Source_Ray->Quadric_Constants_Cached = FALSE;
  362.  
  363.    VSub (Light_Source_Ray->Direction,
  364.       Light_Source->Center,
  365.       *Intersection_Point);
  366.  
  367.    VLength (*Light_Source_Depth, Light_Source_Ray->Direction);
  368.  
  369.    VScale (Light_Source_Ray->Direction, Light_Source_Ray->Direction,
  370.       1.0/(*Light_Source_Depth));
  371.  
  372.    Attenuation = Attenuate_Light(Light_Source, Light_Source_Ray);
  373.  
  374.    /* Now scale the color by the attenuation */
  375.    Light_Colour->Red   *= Attenuation;
  376.    Light_Colour->Green *= Attenuation;
  377.    Light_Colour->Blue  *= Attenuation;
  378.  
  379.  
  380.    return;
  381. }
  382.  
  383. static int do_blocking(Local_Intersection, Light_Colour, Local_Queue)
  384. INTERSECTION *Local_Intersection;
  385. COLOUR *Light_Colour;
  386. PRIOQ *Local_Queue;
  387. {
  388.    Shadow_Rays_Succeeded++;
  389.  
  390.    Determine_Surface_Colour (Local_Intersection, Light_Colour, NULL, TRUE);
  391.  
  392.    if ((Light_Colour->Red < 0.01) && (Light_Colour->Green < 0.01)
  393.       && (Light_Colour->Blue < 0.01)) {
  394.  
  395.       while (pq_get_highest(Local_Queue))
  396.          pq_delete_highest(Local_Queue);
  397.       return(TRUE);
  398.    }
  399.    return(FALSE);
  400. }
  401.  
  402. static void do_phong(Texture, Light_Source_Ray, Eye, Surface_Normal, Colour, Light_Colour, Surface_Colour)
  403. TEXTURE *Texture;
  404. RAY *Light_Source_Ray;
  405. VECTOR *Surface_Normal, Eye;
  406. COLOUR *Colour, *Light_Colour, *Surface_Colour;
  407. {
  408.    DBL Cos_Angle_Of_Incidence, Normal_Length, Intensity;
  409.    VECTOR Local_Normal, Normal_Projection, Reflect_Direction;
  410.  
  411.    VDot(Cos_Angle_Of_Incidence, Eye, *Surface_Normal);
  412.  
  413.    if (Cos_Angle_Of_Incidence < 0.0)
  414.    {
  415.       Local_Normal = *Surface_Normal;
  416.       Cos_Angle_Of_Incidence = -Cos_Angle_Of_Incidence;
  417.    }
  418.    else
  419.    {
  420.       VScale (Local_Normal, *Surface_Normal, -1.0);
  421.    }
  422.  
  423.    VScale (Normal_Projection, Local_Normal, Cos_Angle_Of_Incidence);
  424.    VScale (Normal_Projection, Normal_Projection, 2.0);
  425.    VAdd (Reflect_Direction, Eye, Normal_Projection);
  426.  
  427.    VDot (Cos_Angle_Of_Incidence, Reflect_Direction, Light_Source_Ray->Direction);
  428.    VLength (Normal_Length, Light_Source_Ray->Direction);
  429.  
  430.    if (Normal_Length == 0.0)
  431.       Cos_Angle_Of_Incidence = 0.0;
  432.    else Cos_Angle_Of_Incidence /= Normal_Length;
  433.  
  434.       if (Cos_Angle_Of_Incidence < 0.0)
  435.          Cos_Angle_Of_Incidence = 0;
  436.  
  437.    if (Texture -> Object_PhongSize != 1.0)
  438.       Intensity = pow(Cos_Angle_Of_Incidence, Texture->Object_PhongSize);
  439.    else
  440.       Intensity = Cos_Angle_Of_Incidence;
  441.  
  442.    Intensity *= Texture -> Object_Phong;
  443.  
  444.    if (Texture->Metallic_Flag) {
  445.       Colour->Red+=Intensity*(Surface_Colour->Red);
  446.       Colour->Green+=Intensity*(Surface_Colour->Green);
  447.       Colour->Blue+=Intensity*(Surface_Colour->Blue);
  448.    }
  449.    else {
  450.       Colour->Red+=Intensity*(Light_Colour->Red);
  451.       Colour->Green+=Intensity*(Light_Colour->Green);
  452.       Colour->Blue+=Intensity*(Light_Colour->Blue);
  453.    }
  454.    return;
  455. }
  456.  
  457.    static void do_specular(Texture, Light_Source_Ray, REye, Surface_Normal, Colour, Light_Colour, Surface_Colour)
  458.       TEXTURE *Texture;
  459. RAY *Light_Source_Ray;
  460. VECTOR *Surface_Normal, REye;
  461. COLOUR *Colour, *Light_Colour, *Surface_Colour;
  462. {
  463.    DBL Cos_Angle_Of_Incidence, Normal_Length, Intensity, Halfway_Length, Roughness;
  464.    VECTOR Halfway;
  465.  
  466.    VHalf (Halfway, REye, Light_Source_Ray->Direction);
  467.    VLength (Normal_Length, *Surface_Normal);
  468.    VLength (Halfway_Length, Halfway);
  469.    VDot (Cos_Angle_Of_Incidence, Halfway, *Surface_Normal);
  470.  
  471.    if (Normal_Length == 0.0 || Halfway_Length == 0.0)
  472.       Cos_Angle_Of_Incidence = 0.0;
  473.    else Cos_Angle_Of_Incidence /= (Normal_Length * Halfway_Length);
  474.  
  475.       if (Cos_Angle_Of_Incidence < 0.0)
  476.          Cos_Angle_Of_Incidence = 0.0;
  477.  
  478.    Roughness = 1.0 / Texture->Object_Roughness;
  479.  
  480.    if (Roughness != 1.0)
  481.       Intensity = pow(Cos_Angle_Of_Incidence, Roughness);
  482.    else
  483.       Intensity = Cos_Angle_Of_Incidence;
  484.    Intensity *= Texture->Object_Specular;
  485.    if (Texture->Metallic_Flag) {
  486.       Colour->Red+=Intensity*(Surface_Colour->Red);
  487.       Colour->Green+=Intensity*(Surface_Colour->Green);
  488.       Colour->Blue+=Intensity*(Surface_Colour->Blue);
  489.    }
  490.    else {
  491.       Colour->Red+=Intensity*(Light_Colour->Red);
  492.       Colour->Green+=Intensity*(Light_Colour->Green);
  493.       Colour->Blue+=Intensity*(Light_Colour->Blue);
  494.    }
  495.    return;
  496. }
  497.  
  498.    static void do_diffuse(Texture, Light_Source_Ray, Surface_Normal, Colour, Light_Colour, Surface_Colour, Attenuation)
  499.       TEXTURE *Texture;
  500. RAY *Light_Source_Ray;
  501. VECTOR *Surface_Normal;
  502. COLOUR *Colour, *Light_Colour, *Surface_Colour;
  503. DBL Attenuation;
  504. {
  505.    DBL Cos_Angle_Of_Incidence, Intensity, RandomNumber;
  506.  
  507.    VDot (Cos_Angle_Of_Incidence, *Surface_Normal, Light_Source_Ray->Direction);
  508.    if (Cos_Angle_Of_Incidence < 0.0)
  509.       Cos_Angle_Of_Incidence = -Cos_Angle_Of_Incidence;
  510.  
  511.    if (Texture -> Object_Brilliance != 1.0)
  512.       Intensity = pow(Cos_Angle_Of_Incidence, Texture->Object_Brilliance);
  513.    else
  514.       Intensity = Cos_Angle_Of_Incidence;
  515.  
  516.    Intensity *= Texture -> Object_Diffuse * Attenuation;
  517.  
  518.    RandomNumber = (rand()&0x7FFF)/(DBL) 0x7FFF;
  519.  
  520.    Intensity -= RandomNumber * Texture->Texture_Randomness;
  521.  
  522.    Colour->Red += Intensity * (Surface_Colour->Red) * (Light_Colour->Red);
  523.    Colour->Green += Intensity * (Surface_Colour->Green) * (Light_Colour->Green);
  524.    Colour->Blue += Intensity * (Surface_Colour->Blue) * (Light_Colour->Blue);
  525.    return;
  526. }
  527.  
  528. void Reflect (Texture, Intersection_Point, Ray, Surface_Normal, Colour)
  529. TEXTURE *Texture;
  530. VECTOR *Intersection_Point;
  531. RAY *Ray;
  532. VECTOR *Surface_Normal;
  533. COLOUR *Colour;
  534. {
  535.    RAY New_Ray;
  536.    COLOUR Temp_Colour;
  537.    VECTOR Local_Normal;
  538.    VECTOR Normal_Projection;
  539.    VECTOR Surface_Offset;
  540.    register DBL Normal_Component;
  541.  
  542.    if (Texture -> Object_Reflection != 0.0)
  543.       {
  544.       Reflected_Rays_Traced++;
  545.       VDot (Normal_Component, Ray -> Direction, *Surface_Normal);
  546.       if (Normal_Component < 0.0) {
  547.          Local_Normal = *Surface_Normal;
  548.          Normal_Component *= -1.0;
  549.       }
  550.       else
  551.          VScale (Local_Normal, *Surface_Normal, -1.0);
  552.  
  553.       VScale (Normal_Projection, Local_Normal, Normal_Component);
  554.       VScale (Normal_Projection, Normal_Projection, 2.0);
  555.       VAdd (New_Ray.Direction, Ray -> Direction, Normal_Projection);
  556.       New_Ray.Initial = *Intersection_Point;
  557.  
  558.       /* ARE 08/25/91 */
  559.  
  560.       VScale(Surface_Offset, New_Ray.Direction, 2.0 * Small_Tolerance); 
  561.       VAdd(New_Ray.Initial, New_Ray.Initial, Surface_Offset);           
  562.  
  563.       Copy_Ray_Containers (&New_Ray, Ray);
  564.       Trace_Level++;
  565.       Make_Colour (&Temp_Colour, 0.0, 0.0, 0.0);
  566.       New_Ray.Quadric_Constants_Cached = FALSE;
  567.       Trace (&New_Ray, &Temp_Colour);
  568.       Trace_Level--;
  569.  
  570.       Colour -> Red += Temp_Colour.Red 
  571.       * Texture -> Object_Reflection;
  572.       Colour -> Green += Temp_Colour.Green
  573.       * Texture -> Object_Reflection;
  574.       Colour -> Blue += Temp_Colour.Blue
  575.       * Texture -> Object_Reflection;
  576.  
  577.    }
  578. }
  579.  
  580. void Refract (Texture, Intersection_Point, Ray, Surface_Normal, Colour)
  581. TEXTURE *Texture;
  582. VECTOR *Intersection_Point;
  583. RAY *Ray;
  584. VECTOR *Surface_Normal;
  585. COLOUR *Colour;
  586. {
  587.    RAY New_Ray;
  588.    COLOUR Temp_Colour;
  589.    VECTOR Local_Normal;
  590.    VECTOR Ray_Direction;
  591.    register DBL Normal_Component, Temp_IOR;
  592.    DBL temp, ior;
  593.    int inside;
  594.  
  595.    if (Surface_Normal == NULL) {
  596.       New_Ray.Initial = *Intersection_Point;
  597.       New_Ray.Direction = Ray->Direction;
  598.  
  599.       Copy_Ray_Containers (&New_Ray, Ray);
  600.       Trace_Level++;
  601.       Transmitted_Rays_Traced++;
  602.       Make_Colour (&Temp_Colour, 0.0, 0.0, 0.0);
  603.       New_Ray.Quadric_Constants_Cached = FALSE;
  604.       Trace (&New_Ray, &Temp_Colour);
  605.       Trace_Level--;
  606.       (Colour -> Red) += Temp_Colour.Red;
  607.       (Colour -> Green) += Temp_Colour.Green;
  608.       (Colour -> Blue) += Temp_Colour.Blue;
  609.    }
  610.       else {
  611.          Refracted_Rays_Traced++;
  612.          VDot (Normal_Component, Ray -> Direction, *Surface_Normal);
  613.          if (Normal_Component <= 0.0)
  614.             {
  615.             Local_Normal.x = Surface_Normal -> x;
  616.             Local_Normal.y = Surface_Normal -> y;
  617.             Local_Normal.z = Surface_Normal -> z;
  618.             Normal_Component *= -1.0;
  619.             inside = FALSE;
  620.          }
  621.          else
  622.          {
  623.             VScale (Local_Normal, *Surface_Normal, -1.0);
  624.             inside = TRUE;
  625.          }
  626.  
  627.  
  628.          Copy_Ray_Containers (&New_Ray, Ray);
  629.  
  630.          if (Ray -> Containing_Index == -1)
  631.             {
  632.             /* The ray is entering from the atmosphere */
  633.             Ray_Enter (&New_Ray, Texture);
  634.             ior = (Frame.Atmosphere_IOR)/(Texture -> Object_Index_Of_Refraction);
  635.          }
  636.          else
  637.          {
  638.             /* The ray is currently inside an object */
  639.             if (New_Ray.Containing_Textures [New_Ray.Containing_Index] == Texture) 
  640.                /*         if (inside) */
  641.             {
  642.                /* The ray is leaving the current object */
  643.                Ray_Exit (&New_Ray);
  644.                if (New_Ray.Containing_Index == -1)
  645.                   /* The ray is leaving into the atmosphere */
  646.                Temp_IOR = Frame.Atmosphere_IOR;
  647.                else
  648.                   /* The ray is leaving into another object */
  649.                   Temp_IOR = New_Ray.Containing_IORs [New_Ray.Containing_Index];
  650.  
  651.                ior =  (Texture -> Object_Index_Of_Refraction)/Temp_IOR;
  652.             }
  653.                else
  654.                {
  655.                   /* The ray is entering a new object */
  656.                   Temp_IOR = New_Ray.Containing_IORs [New_Ray.Containing_Index];
  657.                   Ray_Enter (&New_Ray, Texture);
  658.  
  659.                   ior =  Temp_IOR / (Texture -> Object_Index_Of_Refraction);
  660.                }
  661.             }
  662.  
  663.             temp = 1.0 + ior * ior * (Normal_Component * Normal_Component - 1.0);
  664.             if (temp < 0.0) {
  665.                /* Total internal reflection - not yet implemented.
  666.      Reflect (Texture, Intersection_Point, Ray, Surface_Normal, Color);
  667.      */
  668.                return;
  669.             }
  670.  
  671.             temp = ior*Normal_Component - sqrt(temp);
  672.             VScale (Local_Normal, Local_Normal, temp);
  673.             VScale (Ray_Direction, Ray->Direction, ior);
  674.             VAdd (New_Ray.Direction, Local_Normal, Ray_Direction);
  675.             VNormalize (New_Ray.Direction, New_Ray.Direction);
  676.  
  677.             New_Ray.Initial = *Intersection_Point;
  678.             Trace_Level++;
  679.             Make_Colour (&Temp_Colour, 0.0, 0.0, 0.0);
  680.             New_Ray.Quadric_Constants_Cached = FALSE;
  681.  
  682.             Trace (&New_Ray, &Temp_Colour);
  683.             Trace_Level--;
  684.  
  685.             (Colour -> Red) += (Temp_Colour.Red)
  686.                * (Texture -> Object_Refraction);
  687.             (Colour -> Green) += (Temp_Colour.Green)
  688.                * (Texture -> Object_Refraction);
  689.             (Colour -> Blue) += (Temp_Colour.Blue)
  690.                * (Texture -> Object_Refraction);
  691.          }
  692.       }
  693.  
  694.       void Fog (Distance, Fog_Colour, Fog_Distance, Colour)
  695.          DBL Distance, Fog_Distance;
  696.       COLOUR *Fog_Colour, *Colour;
  697.       {
  698.          DBL Fog_Factor, Fog_Factor_Inverse;
  699.  
  700.          Fog_Factor = exp(-1.0 * Distance/Fog_Distance);
  701.          Fog_Factor_Inverse = 1.0 - Fog_Factor;
  702.          Colour->Red = Colour->Red*Fog_Factor + Fog_Colour->Red*Fog_Factor_Inverse;
  703.          Colour->Green = Colour->Green*Fog_Factor + Fog_Colour->Green*Fog_Factor_Inverse;
  704.          Colour->Blue = Colour->Blue*Fog_Factor + Fog_Colour->Blue*Fog_Factor_Inverse;
  705.       }
  706.  
  707.  
  708.  
  709.       void Compute_Reflected_Colour (Ray, Texture, Ray_Intersection, Surface_Colour, Filter_Colour, Colour)
  710.          RAY *Ray;
  711.       TEXTURE *Texture;
  712.       INTERSECTION *Ray_Intersection;
  713.       COLOUR *Surface_Colour;
  714.       COLOUR *Filter_Colour;
  715.       COLOUR *Colour;
  716.       {
  717.          VECTOR Surface_Normal;
  718.          DBL Normal_Direction, Attenuation;
  719.          COLOUR Emitted_Colour;
  720.  
  721.          /* This variable keeps track of how much colour comes from the surface
  722.       of the object and how much is transmited through. */
  723.  
  724.          Make_Colour (&Emitted_Colour, 0.0, 0.0, 0.0);
  725.  
  726.          if (Texture == NULL)
  727.             Texture = Ray_Intersection->Object->Object_Texture;
  728.  
  729.          if (Quality <= 1) {
  730.             Surface_Colour->Alpha = 0.0;
  731.  
  732.             Colour->Red   += Surface_Colour->Red * Filter_Colour->Alpha;
  733.             Colour->Green += Surface_Colour->Green * Filter_Colour->Alpha;
  734.             Colour->Blue  += Surface_Colour->Blue * Filter_Colour->Alpha;
  735.             return;
  736.          }
  737.  
  738.          Normal (&Surface_Normal, (OBJECT *) Ray_Intersection -> Shape,
  739.          &Ray_Intersection -> Point);
  740.  
  741.          if (Quality >= 8) {
  742.             Perturb_Normal (&Surface_Normal, Texture,
  743.             &Ray_Intersection->Point, &Surface_Normal);
  744.          }
  745.  
  746.          /* If the surface normal points away, flip its direction. */
  747.          VDot (Normal_Direction, Surface_Normal, Ray->Direction);
  748.          if (Normal_Direction > 0.0) {
  749.             VScale (Surface_Normal, Surface_Normal, -1.0);
  750.          }
  751.  
  752.          Attenuation = Filter_Colour->Alpha * (1.0 - Surface_Colour->Alpha);
  753.  
  754.  
  755.          Ambient (Texture, Surface_Colour, &Emitted_Colour, Attenuation);
  756.          Diffuse (Texture, &Ray_Intersection -> Point, Ray,
  757.          &Surface_Normal, Surface_Colour, &Emitted_Colour, Attenuation);
  758.          Colour->Red   += Emitted_Colour.Red;
  759.          Colour->Green += Emitted_Colour.Green;
  760.          Colour->Blue  += Emitted_Colour.Blue;
  761.          if (Quality >= 8)
  762.             Reflect (Texture, &Ray_Intersection -> Point, Ray,
  763.          &Surface_Normal, Colour); 
  764.       }
  765.  
  766.       void Determine_Surface_Colour (Ray_Intersection, Colour, Ray, Shadow_Ray)
  767.          INTERSECTION *Ray_Intersection;
  768.       COLOUR *Colour;
  769.       RAY *Ray;
  770.       int Shadow_Ray;
  771.       {
  772.          COLOUR Surface_Colour, Refracted_Colour, Filter_Colour;
  773.          TEXTURE *Temp_Texture, *Texture;
  774.          VECTOR Surface_Normal;
  775.          DBL Normal_Direction;
  776.          int surface;
  777.  
  778.          if (!Shadow_Ray)
  779.             Make_Colour (Colour, 0.0, 0.0, 0.0);
  780.  
  781.          if (Options & DEBUGGING)
  782.             if (Ray_Intersection->Shape->Shape_Colour)
  783.             printf ("Depth: %f Object %d Colour %f %f %f ", Ray_Intersection->Depth,
  784.          Ray_Intersection->Shape->Type,
  785.          Ray_Intersection->Shape->Shape_Colour->Red,
  786.          Ray_Intersection->Shape->Shape_Colour->Green,
  787.          Ray_Intersection->Shape->Shape_Colour->Blue);
  788.          else
  789.             printf ("Depth: %f Object %d Colour NIL ", Ray_Intersection->Depth,
  790.             Ray_Intersection->Shape->Type);
  791.  
  792.  
  793.          Make_Colour (&Surface_Colour, 0.0, 0.0, 0.0);
  794.  
  795.          /* Is there a texture in the shape?  If not, use the one in the object. */
  796.          if ((Texture = Ray_Intersection->Shape->Shape_Texture) == NULL) {
  797.             Texture = Ray_Intersection->Object->Object_Texture;      
  798.          }
  799.          /* Check to see if this object/shape has a material_map texture, if so */
  800.          /* then change the texture pointer to point to the mapped texture - CdW 7/91 */
  801.          if(Texture->Texture_Number == MATERIAL_MAP_TEXTURE)  
  802.             Texture = material_map(&Ray_Intersection->Point, Texture);
  803.  
  804.  
  805.  
  806.          /* If this is just a shadow ray and we're rendering low quality, then return */
  807.  
  808.          if (Shadow_Ray && (Quality <= 5))
  809.             return;
  810.  
  811.          Make_Colour (&Filter_Colour, 1.0, 1.0, 1.0);
  812.          Filter_Colour.Alpha = 1.0;
  813.  
  814.          /* Now, we perform the lighting calculations. */
  815.          for ( surface = 1 , Temp_Texture = Texture;
  816.                 (Temp_Texture != NULL) && (Filter_Colour.Alpha > 0.01) ;
  817.                 surface++, Temp_Texture = Temp_Texture->Next_Texture) {
  818.  
  819.             Make_Colour (&Surface_Colour, 0.0, 0.0, 0.0);
  820.             if (Quality <= 5) {
  821.                if (Ray_Intersection->Shape->Shape_Colour != NULL)
  822.                   Surface_Colour = *Ray_Intersection->Shape->Shape_Colour;
  823.             else if (Ray_Intersection->Object->Object_Colour != NULL)
  824.                Surface_Colour = *Ray_Intersection->Object->Object_Colour;
  825.             else {
  826.                Make_Colour (&Surface_Colour, 0.5, 0.5, 0.5);
  827.             }
  828.          }
  829.          else
  830.             Colour_At (&Surface_Colour,
  831.             Temp_Texture,
  832.             &Ray_Intersection -> Point);
  833.          /* We don't need to compute the lighting characteristics for shadow rays. */
  834.          if (!Shadow_Ray) {
  835.             Compute_Reflected_Colour (Ray,
  836.             Temp_Texture,
  837.             Ray_Intersection,
  838.             &Surface_Colour,
  839.             &Filter_Colour,
  840.             Colour);
  841.  
  842.          }
  843.  
  844.          if (Options & DEBUGGING) {
  845.             printf ("Surface %d\n", surface);
  846.             printf ("   Surf: %6.4f %6.4f %6.4f %6.4f\n",
  847.             Surface_Colour.Red, Surface_Colour.Green, Surface_Colour.Blue, Surface_Colour.Alpha);
  848.             printf ("   Filter_Colour:   %6.4f %6.4f %6.4f %6.4f  Final Colour: %6.4f %6.4f %6.4f %6.4f  \n",
  849.             Filter_Colour.Red, Filter_Colour.Green, Filter_Colour.Blue, Filter_Colour.Alpha,
  850.             Colour->Red, Colour->Green, Colour->Blue, Colour->Alpha);
  851.          }
  852.  
  853.          Filter_Colour.Red   *= Surface_Colour.Red;
  854.          Filter_Colour.Green *= Surface_Colour.Green;
  855.          Filter_Colour.Blue  *= Surface_Colour.Blue;
  856.  
  857.          Filter_Colour.Alpha *= Surface_Colour.Alpha;
  858.       }
  859.  
  860.       /* For shadow rays, we have the filter colour now - time to return */
  861.       if (Shadow_Ray) {
  862.  
  863.          if (Filter_Colour.Alpha < 0.01) {
  864.             Make_Colour (Colour, 0.0, 0.0, 0.0);
  865.             return;
  866.          }
  867.  
  868.          if (Texture->Object_Refraction > 0.0) {
  869.             Colour->Red *= Filter_Colour.Red * Texture->Object_Refraction * Filter_Colour.Alpha;
  870.             Colour->Green *= Filter_Colour.Green * Texture->Object_Refraction * Filter_Colour.Alpha;
  871.             Colour->Blue *= Filter_Colour.Blue * Texture->Object_Refraction * Filter_Colour.Alpha;
  872.          }
  873.          else {
  874.             Colour->Red *= Filter_Colour.Red * Filter_Colour.Alpha;
  875.             Colour->Green *= Filter_Colour.Green * Filter_Colour.Alpha;
  876.             Colour->Blue *= Filter_Colour.Blue * Filter_Colour.Alpha;
  877.          }
  878.          return;
  879.       }
  880.  
  881.          if ((Filter_Colour.Alpha > 0.01) && (Quality > 5)) {
  882.             Make_Colour (&Refracted_Colour, 0.0, 0.0, 0.0);
  883.  
  884.             if (Texture->Object_Refraction > 0.0) {
  885.                Normal (&Surface_Normal, (OBJECT *) Ray_Intersection -> Shape,
  886.                &Ray_Intersection -> Point);
  887.  
  888.                if (Quality > 7) {
  889.                   Perturb_Normal (&Surface_Normal, Texture,
  890.                   &Ray_Intersection->Point, &Surface_Normal);
  891.                }
  892.  
  893.             /* If the surface normal points away, flip its direction. */
  894.             VDot (Normal_Direction, Surface_Normal, Ray->Direction);
  895.             if (Normal_Direction > 0.0) {
  896.                VScale (Surface_Normal, Surface_Normal, -1.0);
  897.             }
  898.  
  899.             Refract (Texture, &Ray_Intersection -> Point, Ray,
  900.             &Surface_Normal, &Refracted_Colour);
  901.          }
  902.             else
  903.                Refract (Texture, &Ray_Intersection->Point, Ray,
  904.                NULL, &Refracted_Colour);
  905.  
  906.             Colour->Red += Filter_Colour.Red * Refracted_Colour.Red * Filter_Colour.Alpha;
  907.             Colour->Green += Filter_Colour.Green * Refracted_Colour.Green * Filter_Colour.Alpha;
  908.             Colour->Blue += Filter_Colour.Blue * Refracted_Colour.Blue * Filter_Colour.Alpha;
  909.  
  910.             if (Texture->Object_Refraction > 0.0 &&
  911.             Texture->Object_Transmit > 0.0) {
  912.                Make_Colour (&Refracted_Colour, 0.0, 0.0, 0.0);
  913.                Refract (Texture, &Ray_Intersection->Point, Ray,
  914.                NULL, &Refracted_Colour);
  915.                Colour->Red += Filter_Colour.Red * Refracted_Colour.Red * Filter_Colour.Alpha;
  916.                Colour->Green += Filter_Colour.Green * Refracted_Colour.Green * Filter_Colour.Alpha;
  917.                Colour->Blue += Filter_Colour.Blue * Refracted_Colour.Blue * Filter_Colour.Alpha;
  918.             }
  919.          }
  920.  
  921.          if (Frame.Fog_Distance != 0.0)  {
  922.             Fog (Ray_Intersection->Depth, &Frame.Fog_Colour, Frame.Fog_Distance,
  923.             Colour);
  924.          }
  925.       }
  926.