home *** CD-ROM | disk | FTP | other *** search
/ Fish 'n' More 2 / fishmore-publicdomainlibraryvol.ii1991xetec.iso / dirs / dkbtrace_397.lzh / DKBTrace / DKBSource.LZH / trace.c < prev    next >
C/C++ Source or Header  |  1990-08-26  |  15KB  |  540 lines

  1. /*****************************************************************************
  2. *
  3. *                                     trace.c
  4. *
  5. *   from DKBTrace (c) 1990  David Buck
  6. *
  7. *  This module contains the entry routine for the raytracer and the code to
  8. *  parse the parameters on the command line.
  9. *
  10. *
  11. * This software is freely distributable. The source and/or object code may be
  12. * copied or uploaded to communications services so long as this notice remains
  13. * at the top of each file.  If any changes are made to the program, you must
  14. * clearly indicate in the documentation and in the programs startup message
  15. * who it was who made the changes. The documentation should also describe what
  16. * those changes were. This software may not be included in whole or in
  17. * part into any commercial package without the express written consent of the
  18. * author.  It may, however, be included in other public domain or freely
  19. * distributed software so long as the proper credit for the software is given.
  20. *
  21. * This software is provided as is without any guarantees or warranty. Although
  22. * the author has attempted to find and correct any bugs in the software, he
  23. * is not responsible for any damage caused by the use of the software.  The
  24. * author is under no obligation to provide service, corrections, or upgrades
  25. * to this package.
  26. *
  27. * Despite all the legal stuff above, if you do find bugs, I would like to hear
  28. * about them.  Also, if you have any comments or questions, you may contact me
  29. * at the following address:
  30. *
  31. *     David Buck
  32. *     22C Sonnet Cres.
  33. *     Nepean Ontario
  34. *     Canada, K2H 8W7
  35. *
  36. *  I can also be reached on the following bulleton boards:
  37. *
  38. *     ATX              (613) 526-4141
  39. *     OMX              (613) 731-3419
  40. *     Mystic           (613) 731-0088 or (613) 731-6698
  41. *
  42. *  Fidonet:   1:163/109.9
  43. *  Internet:  David_Buck@Carleton.CA
  44. *
  45. *  IBM Port by Aaron A. Collins. Aaron may be reached on the following BBS'es:
  46. *
  47. *     Lattice BBS                      (708) 916-1200
  48. *     The Information Exchange BBS     (708) 945-5575
  49. *     Stillwaters BBS                  (708) 403-2826
  50. *
  51. *****************************************************************************/
  52.  
  53. #include <ctype.h>
  54. #include "frame.h"        /* common to ALL modules in this program */
  55. #include "dkbproto.h"
  56.  
  57. #define MAX_FILE_NAMES 1
  58. unsigned long Options;
  59. int Quality;
  60.  
  61. FILE *bfp;
  62.  
  63. FILE *Input_File, *Token_File, *Symbol_File, *Data_File;
  64. extern FRAME Frame;
  65.  
  66. static char *File_Names[MAX_FILE_NAMES];
  67. char Input_File_Name[FILE_NAME_LENGTH], Output_File_Name[FILE_NAME_LENGTH];
  68. char *Output_File_Buffer;
  69. int File_Buffer_Size;
  70. static int Number_Of_Files;
  71. DBL VTemp;
  72. DBL Antialias_Threshold;
  73. int First_Line, Last_Line;
  74.  
  75. /* Stats kept by the ray tracer: */
  76. long Number_Of_Pixels, Number_Of_Rays, Number_Of_Pixels_Supersampled;
  77. long Ray_Sphere_Tests, Ray_Sphere_Tests_Succeeded;
  78. long Ray_Plane_Tests, Ray_Plane_Tests_Succeeded;
  79. long Ray_Triangle_Tests, Ray_Triangle_Tests_Succeeded;
  80. long Ray_Quadric_Tests, Ray_Quadric_Tests_Succeeded;
  81. long Bounding_Region_Tests, Bounding_Region_Tests_Succeeded;
  82. long Calls_To_Noise, Calls_To_DNoise;
  83. long Shadow_Ray_Tests, Shadow_Rays_Succeeded;
  84. long Reflected_Rays_Traced, Refracted_Rays_Traced;
  85. long Transmitted_Rays_Traced;
  86.  
  87.  
  88. void main (argc, argv)
  89.   int argc;
  90.   char **argv;
  91.   {
  92.   register int i;
  93.   char temp[2];
  94.   
  95.   printf ("\n\n              DKB Ray Trace   Version 2.01\n");
  96.   printf ("              ----------------------------\n\n");
  97.   printf ("             Copyright (c) 1990  David Buck\n\n");
  98.   printf ("  Written by:\n");
  99.   printf ("  David K. Buck\n");
  100.   printf ("  22C Sonnet Cr.  Nepean, Ontario\n");
  101.   printf ("  Canada, K2H 8W7\n\n");
  102.   printf ("  This program is freely distributable.\n");
  103.  
  104.   printf ("\n  Conversion to IBM P.C. w/TARGA output \n");
  105.   printf ("    and various improvements by Aaron A. Collins\n\n");
  106.  
  107.   printf ("  GIF format file reader by Steve A. Bennett\n\n");
  108.  
  109.   printf ("  Noise and DNoise functions by Robert Skinner\n\n");
  110.  
  111. /* Parse the command line parameters */
  112.   if (argc == 1)
  113.     {
  114.     printf ("\nUsage:");
  115.     printf ("\n   trace  [+/-] Option1 [+/-] Option2");
  116.     printf ("\n");
  117.     printf ("\n Options:");
  118.     printf ("\n    d  = display");
  119.     printf ("\n    v  = verbose");
  120.     printf ("\n    p  = prompt exit");
  121.     printf ("\n    x  = enable early exit by key hit");
  122.     printf ("\n    f  = write DKB/QRT format output file");
  123.     printf ("\n    t  = write TARGA format output file");
  124.     printf ("\n    a  = perform antialiasing");
  125. /*  printf ("\n    z  = debug mode");    */
  126.     printf ("\n    qx = image quality 0=rough, 9=full");
  127.     printf ("\n    wxxx = width of the screen");
  128.     printf ("\n    hxxx = height of the screen");
  129.     printf ("\n    sxxx = start at line number xxx");
  130.     printf ("\n    exxx = end at line number xxx");
  131.     printf ("\n    bxxx = Use xxx kilobytes for output file buffer space");
  132.     printf ("\n    ifilename = input file name");
  133.     printf ("\n    ofilename = output file name");
  134.     printf ("\n\n");
  135.     exit(0);
  136.     }
  137.  
  138.   bfp = NULL;
  139.   File_Buffer_Size = 0;
  140.   Options = 0;
  141.   Quality = 9;
  142.   Number_Of_Files = 0;
  143.   First_Line = 0;
  144.   Last_Line = -1;
  145.  
  146.   Number_Of_Pixels = 0L;
  147.   Number_Of_Rays = 0L;
  148.   Number_Of_Pixels_Supersampled = 0L;
  149.   Ray_Sphere_Tests = 0L;
  150.   Ray_Sphere_Tests_Succeeded = 0L;
  151.   Ray_Plane_Tests = 0L;
  152.   Ray_Plane_Tests_Succeeded = 0L;
  153.   Ray_Triangle_Tests = 0L;
  154.   Ray_Triangle_Tests_Succeeded = 0L;
  155.   Ray_Quadric_Tests = 0L;
  156.   Ray_Quadric_Tests_Succeeded = 0L;
  157.   Bounding_Region_Tests = 0L;
  158.   Bounding_Region_Tests_Succeeded = 0L;
  159.   Calls_To_Noise = 0L;
  160.   Calls_To_DNoise = 0L;
  161.   Shadow_Ray_Tests = 0L;
  162.   Shadow_Rays_Succeeded = 0L;
  163.   Reflected_Rays_Traced = 0L;
  164.   Refracted_Rays_Traced = 0L;
  165.   Transmitted_Rays_Traced = 0L;
  166.  
  167.   Frame.Screen_Height = 100;
  168.   Frame.Screen_Width = 100;
  169.  
  170.   Antialias_Threshold = 0.3;
  171.   strcpy (&Input_File_Name[0], "object.data");
  172.  
  173. /* Read the default parameters from trace.def */
  174.   get_defaults();
  175.  
  176.   strcpy (&Output_File_Name[0], "data.dis");
  177.  
  178.   if (Options & TARGA)
  179.      strcpy (&Output_File_Name[0], "data.tga");
  180.  
  181.   for (i = 1 ; i < argc ; i++ )
  182.     if ((*argv[i] == '+') || (*argv[i] == '-'))
  183.       parse_option(argv[i]);
  184.     else
  185.       parse_file_name(argv[i]);
  186.  
  187.    if (Last_Line == -1)
  188.       Last_Line = Frame.Screen_Height;
  189.  
  190.    Print_Options();
  191.  
  192. /* Tokenize the input file */
  193.   if ((Input_File = fopen (Input_File_Name, "r")) == NULL)
  194.     {
  195.     printf ("Cannot open input file\n");
  196.     exit (0);
  197.     }
  198.  
  199.   if ((Token_File = fopen ("Token.data", "w")) == NULL)
  200.     {
  201.     printf ("Cannot open token file for write\n");
  202.     exit (0);
  203.     }
  204.  
  205.   if ((Symbol_File = fopen ("Symbols.data", "w")) == NULL)
  206.     {
  207.     printf ("Cannot open string file for writing\n");
  208.     exit(0);
  209.     }
  210.  
  211.   printf ("Tokenizing...\n");
  212.   Tokenize (Input_File_Name, Input_File, Symbol_File, Token_File);
  213.   fclose (Input_File);
  214.   fclose (Token_File);
  215.   fclose (Symbol_File);
  216.  
  217. /* parse the tokenize file */
  218.   if ((Token_File = fopen ("Token.data", "r")) == NULL)
  219.     exit (0);
  220.  
  221.   if ((Symbol_File = fopen ("Symbols.data", "r")) == NULL)
  222.     {
  223.     printf ("Cannot open string file for reading\n");
  224.     exit(0);
  225.     }
  226.  
  227.   printf ("Parsing...\n");
  228.   Parse (Token_File, &Frame);
  229.   fclose (Token_File);
  230.  
  231. /* Get things ready for ray tracing */
  232.   if ((Options & DISKWRITE) || (Options & TARGA)) {
  233.     bfp = fopen (&Output_File_Name[0], "wb");
  234.     if (bfp == NULL) {
  235.         printf ("Cannot open output file\n");
  236.         exit (0);
  237.         }
  238.     if (File_Buffer_Size != 0) {
  239.        Output_File_Buffer = malloc (File_Buffer_Size);
  240.        setvbuf (bfp, Output_File_Buffer, _IOFBF, File_Buffer_Size);
  241.        }
  242.  
  243.     if (Options & TARGA) {        /* Prefix TARGA format file header */
  244.     for (i = 0; i < 10; i++)    /* 00, 00, 02, then 7 00's... */
  245.         if (i == 2)
  246.          putc(i, bfp);
  247.         else putc(0, bfp);
  248.         temp[0] = First_Line % 256;    /* y origin is set to "First_Line" */
  249.         putc (temp[0], bfp);
  250.         temp[0] = First_Line / 256;
  251.         putc (temp[0], bfp);
  252.         }
  253.  
  254.     temp[0] = Frame.Screen_Width % 256;    /* write this to either file type */
  255.     putc (temp[0], bfp);
  256.     temp[0] = Frame.Screen_Width / 256;
  257.     putc (temp[0], bfp);
  258.     temp[0] = Frame.Screen_Height % 256;
  259.     putc (temp[0], bfp);
  260.     temp[0] = Frame.Screen_Height / 256;
  261.     putc (temp[0], bfp);
  262.  
  263.     if (Options & TARGA) {    /* now finish the TARGA format file header */
  264.     putc(24, bfp);        /* 24 bits/pixel (16 million colors!) */
  265.     putc(32, bfp);        /* Not sure about this one, "out of 32" ? */
  266.     }
  267.     }
  268.  
  269.   if (Options & DISPLAY)
  270.     {
  271.     printf ("Displaying...\n");
  272.     display_init();
  273.     }
  274.  
  275.   pq_init();
  276.   Initialize_Noise();
  277.  
  278. /* Ok, go for it - trace the picture */
  279.   Start_Tracing ();
  280.  
  281. /* Wait for a CR if the user requested it. */
  282.  
  283. /* Clean up and leave */
  284.   display_finished();
  285.  
  286.   close_all ();
  287.   print_stats();
  288.   }
  289.  
  290. /* Close all the stuff that has been opened. */
  291. void close_all ()
  292.    {
  293.    if (Options & DISPLAY)
  294.      display_close();
  295.  
  296.    if (bfp)
  297.       fclose (bfp);
  298.    }
  299.  
  300. /* Read the default parameters from trace.def*/
  301. void get_defaults()
  302.   {
  303.   read_options ("trace.def");
  304.   }
  305.  
  306. void read_options (file_name)
  307.   char *file_name;
  308.   {
  309.   FILE *default_file;
  310.   register int c, String_Index, Option_Started;
  311.   char Option_String[80];
  312.  
  313.   String_Index = 0;
  314.   Option_Started = FALSE;
  315.   if (default_file = fopen(file_name, "r"))
  316.     while ((c = getc(default_file)) != EOF)
  317.       {
  318.       if (Option_Started)
  319.         if (isspace(c))
  320.           {
  321.           Option_String[String_Index] = '\0';
  322.           parse_option (Option_String);
  323.           Option_Started = FALSE;
  324.           }
  325.        else
  326.          Option_String[String_Index++] = (char) c;
  327.  
  328.       else /* Option_Started */
  329.  
  330.         if ((c == (int) '-') || (c == (int) '+'))
  331.           {
  332.           String_Index = 0;
  333.           Option_String[String_Index++] = (char) c;
  334.           Option_Started = TRUE;
  335.           }
  336.         else
  337.           if (!isspace(c))
  338.             {
  339.             printf ("\nBad default file format.  Offending char: (%c), val: %d.\n", (char) c, c);
  340.             exit (0);
  341.         }
  342.       }
  343.  
  344.   if (Option_Started)
  345.     {
  346.     Option_String[String_Index] = '\0';
  347.     parse_option (Option_String);
  348.     }
  349.   }
  350.  
  351. /* parse the command line parameters */
  352. void parse_option (Option_String)
  353.   char *Option_String;
  354.   {
  355.   register int Add_Option;
  356.   unsigned long Option_Number;
  357.   DBL threshold;
  358.  
  359.   if (*(Option_String++) == '-')
  360.     Add_Option = FALSE;
  361.   else
  362.     Add_Option = TRUE;
  363.  
  364.   switch (*Option_String)
  365.     {
  366.     case 'B':
  367.     case 'b':  sscanf (&Option_String[1], "%d", &File_Buffer_Size);
  368.                File_Buffer_Size *= 1024;
  369.                if (File_Buffer_Size < BUFSIZ)
  370.                   File_Buffer_Size = BUFSIZ;
  371.                Option_Number = 0;
  372.                break;
  373.  
  374.     case 'D':
  375.     case 'd':  Option_Number = DISPLAY;
  376.                break;
  377.  
  378.     case 'V':
  379.     case 'v':  Option_Number = VERBOSE;
  380.                break;
  381.  
  382.     case 'W':
  383.     case 'w':  sscanf (&Option_String[1], "%d", &Frame.Screen_Width);
  384.            Option_Number = 0;
  385.                break;
  386.  
  387.     case 'H':
  388.     case 'h':  sscanf (&Option_String[1], "%d", &Frame.Screen_Height);
  389.            Option_Number = 0;
  390.                break;
  391.  
  392.     case 'F':
  393.     case 'f':  Option_Number = DISKWRITE;
  394.                break;
  395.  
  396.     case 'P':
  397.     case 'p':  Option_Number = PROMPTEXIT;
  398.                break;
  399.  
  400.     case 'I':
  401.     case 'i':  strncpy (&Input_File_Name[0], &Option_String[1], FILE_NAME_LENGTH);
  402.            Option_Number = 0;
  403.                break;
  404.  
  405.     case 'O':
  406.     case 'o':  strncpy (&Output_File_Name[0], &Option_String[1], FILE_NAME_LENGTH);
  407.            Option_Number = 0;
  408.                break;
  409.  
  410.     case 'A':
  411.     case 'a':  Option_Number = ANTIALIAS;
  412.                if (sscanf (&Option_String[1], DBL_FORMAT_STRING, &threshold) != EOF)
  413.                    Antialias_Threshold = threshold;
  414.                break;
  415.  
  416.     case 'X':
  417.     case 'x':  Option_Number = EXITENABLE;
  418.                break;
  419.  
  420.     case 'S':
  421.     case 's':  sscanf (&Option_String[1], "%d", &First_Line);
  422.            Option_Number = 0;
  423.                break;
  424.  
  425.     case 'E':
  426.     case 'e':  sscanf (&Option_String[1], "%d", &Last_Line);
  427.            Option_Number = 0;
  428.                break;
  429.  
  430.     case 'Q':
  431.     case 'q':  sscanf (&Option_String[1], "%d", &Quality);
  432.            Option_Number = 0;
  433.                break;
  434.  
  435.     case 'T':
  436.     case 't':  Option_Number = TARGA;
  437.                break;
  438.  
  439.     case 'Z':
  440.     case 'z':  Option_Number = DEBUGGING;
  441.                break;
  442.  
  443.     default:   printf ("\nInvalid option: %s\n\n", --Option_String);
  444.            Option_Number = 0;
  445.     }
  446.  
  447.   if (Option_Number != 0)
  448.       if (Add_Option)
  449.            Options |= Option_Number;
  450.       else Options &= ~Option_Number;
  451.   }
  452.  
  453. void Print_Options()
  454.    {
  455.    printf ("Options in effect: ");
  456.    if (Options & DISPLAY)
  457.       printf ("+d ");
  458.    else
  459.       printf ("-d ");
  460.  
  461.    if (Options & VERBOSE)
  462.       printf ("+v ");
  463.    else
  464.       printf ("-v ");
  465.  
  466.    if (Options & DISKWRITE)
  467.       printf ("+f ");
  468.    else
  469.       printf ("-f ");
  470.  
  471.    if (Options & PROMPTEXIT)
  472.       printf ("+p ");
  473.    else
  474.       printf ("-p ");
  475.  
  476.    if (Options & TARGA)
  477.       printf ("+t ");
  478.    else
  479.       printf ("-t ");
  480.  
  481.    if (Options & EXITENABLE)
  482.       printf ("+x ");
  483.    else
  484.       printf ("-x ");
  485.  
  486.    if (Options & ANTIALIAS)
  487.       printf ("+a%f ", Antialias_Threshold);
  488.    else
  489.       printf ("-a ");
  490.  
  491.    if (File_Buffer_Size != 0)
  492.       printf ("-b%d ", File_Buffer_Size/1024);
  493.  
  494.    printf ("-q%d -w%d -h%d -s%d -e%d -i%s ",
  495.            Quality, Frame.Screen_Width, Frame.Screen_Height,
  496.            First_Line, Last_Line, Input_File_Name);
  497.  
  498.    if (Options & DISKWRITE)
  499.       printf ("-o%s", Output_File_Name);
  500.  
  501.    printf ("\n");
  502.    }
  503.  
  504. void parse_file_name (File_Name)
  505.   char *File_Name;
  506.   {
  507.   File_Names [Number_Of_Files++] = File_Name;  
  508.   if (Number_Of_Files > MAX_FILE_NAMES)
  509.     {
  510.     printf ("\nOnly %d file names are allowed in a command line.", 
  511.              MAX_FILE_NAMES);
  512.     exit(0);
  513.     }
  514.   read_options (File_Name);
  515.   }
  516.  
  517. void print_stats()
  518.    {
  519.    printf ("                  Statistics\n");
  520.    printf ("                  ----------\n\n");
  521.    printf ("# Rays:  %10ld    # Pixels:  %10ld  # Pixels supersampled: %10ld\n\n",
  522.             Number_Of_Rays, Number_Of_Pixels, Number_Of_Pixels_Supersampled);
  523.  
  524.    printf ("\nIntersection Tests:\n\n");
  525.    printf ("   Type       Tests    Succeeded\n");
  526.    printf ("   ----    ----------  ----------\n\n");
  527.    printf ("  Sphere   %10ld  %10ld\n", Ray_Sphere_Tests, Ray_Sphere_Tests_Succeeded);
  528.    printf ("  Plane    %10ld  %10ld\n", Ray_Plane_Tests, Ray_Plane_Tests_Succeeded);
  529.    printf ("  Triangle %10ld  %10ld\n", Ray_Triangle_Tests, Ray_Triangle_Tests_Succeeded);
  530.    printf ("  Quadric  %10ld  %10ld\n", Ray_Quadric_Tests, Ray_Quadric_Tests_Succeeded);
  531.    printf ("  Bounds   %10ld  %10ld\n\n", Bounding_Region_Tests, Bounding_Region_Tests_Succeeded);
  532.    printf ("  Calls to Noise:   %10ld\n", Calls_To_Noise);
  533.    printf ("  Calls to DNoise:  %10ld\n", Calls_To_DNoise);
  534.    printf ("  Shadow Ray Tests: %10ld     Blocking Objects Found:  %10ld\n",
  535.               Shadow_Ray_Tests, Shadow_Rays_Succeeded);
  536.    printf ("  Reflected Rays:   %10ld\n", Reflected_Rays_Traced);
  537.    printf ("  Refracted Rays:   %10ld\n", Refracted_Rays_Traced);
  538.    printf ("  Transmitted Rays: %10ld\n", Transmitted_Rays_Traced);
  539.    }
  540.