00001 #ifndef _VertexBufferManager_H_
00002 #define _VertexBufferManager_H_
00003
00004 #include <windows.h>
00005
00006 #include "dxtypes.h"
00007
00008
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
00019 VertexBufferManager() : _vbSize(VB_SIZE), _flushCount(FLUSH_COUNT), _pVertexBuffer(NULL), _primitiveType(D3DPT_TRIANGLELIST) {}
00020
00021
00022 ~VertexBufferManager() { if (_pVertexBuffer) _pVertexBuffer->Release(); }
00023
00024
00025 bool Create(DX_LPDIRECT3DDEVICE pDev, bool bDynamic=true);
00026
00027
00028 void Release(void) { if (_pVertexBuffer) _pVertexBuffer->Release(); _pVertexBuffer=NULL; }
00029
00030
00031 bool Draw(PixelFormatClass * pVtxCollection, D3DPRIMITIVETYPE primitiveType, unsigned int uiVtxCount);
00032
00033
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
00047 void Flush();
00048
00049 private:
00050 const unsigned int _vbSize;
00051 const unsigned int _flushCount;
00052 DX_LPVERTEXBUFFER _pVertexBuffer;
00053 DX_LPDIRECT3DDEVICE _pDev;
00054
00055 unsigned int _baseNum;
00056 unsigned int _vtxToLock;
00057 D3DPRIMITIVETYPE _primitiveType;
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
00081 _baseNum = 0;
00082
00083 if (hr == D3D_OK)
00084 return true;
00085 else
00086 return false;
00087 }
00088
00089
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
00096 _primitiveType = primitiveType;
00097
00098
00099
00100
00101 _vtxToLock = (_flushCount < uiVtxCount ? _flushCount : uiVtxCount);
00102
00103
00104
00105 if (_baseNum + _vtxToLock > _vbSize)
00106 _baseNum = 0;
00107
00108
00109
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
00123 if (hr != D3D_OK)
00124 return false;
00125
00126 unsigned int uiVtxProcNow = 0;
00127
00128 while (_vtxToLock > 0)
00129 {
00130
00131 memcpy( pVertices, &pVtxCollection[uiVtxProcNow], sizeof(PixelFormatClass)*_vtxToLock);
00132
00133
00134 uiVtxProcNow += _vtxToLock;
00135
00136
00137
00138
00139
00140
00141
00142 _pVertexBuffer->Unlock();
00143
00144
00145 Flush();
00146
00147
00148 _baseNum += _vtxToLock;
00149
00150
00151 _vtxToLock = (_flushCount < (uiVtxCount-uiVtxProcNow) ? _flushCount : uiVtxCount-uiVtxProcNow);
00152
00153
00154
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
00171 if (hr != D3D_OK)
00172 return false;
00173 }
00174
00175
00176 _pVertexBuffer->Unlock();
00177
00178 return true;
00179 }
00180
00181
00182
00183 template <class PixelFormatClass, unsigned int FVF>
00184 void VertexBufferManager<PixelFormatClass, FVF>::Flush(void)
00185 {
00186 HRESULT hr;
00187
00188 int primitiveCount;
00189
00190
00191
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_