home *** CD-ROM | disk | FTP | other *** search
/ Cutting-Edge 3D Game Programming with C++ / CE3DC++.ISO / BOOK / CHAP08 / POLYOBJ.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1996-03-05  |  12.3 KB  |  464 lines

  1. //
  2. //
  3. // File name: PolyObj.CPP
  4. //
  5. // Description: The support file for the PolyObj.HPP header
  6. //
  7. // Author: John De Goes
  8. //
  9. // Project: Cutting Edge 3D Game Programming
  10. //
  11.  
  12. #include <Math.H>
  13. #include <CType.H>
  14. #include <Stdio.H>
  15. #include <String.H>
  16.  
  17. // Temp include:
  18. #include <ConIO.H>
  19. #include <IOStream.H>
  20.  
  21. #include "PolyObj.HPP"
  22. #include "Matrix3D.HPP"
  23. #include "Point3D.HPP"
  24. #include "LightP.HPP"
  25.  
  26. // Logical replacement for "strcmp" - returns true
  27. // if strings match:
  28. int inline Match ( char *S1, char *S2 )
  29.   {
  30.   return !strcmp ( S1, S2 );
  31.   }
  32.  
  33.  
  34. int GetLine ( FILE *InFile, char *String )
  35.    {
  36.    // Reads a line of text from a text file:
  37.    int NextByte = fgetc ( InFile );
  38.    int Index = 0;
  39.    
  40.    // Loop until we reach a new-line character:
  41.    while ( NextByte != '\n' )
  42.          {
  43.          // Check for end of file:
  44.          if ( NextByte == EOF )
  45.             {
  46.             // If found, close off string
  47.             // and return EOF:
  48.             String [ Index ] = '\0';
  49.             return EOF;
  50.             }
  51.  
  52.          // If the next byte is not a space....
  53.          if ( !isspace ( NextByte ) )
  54.             {
  55.             // ....record it:
  56.             String [ Index++ ] = ( char ) NextByte;
  57.             }
  58.             
  59.          // Get the next character:
  60.          NextByte = fgetc ( InFile );
  61.          }
  62.    // Close off the string and return success (true):
  63.    String [ Index ] = '\0';//*/
  64.    return 1;
  65.    }
  66.    
  67. void PanelObject::CalcRadius ()
  68.    {
  69.    // Calculates the radius of the object:
  70.    }
  71.    
  72. void PanelObject::Transform ( Matrix3D &M )
  73.    {
  74.    // Translates/rotates entire vertex list:
  75.    unsigned int Count;
  76.  
  77.    // Transform the vertex list:
  78.    for ( Count = 0; Count < VCount; Count++ )
  79.        {
  80.        M.Transform ( VList [ Count ] );
  81.        }
  82.  
  83.    // Update the normal and other panel-specific data:
  84.    for ( Count = 0; Count < PCount; Count++ )
  85.        {
  86.        PList [ Count ].Update ( M );
  87.        }
  88.    }
  89.  
  90. void PanelObject::Display ( Matrix3D &M, unsigned char *Buffer )
  91.    {
  92.    // Displays a world on screen buffer "Buffer"
  93.    const False = 0;
  94.    // Declare variables:
  95.    unsigned int Count;
  96.  
  97.    // Transform the vertex points:
  98.    Transform ( M );
  99.    
  100.    // Display selected panels in the off-screen buffer:
  101.    for ( Count = 0; Count < PCount; Count++ )
  102.        {
  103.        // Determine if polygon is invisible:
  104.        if ( PList [ Count ].Invisible () == False )
  105.           {
  106.           // If the panel is visible in 3D....
  107.           if ( PList [ Count ].IsVisible3D () )
  108.              {
  109.              // ....project it:
  110.              PList [ Count ].Project ();
  111.  
  112.              // If panel is visible in 2D....
  113.              if ( PList [ Count ].IsVisible2D () )
  114.                 {
  115.                 // ....display it:
  116.                 PList [ Count ].Display ( Buffer );
  117.                 }
  118.  
  119.              }
  120.           }
  121.        }
  122.    } 
  123.  
  124. Point3D PanelObject::LoadCoord ( FILE *InFile )
  125.    {
  126.    // Loads a single coordinate from a text file:
  127.    int PCount = 0;
  128.    char String [ 100 ] = "";
  129.    Point3D Coord;
  130.    while ( PCount < 3 )
  131.          {
  132.          if ( GetLine ( InFile, String ) == EOF )
  133.             {
  134.             Coord.Lx = 0;
  135.             Coord.Ly = 0;
  136.             Coord.Lz = 0;
  137.             break;
  138.             }
  139.  
  140.          // Check for the first X coordinate:
  141.          if ( Match ( String, "10" ) )
  142.             {
  143.             GetLine ( InFile, String );
  144.             Coord.Lx = atof ( String );
  145.             ++PCount;
  146.             }
  147.          // Check for the second X coordinate:
  148.          else if ( Match ( String, "11" ) )
  149.                  {
  150.                  GetLine ( InFile, String );
  151.                  Coord.Lx = atof ( String );
  152.                  ++PCount;
  153.                  }
  154.          // Check for the third X coordinate:
  155.          else if ( Match ( String, "12" ) )
  156.                  {
  157.                  GetLine ( InFile, String );
  158.                  Coord.Lx = atof ( String );
  159.                  ++PCount;
  160.                  }
  161.          // Check for the fourth X coordinate:
  162.          else if ( Match ( String, "13" ) )
  163.                  {
  164.                  GetLine ( InFile, String );
  165.                  Coord.Lx = atof ( String );
  166.                  ++PCount;
  167.                  }
  168.          // Check for the first Y coordinate:
  169.          else if ( Match ( String, "20" ) )
  170.                  {
  171.                  GetLine ( InFile, String );
  172.                  Coord.Ly = atof ( String );
  173.                  ++PCount;
  174.                  }
  175.          // Check for the second Y coordinate:
  176.          else if ( Match ( String, "21" ) )
  177.                  {
  178.                  GetLine ( InFile, String );
  179.                  Coord.Ly = atof ( String );
  180.                  ++PCount;
  181.                  }
  182.          // Check for the third Y coordinate:
  183.          else if ( Match ( String, "22" ) )
  184.                  {
  185.                  GetLine ( InFile, String );
  186.                  Coord.Ly = atof ( String );
  187.                  ++PCount;
  188.                  }
  189.          // Check for the fourth Y coordinate:
  190.          else if ( Match ( String, "23" ) )
  191.                  {
  192.                  GetLine ( InFile, String );
  193.                  Coord.Ly = atof ( String );
  194.                  ++PCount;
  195.                  }
  196.          // Check for the first Z coordinate:
  197.          else if ( Match ( String, "30" ) )
  198.                  {
  199.                  GetLine ( InFile, String );
  200.                  Coord.Lz = atof ( String );
  201.                  ++PCount;
  202.                  }
  203.          // Check for the second Z coordinate:
  204.          else if ( Match ( String, "31" ) )
  205.                  {
  206.                  GetLine ( InFile, String );
  207.                  Coord.Lz = atof ( String );
  208.                  ++PCount;
  209.                  }
  210.          // Check for the third Z coordinate:
  211.          else if ( Match ( String, "32" ) )
  212.                  {
  213.                  GetLine ( InFile, String );
  214.                  Coord.Lz = atof ( String );
  215.                  ++PCount;
  216.                  }
  217.          // Check for the fourth Z coordinate:
  218.          else if ( Match ( String, "33" ) )
  219.                  {
  220.                  GetLine ( InFile, String );
  221.                  Coord.Lz = atof ( String );
  222.                  ++PCount;
  223.                  }
  224.          }
  225.  
  226.    // Return a copy of the loaded vertex:
  227.    return Coord;
  228.    }
  229.  
  230. DWORD PanelObject::CountPanels ( char *FileName )
  231.   {
  232.   // Count the number of panels in a text file:
  233.   char String [ 100 ] = "";
  234.   DWORD PanelCount = 0;
  235.   FILE *InFile;
  236.  
  237.   // Open the file:
  238.   if ( ( InFile = fopen ( FileName, "rt" ) ) == 0 )
  239.      return 0;
  240.  
  241.   // Loop until we come to the end of the file:
  242.   for ( ;; )
  243.       {
  244.       // Get a line of text:
  245.       if ( GetLine ( InFile, String ) == EOF )
  246.          break;
  247.  
  248.       // Search for a panel (3DFACE):
  249.       if ( Match ( String, "3DFACE" ) )
  250.          ++PanelCount;
  251.       }
  252.  
  253.   // Close the file:
  254.   fclose ( InFile );
  255.  
  256.   // Return number of vertices:
  257.   return PanelCount;
  258.   }
  259.    
  260. WORD PanelObject::LoadVerts ( char *FileName )
  261.   {
  262.   // Load all vertices from a DXF text file:
  263.  
  264.   // Declare/initialize variables:
  265.  
  266.   PCount = CountPanels ( FileName );
  267.  
  268.   // Allocate memory for temporary list:
  269.   if ( ( TList = new Point3D [ PCount * 4 ] ) == 0 )
  270.      return 0;
  271.  
  272.   // The vertex index in the temporary list:
  273.   unsigned int VIndex = 0, Count;
  274.  
  275.   // A file structure:
  276.   FILE *InFile;
  277.   
  278.   // Open file - abort if error:
  279.   if ( ( InFile = fopen ( FileName, "rt" ) ) == 0 )
  280.      return 0;
  281.  
  282.   // An all-purpose string:
  283.   char String [ 100 ] = "";
  284.   
  285.   // Loop until we come to the end of the file:
  286.   for ( ;; )
  287.       {
  288.       // Get a line of text:
  289.       if ( GetLine ( InFile, String ) == EOF )
  290.          break;
  291.  
  292.       // If a 3DFACE entity is encountered....
  293.       if ( Match ( "3DFACE", String ) )
  294.          {
  295.          // Load four vertices:
  296.          for ( Count = 0; Count < 4; Count++ )
  297.              {
  298.              // Load the next coordinate:
  299.              Point3D TPoint3D = LoadCoord ( InFile );
  300.              TList [ VIndex++ ] = TPoint3D;   
  301.              }
  302.          }
  303.       }
  304.  
  305.   // Close the file:
  306.   fclose ( InFile );
  307.  
  308.   // Set the vertex count at zero:
  309.   VCount = 0;
  310.  
  311.   // Allocate memory for vertex list - abort if error:
  312.   if ( ( VList = new Point3D [ VIndex ] ) == 0 )
  313.      return 0;
  314.  
  315.   // Copy TList to VList:
  316.   for ( Count = 0; Count < VIndex; Count++ )
  317.       {
  318.       if ( UniqueVert ( TList [ Count ], VList, VCount ) )
  319.          {
  320.          VList [ VCount ] = TList [ Count ];
  321.  
  322.          // Increment the vertex count/index:
  323.          ++VCount;
  324.          }
  325.       }
  326.   
  327.   // Return true (success):
  328.   return 1;
  329.   }
  330.  
  331. WORD PanelObject::LoadPanelData ()
  332.    {
  333.    // Read the panel data from a DXF file:
  334.    // Note: Assumes all vertices have been loaded via member
  335.    //       function "LoadVerts"
  336.  
  337.    // Allocate memory for files:
  338.    if ( ( PList = new Panel3D [ PCount ] ) == 0 )
  339.       return 0;
  340.  
  341.    int VIndex = 0;
  342.  
  343.    // Loop until we come to the end of the file:
  344.    for ( unsigned int PIndex = 0; PIndex < PCount; PIndex++ )
  345.        {
  346.        // Load an entire panel:
  347.        LoadPanel ( VIndex, PIndex );
  348.        }
  349.  
  350.    // Deallocate temporary list data
  351.    delete [] TList;
  352.  
  353.    // Return true (success):
  354.    return 1;
  355.    }
  356.  
  357. WORD PanelObject::LoadPanel ( int &VIndex, int Index )
  358.    {
  359.    // Load a panel from a DXF text file:
  360.  
  361.    // 3DFACE has been found - load four coordinates:
  362.    for ( unsigned int Count = 0; Count < 4; Count++ )
  363.        {
  364.        // Assign a vertex to the panel:
  365.        PList [ Index ].VPoint [ Count ] = 
  366.              &VList [ GetVertIndex (  TList [ VIndex ], 
  367.              VList, VCount ) ];
  368.  
  369.        // Increment the vertex index:
  370.        ++VIndex;
  371.        }
  372.  
  373.    // Calculate panel normal:
  374.    PList [ Index ].InitPosition ();
  375.  
  376.    // Calculate panel's intensity:
  377.    PList [ Index ].CalcInten ();
  378.  
  379.    // Return true (success):
  380.    return 1;
  381.    }
  382.  
  383. void PanelObject::LoadDXF ( char *FileName )
  384.    {
  385.    // Load an object from a DXF text file:
  386.    LoadVerts ( FileName );
  387.    LoadPanelData ();
  388.    }
  389.  
  390. void PanelObject::ReadBIN ( char *FileName )
  391.    {
  392.    // Load an object from a BIN binary file:
  393.    unsigned int VertCount, PanelCount, Count;
  394.    unsigned int short PIndex, VIndex;
  395.    double IPer;
  396.    Point3D TVert;
  397.    FILE *InFile;
  398.    if ( ( InFile = fopen ( FileName, "rb" ) ) == NULL )
  399.       return;
  400.    fread ( &VertCount, sizeof VertCount, 1, InFile );
  401.    fread ( &PanelCount, sizeof PanelCount, 1, InFile );
  402.    // Allocate memory:
  403.    VList = new Point3D [ VertCount ];
  404.    PList = new Panel3D [ PanelCount ];
  405.  
  406.    // Load vertices:
  407.    for ( Count = 0; Count < VertCount; Count++ )
  408.        {
  409.        VList [ Count ].Read ( InFile );
  410.        }
  411.    VCount = VertCount;
  412.    PCount = PanelCount;
  413.  
  414.    cout << "\nReading Polygon Dataset:\n";
  415.    // Load panel data:
  416.    for ( Count = 0; Count < PCount; Count++ )
  417.        {
  418.        IPer = ( ( double ) Count / ( double ) PCount ) * 101.0F;
  419.        cout << ( long ) IPer << "%\r";
  420.        for ( VIndex = 0; VIndex < 4; VIndex++ )
  421.            {
  422.            fread ( &PIndex, sizeof PIndex, 1, InFile );
  423.            PList [ Count ].VPoint [ VIndex ] = &VList [ PIndex ];
  424.            }
  425.        // Calculate the panel normal:
  426.        PList [ Count ].InitPosition ();
  427.  
  428.        // Calculate the panel's intensity:
  429.        PList [ Count ].CalcInten ();
  430.        }
  431.    fclose ( InFile );
  432.    }
  433.  
  434. void PanelObject::WriteBIN ( char *FileName )
  435.    {
  436.    // Write a BIN binary file:
  437.    unsigned int VertCount = VCount, PanelCount = PCount, Count;
  438.    unsigned int short PIndex, VIndex;
  439.    Point3D *PVert;
  440.    FILE *OutFile;
  441.    if ( ( OutFile = fopen ( FileName, "wb" ) ) == NULL )
  442.       return;
  443.    fwrite ( &VertCount, sizeof VertCount, 1, OutFile );
  444.    fwrite ( &PanelCount, sizeof PanelCount, 1, OutFile );
  445.  
  446.    // Write vertex data:
  447.    for ( Count = 0; Count < VCount; Count++ )
  448.        {
  449.        VList [ Count ].Write ( OutFile );
  450.        }
  451.  
  452.    // Write panel data:
  453.    for ( Count = 0; Count < PCount; Count++ )
  454.        {
  455.        for ( VIndex = 0; VIndex < 4; VIndex++ )
  456.            {
  457.            PVert = PList [ Count ].VPoint [ VIndex ];
  458.            PIndex = ( unsigned short ) GetVertIndex ( *PVert, VList, VCount );
  459.            fwrite ( &PIndex, sizeof PIndex, 1, OutFile );
  460.            }
  461.        }
  462.    fclose ( OutFile );
  463.    }
  464.