home *** CD-ROM | disk | FTP | other *** search
/ Cutting-Edge 3D Game Programming with C++ / CE3DC++.ISO / BOOK / CHAP12 / CUTTING.CPP < prev    next >
C/C++ Source or Header  |  1996-01-25  |  12KB  |  433 lines

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