home *** CD-ROM | disk | FTP | other *** search
/ Cutting-Edge 3D Game Programming with C++ / CE3DC++.ISO / BOOK / CHAP12 / POLYOBJ.CPP < prev    next >
C/C++ Source or Header  |  1996-04-23  |  26KB  |  884 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. #include "PalShade.HPP"
  27.  
  28. extern float GlobalStep;
  29.  
  30. // Logical replacement for "strcmp" - returns true
  31. // if strings match:
  32. int inline Match ( char *S1, char *S2 )
  33.   {
  34.   return !strcmp ( S1, S2 );
  35.   }
  36.  
  37.  
  38. int GetLine ( FILE *InFile, char *String )
  39.    {
  40.    // Reads a line of text from a text file:
  41.    int NextByte = fgetc ( InFile );
  42.    int Index = 0;
  43.    
  44.    // Loop until we reach a new-line character:
  45.    while ( NextByte != '\n' )
  46.          {
  47.          // Check for end of file:
  48.          if ( NextByte == EOF )
  49.             {
  50.             // If found, close off string
  51.             // and return EOF:
  52.             String [ Index ] = '\0';
  53.             return EOF;
  54.             }
  55.  
  56.          // If the next byte is not a space....
  57.          if ( !isspace ( NextByte ) )
  58.             {
  59.             // ....record it:
  60.             String [ Index++ ] = ( char ) NextByte;
  61.             }
  62.             
  63.          // Get the next character:
  64.          NextByte = fgetc ( InFile );
  65.          }
  66.    // Close off the string and return success (true):
  67.    String [ Index ] = '\0';//*/
  68.    return 1;
  69.    }
  70.    
  71. void PanelObject::CalcRadius ()
  72.    {
  73.    // Calculates the radius of the object:
  74.    }
  75.    
  76. void PanelObject::Transform ( Matrix3D &M )
  77.    {
  78.    // Translates/rotates/morphs entire vertex list:
  79.    unsigned int Count;
  80.  
  81.    // Transform the vertex list:
  82.    if ( ( Morph ) && ( StartMorph ) )
  83.       {
  84.       for ( Count = 0; Count < VCount; Count++ )
  85.           {
  86.           M.Transform ( VList [ Count ] );
  87.           // Perform the morph:
  88.           VList [ Count ] += MList [ Count ];
  89.           }
  90.       }
  91.  
  92.    else {
  93.         for ( Count = 0; Count < VCount; Count++ )
  94.             {
  95.             M.Transform ( VList [ Count ] );
  96.             }
  97.         }
  98.  
  99.    // Update the normal and other panel-specific data:
  100.    for ( Count = 0; Count < PCount; Count++ )
  101.        {
  102.        PList [ Count ].Update ( M );
  103.        }
  104.    }
  105.  
  106. void PanelObject::Display ( Matrix3D &M, unsigned char *Buffer )
  107.    {
  108.    // Displays a world on screen buffer "Buffer"
  109.    const False = 0;
  110.    // Declare variables:
  111.    unsigned int Count;
  112.  
  113.    // Transform the vertex points:
  114.    Transform ( M );
  115.  
  116.    if ( ( Select < 0 ) || ( Select >= PCount ) || 
  117.         ( PList [ Select ].Invis > 0 ) )
  118.       {
  119.       SelNext ();
  120.       }
  121.  
  122.    // Display selected panels in the off-screen buffer:
  123.    for ( Count = 0; Count < PCount; Count++ )
  124.        {
  125.        // Determine if polygon is invisible:
  126.        if ( PList [ Count ].Invisible () == False )
  127.           {
  128.           // If the panel is visible in 3D....
  129.           if ( PList [ Count ].IsVisible3D () )
  130.              {
  131.              // ....project it:
  132.              PList [ Count ].Project ();
  133.  
  134.              // If panel is visible in 2D....
  135.              if ( PList [ Count ].IsVisible2D () )
  136.                 {
  137.                 // ....display it:
  138.                 PList [ Count ].Display ( Buffer );
  139.                 }
  140.  
  141.              }
  142.           }
  143.        }
  144.    } 
  145.  
  146. void PanelObject::SelNext ()
  147.    {
  148.    int OldSelect = ( Select % PCount ), Count;
  149.    // Deselect all old panels:
  150.    for ( Count = 0; Count < PCount; Count++ )
  151.        PList [ Count ].Deselect ();
  152.  
  153.    // Select the next visible panel:
  154.    Select = ( Select + 1 ) % PCount;
  155.    while ( PList [ Select ].Invis > 0 )
  156.          {
  157.          if ( Select == OldSelect ) 
  158.             {
  159.             Select = -1;
  160.             break;
  161.             }
  162.          Select = ( Select + 1 ) % PCount;
  163.          }
  164.    if ( Select != -1 )
  165.       PList [ Select ].Select ();
  166.    }
  167.  
  168. void PanelObject::MoveText ( int Ox, int Oy, int Tx, int Ty )
  169.    {
  170.    float Dist [ 5 ], X, Y;
  171.    long Count, ScreenCount, MinDist;
  172.    // Make sure selection is in allowed range:
  173.    if ( ( Select >= 0 ) && ( Select < PCount ) )
  174.       {
  175.       PList [ Select ].Project ();
  176.       ScreenCount = PList [ Select ].SPCount;
  177.       if ( ScreenCount > 4 )
  178.          ScreenCount = 4;
  179.       // Calculate the distance from each vertex to (Ox, Oy):
  180.       for ( Count = 0; Count < ScreenCount; Count++ )
  181.           {
  182.           X = PList [ Select ].SPoint [ Count ].X;
  183.           Y = PList [ Select ].SPoint [ Count ].Y;
  184.           Dist [ Count ] = sqrt ( ( X - Ox ) * ( X - Ox ) +
  185.                                   ( Y - Oy ) * ( Y - Oy ) );
  186.           }
  187.       // Select minimum distance:
  188.       MinDist = 0;
  189.       for ( Count = 1; Count < ScreenCount; Count++ )
  190.           {
  191.           if ( Dist [ Count ] < Dist [ MinDist ] )
  192.              MinDist = Count;
  193.           }
  194.       // Translate texture vertex by specified amount:
  195.       PList [ Select ].Attrib [ MinDist ].U += Tx;
  196.       PList [ Select ].Attrib [ MinDist ].V += Ty;
  197.       // Clip selected translation:
  198.       if ( PList [ Select ].Attrib [ MinDist ].U < 0 )
  199.          PList [ Select ].Attrib [ MinDist ].U = 0;
  200.  
  201.       if ( PList [ Select ].Attrib [ MinDist ].V < 0 )
  202.          PList [ Select ].Attrib [ MinDist ].V = 0;
  203.  
  204.       if ( PList [ Select ].Attrib [ MinDist ].U >=
  205.            TextDat.TMap [ PList [ Select ].TextHan ].Width )
  206.          {
  207.          PList [ Select ].Attrib [ MinDist ].U = 
  208.              ( TextDat.TMap [ PList [ Select ].TextHan ].Width 
  209.                - 1 );
  210.          }
  211.  
  212.       if ( PList [ Select ].Attrib [ MinDist ].V >=
  213.            TextDat.TMap [ PList [ Select ].TextHan ].Height )
  214.          {
  215.          PList [ Select ].Attrib [ MinDist ].V = 
  216.              ( TextDat.TMap [ PList [ Select ].TextHan ].Height 
  217.                - 1 );
  218.          }
  219.       }
  220.    }
  221.  
  222. void PanelObject::NextInten ( int Sx, int Sy )
  223.    {
  224.    float Dist [ 5 ], X, Y;
  225.    long Count, ScreenCount, MinDist;
  226.    // Make sure selection is in allowed range:
  227.    if ( ( Select >= 0 ) && ( Select < PCount ) )
  228.       {
  229.       PList [ Select ].Project ();
  230.       ScreenCount = PList [ Select ].SPCount;
  231.       if ( ScreenCount > 4 )
  232.          ScreenCount = 4;
  233.       // Calculate the distance from each vertex to (Sx, Sy):
  234.       for ( Count = 0; Count < ScreenCount; Count++ )
  235.           {
  236.           X = PList [ Select ].SPoint [ Count ].X;
  237.           Y = PList [ Select ].SPoint [ Count ].Y;
  238.           Dist [ Count ] = sqrt ( ( X - Sx ) * ( X - Sx ) +
  239.                                   ( Y - Sy ) * ( Y - Sy ) );
  240.           }
  241.       // Select minimum distance:
  242.       MinDist = 0;
  243.       for ( Count = 1; Count < ScreenCount; Count++ )
  244.           {
  245.           if ( Dist [ Count ] < Dist [ MinDist ] )
  246.              MinDist = Count;
  247.           }
  248.       // Select next intensity:
  249.       ++PList [ Select ].Attrib [ MinDist ].I;
  250.       if ( PList [ Select ].Attrib [ MinDist ].I > ( SHADE_COUNT - 1 ) )
  251.          PList [ Select ].Attrib [ MinDist ].I = 0;
  252.       }
  253.    }
  254.  
  255. void PanelObject::InitDefText ()
  256.    {
  257.    float IPer;
  258.    long Count, Odd, Tri;
  259.    cout << "\nInitializing texture-shade data:\n";
  260.    for ( Count = 0; Count < PCount; Count++ )
  261.        {
  262.        IPer = ( ( float ) Count / ( float ) PCount ) * 101.0F;
  263.        cout << ( long ) IPer << "%\r";
  264.        Odd = Count % 2;
  265.        PList [ Count ].TextHan = 0;
  266.        Tri = 0;
  267.        if ( ( *PList [ Count ].VPoint [ 0 ] ) == 
  268.             ( *PList [ Count ].VPoint [ 1 ] ) )
  269.           Tri = 1;
  270.        else if ( ( *PList [ Count ].VPoint [ 0 ] ) == 
  271.                  ( *PList [ Count ].VPoint [ 2 ] ) )
  272.                Tri = 1;
  273.        else if ( ( *PList [ Count ].VPoint [ 0 ] ) == 
  274.                  ( *PList [ Count ].VPoint [ 3 ] ) )
  275.                Tri = 1;
  276.  
  277.        else if ( ( *PList [ Count ].VPoint [ 1 ] ) == 
  278.                  ( *PList [ Count ].VPoint [ 2 ] ) )
  279.                Tri = 1;
  280.        else if ( ( *PList [ Count ].VPoint [ 1 ] ) == 
  281.                  ( *PList [ Count ].VPoint [ 3 ] ) )
  282.                Tri = 1;
  283.  
  284.        else if ( ( *PList [ Count ].VPoint [ 2 ] ) == 
  285.                  ( *PList [ Count ].VPoint [ 3 ] ) )
  286.                Tri = 1;
  287.  
  288.        if ( Tri )
  289.           {
  290.           if ( !Odd )
  291.              {
  292.              PList [ Count ].Attrib [ 3 ].U = 0;
  293.              PList [ Count ].Attrib [ 3 ].V = 0;
  294.              PList [ Count ].Attrib [ 3 ].I = PList [ Count ].Color;
  295.  
  296.              PList [ Count ].Attrib [ 2 ].U = TextDat.TMap [ 0 ].Width - 1;
  297.              PList [ Count ].Attrib [ 2 ].V = 0;
  298.              PList [ Count ].Attrib [ 2 ].I = PList [ Count ].Color;
  299.  
  300.              PList [ Count ].Attrib [ 1 ].U = TextDat.TMap [ 0 ].Width - 1;
  301.              PList [ Count ].Attrib [ 1 ].V = TextDat.TMap [ 0 ].Height - 1;
  302.              PList [ Count ].Attrib [ 1 ].I = PList [ Count ].Color;
  303.  
  304.              PList [ Count ].Attrib [ 0 ].U = TextDat.TMap [ 0 ].Width - 1;
  305.              PList [ Count ].Attrib [ 0 ].V = TextDat.TMap [ 0 ].Height - 1;
  306.              PList [ Count ].Attrib [ 0 ].I = PList [ Count ].Color;
  307.              }
  308.           if ( Odd )
  309.              {
  310.              PList [ Count ].Attrib [ 3 ].U = 0;
  311.              PList [ Count ].Attrib [ 3 ].V = 0;
  312.              PList [ Count ].Attrib [ 3 ].I = PList [ Count ].Color;
  313.  
  314.              PList [ Count ].Attrib [ 2 ].U = TextDat.TMap [ 0 ].Width - 1;
  315.              PList [ Count ].Attrib [ 2 ].V = TextDat.TMap [ 0 ].Height - 1;
  316.              PList [ Count ].Attrib [ 2 ].I = PList [ Count ].Color;
  317.  
  318.              PList [ Count ].Attrib [ 1 ].U = 0;
  319.              PList [ Count ].Attrib [ 1 ].V = TextDat.TMap [ 0 ].Height - 1;
  320.              PList [ Count ].Attrib [ 1 ].I = PList [ Count ].Color;
  321.  
  322.              PList [ Count ].Attrib [ 0 ].U = 0;
  323.              PList [ Count ].Attrib [ 0 ].V = TextDat.TMap [ 0 ].Height - 1;
  324.              PList [ Count ].Attrib [ 0 ].I = PList [ Count ].Color;
  325.              }
  326.            }
  327.        else {
  328.             PList [ Count ].Attrib [ 0 ].U = 0;
  329.             PList [ Count ].Attrib [ 0 ].V = 0;
  330.             PList [ Count ].Attrib [ 0 ].I = PList [ Count ].Color;
  331.  
  332.             PList [ Count ].Attrib [ 1 ].U = TextDat.TMap [ 0 ].Width - 1;
  333.             PList [ Count ].Attrib [ 1 ].V = 0;
  334.             PList [ Count ].Attrib [ 1 ].I = PList [ Count ].Color;
  335.  
  336.             PList [ Count ].Attrib [ 2 ].U = TextDat.TMap [ 0 ].Width - 1;
  337.             PList [ Count ].Attrib [ 2 ].V = TextDat.TMap [ 0 ].Height - 1;
  338.             PList [ Count ].Attrib [ 2 ].I = PList [ Count ].Color;
  339.  
  340.             PList [ Count ].Attrib [ 3 ].U = 0;
  341.             PList [ Count ].Attrib [ 3 ].V = TextDat.TMap [ 0 ].Height - 1;
  342.             PList [ Count ].Attrib [ 3 ].I = PList [ Count ].Color;
  343.             }
  344.        }
  345.    }
  346.  
  347. int PanelObject::MorphTo ( char *FileName, float Steps )
  348.   {
  349.   // Note: FileName must be a BIN file
  350.   // Load an object from a BIN binary file:
  351.    unsigned int VertCount, PanelCount, Count;
  352.    Point3D TVert;
  353.    FILE *InFile;
  354.  
  355.    StartMorph = 1;
  356.  
  357.    if ( ( InFile = fopen ( FileName, "rb" ) ) == NULL )
  358.       return 0;
  359.    fread ( &VertCount, sizeof VertCount, 1, InFile );
  360.    fread ( &PanelCount, sizeof PanelCount, 1, InFile );
  361.  
  362.    if ( VertCount != VCount )
  363.       {
  364.       fclose ( InFile );
  365.       return 0;
  366.       }
  367.  
  368.    // Allocate memory:
  369.    TList = new Point3D [ VertCount ];
  370.  
  371.    if ( !Morph )
  372.       {
  373.       Morph = 1;
  374.       MList = new Point3D [ VertCount ];
  375.       }
  376.  
  377.    // Load vertices:
  378.    for ( Count = 0; Count < VertCount; Count++ )
  379.        {
  380.        TList [ Count ].Read ( InFile );
  381.        }
  382.  
  383.   // Generate morphing data to morph VList to TList:
  384.   for ( Count = 0; Count < VertCount; Count++ )
  385.       {
  386.       MList [ Count ] = ( TList [ Count ] - VList [ Count ] ) /
  387.                         Steps;
  388.       }
  389.  
  390.   // Delete memory:
  391.   delete [] TList;
  392.  
  393.   // Close file:
  394.   fclose ( InFile );
  395.  
  396.   // Return success:
  397.   return 1;
  398.   }
  399.  
  400. void PanelObject::MorphRev ()
  401.    {
  402.    // Reverse the direction of the morph:
  403.    DWORD Count;
  404.    for ( Count = 0; Count < VCount; Count++ )
  405.        {
  406.        MList [ Count ] = MList [ Count ] * -1.0F;
  407.        }
  408.    }
  409.  
  410. void WRITE ( char *Message, float Value )
  411.    {
  412.    static int Opened = 0;
  413.    FILE *File;
  414.    if ( !Opened )
  415.       {
  416.       File = fopen ( "Debug.DAT", "wt" );
  417.       Opened = 1;
  418.       }
  419.    else File = fopen ( "Debug.DAT", "at" );
  420.    fprintf ( File, Message, Value );
  421.    fclose ( File );
  422.    }
  423.  
  424. int PanelObject::Collide ( float &X, float &Y, float &Z,
  425.                            float Rad )
  426.   {
  427.   long Count;
  428.   float Dist, X2, Y2, Z2, A, B, C, D, Sign, MinDist, NormY;
  429.   const float NOSE = 300.0F, VIEW_HEIGHT = 700.0F;
  430.   Y -= VIEW_HEIGHT;
  431.   for ( Count = 0; Count < PCount; Count++ )
  432.       {
  433.       X2 = ( PList [ Count ].VPoint [ 0 ]->Wx +
  434.              PList [ Count ].VPoint [ 1 ]->Wx +
  435.              PList [ Count ].VPoint [ 2 ]->Wx +
  436.              PList [ Count ].VPoint [ 3 ]->Wx ) / 4.0F;
  437.  
  438.       Y2 = ( PList [ Count ].VPoint [ 0 ]->Wy +
  439.              PList [ Count ].VPoint [ 1 ]->Wy +
  440.              PList [ Count ].VPoint [ 2 ]->Wy +
  441.              PList [ Count ].VPoint [ 3 ]->Wy ) / 4.0F;
  442.  
  443.       Z2 = ( PList [ Count ].VPoint [ 0 ]->Wz +
  444.              PList [ Count ].VPoint [ 1 ]->Wz +
  445.              PList [ Count ].VPoint [ 2 ]->Wz +
  446.              PList [ Count ].VPoint [ 3 ]->Wz ) / 4.0F;
  447.  
  448.       // Calculate distance to panel:
  449.       Dist = sqrt ( ( X2 - X ) * ( X2 - X ) +
  450.                     ( Y2 - Y ) * ( Y2 - Y ) +
  451.                     ( Z2 - Z ) * ( Z2 - Z ) );
  452.       // Check for possible collision by using bounding sphere:
  453.       MinDist = Rad + PList [ Count ].Radius;
  454.       if ( Dist <= MinDist )
  455.          {
  456.          // Confirm/reject collision warning by calculating
  457.          // which side of the plane the viewer will be on:
  458.          A = ( PList [ Count ].Normal.Tx -
  459.                PList [ Count ].VPoint [ 0 ]->Wx );
  460.          B = ( PList [ Count ].Normal.Ty -
  461.                PList [ Count ].VPoint [ 0 ]->Wy );
  462.          C = ( PList [ Count ].Normal.Tz -
  463.                PList [ Count ].VPoint [ 0 ]->Wz );
  464.          D = -( A * PList [ Count ].VPoint [ 0 ]->Wx +
  465.                 B * PList [ Count ].VPoint [ 0 ]->Wy +
  466.                 C * PList [ Count ].VPoint [ 0 ]->Wz );
  467.          Sign = A * X + B * Y + C * ( Z + NOSE ) + D;
  468.          if ( Sign <= 0.0F )
  469.             {
  470.             // Collision is definite:
  471.  
  472.             // Store the Y component of the panel normal:
  473.             NormY = B;
  474.  
  475.             // If panel is a wall....
  476.             if ( fabs ( NormY ) < sqrt ( 0.5F ) )
  477.                {
  478.                if ( A )
  479.                   {
  480.                   Z = ( A * X + B * Y + D ) / ( -C ) + 10.0F - NOSE;
  481.                   X = ( B * Y + C * ( Z + NOSE ) + D ) / ( -A );
  482.                   }
  483.                else X = Z = 0.0F;
  484.                }
  485.             // Else panel is a floor or ceiling....
  486.             else {
  487.                  // Determine if panel is a floor:
  488.                  if ( NormY > 0.0F )
  489.                     {
  490.                     Y = ( A * X + C * Z + D ) / ( - B );
  491.                     }
  492.                  }
  493.             }
  494.          }
  495.       }
  496.   Y += VIEW_HEIGHT;
  497.   return 0;
  498.   }
  499.  
  500. Point3D PanelObject::LoadCoord ( FILE *InFile )
  501.    {
  502.    // Loads a single coordinate from a text file:
  503.    int PCount = 0;
  504.    char String [ 100 ] = "";
  505.    Point3D Coord;
  506.    while ( PCount < 3 )
  507.          {
  508.          if ( GetLine ( InFile, String ) == EOF )
  509.             {
  510.             Coord.Lx = 0;
  511.             Coord.Ly = 0;
  512.             Coord.Lz = 0;
  513.             break;
  514.             }
  515.  
  516.          // Check for the first X coordinate:
  517.          if ( Match ( String, "10" ) )
  518.             {
  519.             GetLine ( InFile, String );
  520.             Coord.Lx = atof ( String );
  521.             ++PCount;
  522.             }
  523.          // Check for the second X coordinate:
  524.          else if ( Match ( String, "11" ) )
  525.                  {
  526.                  GetLine ( InFile, String );
  527.                  Coord.Lx = atof ( String );
  528.                  ++PCount;
  529.                  }
  530.          // Check for the third X coordinate:
  531.          else if ( Match ( String, "12" ) )
  532.                  {
  533.                  GetLine ( InFile, String );
  534.                  Coord.Lx = atof ( String );
  535.                  ++PCount;
  536.                  }
  537.          // Check for the fourth X coordinate:
  538.          else if ( Match ( String, "13" ) )
  539.                  {
  540.                  GetLine ( InFile, String );
  541.                  Coord.Lx = atof ( String );
  542.                  ++PCount;
  543.                  }
  544.          // Check for the first Y coordinate:
  545.          else if ( Match ( String, "20" ) )
  546.                  {
  547.                  GetLine ( InFile, String );
  548.                  Coord.Ly = atof ( String );
  549.                  ++PCount;
  550.                  }
  551.          // Check for the second Y coordinate:
  552.          else if ( Match ( String, "21" ) )
  553.                  {
  554.                  GetLine ( InFile, String );
  555.                  Coord.Ly = atof ( String );
  556.                  ++PCount;
  557.                  }
  558.          // Check for the third Y coordinate:
  559.          else if ( Match ( String, "22" ) )
  560.                  {
  561.                  GetLine ( InFile, String );
  562.                  Coord.Ly = atof ( String );
  563.                  ++PCount;
  564.                  }
  565.          // Check for the fourth Y coordinate:
  566.          else if ( Match ( String, "23" ) )
  567.                  {
  568.                  GetLine ( InFile, String );
  569.                  Coord.Ly = atof ( String );
  570.                  ++PCount;
  571.                  }
  572.          // Check for the first Z coordinate:
  573.          else if ( Match ( String, "30" ) )
  574.                  {
  575.                  GetLine ( InFile, String );
  576.                  Coord.Lz = atof ( String );
  577.                  ++PCount;
  578.                  }
  579.          // Check for the second Z coordinate:
  580.          else if ( Match ( String, "31" ) )
  581.                  {
  582.                  GetLine ( InFile, String );
  583.                  Coord.Lz = atof ( String );
  584.                  ++PCount;
  585.                  }
  586.          // Check for the third Z coordinate:
  587.          else if ( Match ( String, "32" ) )
  588.                  {
  589.                  GetLine ( InFile, String );
  590.                  Coord.Lz = atof ( String );
  591.                  ++PCount;
  592.                  }
  593.          // Check for the fourth Z coordinate:
  594.          else if ( Match ( String, "33" ) )
  595.                  {
  596.                  GetLine ( InFile, String );
  597.                  Coord.Lz = atof ( String );
  598.                  ++PCount;
  599.                  }
  600.          }
  601.  
  602.    // Return a copy of the loaded vertex:
  603.    return Coord;
  604.    }
  605.  
  606. DWORD PanelObject::CountPanels ( char *FileName )
  607.   {
  608.   // Count the number of panels in a text file:
  609.   char String [ 100 ] = "";
  610.   DWORD PanelCount = 0;
  611.   FILE *InFile;
  612.  
  613.   // Open the file:
  614.   if ( ( InFile = fopen ( FileName, "rt" ) ) == 0 )
  615.      return 0;
  616.  
  617.   // Loop until we come to the end of the file:
  618.   for ( ;; )
  619.       {
  620.       // Get a line of text:
  621.       if ( GetLine ( InFile, String ) == EOF )
  622.          break;
  623.  
  624.       // Search for a panel (3DFACE):
  625.       if ( Match ( String, "3DFACE" ) )
  626.          ++PanelCount;
  627.       }
  628.  
  629.   // Close the file:
  630.   fclose ( InFile );
  631.  
  632.   // Return number of vertices:
  633.   return PanelCount;
  634.   }
  635.    
  636. WORD PanelObject::LoadVerts ( char *FileName )
  637.   {
  638.   // Load all vertices from a DXF text file:
  639.  
  640.   // Declare/initialize variables:
  641.  
  642.   PCount = CountPanels ( FileName );
  643.  
  644.   // Allocate memory for temporary list:
  645.   if ( ( TList = new Point3D [ PCount * 4 ] ) == 0 )
  646.      return 0;
  647.  
  648.   // The vertex index in the temporary list:
  649.   unsigned int VIndex = 0, Count;
  650.  
  651.   // A file structure:
  652.   FILE *InFile;
  653.   
  654.   // Open file - abort if error:
  655.   if ( ( InFile = fopen ( FileName, "rt" ) ) == 0 )
  656.      return 0;
  657.  
  658.   // An all-purpose string:
  659.   char String [ 100 ] = "";
  660.   
  661.   // Loop until we come to the end of the file:
  662.   for ( ;; )
  663.       {
  664.       // Get a line of text:
  665.       if ( GetLine ( InFile, String ) == EOF )
  666.          break;
  667.  
  668.       // If a 3DFACE entity is encountered....
  669.       if ( Match ( "3DFACE", String ) )
  670.          {
  671.          // Load four vertices:
  672.          for ( Count = 0; Count < 4; Count++ )
  673.              {
  674.              // Load the next coordinate:
  675.              Point3D TPoint3D = LoadCoord ( InFile );
  676.              TList [ VIndex++ ] = TPoint3D;   
  677.              }
  678.          }
  679.       }
  680.  
  681.   // Close the file:
  682.   fclose ( InFile );
  683.  
  684.   // Set the vertex count at zero:
  685.   VCount = 0;
  686.  
  687.   // Allocate memory for vertex list - abort if error:
  688.   if ( ( VList = new Point3D [ VIndex ] ) == 0 )
  689.      return 0;
  690.  
  691.   // Copy TList to VList:
  692.   for ( Count = 0; Count < VIndex; Count++ )
  693.       {
  694.       if ( UniqueVert ( TList [ Count ], VList, VCount ) )
  695.          {
  696.          VList [ VCount ] = TList [ Count ];
  697.  
  698.          // Increment the vertex count/index:
  699.          ++VCount;
  700.          }
  701.       }
  702.   
  703.   // Return true (success):
  704.   return 1;
  705.   }
  706.  
  707. WORD PanelObject::LoadPanelData ()
  708.    {
  709.    // Read the panel data from a DXF file:
  710.    // Note: Assumes all vertices have been loaded via member
  711.    //       function "LoadVerts"
  712.  
  713.    // Allocate memory for files:
  714.    if ( ( PList = new Panel3D [ PCount ] ) == 0 )
  715.       return 0;
  716.  
  717.    int VIndex = 0;
  718.  
  719.    // Loop until we come to the end of the file:
  720.    for ( unsigned int PIndex = 0; PIndex < PCount; PIndex++ )
  721.        {
  722.        // Load an entire panel:
  723.        LoadPanel ( VIndex, PIndex );
  724.        }
  725.  
  726.    // Deallocate temporary list data
  727.    delete [] TList;
  728.  
  729.    // Return true (success):
  730.    return 1;
  731.    }
  732.  
  733. WORD PanelObject::LoadPanel ( int &VIndex, int Index )
  734.    {
  735.    // Load a panel from a DXF text file:
  736.  
  737.    // 3DFACE has been found - load four coordinates:
  738.    for ( unsigned int Count = 0; Count < 4; Count++ )
  739.        {
  740.        // Assign a vertex to the panel:
  741.        PList [ Index ].VPoint [ Count ] = 
  742.              &VList [ GetVertIndex (  TList [ VIndex ], 
  743.              VList, VCount ) ];
  744.  
  745.        // Increment the vertex index:
  746.        ++VIndex;
  747.        }
  748.  
  749.    // Calculate panel normal:
  750.    PList [ Index ].InitPosition ();
  751.  
  752.    // Calculate panel's intensity:
  753.    PList [ Index ].CalcInten ();
  754.  
  755.    // Return true (success):
  756.    return 1;
  757.    }
  758.  
  759. void PanelObject::LoadDXF ( char *FileName )
  760.    {
  761.    // Load an object from a DXF text file:
  762.    LoadVerts ( FileName );
  763.    LoadPanelData ();
  764.    }
  765.  
  766. void PanelObject::ReadBIN ( char *FileName )
  767.    {
  768.    // Load an object from a BIN binary file:
  769.    unsigned int VertCount, PanelCount, Count;
  770.    unsigned int short PIndex, VIndex;
  771.    float IPer;
  772.    Point3D TVert;
  773.    FILE *InFile;
  774.    if ( ( InFile = fopen ( FileName, "rb" ) ) == NULL )
  775.       return;
  776.    fread ( &VertCount, sizeof VertCount, 1, InFile );
  777.    fread ( &PanelCount, sizeof PanelCount, 1, InFile );
  778.    // Allocate memory:
  779.    VList = new Point3D [ VertCount ];
  780.    PList = new Panel3D [ PanelCount ];
  781.  
  782.    // Load vertices:
  783.    for ( Count = 0; Count < VertCount; Count++ )
  784.        {
  785.        VList [ Count ].Read ( InFile );
  786.        }
  787.    VCount = VertCount;
  788.    PCount = PanelCount;
  789.  
  790.    cout << "\nReading Polygon Dataset:\n";
  791.    // Load panel data:
  792.    for ( Count = 0; Count < PCount; Count++ )
  793.        {
  794.        IPer = ( ( float ) Count / ( float ) PCount ) * 101.0F;
  795.        cout << ( long ) IPer << "%\r";
  796.        for ( VIndex = 0; VIndex < 4; VIndex++ )
  797.            {
  798.            fread ( &PIndex, sizeof PIndex, 1, InFile );
  799.            PList [ Count ].VPoint [ VIndex ] = &VList [ PIndex ];
  800.            }
  801.        // Calculate the panel normal:
  802.        PList [ Count ].InitPosition ();
  803.  
  804.        // Calculate the panel's intensity:
  805.        PList [ Count ].CalcInten ();
  806.        }
  807.    fclose ( InFile );
  808.    }
  809.  
  810. void PanelObject::WriteBIN ( char *FileName )
  811.    {
  812.    // Write a BIN binary file:
  813.    unsigned int VertCount = VCount, PanelCount = PCount, Count;
  814.    unsigned int short PIndex, VIndex;
  815.    Point3D *PVert;
  816.    FILE *OutFile;
  817.    if ( ( OutFile = fopen ( FileName, "wb" ) ) == NULL )
  818.       return;
  819.    fwrite ( &VertCount, sizeof VertCount, 1, OutFile );
  820.    fwrite ( &PanelCount, sizeof PanelCount, 1, OutFile );
  821.  
  822.    // Write vertex data:
  823.    for ( Count = 0; Count < VCount; Count++ )
  824.        {
  825.        VList [ Count ].Write ( OutFile );
  826.        }
  827.  
  828.    // Write panel data:
  829.    for ( Count = 0; Count < PCount; Count++ )
  830.        {
  831.        for ( VIndex = 0; VIndex < 4; VIndex++ )
  832.            {
  833.            PVert = PList [ Count ].VPoint [ VIndex ];
  834.            PIndex = ( unsigned short ) GetVertIndex ( *PVert, VList, VCount );
  835.            fwrite ( &PIndex, sizeof PIndex, 1, OutFile );
  836.            }
  837.        }
  838.    fclose ( OutFile );
  839.    }
  840.  
  841. int PanelObject::ReadText ( char *FileName )
  842.   {
  843.   long Count;
  844.   FILE *InFile;
  845.   if ( ( InFile = fopen ( FileName, "rb" ) ) == 0 )
  846.      return 0;
  847.   // Load the textures:
  848.   TextDat.LoadBT ( InFile );
  849.  
  850.   // Load the texture coordinates and handles:
  851.   for ( Count = 0; Count < PCount; Count++ )
  852.       {
  853.       fread ( &PList [ Count ].TextHan, 
  854.               sizeof PList [ Count ].TextHan, 1, InFile );
  855.       fread ( PList [ Count ].Attrib, sizeof ( Detail3D ), 4, 
  856.               InFile );
  857.       }
  858.   fclose ( InFile );
  859.  
  860.   return 1;
  861.   }
  862.  
  863. int PanelObject::WriteText ( char *FileName )
  864.   {
  865.   long Count;
  866.   FILE *OutFile;
  867.   if ( ( OutFile = fopen ( FileName, "wb" ) ) == 0 )
  868.      return 0;
  869.   // Save the textures:
  870.   TextDat.SaveBT ( OutFile );
  871.  
  872.   // Save the texture coordinates and handles:
  873.   for ( Count = 0; Count < PCount; Count++ )
  874.       {
  875.       fwrite ( &PList [ Count ].TextHan, 
  876.                sizeof PList [ Count ].TextHan, 1, OutFile );
  877.       fwrite ( PList [ Count ].Attrib, sizeof ( Detail3D ), 4, 
  878.                OutFile );
  879.       }
  880.   fclose ( OutFile );
  881.  
  882.   return 1;
  883.   }
  884.