Jump to content
  • Advertisement
Sign in to follow this  
buggypixels

DX9: Generic VertexBuffer using template

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

If you intended to correct an error in the post then please contact us.

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 this post


Link to post
Share on other sites
Advertisement
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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.


Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!