home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / DirectX SDK / DXSDK / samples / Multimedia / DirectPlay / Maze / MazeClient / SmartVB.h < prev    next >
Encoding:
C/C++ Source or Header  |  2001-10-31  |  10.3 KB  |  301 lines

  1. //----------------------------------------------------------------------------
  2. // File: SmartVB.h
  3. //
  4. // Desc: see main.cpp
  5. //
  6. // Copyright (c) 1999-2001 Microsoft Corp. All rights reserved.
  7. //-----------------------------------------------------------------------------
  8. #ifndef _SMARTVB_H
  9. #define _SMARTVB_H
  10.  
  11.  
  12. #include "DXUtil.h"
  13.  
  14.  
  15. //-----------------------------------------------------------------------------
  16. // Name: 
  17. // Desc: 
  18. //-----------------------------------------------------------------------------
  19. // Smart vertex buffer template class. This performs the usual NOOVERWRITE/DISCARDCONTENTS
  20. // filling loop. Simply call Begin(), then multiple instances of MakeRoom() to be given
  21. // pointers to where to store vertex and index data, then End() when done. The class
  22. // automatically flushes rendering as the buffer fills.
  23. //
  24. // By default rendering is performed by calling DrawIndexedPrimitive with a TRIANGELIST
  25. // consisting of the submitted data, but the client can supply a callback if more complex
  26. // rendering is required (perhaps for multipass?).
  27. typedef void (__stdcall *SmartVBRenderCallback)( LPDIRECT3DVERTEXBUFFER8 pVB,
  28.                                                  DWORD dwStartVertex,
  29.                                                  DWORD dwNumVertices,
  30.                                                  LPDIRECT3DINDEXBUFFER8 pIB,
  31.                                                  DWORD dwStartIndex,
  32.                                                  DWORD dwIndexCount,
  33.                                                  void* pParam );
  34.  
  35.  
  36.  
  37.  
  38. //-----------------------------------------------------------------------------
  39. // Name: 
  40. // Desc: 
  41. //-----------------------------------------------------------------------------
  42. template< class VertType, DWORD VertFVF, DWORD NumIndex > class SmartVB
  43. {
  44. public:
  45.     //-----------------------------------------------------------------------------
  46.     // Name: 
  47.     // Desc:
  48.     //-----------------------------------------------------------------------------
  49.     SmartVB() : m_pVB(NULL), m_pd3dDevice(NULL), m_pIB(NULL)
  50.     { 
  51.         SetRenderCallback(); 
  52.     };
  53.  
  54.  
  55.  
  56.     //-----------------------------------------------------------------------------
  57.     // Name: 
  58.     // Desc:
  59.     //-----------------------------------------------------------------------------
  60.     ~SmartVB()
  61.     {
  62.         Uninit();
  63.     };
  64.  
  65.  
  66.  
  67.     //-----------------------------------------------------------------------------
  68.     // Name: 
  69.     // Desc:
  70.     //-----------------------------------------------------------------------------
  71.     HRESULT Init( IDirect3D8* pD3D, IDirect3DDevice8* pDevice, DWORD dwNumVerts )
  72.     {
  73.         HRESULT hr;
  74.  
  75.         Uninit();
  76.  
  77.         m_dwNumVerts    = dwNumVerts;
  78.         m_pd3dDevice    = pDevice;
  79.  
  80.         if( m_pd3dDevice )
  81.             m_pd3dDevice->AddRef();
  82.         else
  83.             return E_INVALIDARG;
  84.  
  85.         m_pNextIndex    = NULL;
  86.         m_dwNextIndex   = 0;
  87.         if( FAILED( hr = m_pd3dDevice->CreateIndexBuffer( NumIndex * sizeof(WORD),
  88.                                                      D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, 
  89.                                                      D3DPOOL_DEFAULT, &m_pIB ) ) )
  90.             return hr;
  91.  
  92.         m_pNextVert     = NULL;
  93.         m_dwNextVert    = 0;
  94.         DWORD dwFVFSize = D3DXGetFVFVertexSize( VertFVF );
  95.         if( FAILED( hr = m_pd3dDevice->CreateVertexBuffer( dwFVFSize * dwNumVerts, 
  96.                                                     D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY, VertFVF, 
  97.                                                     D3DPOOL_DEFAULT, &m_pVB ) ) )
  98.             return hr;
  99.  
  100.         return S_OK;
  101.     };
  102.  
  103.  
  104.  
  105.     //-----------------------------------------------------------------------------
  106.     // Name: 
  107.     // Desc:
  108.     //-----------------------------------------------------------------------------
  109.     void Uninit()
  110.     {
  111.         SAFE_RELEASE( m_pVB );
  112.         SAFE_RELEASE( m_pIB );
  113.         SAFE_RELEASE( m_pd3dDevice );
  114.     };
  115.  
  116.  
  117.  
  118.     //-----------------------------------------------------------------------------
  119.     // Name: 
  120.     // Desc: Set rendering callback. Passing NULL for the callback gets you a default
  121.     //       call to DrawIndexedPrimitive. pParam is passed through to the callback.
  122.     //-----------------------------------------------------------------------------
  123.     void    SetRenderCallback( SmartVBRenderCallback pCallback = NULL, void* pParam = NULL )
  124.     {
  125.         if ( pCallback != NULL )
  126.         {
  127.             m_pCallback      = pCallback;
  128.             m_pCallbackParam = pParam;
  129.         }
  130.         else
  131.         {
  132.             m_pCallback      = DefaultRenderCallback;
  133.             m_pCallbackParam = this;
  134.         }
  135.     };
  136.  
  137.  
  138.  
  139.     //-----------------------------------------------------------------------------
  140.     // Name: 
  141.     // Desc:
  142.     //-----------------------------------------------------------------------------
  143.     HRESULT Begin()
  144.     {
  145.         // Check we haven't already begun
  146.         if ( m_pNextVert != NULL && m_pNextIndex != NULL )
  147.             return E_FAIL;
  148.  
  149.         // Lock buffer, use D3DLOCK_DISCARD flag
  150.         m_pVB->Lock( 0, 0, (BYTE**)&m_pNextVert, D3DLOCK_DISCARD );
  151.         m_pNextVert     += m_dwNextVert;
  152.         m_dwFirstVert   = m_dwNextVert;
  153.         m_dwVertexCount = 0;
  154.  
  155.         m_pIB->Lock( 0, 0, (BYTE**)&m_pNextIndex, D3DLOCK_DISCARD );
  156.         m_pNextIndex    += m_dwNextIndex;
  157.         m_dwFirstIndex  = m_dwNextIndex;
  158.         m_dwIndexCount  = 0;
  159.  
  160.         return S_OK;
  161.     };
  162.  
  163.  
  164.  
  165.     //-----------------------------------------------------------------------------
  166.     // Name: 
  167.     // Desc: Request space to submit data, may cause a 'flush' for rendering
  168.     //-----------------------------------------------------------------------------
  169.     HRESULT MakeRoom( DWORD dwNumVert, DWORD dwNumIndex, VertType** pVertPtr,
  170.                       WORD** pIndexPtr, WORD* wIndexOffset )
  171.     {
  172.         Flush();
  173.         // Have we room left in the buffer?
  174.         if ( (dwNumVert  + m_dwNextVert  >= m_dwNumVerts) ||
  175.              (dwNumIndex + m_dwNextIndex >= NumIndex) )
  176.         {
  177.             // Nope, so flush current batch
  178.             Flush();
  179.  
  180.             // Check we could fit this in at all
  181.             if ( (dwNumVert > m_dwNumVerts) || (dwNumIndex > NumIndex) )
  182.                 return E_INVALIDARG;
  183.         }
  184.  
  185.         // Got room, so just return position in buffer
  186.         *pVertPtr       = m_pNextVert;
  187.         *pIndexPtr      = m_pNextIndex;
  188.         *wIndexOffset   = WORD(m_dwVertexCount);
  189.  
  190.         // Update position
  191.         m_pNextVert     += dwNumVert;
  192.         m_dwNextVert    += dwNumVert;
  193.         m_dwVertexCount += dwNumVert;
  194.  
  195.         m_pNextIndex    += dwNumIndex;
  196.         m_dwNextIndex   += dwNumIndex;
  197.         m_dwIndexCount  += dwNumIndex;
  198.  
  199.         // Done
  200.         return S_OK;
  201.     };
  202.  
  203.  
  204.  
  205.     //-----------------------------------------------------------------------------
  206.     // Name: 
  207.     // Desc: End data filling, and submit for rendering via callback
  208.     //-----------------------------------------------------------------------------
  209.     void    End()
  210.     {
  211.         // Unlock VB
  212.         m_pVB->Unlock();
  213.         m_pIB->Unlock();
  214.  
  215.         // Submit for rendering
  216.         if ( m_dwVertexCount > 0 && m_dwIndexCount > 0 )
  217.             m_pCallback( m_pVB, m_dwFirstVert, m_dwVertexCount, 
  218.                          m_pIB, m_dwFirstIndex, m_dwIndexCount, 
  219.                          m_pCallbackParam );
  220.  
  221.         m_pNextVert  = NULL;
  222.         m_pNextIndex = NULL;
  223.     };
  224.  
  225.  
  226.  
  227.     //-----------------------------------------------------------------------------
  228.     // Name: 
  229.     // Desc: Flush data if we overflowed
  230.     //-----------------------------------------------------------------------------
  231.     void    Flush()
  232.     {
  233.         // Unlock VB
  234.         m_pVB->Unlock();
  235.         m_pIB->Unlock();
  236.  
  237.         // Submit for rendering
  238.         if ( m_dwVertexCount > 0 && m_dwIndexCount > 0 )
  239.             m_pCallback( m_pVB, m_dwFirstVert, m_dwVertexCount, 
  240.                          m_pIB, m_dwFirstIndex, m_dwIndexCount, 
  241.                          m_pCallbackParam );
  242.  
  243.         // Lock VB again
  244.         m_pVB->Lock( 0, 0, (BYTE**)&m_pNextVert, D3DLOCK_DISCARD );
  245.         m_dwFirstVert   = 0;
  246.         m_dwVertexCount = 0;
  247.         m_dwNextVert    = 0;
  248.  
  249.         m_pIB->Lock( 0, 0, (BYTE**)&m_pNextIndex, D3DLOCK_DISCARD );
  250.         m_dwFirstIndex  = 0;
  251.         m_dwIndexCount  = 0;
  252.         m_dwNextIndex   = 0;
  253.     };
  254.  
  255. protected:
  256.     IDirect3DDevice8*       m_pd3dDevice;
  257.     DWORD                   m_dwNumVerts;
  258.  
  259.     SmartVBRenderCallback   m_pCallback;
  260.     void*                   m_pCallbackParam;
  261.  
  262.     // Current position of 'write cursor' in buffer
  263.     LPDIRECT3DINDEXBUFFER8  m_pIB;
  264.     WORD*                   m_pNextIndex;
  265.     DWORD                   m_dwNextIndex;
  266.     DWORD                   m_dwFirstIndex;
  267.  
  268.     LPDIRECT3DVERTEXBUFFER8 m_pVB;
  269.     VertType*               m_pNextVert;
  270.     DWORD                   m_dwNextVert;
  271.     DWORD                   m_dwFirstVert;
  272.  
  273.     // Counts of vertices and indicies in the current batch
  274.     DWORD                   m_dwVertexCount;
  275.     DWORD                   m_dwIndexCount;
  276.  
  277.     static void __stdcall DefaultRenderCallback( LPDIRECT3DVERTEXBUFFER8 pVB,
  278.                                                  DWORD dwStartVertex,
  279.                                                  DWORD dwNumVertices,
  280.                                                  LPDIRECT3DINDEXBUFFER8 pIB,
  281.                                                  DWORD dwStartIndex,
  282.                                                  DWORD dwIndexCount,
  283.                                                  void* pParam )
  284.     {
  285.         ((SmartVB*)pParam)->m_pd3dDevice->SetVertexShader( VertFVF );
  286.         ((SmartVB*)pParam)->m_pd3dDevice->SetStreamSource( 0, pVB, sizeof(VertType) );
  287.         ((SmartVB*)pParam)->m_pd3dDevice->SetIndices( pIB, 0 );
  288.         ((SmartVB*)pParam)->m_pd3dDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, dwStartVertex, 
  289.                                                                 dwNumVertices, dwStartIndex, dwIndexCount/3 );
  290.     };
  291.  
  292. private:
  293.     SmartVB( const SmartVB& );
  294.     void operator=( const SmartVB& );
  295. };
  296.  
  297.  
  298.  
  299.  
  300. #endif
  301.