home *** CD-ROM | disk | FTP | other *** search
/ Cutting-Edge 3D Game Programming with C++ / CE3DC++.ISO / BOOK / CHAP10 / PERSP / POLYOBJ.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-19  |  17.0 KB  |  620 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. #include "TextType.HPP"
  26.  
  27. // Logical replacement for "strcmp" - returns true
  28. // if strings match:
  29. int inline Match ( char *S1, char *S2 )
  30.   {
  31.   return !strcmp ( S1, S2 );
  32.   }
  33.  
  34.  
  35. int GetLine ( FILE *InFile, char *String )
  36.    {
  37.    // Reads a line of text from a text file:
  38.    int NextByte = fgetc ( InFile );
  39.    int Index = 0;
  40.    
  41.    // Loop until we reach a new-line character:
  42.    while ( NextByte != '\n' )
  43.          {
  44.          // Check for end of file:
  45.          if ( NextByte == EOF )
  46.             {
  47.             // If found, close off string
  48.             // and return EOF:
  49.             String [ Index ] = '\0';
  50.             return EOF;
  51.             }
  52.  
  53.          // If the next byte is not a space....
  54.          if ( !isspace ( NextByte ) )
  55.             {
  56.             // ....record it:
  57.             String [ Index++ ] = ( char ) NextByte;
  58.             }
  59.             
  60.          // Get the next character:
  61.          NextByte = fgetc ( InFile );
  62.          }
  63.    // Close off the string and return success (true):
  64.    String [ Index ] = '\0';//*/
  65.    return 1;
  66.    }
  67.    
  68. void PanelObject::CalcRadius ()
  69.    {
  70.    // Calculates the radius of the object:
  71.    }
  72.    
  73. void PanelObject::Transform ( Matrix3D &M )
  74.    {
  75.    // Translates/rotates entire vertex list:
  76.    unsigned int Count;
  77.  
  78.    // Transform the vertex list:
  79.    for ( Count = 0; Count < VCount; Count++ )
  80.        {
  81.        M.Transform ( VList [ Count ] );
  82.        }
  83.  
  84.    // Update the normal and other panel-specific data:
  85.    for ( Count = 0; Count < PCount; Count++ )
  86.        {
  87.        PList [ Count ].Update ( M );
  88.        }
  89.    }
  90.  
  91. void PanelObject::Display ( Matrix3D &M, unsigned char *Buffer )
  92.    {
  93.    // Displays a world on screen buffer "Buffer"
  94.    const False = 0;
  95.    // Declare variables:
  96.    unsigned int Count;
  97.  
  98.    // Transform the vertex points:
  99.    Transform ( M );
  100.  
  101.    if ( ( Select < 0 ) || ( Select >= PCount ) || 
  102.         ( PList [ Select ].Invis > 0 ) )
  103.       {
  104.       SelNext ();
  105.       }
  106.  
  107.    // Display selected panels in the off-screen buffer:
  108.    for ( Count = 0; Count < PCount; Count++ )
  109.        {
  110.        // Determine if polygon is invisible:
  111.        if ( PList [ Count ].Invisible () == False )
  112.           {
  113.           // If the panel is visible in 3D....
  114.           if ( PList [ Count ].IsVisible3D () )
  115.              {
  116.              // ....project it:
  117.              PList [ Count ].Project ();
  118.  
  119.              // If panel is visible in 2D....
  120.              if ( PList [ Count ].IsVisible2D () )
  121.                 {
  122.                 // ....display it:
  123.                 PList [ Count ].Display ( Buffer );
  124.                 }
  125.  
  126.              }
  127.           }
  128.        }
  129.    } 
  130.  
  131. void PanelObject::SelNext ()
  132.    {
  133.    int OldSelect = Select % PCount, Count;
  134.    // Deselect all old panels:
  135.    for ( Count = 0; Count < PCount; Count++ )
  136.        PList [ Count ].Deselect ();
  137.  
  138.    // Select the next visible panel:
  139.    Select = ( Select + 1 ) % PCount;
  140.    while ( PList [ Select ].Invis > 0 )
  141.          {
  142.          if ( Select == OldSelect ) 
  143.             {
  144.             Select = -1;
  145.             break;
  146.             }
  147.          Select = ( Select + 1 ) % PCount;
  148.          }
  149.    if ( Select != -1 )
  150.       PList [ Select ].Select ();
  151.    }
  152.  
  153. void PanelObject::MoveText ( int Ox, int Oy, int Tx, int Ty )
  154.    {
  155.    double Dist [ 5 ], X, Y;
  156.    long Count, ScreenCount, MinDist;
  157.    // Make sure selection is in allowed range:
  158.    if ( ( Select >= 0 ) && ( Select < PCount ) )
  159.       {
  160.       PList [ Select ].Project ();
  161.       ScreenCount = PList [ Select ].SPCount;
  162.       if ( ScreenCount > 4 )
  163.          ScreenCount = 4;
  164.       // Calculate the distance from each vertex to (Ox, Oy):
  165.       for ( Count = 0; Count < ScreenCount; Count++ )
  166.           {
  167.           X = PList [ Select ].SPoint [ Count ].X;
  168.           Y = PList [ Select ].SPoint [ Count ].Y;
  169.           Dist [ Count ] = sqrt ( ( X - Ox ) * ( X - Ox ) +
  170.                                   ( Y - Oy ) * ( Y - Oy ) );
  171.           }
  172.       // Select minimum distance:
  173.       MinDist = 0;
  174.       for ( Count = 1; Count < ScreenCount; Count++ )
  175.           {
  176.           if ( Dist [ Count ] < Dist [ MinDist ] )
  177.              MinDist = Count;
  178.           }
  179.       // Translate texture vertex by specified amount:
  180.       PList [ Select ].Attrib [ MinDist ].U += Tx;
  181.       PList [ Select ].Attrib [ MinDist ].V += Ty;
  182.       // Clip selected translation:
  183.       if ( PList [ Select ].Attrib [ MinDist ].U < 0 )
  184.          PList [ Select ].Attrib [ MinDist ].U = 0;
  185.  
  186.       if ( PList [ Select ].Attrib [ MinDist ].V < 0 )
  187.          PList [ Select ].Attrib [ MinDist ].V = 0;
  188.  
  189.       if ( PList [ Select ].Attrib [ MinDist ].U >=
  190.            TextDat.TMap [ PList [ Select ].TextHan ].Width )
  191.          {
  192.          PList [ Select ].Attrib [ MinDist ].U = 
  193.              ( TextDat.TMap [ PList [ Select ].TextHan ].Width 
  194.                - 1 );
  195.          }
  196.  
  197.       if ( PList [ Select ].Attrib [ MinDist ].V >=
  198.            TextDat.TMap [ PList [ Select ].TextHan ].Height )
  199.          {
  200.          PList [ Select ].Attrib [ MinDist ].V = 
  201.              ( TextDat.TMap [ PList [ Select ].TextHan ].Height 
  202.                - 1 );
  203.          }
  204.       }
  205.    }
  206.  
  207. void PanelObject::InitDefText ()
  208.    {
  209.    double IPer;
  210.    long Count;
  211.    cout << "\nInitializing texture-shade data:\n";
  212.    for ( Count = 0; Count < PCount; Count++ )
  213.        {
  214.        IPer = ( ( double ) Count / ( double ) PCount ) * 101.0F;
  215.        cout << ( long ) IPer << "%\r";
  216.        PList [ Count ].Attrib [ 0 ].U = 0;
  217.        PList [ Count ].Attrib [ 0 ].V = 0;
  218.        PList [ Count ].Attrib [ 0 ].I = PList [ Count ].Color;
  219.  
  220.        PList [ Count ].Attrib [ 1 ].U = TextDat.TMap [ 0 ].Width - 1;
  221.        PList [ Count ].Attrib [ 1 ].V = 0;
  222.        PList [ Count ].Attrib [ 1 ].I = PList [ Count ].Color;
  223.  
  224.        PList [ Count ].Attrib [ 2 ].U = TextDat.TMap [ 0 ].Width - 1;
  225.        PList [ Count ].Attrib [ 2 ].V = TextDat.TMap [ 0 ].Height - 1;
  226.        PList [ Count ].Attrib [ 2 ].I = PList [ Count ].Color;
  227.  
  228.        PList [ Count ].Attrib [ 3 ].U = 0;
  229.        PList [ Count ].Attrib [ 3 ].V = TextDat.TMap [ 0 ].Height - 1;
  230.        PList [ Count ].Attrib [ 3 ].I = PList [ Count ].Color;
  231.  
  232.        PList [ Count ].TextHan = 0;
  233.        }
  234.    }
  235.  
  236. Point3D PanelObject::LoadCoord ( FILE *InFile )
  237.    {
  238.    // Loads a single coordinate from a text file:
  239.    int PCount = 0;
  240.    char String [ 100 ] = "";
  241.    Point3D Coord;
  242.    while ( PCount < 3 )
  243.          {
  244.          if ( GetLine ( InFile, String ) == EOF )
  245.             {
  246.             Coord.Lx = 0;
  247.             Coord.Ly = 0;
  248.             Coord.Lz = 0;
  249.             break;
  250.             }
  251.  
  252.          // Check for the first X coordinate:
  253.          if ( Match ( String, "10" ) )
  254.             {
  255.             GetLine ( InFile, String );
  256.             Coord.Lx = atof ( String );
  257.             ++PCount;
  258.             }
  259.          // Check for the second X coordinate:
  260.          else if ( Match ( String, "11" ) )
  261.                  {
  262.                  GetLine ( InFile, String );
  263.                  Coord.Lx = atof ( String );
  264.                  ++PCount;
  265.                  }
  266.          // Check for the third X coordinate:
  267.          else if ( Match ( String, "12" ) )
  268.                  {
  269.                  GetLine ( InFile, String );
  270.                  Coord.Lx = atof ( String );
  271.                  ++PCount;
  272.                  }
  273.          // Check for the fourth X coordinate:
  274.          else if ( Match ( String, "13" ) )
  275.                  {
  276.                  GetLine ( InFile, String );
  277.                  Coord.Lx = atof ( String );
  278.                  ++PCount;
  279.                  }
  280.          // Check for the first Y coordinate:
  281.          else if ( Match ( String, "20" ) )
  282.                  {
  283.                  GetLine ( InFile, String );
  284.                  Coord.Ly = atof ( String );
  285.                  ++PCount;
  286.                  }
  287.          // Check for the second Y coordinate:
  288.          else if ( Match ( String, "21" ) )
  289.                  {
  290.                  GetLine ( InFile, String );
  291.                  Coord.Ly = atof ( String );
  292.                  ++PCount;
  293.                  }
  294.          // Check for the third Y coordinate:
  295.          else if ( Match ( String, "22" ) )
  296.                  {
  297.                  GetLine ( InFile, String );
  298.                  Coord.Ly = atof ( String );
  299.                  ++PCount;
  300.                  }
  301.          // Check for the fourth Y coordinate:
  302.          else if ( Match ( String, "23" ) )
  303.                  {
  304.                  GetLine ( InFile, String );
  305.                  Coord.Ly = atof ( String );
  306.                  ++PCount;
  307.                  }
  308.          // Check for the first Z coordinate:
  309.          else if ( Match ( String, "30" ) )
  310.                  {
  311.                  GetLine ( InFile, String );
  312.                  Coord.Lz = atof ( String );
  313.                  ++PCount;
  314.                  }
  315.          // Check for the second Z coordinate:
  316.          else if ( Match ( String, "31" ) )
  317.                  {
  318.                  GetLine ( InFile, String );
  319.                  Coord.Lz = atof ( String );
  320.                  ++PCount;
  321.                  }
  322.          // Check for the third Z coordinate:
  323.          else if ( Match ( String, "32" ) )
  324.                  {
  325.                  GetLine ( InFile, String );
  326.                  Coord.Lz = atof ( String );
  327.                  ++PCount;
  328.                  }
  329.          // Check for the fourth Z coordinate:
  330.          else if ( Match ( String, "33" ) )
  331.                  {
  332.                  GetLine ( InFile, String );
  333.                  Coord.Lz = atof ( String );
  334.                  ++PCount;
  335.                  }
  336.          }
  337.  
  338.    // Return a copy of the loaded vertex:
  339.    return Coord;
  340.    }
  341.  
  342. DWORD PanelObject::CountPanels ( char *FileName )
  343.   {
  344.   // Count the number of panels in a text file:
  345.   char String [ 100 ] = "";
  346.   DWORD PanelCount = 0;
  347.   FILE *InFile;
  348.  
  349.   // Open the file:
  350.   if ( ( InFile = fopen ( FileName, "rt" ) ) == 0 )
  351.      return 0;
  352.  
  353.   // Loop until we come to the end of the file:
  354.   for ( ;; )
  355.       {
  356.       // Get a line of text:
  357.       if ( GetLine ( InFile, String ) == EOF )
  358.          break;
  359.  
  360.       // Search for a panel (3DFACE):
  361.       if ( Match ( String, "3DFACE" ) )
  362.          ++PanelCount;
  363.       }
  364.  
  365.   // Close the file:
  366.   fclose ( InFile );
  367.  
  368.   // Return number of vertices:
  369.   return PanelCount;
  370.   }
  371.    
  372. WORD PanelObject::LoadVerts ( char *FileName )
  373.   {
  374.   // Load all vertices from a DXF text file:
  375.  
  376.   // Declare/initialize variables:
  377.  
  378.   PCount = CountPanels ( FileName );
  379.  
  380.   // Allocate memory for temporary list:
  381.   if ( ( TList = new Point3D [ PCount * 4 ] ) == 0 )
  382.      return 0;
  383.  
  384.   // The vertex index in the temporary list:
  385.   unsigned int VIndex = 0, Count;
  386.  
  387.   // A file structure:
  388.   FILE *InFile;
  389.   
  390.   // Open file - abort if error:
  391.   if ( ( InFile = fopen ( FileName, "rt" ) ) == 0 )
  392.      return 0;
  393.  
  394.   // An all-purpose string:
  395.   char String [ 100 ] = "";
  396.   
  397.   // Loop until we come to the end of the file:
  398.   for ( ;; )
  399.       {
  400.       // Get a line of text:
  401.       if ( GetLine ( InFile, String ) == EOF )
  402.          break;
  403.  
  404.       // If a 3DFACE entity is encountered....
  405.       if ( Match ( "3DFACE", String ) )
  406.          {
  407.          // Load four vertices:
  408.          for ( Count = 0; Count < 4; Count++ )
  409.              {
  410.              // Load the next coordinate:
  411.              Point3D TPoint3D = LoadCoord ( InFile );
  412.              TList [ VIndex++ ] = TPoint3D;   
  413.              }
  414.          }
  415.       }
  416.  
  417.   // Close the file:
  418.   fclose ( InFile );
  419.  
  420.   // Set the vertex count at zero:
  421.   VCount = 0;
  422.  
  423.   // Allocate memory for vertex list - abort if error:
  424.   if ( ( VList = new Point3D [ VIndex ] ) == 0 )
  425.      return 0;
  426.  
  427.   // Copy TList to VList:
  428.   for ( Count = 0; Count < VIndex; Count++ )
  429.       {
  430.       if ( UniqueVert ( TList [ Count ], VList, VCount ) )
  431.          {
  432.          VList [ VCount ] = TList [ Count ];
  433.  
  434.          // Increment the vertex count/index:
  435.          ++VCount;
  436.          }
  437.       }
  438.   
  439.   // Return true (success):
  440.   return 1;
  441.   }
  442.  
  443. WORD PanelObject::LoadPanelData ()
  444.    {
  445.    // Read the panel data from a DXF file:
  446.    // Note: Assumes all vertices have been loaded via member
  447.    //       function "LoadVerts"
  448.  
  449.    // Allocate memory for files:
  450.    if ( ( PList = new Panel3D [ PCount ] ) == 0 )
  451.       return 0;
  452.  
  453.    int VIndex = 0;
  454.  
  455.    // Loop until we come to the end of the file:
  456.    for ( unsigned int PIndex = 0; PIndex < PCount; PIndex++ )
  457.        {
  458.        // Load an entire panel:
  459.        LoadPanel ( VIndex, PIndex );
  460.        }
  461.  
  462.    // Deallocate temporary list data
  463.    delete [] TList;
  464.  
  465.    // Return true (success):
  466.    return 1;
  467.    }
  468.  
  469. WORD PanelObject::LoadPanel ( int &VIndex, int Index )
  470.    {
  471.    // Load a panel from a DXF text file:
  472.  
  473.    // 3DFACE has been found - load four coordinates:
  474.    for ( unsigned int Count = 0; Count < 4; Count++ )
  475.        {
  476.        // Assign a vertex to the panel:
  477.        PList [ Index ].VPoint [ Count ] = 
  478.              &VList [ GetVertIndex (  TList [ VIndex ], 
  479.              VList, VCount ) ];
  480.  
  481.        // Increment the vertex index:
  482.        ++VIndex;
  483.        }
  484.  
  485.    // Calculate panel normal:
  486.    PList [ Index ].InitPosition ();
  487.  
  488.    // Calculate panel's intensity:
  489.    PList [ Index ].CalcInten ();
  490.  
  491.    // Return true (success):
  492.    return 1;
  493.    }
  494.  
  495. void PanelObject::LoadDXF ( char *FileName )
  496.    {
  497.    // Load an object from a DXF text file:
  498.    LoadVerts ( FileName );
  499.    LoadPanelData ();
  500.    }
  501.  
  502. void PanelObject::ReadBIN ( char *FileName )
  503.    {
  504.    // Load an object from a BIN binary file:
  505.    unsigned int VertCount, PanelCount, Count;
  506.    unsigned int short PIndex, VIndex;
  507.    double IPer;
  508.    Point3D TVert;
  509.    FILE *InFile;
  510.    if ( ( InFile = fopen ( FileName, "rb" ) ) == NULL )
  511.       return;
  512.    fread ( &VertCount, sizeof VertCount, 1, InFile );
  513.    fread ( &PanelCount, sizeof PanelCount, 1, InFile );
  514.    // Allocate memory:
  515.    VList = new Point3D [ VertCount ];
  516.    PList = new Panel3D [ PanelCount ];
  517.  
  518.    // Load vertices:
  519.    for ( Count = 0; Count < VertCount; Count++ )
  520.        {
  521.        VList [ Count ].Read ( InFile );
  522.        }
  523.    VCount = VertCount;
  524.    PCount = PanelCount;
  525.  
  526.    cout << "\nReading Polygon Dataset:\n";
  527.    // Load panel data:
  528.    for ( Count = 0; Count < PCount; Count++ )
  529.        {
  530.        IPer = ( ( double ) Count / ( double ) PCount ) * 101.0F;
  531.        cout << ( long ) IPer << "%\r";
  532.        for ( VIndex = 0; VIndex < 4; VIndex++ )
  533.            {
  534.            fread ( &PIndex, sizeof PIndex, 1, InFile );
  535.            PList [ Count ].VPoint [ VIndex ] = &VList [ PIndex ];
  536.            }
  537.        // Calculate the panel normal:
  538.        PList [ Count ].InitPosition ();
  539.  
  540.        // Calculate the panel's intensity:
  541.        PList [ Count ].CalcInten ();
  542.        }
  543.    fclose ( InFile );
  544.    }
  545.  
  546. void PanelObject::WriteBIN ( char *FileName )
  547.    {
  548.    // Write a BIN binary file:
  549.    unsigned int VertCount = VCount, PanelCount = PCount, Count;
  550.    unsigned int short PIndex, VIndex;
  551.    Point3D *PVert;
  552.    FILE *OutFile;
  553.    if ( ( OutFile = fopen ( FileName, "wb" ) ) == NULL )
  554.       return;
  555.    fwrite ( &VertCount, sizeof VertCount, 1, OutFile );
  556.    fwrite ( &PanelCount, sizeof PanelCount, 1, OutFile );
  557.  
  558.    // Write vertex data:
  559.    for ( Count = 0; Count < VCount; Count++ )
  560.        {
  561.        VList [ Count ].Write ( OutFile );
  562.        }
  563.  
  564.    // Write panel data:
  565.    for ( Count = 0; Count < PCount; Count++ )
  566.        {
  567.        for ( VIndex = 0; VIndex < 4; VIndex++ )
  568.            {
  569.            PVert = PList [ Count ].VPoint [ VIndex ];
  570.            PIndex = ( unsigned short ) GetVertIndex ( *PVert, VList, VCount );
  571.            fwrite ( &PIndex, sizeof PIndex, 1, OutFile );
  572.            }
  573.        }
  574.    fclose ( OutFile );
  575.    }
  576.  
  577. int PanelObject::ReadText ( char *FileName )
  578.   {
  579.   long Count;
  580.   FILE *InFile;
  581.   if ( ( InFile = fopen ( FileName, "rb" ) ) == 0 )
  582.      return 0;
  583.   // Load the textures:
  584.   TextDat.LoadBT ( InFile );
  585.  
  586.   // Load the texture coordinates and handles:
  587.   for ( Count = 0; Count < PCount; Count++ )
  588.       {
  589.       fread ( &PList [ Count ].TextHan, 
  590.               sizeof PList [ Count ].TextHan, 1, InFile );
  591.       fread ( PList [ Count ].Attrib, sizeof ( Detail3D ), 4, 
  592.               InFile );
  593.       }
  594.   fclose ( InFile );
  595.  
  596.   return 1;
  597.   }
  598.  
  599. int PanelObject::WriteText ( char *FileName )
  600.   {
  601.   long Count;
  602.   FILE *OutFile;
  603.   if ( ( OutFile = fopen ( FileName, "wb" ) ) == 0 )
  604.      return 0;
  605.   // Save the textures:
  606.   TextDat.SaveBT ( OutFile );
  607.  
  608.   // Save the texture coordinates and handles:
  609.   for ( Count = 0; Count < PCount; Count++ )
  610.       {
  611.       fwrite ( &PList [ Count ].TextHan, 
  612.                sizeof PList [ Count ].TextHan, 1, OutFile );
  613.       fwrite ( PList [ Count ].Attrib, sizeof ( Detail3D ), 4, 
  614.                OutFile );
  615.       }
  616.   fclose ( OutFile );
  617.  
  618.   return 1;
  619.   }
  620.