home *** CD-ROM | disk | FTP | other *** search
/ Chestnut's Multimedia Mania / MM_MANIA.ISO / graphics / povsrc20 / render.c < prev    next >
C/C++ Source or Header  |  1993-08-26  |  16KB  |  534 lines

  1. /****************************************************************************
  2. *                   render.c
  3. *
  4. *  This module implements the main raytracing loop.
  5. *
  6. * 08/07/92 lsk    Changed the normal antialiasing function to use a loop 
  7. *                 where the number of rays per pixel when antialiasing can 
  8. *                 be sepcified.
  9. *
  10. *  from Persistence of Vision Raytracer
  11. *  Copyright 1993 Persistence of Vision Team
  12. *---------------------------------------------------------------------------
  13. *  NOTICE: This source code file is provided so that users may experiment
  14. *  with enhancements to POV-Ray and to port the software to platforms other
  15. *  than those supported by the POV-Ray Team.  There are strict rules under
  16. *  which you are permitted to use this file.  The rules are in the file
  17. *  named POVLEGAL.DOC which should be distributed with this file. If
  18. *  POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  19. *  Team Coordinator by leaving a message in CompuServe's Graphics Developer's
  20. *  Forum.  The latest version of POV-Ray may be found there as well.
  21. *
  22. * This program is based on the popular DKB raytracer version 2.12.
  23. * DKBTrace was originally written by David K. Buck.
  24. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  25. *
  26. ******************************************************************************/
  27.  
  28. #include "frame.h"
  29. #include "vector.h"
  30. #include "povproto.h"
  31.  
  32. extern FILE_HANDLE *Output_File_Handle;
  33. extern char Output_File_Name[FILE_NAME_LENGTH];
  34. extern char Input_File_Name[FILE_NAME_LENGTH];
  35. extern char Stat_File_Name[FILE_NAME_LENGTH];
  36. extern char OutputFormat, Color_Bits, PaletteOption;
  37. extern char VerboseFormat;
  38. extern unsigned int Options;
  39. extern int File_Buffer_Size;
  40. extern int Use_Slabs;
  41. volatile int Stop_Flag;
  42. extern int First_Line, Last_Line;
  43. extern int First_Column, Last_Column;
  44. extern long Number_Of_Pixels, Number_Of_Rays, Number_Of_Pixels_Supersampled;
  45. extern short *hashTable;
  46. extern unsigned short crctab[256];
  47. extern OBJECT *Root_Object;
  48. extern long AntialiasDepth;
  49. extern DBL JitterScale;
  50.  
  51. #define rand3d(a,b) crctab[(int)(hashTable[(int)(hashTable[(int)((a)&0xfff)]^(b))&0xfff])&0xff]
  52.  
  53. FRAME Frame;
  54. RAY *CM_Ray;
  55. int Trace_Level, SuperSampleCount;
  56.  
  57. DBL Max_Trace_Level = 5;
  58. DBL maxclr;
  59.  
  60. static void check_stats PARAMS((int y));
  61. static void do_anti_aliasing PARAMS((int x, int y, COLOUR *Colour));
  62. static void output_line PARAMS((int y));
  63.  
  64. COLOUR *Previous_Line, *Current_Line;
  65.  
  66. char *Previous_Line_Antialiased_Flags, *Current_Line_Antialiased_Flags;
  67. RAY Ray;
  68.  
  69. void Create_Ray (ray, width, height, x, y)
  70. RAY *ray;
  71. int width, height;
  72. DBL x, y;
  73.   {
  74.   register DBL X_Scalar, Y_Scalar;
  75.   VECTOR Temp_Vect_1, Temp_Vect_2;
  76.  
  77.   /* Convert the X Coordinate to be a DBL from 0.0 to 1.0 */
  78.   X_Scalar = (x - (DBL) width / 2.0) / (DBL) width;
  79.  
  80.   /* Convert the Y Coordinate to be a DBL from 0.0 to 1.0 */
  81.   Y_Scalar = (( (DBL)(Frame.Screen_Height - 1) - y) -
  82.     (DBL) height / 2.0) / (DBL) height;
  83.  
  84.   VScale (Temp_Vect_1, Frame.Camera->Up, Y_Scalar);
  85.   VScale (Temp_Vect_2, Frame.Camera->Right, X_Scalar);
  86.   VAdd (ray->Direction, Temp_Vect_1, Temp_Vect_2);
  87.   VAdd (ray->Direction, ray->Direction, Frame.Camera->Direction);
  88.   VNormalize (ray->Direction, ray->Direction);
  89.   Initialize_Ray_Containers (ray);
  90.   ray->Quadric_Constants_Cached = FALSE;
  91.   }
  92.  
  93. void Read_Rendered_Part()
  94.   {
  95.   int rc, x, line_number;
  96.   unsigned char Red, Green, Blue;
  97.   DBL grey;
  98.  
  99.   maxclr = (DBL)(1 << Color_Bits) - 1.0;
  100.   while ((rc = Read_Line(Output_File_Handle, Previous_Line, &line_number)) == 1) 
  101.     {
  102.     if (Options & DISPLAY)
  103.       for (x = 0 ; x < Frame.Screen_Width ; x++) 
  104.       {
  105.       if (PaletteOption == GREY) 
  106.         {
  107.         grey = Previous_Line[x].Red * 0.287 +
  108.         Previous_Line[x].Green * 0.589 +
  109.         Previous_Line[x].Blue * 0.114;
  110.         Red = Green = Blue = (unsigned char)(grey * maxclr);
  111.         }
  112.       else 
  113.         {
  114.         Red = (unsigned char) (Previous_Line[x].Red * maxclr);
  115.         Green = (unsigned char) (Previous_Line[x].Green * maxclr);
  116.         Blue = (unsigned char) (Previous_Line[x].Blue * maxclr);
  117.         }
  118.       display_plot (x, line_number, Red, Green, Blue);
  119.       COOPERATE     /* Moved inside loop JLN 12/91 */
  120.         }
  121.       }
  122.  
  123.     First_Line = line_number+1;
  124.  
  125.   if (rc == 0) 
  126.     {
  127.     Close_File(Output_File_Handle);
  128.     if (Open_File (Output_File_Handle, Output_File_Name,
  129.       &Frame.Screen_Width, &Frame.Screen_Height, File_Buffer_Size,
  130.       APPEND_MODE) != 1) 
  131.       {
  132.       fprintf (stderr, "Error opening output file\n");
  133.       fflush(stdout);
  134.       close_all();
  135.       exit(1);
  136.       }
  137.     return;
  138.     }
  139.  
  140.   fprintf (stderr, "Error reading aborted data file\n");
  141.   }
  142.  
  143. void Start_Tracing ()
  144.   {
  145.   COLOUR Colour;
  146.   register int x, y;
  147.   unsigned char Red, Green, Blue;
  148.   DBL grey;
  149.  
  150.   for (y = (Options & ANTIALIAS)?First_Line-1:First_Line; y<Last_Line; y++) 
  151.     {
  152.  
  153.     check_stats(y);
  154.  
  155.     for (x = First_Column ; x <= Last_Column ; x++) 
  156.       {
  157.  
  158.       Check_User_Abort(1);
  159.       
  160.       Number_Of_Pixels++;
  161.  
  162.       Create_Ray (CM_Ray, Frame.Screen_Width, Frame.Screen_Height, (DBL) x, (DBL) y);
  163.       Trace_Level = 0;
  164.       Trace (&Ray, &Colour);
  165.       Clip_Colour (&Colour, &Colour);
  166.  
  167.       Current_Line[x] = Colour;
  168.  
  169.       if (Options & ANTIALIAS)      
  170.         do_anti_aliasing(x, y, &Colour); 
  171.  
  172.       if (y != First_Line-1) 
  173.         {
  174.  
  175.         if (PaletteOption == GREY) 
  176.           {
  177.           grey = Colour.Red * 0.287 +
  178.           Colour.Green * 0.589 +
  179.           Colour.Blue * 0.114;
  180.           Red = Green = Blue = (unsigned char)(grey * maxclr);
  181.           }
  182.         else 
  183.           {
  184.           Red = (unsigned char) (Colour.Red * maxclr);
  185.           Green = (unsigned char) (Colour.Green * maxclr);
  186.           Blue = (unsigned char) (Colour.Blue * maxclr);
  187.           }
  188.         if (Options & DISPLAY)
  189.           display_plot (x, y, Red, Green, Blue);
  190.         }
  191.       }
  192.     output_line(y);
  193.     }
  194.  
  195.   if (Options & DISKWRITE) 
  196.     {
  197.     Write_Line (Output_File_Handle, Previous_Line, Last_Line - 1);
  198.     }
  199.   }
  200.  
  201. static void check_stats(y)
  202. register int y;
  203.   {
  204.   FILE *stat_file;
  205.  
  206.   /* New verbose options CdW */
  207.   if (Options & VERBOSE && VerboseFormat=='0')
  208.     {
  209.     printf ("POV-Ray rendering %s to %s",Input_File_Name,Output_File_Name);
  210.     if((First_Line != 0) || (Last_Line != Frame.Screen_Height))
  211.       printf(" from %4d to %4d:\n",First_Line, Last_Line);
  212.     else
  213.       printf (":\n");
  214.     printf ("Res %4d X %4d. Calc line %4d of %4d",Frame.Screen_Width, Frame.Screen_Height, (y-First_Line)+1, Last_Line-First_Line);
  215.     if (!(Options & ANTIALIAS))
  216.       printf(".");
  217.     }
  218.   if (Options & VERBOSE_FILE)
  219.     {
  220.     stat_file = fopen(Stat_File_Name,"w+t");
  221.     fprintf (stat_file,"Line %4d.\n", y);
  222.     fclose(stat_file);
  223.     }
  224.  
  225.   /* Use -vO for Old style verbose */
  226.   if (Options & VERBOSE && (VerboseFormat=='O')) 
  227.     {
  228.     printf ("Line %4d", y);
  229.     }
  230.   if (Options & VERBOSE && VerboseFormat=='1')
  231.     {
  232.     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);
  233.     if (!(Options & ANTIALIAS))
  234.       fprintf(stderr,".");
  235.     }
  236.  
  237.   if (Options & ANTIALIAS)
  238.     SuperSampleCount = 0;
  239.   }
  240.  
  241. static void do_anti_aliasing(x, y, Colour)
  242. register int x, y;
  243. COLOUR *Colour;
  244.   {
  245.   char Antialias_Center_Flag = 0;
  246.  
  247.   Current_Line_Antialiased_Flags[x] = 0;
  248.  
  249.   if (x != 0) 
  250.     {
  251.     if (Colour_Distance (&Current_Line[x-1], &Current_Line[x])
  252.       >= Frame.Antialias_Threshold) 
  253.       {
  254.       Antialias_Center_Flag = 1;
  255.       if (!(Current_Line_Antialiased_Flags[x-1])) 
  256.         {
  257.         Supersample (&Current_Line[x-1],
  258.           x-1, y, Frame.Screen_Width, Frame.Screen_Height);
  259.         Current_Line_Antialiased_Flags[x-1] = 1;
  260.         SuperSampleCount++;
  261.         }
  262.       }
  263.     }
  264.  
  265.   if (y != First_Line-1) 
  266.     {
  267.     if (Colour_Distance (&Previous_Line[x], &Current_Line[x])
  268.       >= Frame.Antialias_Threshold) 
  269.       {
  270.       Antialias_Center_Flag = 1;
  271.       if (!(Previous_Line_Antialiased_Flags[x])) 
  272.         {
  273.         Supersample (&Previous_Line[x],
  274.           x, y-1, Frame.Screen_Width, Frame.Screen_Height);
  275.         Previous_Line_Antialiased_Flags[x] = 1;
  276.         SuperSampleCount++;
  277.         }
  278.       }
  279.     }
  280.  
  281.   if (Antialias_Center_Flag) 
  282.     {
  283.     Supersample (&Current_Line[x],
  284.       x, y, Frame.Screen_Width, Frame.Screen_Height);
  285.     Current_Line_Antialiased_Flags[x] = 1;
  286.     *Colour = Current_Line[x];
  287.     SuperSampleCount++;
  288.     }
  289.  
  290.   return;
  291.   }
  292.  
  293.  
  294. void Initialize_Renderer PARAMS((void))
  295.   {
  296.   register int i;
  297.  
  298.   CM_Ray = &Ray;
  299.  
  300.   maxclr = (DBL)(1 << Color_Bits) - 1.0;
  301.  
  302.   /* These malloc's are never freed! Why ? Need a Deinit_Renderer() ?*/
  303.   Previous_Line = (COLOUR *) malloc (sizeof (COLOUR)*(Frame.Screen_Width + 1));
  304.   Current_Line = (COLOUR *) malloc (sizeof (COLOUR)*(Frame.Screen_Width + 1));
  305.  
  306.   for (i = 0 ; i <= Frame.Screen_Width ; i++) 
  307.     {
  308.     Previous_Line[i].Red = 0.0;
  309.     Previous_Line[i].Green = 0.0;
  310.     Previous_Line[i].Blue = 0.0;
  311.     Current_Line[i].Red = 0.0;
  312.     Current_Line[i].Green = 0.0;
  313.     Current_Line[i].Blue = 0.0;
  314.     }
  315.  
  316.   if (Options & ANTIALIAS) 
  317.     {
  318.     Previous_Line_Antialiased_Flags =
  319.     (char *) malloc (sizeof (char)*(Frame.Screen_Width + 1));
  320.     Current_Line_Antialiased_Flags =
  321.     (char *)  malloc (sizeof (char)*(Frame.Screen_Width + 1));
  322.  
  323.     for (i = 0 ; i <= Frame.Screen_Width ; i++) 
  324.       {
  325.       (Previous_Line_Antialiased_Flags)[i] = 0;
  326.       (Current_Line_Antialiased_Flags)[i] = 0;
  327.       }
  328.     }
  329.  
  330.   Ray.Initial = Frame.Camera->Location;
  331.   return;
  332.   }
  333.  
  334. static void output_line (y)
  335. register int y;
  336.   {
  337.   COLOUR *Temp_Colour_Ptr;
  338.   char *Temp_Char_Ptr;
  339.  
  340.   if (Options & DISKWRITE)
  341.     if (y > First_Line) 
  342.     {
  343.     Write_Line (Output_File_Handle, Previous_Line, y-1);
  344.     }
  345.  
  346.   if (Options & VERBOSE)
  347.     {
  348.     if (Options & ANTIALIAS && VerboseFormat != '1')
  349.       printf (" supersampled %d times.", SuperSampleCount);
  350.  
  351.     if (Options & ANTIALIAS && VerboseFormat == '1')
  352.       {
  353.       fprintf (stderr," supersampled %d times.", SuperSampleCount);
  354.  
  355.       }
  356.     if (VerboseFormat == '1')
  357.       fprintf (stderr,"\r");
  358.     else
  359.       fprintf (stderr,"\n");
  360.     }
  361.   Temp_Colour_Ptr = Previous_Line;
  362.   Previous_Line = Current_Line;
  363.   Current_Line = Temp_Colour_Ptr;
  364.  
  365.   Temp_Char_Ptr = Previous_Line_Antialiased_Flags;
  366.   Previous_Line_Antialiased_Flags = Current_Line_Antialiased_Flags;
  367.   Current_Line_Antialiased_Flags = Temp_Char_Ptr;
  368.  
  369.   return;
  370.   }
  371.  
  372. void Trace (Ray, Colour)
  373. RAY *Ray;
  374. COLOUR *Colour;
  375.   {
  376.   OBJECT *Object;
  377.   INTERSECTION Best_Intersection, New_Intersection;
  378.   register int Intersection_Found;
  379.  
  380.   COOPERATE
  381.   Number_Of_Rays++;
  382.   Make_Colour (Colour, 0.0, 0.0, 0.0);
  383.  
  384.   if (Trace_Level > (int) Max_Trace_Level) 
  385.     return;
  386.  
  387.   Intersection_Found = FALSE;
  388.   Best_Intersection.Depth = BOUND_HUGE;
  389.  
  390.     /* What objects does this ray intersect? */
  391.   if (!Use_Slabs)
  392.     for (Object = Frame.Objects ; 
  393.          Object != NULL ;
  394.          Object = Object -> Sibling) 
  395.     {
  396.     if (Intersection (&New_Intersection, Object, Ray))
  397.       if (New_Intersection.Depth < Best_Intersection.Depth) 
  398.         {
  399.         Best_Intersection = New_Intersection;
  400.         Intersection_Found = TRUE;
  401.         }
  402.     }
  403.   else
  404.     Intersection_Found = Bounds_Intersect(Root_Object, Ray,
  405.       &Best_Intersection,&Object);
  406.  
  407.   if (Intersection_Found)
  408.     Determine_Apparent_Colour (&Best_Intersection, Colour, Ray);
  409.   else
  410.     if (Frame.Fog_Distance > 0.0)
  411.       *Colour = Frame.Fog_Colour;
  412.     else
  413.       *Colour = Frame.Background_Colour;
  414.   }
  415.  
  416. /* exit with error if image not completed/user abort*/
  417. void Check_User_Abort (Do_Stats)
  418. int Do_Stats;
  419.   {
  420.   TEST_ABORT
  421.   if (Stop_Flag) 
  422.     {
  423.     close_all();
  424.     if (Do_Stats)
  425.       {
  426.       PRINT_STATS
  427.       }
  428.     exit(2);
  429.     }
  430.   }
  431.  
  432. /*---------------  Standard sampling in loop  -----------------------*/
  433.  
  434. unsigned short JRanges[] = {1,1,1,1,3,2,5,3,7,4}; /* LSK */
  435.  
  436. void Supersample (result, x, y, Width, Height)
  437. COLOUR *result;
  438. int x, y, Width, Height;
  439.   {
  440.   COLOUR colour;
  441.   register DBL dx, dy, Jitter_X, Jitter_Y;
  442.   register int Jitt_Offset;
  443.   unsigned char Red, Green, Blue;
  444.   int JRange;                               /* LSK */
  445.   int JSteps;                               /* LSK */
  446.   DBL JScale;                               /* LSK */
  447.   DBL JSize,JOffset;                        /* LSK */
  448.   int i,j;                                  /* LSK */
  449.  
  450.   dx = (DBL) x;                             /* LSK */
  451.   dy = (DBL) y;                             /* LSK */
  452.   Jitt_Offset = 10;
  453.  
  454.   Number_Of_Pixels_Supersampled++;
  455.  
  456.   Make_Colour (result, 0.0, 0.0, 0.0);
  457.  
  458.   if (AntialiasDepth>1)                                           /* LSK */
  459.     {                                                             /* LSK */
  460.     /* JSize is the size of the jitter scattering area */
  461.     JSize = 1.0/AntialiasDepth;                                   /* LSK */
  462.  
  463.     /* JOffset is the 'radius' of the jitter scatter area */
  464.     JOffset = JSize/2.0;                                        /* LSK */
  465.  
  466.     /* JSteps is either 1 or 2 depending on whether the number of samples
  467.         is odd or even. This is because the loop need to either run through
  468.         or over 0
  469.      */
  470.     JSteps = 2-(AntialiasDepth % 2);                              /* LSK */
  471.  
  472.     /* JRange is the range that the loop will run through. I couldn't
  473.         come up with a function describing the values, so I used an array
  474.         for 2x2 up to 9x9.
  475.      */
  476.     JRange = JRanges[AntialiasDepth];                             /* LSK */
  477.  
  478.     /* JScale is the scaling value for the color resulting from the
  479.         ray before adding to the resultant color
  480.      */
  481.     JScale = 1.0/(DBL)(AntialiasDepth*AntialiasDepth);              /* LSK */
  482.  
  483.     for (i=-JRange;i<=JRange;i+=JSteps)
  484.       for (j=-JRange;j<=JRange;j+=JSteps)
  485.       {
  486.       if (Options & JITTER)
  487.         {
  488.         Jitter_X = (rand3d(x+Jitt_Offset, y) & 0x7FFF) / 32768.0 * JSize - JOffset;
  489.         Jitt_Offset++;
  490.         Jitter_Y = (rand3d(x+Jitt_Offset, y) & 0x7FFF) / 32768.0 * JSize - JOffset;
  491.         Jitt_Offset++;
  492.         }
  493.       else
  494.         {
  495.         Jitter_X=Jitter_Y=0.0;
  496.         }
  497.       Jitter_X*=JitterScale;
  498.       Jitter_Y*=JitterScale;
  499.  
  500.       Create_Ray (CM_Ray, Frame.Screen_Width, Frame.Screen_Height,
  501.         dx + Jitter_X + i * JSize/JSteps,
  502.         dy + Jitter_Y + j * JSize/JSteps );
  503.  
  504.       Trace_Level = 0;
  505.       Trace (CM_Ray, &colour);
  506.       Clip_Colour (&colour, &colour);
  507.       Scale_Colour (&colour, &colour, JScale );
  508.       Add_Colour (result, result, &colour);
  509.  
  510.       }
  511.     }                                       /* LSK */
  512.   else   /* 1x1 specified! */
  513.     {
  514.     Create_Ray (CM_Ray, Frame.Screen_Width, Frame.Screen_Height,dx,dy );
  515.  
  516.     Trace_Level = 0;
  517.     Trace (CM_Ray, &colour);
  518.     Clip_Colour (&colour, &colour);
  519.     Add_Colour (result, result, &colour);
  520.     Jitt_Offset += 10;
  521.     }
  522.  
  523.   if ((y != First_Line - 1) && (Options & DISPLAY)) 
  524.     {
  525.     Red = (unsigned char)(result->Red * maxclr);
  526.     Green = (unsigned char)(result->Green * maxclr);
  527.     Blue = (unsigned char)(result->Blue * maxclr);
  528.     display_plot (x, y, Red, Green, Blue);
  529.     }
  530.  
  531.   }
  532.  
  533.  
  534.