This is one i finished working on a good while ago:
#ifndef _DYNAMIC_VERTEX_BUFFER_H_#define _DYNAMIC_VERTEX_BUFFER_H_#include <vector>#include <d3dx9.h>namespace{ const unsigned int grow_default = 1000; const unsigned int size_default = 1000;}struct Dynamic_Vertexbuffer_Props{ LPDIRECT3DDEVICE9 device; DWORD fvf; D3DPOOL pool; DWORD usage;};template <class T>class DynamicVertexBuffer{public: DynamicVertexBuffer( unsigned int grow, unsigned int capacity, const Dynamic_Vertexbuffer_Props* props ); ~DynamicVertexBuffer(); void Add( T& vertex ); void Add( T vertices[], unsigned int size ); void Add( const std::vector<T>& vec ); void Add( const DynamicVertexBuffer<T>& dvb ); void Extract ( unsigned int first, unsigned int last, std::vector<T>& out ); void Clear(); unsigned int Size() const; unsigned int Capacity() const; void Grow(); void Reset(); void Reset( unsigned int grow, unsigned int capacity, const Dynamic_Vertexbuffer_Props* props ); IDirect3DVertexBuffer9* operator&() { if ( m_vertexBuffer ) return m_vertexBuffer; else return NULL; } const IDirect3DVertexBuffer9& operator*() { if ( m_vertexBuffer ) return *m_vertexBuffer; } inline void operator+=( T& vertex ) { Add( vertex ); }; inline void operator+=( const std::vector<T>& vec ) { Add( vec ); }; inline void operator+=( const DynamicVertexBuffer& dib ) { Add( dib ); }; const LPDIRECT3DVERTEXBUFFER9& Const_Ref() { return m_vertexBuffer; };private: Dynamic_Vertexbuffer_Props m_props; LPDIRECT3DVERTEXBUFFER9 m_vertexBuffer; unsigned int m_size; unsigned int m_capacity; bool m_validProps; bool m_made; unsigned int m_grow; void Create(unsigned int size); bool ValidateProperties(const Dynamic_Vertexbuffer_Props* props);};template<class T>DynamicVertexBuffer<T>::DynamicVertexBuffer( unsigned int grow, unsigned int capacity, const Dynamic_Vertexbuffer_Props* props ) : m_capacity(0), m_size(0), m_made(false), m_validProps(false), m_vertexBuffer(NULL){ Reset( grow, capacity, props );}template<class T>DynamicVertexBuffer<T>::~DynamicVertexBuffer(){ Reset();}template<class T>void DynamicVertexBuffer<T>::Add( T& vertex ){ if ( m_made == true ) { if ( 1 <= (m_capacity - m_size ) ) { void* pDest; m_vertexBuffer->Lock( m_size*sizeof(T), sizeof(T), &pDest, 0); memcpy( pDest, &vertex, sizeof( T ) ); m_vertexBuffer->Unlock(); #ifdef DYNAMICVB_DEBUG OutputDebugString("DynamicVertexBuffer: (INFO) Single vertex added\n"); #endif m_size++; } else { #ifdef DYNAMICVB_DEBUG OutputDebugString("DynamicVertexBuffer: (INFO) Grow needed for single vertex\n"); #endif Grow(); Add( vertex ); } }}template<class T>void DynamicVertexBuffer<T>::Add( T vertices[], unsigned int size ){ if ( m_made == true ) { if ( size <= (m_capacity - m_size ) ) { void* pDest; m_vertexBuffer->Lock( m_size * sizeof(T), size *sizeof( T ), &pDest, 0); memcpy( pDest, &vertices[0], size * sizeof( T ) ); m_vertexBuffer->Unlock(); #ifdef DYNAMICVB_DEBUG OutputDebugString("DynamicVertexBuffer: (INFO) Vertex array added\n"); #endif m_size += size; } else { #ifdef DYNAMICVB_DEBUG OutputDebugString("DynamicVertexBuffer: (INFO) Grow needed for vertex array\n"); #endif Grow(); Add(vertices, size); } }}template<class T>void DynamicVertexBuffer<T>::Add( const std::vector<T>& vec ){ if ( m_made == true ) { if ( vec.size() <= (m_capacity - m_size ) ) { void* pDest; void* pMCRet = NULL; m_vertexBuffer->Lock( m_size * sizeof(T), (unsigned int) vec.size() * sizeof(T), &pDest, 0); pMCRet = memcpy( pDest, &vec[0], vec.size() * sizeof( T ) ); if ( pMCRet == NULL ) { MessageBox(NULL, "pMCRET","", MB_OK ); } m_vertexBuffer->Unlock(); #ifdef DYNAMICVB_DEBUG OutputDebugString("DynamicVertexBuffer: (INFO) Vertex std::vector added\n"); #endif m_size += (unsigned int) vec.size(); } else { #ifdef DYNAMICVB_DEBUG OutputDebugString("DynamicVertexBuffer: (INFO) Grow needed for vertex std::vector\n"); #endif Grow(); Add( vec ); } }}template<class T>void DynamicVertexBuffer<T>::Add( const DynamicVertexBuffer<T>& dvb ){ std::vector<T> tempVertices(dvb.Size()); Extract(0, dvb.Size(), tempVertices); Add(tempVertices);}template<class T>unsigned int DynamicVertexBuffer<T>::Size() const{ return m_size;}template<class T>unsigned int DynamicVertexBuffer<T>::Capacity() const{ return m_capacity;} template<class T>void DynamicVertexBuffer<T>::Grow(){ if ( m_made == true ) { Create( m_capacity + m_grow ); }}template<class T>void DynamicVertexBuffer<T>::Reset(){ m_made = false; m_size = 0; m_capacity = 0; m_validProps = false; if ( m_vertexBuffer != NULL ) m_vertexBuffer->Release(); #ifdef DYNAMICVB_DEBUG OutputDebugString("DynamicVertexBuffer: (INFO) DynamicVertexBuffer Reset\n"); #endif}template<class T>void DynamicVertexBuffer<T>::Reset( unsigned int grow, unsigned int capacity, const Dynamic_Vertexbuffer_Props* props ){ m_made = false; m_size = 0; m_capacity = 0; m_validProps = false; if ( m_vertexBuffer != NULL ) m_vertexBuffer->Release(); #ifdef DYNAMICVB_DEBUG OutputDebugString("DynamicVertexBuffer: (INFO) DynamicVertexBuffer Reset\n"); #endif if ( ValidateProperties( props ) ) { #ifdef DYNAMICVB_DEBUG OutputDebugString("DynamicVertexBuffer: (INFO) Properties valid\n"); #endif this->m_props = ( *props ); if ( grow == 0 ) { m_grow = grow_default; #ifdef DYNAMICVB_DEBUG OutputDebugString("DynamicVertexBuffer: (INFO) Default grow used\n"); #endif } else { m_grow = grow; #ifdef DYNAMICVB_DEBUG OutputDebugString("DynamicVertexBuffer: (INFO) Custom grow used\n"); #endif } if ( capacity != 0 ) { #ifdef DYNAMICVB_DEBUG OutputDebugString("DynamicVertexBuffer: (INFO) Custom capacity used\n"); #endif Create( capacity ); } else { #ifdef DYNAMICVB_DEBUG OutputDebugString("DynamicVertexBuffer: (INFO) Default capacity used\n"); #endif Create( size_default ); } }}template<class T>void DynamicVertexBuffer<T>::Clear(){ m_size = 0; #ifdef DYNAMICVB_DEBUG OutputDebugString("DynamicVertexBuffer: (INFO) DynamicVertexBuffer Clear\n"); #endif}template<class T>void DynamicVertexBuffer<T>::Create( unsigned int capacity ){ if ( m_validProps == true ) { if ( m_vertexBuffer != NULL ) { void* pSource; void* pDest; // create a vector to hold the verts std::vector<T> tempVerts(m_size); // HERE: Only backup of vertices if m_size > 0; if ( m_size > 0 ) { // Lock the current vertex buffer, copy, unlock m_vertexBuffer->Lock( 0, m_size, &pSource, 0); memcpy( &tempVerts[0], pSource, m_size * sizeof(T) ); m_vertexBuffer->Unlock(); #ifdef DYNAMICVB_DEBUG OutputDebugString("DynamicVertexBuffer: (INFO) Vertices backed up before grow\n"); #endif } // BACKUP MADE // release the old buffer m_vertexBuffer->Release(); // create a new one m_props.device->CreateVertexBuffer( capacity * sizeof(T), m_props.usage, m_props.fvf, m_props.pool, &m_vertexBuffer, NULL); #ifdef DYNAMICVB_DEBUG OutputDebugString("DynamicVertexBuffer: (INFO) Larger vertex buffer created\n"); #endif // set the new size m_capacity = capacity; // HERE: Restore the vertices if ( m_size > 0 ) { // Lock the current vertex buffer, copy, unlock m_vertexBuffer->Lock( 0, m_size, &pDest, 0); memcpy( pDest, &tempVerts[0], m_size * sizeof(T) ); m_vertexBuffer->Unlock(); #ifdef DYNAMICVB_DEBUG OutputDebugString("DynamicVertexBuffer: (INFO) Vertices restored after grow\n"); #endif } } else if ( m_vertexBuffer == NULL ) { m_props.device->CreateVertexBuffer( (capacity) * sizeof(T), m_props.usage, m_props.fvf, m_props.pool, &m_vertexBuffer, NULL); #ifdef DYNAMICVB_DEBUG OutputDebugString("DynamicVertexBuffer: (INFO) Vertex buffer created\n"); #endif m_capacity = capacity; m_made = true; } }}template<class T>bool DynamicVertexBuffer<T>::ValidateProperties(const Dynamic_Vertexbuffer_Props* props){ bool valid = true; if ( props->device == NULL ) { valid = false; #ifdef DYNAMICVB_DEBUG OutputDebugString("DynamicVertexBuffer: (ERROR) Device invalid!\n"); #endif } if ( props->fvf == NULL ) { // This is now acceptable for elements //valid = false; #ifdef DYNAMICVB_DEBUG OutputDebugString("DynamicVertexBuffer: (ERROR) FVF invalid!\n"); #endif } if ( ( props->pool < 0 ) || ( props->pool > 3 ) ) { valid = false; #ifdef DYNAMICVB_DEBUG OutputDebugString("DynamicVertexBuffer: (ERROR) Pool invalid!\n"); #endif } if ( props->usage < 0 ) { valid = false; #ifdef DYNAMICVB_DEBUG OutputDebugString("DynamicVertexBuffer: (ERROR) Usage invalid!\n"); #endif } if ( valid == true ) { m_validProps = true; } return valid;}template<class T>void DynamicVertexBuffer<T>::Extract ( unsigned int first, unsigned int last, std::vector<T>& out ){ // check to see if the buffer is writeonly, if so dont allow this and throw a warning to debug out if ( !(this->m_props.usage & D3DUSAGE_WRITEONLY) ) { if ( out.capacity() >= m_size ) { if ( ( last > first ) && (last <= m_size) ) { void* pSource; m_vertexBuffer->Lock( first * sizeof( T ), ( (last-first) * sizeof( T ) ), &pSource, 0); memcpy( &out[0], pSource, (last-first) * sizeof( T ) ); m_vertexBuffer->Unlock(); #ifdef DYNAMICVB_DEBUG OutputDebugString("DynamicVertexBuffer: (ERROR) Extract call - successful\n"); #endif } } else { #ifdef DYNAMICVB_DEBUG OutputDebugString("DynamicVertexBuffer: (ERROR) Extract call - target std::vector bad size\n"); #endif } } else { #ifdef DYNAMICVB_DEBUG OutputDebugString("DynamicVertexBuffer: (ERROR) Extract call - Write only buffer specified\n"); #endif }}#endif
ace