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