# DX9: Generic VertexBuffer using template

This topic is 2885 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hi everyone,

I am trying to build a generic vertexbuffer. Generic means that I could use any kind of Vertex along a VertexDeclaration. So far I have a working version which is posted below.
The problem is the way how I copy the data to the vertex buffer. First I get a warning from the compiler. Here is the snippet:

 template<class T> void DynamicVertexBuffer<T>::update() { int total = m_Vertices.size(); if ( total > 0 ) { T* pVertices; HR(vertexBuffer->Lock( 0, 0, ( void** )&pVertices, 0 )); for ( size_t i = 0; i < total; ++i ) { m_Vertices->set(pVertices); pVertices++; } HR(vertexBuffer->Unlock()); } m_numVertices = total; }

Basically I want the vertex buffer to have a list/vector of vertices and the update method will copy the vertices to the buffer. The warning is about this line:
 T* pVertices; 

Also I do not like the way how I currently handle the building of the pointer:

 m_Vertices->set(pVertices); 

But that was the only solution I could come up with that is working.
When you search around the internet you can find a huge list of examples but they all take a slightly different approach.
For example Chad Vernon uses a method like this in his generic vertex buffer:

 BOOL SetData( UINT numVertices, void *pVertices, DWORD flags = D3DLOCK_DISCARD ); 

So in his code the vertex buffer is not storing the data (which I would prefer). Also he uses arrays and memcopy to build the actual vertex buffer.
I would still prefer the vector/list approach.

Now here are my questions:
• I am on the wrong track
• Can somebody give me a hint about the compiler warning
• Does someone has a better idea
• Should I drop my stuff and simply take the same approach as all the others

Any feedback would be great.

Here is the entire code:
 #pragma once #include "..\dxstdafx.h" #include "IndexBuffer.h" #include <vector> namespace ds { template <class T> class DynamicVertexBuffer { typedef std::vector<T*> Vertices; public: DynamicVertexBuffer(D3DPRIMITIVETYPE primitiveType,IDirect3DVertexDeclaration9* vertexDeclaration,const int& vertexSize,const int& maxVertices); ~DynamicVertexBuffer(); void addVertex(T* v); void clear(); void update(); void preRendering(); void render(int numPrimitives); void postRendering(); private: Vertices m_Vertices; int m_MaxVertices; IDirect3DVertexDeclaration9* m_VertexDeclaration; LPDIRECT3DVERTEXBUFFER9 vertexBuffer; IndexBuffer* indexBuffer; UINT m_numVertices; int m_vertexSize; D3DPRIMITIVETYPE m_primitiveType; }; template<class T> DynamicVertexBuffer<T>::DynamicVertexBuffer(D3DPRIMITIVETYPE primitiveType,IDirect3DVertexDeclaration9* vertexDeclaration,const int& vertexSize,const int& maxVertices) : m_VertexDeclaration(vertexDeclaration) , m_vertexSize(vertexSize) , m_primitiveType(primitiveType) , m_MaxVertices(maxVertices) { IDirect3DDevice9 * pDevice = gEngine->getDevice(); D3DPOOL pool = D3DPOOL_DEFAULT; DWORD usage = D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC; LOG(logINFO) << "creating new dynamic vertext buffer - size: " << m_MaxVertices; HR(pDevice->CreateVertexBuffer( m_MaxVertices * vertexSize,usage,0 ,pool, &vertexBuffer, NULL )); indexBuffer = 0; } template<class T> DynamicVertexBuffer<T>::~DynamicVertexBuffer() { if( vertexBuffer ) { vertexBuffer->Release(); vertexBuffer = NULL; } } template<class T> void DynamicVertexBuffer<T>::addVertex(T* v) { m_Vertices.push_back(v); } template<class T> void DynamicVertexBuffer<T>::clear() { for ( size_t i = 0 ; i < m_Vertices.size(); ++i ) { delete m_Vertices; } m_Vertices.clear(); } template<class T> void DynamicVertexBuffer<T>::update() { int total = m_Vertices.size(); if ( total > 0 ) { T* pVertices; HR(vertexBuffer->Lock( 0, 0, ( void** )&pVertices, 0 )); for ( size_t i = 0; i < total; ++i ) { m_Vertices->set(pVertices); pVertices++; } HR(vertexBuffer->Unlock()); } m_numVertices = total; } template<class T> void DynamicVertexBuffer<T>::preRendering() { if ( m_numVertices > 0 ) { IDirect3DDevice9 * pDevice = gEngine->getDevice(); update(); if ( indexBuffer != 0 ) { indexBuffer->init(); } pDevice->SetStreamSource( 0, vertexBuffer, 0, m_vertexSize ); pDevice->SetVertexDeclaration(m_VertexDeclaration); } } template<class T> void DynamicVertexBuffer<T>::render(int numPrimitives) { if ( m_numVertices > 0 ) { IDirect3DDevice9 * pDevice = gEngine->getDevice(); if ( indexBuffer ) { HR(pDevice->SetIndices( indexBuffer->getIndexBuffer() )); HR(pDevice->DrawIndexedPrimitive( m_primitiveType, 0, 0, m_numVertices, 0, numPrimitives )); gEngine->getDrawCounter()->addIndices(indexBuffer->getSize()); gEngine->getDrawCounter()->addPrimitives(m_numVertices); } else { HR(pDevice->DrawPrimitive(m_primitiveType,0,numPrimitives)); gEngine->getDrawCounter()->addPrimitives(m_numVertices); } } } template<class T> void DynamicVertexBuffer<T>::postRendering() { } }; 

