home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 2 / crawlyvol2.bin / graphics / ftpovstc / lighting.c < prev    next >
C/C++ Source or Header  |  1994-05-25  |  52KB  |  1,756 lines

  1. /****************************************************************************
  2. *
  3. *  ATTENTION!!!
  4. *
  5. *  THIS FILE HAS BEEN MODIFIED!!! IT IS NOT PART OF THE OFFICAL
  6. *  POV-RAY 2.2 DISTRIBUTION!!!
  7. *
  8. *  THIS FILE IS PART OF "FASTER THAN POV-RAY" (VERSION 1.1),
  9. *  A SPED-UP VERSION OF POV-RAY 2.2. USE AT YOUR OWN RISK!!!!!!
  10. *
  11. *  New files: addon0.c, addon1.c, addon2.c, addon3.c, addon.h
  12. *
  13. *  The additional modules were written by Dieter Bayer.
  14. *
  15. *  Send comments, suggestions, bugs, ideas ... to:
  16. *
  17. *  dieter@cip.e-technik.uni-erlangen.de
  18. *
  19. *  All changed/added lines are enclosed in #ifdef DB_CODE ... #endif
  20. *
  21. *  The vista projection was taken from:
  22. *
  23. *    A. Hashimoto, T. Akimoto, K. Mase, and Y. Suenaga, 
  24. *    "Vista Ray-Tracing: High Speed Ray Tracing Using Perspective
  25. *    Projection Image", New Advances in Computer Graphics, Proceedings
  26. *    of CG International '89, R. A. Earnshaw, B. Wyvill (Eds.), 
  27. *    Springer, ..., pp. 549-560
  28. *
  29. *  The idea for the light buffer was taken from:
  30. *
  31. *    E. Haines and D. Greenberg, "The Light Buffer: A Shadow-Testing 
  32. *    Accelerator", IEEE CG&A, Vol. 6, No. 9, Sept. 1986, pp. 6-16
  33. *
  34. *****************************************************************************/
  35.  
  36. /****************************************************************************
  37. *                   lighting.c
  38. *
  39. *  This module calculates lighting properties like ambient, diffuse, specular,
  40. *  reflection, refraction, etc.
  41. *
  42. *  from Persistence of Vision Raytracer
  43. *  Copyright 1993 Persistence of Vision Team
  44. *---------------------------------------------------------------------------
  45. *  NOTICE: This source code file is provided so that users may experiment
  46. *  with enhancements to POV-Ray and to port the software to platforms other
  47. *  than those supported by the POV-Ray Team.  There are strict rules under
  48. *  which you are permitted to use this file.  The rules are in the file
  49. *  named POVLEGAL.DOC which should be distributed with this file. If
  50. *  POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  51. *  Team Coordinator by leaving a message in CompuServe's Graphics Developer's
  52. *  Forum.  The latest version of POV-Ray may be found there as well.
  53. *
  54. * This program is based on the popular DKB raytracer version 2.12.
  55. * DKBTrace was originally written by David K. Buck.
  56. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  57. *
  58. *****************************************************************************/
  59.  
  60. #include "frame.h"
  61. #include "vector.h"
  62. #include "povproto.h"
  63. #ifdef DB_CODE
  64. /* Changes necessary for the light buffer. */
  65. #include "addon.h"
  66. #endif
  67.  
  68. extern int Trace_Level;
  69. extern FRAME Frame;
  70. extern OBJECT *Root_Object;
  71. extern unsigned int Options;
  72. extern int Use_Slabs;
  73. extern unsigned long Quality_Flags;
  74. extern int Shadow_Test_Flag;
  75. extern long Shadow_Ray_Tests, Shadow_Rays_Succeeded, Shadow_Cache_Hits;
  76. extern long Reflected_Rays_Traced, Refracted_Rays_Traced;
  77. extern long Transmitted_Rays_Traced;
  78. #ifdef DB_CODE
  79. /* Changes necessary for the light buffer. */
  80. extern unsigned int Extended_Options;
  81. #endif
  82.  
  83. extern short *hashTable;
  84. extern unsigned short crctab[256];
  85. #define rand3d(a,b) crctab[(int)(hashTable[(int)(hashTable[(int)((a)&0xfff)]^(b))&0xfff])&0xff]
  86.  
  87. #define COORDINATE_LIMIT 1.0e17
  88. #define BLACK_LEVEL 0.003
  89.  
  90. /* "Small_Tolerance" is just too tight for higher order polynomial equations.
  91.    this value should probably be a variable of some sort, but for now just
  92.    use a reasonably small value.  If people render real small objects real
  93.    close to each other then there may be some shading problems.  Otherwise
  94.    having SHADOW_TOLERANCE as large as this won't affect images. */
  95. #define SHADOW_TOLERANCE 1.0e-3
  96.  
  97. static void do_light PARAMS((LIGHT_SOURCE *Light_Source,
  98. DBL *Light_Source_Depth, RAY *Light_Source_Ray, VECTOR *IPoint,
  99. COLOUR *Light_Colour));
  100. static int do_blocking PARAMS((INTERSECTION *Local_Intersection,
  101. COLOUR *Light_Colour, ISTACK *Local_Stack));
  102. static void do_phong PARAMS((FINISH *Finish, RAY *Light_Source_Ray,
  103. VECTOR *Eye, VECTOR *Layer_Normal, COLOUR *Colour, COLOUR *Light_Colour,
  104. COLOUR *Layer_Pigment_Colour));
  105. static void do_specular PARAMS((FINISH *Finish, RAY *Light_Source_Ray,
  106. VECTOR *REye, VECTOR *Layer_Normal, COLOUR *Colour, COLOUR *Light_Colour,
  107. COLOUR *Layer_Pigment_Colour));
  108. static void do_diffuse PARAMS((FINISH *Finish, RAY *Light_Source_Ray,
  109. VECTOR *Layer_Normal, COLOUR *Colour, COLOUR *Light_Colour,
  110. COLOUR *Layer_Pigment_Colour, DBL Attenuation));
  111. static void Block_Area_Light PARAMS((LIGHT_SOURCE *Light_Source,
  112. DBL Light_Source_Depth, RAY *Light_Source_Ray_Ptr, VECTOR *IPoint,
  113. COLOUR *Light_Colour, int u1, int v1, int u2, int v2, int Level));
  114. static void Block_Point_Light PARAMS((LIGHT_SOURCE *Light_Source,
  115. DBL Light_Source_Depth, RAY *Light_Source_Ray_Ptr, COLOUR *Light_Colour));
  116.  
  117. #ifdef DB_CODE
  118. /* Changes necessary for the light buffer. */
  119. static void Block_Point_Light_Light_Buffer PARAMS((LIGHT_SOURCE *Light_Source,
  120.   DBL Light_Source_Depth, RAY *Light_Source_Ray_Ptr, COLOUR *Light_Colour));
  121.  
  122.  
  123.  
  124. /******************************************************************************
  125.    Intersect a shadow ray with the light buffer tree.
  126.  ******************************************************************************/
  127. static void Block_Point_Light_Light_Buffer (Light_Source, Light_Source_Depth, Light_Source_Ray_Ptr, Light_Colour)
  128. LIGHT_SOURCE *Light_Source;
  129. DBL Light_Source_Depth;
  130. RAY *Light_Source_Ray_Ptr;
  131. COLOUR *Light_Colour;
  132. {
  133.   int Quit_Looking, Not_Found_Shadow, Cache_Me;
  134.   ISTACK *Local_Stack;
  135.   RAY Light_Source_Ray;
  136.   INTERSECTION *Local_Intersection, Bounded_Intersection;
  137.   RAY Local_Ray;
  138.  
  139.   VECTOR V;
  140.   DBL ax, ay, az;
  141.   int u, v, axis;
  142.   OBJECT *Blocking_Object;
  143.  
  144.   Light_Source_Ray = *Light_Source_Ray_Ptr;
  145.  
  146.   Local_Stack = open_istack ();
  147.   Quit_Looking = FALSE;
  148.  
  149.   /* Test the cached object first */
  150.   /* Made changes so that semi-transparent objects never get cached */
  151.  
  152.   if (Light_Source->Shadow_Cached_Object != NULL)
  153.   {
  154.     Shadow_Ray_Tests++;
  155.  
  156.     if (Ray_In_Bounds(&Light_Source_Ray, Light_Source->Shadow_Cached_Object->Bound))
  157.     {
  158.       if (All_Intersections(Light_Source->Shadow_Cached_Object, &Light_Source_Ray, Local_Stack))
  159.       {
  160.     while ((Local_Intersection=pop_entry(Local_Stack)) != NULL)
  161.     {
  162.       if ((!Local_Intersection->Object->No_Shadow_Flag) &&
  163.           (Local_Intersection->Depth < Light_Source_Depth-Small_Tolerance) &&
  164.           (Local_Intersection->Depth > SHADOW_TOLERANCE))
  165.       {
  166.         if (do_blocking(Local_Intersection, Light_Colour, Local_Stack))
  167.         {
  168.           Quit_Looking = TRUE;
  169.           Shadow_Cache_Hits++;
  170.           break;
  171.         }
  172.       }
  173.     }
  174.       }
  175.     }
  176.   }
  177.  
  178.   if (Quit_Looking)
  179.   {
  180.     close_istack(Local_Stack);
  181.     return;
  182.   }
  183.  
  184.   V.x = -Light_Source_Ray.Direction.x;
  185.   V.y = -Light_Source_Ray.Direction.y;
  186.   V.z = -Light_Source_Ray.Direction.z;
  187.  
  188.   ax = fabs(V.x);
  189.   ay = fabs(V.y);
  190.   az = fabs(V.z);
  191.  
  192.   if ((ax>ay) && (ax>az))
  193.   {
  194.     if (V.x>0.0)
  195.       axis = XaxisP;
  196.     else
  197.       axis = XaxisM;
  198.     u = (int)(MAX_LB_ENTRY * V.y/ax);
  199.     v = (int)(MAX_LB_ENTRY * V.z/ax);
  200.   }
  201.   else
  202.   {
  203.     if (ay>az)
  204.     {
  205.       if (V.y>0.0)
  206.     axis = YaxisP;
  207.       else
  208.     axis = YaxisM;
  209.       u = (int)(MAX_LB_ENTRY * V.x/ay);
  210.       v = (int)(MAX_LB_ENTRY * V.z/ay);
  211.     }
  212.     else
  213.     {
  214.       if (V.z>0.0)
  215.     axis = ZaxisP;
  216.       else
  217.     axis = ZaxisM;
  218.       u = (int)(MAX_LB_ENTRY * V.x/az);
  219.       v = (int)(MAX_LB_ENTRY * V.y/az);
  220.     }
  221.   }
  222.  
  223.   if (Light_Source->Light_Buffer[axis] == NULL)
  224.   {
  225.     close_istack(Local_Stack);
  226.     return;
  227.   }
  228.  
  229.   Not_Found_Shadow = TRUE;
  230.   Cache_Me = FALSE;
  231.  
  232.   Local_Ray = Light_Source_Ray;
  233.  
  234.   while (!Quit_Looking)
  235.   {
  236.     Shadow_Ray_Tests++;
  237.  
  238.     Local_Ray.Quadric_Constants_Cached = 0;
  239.  
  240.     Bounded_Intersection.Depth = Light_Source_Depth;
  241.  
  242.     if (Intersect_Light_Tree(&Local_Ray, Light_Source->Light_Buffer[axis],
  243.     u, v, &Bounded_Intersection, &Blocking_Object))
  244.     {
  245.       if (Bounded_Intersection.Depth > Light_Source_Depth)
  246.     break; /* Intersection was beyond the light */
  247.  
  248.       if (!(Bounded_Intersection.Object->No_Shadow_Flag))
  249.       {
  250.     if (Blocking_Object != Light_Source->Shadow_Cached_Object)
  251.     {
  252.       Shadow_Rays_Succeeded++;
  253.  
  254.       Filter_Shadow_Ray(&Bounded_Intersection, Light_Colour);
  255.  
  256.       if ((fabs(Light_Colour->Red) < BLACK_LEVEL) &&
  257.           (fabs(Light_Colour->Green) < BLACK_LEVEL) &&
  258.           (fabs(Light_Colour->Blue) < BLACK_LEVEL))
  259.       {
  260.         Cache_Me = Not_Found_Shadow;
  261.         Quit_Looking = TRUE;
  262.         break; /* from while */
  263.       }
  264.     }
  265.  
  266.     /* Move the ray to the point of intersection, plus some */
  267.  
  268.     Light_Source_Depth -= Bounded_Intersection.Depth;
  269.  
  270.     Local_Ray.Initial = Bounded_Intersection.IPoint;
  271.  
  272.     Not_Found_Shadow = FALSE;
  273.       }
  274.     }
  275.     else /* No intersections in the direction of the ray */
  276.     {
  277.       break;
  278.     }
  279.   } /*endwhile*/
  280.  
  281.   if (Cache_Me)
  282.   {
  283.     Light_Source->Shadow_Cached_Object = Blocking_Object;
  284.   }
  285.  
  286.   close_istack(Local_Stack);
  287. }
  288. #endif
  289.  
  290. static void Block_Point_Light (Light_Source, Light_Source_Depth, Light_Source_Ray_Ptr, Light_Colour)
  291. LIGHT_SOURCE *Light_Source;
  292. DBL Light_Source_Depth;
  293. RAY *Light_Source_Ray_Ptr;
  294. COLOUR *Light_Colour;
  295.   {
  296.   OBJECT *Blocking_Object;
  297.   int Quit_Looking, Not_Found_Shadow, Cache_Me;
  298.   INTERSECTION *Local_Intersection, Bounded_Intersection;
  299.   ISTACK *Local_Stack;
  300.   RAY Local_Ray;
  301.   RAY Light_Source_Ray;
  302.  
  303.   Light_Source_Ray = *Light_Source_Ray_Ptr;
  304.  
  305.   Local_Stack = open_istack ();
  306.   Quit_Looking = FALSE;
  307.  
  308.   /* Test the cached object first */
  309.   /* Made changes so that semi-transparent objects never get cached */
  310.   if (Light_Source->Shadow_Cached_Object != NULL) 
  311.     {
  312.     Shadow_Ray_Tests++;
  313.  
  314.     if (Ray_In_Bounds (&Light_Source_Ray, Light_Source->Shadow_Cached_Object->Bound))
  315.       {
  316.       if (All_Intersections (Light_Source->Shadow_Cached_Object, &Light_Source_Ray, Local_Stack))
  317.         while ((Local_Intersection=pop_entry(Local_Stack)) != NULL)
  318.       {
  319.           if ((!Local_Intersection->Object->No_Shadow_Flag) && 
  320.         (Local_Intersection->Depth < Light_Source_Depth-Small_Tolerance) &&
  321.             (Local_Intersection->Depth > SHADOW_TOLERANCE))
  322.             if (do_blocking(Local_Intersection, Light_Colour, Local_Stack))
  323.           {
  324.               Quit_Looking = TRUE;
  325.               Shadow_Cache_Hits++;
  326.               break;
  327.               }
  328.           }
  329.       }
  330.     }
  331.  
  332.   if (Quit_Looking) 
  333.     {
  334.     close_istack (Local_Stack);
  335.     return;
  336.     }
  337.  
  338.   Not_Found_Shadow = TRUE;   
  339.   Cache_Me = FALSE;
  340.   if (!Use_Slabs)
  341.     {
  342.     for (Blocking_Object = Frame.Objects;
  343.     Blocking_Object != NULL;
  344.     Blocking_Object = Blocking_Object->Sibling)
  345.       {
  346.       if (Blocking_Object == Light_Source->Shadow_Cached_Object)
  347.     continue;
  348.  
  349.       Shadow_Ray_Tests++;
  350.  
  351.       if (!Ray_In_Bounds (&Light_Source_Ray, Blocking_Object->Bound))
  352.     continue;
  353.  
  354.       if (!All_Intersections (Blocking_Object, &Light_Source_Ray, Local_Stack))
  355.     continue;
  356.  
  357.       while ((Local_Intersection = pop_entry(Local_Stack)) != NULL)
  358.     if ((!Local_Intersection->Object->No_Shadow_Flag) &&
  359.           (Local_Intersection->Depth < Light_Source_Depth-Small_Tolerance) && 
  360.           (Local_Intersection->Depth > SHADOW_TOLERANCE))
  361.           {
  362.           if (do_blocking(Local_Intersection, Light_Colour, Local_Stack))
  363.             {
  364.             Cache_Me = Not_Found_Shadow;
  365.             Quit_Looking = TRUE;
  366.             break; /* from while */
  367.             }
  368.           Not_Found_Shadow = FALSE;
  369.       }
  370.       if (Quit_Looking)
  371.     break; /* from for */
  372.       }
  373.     }
  374.   else   /* Use bounding slabs to look for shadows */
  375.     {
  376.     Local_Ray = Light_Source_Ray;
  377.     while (!Quit_Looking)
  378.       {
  379.       Shadow_Ray_Tests++;
  380.       Local_Ray.Quadric_Constants_Cached = 0;
  381.       Bounded_Intersection.Depth = Light_Source_Depth;
  382.       if (Bounds_Intersect(Root_Object, &Local_Ray, &Bounded_Intersection,
  383.     &Blocking_Object))
  384.     {
  385.     if (Bounded_Intersection.Depth > Light_Source_Depth)
  386.       break; /* Intersection was beyond the light */
  387.  
  388.     if (!(Bounded_Intersection.Object->No_Shadow_Flag))
  389.       if (Blocking_Object != Light_Source->Shadow_Cached_Object)
  390.         {
  391.         Shadow_Rays_Succeeded++;
  392.         Filter_Shadow_Ray(&Bounded_Intersection, Light_Colour);
  393.         if ((fabs(Light_Colour->Red) < BLACK_LEVEL) &&
  394.           (fabs(Light_Colour->Green) < BLACK_LEVEL) &&
  395.           (fabs(Light_Colour->Blue) < BLACK_LEVEL))
  396.           {
  397.           Cache_Me = Not_Found_Shadow;
  398.           Quit_Looking = TRUE;
  399.           break; /* from while */
  400.           }
  401.         }
  402.     /* Move the ray to the point of intersection, plus some */
  403.     Light_Source_Depth -= Bounded_Intersection.Depth;
  404.     Local_Ray.Initial = Bounded_Intersection.IPoint;
  405.     Not_Found_Shadow = FALSE;
  406.     }
  407.       else /* No intersections in the direction of the ray */
  408.     {
  409.     break;
  410.     }
  411.       } /*endwhile*/
  412.     } /*endelse*/
  413.   if (Cache_Me) 
  414.     Light_Source->Shadow_Cached_Object = Blocking_Object;
  415.   close_istack (Local_Stack);
  416.   }
  417.  
  418.  
  419. static void Block_Area_Light (Light_Source, Light_Source_Depth,
  420. Light_Source_Ray_Ptr,IPoint, Light_Colour, u1, v1, u2, v2, Level)
  421. LIGHT_SOURCE *Light_Source;
  422. DBL Light_Source_Depth;
  423. RAY *Light_Source_Ray_Ptr;
  424. VECTOR *IPoint;
  425. COLOUR *Light_Colour;
  426. int u1, v1, u2, v2, Level;
  427.   {
  428.   COLOUR Sample_Colour[4], Dummy_Colour;
  429.   VECTOR Center_Save, NewAxis1, NewAxis2;
  430.   int i, j, u, v, New_u1, New_v1, New_u2, New_v2;
  431.  
  432.   DBL Jitter_u, Jitter_v, ScaleFactor;
  433.   RAY Light_Source_Ray;
  434.  
  435.   Light_Source_Ray = *Light_Source_Ray_Ptr;
  436.  
  437.   /* First call, initialize */
  438.   if (u1 == 0 && v1 == 0 && u2 == 0 && v2 == 0) 
  439.     {
  440.     /* Flag uncalculated points with a negative value for Red */
  441.     for (i = 0; i < Light_Source->Area_Size1; i++) 
  442.       {
  443.       for (j = 0; j < Light_Source->Area_Size2; j++)
  444.         Light_Source->Light_Grid[i][j].Red = -1.0;
  445.       }
  446.  
  447.     u1 = 0;
  448.     v1 = 0;
  449.     u2 = Light_Source->Area_Size1 - 1;
  450.     v2 = Light_Source->Area_Size2 - 1;
  451.     }
  452.  
  453.   /* Save the light source center since we'll be fiddling with it */
  454.   Center_Save=Light_Source->Center;
  455.  
  456.   /* Sample the four corners of the region */
  457.   for (i = 0; i < 4; i++) 
  458.     {
  459.     switch (i) 
  460.     {
  461.     case 0: 
  462.       u = u1; v = v1; break;
  463.     case 1: 
  464.       u = u2; v = v1; break;
  465.     case 2: 
  466.       u = u1; v = v2; break;
  467.     case 3: 
  468.       u = u2; v = v2; break;
  469.     }
  470.  
  471.     if (Light_Source -> Light_Grid[u][v].Red >= 0.0)
  472.       /* We've already calculated this point, reuse it */
  473.       Sample_Colour[i]=Light_Source->Light_Grid[u][v];
  474.     else
  475.       {
  476.       Jitter_u = (DBL)u;
  477.       Jitter_v = (DBL)v;
  478.  
  479.       if (Light_Source -> Jitter) 
  480.         {
  481.         Jitter_u += (rand() % 4096)/4096.0 - 0.5;
  482.         Jitter_v += (rand() % 4096)/4096.0 - 0.5;
  483.         /*
  484.   Not sure if    jx = IPoint->x + 100*u;
  485.   this works    jy = IPoint->y + 100*v;
  486.   yet
  487.         Jitter_u += ((rand3d(jx, jy) & 0x7FFF)/32768.0) - 0.5;
  488.         Jitter_v += ((rand3d(jx+10, jy+10) & 0x7FFF)/32768.0) - 0.5;
  489. */
  490.         }
  491.  
  492.       if (Light_Source -> Area_Size1 > 1) 
  493.         {
  494.         ScaleFactor = Jitter_u/(DBL)(Light_Source->Area_Size1 - 1) - 0.5;
  495.         VScale (NewAxis1, Light_Source->Axis1, ScaleFactor)
  496.           }
  497.       else
  498.         Make_Vector (&NewAxis1, 0.0, 0.0, 0.0);
  499.  
  500.       if (Light_Source -> Area_Size2 > 1) 
  501.         {
  502.         ScaleFactor = Jitter_v/(DBL)(Light_Source->Area_Size2 - 1) - 0.5;
  503.         VScale (NewAxis2, Light_Source->Axis2, ScaleFactor)
  504.         }
  505.       else
  506.         Make_Vector (&NewAxis2, 0.0, 0.0, 0.0);
  507.  
  508.       Light_Source->Center=Center_Save;
  509.       VAdd  (Light_Source->Center, Light_Source->Center, NewAxis1);
  510.       VAdd  (Light_Source->Center, Light_Source->Center, NewAxis2);
  511.  
  512.       /* Recalculate the light source ray but not the colour */
  513.       do_light (Light_Source, &Light_Source_Depth, &Light_Source_Ray,
  514.         IPoint, &Dummy_Colour);
  515.  
  516.       Sample_Colour[i]= *Light_Colour;
  517.  
  518.       Block_Point_Light (Light_Source, Light_Source_Depth,
  519.         &Light_Source_Ray, &Sample_Colour[i]);
  520.  
  521.       Light_Source->Light_Grid[u][v]=Sample_Colour[i];
  522.       }
  523.     }
  524.  
  525.   Light_Source->Center=Center_Save;
  526.  
  527.   if ( (u2 - u1 > 1 || v2 - v1 > 1) && (Level < Light_Source -> Adaptive_Level ||
  528.     Colour_Distance (&Sample_Colour[0], &Sample_Colour[1]) > 0.1 ||
  529.     Colour_Distance (&Sample_Colour[1], &Sample_Colour[3]) > 0.1 ||
  530.     Colour_Distance (&Sample_Colour[3], &Sample_Colour[2]) > 0.1 ||
  531.     Colour_Distance (&Sample_Colour[2], &Sample_Colour[0]) > 0.1) )
  532.     {
  533.     for (i = 0; i < 4; i++) 
  534.       {
  535.       switch (i) 
  536.       {
  537.       case 0: 
  538.         New_u1 = u1;
  539.         New_v1 = v1;
  540.         New_u2 = (int)floor ((u1 + u2)/2.0);
  541.         New_v2 = (int)floor ((v1 + v2)/2.0);
  542.         break;
  543.  
  544.       case 1: 
  545.         New_u1 = (int)ceil  ((u1 + u2)/2.0);
  546.         New_v1 = v1;
  547.         New_u2 = u2;
  548.         New_v2 = (int)floor ((v1 + v2)/2.0);
  549.         break;
  550.  
  551.       case 2: 
  552.         New_u1 = u1;
  553.         New_v1 = (int)ceil  ((v1 + v2)/2.0);
  554.         New_u2 = (int)floor ((u1 + u2)/2.0);
  555.         New_v2 = v2;
  556.         break;
  557.  
  558.       case 3: 
  559.         New_u1 = (int)ceil ((u1 + u2)/2.0);
  560.         New_v1 = (int)ceil ((v1 + v2)/2.0);
  561.         New_u2 = u2;
  562.         New_v2 = v2;
  563.         break;
  564.       }
  565.  
  566.       /* Recalculate the light source ray but not the colour */
  567.       do_light (Light_Source, &Light_Source_Depth, &Light_Source_Ray,
  568.         IPoint, &Dummy_Colour);
  569.  
  570.       Sample_Colour[i]= *Light_Colour;
  571.  
  572.       Block_Area_Light (Light_Source, Light_Source_Depth,
  573.         &Light_Source_Ray, IPoint,
  574.         &Sample_Colour[i],
  575.         New_u1, New_v1, New_u2, New_v2, Level+1);
  576.       }
  577.     }
  578.  
  579.   /* Add up the light contributions */
  580.   Make_Colour (Light_Colour, 0.0, 0.0, 0.0);
  581.  
  582.   for (i = 0; i < 4; i++) 
  583.     {
  584.     Scale_Colour (&Sample_Colour[i], &Sample_Colour[i], 0.25);
  585.     Add_Colour (Light_Colour, Light_Colour, &Sample_Colour[i]);
  586.     }
  587.   }
  588.  
  589. static void do_light(Light_Source, Light_Source_Depth, Light_Source_Ray, IPoint, Light_Colour)
  590. LIGHT_SOURCE *Light_Source;
  591. DBL *Light_Source_Depth;
  592. RAY *Light_Source_Ray;
  593. VECTOR *IPoint;
  594. COLOUR *Light_Colour;
  595.   {
  596.   DBL Attenuation = 1.0;
  597.  
  598.   /* Get the light source colour. */
  599.   *Light_Colour = Light_Source->Colour;
  600.  
  601.   Light_Source_Ray->Initial = *IPoint;
  602.   Light_Source_Ray->Quadric_Constants_Cached = FALSE;
  603.  
  604.   VSub (Light_Source_Ray->Direction,
  605.     Light_Source->Center,
  606.     *IPoint);
  607.  
  608.   VLength (*Light_Source_Depth, Light_Source_Ray->Direction);
  609.  
  610.   VScale (Light_Source_Ray->Direction, Light_Source_Ray->Direction,
  611.     1.0/(*Light_Source_Depth));
  612.  
  613.   Attenuation = Attenuate_Light(Light_Source, Light_Source_Ray);
  614.  
  615.   /* Now scale the color by the attenuation */
  616.   Light_Colour->Red   *= Attenuation;
  617.   Light_Colour->Green *= Attenuation;
  618.   Light_Colour->Blue  *= Attenuation;
  619.  
  620.  
  621.   return;
  622.   }
  623.  
  624. static int do_blocking(Local_Intersection, Light_Colour, Local_Stack)
  625. INTERSECTION *Local_Intersection;
  626. COLOUR *Light_Colour;
  627. ISTACK *Local_Stack;
  628.   {
  629.   Shadow_Rays_Succeeded++;
  630.  
  631.   Filter_Shadow_Ray (Local_Intersection, Light_Colour);
  632.  
  633.   if ((fabs(Light_Colour->Red) < BLACK_LEVEL) && 
  634.     (fabs(Light_Colour->Green) < BLACK_LEVEL) && 
  635.     (fabs(Light_Colour->Blue) < BLACK_LEVEL)) 
  636.     {
  637.     while ((Local_Intersection = pop_entry(Local_Stack)) != NULL)
  638.       {
  639.       }
  640.     return(TRUE);
  641.     }
  642.   return(FALSE);
  643.   }
  644.  
  645. #ifdef DB_CODE
  646. /* Some things have been optimized. */
  647. /******************************************************************************
  648.    Light_Source_Ray->Direction is a unit vector, so its length       
  649.    needn't be calculated!                                            
  650.    
  651.    The first test (Cos_Angle_Of_Incidence < 0.0) is unnecessary,     
  652.    since the negation of Normal_Component leads to the same result     
  653.    as the negation of the normal vector!                             
  654.  ******************************************************************************/
  655. static void do_phong(Finish, Light_Source_Ray, Eye, Layer_Normal, Colour, Light_Colour, Layer_Pigment_Colour)
  656. FINISH *Finish;
  657. RAY *Light_Source_Ray;
  658. VECTOR *Layer_Normal, *Eye;
  659. COLOUR *Colour, *Light_Colour, *Layer_Pigment_Colour;
  660. {
  661.   DBL k; /* Cos_Angle_Of_Incidence */
  662.   DBL Intensity;
  663.   VECTOR Reflect_Direction;
  664.  
  665.   k = 2.0 * (Eye->x * Layer_Normal->x +
  666.          Eye->y * Layer_Normal->y +
  667.          Eye->z * Layer_Normal->z);
  668.  
  669.   Reflect_Direction.x = Eye->x - k * Layer_Normal->x;
  670.   Reflect_Direction.y = Eye->y - k * Layer_Normal->y;
  671.   Reflect_Direction.z = Eye->z - k * Layer_Normal->z;
  672.  
  673.   VDot (k, Reflect_Direction, Light_Source_Ray->Direction);
  674.  
  675.   if (k <= 0.0)
  676.     return;
  677.  
  678.   if (Finish->Phong_Size != 1.0)
  679.     Intensity = Finish->Phong * pow(k, Finish->Phong_Size);
  680.   else
  681.     Intensity = Finish->Phong * k;
  682.  
  683.   if (Finish->Metallic_Flag)
  684.   {
  685.     Colour->Red+=Intensity*(Layer_Pigment_Colour->Red)*(Light_Colour->Red);
  686.     Colour->Green+=Intensity*(Layer_Pigment_Colour->Green)*(Light_Colour->Green);
  687.     Colour->Blue+=Intensity*(Layer_Pigment_Colour->Blue)*(Light_Colour->Blue);
  688.   }
  689.   else
  690.   {
  691.     Colour->Red+=Intensity*(Light_Colour->Red);
  692.     Colour->Green+=Intensity*(Light_Colour->Green);
  693.     Colour->Blue+=Intensity*(Light_Colour->Blue);
  694.   }
  695. }
  696. #else
  697. static void do_phong(Finish, Light_Source_Ray, Eye, Layer_Normal, Colour, Light_Colour, Layer_Pigment_Colour)
  698. FINISH *Finish;
  699. RAY *Light_Source_Ray;
  700. VECTOR *Layer_Normal, *Eye;
  701. COLOUR *Colour, *Light_Colour, *Layer_Pigment_Colour;
  702.   {
  703.   DBL Cos_Angle_Of_Incidence, Normal_Length, Intensity;
  704.   VECTOR Local_Normal, Normal_Projection, Reflect_Direction;
  705.  
  706.   VDot(Cos_Angle_Of_Incidence, *Eye, *Layer_Normal);
  707.  
  708.   if (Cos_Angle_Of_Incidence < 0.0)
  709.     {
  710.     Local_Normal = *Layer_Normal;
  711.     Cos_Angle_Of_Incidence = -Cos_Angle_Of_Incidence;
  712.     }
  713.   else
  714.     {
  715.     VScale (Local_Normal, *Layer_Normal, -1.0);
  716.     }
  717.  
  718.   VScale (Normal_Projection, Local_Normal, Cos_Angle_Of_Incidence);
  719.   VScale (Normal_Projection, Normal_Projection, 2.0);
  720.   VAdd (Reflect_Direction, *Eye, Normal_Projection);
  721.  
  722.   VDot (Cos_Angle_Of_Incidence, Reflect_Direction, Light_Source_Ray->Direction);
  723.   VLength (Normal_Length, Light_Source_Ray->Direction);
  724.  
  725.   if (Normal_Length == 0.0)
  726.     Cos_Angle_Of_Incidence = 0.0;
  727.   else 
  728.     Cos_Angle_Of_Incidence /= Normal_Length;
  729.  
  730.   if (Cos_Angle_Of_Incidence < 0.0)
  731.     Cos_Angle_Of_Incidence = 0;
  732.  
  733.   if (Finish->Phong_Size != 1.0)
  734.     Intensity = pow(Cos_Angle_Of_Incidence, Finish->Phong_Size);
  735.   else
  736.     Intensity = Cos_Angle_Of_Incidence;
  737.  
  738.   Intensity *= Finish->Phong;
  739.  
  740.   if (Finish->Metallic_Flag) 
  741.     {
  742.     Colour->Red+=Intensity*(Layer_Pigment_Colour->Red)*(Light_Colour->Red);    
  743.     Colour->Green+=Intensity*(Layer_Pigment_Colour->Green)*(Light_Colour->Green);
  744.     Colour->Blue+=Intensity*(Layer_Pigment_Colour->Blue)*(Light_Colour->Blue);  
  745.     }
  746.   else 
  747.     {
  748.     Colour->Red+=Intensity*(Light_Colour->Red);
  749.     Colour->Green+=Intensity*(Light_Colour->Green);
  750.     Colour->Blue+=Intensity*(Light_Colour->Blue);  
  751.     }
  752.   }
  753. #endif
  754.  
  755. #ifdef DB_CODE
  756. /* Some things have been optimized. */
  757. /******************************************************************************
  758.    There's no need to multiply the vector Halfway by 0.5!            
  759.    The normal vector is already unit!                                
  760.  ******************************************************************************/
  761. static void do_specular(Finish, Light_Source_Ray, REye, Layer_Normal, Colour, Light_Colour, Layer_Pigment_Colour)
  762. FINISH *Finish;
  763. RAY *Light_Source_Ray;
  764. VECTOR *Layer_Normal, *REye;
  765. COLOUR *Colour, *Light_Colour, *Layer_Pigment_Colour;
  766. {
  767.   DBL Cos_Angle_Of_Incidence, Intensity, Halfway_Length;
  768.   VECTOR Halfway;
  769.  
  770.   Halfway.x = REye->x + Light_Source_Ray->Direction.x;
  771.   Halfway.y = REye->y + Light_Source_Ray->Direction.y;
  772.   Halfway.z = REye->z + Light_Source_Ray->Direction.z;
  773.  
  774.   VLength (Halfway_Length, Halfway);
  775.  
  776.   VDot (Cos_Angle_Of_Incidence, Halfway, *Layer_Normal);
  777.  
  778.   if (Cos_Angle_Of_Incidence <= 0.0)
  779.     return;
  780.   else
  781.     Cos_Angle_Of_Incidence /= Halfway_Length;
  782.  
  783.   if (Finish->Roughness != 1.0)
  784.     Intensity = Finish->Specular * pow(Cos_Angle_Of_Incidence, Finish->Roughness);
  785.   else
  786.     Intensity = Finish->Specular * Cos_Angle_Of_Incidence;
  787.  
  788.   if (Finish->Metallic_Flag)
  789.   {
  790.     Colour->Red+=Intensity*(Layer_Pigment_Colour->Red)*(Light_Colour->Red);
  791.     Colour->Green+=Intensity*(Layer_Pigment_Colour->Green)*(Light_Colour->Green);
  792.     Colour->Blue+=Intensity*(Layer_Pigment_Colour->Blue)*(Light_Colour->Blue);
  793.   }
  794.   else
  795.   {
  796.     Colour->Red+=Intensity*(Light_Colour->Red);
  797.     Colour->Green+=Intensity*(Light_Colour->Green);
  798.     Colour->Blue+=Intensity*(Light_Colour->Blue);
  799.   }
  800. }
  801. #else
  802. static void do_specular(Finish, Light_Source_Ray, REye, Layer_Normal, Colour, Light_Colour, Layer_Pigment_Colour)
  803. FINISH *Finish;
  804. RAY *Light_Source_Ray;
  805. VECTOR *Layer_Normal, *REye;
  806. COLOUR *Colour, *Light_Colour, *Layer_Pigment_Colour;
  807.   {
  808.   DBL Cos_Angle_Of_Incidence, Normal_Length, Intensity, Halfway_Length;
  809.   VECTOR Halfway;
  810.  
  811.   VHalf (Halfway, *REye, Light_Source_Ray->Direction);
  812.   VLength (Normal_Length, *Layer_Normal);
  813.   VLength (Halfway_Length, Halfway);
  814.   VDot (Cos_Angle_Of_Incidence, Halfway, *Layer_Normal);
  815.  
  816.   if (Normal_Length == 0.0 || Halfway_Length == 0.0)
  817.     Cos_Angle_Of_Incidence = 0.0;
  818.   else
  819.     Cos_Angle_Of_Incidence /= (Normal_Length * Halfway_Length);
  820.  
  821.   if (Cos_Angle_Of_Incidence < 0.0)
  822.     Cos_Angle_Of_Incidence = 0.0;
  823.  
  824.  
  825.   if (Finish->Roughness != 1.0)
  826.     Intensity = pow(Cos_Angle_Of_Incidence, Finish->Roughness);
  827.   else
  828.     Intensity = Cos_Angle_Of_Incidence;
  829.  
  830.   Intensity *= Finish->Specular;
  831.   if (Finish->Metallic_Flag) 
  832.     {
  833.     Colour->Red+=Intensity*(Layer_Pigment_Colour->Red)*(Light_Colour->Red);    
  834.     Colour->Green+=Intensity*(Layer_Pigment_Colour->Green)*(Light_Colour->Green);
  835.     Colour->Blue+=Intensity*(Layer_Pigment_Colour->Blue)*(Light_Colour->Blue);  
  836.     }
  837.   else 
  838.     {
  839.     Colour->Red+=Intensity*(Light_Colour->Red);
  840.     Colour->Green+=Intensity*(Light_Colour->Green);
  841.     Colour->Blue+=Intensity*(Light_Colour->Blue);
  842.     }
  843.   }
  844. #endif
  845.  
  846. static void do_diffuse(Finish, Light_Source_Ray, Layer_Normal, Colour, Light_Colour, Layer_Pigment_Colour, Attenuation)
  847. FINISH *Finish;
  848. RAY *Light_Source_Ray;
  849. VECTOR *Layer_Normal;
  850. COLOUR *Colour, *Light_Colour, *Layer_Pigment_Colour;
  851. DBL Attenuation;
  852.   {
  853.   DBL Cos_Angle_Of_Incidence, Intensity;
  854.  
  855.   VDot (Cos_Angle_Of_Incidence, *Layer_Normal, Light_Source_Ray->Direction);
  856.   if (Cos_Angle_Of_Incidence < 0.0)
  857.     Cos_Angle_Of_Incidence = -Cos_Angle_Of_Incidence;
  858.  
  859.   if (Finish->Brilliance != 1.0)
  860.     Intensity = pow(Cos_Angle_Of_Incidence, Finish->Brilliance);
  861.   else
  862.     Intensity = Cos_Angle_Of_Incidence;
  863.  
  864.   Intensity *= Finish->Diffuse * Attenuation;
  865.  
  866.   if (Finish->Crand > 0.0)
  867.     Intensity -= ((rand()&0x7FFF)/(DBL) 0x7FFF) * Finish->Crand;
  868.  
  869.   Colour->Red += Intensity * (Layer_Pigment_Colour->Red) * (Light_Colour->Red);
  870.   Colour->Green += Intensity * (Layer_Pigment_Colour->Green) * (Light_Colour->Green);
  871.   Colour->Blue += Intensity * (Layer_Pigment_Colour->Blue) * (Light_Colour->Blue);
  872.   return;
  873.   }
  874.  
  875. /* Given a 3d point and a pigment, accumulate colour from that layer */
  876. /* Formerly called "Colour_At" */
  877. void Add_Pigment (Colour, Pigment, IPoint)
  878. COLOUR *Colour;
  879. PIGMENT *Pigment;
  880. VECTOR *IPoint;
  881.   {
  882.   register DBL x, y, z;
  883.   VECTOR TPoint,PTurbulence;
  884.  
  885.   if (Pigment->Trans != NULL) 
  886.     MInvTransPoint (&TPoint, IPoint, Pigment->Trans);
  887.   else 
  888.     TPoint = *IPoint;
  889.  
  890.   x = TPoint.x;
  891.   y = TPoint.y;
  892.   z = TPoint.z;
  893.   if(Pigment->Type != WOOD_PIGMENT &&
  894.     Pigment->Type != MARBLE_PIGMENT &&
  895.     Pigment->Type != NO_PIGMENT &&
  896.     Pigment->Type != COLOUR_PIGMENT &&
  897.     /*      Pigment->Type != SPOTTED_PIGMENT && */ /*maybe?*/
  898.     Pigment->Flags & HAS_TURB)
  899.     {
  900.     DTurbulence (&PTurbulence, x, y, z,
  901.       Pigment->omega,Pigment->lambda,Pigment->Octaves);
  902.     x += PTurbulence.x * Pigment->Turbulence.x;
  903.     y += PTurbulence.y * Pigment->Turbulence.y;
  904.     z += PTurbulence.z * Pigment->Turbulence.z;
  905.     }
  906.  
  907.  
  908.   if (x > COORDINATE_LIMIT)
  909.     x = COORDINATE_LIMIT;
  910.   else
  911.     if (x < -COORDINATE_LIMIT)
  912.       x = -COORDINATE_LIMIT;
  913.  
  914.   if (y > COORDINATE_LIMIT)
  915.     y = COORDINATE_LIMIT;
  916.   else
  917.     if (y < -COORDINATE_LIMIT)
  918.       y = -COORDINATE_LIMIT;
  919.  
  920.   if (z > COORDINATE_LIMIT)
  921.     z = COORDINATE_LIMIT;
  922.   else
  923.     if (z < -COORDINATE_LIMIT)
  924.       z = -COORDINATE_LIMIT;
  925.  
  926.   switch (Pigment->Type) 
  927.   {
  928.   case NO_PIGMENT:
  929.     /* No colouring pigment has been specified - make it black. */
  930.     Make_Colour (Colour, 0.0, 0.0, 0.0);
  931.     Colour -> Filter  = 0.0;
  932.     break;
  933.  
  934.   case COLOUR_PIGMENT:
  935.     Colour -> Red += Pigment->Colour1->Red;
  936.     Colour -> Green += Pigment->Colour1->Green;
  937.     Colour -> Blue += Pigment->Colour1->Blue;
  938.     Colour -> Filter += Pigment->Colour1->Filter;
  939.     break;
  940.  
  941.   case BOZO_PIGMENT:
  942.     bozo (x, y, z, Pigment, Colour);
  943.     break;
  944.  
  945.   case MARBLE_PIGMENT:
  946.     marble (x, y, z, Pigment, Colour);
  947.     break;
  948.  
  949.   case WOOD_PIGMENT:
  950.     wood (x, y, z, Pigment, Colour);
  951.     break;
  952.  
  953.   case CHECKER_PIGMENT:
  954.     checker (x, y, z, Pigment, Colour);
  955.     break;
  956.  
  957.   case SPOTTED_PIGMENT:
  958.     spotted (x, y, z, Pigment, Colour);
  959.     break;
  960.  
  961.   case AGATE_PIGMENT:
  962.     agate (x, y, z, Pigment, Colour);
  963.     break;
  964.  
  965.   case GRANITE_PIGMENT:
  966.     granite (x, y, z, Pigment, Colour);
  967.     break;
  968.  
  969.   case GRADIENT_PIGMENT:
  970.     gradient (x, y, z, Pigment, Colour);
  971.     break;
  972.  
  973.   case HEXAGON_PIGMENT:
  974.     hexagon (x, y, z, Pigment, Colour);
  975.     break;
  976.  
  977.   case RADIAL_PIGMENT:
  978.     radial (x, y, z, Pigment, Colour);
  979.     break;
  980.  
  981.   case MANDEL_PIGMENT:
  982.     mandel (x, y, z, Pigment, Colour);
  983.     break;
  984.  
  985.   case IMAGE_MAP_PIGMENT:
  986.     image_map (x, y, z, Pigment, Colour);
  987.     break;
  988.  
  989.   case ONION_PIGMENT:
  990.     onion (x, y, z, Pigment, Colour);
  991.     break;
  992.  
  993.   case LEOPARD_PIGMENT:
  994.     leopard (x, y, z, Pigment, Colour);
  995.     break;
  996.  
  997.   case PAINTED1_PIGMENT:
  998.     painted1 (x, y, z, Pigment, Colour);
  999.     break;
  1000.  
  1001.   case PAINTED2_PIGMENT:
  1002.     painted2 (x, y, z, Pigment, Colour);
  1003.     break;
  1004.  
  1005.   case PAINTED3_PIGMENT:
  1006.     painted3 (x, y, z, Pigment, Colour);
  1007.     break;
  1008.   }
  1009.   }
  1010.  
  1011.  
  1012. void Perturb_Normal(Layer_Normal, Tnormal, IPoint)
  1013. VECTOR *Layer_Normal, *IPoint;
  1014. TNORMAL *Tnormal;
  1015.   {
  1016.   register DBL x, y, z;
  1017.   VECTOR TPoint,NTurbulence;
  1018.  
  1019.   if (Tnormal->Trans != NULL) 
  1020.     MInvTransPoint (&TPoint, IPoint, Tnormal->Trans);
  1021.   else 
  1022.     TPoint = *IPoint;
  1023.  
  1024.   x = TPoint.x;
  1025.   y = TPoint.y;
  1026.   z = TPoint.z;
  1027.  
  1028.   if(Tnormal->Flags & HAS_TURB)
  1029.     {
  1030.     DTurbulence (&NTurbulence, x, y, z,
  1031.       Tnormal->omega,Tnormal->lambda,Tnormal->Octaves);
  1032.     x += NTurbulence.x * Tnormal->Turbulence.x;
  1033.     y += NTurbulence.y * Tnormal->Turbulence.y;
  1034.     z += NTurbulence.z * Tnormal->Turbulence.z;
  1035.     }
  1036.  
  1037.  
  1038.   switch (Tnormal->Type) 
  1039.   {
  1040.  
  1041.   case WAVES: 
  1042.     waves (x, y, z, Tnormal, Layer_Normal);
  1043.     break;
  1044.  
  1045.   case RIPPLES: 
  1046.     ripples (x, y, z, Tnormal, Layer_Normal);
  1047.     break;
  1048.  
  1049.   case WRINKLES: 
  1050.     wrinkles (x, y, z, Tnormal, Layer_Normal);
  1051.     break;
  1052.  
  1053.   case BUMPS: 
  1054.     bumps (x, y, z, Tnormal, Layer_Normal);
  1055.     break;
  1056.  
  1057.   case DENTS: 
  1058.     dents (x, y, z, Tnormal, Layer_Normal);
  1059.     break; 
  1060.  
  1061.   case BUMPY1: 
  1062.     bumpy1 (x, y, z, Tnormal, Layer_Normal);
  1063.     break;
  1064.  
  1065.   case BUMPY2: 
  1066.     bumpy2 (x, y, z, Tnormal, Layer_Normal);
  1067.     break;
  1068.  
  1069.   case BUMPY3: 
  1070.     bumpy3 (x, y, z, Tnormal, Layer_Normal);
  1071.     break;
  1072.  
  1073.   case BUMP_MAP: 
  1074.     bump_map (x, y, z, Tnormal, Layer_Normal);
  1075.     break;
  1076.   }
  1077.   return;
  1078.   }
  1079.  
  1080. void Diffuse (Finish, IPoint, Eye, Layer_Normal, Layer_Pigment_Colour, Colour, Attenuation, Object)
  1081. FINISH *Finish;
  1082. VECTOR *IPoint, *Layer_Normal;
  1083. COLOUR *Layer_Pigment_Colour;
  1084. COLOUR *Colour;
  1085. RAY    *Eye;
  1086. DBL    Attenuation;
  1087. OBJECT *Object;
  1088.   {
  1089.   DBL Light_Source_Depth, Cos_Shadow_Angle;
  1090.   RAY Light_Source_Ray;
  1091.   LIGHT_SOURCE *Light_Source;
  1092.   VECTOR REye;
  1093.   COLOUR Light_Colour;
  1094.  
  1095.   if ((Finish->Diffuse == 0.0) && (Finish->Specular == 0.0) && (Finish->Phong == 0.0))
  1096.     return;
  1097.  
  1098.   if (Finish->Specular != 0.0)
  1099.     {
  1100.     REye.x = -Eye->Direction.x;
  1101.     REye.y = -Eye->Direction.y;
  1102.     REye.z = -Eye->Direction.z;
  1103.     }
  1104.  
  1105.   for (Light_Source = Frame.Light_Sources ; 
  1106.   Light_Source != NULL;
  1107.   Light_Source = Light_Source->Next_Light_Source)
  1108.     {
  1109.     /* Get a colour and a ray */
  1110.  
  1111.     do_light(Light_Source,       &Light_Source_Depth, 
  1112.       &Light_Source_Ray,  IPoint,
  1113.       &Light_Colour);
  1114.  
  1115.     /* Don't calculate spotlights when outside of the light's cone */
  1116.     if (fabs(Light_Colour.Red) < BLACK_LEVEL && 
  1117.       fabs(Light_Colour.Green) < BLACK_LEVEL && 
  1118.       fabs(Light_Colour.Blue) < BLACK_LEVEL)
  1119.       continue;
  1120.  
  1121.     /* See if light on far side of surface from camera. */
  1122.  
  1123.     if (!(Object->Type & DOUBLE_ILLUMINATE))
  1124.       {
  1125.        VDot(Cos_Shadow_Angle,*Layer_Normal,Light_Source_Ray.Direction);
  1126.        if (Cos_Shadow_Angle < 0.0)
  1127.          continue;
  1128.       }
  1129.  
  1130.     /* If light source was not blocked by any intervening object, then
  1131.       calculate it's contribution to the object's overall illumination */
  1132.  
  1133.     Shadow_Test_Flag = TRUE;
  1134.     if (Quality_Flags & Q_SHADOW)
  1135.       {
  1136.       if ((Light_Source->Area_Light) && (Quality_Flags & Q_AREA_LIGHT))
  1137.         Block_Area_Light (Light_Source, Light_Source_Depth,
  1138.           &Light_Source_Ray, IPoint,
  1139.           &Light_Colour, 0, 0, 0, 0, 0);
  1140.       else
  1141. #ifdef DB_CODE
  1142.     /* Changes necessary for the light buffer. */
  1143.     if (Extended_Options & USE_LIGHT_BUFFER)
  1144.           Block_Point_Light_Light_Buffer (Light_Source, Light_Source_Depth, &Light_Source_Ray, &Light_Colour);
  1145.         else
  1146.           Block_Point_Light (Light_Source, Light_Source_Depth, &Light_Source_Ray, &Light_Colour);
  1147. #else
  1148.         Block_Point_Light (Light_Source, Light_Source_Depth, &Light_Source_Ray, &Light_Colour);
  1149. #endif
  1150.       }
  1151.     Shadow_Test_Flag = FALSE;
  1152.  
  1153.     if (fabs(Light_Colour.Red)  > BLACK_LEVEL || 
  1154.       fabs(Light_Colour.Green) > BLACK_LEVEL || 
  1155.       fabs(Light_Colour.Blue) > BLACK_LEVEL) 
  1156.       {
  1157.       if (Finish->Phong > 0.0) 
  1158.         do_phong(Finish,&Light_Source_Ray,&Eye->Direction,Layer_Normal,Colour,&Light_Colour, Layer_Pigment_Colour);
  1159.  
  1160.       if (Finish->Specular > 0.0) 
  1161.         do_specular(Finish,&Light_Source_Ray,&REye,Layer_Normal,Colour,&Light_Colour, Layer_Pigment_Colour);
  1162.  
  1163.       if (Finish->Diffuse > 0.0)
  1164.     do_diffuse(Finish,&Light_Source_Ray,Layer_Normal,Colour,&Light_Colour,Layer_Pigment_Colour, Attenuation);
  1165.       }
  1166.     }
  1167.   return;
  1168.   }
  1169.  
  1170. #ifdef DB_CODE
  1171. /* Some things have been optimized. */
  1172. /******************************************************************************
  1173.    The test (Normal_Component < 0.0) is unnecessary!
  1174.  ******************************************************************************/
  1175. void Reflect (Reflection, IPoint, Ray, Layer_Normal, Colour)
  1176. DBL Reflection;
  1177. VECTOR *IPoint;
  1178. RAY *Ray;
  1179. VECTOR *Layer_Normal;
  1180. COLOUR *Colour;
  1181. {
  1182.   RAY New_Ray;
  1183.   COLOUR Temp_Colour;
  1184.   register DBL k; /* Normal_Component */
  1185.  
  1186.   if (Reflection != 0.0)
  1187.   {
  1188.     Reflected_Rays_Traced++;
  1189.     k = 2.0 * (Ray->Direction.x * Layer_Normal->x +
  1190.            Ray->Direction.y * Layer_Normal->y +
  1191.            Ray->Direction.z * Layer_Normal->z);
  1192.  
  1193.     New_Ray.Direction.x = Ray->Direction.x - k * Layer_Normal->x;
  1194.     New_Ray.Direction.y = Ray->Direction.y - k * Layer_Normal->y;
  1195.     New_Ray.Direction.z = Ray->Direction.z - k * Layer_Normal->z;
  1196.  
  1197.     /* ARE 08/25/91 */
  1198.  
  1199.     k = 2.0 * Small_Tolerance;
  1200.  
  1201.     New_Ray.Initial.x = IPoint->x + k * New_Ray.Direction.x;
  1202.     New_Ray.Initial.y = IPoint->y + k * New_Ray.Direction.y;
  1203.     New_Ray.Initial.z = IPoint->z + k * New_Ray.Direction.z;
  1204.  
  1205.     Copy_Ray_Containers (&New_Ray, Ray);
  1206.     Trace_Level++;
  1207.     Make_Colour (&Temp_Colour, 0.0, 0.0, 0.0);
  1208.     New_Ray.Quadric_Constants_Cached = FALSE;
  1209.     Trace (&New_Ray, &Temp_Colour);
  1210.     Trace_Level--;
  1211.  
  1212.     Colour->Red   += Temp_Colour.Red   * Reflection;
  1213.     Colour->Green += Temp_Colour.Green * Reflection;
  1214.     Colour->Blue  += Temp_Colour.Blue  * Reflection;
  1215.   }
  1216. }
  1217. #else
  1218. void Reflect (Reflection, IPoint, Ray, Layer_Normal, Colour)
  1219. DBL Reflection;
  1220. VECTOR *IPoint;
  1221. RAY *Ray;
  1222. VECTOR *Layer_Normal;
  1223. COLOUR *Colour;
  1224.   {
  1225.   RAY New_Ray;
  1226.   COLOUR Temp_Colour;
  1227.   VECTOR Local_Normal;
  1228.   VECTOR Normal_Projection;
  1229.   VECTOR Surface_Offset;
  1230.   register DBL Normal_Component;
  1231.  
  1232.   if (Reflection != 0.0)
  1233.     {
  1234.     Reflected_Rays_Traced++;
  1235.     VDot (Normal_Component, Ray -> Direction, *Layer_Normal);
  1236.     if (Normal_Component < 0.0) 
  1237.       {
  1238.       Local_Normal = *Layer_Normal;
  1239.       Normal_Component *= -1.0;
  1240.       }
  1241.     else
  1242.       VScale (Local_Normal, *Layer_Normal, -1.0);
  1243.  
  1244.     VScale (Normal_Projection, Local_Normal, Normal_Component);
  1245.     VScale (Normal_Projection, Normal_Projection, 2.0);
  1246.     VAdd (New_Ray.Direction, Ray -> Direction, Normal_Projection);
  1247.     New_Ray.Initial = *IPoint;
  1248.  
  1249.     /* ARE 08/25/91 */
  1250.  
  1251.     VScale(Surface_Offset, New_Ray.Direction, 2.0 * Small_Tolerance); 
  1252.     VAdd(New_Ray.Initial, New_Ray.Initial, Surface_Offset);           
  1253.  
  1254.     Copy_Ray_Containers (&New_Ray, Ray);
  1255.     Trace_Level++;
  1256.     Make_Colour (&Temp_Colour, 0.0, 0.0, 0.0);
  1257.     New_Ray.Quadric_Constants_Cached = FALSE;
  1258.     Trace (&New_Ray, &Temp_Colour);
  1259.     Trace_Level--;
  1260.  
  1261.     Colour -> Red   += Temp_Colour.Red   * Reflection;
  1262.     Colour -> Green += Temp_Colour.Green * Reflection;
  1263.     Colour -> Blue  += Temp_Colour.Blue  * Reflection;
  1264.  
  1265.     }
  1266.   }
  1267. #endif
  1268.  
  1269. #ifdef DB_CODE
  1270. /* Some things have been optimized. */
  1271. /******************************************************************************
  1272.    Calculating the refracted ray using Heckbert's method guarantees  
  1273.    that it will be unit!!! (no need to normalize it)                 
  1274.  ******************************************************************************/
  1275. void Refract (Texture, IPoint, Ray, Top_Normal, Colour)
  1276. TEXTURE *Texture;
  1277. VECTOR *IPoint;
  1278. RAY *Ray;
  1279. VECTOR *Top_Normal;
  1280. COLOUR *Colour;
  1281. {
  1282.   RAY New_Ray;
  1283.   COLOUR Temp_Colour;
  1284.   VECTOR Local_Normal;
  1285.   register DBL Normal_Component, Temp_IOR;
  1286.   DBL temp, ior;
  1287.   /*   int inside; */
  1288.  
  1289.   if (Top_Normal == NULL)
  1290.   {
  1291.     New_Ray.Initial = *IPoint;
  1292.     New_Ray.Direction = Ray->Direction;
  1293.  
  1294.     Copy_Ray_Containers (&New_Ray, Ray);
  1295.     Trace_Level++;
  1296.     Transmitted_Rays_Traced++;
  1297.     Make_Colour (&Temp_Colour, 0.0, 0.0, 0.0);
  1298.     New_Ray.Quadric_Constants_Cached = FALSE;
  1299.     Trace (&New_Ray, &Temp_Colour);
  1300.     Trace_Level--;
  1301.     Colour->Red   += Temp_Colour.Red;
  1302.     Colour->Green += Temp_Colour.Green;
  1303.     Colour->Blue  += Temp_Colour.Blue;
  1304.   }
  1305.   else
  1306.   {
  1307.     Refracted_Rays_Traced++;
  1308.     Normal_Component = Ray->Direction.x * Top_Normal->x +
  1309.                Ray->Direction.y * Top_Normal->y +
  1310.                Ray->Direction.z * Top_Normal->z;
  1311.  
  1312.     if (Normal_Component < 0.0)
  1313.     {
  1314.       Local_Normal = *Top_Normal;
  1315.       Normal_Component = -Normal_Component;
  1316.     }
  1317.     else
  1318.     {
  1319.       Local_Normal.x = -Top_Normal->x;
  1320.       Local_Normal.y = -Top_Normal->y;
  1321.       Local_Normal.z = -Top_Normal->z;
  1322.     }
  1323.  
  1324.     Copy_Ray_Containers (&New_Ray, Ray);
  1325.  
  1326.     if (Ray->Containing_Index == -1)
  1327.     {
  1328.       /* The ray is entering from the atmosphere */
  1329.       Ray_Enter (&New_Ray, Texture);
  1330.       ior = (Frame.Atmosphere_IOR)/(Texture->Finish->Index_Of_Refraction);
  1331.     }
  1332.     else
  1333.     {
  1334.       /* The ray is currently inside an object */
  1335.       if (New_Ray.Containing_Textures[New_Ray.Containing_Index] == Texture)
  1336.       {
  1337.     /* The ray is leaving the current object */
  1338.     Ray_Exit (&New_Ray);
  1339.     if (New_Ray.Containing_Index == -1)
  1340.       /* The ray is leaving into the atmosphere */
  1341.       Temp_IOR = Frame.Atmosphere_IOR;
  1342.     else
  1343.       /* The ray is leaving into another object */
  1344.       Temp_IOR = New_Ray.Containing_IORs[New_Ray.Containing_Index];
  1345.  
  1346.     ior = (Texture->Finish->Index_Of_Refraction)/Temp_IOR;
  1347.       }
  1348.       else
  1349.       {
  1350.     /* The ray is entering a new object */
  1351.     Temp_IOR = New_Ray.Containing_IORs[New_Ray.Containing_Index];
  1352.     Ray_Enter (&New_Ray, Texture);
  1353.  
  1354.     ior =  Temp_IOR / (Texture->Finish->Index_Of_Refraction);
  1355.       }
  1356.     }
  1357.  
  1358.     temp = 1.0 + ior * ior * (Normal_Component * Normal_Component - 1.0);
  1359.     if (temp < 0.0)
  1360.     {
  1361.       /* total internal reflection */
  1362.       Reflect ((1.0 - Texture->Finish->Reflection), IPoint,
  1363.     Ray, Top_Normal, Colour);
  1364.       return;
  1365.     }
  1366.  
  1367.     temp = ior*Normal_Component - sqrt(temp);
  1368.     New_Ray.Direction.x = ior * Ray->Direction.x + temp * Local_Normal.x;
  1369.     New_Ray.Direction.y = ior * Ray->Direction.y + temp * Local_Normal.y;
  1370.     New_Ray.Direction.z = ior * Ray->Direction.z + temp * Local_Normal.z;
  1371.  
  1372.     New_Ray.Initial = *IPoint;
  1373.     Trace_Level++;
  1374.     Make_Colour (&Temp_Colour, 0.0, 0.0, 0.0);
  1375.     New_Ray.Quadric_Constants_Cached = FALSE;
  1376.  
  1377.     Trace (&New_Ray, &Temp_Colour);
  1378.     Trace_Level--;
  1379.  
  1380.     Colour->Red   += Temp_Colour.Red * Texture->Finish->Refraction;
  1381.     Colour->Green += Temp_Colour.Green * Texture->Finish->Refraction;
  1382.     Colour->Blue  += Temp_Colour.Blue * Texture->Finish->Refraction;
  1383.   }
  1384. }
  1385. #else
  1386. void Refract (Texture, IPoint, Ray, Top_Normal, Colour)
  1387. TEXTURE *Texture;
  1388. VECTOR *IPoint;
  1389. RAY *Ray;
  1390. VECTOR *Top_Normal;
  1391. COLOUR *Colour;
  1392.   {
  1393.   RAY New_Ray;
  1394.   COLOUR Temp_Colour;
  1395.   VECTOR Local_Normal;
  1396.   VECTOR Ray_Direction;
  1397.   register DBL Normal_Component, Temp_IOR;
  1398.   DBL temp, ior;
  1399.   /*   int inside; */
  1400.  
  1401.   if (Top_Normal == NULL)
  1402.     {
  1403.     New_Ray.Initial = *IPoint;
  1404.     New_Ray.Direction = Ray->Direction;
  1405.  
  1406.     Copy_Ray_Containers (&New_Ray, Ray);
  1407.     Trace_Level++;
  1408.     Transmitted_Rays_Traced++;
  1409.     Make_Colour (&Temp_Colour, 0.0, 0.0, 0.0);
  1410.     New_Ray.Quadric_Constants_Cached = FALSE;
  1411.     Trace (&New_Ray, &Temp_Colour);
  1412.     Trace_Level--;
  1413.     (Colour -> Red) += Temp_Colour.Red;
  1414.     (Colour -> Green) += Temp_Colour.Green;
  1415.     (Colour -> Blue) += Temp_Colour.Blue;
  1416.     }
  1417.   else
  1418.     {
  1419.     Refracted_Rays_Traced++;
  1420.     VDot (Normal_Component, Ray -> Direction, *Top_Normal);
  1421.     if (Normal_Component <= 0.0)
  1422.       {
  1423.       Local_Normal.x = Top_Normal -> x;
  1424.       Local_Normal.y = Top_Normal -> y;
  1425.       Local_Normal.z = Top_Normal -> z;
  1426.       Normal_Component *= -1.0;
  1427.       /*     inside = FALSE;*/
  1428.       }
  1429.     else
  1430.       {
  1431.       VScale (Local_Normal, *Top_Normal, -1.0);
  1432.       /*     inside = TRUE;*/
  1433.       }
  1434.  
  1435.  
  1436.     Copy_Ray_Containers (&New_Ray, Ray);
  1437.  
  1438.     if (Ray -> Containing_Index == -1)
  1439.       {
  1440.       /* The ray is entering from the atmosphere */
  1441.       Ray_Enter (&New_Ray, Texture);
  1442.       ior = (Frame.Atmosphere_IOR)/(Texture->Finish->Index_Of_Refraction);
  1443.       }
  1444. else
  1445.   {
  1446.   /* The ray is currently inside an object */
  1447.   if (New_Ray.Containing_Textures [New_Ray.Containing_Index] == Texture) 
  1448.     /*         if (inside) */
  1449.     {
  1450.     /* The ray is leaving the current object */
  1451.     Ray_Exit (&New_Ray);
  1452.     if (New_Ray.Containing_Index == -1)
  1453.       /* The ray is leaving into the atmosphere */
  1454.     Temp_IOR = Frame.Atmosphere_IOR;
  1455.     else
  1456.       /* The ray is leaving into another object */
  1457.       Temp_IOR = New_Ray.Containing_IORs [New_Ray.Containing_Index];
  1458.  
  1459.     ior =  (Texture->Finish->Index_Of_Refraction)/Temp_IOR;
  1460.     }
  1461.     else
  1462.       {
  1463.       /* The ray is entering a new object */
  1464.       Temp_IOR = New_Ray.Containing_IORs [New_Ray.Containing_Index];
  1465.       Ray_Enter (&New_Ray, Texture);
  1466.  
  1467.       ior =  Temp_IOR / (Texture->Finish->Index_Of_Refraction);
  1468.       }
  1469.     }
  1470.  
  1471.   temp = 1.0 + ior * ior * (Normal_Component * Normal_Component - 1.0);
  1472.   if (temp < 0.0) 
  1473.       {
  1474.     Reflect ((1.0 - Texture->Finish->Reflection), IPoint, 
  1475.     Ray, Top_Normal, Colour);
  1476.     return;
  1477.     }
  1478.  
  1479.   temp = ior*Normal_Component - sqrt(temp);
  1480.   VScale (Local_Normal, Local_Normal, temp);
  1481.   VScale (Ray_Direction, Ray->Direction, ior);
  1482.   VAdd (New_Ray.Direction, Local_Normal, Ray_Direction);
  1483.   VNormalize (New_Ray.Direction, New_Ray.Direction);
  1484.  
  1485.   New_Ray.Initial = *IPoint;
  1486.   Trace_Level++;
  1487.   Make_Colour (&Temp_Colour, 0.0, 0.0, 0.0);
  1488.   New_Ray.Quadric_Constants_Cached = FALSE;
  1489.  
  1490.   Trace (&New_Ray, &Temp_Colour);
  1491.   Trace_Level--;
  1492.  
  1493.   (Colour -> Red) += (Temp_Colour.Red)
  1494.     * (Texture -> Finish->Refraction);
  1495.   (Colour -> Green) += (Temp_Colour.Green)
  1496.     * (Texture -> Finish->Refraction);
  1497.   (Colour -> Blue) += (Temp_Colour.Blue)
  1498.     * (Texture -> Finish->Refraction);
  1499.   }
  1500. }
  1501. #endif
  1502.  
  1503. void Fog (Distance, Fog_Colour, Fog_Distance, Colour)
  1504. DBL Distance, Fog_Distance;
  1505. COLOUR *Fog_Colour, *Colour;
  1506.   {
  1507.   DBL Fog_Factor, Fog_Factor_Inverse;
  1508.  
  1509.   Fog_Factor = exp(-1.0 * Distance/Fog_Distance);
  1510.   Fog_Factor_Inverse = 1.0 - Fog_Factor;
  1511.   Colour->Red = Colour->Red*Fog_Factor + Fog_Colour->Red*Fog_Factor_Inverse;
  1512.   Colour->Green = Colour->Green*Fog_Factor + Fog_Colour->Green*Fog_Factor_Inverse;
  1513.   Colour->Blue = Colour->Blue*Fog_Factor + Fog_Colour->Blue*Fog_Factor_Inverse;
  1514.   }
  1515.  
  1516. void Compute_Reflected_Colour (Ray, Finish, Ray_Intersection, Layer_Pigment_Colour, Filter_Colour, Colour, Layer_Normal)
  1517. RAY *Ray;
  1518. FINISH *Finish;
  1519. INTERSECTION *Ray_Intersection;
  1520. COLOUR *Layer_Pigment_Colour;
  1521. COLOUR *Filter_Colour;
  1522. COLOUR *Colour;
  1523. VECTOR *Layer_Normal;
  1524.   {
  1525.   DBL Attenuation, Ambient;
  1526.   COLOUR Emitted_Colour;
  1527.  
  1528.   /* This variable keeps track of how much colour comes from the surface
  1529.       of the object and how much is transmited through. */
  1530.   Make_Colour (&Emitted_Colour, 0.0, 0.0, 0.0);
  1531.  
  1532.   if (Quality_Flags & Q_FULL_AMBIENT) 
  1533.     {
  1534.     Layer_Pigment_Colour->Filter = 0.0;
  1535.  
  1536.     Colour->Red   += Layer_Pigment_Colour->Red * Filter_Colour->Filter;
  1537.     Colour->Green += Layer_Pigment_Colour->Green * Filter_Colour->Filter;
  1538.     Colour->Blue  += Layer_Pigment_Colour->Blue * Filter_Colour->Filter;
  1539.     return;
  1540.     }
  1541.  
  1542.   Attenuation = Filter_Colour->Filter * (1.0 - Layer_Pigment_Colour->Filter);
  1543.  
  1544.   if ((Ambient = Finish->Ambient*Attenuation) != 0.0)
  1545.     {
  1546.     Emitted_Colour.Red += Layer_Pigment_Colour->Red * Ambient;
  1547.     Emitted_Colour.Green += Layer_Pigment_Colour->Green * Ambient;
  1548.     Emitted_Colour.Blue += Layer_Pigment_Colour->Blue * Ambient;
  1549.     }
  1550.  
  1551.   Diffuse (Finish, &Ray_Intersection->IPoint, Ray,
  1552.     Layer_Normal, Layer_Pigment_Colour, &Emitted_Colour, Attenuation, 
  1553.     Ray_Intersection->Object);
  1554.  
  1555.   Colour->Red   += Emitted_Colour.Red;
  1556.   Colour->Green += Emitted_Colour.Green;
  1557.   Colour->Blue  += Emitted_Colour.Blue;
  1558.  
  1559.   if (Quality_Flags & Q_REFLECT)
  1560.     Reflect (Finish->Reflection, &Ray_Intersection -> IPoint, Ray,
  1561.       Layer_Normal, Colour);
  1562.   }
  1563.  
  1564. /* Given an intersection point, a ray, & a shadow flag, add that point's
  1565.   color to the given colour and return it. */
  1566.  
  1567. void Determine_Apparent_Colour (Ray_Intersection, Colour, Ray)
  1568. INTERSECTION *Ray_Intersection;
  1569. COLOUR *Colour;
  1570. RAY *Ray;
  1571.   {
  1572.   COLOUR Layer_Pigment_Colour, Refracted_Colour, Filter_Colour;
  1573.   TEXTURE *Layer, *Texture;
  1574.   FINISH *Finish;
  1575.   VECTOR Layer_Normal, Raw_Normal, Top_Normal;
  1576.   DBL Normal_Direction;
  1577.   int layer_number;
  1578.  
  1579. #define QColour Texture->Pigment->Quick_Colour
  1580.  
  1581.   /* Get the normal to the surface */
  1582.   if (Ray_Intersection->NFlag)
  1583.      Raw_Normal = Ray_Intersection->INormal;
  1584.   else
  1585.      Normal (&Raw_Normal, Ray_Intersection->Object, &Ray_Intersection->IPoint);
  1586.  
  1587.   /* Now, we perform the lighting calculations. */
  1588.  
  1589.   /* We assume here that Post_Process has propagated all parent
  1590.    textures to the object itself and that everything has some texture.
  1591.    Redirrect to the proper texture if its a material or checker texture */
  1592.  
  1593.   for (Texture = Ray_Intersection->Object->Texture;
  1594.   Texture->Type != PNF_TEXTURE;)
  1595.     switch (Texture->Type)
  1596.     {
  1597.     case TILE_TEXTURE:
  1598.       Texture = tiles_texture(&Ray_Intersection->IPoint,((TILES *)Texture));
  1599.       break;
  1600.     case MAT_TEXTURE:
  1601.       Texture = material_map(&Ray_Intersection->IPoint,((MATERIAL *)Texture));
  1602.       break;
  1603.     default:
  1604.       fprintf(stderr, "Bad texture type: %d\n", Texture->Type);
  1605.       close_all(); 
  1606.       exit(1);
  1607.     };
  1608.  
  1609.   Make_ColourA (&Filter_Colour, 1.0, 1.0, 1.0, 1.0);
  1610.   for (layer_number=1 , Layer = Texture;
  1611.   (Layer != NULL) && (fabs(Filter_Colour.Filter) > BLACK_LEVEL);
  1612.   layer_number++, Layer = Layer->Next_Layer)
  1613.     {
  1614.     Make_Colour (&Layer_Pigment_Colour, 0.0, 0.0, 0.0);
  1615.     if (Quality_Flags & Q_QUICKC)
  1616.       Layer_Pigment_Colour = QColour;
  1617.     else
  1618.       Add_Pigment (&Layer_Pigment_Colour, Layer->Pigment, &Ray_Intersection->IPoint);
  1619.  
  1620.     Layer_Normal = Raw_Normal;
  1621.     if ((Quality_Flags & Q_NORMAL) && (Texture->Tnormal != NULL))
  1622.       Perturb_Normal (&Layer_Normal, Texture->Tnormal,
  1623.         &Ray_Intersection->IPoint);
  1624.  
  1625.     /* If the surface normal points away, flip its direction. */
  1626.     VDot (Normal_Direction, Layer_Normal, Ray->Direction);
  1627.     if (Normal_Direction > 0.0) 
  1628.       {
  1629. #ifdef DB_CODE
  1630.       /* Some things have been optimized. */
  1631.       Layer_Normal.x = -Layer_Normal.x;
  1632.       Layer_Normal.y = -Layer_Normal.y;
  1633.       Layer_Normal.z = -Layer_Normal.z;
  1634. #else
  1635.       VScaleEq (Layer_Normal, -1.0);
  1636. #endif
  1637.       }
  1638.     if (layer_number == 1)
  1639.       Top_Normal = Layer_Normal;
  1640.  
  1641.     Compute_Reflected_Colour (Ray,
  1642.       Layer->Finish,
  1643.       Ray_Intersection,
  1644.       &Layer_Pigment_Colour,
  1645.       &Filter_Colour,
  1646.       Colour, &Layer_Normal);
  1647.  
  1648.     Filter_Colour.Red   *= Layer_Pigment_Colour.Red;
  1649.     Filter_Colour.Green *= Layer_Pigment_Colour.Green;
  1650.     Filter_Colour.Blue  *= Layer_Pigment_Colour.Blue;
  1651.     Filter_Colour.Filter *= Layer_Pigment_Colour.Filter;
  1652.     }
  1653.  
  1654.   Finish = Texture->Finish;
  1655.  
  1656.   if ((fabs(Filter_Colour.Filter) > BLACK_LEVEL) && (Quality_Flags & Q_REFRACT))
  1657.     {
  1658.     Make_Colour (&Refracted_Colour, 0.0, 0.0, 0.0);
  1659.  
  1660.     if (Finish->Refraction > 0.0)
  1661.       Refract (Texture, &Ray_Intersection -> IPoint, Ray,
  1662.     &Top_Normal, &Refracted_Colour);
  1663.     else
  1664.       Refract (Texture, &Ray_Intersection->IPoint, Ray,
  1665.     NULL, &Refracted_Colour);
  1666.  
  1667.     Colour->Red += Filter_Colour.Red * Refracted_Colour.Red * Filter_Colour.Filter;
  1668.     Colour->Green += Filter_Colour.Green * Refracted_Colour.Green * Filter_Colour.Filter;
  1669.     Colour->Blue += Filter_Colour.Blue * Refracted_Colour.Blue * Filter_Colour.Filter;
  1670.     }
  1671.  
  1672.   if (Frame.Fog_Distance != 0.0)
  1673.     Fog (Ray_Intersection->Depth, &Frame.Fog_Colour, Frame.Fog_Distance,
  1674.       Colour);
  1675.   }
  1676.  
  1677. void Filter_Shadow_Ray (Ray_Intersection, Colour)
  1678. INTERSECTION *Ray_Intersection;
  1679. COLOUR *Colour;
  1680.   {
  1681.   COLOUR Layer_Pigment_Colour, Filter_Colour;
  1682.   TEXTURE *Layer, *Texture;
  1683.   FINISH *Finish;
  1684.   int layer_number;
  1685.  
  1686. #define QColour Texture->Pigment->Quick_Colour
  1687.  
  1688.   if (!(Quality_Flags & Q_SHADOW))
  1689.     return;
  1690.  
  1691.   /* Now, we perform the lighting calculations. */
  1692.  
  1693.   /* We assume here that Post_Process has propagated all parent
  1694.    textures to the object itself and that everything has some texture.
  1695.    Redirrect to the proper texture if its a material or checker texture */
  1696.  
  1697.   for (Texture = Ray_Intersection->Object->Texture;
  1698.   Texture->Type != PNF_TEXTURE;)
  1699.     switch (Texture->Type)
  1700.     {
  1701.     case TILE_TEXTURE:
  1702.       Texture = tiles_texture(&Ray_Intersection->IPoint,((TILES *)Texture));
  1703.       break;
  1704.     case MAT_TEXTURE:
  1705.       Texture = material_map(&Ray_Intersection->IPoint,((MATERIAL *)Texture));
  1706.       break;
  1707.     default:
  1708.       fprintf(stderr, "Bad texture type: %d\n", Texture->Type);
  1709.       close_all(); 
  1710.       exit(1);
  1711.     };
  1712.  
  1713.   Make_ColourA (&Filter_Colour, 1.0, 1.0, 1.0, 1.0);
  1714.   for (layer_number=1 , Layer = Texture;
  1715.   (Layer != NULL) && (fabs(Filter_Colour.Filter) > BLACK_LEVEL);
  1716.   layer_number++, Layer = Layer->Next_Layer)
  1717.     {
  1718.     if (Quality_Flags & Q_QUICKC)
  1719.       Layer_Pigment_Colour = QColour;
  1720.     else
  1721.       {
  1722.       Make_Colour (&Layer_Pigment_Colour, 0.0, 0.0, 0.0);
  1723.       Add_Pigment (&Layer_Pigment_Colour, Layer->Pigment, &Ray_Intersection->IPoint);
  1724.       }
  1725.  
  1726.     Filter_Colour.Red   *= Layer_Pigment_Colour.Red;
  1727.     Filter_Colour.Green *= Layer_Pigment_Colour.Green;
  1728.     Filter_Colour.Blue  *= Layer_Pigment_Colour.Blue;
  1729.     Filter_Colour.Filter *= Layer_Pigment_Colour.Filter;
  1730.     }
  1731.  
  1732.   Finish = Texture->Finish;
  1733.  
  1734.   /* For shadow rays, we have the filter colour now - time to return */
  1735.   if (fabs(Filter_Colour.Filter) < BLACK_LEVEL) 
  1736.     {
  1737.     Make_Colour (Colour, 0.0, 0.0, 0.0);
  1738.     return;
  1739.     }
  1740.  
  1741.   if (Finish->Refraction > 0.0) 
  1742.     {
  1743.     Colour->Red *= Filter_Colour.Red * Finish->Refraction * Filter_Colour.Filter;
  1744.     Colour->Green *= Filter_Colour.Green * Finish->Refraction * Filter_Colour.Filter;
  1745.     Colour->Blue *= Filter_Colour.Blue * Finish->Refraction * Filter_Colour.Filter;
  1746.     }
  1747.   else 
  1748.     {
  1749.     Colour->Red *= Filter_Colour.Red * Filter_Colour.Filter;
  1750.     Colour->Green *= Filter_Colour.Green * Filter_Colour.Filter;
  1751.     Colour->Blue *= Filter_Colour.Blue * Filter_Colour.Filter;
  1752.     }
  1753.   return;
  1754.  
  1755.   }
  1756.