home *** CD-ROM | disk | FTP | other *** search
/ Cutting-Edge 3D Game Programming with C++ / CE3DC++.ISO / BOOK / CHAP14 / COLLIDE.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1995-12-23  |  10.8 KB  |  404 lines

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