home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the 3D Game Programming Gurus / gurus.iso / Articles / TextureMapMania / tmapdemo.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-02-05  |  19.2 KB  |  684 lines

  1. // TMAPDEMO.CPP - DirectX 5.0 Texture Mapping Demo
  2. // Compile as Win32 Application along with TMAPPER.CPP, DDRAW.LIB, and WINMM.LIB
  3. // Press ESC to exit, you may have to hold it!
  4.  
  5. // INCLUDES ///////////////////////////////////////////////////////////////////
  6.  
  7. #define WIN32_LEAN_AND_MEAN  // make sure certain headers are included correctly
  8.  
  9. #include <windows.h>   // include important windows stuff
  10. #include <windowsx.h> 
  11. #include <mmsystem.h>
  12. #include <iostream.h>  // include important C/C++ stuff
  13. #include <conio.h>
  14. #include <stdlib.h>
  15. #include <malloc.h>
  16. #include <memory.h>
  17. #include <string.h>
  18. #include <stdarg.h>
  19. #include <stdio.h>
  20. #include <math.h>
  21. #include <io.h>
  22. #include <fcntl.h>
  23. #include "tmapper.h"   // need the class defs
  24. #include <ddraw.h>     // include directdraw
  25.  
  26. // DEFINES ////////////////////////////////////////////////////////////////////
  27.  
  28. #define WINDOW_CLASS_NAME "WINDOW_CLASS" // this is the name of the window class
  29.  
  30. // defines for screen parameters
  31. #define SCREEN_WIDTH     640         // the width of the viewing surface
  32. #define SCREEN_HEIGHT    480         // the height of the viewing surface
  33. #define SCREEN_BPP       8           // the bits per pixel
  34. #define MAX_COLORS       256         // the maximum number of colors
  35.  
  36. // graphics defines
  37. #define BITMAP_ID            0x4D42 // universal id for a bitmap
  38.  
  39. // TYPES /////////////////////////////////////////////////////////////////////
  40.  
  41. // container structure for bitmaps .BMP file
  42. typedef struct BITMAP_FILE_TAG
  43.         {
  44.         BITMAPFILEHEADER bitmapfileheader;  // this contains the bitmapfile header
  45.         BITMAPINFOHEADER bitmapinfoheader;  // this is all the info including the palette
  46.         PALETTEENTRY     palette[256];      // we will store the palette here
  47.         UCHAR            *buffer;           // this is a pointer to the data
  48.  
  49.         } BITMAP_FILE, *BITMAP_FILE_PTR;
  50.  
  51. // MACROS /////////////////////////////////////////////////////////////////////
  52.  
  53. // this builds a 16 bit color value
  54. #define _RGB16BIT(r,g,b) ((b%32) + ((g%32) << 5) + ((r%32) << 10))
  55.  
  56. // these query the keyboard in real-time
  57. #define KEY_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
  58. #define KEY_UP(vk_code)   ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)
  59.  
  60. // PROTOTYPES ////////////////////////////////////////////////////////////////
  61.  
  62. int DD_Init(HWND hwnd);
  63. int DD_Shutdown(void);
  64.  
  65. void Game_Init(void);
  66. void Game_Main(void);
  67. void Game_Shutdown(void);
  68.  
  69. // bitmap file functions
  70. int Load_Bitmap_File(BITMAP_FILE_PTR bitmap, char *filename);
  71. int Unload_Bitmap_File(BITMAP_FILE_PTR bitmap);
  72. int Set_Palette(LPPALETTEENTRY set_palette);
  73. int Flip_Bitmap(UCHAR *image, int bytes_per_line, int height);
  74. void Draw_Textured_Triangle(void *vface,UCHAR *dest_buffer,int mem_pitch);
  75.  
  76. // DIRECTDRAW GLOBALS ////////////////////////////////////////////////////////
  77.  
  78. LPDIRECTDRAW         lpdd         = NULL;        // dd object
  79. LPDIRECTDRAWSURFACE  lpddsprimary = NULL;        // dd primary surface
  80. LPDIRECTDRAWPALETTE  lpddpal      = NULL;        // a pointer to the created dd palette
  81. PALETTEENTRY         palette[256];                // holds the shadow palette entries
  82. DDSURFACEDESC        ddsd;                        // a direct draw surface description struct
  83. DDSCAPS              ddscaps;                    // a direct draw surface capabilities struct
  84. HRESULT              ddrval;                    // result back from dd calls
  85. HWND                 main_window_handle = NULL; // used to store the window handle
  86. UCHAR                *video_buffer = NULL;      // pointer to video ram
  87. int                  mem_pitch;                 // horizontal memory pitch
  88.  
  89. BITMAP_FILE          bitmap;                    // used to hold bitmap
  90.  
  91. // these defined the general clipping rectangle
  92. int poly_clip_min_x = 0,
  93.     poly_clip_max_x = SCREEN_WIDTH-1,
  94.     poly_clip_min_y = 0,
  95.     poly_clip_max_y = SCREEN_HEIGHT-1;  
  96.  
  97. // GAME GLOBALS GO HERE ///////////////////////////////////////////////////// 
  98.  
  99. // DIRECT X FUNCTIONS /////////////////////////////////////////////////////////
  100.  
  101. int DD_Init(HWND hwnd)
  102. {
  103. // this function is responsible for initializing direct draw, it creates a
  104. // primary surface 
  105.  
  106. int  index;     // looping index
  107.  
  108. // now that the windows portion is complete, start up direct draw
  109. if (DirectDrawCreate(NULL,&lpdd,NULL)!=DD_OK)
  110.    {
  111.    // shutdown any other dd objects and kill window
  112.    DD_Shutdown();
  113.    return(0);
  114.    } // end if
  115.  
  116. // now set the coop level to exclusive and set for full screen and mode x
  117. if (lpdd->SetCooperativeLevel(hwnd, DDSCL_NORMAL)!=DD_OK)
  118.    {
  119.    // shutdown any other dd objects and kill window
  120.    DD_Shutdown();
  121.    return(0);
  122.    } // end if
  123.  
  124. // now set the coop level to exclusive and set for full screen and mode x
  125. if (lpdd->SetCooperativeLevel(hwnd, DDSCL_ALLOWREBOOT | DDSCL_EXCLUSIVE |
  126.                               DDSCL_FULLSCREEN | DDSCL_ALLOWMODEX)!=DD_OK)
  127.    {
  128.    // shutdown any other dd objects and kill window
  129.    DD_Shutdown();
  130.    return(0);
  131.    } // end if
  132.  
  133. // now set the display mode
  134. if (lpdd->SetDisplayMode(SCREEN_WIDTH,SCREEN_HEIGHT,SCREEN_BPP)!=DD_OK)
  135.    {
  136.    // shutdown any other dd objects and kill window
  137.    DD_Shutdown();
  138.    return(0);
  139.    } // end if
  140.  
  141. // Create the primary surface
  142. ddsd.dwSize            = sizeof(ddsd);
  143. ddsd.dwFlags           = DDSD_CAPS;
  144. ddsd.ddsCaps.dwCaps    = DDSCAPS_PRIMARYSURFACE;
  145.  
  146. if (lpdd->CreateSurface(&ddsd,&lpddsprimary,NULL)!=DD_OK)
  147.    {
  148.    // shutdown any other dd objects and kill window
  149.    DD_Shutdown();
  150.    return(0);
  151.    } // end if
  152.  
  153. // create the palette and attach it to the primary surface
  154.  
  155. // clear all the palette entries to RGB 0,0,0
  156. memset(palette,0,256*sizeof(PALETTEENTRY));
  157.  
  158. // set all of the flags to the correct value
  159. for (index=0; index<256; index++)
  160.     {
  161.     // create the GRAY/RED/GREEN/BLUE palette, 64 shades of each
  162.     if ((index / 64)==0) 
  163.         palette[index].peRed = palette[index].peGreen = palette[index].peBlue  = index*4;
  164.     else
  165.     if ((index / 64)==1) 
  166.         palette[index].peRed  = (index%64)*4;
  167.     else
  168.     if ((index / 64)==2) 
  169.         palette[index].peGreen = (index%64)*4;
  170.     else
  171.     if ((index / 64)==3) 
  172.         palette[index].peBlue  = (index%64)*4;
  173.  
  174.     // set the no collapse flag
  175.     palette[index].peFlags = PC_NOCOLLAPSE;
  176.     
  177.     } // end for index
  178.  
  179. // now create the palette object, note that it is a member of the dd object itself
  180. if (lpdd->CreatePalette((DDPCAPS_8BIT | DDPCAPS_INITIALIZE),palette,&lpddpal,NULL)!=DD_OK)
  181.     {
  182.     // shutdown any other dd objects and kill window
  183.     DD_Shutdown();
  184.     return(0);
  185.     } // end if
  186.  
  187. // now attach the palette to the primary surface
  188. lpddsprimary->SetPalette(lpddpal);
  189.  
  190. // return success if we got this far
  191. return(1);
  192.  
  193. } // end DD_Init
  194.  
  195. ///////////////////////////////////////////////////////////////////////////////
  196.  
  197. int DD_Shutdown(void)
  198. {
  199. // this function tests for dd components that have been created and releases
  200. // them back to the operating system
  201.  
  202. // test if the dd object exists
  203. if (lpdd)
  204.    {
  205.    // test if there is a primary surface
  206.    if (lpddsprimary)
  207.       {
  208.       // release the memory and set pointer to NULL
  209.       lpddsprimary->Release();
  210.       lpddsprimary = NULL;
  211.       } // end if
  212.  
  213.     // now release the dd object itself
  214.     lpdd->Release();
  215.     lpdd = NULL;
  216.  
  217.     // return success
  218.     return(1);
  219.  
  220.     } // end if
  221. else
  222.     return(0);
  223.  
  224. } // end DD_Shutdown
  225.  
  226. // GENERAL GRAPHICS HERE /////////////////////////////////////////////////////
  227.  
  228. int Load_Bitmap_File(BITMAP_FILE_PTR bitmap, char *filename)
  229. {
  230. // this function opens a bitmap file and loads the data into bitmap
  231.  
  232. int file_handle,  // the file handle
  233.     index;        // looping index
  234.  
  235. UCHAR *temp_buffer = NULL; // used to convert 24 bit images to 16 bit
  236. OFSTRUCT file_data;        // the file data information
  237.  
  238. // open the file if it exists
  239. if ((file_handle = OpenFile(filename,&file_data,OF_READ))==-1)
  240.    return(0);
  241.  
  242. // now load the bitmap file header
  243. _lread(file_handle, &bitmap->bitmapfileheader,sizeof(BITMAPFILEHEADER));
  244.  
  245. // test if this is a bitmap file
  246. if (bitmap->bitmapfileheader.bfType!=BITMAP_ID)
  247.    {
  248.    // close the file
  249.    _lclose(file_handle);
  250.  
  251.    // return error
  252.    return(0);
  253.    } // end if
  254.  
  255. // now we know this is a bitmap, so read in all the sections
  256.  
  257. // first the bitmap infoheader
  258.  
  259. // now load the bitmap file header
  260. _lread(file_handle, &bitmap->bitmapinfoheader,sizeof(BITMAPINFOHEADER));
  261.  
  262. // now load the color palette if there is one
  263. if (bitmap->bitmapinfoheader.biBitCount == 8)
  264.    {
  265.    _lread(file_handle, &bitmap->palette,256*sizeof(PALETTEENTRY));
  266.  
  267.    // now set all the flags in the palette correctly and fix the reversed 
  268.    // BGR RGBQUAD data format
  269.    for (index=0; index < 256; index++)
  270.        {
  271.        // reverse the red and green fields
  272.        int temp_color = bitmap->palette[index].peRed;
  273.        bitmap->palette[index].peRed  = bitmap->palette[index].peBlue;
  274.        bitmap->palette[index].peBlue = temp_color;
  275.        
  276.        // always set the flags word to this
  277.        bitmap->palette[index].peFlags = PC_NOCOLLAPSE;
  278.        } // end for index
  279.  
  280.     } // end if
  281.  
  282. // finally the image data itself
  283. _lseek(file_handle,-(int)(bitmap->bitmapinfoheader.biSizeImage),SEEK_END);
  284.  
  285. // now read in the image, if the image is 8 or 16 bit then simply read it
  286. // but if its 24 bit then read it into a temporary area and then convert
  287. // it to a 16 bit image
  288.  
  289. if (bitmap->bitmapinfoheader.biBitCount==8 || bitmap->bitmapinfoheader.biBitCount==16)
  290.    {
  291.    // delete the last image if there was one
  292.    if (bitmap->buffer)
  293.        free(bitmap->buffer);
  294.  
  295.    // allocate the memory for the image
  296.    if (!(bitmap->buffer = (UCHAR *)malloc(bitmap->bitmapinfoheader.biSizeImage)))
  297.       {
  298.       // close the file
  299.       _lclose(file_handle);
  300.  
  301.       // return error
  302.       return(0);
  303.       } // end if
  304.  
  305.    // now read it in
  306.    _lread(file_handle,bitmap->buffer,bitmap->bitmapinfoheader.biSizeImage);
  307.  
  308.    } // end if
  309. else
  310.    {
  311.    // this must be a 24 bit image, load it in and convert it to 16 bit
  312. //   printf("\nconverting 24 bit image...");
  313.  
  314.    // allocate temporary buffer
  315.    if (!(temp_buffer = (UCHAR *)malloc(bitmap->bitmapinfoheader.biSizeImage)))
  316.       {
  317.       // close the file
  318.       _lclose(file_handle);
  319.  
  320.       // return error
  321.       return(0);
  322.       } // end if
  323.    
  324.    // allocate final 16 bit storage buffer
  325.    if (!(bitmap->buffer=(UCHAR *)malloc(2*bitmap->bitmapinfoheader.biWidth * 
  326.                                         bitmap->bitmapinfoheader.biHeight)))
  327.       {
  328.       // close the file
  329.       _lclose(file_handle);
  330.  
  331.       // release working buffer
  332.       free(temp_buffer);
  333.  
  334.       // return error
  335.       return(0);
  336.       } // end if
  337.  
  338.    // now read it in
  339.    _lread(file_handle,temp_buffer,bitmap->bitmapinfoheader.biSizeImage);
  340.  
  341.    // now convert each 24 bit RGB value into a 16 bit value
  342.    for (index=0; index<bitmap->bitmapinfoheader.biWidth*bitmap->bitmapinfoheader.biHeight; index++)
  343.        {
  344.        // extract RGB components (in BGR order), note the scaling
  345.        UCHAR blue  = (temp_buffer[index*3 + 0] >> 3),
  346.              green = (temp_buffer[index*3 + 1] >> 3),
  347.              red   = (temp_buffer[index*3 + 2] >> 3);
  348.  
  349.        // build up 16 bit color word
  350.        USHORT color = _RGB16BIT(red,green,blue);
  351.  
  352.        // write color to buffer
  353.        ((USHORT *)bitmap->buffer)[index] = color;
  354.  
  355.        } // end for index
  356.  
  357.    // finally write out the correct number of bits
  358.    bitmap->bitmapinfoheader.biBitCount=16;
  359.  
  360.    } // end if
  361.  
  362.  
  363. // close the file
  364. _lclose(file_handle);
  365.  
  366. // flip the bitmap
  367. Flip_Bitmap(bitmap->buffer, 
  368.             bitmap->bitmapinfoheader.biWidth*(bitmap->bitmapinfoheader.biBitCount/8), 
  369.             bitmap->bitmapinfoheader.biHeight);
  370.  
  371. // return success
  372. return(1);
  373.  
  374. } // end Load_Bitmap_File
  375.  
  376. ///////////////////////////////////////////////////////////
  377.  
  378. int Unload_Bitmap_File(BITMAP_FILE_PTR bitmap)
  379. {
  380. // this function releases all memory associated with "bitmap"
  381. if (bitmap->buffer)
  382.    {
  383.    // release memory
  384.    free(bitmap->buffer);
  385.  
  386.    // reset pointer
  387.    bitmap->buffer = NULL;
  388.  
  389.    } // end if
  390.  
  391. // return success
  392. return(1);
  393.  
  394. } // end Unload_Bitmap_File
  395.  
  396. ////////////////////////////////////////////////////////////////////////////////
  397.  
  398. int Flip_Bitmap(UCHAR *image, int bytes_per_line, int height)
  399. {
  400. // this function is used to flip upside down .BMP images
  401.  
  402. UCHAR *buffer; // used to perform the image processing
  403. int index;     // looping index
  404.  
  405. // allocate the temporary buffer
  406. if (!(buffer = (UCHAR *)malloc(bytes_per_line*height)))
  407.    return(0);
  408.  
  409. // copy image to work area
  410. memcpy(buffer,image,bytes_per_line*height);
  411.  
  412. // flip vertically
  413. for (index=0; index < height; index++)
  414.     memcpy(&image[((height-1) - index)*bytes_per_line],
  415.            &buffer[index*bytes_per_line], bytes_per_line);
  416.  
  417. // release the memory
  418. free(buffer);
  419.  
  420. // return success
  421. return(1);
  422.  
  423. } // end Flip_Bitmap
  424.  
  425. ///////////////////////////////////////////////////////////////////////////////
  426.  
  427. int Set_Palette(LPPALETTEENTRY set_palette)
  428. {
  429. // this function writes the sent palette
  430.  
  431. // first save the new palette in shadow
  432. memcpy(palette, set_palette,256*sizeof(PALETTEENTRY));
  433.  
  434. // now set the new palette
  435. lpddpal->SetEntries(0,0,256,palette);
  436.  
  437. // return success
  438. return(1);
  439. } // end Set_Palette
  440.  
  441.  
  442. // WINDOWS CALLBACK FUNCTION //////////////////////////////////////////////////                     
  443.  
  444. LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
  445. {
  446. // this is the main message handler of the system
  447.  
  448. HDC            hdc;        // handle to graphics context
  449. PAINTSTRUCT ps;            // used to hold the paint info
  450.  
  451. // what is the message?
  452.  
  453. switch(msg)
  454.     {    
  455.     case WM_CREATE:
  456.         {
  457.         // do windows inits here
  458.         return(0);
  459.         } break;
  460.  
  461.     case WM_PAINT:
  462.         {
  463.         // this message occurs when your window needs repainting
  464.         hdc = BeginPaint(hwnd,&ps);     
  465.         EndPaint(hdc,&ps);
  466.         
  467.         return(0);
  468.            } break;
  469.  
  470.     case WM_DESTROY:
  471.         {
  472.         // this message is sent when your window is destroyed
  473.         PostQuitMessage(0);
  474.         return(0);
  475.         } break;
  476.  
  477.     default:break;
  478.  
  479.     } // end switch
  480.  
  481. // let windows process any messages that we didn't take care of 
  482. return (DefWindowProc(hwnd, msg, wparam, lparam));
  483.  
  484. } // end WinProc
  485.  
  486. // WINMAIN ////////////////////////////////////////////////////////////////////
  487.  
  488. int WINAPI WinMain(    HINSTANCE hinstance,
  489.                     HINSTANCE hprevinstance,
  490.                     LPSTR lpcmdline,
  491.                     int ncmdshow)
  492. {
  493. WNDCLASSEX        winclass;    // this holds the windows class info
  494. HWND            hwnd;        // this holds the handle of our new window
  495. MSG                msg;        // this holds a generic message
  496.  
  497. // first fill in the window class stucture
  498.  
  499. winclass.cbSize            = sizeof(WNDCLASSEX);
  500. winclass.style            = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
  501. winclass.lpfnWndProc    = WindowProc;
  502. winclass.cbClsExtra        = 0;
  503. winclass.cbWndExtra        = 0;
  504. winclass.hInstance        = hinstance;
  505. winclass.hIcon            = LoadIcon(NULL, IDI_APPLICATION);
  506. winclass.hIconSm        = LoadIcon(NULL, IDI_APPLICATION);
  507. winclass.hCursor        = LoadCursor(NULL, IDC_ARROW);
  508. winclass.hbrBackground    = GetStockObject(BLACK_BRUSH);
  509. winclass.lpszMenuName    = NULL;
  510. winclass.lpszClassName    = WINDOW_CLASS_NAME;
  511.  
  512. // register the window class
  513. if (!RegisterClassEx(&winclass))
  514.     return(0);
  515.  
  516. // create the window
  517. if (!(hwnd = CreateWindowEx(0, 
  518.                             WINDOW_CLASS_NAME,                    // class
  519.                             "Texture Mapping Demo!",            // title
  520.                             WS_OVERLAPPED | WS_VISIBLE,
  521.                              0,0,                                // x,y
  522.                             320, // GetSystemMetrics(SM_CXSCREEN),
  523.                             240, // GetSystemMetrics(SM_CYSCREEN),                
  524.                             NULL,                                // parent
  525.                             NULL,                                // menu
  526.                             hinstance,                            // instance
  527.                             NULL)))                                // creation parms
  528. return(0);
  529.  
  530. // hide the mouse cursor
  531. ShowCursor(0);
  532.  
  533. // save the window handle
  534. main_window_handle = hwnd;
  535.  
  536. // initialize direct draw
  537. if (!DD_Init(hwnd))
  538.    {
  539.    DestroyWindow(hwnd);
  540.    return(0);
  541.    } // end if
  542.  
  543. // initialize game
  544. Game_Init();
  545.  
  546. // enter main event loop
  547. while(1)
  548.     {
  549.     if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
  550.         { 
  551.         // test if this is a quit
  552.         if (msg.message == WM_QUIT)
  553.            break;
  554.     
  555.         // translate any accelerator keys
  556.         TranslateMessage(&msg);
  557.  
  558.         // send the message to the window proc
  559.         DispatchMessage(&msg);
  560.         } // end if
  561.     else
  562.         {
  563.         // do asynchronous processing here
  564.  
  565.         // acquire pointer to video ram, note it is always linear
  566.         memset(&ddsd,0,sizeof(ddsd));
  567.         ddsd.dwSize = sizeof(ddsd);
  568.         lpddsprimary->Lock(NULL,&ddsd,DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR,NULL);
  569.  
  570.         // get video pointer
  571.         video_buffer = (UCHAR *)ddsd.lpSurface;
  572.  
  573.         // get video pitch, should be SCREEN_WIDTH, but possibly not!
  574.         mem_pitch = (int)ddsd.lPitch;
  575.  
  576.         // call main logic module
  577.         Game_Main();
  578.  
  579.         // release pointer to video ram
  580.         lpddsprimary->Unlock(ddsd.lpSurface);
  581.         
  582.         } // end else
  583.  
  584.     } // end while
  585.  
  586. // shut down direct draw
  587. DD_Shutdown();
  588.  
  589. // shutdown game
  590. Game_Shutdown();
  591.  
  592. // return to Windows
  593. return(msg.wParam);
  594.  
  595. } // end WinMain
  596.  
  597. // HERE ARE OUR GAME CONSOLE FUNCTIONS ///////////////////////////////////////////////////////
  598.  
  599. void Game_Init(void)
  600. {
  601. // do any initialization here
  602.  
  603. // load in the bitmap file here, 64x64 8 bit
  604. Load_Bitmap_File(&bitmap, "texture.bmp");
  605.  
  606. // set new palette
  607. Set_Palette(bitmap.palette);
  608.  
  609. } // end Game_Init
  610.  
  611. /////////////////////////////////////////////////////////////////////////////////////////////
  612.  
  613. void Game_Shutdown(void)
  614. {
  615. // cleanup and release all resources here
  616.  
  617. // release bitmap memory
  618. Unload_Bitmap_File(&bitmap);
  619.  
  620. } // end Game_Shutdown
  621.  
  622. /////////////////////////////////////////////////////////////////////////////////////////////
  623.  
  624. void Game_Main(void)
  625. {
  626. // process your game logic and draw next frame
  627. // this function must exit each frame and return back to windows
  628. // also this function is responsible for controlling the frame rate
  629. // therefore, if you want the game to run at 60fps, then the function should
  630. // take 1/60th of a second before returning
  631.  
  632. // on entry video_buffer and mem_pitch are valid
  633.  
  634. // get input, note how keyboard is accessed with constants "VK_"
  635. // these are defined in "winuser.h" are basically the scan codes
  636. // for letters just use capital ASCII codes
  637.  
  638. FACE3D face; // the triangle object
  639.  
  640. // test for exit
  641. if (KEY_DOWN(VK_ESCAPE))
  642.     PostMessage(main_window_handle,WM_DESTROY,0,0); 
  643.  
  644. // draw 100 polys a frame
  645. for (int polys=0; polys < 100; polys++)
  646. {
  647. // set up the vertices
  648. face.tlist[0].x = rand()%SCREEN_WIDTH;
  649. face.tlist[0].y = rand()%SCREEN_HEIGHT;
  650. face.tlist[0].u = 0;
  651. face.tlist[0].v = 0;
  652.  
  653. face.tlist[1].x = rand()%SCREEN_WIDTH;
  654. face.tlist[1].y = rand()%SCREEN_HEIGHT;
  655. face.tlist[1].u = 0;
  656. face.tlist[1].v = 63;
  657.  
  658. face.tlist[2].x = rand()%SCREEN_WIDTH;
  659. face.tlist[2].y = rand()%SCREEN_HEIGHT;
  660. face.tlist[2].u = 63;
  661. face.tlist[2].v = 63;
  662.  
  663. // assign the texture to your 64x64 texture map buffer
  664. face.texture = bitmap.buffer;
  665.  
  666. // set the clipping coords of the desired 2D viewport
  667. poly_clip_min_x = 0; 
  668. poly_clip_max_x = SCREEN_WIDTH-1;
  669. poly_clip_min_y = 0;
  670. poly_clip_max_y = SCREEN_HEIGHT-1;
  671.  
  672. // then draw the triangle to the rendering buffer
  673. Draw_Textured_Triangle((void *)&face, video_buffer, mem_pitch);
  674.  
  675. } // end for polys
  676.  
  677. // use sleep to slow system down to 60ish fps
  678. Sleep(15);
  679.  
  680. // return and let main event loop work a bit
  681.  
  682. } // end Game_Main
  683.  
  684.