##### Share on other sites
The solution was quite easy. Instead of using vector I am not using an array. It is also much easier to copy the data to memory.
Now I have a nice vertex and index buffer that can use any kind of vertex data.

If anyone is interested I can post the code.

##### Share on other sites

The solution was quite easy. Instead of using vector I am not using an array. It is also much easier to copy the data to memory.
Now I have a nice vertex and index buffer that can use any kind of vertex data.

If anyone is interested I can post the code.

Any information about DirectX is good to post because Microsoft don't have enough examples.

##### Share on other sites
I have posted the code along with some short explanations at my webset buggypixels.com
Hope you find it interesting.

##### Share on other sites

Any information about DirectX is good to post because Microsoft don't have enough examples.

That was sarcasm, right? Was it?

@buggypixels
The idea with the templated VertexBuffer seems pretty neat. Never thought about that.
On the other hand there are only a few places in my code where I actually update a vertex buffer, so the extra code might not be worth the effort.

##### Share on other sites
It's not only about the update, I think. The boilerplating can not only ease the creation of "meshes", but all the details - like setting streams, declarations and especially the correct parameters for the draw call - one has to care about when doing it manually can (hopefully) be forgotten now. It's an abstraction after all. So, yeah, pretty neat, Thanks for sharing.

I've one concern with your implementation, though: You're fixed to 16-bit indices. I'm not very much C++, but you could probably just use a second type parameter for your template

##### Share on other sites

I've one concern with your implementation, though: You're fixed to 16-bit indices. I'm not very much C++, but you could probably just use a second type parameter for your template

You are right. Right now I only need 16-bit indices in my engine. But it should be straight forward to use the index type as second template type.

My next step is to support subsets within the vertex buffer. Basically the same as you have when using the IDXMesh object. So I can activate or deactivate certain subsets
and do not take care of rendering any particular subset individually. Someone might argue that I could use the said IDXMesh. But hey, I am doing it for the fun of it.

As you can see that actual part of setting textures/shaders/materials are not part of the vertex buffer since the engine during the render stages takes care of this already.
So probably this is not as generic as it could be. I just wanted to share the idea of using a template here.

1. 1
2. 2
3. 3
Rutin
12
4. 4
5. 5

• 26
• 10
• 9
• 9
• 11
• ### Forum Statistics

• Total Topics
633695
• Total Posts
3013382
×