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

  1. /****************************************************************************
  2. *                   render.c
  3. *
  4. *  This module implements the main raytracing loop.
  5. *
  6. *  from Persistence of Vision Raytracer
  7. *  Copyright 1992 Persistence of Vision Team
  8. *---------------------------------------------------------------------------
  9. *  Copying, distribution and legal info is in the file povlegal.doc which
  10. *  should be distributed with this file. If povlegal.doc is not available
  11. *  or for more info please contact:
  12. *
  13. *       Drew Wells [POV-Team Leader]
  14. *       CIS: 73767,1244  Internet: 73767.1244@compuserve.com
  15. *       Phone: (213) 254-4041
  16. *
  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. * 01/16/92 dfm    Added David Buck's bug fix to add a different offset
  22. *                 to x and y coordinates for each call to Rand3D() in the
  23. *                 subsampling routine.  Said to smooth the anti-aliasing.
  24. *                 Previously, each call returned the same random number,
  25. *                 hence, no true jittering.
  26. *                 I consider this an interim fix until we get a better
  27. *                 algorithm for anti-aliasing.
  28. *****************************************************************************/
  29.  
  30. #include "frame.h"
  31. #include "vector.h"
  32. #include "povproto.h"
  33.  
  34. extern FILE_HANDLE *Output_File_Handle;
  35. extern char Output_File_Name[FILE_NAME_LENGTH];
  36. extern char Input_File_Name[FILE_NAME_LENGTH];
  37. extern char Stat_File_Name[FILE_NAME_LENGTH];
  38. extern char OutputFormat, Color_Bits, PaletteOption;
  39. extern char VerboseFormat;
  40. extern unsigned int Options;
  41. extern int File_Buffer_Size;
  42. extern int Quality;
  43. volatile int Stop_Flag;
  44. extern int First_Line, Last_Line;
  45. extern long Number_Of_Pixels, Number_Of_Rays, Number_Of_Pixels_Supersampled;
  46.  
  47. extern short *hashTable;
  48. extern unsigned short crctab[256];
  49. #define rand3d(a,b) crctab[(int)(hashTable[(int)(hashTable[(int)((a)&0xfff)]^(b))&0xfff])&0xff]
  50.  
  51. FRAME Frame;
  52. RAY *VP_Ray;
  53. int Trace_Level, SuperSampleCount;
  54.  
  55. DBL Max_Trace_Level = 5;
  56. DBL maxclr;
  57.  
  58. static void check_stats PARAMS((int y));
  59. static void do_anti_aliasing PARAMS((int x, int y, COLOUR *Colour));
  60. static void output_line PARAMS((int y));
  61.  
  62. COLOUR *Previous_Line, *Current_Line;
  63. char *Previous_Line_Antialiased_Flags, *Current_Line_Antialiased_Flags;
  64. RAY Ray;
  65.  
  66. void Create_Ray (ray, width, height, x, y)
  67. RAY *ray;
  68. int width, height;
  69. DBL x, y;
  70. {
  71.    register DBL X_Scalar, Y_Scalar;
  72.    VECTOR Temp_Vect_1, Temp_Vect_2;
  73.  
  74.  
  75.    /* Convert the X Coordinate to be a DBL from 0.0 to 1.0 */
  76.    X_Scalar = (x - (DBL) width / 2.0) / (DBL) width;
  77.  
  78.    /* Convert the Y Coordinate to be a DBL from 0.0 to 1.0 */
  79.    Y_Scalar = (( (DBL)(Frame.Screen_Height - 1) - y) -
  80.       (DBL) height / 2.0) / (DBL) height;
  81.  
  82.    VScale (Temp_Vect_1, Frame.View_Point.Up, Y_Scalar);
  83.    VScale (Temp_Vect_2, Frame.View_Point.Right, X_Scalar);
  84.    VAdd (ray->Direction, Temp_Vect_1, Temp_Vect_2);
  85.    VAdd (ray->Direction, ray->Direction, Frame.View_Point.Direction);
  86.    VNormalize (ray->Direction, ray->Direction);
  87.    Initialize_Ray_Containers (ray);
  88.    ray->Quadric_Constants_Cached = FALSE;
  89. }
  90.  
  91.  
  92. void Supersample (result, x, y, Width, Height)
  93. COLOUR *result;
  94. int x, y, Width, Height;
  95. {
  96.    COLOUR colour;
  97.    register DBL dx, dy, Jitter_X, Jitter_Y;
  98.    register int Jitt_Offset;
  99.    unsigned char Red, Green, Blue;
  100.  
  101.  
  102.    dx = (DBL) x;
  103.    dy = (DBL) y;
  104.    Jitt_Offset = 10;
  105.  
  106.    Number_Of_Pixels_Supersampled++;
  107.  
  108.    Make_Colour (result, 0.0, 0.0, 0.0);
  109.  
  110.    Jitter_X = (rand3d(x+Jitt_Offset, y) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  111.    Jitter_Y = (rand3d(x+Jitt_Offset, y) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  112.    Create_Ray (VP_Ray, Frame.Screen_Width, Frame.Screen_Height,
  113.       dx + Jitter_X, dy + Jitter_Y);
  114.  
  115.    Trace_Level = 0;
  116.    Trace (VP_Ray, &colour);
  117.    Clip_Colour (&colour, &colour);
  118.    Scale_Colour (&colour, &colour, 0.11111111);
  119.    Add_Colour (result, result, &colour);
  120.    Jitt_Offset += 10;
  121.  
  122.    Jitter_X = (rand3d(x+Jitt_Offset, y+Jitt_Offset) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  123.    Jitter_Y = (rand3d(x+Jitt_Offset, y+Jitt_Offset) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  124.    Create_Ray (VP_Ray, Width, Height, dx + Jitter_X - 0.3333333,
  125.       dy + Jitter_Y - 0.3333333);
  126.    Trace_Level = 0;
  127.    Trace (VP_Ray, &colour);
  128.    Clip_Colour (&colour, &colour);
  129.    Scale_Colour (&colour, &colour, 0.11111111);
  130.    Add_Colour (result, result, &colour);
  131.    Jitt_Offset += 10;
  132.  
  133.    Jitter_X = (rand3d(x+Jitt_Offset, y+Jitt_Offset) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  134.    Jitter_Y = (rand3d(x+Jitt_Offset, y+Jitt_Offset) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  135.    Create_Ray (VP_Ray, Width, Height, dx + Jitter_X - 0.3333333,
  136.       dy + Jitter_Y);
  137.    Trace_Level = 0;
  138.    Trace (VP_Ray, &colour);
  139.    Clip_Colour (&colour, &colour);
  140.    Scale_Colour (&colour, &colour, 0.11111111);
  141.    Add_Colour (result, result, &colour);
  142.    Jitt_Offset += 10;
  143.  
  144.    Jitter_X = (rand3d(x+Jitt_Offset, y+Jitt_Offset) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  145.    Jitter_Y = (rand3d(x+Jitt_Offset, y+Jitt_Offset) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  146.    Create_Ray (VP_Ray, Width, Height, dx + Jitter_X - 0.3333333,
  147.       dy + Jitter_Y + 0.3333333);
  148.    Trace_Level = 0;
  149.    Trace (VP_Ray, &colour);
  150.    Clip_Colour (&colour, &colour);
  151.    Scale_Colour (&colour, &colour, 0.11111111);
  152.    Add_Colour (result, result, &colour);
  153.    Jitt_Offset += 10;
  154.  
  155.    Jitter_X = (rand3d(x+Jitt_Offset, y+Jitt_Offset) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  156.    Jitter_Y = (rand3d(x+Jitt_Offset, y+Jitt_Offset) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  157.    Create_Ray (VP_Ray, Width, Height, dx + Jitter_X,
  158.       dy + Jitter_Y - 0.3333333);
  159.    Trace_Level = 0;
  160.    Trace (VP_Ray, &colour);
  161.    Clip_Colour (&colour, &colour);
  162.    Scale_Colour (&colour, &colour, 0.11111111);
  163.    Add_Colour (result, result, &colour);
  164.    Jitt_Offset += 10;
  165.  
  166.    Jitter_X = (rand3d(x+Jitt_Offset, y+Jitt_Offset) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  167.    Jitter_Y = (rand3d(x+Jitt_Offset, y+Jitt_Offset) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  168.    Create_Ray (VP_Ray, Width, Height, dx + Jitter_X,
  169.       dy + Jitter_Y + 0.3333333);
  170.    Trace_Level = 0;
  171.    Trace (VP_Ray, &colour);
  172.    Clip_Colour (&colour, &colour);
  173.    Scale_Colour (&colour, &colour, 0.11111111);
  174.    Add_Colour (result, result, &colour);
  175.    Jitt_Offset += 10;
  176.  
  177.    Jitter_X = (rand3d(x+Jitt_Offset, y+Jitt_Offset) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  178.    Jitter_Y = (rand3d(x+Jitt_Offset, y+Jitt_Offset) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  179.    Create_Ray (VP_Ray, Width, Height, dx + Jitter_X + 0.3333333,
  180.       dy + Jitter_Y - 0.3333333);
  181.    Trace_Level = 0;
  182.    Trace (VP_Ray, &colour);
  183.    Clip_Colour (&colour, &colour);
  184.    Scale_Colour (&colour, &colour, 0.11111111);
  185.    Add_Colour (result, result, &colour);
  186.    Jitt_Offset += 10;
  187.  
  188.    Jitter_X = (rand3d(x+Jitt_Offset, y+Jitt_Offset) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  189.    Jitter_Y = (rand3d(x+Jitt_Offset, y+Jitt_Offset) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  190.    Create_Ray (VP_Ray, Width, Height, dx + Jitter_X + 0.3333333,
  191.       dy + Jitter_Y);
  192.    Trace_Level = 0;
  193.    Trace (VP_Ray, &colour);
  194.    Clip_Colour (&colour, &colour);
  195.    Scale_Colour (&colour, &colour, 0.11111111);
  196.    Add_Colour (result, result, &colour);
  197.    Jitt_Offset += 10;
  198.  
  199.    Jitter_X = (rand3d(x+Jitt_Offset, y+Jitt_Offset) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  200.    Jitter_Y = (rand3d(x+Jitt_Offset, y+Jitt_Offset) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  201.    Create_Ray (VP_Ray, Width, Height, dx + Jitter_X + 0.3333333,
  202.       dy + Jitter_Y + 0.3333333);
  203.    Trace_Level = 0;
  204.    Trace (VP_Ray, &colour);
  205.    Clip_Colour (&colour, &colour);
  206.    Scale_Colour (&colour, &colour, 0.11111111);
  207.    Add_Colour (result, result, &colour);
  208.  
  209.    if ((y != First_Line - 1) && (Options & DISPLAY)) {
  210.       Red = (unsigned char)(result->Red * maxclr);
  211.       Green = (unsigned char)(result->Green * maxclr);
  212.       Blue = (unsigned char)(result->Blue * maxclr);
  213.       display_plot (x, y, Red, Green, Blue);
  214.    }
  215. }
  216.  
  217. void Read_Rendered_Part()
  218. {
  219.    int rc, x, line_number;
  220.    unsigned char Red, Green, Blue;
  221.    DBL grey;
  222.  
  223.    maxclr = (DBL)(1 << Color_Bits) - 1.0;
  224.    while ((rc = Read_Line(Output_File_Handle, Previous_Line, &line_number)) == 1) {
  225.       if (Options & DISPLAY)
  226.          for (x = 0 ; x < Frame.Screen_Width ; x++) {
  227.             if (PaletteOption == GREY) {
  228.                grey = Previous_Line[x].Red * 0.287 +
  229.                Previous_Line[x].Green * 0.589 +
  230.                Previous_Line[x].Blue * 0.114;
  231.                Red = Green = Blue = (unsigned char)(grey * maxclr);
  232.             }
  233.             else {
  234.                Red = (unsigned char) (Previous_Line[x].Red * maxclr);
  235.                Green = (unsigned char) (Previous_Line[x].Green * maxclr);
  236.                Blue = (unsigned char) (Previous_Line[x].Blue * maxclr);
  237.             }
  238.             display_plot (x, line_number, Red, Green, Blue);
  239.             COOPERATE     /* Moved inside loop JLN 12/91 */
  240.             }
  241.       }
  242.  
  243.       First_Line = line_number+1;
  244.  
  245.       if (rc == 0) {
  246.          Close_File(Output_File_Handle);
  247.          if (Open_File (Output_File_Handle, Output_File_Name,
  248.             &Frame.Screen_Width, &Frame.Screen_Height, File_Buffer_Size,
  249.             APPEND_MODE) != 1) {
  250.             fprintf (stderr, "Error opening output file\n");
  251.             exit(1);
  252.          }
  253.          return;
  254.       }
  255.  
  256.       fprintf (stderr, "Error reading aborted data file\n");
  257.    }
  258.  
  259.    void Start_Tracing ()
  260.    {
  261.       COLOUR Colour;
  262.       register int x, y;
  263.       unsigned char Red, Green, Blue;
  264.       DBL grey;
  265.  
  266.       for (y = (Options & ANTIALIAS)?First_Line-1:First_Line; y<Last_Line; y++) {
  267.  
  268.          check_stats(y);
  269.  
  270.          for (x = 0 ; x < Frame.Screen_Width ; x++) {
  271.  
  272.             TEST_ABORT
  273.  
  274.             if (Stop_Flag) {
  275.                close_all();
  276.                PRINT_STATS
  277.                /* exit with error if image not completed/user abort*/
  278.                exit(2);
  279.             }
  280.  
  281.             Number_Of_Pixels++;
  282.  
  283.             Create_Ray (VP_Ray, Frame.Screen_Width, Frame.Screen_Height, (DBL) x, (DBL) y);
  284.             Trace_Level = 0;
  285.             Trace (&Ray, &Colour);
  286.             Clip_Colour (&Colour, &Colour);
  287.  
  288.             Current_Line[x] = Colour;
  289.  
  290.             if (Options & ANTIALIAS)
  291.                do_anti_aliasing(x, y, &Colour);
  292.  
  293.             if (y != First_Line-1) {
  294.                if (PaletteOption == GREY) {
  295.                   grey = Previous_Line[x].Red * 0.287 +
  296.                   Previous_Line[x].Green * 0.589 +
  297.                   Previous_Line[x].Blue * 0.114;
  298.                   Red = Green = Blue = (unsigned char)(grey * maxclr);
  299.                }
  300.                else {
  301.                   Red = (unsigned char) (Colour.Red * maxclr);
  302.                   Green = (unsigned char) (Colour.Green * maxclr);
  303.                   Blue = (unsigned char) (Colour.Blue * maxclr);
  304.                }
  305.                if (Options & DISPLAY)
  306.                   display_plot (x, y, Red, Green, Blue);
  307.             }
  308.          }
  309.          output_line(y);
  310.       }
  311.  
  312.       if (Options & DISKWRITE) {
  313.          Write_Line (Output_File_Handle, Previous_Line, Last_Line - 1);
  314.       }
  315.    }
  316.  
  317.    static void check_stats(y)
  318.       register int y;
  319.    {
  320.       FILE *stat_file;
  321.  
  322.       /* New verbose options CdW */
  323.       if (Options & VERBOSE && VerboseFormat=='0'){
  324.          printf ("POV-Ray rendering %s to %s",Input_File_Name,Output_File_Name);
  325.          if((First_Line != 0) || (Last_Line != Frame.Screen_Height))
  326.             printf(" from %4d to %4d:\n",First_Line, Last_Line);
  327.          else
  328.             printf (":\n");
  329.          printf ("Res %4d X %4d. Calc line %4d of %4d",Frame.Screen_Width, Frame.Screen_Height, (y-First_Line)+1, Last_Line-First_Line);
  330.          if (!(Options & ANTIALIAS))
  331.             printf(".");
  332.       }
  333.       if (Options & VERBOSE_FILE){
  334.          stat_file = fopen(Stat_File_Name,"w+t");
  335.          fprintf (stat_file,"Line %4d.\n", y);
  336.          fclose(stat_file);
  337.       }
  338.  
  339.       /* Use -vO for Old style verbose */
  340.       if (Options & VERBOSE && (VerboseFormat=='O')) {
  341.          printf ("Line %4d", y);
  342.       }
  343.       if (Options & VERBOSE && VerboseFormat=='1'){
  344.          fprintf (stderr,"Res %4d X %4d. Calc line %4d of %4d",Frame.Screen_Width, Frame.Screen_Height, (y-First_Line)+1, Last_Line-First_Line);
  345.          if (!(Options & ANTIALIAS))
  346.             fprintf(stderr,".");
  347.       }
  348.  
  349.       if (Options & ANTIALIAS)
  350.          SuperSampleCount = 0;
  351.    }
  352.  
  353.    static void do_anti_aliasing(x, y, Colour)
  354.       register int x, y;
  355.    COLOUR *Colour;
  356.    {
  357.       char Antialias_Center_Flag = 0;
  358.  
  359.       Current_Line_Antialiased_Flags[x] = 0;
  360.  
  361.       if (x != 0) {
  362.          if (Colour_Distance (&Current_Line[x-1], &Current_Line[x])
  363.             >= Frame.Antialias_Threshold) {
  364.             Antialias_Center_Flag = 1;
  365.             if (!(Current_Line_Antialiased_Flags[x-1])) {
  366.                Supersample (&Current_Line[x-1],
  367.                   x-1, y, Frame.Screen_Width, Frame.Screen_Height);
  368.                Current_Line_Antialiased_Flags[x-1] = 1;
  369.                SuperSampleCount++;
  370.             }
  371.          }
  372.       }
  373.  
  374.       if (y != First_Line-1) {
  375.          if (Colour_Distance (&Previous_Line[x], &Current_Line[x])
  376.             >= Frame.Antialias_Threshold) {
  377.             Antialias_Center_Flag = 1;
  378.             if (!(Previous_Line_Antialiased_Flags[x])) {
  379.                Supersample (&Previous_Line[x],
  380.                   x, y-1, Frame.Screen_Width, Frame.Screen_Height);
  381.                Previous_Line_Antialiased_Flags[x] = 1;
  382.                SuperSampleCount++;
  383.             }
  384.          }
  385.       }
  386.  
  387.       if (Antialias_Center_Flag) {
  388.          Supersample (&Current_Line[x],
  389.             x, y, Frame.Screen_Width, Frame.Screen_Height);
  390.          Current_Line_Antialiased_Flags[x] = 1;
  391.          *Colour = Current_Line[x];
  392.          SuperSampleCount++;
  393.       }
  394.  
  395.       return;
  396.    }
  397.  
  398.    void Initialize_Renderer PARAMS((void))
  399.    {
  400.       register int i;
  401.  
  402.       VP_Ray = &Ray;
  403.       maxclr = (DBL)(1 << Color_Bits) - 1.0;
  404.  
  405.       Previous_Line = (COLOUR *) malloc (sizeof (COLOUR)*(Frame.Screen_Width + 1));
  406.       Current_Line = (COLOUR *) malloc (sizeof (COLOUR)*(Frame.Screen_Width + 1));
  407.  
  408.       for (i = 0 ; i <= Frame.Screen_Width ; i++) {
  409.          Previous_Line[i].Red = 0.0;
  410.          Previous_Line[i].Green = 0.0;
  411.          Previous_Line[i].Blue = 0.0;
  412.  
  413.          Current_Line[i].Red = 0.0;
  414.          Current_Line[i].Green = 0.0;
  415.          Current_Line[i].Blue = 0.0;
  416.       }
  417.  
  418.       if (Options & ANTIALIAS) {
  419.          Previous_Line_Antialiased_Flags =
  420.          (char *) malloc (sizeof (char)*(Frame.Screen_Width + 1));
  421.          Current_Line_Antialiased_Flags =
  422.          (char *)  malloc (sizeof (char)*(Frame.Screen_Width + 1));
  423.  
  424.          for (i = 0 ; i <= Frame.Screen_Width ; i++) {
  425.             (Previous_Line_Antialiased_Flags)[i] = 0;
  426.             (Current_Line_Antialiased_Flags)[i] = 0;
  427.          }
  428.       }
  429.  
  430.       Ray.Initial = Frame.View_Point.Location;
  431.       return;
  432.    }
  433.  
  434.    static void output_line (y)
  435.       register int y;
  436.    {
  437.       COLOUR *Temp_Colour_Ptr;
  438.       char *Temp_Char_Ptr;
  439.  
  440.       if (Options & DISKWRITE)
  441.          if (y > First_Line) {
  442.             Write_Line (Output_File_Handle, Previous_Line, y-1);
  443.       }
  444.  
  445.    if (Options & VERBOSE){
  446.       if (Options & ANTIALIAS && VerboseFormat != '1')
  447.          printf (" supersampled %d times.", SuperSampleCount);
  448.  
  449.       if (Options & ANTIALIAS && VerboseFormat == '1'){
  450.          fprintf (stderr," supersampled %d times.", SuperSampleCount);
  451.  
  452.       }
  453.       if (VerboseFormat == '1')
  454.          fprintf (stderr,"\r");
  455.       else
  456.          fprintf (stderr,"\n");
  457.    }
  458.    Temp_Colour_Ptr = Previous_Line;
  459.    Previous_Line = Current_Line;
  460.    Current_Line = Temp_Colour_Ptr;
  461.  
  462.    Temp_Char_Ptr = Previous_Line_Antialiased_Flags;
  463.    Previous_Line_Antialiased_Flags = Current_Line_Antialiased_Flags;
  464.    Current_Line_Antialiased_Flags = Temp_Char_Ptr;
  465.  
  466.    return;
  467. }
  468.  
  469. void Trace (Ray, Colour)
  470. RAY *Ray;
  471. COLOUR *Colour;
  472. {
  473.    OBJECT *Object;
  474.    INTERSECTION *Local_Intersection, *New_Intersection;
  475.    register int Intersection_Found;
  476.  
  477.    COOPERATE
  478.    Number_Of_Rays++;
  479.    Make_Colour (Colour, 0.0, 0.0, 0.0);
  480.  
  481.    Intersection_Found = FALSE;
  482.    Local_Intersection = NULL;
  483.  
  484.    if (Trace_Level > (int) Max_Trace_Level) {
  485.       return;
  486.    }
  487.  
  488.    if (Frame.Fog_Distance == 0.0) {
  489.       Make_Colour (Colour, 0.0, 0.0, 0.0);
  490.    }
  491.    else
  492.       *Colour = Frame.Fog_Colour;
  493.  
  494.    if (Options & DEBUGGING)
  495.       printf ("Calculating intersections level %d\n", Trace_Level);
  496.  
  497.    /* What objects does this ray intersect? */
  498.    for (Object = Frame.Objects ;
  499.               Object != NULL ;
  500.               Object = Object -> Next_Object) {
  501.       COOPERATE
  502.       if ( (New_Intersection = Intersection (Object, Ray)) != NULL ) {
  503.          if (Intersection_Found) {
  504.             if (Local_Intersection -> Depth > New_Intersection -> Depth) {
  505.                free (Local_Intersection);
  506.                Local_Intersection = New_Intersection;
  507.             }
  508.             else
  509.                free (New_Intersection);
  510.          }
  511.          else
  512.             Local_Intersection = New_Intersection;
  513.  
  514.          Intersection_Found = TRUE;
  515.       }
  516.    }
  517.  
  518.    if (Intersection_Found) {
  519.       Determine_Surface_Colour (Local_Intersection, Colour, Ray, FALSE);
  520.       free (Local_Intersection);
  521.    }
  522. }
  523.