home *** CD-ROM | disk | FTP | other *** search
/ Cutting-Edge 3D Game Programming with C++ / CE3DC++.ISO / BOOK / CHAP11 / MORPH / MORPH.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-19  |  10.7 KB  |  399 lines

  1. //
  2. // File name: Morph.CPP
  3. //
  4. // Description: The main file for a simple morph demo
  5. //
  6. // Author: John De Goes
  7. //
  8. // Project: Cutting Edge 3D Game Programming
  9. //
  10.  
  11. // ------------------------------------------------------------
  12. // | Global include files:                                    |
  13. // ------------------------------------------------------------
  14.  
  15. #include <Dos.H>
  16. #include <Math.H>
  17. #include <Conio.H>
  18. #include <Time.H>
  19. #include <Stdio.H>
  20. #include <Windows.H>
  21. #include <Iostream.H>
  22.  
  23. // ------------------------------------------------------------
  24. // | Local include files:                                     |
  25. // ------------------------------------------------------------
  26.  
  27. #include "32Bit.HPP"
  28. #include "MouseLib.HPP"
  29. #include "Palette.HPP"
  30. #include "TextType.HPP"
  31. #include "3Dclass.HPP"
  32. #include "LineType.HPP"
  33. #include "PalShade.HPP"
  34.  
  35. // ------------------------------------------------------------
  36. // | Global variables/constants:                              |
  37. // ------------------------------------------------------------
  38.  
  39. float SpeedStep  = 20.0F;
  40.  
  41. // Create an image of a cross for the mouse:
  42. unsigned char Cursor [ ] = {
  43.                      0, 0, 0, 0, 0,10,10, 0, 0, 0, 0, 0,
  44.                      0, 0, 0, 0, 0,10,10, 0, 0, 0, 0, 0,
  45.                      0, 0, 0, 0, 0,10,10, 0, 0, 0, 0, 0,
  46.                      0, 0, 0, 0, 0,10,10, 0, 0, 0, 0, 0,
  47.                      0, 0, 0, 0, 0,10,10, 0, 0, 0, 0, 0,
  48.                      10,10,10,10,10,11,11,10,10,10,10,10,
  49.                      10,10,10,10,10,11,11,10,10,10,10,10,
  50.                      0, 0, 0, 0, 0,10,10, 0, 0, 0, 0, 0,
  51.                      0, 0, 0, 0, 0,10,10, 0, 0, 0, 0, 0,
  52.                      0, 0, 0, 0, 0,10,10, 0, 0, 0, 0, 0,
  53.                      0, 0, 0, 0, 0,10,10, 0, 0, 0, 0, 0,
  54.                      0, 0, 0, 0, 0,10,10, 0, 0, 0, 0, 0,
  55.                      };
  56.  
  57. // ------------------------------------------------------------
  58. // | Local structs/classes:                                   |
  59. // ------------------------------------------------------------
  60.  
  61. struct View {
  62. int XRot, YRot, ZRot;
  63. double ZPos;
  64. View () { XRot = YRot = ZRot = 0; ZPos = 0.0F; }
  65. void Clear () { XRot = YRot = ZRot = 0; ZPos = 0.0F; }
  66. };
  67.  
  68. // ------------------------------------------------------------
  69. // | Function section:                                        |
  70. // ------------------------------------------------------------
  71.  
  72. int InitZBuffer ()
  73.   {
  74.   // Allocate memory for Z-buffer:
  75.   if ( ( ZBuffer = new long [ 64000 ] ) == 0 )
  76.      return 0;
  77.   return 1;
  78.   }
  79.  
  80. int DestZBuffer ()
  81.   {
  82.   // Deallocate Z-buffer's memory:
  83.   delete [] ZBuffer;
  84.   if ( ZBuffer )
  85.      return 0;
  86.   return 1;
  87.   }
  88.  
  89. void ClearBuffer ()
  90.    {
  91.    // Clear the Z-buffer:
  92.    long *ZPtr = ZBuffer;
  93.    for ( unsigned int Index = 0; Index < 6400; Index++ )
  94.        {
  95.        *ZPtr++ = 0;
  96.        *ZPtr++ = 0;
  97.  
  98.        *ZPtr++ = 0;
  99.        *ZPtr++ = 0;
  100.  
  101.        *ZPtr++ = 0;
  102.        *ZPtr++ = 0;
  103.  
  104.        *ZPtr++ = 0;
  105.        *ZPtr++ = 0;
  106.  
  107.        *ZPtr++ = 0;
  108.        *ZPtr++ = 0;
  109.        }
  110.    }
  111.  
  112. // Create a virtual track-ball:
  113. void UpdatePos ( PanelObject *World, MousePtr &Mouse, View &V )
  114.    {
  115.    int X, Y;
  116.    static int Px = 0, Py = 0, Pressed = 0, Lx, Ly;
  117.  
  118.    // Get the mouse coordinates and map them to a suitable
  119.    // range:
  120.    X = ( Mouse.GetX () - 50 ) / 4;
  121.    Y = ( Mouse.GetY () - 50 ) / 4;
  122.  
  123.    V.ZPos += SpeedStep;
  124.  
  125.    // If no buttons are being pressed:   
  126.    if ( ( !Mouse.GetRb () ) && ( !Mouse.GetLb () ) )
  127.       {
  128.       // Do the rotations:
  129.       V.XRot += Y;
  130.       V.YRot += X;
  131.       V.ZRot += ( X / 16 );
  132.       Pressed = 0;
  133.       }
  134.  
  135.    // If the right button is pressed:   
  136.    if ( ( !Mouse.GetRb () ) && ( Mouse.GetLb () ) )
  137.       {
  138.       // Rotate on the Z axis:
  139.       V.ZRot -= X;
  140.       Pressed = 0;
  141.       }
  142.  
  143.    // Else if both buttons are pressed:
  144.    else if ( Mouse.GetRb () && Mouse.GetLb () )
  145.            {
  146.            if ( Pressed == 0 )
  147.               {
  148.               Pressed = 1;
  149.               // Record the actual screen coordinates of the 
  150.               // mouse pointer:
  151.               Px = Mouse.GetSx ();
  152.               Py = Mouse.GetSy ();
  153.  
  154.               Lx = Mouse.GetSx ();
  155.               Ly = Mouse.GetSy ();
  156.               }
  157.            else {
  158.                 World->MoveText ( Px, Py, 
  159.                                   ( Lx - Mouse.GetSx () ) >> 2, 
  160.                                   ( Ly - Mouse.GetSy () ) >> 2 );
  161.                 Lx = Mouse.GetSx ();
  162.                 Ly = Mouse.GetSy ();
  163.                 }
  164.            }
  165.  
  166.    // Else no buttons are pressed:
  167.    else Pressed = 0;
  168.    }
  169.  
  170. void HandleKey ( PanelObject *World, MousePtr &Mouse, long Key )
  171.    {
  172.    switch ( Key )
  173.           {
  174.           case ('\t'):
  175.                {
  176.                World->SelNext ();
  177.                break;
  178.                }
  179.           case ('t'):
  180.           case ('T'):
  181.                {
  182.                World->NexText ();
  183.                break;
  184.                }
  185.           case ('r'):
  186.           case ('R'):
  187.                {
  188.                World->RotText ();
  189.                break;
  190.                }
  191.           case ('i'):
  192.           case ('I'):
  193.                {
  194.                World->NextInten ( Mouse.GetSx (), 
  195.                                   Mouse.GetSy () );
  196.                break;
  197.                }
  198.           case ('-'):
  199.                {
  200.                if ( SpeedStep > 0.0F )
  201.                   SpeedStep -= 10.0F;
  202.                break;
  203.                }
  204.           case ('+'):
  205.                {
  206.                if ( SpeedStep < 50.0F )
  207.                   SpeedStep += 10.0F;
  208.                break;
  209.                }
  210.           default: break;
  211.           }
  212.    }
  213.  
  214. double RunWorld ( unsigned char *VidMem, unsigned char *VidBuf,
  215.                   PanelObject *World )
  216.    {
  217.    // Enter the main loop, updating view as necessary:
  218.  
  219.    VidMem; VidBuf; World;
  220.    MousePtr Mouse;
  221.    Matrix3D M; View V;
  222.    long QuitFlag = 0, StartTime, EndTime, FrameCount = 0, 
  223.         MaxWait, Input, BackC;
  224.    double FramesPerSecond;
  225.    ZTrans = 0;
  226.  
  227.    // Initialize the mouse driver:
  228.    Mouse.Init ();
  229.  
  230.    // Hide the pointer:   
  231.    Mouse.Hide ();
  232.  
  233.    // Re-map the cursor's coordinates:
  234.    Mouse.MappingRange ( 100, 100 );
  235.  
  236.    // Clip the cursor to a rectangular region:
  237.    Mouse.Clip ( 5, 5, 95, 95 );
  238.  
  239.    // Give the cursor a face-lift:
  240.    Mouse.ChangeCursor ( Cursor, 12, 12 );
  241.  
  242.    // Allocate memory for Z-buffer:
  243.    InitZBuffer ();
  244.  
  245.    // Raise the viewer:
  246.    M.Initialize ();
  247.    M.Translate ( 0, -1000, 0 );
  248.    ClearBuffer ();
  249.    World->Display ( M, VidBuf );
  250.    MaxWait = ( long ) pow ( 2, 31 - ZSTEP_PREC  );
  251.  
  252.    // Record the time:
  253.    StartTime = clock ();
  254.  
  255.    // Calculate the background color (a shade of whitish-gray):
  256.    BackC = GetColor ( 150, 150, 150, TextDat.TMap [ 0 ].Palette );
  257.  
  258.    // Loop until ESC pressed:
  259.    while ( !QuitFlag )
  260.          {
  261.          UpdatePos ( World, Mouse, V );
  262.  
  263.          M.Translate ( 0, 0, -V.ZPos );
  264.          M.Rotate ( -V.XRot, -V.YRot, -V.ZRot );
  265.          V.Clear ();
  266.  
  267.          setmem ( VidBuf, 64000, BackC );
  268.  
  269.          // Clear the Z-buffer (if necessary):
  270.          ZTrans += ( 1 << ZSTEP_PREC );
  271.          if ( ( FrameCount % MaxWait ) == 0 )
  272.             {
  273.             ZTrans = 0;
  274.             ClearBuffer ();
  275.             }
  276.  
  277.          World->Display ( M, VidBuf );
  278.          Mouse.Display ( VidBuf );
  279.  
  280.          memmove ( VidMem, VidBuf, 64000 );
  281.          if ( kbhit () )
  282.             {
  283.             Input = getch ();
  284.             if ( Input == 27 )
  285.                QuitFlag = 1;
  286.             else HandleKey ( World, Mouse, Input );
  287.             }
  288.          ++FrameCount; 
  289.          }
  290.    EndTime = clock ();
  291.  
  292.    DestZBuffer ();
  293.  
  294.    // Calculate the frames per second:
  295.    FramesPerSecond = ( double ) FrameCount * 
  296.                      ( double )  CLK_TCK /
  297.                      ( double ) ( EndTime - StartTime ); 
  298.    return FramesPerSecond;
  299.    }
  300.  
  301. void SetPalette ( RGBQUAD *Palette )
  302.    {
  303.    short Index, Red, Green, Blue;
  304.    for ( Index = 0; Index < 256; Index++ )
  305.        {
  306.        Red    = ( short ) ( Palette [ Index ].rgbRed   >> 2 );
  307.        Green  = ( short ) ( Palette [ Index ].rgbGreen >> 2 );
  308.        Blue   = ( short ) ( Palette [ Index ].rgbBlue  >> 2 );
  309.        setpalreg ( Index, Green, Blue, Red );
  310.        }
  311.    }
  312.  
  313.  
  314. // ------------------------------------------------------------
  315. // | Program entry:                                           |
  316. // ------------------------------------------------------------
  317.  
  318. void main ( int ArgCount, char *Arg[] )
  319.    {
  320.    // Declare/initialize variables and allocate memory:
  321.    unsigned char *VidMem, *VidBuf;
  322.    VidMem = VideoAddress ();
  323.    double FramesPerSecond;
  324.  
  325.    // Allocate buffer memory - abort if error:
  326.    if ( ( VidBuf = new unsigned char [ 64000 ] ) == NULL )
  327.       return;
  328.  
  329.    // Allocate memory for a panel object:
  330.    PanelObject *World = new PanelObject;
  331.  
  332.    if ( ( ArgCount > 1 ) && 
  333.         ( !strcmp ( strupr ( Arg [ 1 ] ), "WRITEBINARY" ) ) )
  334.       {
  335.       World->LoadDXF ( "Test.DXF" );
  336.       World->WriteBIN ( "Test.BIN" );
  337.       }
  338.  
  339.    else {
  340.         // Read the panel data:
  341.         World->ReadBIN ( "Test.BIN" );
  342.  
  343.         // Generate morphing data:
  344.         World->MorphTo ( "Test2.BIN", 800.0F );
  345.  
  346.         // Read -- if possible -- the texture data:
  347.         if ( World->ReadText ( "Text.BT" ) == 0 )
  348.            {
  349.            if ( TextDat.LoadINI ( "Text.INI" ) == 0 )
  350.               {
  351.               cout << "\nError loading Text.INI\n";
  352.               delete [] VidBuf;
  353.               delete World;
  354.               return;
  355.               }
  356.            // Initialize default texture coords:
  357.            World->InitDefText ();
  358.            }
  359.         // Read -- if possible -- the shade table:
  360.         if ( TextShade.LoadTable ( "Shade.TAB" ) == 0 )
  361.            {
  362.            // Generate a palette that fades to white:
  363.            TextShade.GenTable ( 150.0F, 150.0F, 150.0F, 
  364.                                 TextDat.TMap [ 0 ].Palette );
  365.            TextShade.SaveTable ( "Shade.TAB" );
  366.            }
  367.  
  368.         // Set video mode:
  369.         SetVideo ( 0x13 );
  370.  
  371.         // Set the palette:
  372.         SetPalette ( TextDat.TMap [ 0 ].Palette );
  373.  
  374.         // Enter main loop:
  375.         FramesPerSecond = RunWorld ( VidMem, VidBuf, World );
  376.  
  377.         // Set video mode:
  378.         SetVideo ( 0x03 );
  379.  
  380.         // Display FPS:
  381.         cout << "\nFrames per second: " << FramesPerSecond;
  382.  
  383.         // Save the texture data:
  384.         World->WriteText ( "Text.BT" );
  385.         }
  386.  
  387.    // Deallocate memory for buffer:
  388.    cout << "\nDeallocating memory...";
  389.    delete [] VidBuf;
  390.       
  391.    // Deallocate memory for panel object:
  392.    delete World;
  393.  
  394.    cout << "\nReturning control to OS...";
  395.  
  396.    // Exit program:
  397.    return;
  398.    }
  399.