VertexBufferManager.h

00001 #ifndef _VertexBufferManager_H_
00002 #define _VertexBufferManager_H_
00003 
00004 #include <windows.h>
00005 
00006 #include "dxtypes.h"
00007 //#include "Renderer.h"
00008 //#include <assert.h>
00009 
00010 namespace zak {
00011 
00012 template <class PixelFormatClass, unsigned int FVF>
00013 class VertexBufferManager
00014 {
00015         static const int VB_SIZE                = 450;
00016         static const int FLUSH_COUNT    = 150;
00017 public:
00018         // Constructor (es conveniente que flush sea múltiplo de size y de 3)
00019         VertexBufferManager() : _vbSize(VB_SIZE), _flushCount(FLUSH_COUNT), _pVertexBuffer(NULL), _primitiveType(D3DPT_TRIANGLELIST) {}
00020         
00021         // Destructor
00022         ~VertexBufferManager() { if (_pVertexBuffer) _pVertexBuffer->Release(); }
00023 
00024         // Crea un vertex buffer
00025         bool Create(DX_LPDIRECT3DDEVICE pDev, bool bDynamic=true);
00026 
00027         // Libera a un vertex buffer
00028         void Release(void) { if (_pVertexBuffer) _pVertexBuffer->Release(); _pVertexBuffer=NULL; }
00029 
00030         // Actualiza el contenido del vertex buffer
00031         bool Draw(PixelFormatClass * pVtxCollection, D3DPRIMITIVETYPE primitiveType, unsigned int uiVtxCount);
00032 
00033         // Bind
00034         void Bind(void)
00035         {
00036 #ifdef USING_DIRECTX81
00037                 _pDev->SetVertexShader(FVF);
00038                 _pDev->SetStreamSource(0, _pVertexBuffer, sizeof(PixelFormatClass));
00039 #else
00040                 _pDev->SetVertexShader(NULL);
00041                 _pDev->SetFVF(FVF);
00042                 _pDev->SetStreamSource(0, _pVertexBuffer, 0, sizeof(PixelFormatClass));
00043 #endif 
00044         }
00045         
00046         // Envía los datos al pipeline
00047         void Flush();
00048 
00049 private:
00050         const unsigned int      _vbSize;                                        // Cantidad de vértices que contiene el vertex buffer
00051         const unsigned int      _flushCount;                            // Cantidad de vértices entre flushes
00052         DX_LPVERTEXBUFFER       _pVertexBuffer;         // Vertex Buffer encapsulado
00053         DX_LPDIRECT3DDEVICE     _pDev;                          // Device asociado en el método Create
00054         
00055         unsigned int _baseNum;                                          // Base del vertex buffer a lockear
00056         unsigned int _vtxToLock;                                        // Indica la cantidad de vértices lockeados en el vb
00057         D3DPRIMITIVETYPE _primitiveType;                        // Primitiva actual
00058 
00059         
00060 };
00061 
00062 // ------------------------------------------------------------------------------
00063 template <class PixelFormatClass, unsigned int FVF>
00064 bool VertexBufferManager<PixelFormatClass, FVF>::Create(DX_LPDIRECT3DDEVICE pDev, bool bDynamic)
00065 {
00066         _pDev = pDev;
00067 #ifdef USING_DIRECTX81
00068         HRESULT hr = pDev->CreateVertexBuffer(_vbSize*sizeof(PixelFormatClass),
00069                                                                         (bDynamic ? D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC : 0),
00070                                                                         FVF,
00071                                     D3DPOOL_DEFAULT,
00072                                                                         &_pVertexBuffer);
00073 #else
00074         HRESULT hr = pDev->CreateVertexBuffer(_vbSize*sizeof(PixelFormatClass),
00075                 (bDynamic ? D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC : 0),
00076                 FVF,
00077                 D3DPOOL_DEFAULT,
00078                 &_pVertexBuffer, NULL);
00079 #endif 
00080         // Indico que la base de vb a lockear es cero
00081         _baseNum = 0;
00082         
00083         if (hr == D3D_OK)
00084                 return true;
00085         else
00086                 return false;
00087 }
00088 // ------------------------------------------------------------------------------
00089 // Actualiza el contenido del vertex buffer
00090 template <class PixelFormatClass, unsigned int FVF>
00091 bool VertexBufferManager<PixelFormatClass, FVF>::Draw(PixelFormatClass * pVtxCollection, D3DPRIMITIVETYPE primitiveType, unsigned int uiVtxCount)
00092 {
00093         VOID * pVertices;
00094 
00095         // Almaceno cual es la primitiva deseada
00096         _primitiveType = primitiveType;
00097 
00098         // Si la cantidad de vértices que faltan para realizar un flush es menor
00099         // a la cantidad de vértices pasados, copio primero sólo los que faltan
00100         // para el flush y realizo el mismo
00101         _vtxToLock = (_flushCount < uiVtxCount ? _flushCount : uiVtxCount);
00102         
00103         // Verifico que la cantidad de vértices a lockear + la base
00104         // no exeda el tamaño total del vertex buffer
00105         if (_baseNum + _vtxToLock > _vbSize)
00106                 _baseNum = 0;
00107 
00108         // Lockeo el vertex buffer a partir de la base y un chunk correspondiente
00109         // al tamaño del flush
00110 #ifdef USING_DIRECTX81
00111         HRESULT hr = _pVertexBuffer->Lock(_baseNum * sizeof(PixelFormatClass),
00112                                                                                 _vtxToLock * sizeof(PixelFormatClass),
00113                                                                                 (BYTE **) &pVertices,
00114                                                                                 _baseNum ? D3DLOCK_NOOVERWRITE : D3DLOCK_DISCARD);
00115 #else
00116         HRESULT hr = _pVertexBuffer->Lock(_baseNum * sizeof(PixelFormatClass),
00117                                                                                 _vtxToLock * sizeof(PixelFormatClass),
00118                                                                                 (VOID **) &pVertices,
00119                                                                                 _baseNum ? D3DLOCK_NOOVERWRITE : D3DLOCK_DISCARD);
00120 #endif
00121 
00122         // Si no he podido realizar un lock, retorno false
00123         if (hr != D3D_OK)
00124                 return false;
00125 
00126         unsigned int uiVtxProcNow = 0;
00127         // Mientras que queden vértices a copiar...
00128         while (_vtxToLock > 0)
00129         {
00130                 // Copio vértices al vertex buffer
00131                 memcpy( pVertices, &pVtxCollection[uiVtxProcNow], sizeof(PixelFormatClass)*_vtxToLock);
00132 
00133                 // Actualizo el índice de copia de los vértices pasados como parámetros
00134                 uiVtxProcNow += _vtxToLock;
00135                 
00136                 // -------------------------------------------------------------------------
00137                 // Copiados los vértices al vb, los envío al pipeline
00138                 // por medio del DrawPrimitive
00139                 // -------------------------------------------------------------------------
00140                 
00141                 // Destrabo el vb
00142                 _pVertexBuffer->Unlock();
00143 
00144                 // Realizo el DrawPrimitive
00145                 Flush();
00146 
00147                 // Actualizo la base de vértices a lockear
00148                 _baseNum += _vtxToLock;
00149                 
00150                 // Calculo nuevamente la cantidad de vértices a copiar
00151                 _vtxToLock = (_flushCount < (uiVtxCount-uiVtxProcNow) ? _flushCount : uiVtxCount-uiVtxProcNow);
00152 
00153                 // Verifico que la cantidad de vértices a lockear + la base
00154                 // no exeda el tamaño total del vertex buffer
00155                 if (_baseNum + _vtxToLock > _vbSize)
00156                         _baseNum = 0;
00157 
00158 #ifdef USING_DIRECTX81
00159                 hr = _pVertexBuffer->Lock(_baseNum * sizeof(PixelFormatClass),
00160                                                                         _vtxToLock * sizeof(PixelFormatClass),
00161                                                                         (BYTE **) &pVertices,
00162                                                                         _baseNum ? D3DLOCK_NOOVERWRITE : D3DLOCK_DISCARD);
00163 #else
00164                 hr = _pVertexBuffer->Lock(_baseNum * sizeof(PixelFormatClass),
00165                                                                         _vtxToLock * sizeof(PixelFormatClass),
00166                                                                         (VOID **) &pVertices,
00167                                                                         _baseNum ? D3DLOCK_NOOVERWRITE : D3DLOCK_DISCARD);
00168 #endif
00169 
00170                 // Si no he podido realizar un lock, retorno false
00171                 if (hr != D3D_OK)
00172                         return false;
00173         }
00174 
00175         // Destrabo el vb
00176         _pVertexBuffer->Unlock();
00177 
00178         return true;
00179 }
00180 
00181 // ------------------------------------------------------------------------------
00182 // Envía los datos al pipeline
00183 template <class PixelFormatClass, unsigned int FVF>
00184 void VertexBufferManager<PixelFormatClass, FVF>::Flush(void)
00185 {
00186         HRESULT hr;
00187 
00188         int primitiveCount;
00189         
00190         // Determino la cantidad de primitivas a realizar en función
00191         // del tipo
00192         if (_primitiveType == D3DPT_POINTLIST)
00193                 primitiveCount = _vtxToLock;
00194         else if (_primitiveType == D3DPT_LINELIST)
00195                 primitiveCount = _vtxToLock/2;
00196         else if (_primitiveType == D3DPT_LINESTRIP)
00197                 primitiveCount = _vtxToLock-1;
00198         else if (_primitiveType == D3DPT_TRIANGLELIST)
00199                 primitiveCount = _vtxToLock/3;
00200         else if (_primitiveType == D3DPT_TRIANGLESTRIP)
00201                 primitiveCount = _vtxToLock-2;
00202         else if (_primitiveType == D3DPT_TRIANGLEFAN)
00203                 primitiveCount = _vtxToLock-2;
00204         else
00205                 primitiveCount = 0;
00206 
00207         hr = _pDev->DrawPrimitive(_primitiveType, _baseNum, primitiveCount);
00208 
00209 }
00210 
00211 }
00212 
00213 #endif // _VertexBufferManager_H_

Generado el Tue May 29 14:46:15 2007 para Zak Engine v1.1.0 por  doxygen 1.5.1-p1