home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 300-399 / ff397.lzh / DKBTrace / DKBSource.LZH / render.c < prev    next >
C/C++ Source or Header  |  1990-08-26  |  16KB  |  482 lines

  1. /*****************************************************************************
  2. *
  3. *                                    render.c
  4. *
  5. *   from DKBTrace (c) 1990  David Buck
  6. *
  7. *  This module implements the main raytracing loop.
  8. *
  9. * This software is freely distributable. The source and/or object code may be
  10. * copied or uploaded to communications services so long as this notice remains
  11. * at the top of each file.  If any changes are made to the program, you must
  12. * clearly indicate in the documentation and in the programs startup message
  13. * who it was who made the changes. The documentation should also describe what
  14. * those changes were. This software may not be included in whole or in
  15. * part into any commercial package without the express written consent of the
  16. * author.  It may, however, be included in other public domain or freely
  17. * distributed software so long as the proper credit for the software is given.
  18. *
  19. * This software is provided as is without any guarantees or warranty. Although
  20. * the author has attempted to find and correct any bugs in the software, he
  21. * is not responsible for any damage caused by the use of the software.  The
  22. * author is under no obligation to provide service, corrections, or upgrades
  23. * to this package.
  24. *
  25. * Despite all the legal stuff above, if you do find bugs, I would like to hear
  26. * about them.  Also, if you have any comments or questions, you may contact me
  27. * at the following address:
  28. *
  29. *     David Buck
  30. *     22C Sonnet Cres.
  31. *     Nepean Ontario
  32. *     Canada, K2H 8W7
  33. *
  34. *  I can also be reached on the following bulleton boards:
  35. *
  36. *     ATX              (613) 526-4141
  37. *     OMX              (613) 731-3419
  38. *     Mystic           (613) 731-0088 or (613) 731-6698
  39. *
  40. *  Fidonet:   1:163/109.9
  41. *  Internet:  David_Buck@Carleton.CA
  42. *
  43. *  IBM Port by Aaron A. Collins. Aaron may be reached on the following BBS'es:
  44. *
  45. *     Lattice BBS                      (708) 916-1200
  46. *     The Information Exchange BBS     (708) 945-5575
  47. *     Stillwaters BBS                  (708) 403-2826
  48. *
  49. *****************************************************************************/
  50.  
  51.  
  52. #include "frame.h"
  53. #include "vector.h"
  54. #include "dkbproto.h"
  55.  
  56. extern FILE *bfp;
  57. extern char Output_File_Name[30];
  58. extern int File_Buffer_Size;
  59. extern unsigned long Options;
  60. extern int Quality;
  61. volatile int Stop_Flag;
  62. extern int First_Line, Last_Line;
  63. extern long Number_Of_Pixels, Number_Of_Rays, Number_Of_Pixels_Supersampled;
  64.  
  65. extern short *hashTable;
  66. extern unsigned short crctab[256];
  67. #define rand3d(a,b) crctab[(int)(hashTable[(int)(hashTable[(int)((a)&0xfff)]^(b))&0xfff])&0xff]
  68.  
  69. FRAME Frame;
  70. RAY *VP_Ray;
  71. int Trace_Level;
  72.  
  73. #define MAX_TRACE_LEVEL 5
  74.  
  75. void Create_Ray (ray, width, height, x, y)
  76.    RAY *ray;
  77.    int width, height;
  78.    DBL x, y;
  79.    {
  80.    register DBL X_Scalar, Y_Scalar;
  81.    VECTOR Temp_Vect_1, Temp_Vect_2;
  82.  
  83.    /* Convert the X Coordinate to be a DBL from 0.0 to 1.0 */
  84.    X_Scalar = (x - (DBL) width / 2.0) / (DBL) width;
  85.  
  86.    /* Convert the Y Coordinate to be a DBL from 0.0 to 1.0 */
  87.    Y_Scalar = (( (DBL)(Frame.Screen_Height - 1) - y) -
  88.           (DBL) height / 2.0) / (DBL) height;
  89.  
  90.    VScale (Temp_Vect_1, Frame.View_Point.Up, Y_Scalar);
  91.    VScale (Temp_Vect_2, Frame.View_Point.Right, X_Scalar);
  92.    VAdd (ray->Direction, Temp_Vect_1, Temp_Vect_2);
  93.    VAdd (ray->Direction, ray->Direction, Frame.View_Point.Direction);
  94.    VNormalize (ray->Direction, ray->Direction);
  95.    Initialize_Ray_Containers (ray);
  96.    ray->Quadric_Constants_Cached = FALSE;
  97.    }
  98.  
  99. void Write_Line (Line, y)
  100.    COLOUR *Line;
  101.    int y;
  102.    {
  103.    char Red, Green, Blue, temp[2];
  104.    register int x;
  105.  
  106.    if (!(Options & TARGA))    /* Write out line in DKB/QRT RAW format */
  107.       {
  108.       temp[0] = y % 256;
  109.       putc (temp[0], bfp);
  110.       temp[0] = y / 256;
  111.       putc (temp[0], bfp);
  112.  
  113.       for (x = 0 ; x < Frame.Screen_Width ; x++) {
  114.          Red = (char) floor (Line[x].Red * 255.0);
  115.          putc (Red, bfp);
  116.          }
  117.  
  118.       for (x = 0 ; x < Frame.Screen_Width ; x++) {
  119.          Green = (char) floor (Line[x].Green * 255.0);
  120.          putc (Green, bfp);
  121.          }
  122.  
  123.       for (x = 0 ; x < Frame.Screen_Width ; x++) {
  124.          Blue = (char) floor (Line[x].Blue * 255.0);
  125.          putc (Blue, bfp);
  126.          }
  127.       }
  128.    else       /* write out TrueVision Targa 24 format file */
  129.       {
  130.       for (x = 0; x < Frame.Screen_Width; x++) {
  131.          putc((char) floor (Line[x].Blue * 255.0), bfp);
  132.          putc((char) floor (Line[x].Green * 255.0), bfp);
  133.          putc((char) floor (Line[x].Red * 255.0), bfp);
  134.          }
  135.       }
  136.  
  137.    if (File_Buffer_Size == 0) {
  138.       fflush(bfp);                       /* close and reopen file for */
  139.       bfp = freopen(Output_File_Name, "ab", bfp); /* integrity in case we crash*/
  140.       }
  141.    }
  142.  
  143. void Supersample (result, x, y, Width, Height)
  144.    COLOUR *result;
  145.    int x, y, Width, Height;
  146.    {
  147.    COLOUR colour;
  148.    register DBL dx, dy, Jitter_X, Jitter_Y;
  149.  
  150.    dx = (DBL) x;
  151.    dy = (DBL) y;
  152.  
  153.    Number_Of_Pixels_Supersampled++;
  154.  
  155.    Make_Colour (result, 0.0, 0.0, 0.0);
  156.  
  157.    Jitter_X = (rand3d(x, y) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  158.    Jitter_Y = (rand3d(x, y) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  159.    Create_Ray (VP_Ray, Frame.Screen_Width, Frame.Screen_Height,
  160.              dx + Jitter_X, dy + Jitter_Y);
  161.  
  162.    Trace_Level = 0;
  163.    Trace (VP_Ray, &colour);
  164.    Clip_Colour (&colour, &colour);
  165.    Scale_Colour (&colour, &colour, 0.11111111);
  166.    Add_Colour (result, result, &colour);
  167.  
  168.    Jitter_X = (rand3d(x, y) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  169.    Jitter_Y = (rand3d(x, y) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  170.    Create_Ray (VP_Ray, Width, Height, dx + Jitter_X - 0.3333333,
  171.                                       dy + Jitter_Y - 0.3333333);
  172.    Trace_Level = 0;
  173.    Trace (VP_Ray, &colour);
  174.    Clip_Colour (&colour, &colour);
  175.    Scale_Colour (&colour, &colour, 0.11111111);
  176.    Add_Colour (result, result, &colour);
  177.  
  178.    Jitter_X = (rand3d(x, y) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  179.    Jitter_Y = (rand3d(x, y) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  180.    Create_Ray (VP_Ray, Width, Height, dx + Jitter_X - 0.3333333,
  181.                                       dy + Jitter_Y);
  182.    Trace_Level = 0;
  183.    Trace (VP_Ray, &colour);
  184.    Clip_Colour (&colour, &colour);
  185.    Scale_Colour (&colour, &colour, 0.11111111);
  186.    Add_Colour (result, result, &colour);
  187.  
  188.    Jitter_X = (rand3d(x, y) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  189.    Jitter_Y = (rand3d(x, y) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  190.    Create_Ray (VP_Ray, Width, Height, dx + Jitter_X - 0.3333333,
  191.                                       dy + Jitter_Y + 0.3333333);
  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.  
  198.    Jitter_X = (rand3d(x, y) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  199.    Jitter_Y = (rand3d(x, y) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  200.    Create_Ray (VP_Ray, Width, Height, dx + Jitter_X,
  201.                                       dy + Jitter_Y - 0.3333333);
  202.    Trace_Level = 0;
  203.    Trace (VP_Ray, &colour);
  204.    Clip_Colour (&colour, &colour);
  205.    Scale_Colour (&colour, &colour, 0.11111111);
  206.    Add_Colour (result, result, &colour);
  207.  
  208.    Jitter_X = (rand3d(x, y) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  209.    Jitter_Y = (rand3d(x, y) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  210.    Create_Ray (VP_Ray, Width, Height, dx + Jitter_X,
  211.                                       dy + Jitter_Y + 0.3333333);
  212.    Trace_Level = 0;
  213.    Trace (VP_Ray, &colour);
  214.    Clip_Colour (&colour, &colour);
  215.    Scale_Colour (&colour, &colour, 0.11111111);
  216.    Add_Colour (result, result, &colour);
  217.  
  218.    Jitter_X = (rand3d(x, y) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  219.    Jitter_Y = (rand3d(x, y) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  220.    Create_Ray (VP_Ray, Width, Height, dx + Jitter_X + 0.3333333,
  221.                                       dy + Jitter_Y - 0.3333333);
  222.    Trace_Level = 0;
  223.    Trace (VP_Ray, &colour);
  224.    Clip_Colour (&colour, &colour);
  225.    Scale_Colour (&colour, &colour, 0.11111111);
  226.    Add_Colour (result, result, &colour);
  227.  
  228.    Jitter_X = (rand3d(x, y) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  229.    Jitter_Y = (rand3d(x, y) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  230.    Create_Ray (VP_Ray, Width, Height, dx + Jitter_X + 0.3333333,
  231.                                       dy + Jitter_Y);
  232.    Trace_Level = 0;
  233.    Trace (VP_Ray, &colour);
  234.    Clip_Colour (&colour, &colour);
  235.    Scale_Colour (&colour, &colour, 0.11111111);
  236.    Add_Colour (result, result, &colour);
  237.  
  238.    Jitter_X = (rand3d(x, y) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  239.    Jitter_Y = (rand3d(x, y) & 0x7FFF) / 32768.0 * 0.33333333 - 0.16666666;
  240.    Create_Ray (VP_Ray, Width, Height, dx + Jitter_X + 0.3333333,
  241.                                       dy + Jitter_Y + 0.3333333);
  242.    Trace_Level = 0;
  243.    Trace (VP_Ray, &colour);
  244.    Clip_Colour (&colour, &colour);
  245.    Scale_Colour (&colour, &colour, 0.11111111);
  246.    Add_Colour (result, result, &colour);
  247.    }
  248.  
  249. void Start_Tracing ()
  250.    {
  251.    COLOUR Colour;
  252.    RAY Ray;
  253.    register int x, y, i, SuperSampleCount;
  254.    char Red, Green, Blue, Antialias_Center_Flag;
  255.    COLOUR *Previous_Line, *Current_Line, *Temp_Colour_Ptr;
  256.    char *Previous_Line_Antialiased_Flags, *Current_Line_Antialiased_Flags,
  257.         *Temp_Char_Ptr;
  258.  
  259.  
  260.    if (Options & VERBOSE) {
  261.        printf("Tracing...\n");
  262.        fflush (stdout);
  263.        }
  264.  
  265.    VP_Ray = &Ray;
  266.  
  267.    Previous_Line = (COLOUR *)   malloc (sizeof (COLOUR)*(Frame.Screen_Width + 1));
  268.    Current_Line = (COLOUR *) malloc (sizeof (COLOUR)*(Frame.Screen_Width + 1));
  269.  
  270.    for (i = 0 ; i <= Frame.Screen_Width ; i++) {
  271.       Previous_Line[i].Red = 0.0;
  272.       Previous_Line[i].Green = 0.0;
  273.       Previous_Line[i].Blue = 0.0;
  274.  
  275.       Current_Line[i].Red = 0.0;
  276.       Current_Line[i].Green = 0.0;
  277.       Current_Line[i].Blue = 0.0;
  278.       }
  279.  
  280.    if (Options & ANTIALIAS) {
  281.       Previous_Line_Antialiased_Flags =
  282.           (char *) malloc (sizeof (char)*(Frame.Screen_Width + 1));
  283.       Current_Line_Antialiased_Flags =
  284.           (char *)  malloc (sizeof (char)*(Frame.Screen_Width + 1));
  285.  
  286.       for (i = 0 ; i <= Frame.Screen_Width ; i++) {
  287.          Previous_Line_Antialiased_Flags[i] = 0;
  288.          Current_Line_Antialiased_Flags[i] = 0;
  289.          }
  290.       }
  291.  
  292.    Ray.Initial = Frame.View_Point.Location;
  293.  
  294.    for (y = (Options & ANTIALIAS)?First_Line-1:First_Line ; y<Last_Line ; y++) {
  295.  
  296.       TEST_ABORT
  297.  
  298.       if (Options & VERBOSE)
  299.          printf ("Line %3d", y);
  300.  
  301.       if (Options & ANTIALIAS)
  302.          SuperSampleCount = 0;
  303.  
  304.       for (x = 0 ; x < Frame.Screen_Width ; x++) {
  305.          Number_Of_Pixels++;
  306.          if (Stop_Flag) {
  307.             close_all();
  308.             exit(0);
  309.             }
  310.  
  311.          Create_Ray (VP_Ray, Frame.Screen_Width, Frame.Screen_Height, (DBL) x, (DBL) y);
  312.          Trace_Level = 0;
  313.          Trace (&Ray, &Colour);
  314.          Clip_Colour (&Colour, &Colour);
  315.  
  316.          Current_Line[x] = Colour;
  317.  
  318.          if (Options & ANTIALIAS) {
  319.             Antialias_Center_Flag = 0;
  320.             Current_Line_Antialiased_Flags[x] = 0;
  321.  
  322.             if (x != 0) {
  323.                if (Colour_Distance (&Current_Line[x-1], &Current_Line[x])
  324.                    >= Frame.Antialias_Threshold) {
  325.                   Antialias_Center_Flag = 1;
  326.                   if (!(Current_Line_Antialiased_Flags[x-1])) {
  327.                      Supersample (&Current_Line[x-1], 
  328.                                   x-1, y, Frame.Screen_Width, Frame.Screen_Height);
  329.                      Current_Line_Antialiased_Flags[x-1] = 1;
  330.                      SuperSampleCount++;
  331.                      }
  332.                   }
  333.                }
  334.  
  335.             if (y != First_Line-1) {
  336.                if (Colour_Distance (&Previous_Line[x], &Current_Line[x])
  337.                     >= Frame.Antialias_Threshold) {
  338.                   Antialias_Center_Flag = 1;
  339.                   if (!(Previous_Line_Antialiased_Flags[x])) {
  340.                      Supersample (&Previous_Line[x],
  341.                                   x, y-1, Frame.Screen_Width, Frame.Screen_Height);
  342.                      Previous_Line_Antialiased_Flags[x] = 1;
  343.                      SuperSampleCount++;
  344.                      }
  345.                   }
  346.                }
  347.  
  348.             if (Antialias_Center_Flag) {
  349.                Supersample (&Current_Line[x],
  350.                             x, y, Frame.Screen_Width, Frame.Screen_Height);
  351.                Current_Line_Antialiased_Flags[x] = 1;
  352.                Colour = Current_Line[x];
  353.                SuperSampleCount++;
  354.                }
  355.             }
  356.  
  357.          if (y != First_Line-1) {
  358.             Red = (char) (Colour.Red * 255.0);
  359.             Green = (char) (Colour.Green * 255.0);
  360.             Blue = (char) (Colour.Blue * 255.0);
  361.  
  362.             if (Options & DISPLAY)
  363.                display_plot (x, y, Red, Green, Blue);
  364.             }
  365.          }
  366.  
  367.       if ((Options & DISKWRITE) || (Options & TARGA))
  368.          if (y > First_Line) {
  369.             Write_Line (Previous_Line, y-1);
  370.          }
  371.  
  372.       if (Options & VERBOSE)
  373.          if (Options & ANTIALIAS)
  374.             printf (" supersampled %d times\n", SuperSampleCount);
  375.          else
  376.             putchar ('\n');
  377.  
  378.       Temp_Colour_Ptr = Previous_Line;
  379.       Previous_Line = Current_Line;
  380.       Current_Line = Temp_Colour_Ptr;
  381.  
  382.       Temp_Char_Ptr = Previous_Line_Antialiased_Flags;
  383.       Previous_Line_Antialiased_Flags = Current_Line_Antialiased_Flags;
  384.       Current_Line_Antialiased_Flags = Temp_Char_Ptr;
  385.       }
  386.  
  387.    if ((Options & DISKWRITE) || (Options & TARGA)) {
  388.       Write_Line (Previous_Line, Last_Line - 1);
  389.       }
  390.    }
  391.  
  392. void Trace (Ray, Colour)
  393.    RAY *Ray;
  394.    COLOUR *Colour;
  395.    {
  396.    COLOUR Temp_Colour, Surface_Colour;
  397.    OBJECT *Object;
  398.    VECTOR Surface_Normal;
  399.    INTERSECTION *Local_Intersection, *New_Intersection;
  400.    register int Intersection_Found;
  401.    DBL Normal_Direction;
  402.  
  403.    Number_Of_Rays++;
  404.    if (Frame.Fog_Distance == 0.0) {
  405.       Make_Colour (&Temp_Colour, 0.0, 0.0, 0.0);
  406.       }
  407.    else
  408.       Temp_Colour = Frame.Fog_Colour;
  409.  
  410.    Intersection_Found = FALSE;
  411.    Local_Intersection = NULL;
  412.  
  413.    if (Trace_Level > MAX_TRACE_LEVEL)
  414.       return;
  415.  
  416.     /* What objects does this ray intersect? */
  417.    for (Object = Frame.Objects ; 
  418.         Object != NULL ;
  419.         Object = Object -> Next_Object) {
  420.  
  421.       if (New_Intersection = Intersection (Object, Ray)) {
  422.          if (Intersection_Found) {
  423.             if (Local_Intersection -> Depth > New_Intersection -> Depth) {
  424.                free (Local_Intersection);
  425.                Local_Intersection = New_Intersection;
  426.                }
  427.             else
  428.                free (New_Intersection);
  429.             }
  430.          else
  431.             Local_Intersection = New_Intersection;
  432.  
  433.          Intersection_Found = TRUE;
  434.          }
  435.       }
  436.  
  437.    if (Intersection_Found) {
  438.       Make_Colour (&Temp_Colour, 0.0, 0.0, 0.0);
  439.       Make_Colour (&Surface_Colour, 0.0, 0.0, 0.0);
  440.  
  441.       if (Quality > 5)
  442.          Colour_At (&Surface_Colour, Local_Intersection->Object,
  443.                     &Local_Intersection -> Point);
  444.       else
  445.          Surface_Colour = Local_Intersection->Object->Object_Colour;
  446.  
  447.  
  448.       if (Quality <= 1)
  449.          Temp_Colour = Surface_Colour;
  450.       else {
  451.          Normal (&Surface_Normal, (OBJECT *) Local_Intersection -> Shape,
  452.                  &Local_Intersection -> Point);
  453.          VDot (Normal_Direction, Surface_Normal, Ray->Direction);
  454.          if (Normal_Direction > 0.0) {
  455.             VScale (Surface_Normal, Surface_Normal, -1.0);
  456.             }
  457.  
  458.          Ambient (Local_Intersection -> Object, &Local_Intersection -> Point,
  459.                     &Surface_Colour, &Temp_Colour);
  460.          Diffuse (Local_Intersection -> Object, &Local_Intersection -> Point, Ray,
  461.                     &Surface_Normal, &Surface_Colour, &Temp_Colour);
  462.  
  463.          if (Quality > 7) {
  464.             Transmit (Local_Intersection -> Object, &Local_Intersection -> Point, Ray,
  465.                       &Surface_Normal, &Surface_Colour, &Temp_Colour);
  466.             Reflect (Local_Intersection -> Object, &Local_Intersection -> Point, Ray,
  467.                      &Surface_Normal, &Temp_Colour);
  468.             Refract (Local_Intersection -> Object, &Local_Intersection -> Point, Ray,
  469.                      &Surface_Normal, &Temp_Colour);
  470.  
  471.             if (Frame.Fog_Distance != 0.0)
  472.                Fog (Local_Intersection->Depth, &Frame.Fog_Colour, Frame.Fog_Distance,
  473.                     &Temp_Colour);
  474.             }
  475.          }
  476.       free (Local_Intersection);
  477.       }
  478.  
  479.    *Colour = Temp_Colour;
  480.    }
  481.  
  482.