home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Professional / OS2PRO194.ISO / os2 / graphic / dkb / source / trace.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-04  |  17.4 KB  |  569 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. *     OMX              (613) 731-3419
  39. *     Mystic           (613) 596-4249  or  (613) 596-4772
  40. *
  41. *  Fidonet:   1:163/109.9
  42. *  Internet:  dbuck@ccs.carleton.ca
  43. *  The "You Can Call Me RAY" BBS    (708) 358-5611
  44. *
  45. *  IBM Port by Aaron A. Collins. Aaron may be reached on the following BBS'es:
  46. *
  47. *     The "You Can Call Me RAY" BBS (708) 358-5611
  48. *     The Information Exchange BBS  (708) 945-5575
  49. *
  50. *****************************************************************************/
  51.  
  52. #include <ctype.h>
  53. #include <time.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 int Options;
  59. int Quality;
  60.  
  61. FILE *bfp;
  62.  
  63. extern FRAME Frame;
  64.  
  65. /* this define is copied from bsedos.h */
  66. #define CCHMAXPATH 260
  67. char Output_File_Name [CCHMAXPATH];
  68.  
  69. #define MAX_LIBRARIES 10
  70. char *Library_Paths [MAX_LIBRARIES];
  71. int Library_Path_Index;
  72.  
  73. FILE_HANDLE *Output_File_Handle;
  74. int File_Buffer_Size;
  75. static int Number_Of_Files;
  76. DBL VTemp;
  77. DBL Antialias_Threshold;
  78. int First_Line, Last_Line;
  79. int Screen_Width, Screen_Height;
  80.  
  81. /* Stats kept by the ray tracer: */
  82. long Number_Of_Pixels, Number_Of_Rays, Number_Of_Pixels_Supersampled;
  83. long Ray_Sphere_Tests, Ray_Sphere_Tests_Succeeded;
  84. long Ray_Plane_Tests, Ray_Plane_Tests_Succeeded;
  85. long Ray_Triangle_Tests, Ray_Triangle_Tests_Succeeded;
  86. long Ray_Quadric_Tests, Ray_Quadric_Tests_Succeeded;
  87. long Ray_Quartic_Tests, Ray_Quartic_Tests_Succeeded;
  88. long Bounding_Region_Tests, Bounding_Region_Tests_Succeeded;
  89. long Calls_To_Noise, Calls_To_DNoise;
  90. long Shadow_Ray_Tests, Shadow_Rays_Succeeded;
  91. long Reflected_Rays_Traced, Refracted_Rays_Traced;
  92. long Transmitted_Rays_Traced;
  93.  
  94. char OutputFormat;
  95.  
  96. extern time_t  Start_Time, Previous_Time;
  97. extern int Stop_Flag;
  98.  
  99. void text_main (argc, argv)
  100.   int argc;
  101.   char **argv;
  102.   {
  103.   register int i;
  104.  
  105.     PRINT ("\n");
  106.   PRINT ("DKB Ray Trace Version 2.12 Copyright (c) 1991 David K. Buck\n");
  107.     PRINT ("\n");
  108.   PRINT ("Written by: David K. Buck (dbuck@ccs.carleton.ca) (CIS: 70521, 1371)\n");
  109.   PRINT ("     22C Sonnet Cr. Nepean, Ontario Canada, K2H 8W7\n");
  110.   PRINT ("Conversion to IBM PC with TARGA output and other improvements by Aaron A. Collins\n");
  111.   PRINT ("GIF format file reader by Steve A. Bennett\n");
  112.   PRINT ("Noise and DNoise functions by Robert Skinner\n");
  113.   PRINT ("Quartic (4th order) Shapes by Alexander Enzmann\n");
  114.     PRINT ("Conversion to OS/2 2.0 PM by Michael Caldwell (mcaldwel@netcom.com).\n");
  115.   PRINT ("This program is freely distributable.\n");
  116.     PRINT ("\n");
  117.  
  118.   PRINT_OTHER_CREDITS
  119.  
  120. /* initialize defaults */
  121.   init_options();
  122.  
  123. /* Read the default parameters from trace.def */
  124.   get_defaults();
  125.  
  126. /* Parse the command line parameters */
  127.   for (i = 1 ; i < argc ; i++ )
  128.     if ((*argv[i] == '+') || (*argv[i] == '-'))
  129.       parse_option(argv[i]);
  130.     else
  131.       parse_file_name(argv[i]);
  132. }
  133.  
  134. void StartTrace (char * Input_File_Name) {
  135.  
  136.     init_vars ();
  137.  
  138.     PRINT ("Input File: %s\n", Input_File_Name);
  139.     if (Options & DISKWRITE)
  140.         PRINT ("Output File: %s\n", Output_File_Name);
  141.    Print_Options ();
  142.  
  143.    Initialize_Tokenizer (Input_File_Name);
  144.    PRINT ("Parsing...");
  145.    Parse (&Frame);
  146.    Terminate_Tokenizer();
  147.  
  148. /* Get things ready for ray tracing */
  149.     Output_File_Handle = NULL;
  150.    if (Options & DISKWRITE) {
  151.       switch (OutputFormat) {
  152.          case 'd':
  153.             Output_File_Handle = Get_Dump_File_Handle();
  154.                 if (Output_File_Handle == NULL) {
  155.                     PRINT ("Error: cannot get output file handle.\n");
  156.                 }
  157.             break;
  158.  
  159.          case 'r':
  160.             Output_File_Handle = Get_Raw_File_Handle();
  161.                 if (Output_File_Handle == NULL) {
  162.                     PRINT ("Error: cannot get output file handle.\n");
  163.                 }
  164.             break;
  165.  
  166.          case 't':
  167.             Output_File_Handle = Get_Targa_File_Handle();
  168.                 if (Output_File_Handle == NULL) {
  169.                     PRINT ("Error: cannot get output file handle.\n");
  170.                 }
  171.             break;
  172.  
  173.          default:
  174.             PRINT ("Error: unrecognized output file format %c.\n", OutputFormat);
  175.       }
  176.         if (Output_File_Handle) {
  177.           if (Open_File (Output_File_Handle, Output_File_Name,
  178.                    &Frame.Screen_Width, &Frame.Screen_Height, File_Buffer_Size,
  179.                    WRITE_MODE) != 1) {
  180.             /* must do a Close_File to free dynamically allocated memory */
  181.               Close_File (Output_File_Handle);
  182.                 Output_File_Handle = NULL;
  183.              PRINT ("Error: cannot open output file.\n");
  184.            }
  185.        }
  186.    }
  187.  
  188.     initialize_renderer();
  189.     pq_init();
  190.     Initialize_Noise();
  191.  
  192. /* Ok, go for it - trace the picture */
  193.     PRINT ("Rendering...\n");
  194.     Start_Tracing ();
  195.     if (Stop_Flag) {
  196.         PRINT ("Aborted.\n");
  197.     } else {
  198.         PRINT ("Done.\n");
  199.     }
  200.     PRINT ("\n");
  201.  
  202.     if (Output_File_Handle)
  203.         Close_File (Output_File_Handle);
  204. }
  205.  
  206. void usage ()
  207.     {
  208.     PRINT ("\n");
  209.     PRINT ("Usage:\n");
  210.     PRINT ("     tracepm [{+|-}Option]... [option file]\n");
  211.     PRINT ("\n");
  212.     PRINT ("Options:\n");
  213.     PRINT ("     d  = display image\n");
  214.     PRINT ("     v  = display statistics\n");
  215.     PRINT ("     fx = write output file in format x\n");
  216.     PRINT ("          ft - Uncompressed Targa-24  fd - DKB/QRT Dump  fr - 3 Raw Files\n");
  217.     PRINT ("     a  = perform antialiasing\n");
  218.     PRINT ("     qx = image quality 0=rough, 9=full\n");
  219.     PRINT ("     lxxx = library path prefix\n");
  220.     PRINT ("     wxxx = width of the screen\n");
  221.     PRINT ("     hxxx = height of the screen\n");
  222.     PRINT ("     bxxx = Use xxx kilobytes for output file buffer space\n");
  223.     PRINT ("\n");
  224.     }
  225.  
  226. init_options () {
  227.     Options = 0;
  228.     Quality = 9;
  229.     Frame.Screen_Width = 160;
  230.     Screen_Width = Frame.Screen_Width;
  231.     Frame.Screen_Height = 120;
  232.     Screen_Height = Frame.Screen_Height;
  233.     Antialias_Threshold = 0.3;
  234.     File_Buffer_Size = 0;
  235.     Library_Paths [0] = NULL;
  236.     Library_Path_Index = 0;
  237.     return;
  238. }
  239.  
  240. void init_vars() {
  241.     Frame.Screen_Width = Screen_Width;
  242.     Frame.Screen_Height = Screen_Height;
  243.     Frame.Antialias_Threshold = Antialias_Threshold;
  244.     First_Line = 0;
  245.     Last_Line = Frame.Screen_Height;
  246.     Number_Of_Pixels = 0L;
  247.     Number_Of_Rays = 0L;
  248.     Number_Of_Pixels_Supersampled = 0L;
  249.     Ray_Sphere_Tests = 0L;
  250.     Ray_Sphere_Tests_Succeeded = 0L;
  251.     Ray_Plane_Tests = 0L;
  252.     Ray_Plane_Tests_Succeeded = 0L;
  253.     Ray_Triangle_Tests = 0L;
  254.     Ray_Triangle_Tests_Succeeded = 0L;
  255.     Ray_Quadric_Tests = 0L;
  256.     Ray_Quadric_Tests_Succeeded = 0L;
  257.     Ray_Quartic_Tests = 0L;
  258.     Ray_Quartic_Tests_Succeeded = 0L;
  259.     Bounding_Region_Tests = 0L;
  260.     Bounding_Region_Tests_Succeeded = 0L;
  261.     Calls_To_Noise = 0L;
  262.     Calls_To_DNoise = 0L;
  263.     Shadow_Ray_Tests = 0L;
  264.     Shadow_Rays_Succeeded = 0L;
  265.     Reflected_Rays_Traced = 0L;
  266.     Refracted_Rays_Traced = 0L;
  267.     Transmitted_Rays_Traced = 0L;
  268.     return;
  269. }
  270.  
  271. /* Read the default parameters from trace.def */
  272. void get_defaults()
  273.   {
  274.   FILE *defaults_file;
  275.   char Option_String[256], *Option_String_Ptr;
  276.  
  277.   if ((defaults_file = fopen("trace.def", "r")) != NULL) {
  278.      while (fgets(Option_String, 256, defaults_file) != NULL)
  279.         read_options(Option_String);
  280.      fclose (defaults_file);
  281.      }
  282.  
  283.   if ((Option_String_Ptr = getenv("DKBOPT")) != NULL)
  284.      read_options(Option_String_Ptr);
  285.   }
  286.  
  287. void read_options (Option_Line)
  288.   char *Option_Line;
  289.   {
  290.   register int c, String_Index, Option_Started;
  291.   short Option_Line_Index = 0;
  292.   char Option_String[80];
  293.  
  294.   String_Index = 0;
  295.   Option_Started = FALSE;
  296.   while ((c = Option_Line[Option_Line_Index++]) != '\0')
  297.     {
  298.     if (Option_Started)
  299.       if (isspace(c))
  300.         {
  301.         Option_String[String_Index] = '\0';
  302.         parse_option (Option_String);
  303.         Option_Started = FALSE;
  304.     String_Index = 0;
  305.         }
  306.      else
  307.        Option_String[String_Index++] = (char) c;
  308.  
  309.     else /* Option_Started */
  310.       if ((c == (int) '-') || (c == (int) '+'))
  311.         {
  312.         String_Index = 0;
  313.         Option_String[String_Index++] = (char) c;
  314.         Option_Started = TRUE;
  315.         }
  316.       else
  317.         if (!isspace(c))
  318.           {
  319.           PRINT ("Error: bad option format, char: (%c) val: %d.\n",
  320.                     (char) c, c);
  321.             usage ();
  322.             return;
  323.           }
  324.     }
  325.  
  326.   if (Option_Started)
  327.     {
  328.     Option_String[String_Index] = '\0';
  329.     parse_option (Option_String);
  330.     }
  331.   }
  332.  
  333. /* parse the command line parameters */
  334. void parse_option (Option_String)
  335.   char *Option_String;
  336.   {
  337.   register int Add_Option;
  338.   unsigned int Option_Number;
  339.   DBL threshold;
  340.  
  341.   if (*(Option_String++) == '-')
  342.     Add_Option = FALSE;
  343.   else
  344.     Add_Option = TRUE;
  345.  
  346.   switch (*Option_String)
  347.     {
  348.     case 'B':
  349.     case 'b':  sscanf (&Option_String[1], "%d", &File_Buffer_Size);
  350.                File_Buffer_Size *= 1024;
  351.                if (File_Buffer_Size < BUFSIZ)
  352.                   File_Buffer_Size = BUFSIZ;
  353.                Option_Number = 0;
  354.                break;
  355.  
  356.     case 'D':
  357.     case 'd':  Option_Number = DISPLAY;
  358.                break;
  359.  
  360.     case 'V':
  361.     case 'v':  Option_Number = VERBOSE;
  362.                break;
  363.  
  364.     case 'W':
  365.     case 'w':  sscanf (&Option_String[1], "%d", &Frame.Screen_Width);
  366.                     Screen_Width = Frame.Screen_Width;
  367.                     Option_Number = 0;
  368.                break;
  369.  
  370.     case 'H':
  371.     case 'h':  sscanf (&Option_String[1], "%d", &Frame.Screen_Height);
  372.                     Screen_Height = Frame.Screen_Height;
  373.                      Option_Number = 0;
  374.                break;
  375.  
  376.     case 'F':
  377.     case 'f':  Option_Number = DISKWRITE;
  378.                if (isupper(Option_String[1]))
  379.                   OutputFormat = (char)tolower(Option_String[1]);
  380.                else
  381.                   OutputFormat = Option_String[1];
  382.  
  383.                if (OutputFormat == '\0')
  384.                   OutputFormat = DEFAULT_OUTPUT_FORMAT;
  385.                break;
  386.  
  387.     case 'A':
  388.     case 'a':  Option_Number = ANTIALIAS;
  389.                if (sscanf (&Option_String[1], DBL_FORMAT_STRING, &threshold) != EOF)
  390.                    Antialias_Threshold = threshold;
  391.                break;
  392.  
  393.     case 'L':
  394.     case 'l':
  395.         if (Library_Path_Index < MAX_LIBRARIES) {
  396.            Library_Paths [Library_Path_Index] = malloc (strlen(Option_String));
  397.           if (Library_Paths [Library_Path_Index]) {
  398.              strcpy (Library_Paths [Library_Path_Index], &Option_String[1]);
  399.              Library_Path_Index++;
  400.             } else {
  401.                PRINT ("Error: cannot allocate memory for library pathname %s.\n",
  402.                          Option_String);
  403.             }
  404.         } else {
  405.          PRINT ("Error: more than %d library directories specified.\n",
  406.                     MAX_LIBRARIES);
  407.       }
  408.  
  409.        Option_Number = 0;
  410.       break;
  411.  
  412.     case 'Q':
  413.     case 'q':  sscanf (&Option_String[1], "%d", &Quality);
  414.            Option_Number = 0;
  415.                break;
  416.  
  417.                /* Turn on debugging print statements. */
  418.     case 'Z':
  419.     case 'z':  Option_Number = DEBUGGING;
  420.                break;
  421.  
  422.     default:   PRINT ("Error: invalid option %s.\n", --Option_String);
  423.             usage ();
  424.             return;
  425.     }
  426.  
  427.   if (Option_Number != 0)
  428.       if (Add_Option)
  429.            Options |= Option_Number;
  430.       else Options &= ~Option_Number;
  431.   }
  432.  
  433. void Print_Options()
  434.    {
  435.     char szOptions [128];
  436.     char * pszOptions;
  437.    int i;
  438.  
  439.     pszOptions = szOptions;
  440.  
  441.    pszOptions += sprintf (pszOptions, "Options in effect: ");
  442.  
  443.    if (Options & DISPLAY)
  444.       pszOptions += sprintf (pszOptions, "+d ");
  445.    else
  446.       pszOptions += sprintf (pszOptions, "-d ");
  447.  
  448.    if (Options & VERBOSE)
  449.       pszOptions += sprintf (pszOptions, "+v ");
  450.    else
  451.       pszOptions += sprintf (pszOptions, "-v ");
  452.  
  453.    if (Options & DISKWRITE)
  454.       pszOptions += sprintf (pszOptions, "+f%c ", OutputFormat);
  455.    else
  456.       pszOptions += sprintf (pszOptions, "-f ");
  457.  
  458.    if (Options & ANTIALIAS)
  459.       pszOptions += sprintf (pszOptions, "+a%f ", Antialias_Threshold);
  460.    else
  461.       pszOptions += sprintf (pszOptions, "-a ");
  462.  
  463.    if (Options & DEBUGGING)
  464.       pszOptions += sprintf (pszOptions, "+z ");
  465.  
  466.    if (File_Buffer_Size != 0)
  467.       pszOptions += sprintf (pszOptions, "-b%d ", File_Buffer_Size / 1024);
  468.  
  469.    pszOptions += sprintf (pszOptions, "-q%d -w%d -h%d", Quality,
  470.             Frame.Screen_Width, Frame.Screen_Height);
  471.  
  472.    for (i = 0 ; i < Library_Path_Index ; i++)
  473.       pszOptions += sprintf (pszOptions, " -l%s ", Library_Paths[i]);
  474.  
  475.     PRINT (szOptions);
  476.    PRINT ("\n");
  477.    }
  478.  
  479. void parse_file_name (File_Name)
  480.   char *File_Name;
  481.   {
  482.   FILE *defaults_file;
  483.   char Option_String[256];
  484.  
  485.   if (++Number_Of_Files > MAX_FILE_NAMES)
  486.     {
  487.     PRINT ("Only %d option file(s) are allowed in a command line.\n",
  488.             MAX_FILE_NAMES);
  489.     return;
  490.     }
  491.  
  492.   if ((defaults_file = fopen(File_Name, "r")) != NULL) {
  493.      while (fgets(Option_String, 256, defaults_file) != NULL)
  494.         read_options(Option_String);
  495.      fclose (defaults_file);
  496.      }
  497.   }
  498.  
  499. #ifdef TEXTMODE
  500. void print_line_stats (register int y) {
  501.     time_t      Current_Time;
  502.     time_t      Time;
  503.     time_t      Temp;
  504.  
  505.     Current_Time = time (NULL);
  506. /* keep the number of "\n"s down to 25 */
  507.     PRINT ("\n");
  508.     PRINT ("Statistics for line %04d\n", y);
  509.     PRINT ("------------------------\n\n");
  510.     PRINT ("# Rays: %10ld   # Pixels: %10ld   # Pixels supersampled: %10ld\n\n", Number_Of_Rays, Number_Of_Pixels, Number_Of_Pixels_Supersampled);
  511.     PRINT ("Intersection Tests:   Type          Tests    Succeeded\n");
  512.     PRINT ("                      ----     ----------   ----------\n");
  513.     PRINT ("                      Sphere   %10ld   %10ld\n", Ray_Sphere_Tests, Ray_Sphere_Tests_Succeeded);
  514.     PRINT ("                      Plane    %10ld   %10ld\n", Ray_Plane_Tests, Ray_Plane_Tests_Succeeded);
  515.     PRINT ("                      Triangle %10ld   %10ld\n", Ray_Triangle_Tests, Ray_Triangle_Tests_Succeeded);
  516.     PRINT ("                      Quadric  %10ld   %10ld\n", Ray_Quadric_Tests, Ray_Quadric_Tests_Succeeded);
  517.     PRINT ("                      Quartic  %10ld   %10ld\n", Ray_Quartic_Tests, Ray_Quartic_Tests_Succeeded);
  518.     PRINT ("                      Bounds   %10ld   %10ld\n\n", Bounding_Region_Tests, Bounding_Region_Tests_Succeeded);
  519.     PRINT ("   Calls to Noise:         %10ld\n", Calls_To_Noise);
  520.     PRINT ("   Calls to DNoise:        %10ld\n", Calls_To_DNoise);
  521.     PRINT ("   Shadow Ray Tests:       %10ld\n", Shadow_Ray_Tests);
  522.     PRINT ("   Blocking Objects Found: %10ld\n", Shadow_Rays_Succeeded);
  523.     PRINT ("   Reflected Rays:         %10ld\n", Reflected_Rays_Traced);
  524.     PRINT ("   Refracted Rays:         %10ld\n", Refracted_Rays_Traced);
  525.     PRINT ("   Transmitted Rays:       %10ld\n", Transmitted_Rays_Traced);
  526.     Time = Current_Time - Previous_Time;
  527.    PRINT ("   Time for this line:     %02dd", Temp = Time / 86400);
  528.     PRINT (" %02dh", Temp = (Time -= Temp * 86400) / 3600);
  529.     PRINT (" %02dm", Temp = (Time -= Temp * 3600) / 60);
  530.     PRINT (" %02ds\n", Time - Temp * 60);
  531.     Time = Current_Time - Start_Time;
  532.    PRINT ("   Total elapsed time:     %02dd", Temp = Time / 86400);
  533.     PRINT (" %02dh", Temp = (Time -= Temp * 86400) / 3600);
  534.     PRINT (" %02dm", Temp = (Time -= Temp * 3600) / 60);
  535.     PRINT (" %02ds\n", Time - Temp * 60);
  536.     Time = (Current_Time - Start_Time) / (y + 1);
  537.    PRINT ("   Average time per line:  %02dd", Temp = Time / 86400);
  538.     PRINT (" %02dh", Temp = (Time -= Temp * 86400) / 3600);
  539.     PRINT (" %02dm", Temp = (Time -= Temp * 3600) / 60);
  540.     PRINT (" %02ds", Time - Temp * 60);
  541.    Previous_Time = time (NULL);
  542.     PRINT ("                    I/O %ds\n", Previous_Time - Current_Time);
  543. }
  544. #endif
  545.  
  546. /* Find a file in the search path. */
  547. FILE *Locate_File (filename, mode)
  548.    char *filename, *mode;
  549.    {
  550.    FILE *f;
  551.    int i;
  552.    char pathname[CCHMAXPATH];
  553.  
  554.    /* Check the current directory first. */
  555.    if ((f = fopen (filename, mode)) != NULL)
  556.       return (f);
  557.  
  558.    for (i = 0 ; i < Library_Path_Index ; i++) {
  559.       strcpy (pathname, Library_Paths[i]);
  560.       if (FILENAME_SEPARATOR != NULL)
  561.          strcat (pathname, FILENAME_SEPARATOR);
  562.       strcat (pathname, filename);
  563.       if ((f = fopen (pathname, mode)) != NULL)
  564.          return (f);
  565.       }
  566.  
  567.    return (NULL);
  568.    }
  569.