This section of the archives stores flipcode's complete Developer Toolbox collection, featuring a variety of mini-articles and source code contributions from our readers.

| Vertex Buffer Proxy Submitted by

I got tired of constantly rewriting code to access data in a D3D vertex buffer. If the vertex format changed, the code would have to be changed. Also, since the vertex data in a ID3DXMesh can be any format, that accessing vertex data in a mesh was complicated. To solve these problems I created this class: VertexBufferProxy. Given a mesh or a vertex buffer, it will figure out the size of each vertex and the offset to each piece of data. The class enables you to access a vertex buffer as if it is an array of vertices. The additional cost ranges from low to none, depending on the compiler's optimizer. Here is an example of accessing vertices using an index buffer:

        indexBuffer.Lock( ... )
        VertexBufferProxy    vb( &vertexBuffer );
        vb.Lock(...);
        for ( int i = 0; i < numIndexes; i++ )
        {
            int index = indexBufferData[i];
            D3DXVECTOR3 v = vb[index].Position();
            D3DXVECTOR3 n = vb[index].Normal();
            ...
        }
        vb.Unlock(...);
        indexBuffer.Unlock(...);

Warning: The code is not thoroughly tested -- your comments and suggestions are apprectiated.

Currently browsing [VBP.zip] (4,783 bytes) - [VertexBufferProxy.cpp] - (7,929 bytes)

    /** @file *//********************************************************************************************************

                                                        VertexBufferProxy.cpp

    	--------------------------------------------------------------------------------------------------------------

    	$Header: //depot/Libraries/Dxx/VertexBufferProxy.cpp#6 $

    	$NoKeywords: $

    *********************************************************************************************************************/

    #include "PrecompiledHeaders.h"

    #include "VertexBufferProxy.h"

    #include <d3d9.h>
    #include <d3dx9.h>

    namespace Dxx
    {

    /********************************************************************************************************************/
    /*																													*/
    /*																													*/
    /********************************************************************************************************************/

    ///
    /// @param	pMesh	Mesh containing the vertex buffer to proxy

    VertexBufferProxy::VertexBufferProxy( ID3DXMesh * pMesh )
    {
    	pMesh->GetVertexBuffer( &m_pBuffer );

    	// Get the "Desc" data

    	m_pBuffer->GetDesc( &m_Desc );

    	InitializeOffsets();
    }

    /********************************************************************************************************************/
    /*																													*/
    /*																													*/
    /********************************************************************************************************************/

    /// @param	pBuffer		Vertex buffer to proxy

    VertexBufferProxy::VertexBufferProxy( IDirect3DVertexBuffer9 * pBuffer )
    	: m_pBuffer( pBuffer )
    {
    	m_pBuffer->AddRef();

    	// Get the "Desc" data

    	m_pBuffer->GetDesc( &m_Desc );

    	InitializeOffsets();
    }

    /********************************************************************************************************************/
    /*																													*/
    /*																													*/
    /********************************************************************************************************************/

    void VertexBufferProxy::InitializeOffsets()
    {
    	int		bump;

    	// Compute the stride and offset values

    	switch ( m_Desc.FVF & D3DFVF_POSITION_MASK )
    	{
    	case D3DFVF_XYZ:
    		bump					= sizeof( D3DVECTOR );
    		break;

    	case D3DFVF_XYZRHW:
    	case D3DFVF_XYZW:
    		m_WOffset				= sizeof( D3DVECTOR );
    		bump					= m_WOffset				+ sizeof( float );
    		break;

    	case D3DFVF_XYZB1:
    		m_Blend0Offset			= sizeof( D3DVECTOR );
    		bump					= m_Blend0Offset		+ sizeof( float );
    		break;

    	case D3DFVF_XYZB2:
    		m_Blend0Offset			= sizeof( D3DVECTOR );
    		m_Blend1Offset			= m_Blend0Offset 		+ sizeof( float );
    		bump					= m_Blend1Offset 		+ sizeof( float );
    		break;

    	case D3DFVF_XYZB3:
    		m_Blend0Offset			= sizeof( D3DVECTOR );
    		m_Blend1Offset			= m_Blend0Offset 		+ sizeof( float );
    		m_Blend2Offset			= m_Blend1Offset 		+ sizeof( float );
    		bump					= m_Blend2Offset 		+ sizeof( float );
    		break;

    	case D3DFVF_XYZB4:
    		m_Blend0Offset			= sizeof( D3DVECTOR );
    		m_Blend1Offset			= m_Blend0Offset 		+ sizeof( float );
    		m_Blend2Offset			= m_Blend1Offset 		+ sizeof( float );
    		m_Blend3Offset			= m_Blend2Offset 		+ sizeof( float );
    		bump					= m_Blend3Offset 		+ sizeof( float );
    		break;

    	case D3DFVF_XYZB5:
    		m_Blend0Offset			= sizeof( D3DVECTOR );
    		m_Blend1Offset			= m_Blend0Offset		+ sizeof( float );
    		m_Blend2Offset			= m_Blend1Offset		+ sizeof( float );
    		m_Blend3Offset			= m_Blend2Offset		+ sizeof( float );
    		m_BlendIndexesOffset	= m_Blend3Offset		+ sizeof( float );
    		bump					= m_BlendIndexesOffset	+ sizeof( DWORD );
    		break;

    	default:
    		bump					 = 0;	// No position value.
    		break;
    	}

    	m_NormalOffset			= bump;
    	m_PointSizeOffset		= bump;
    	m_DiffuseOffset			= bump;
    	m_SpecularOffset		= bump;
    	m_TexCoord0Offset		= bump;
    	m_TexCoord1Offset		= bump;
    	m_TexCoord2Offset		= bump;
    	m_TexCoord3Offset		= bump;
    	m_TexCoord4Offset		= bump;
    	m_TexCoord5Offset		= bump;
    	m_TexCoord6Offset		= bump;
    	m_TexCoord7Offset		= bump;
    	m_Stride				= bump;

    	if ( ( m_Desc.FVF & D3DFVF_NORMAL ) != 0 )
    	{
    		bump					= sizeof( D3DVECTOR );
    		m_PointSizeOffset		+= bump;
    		m_DiffuseOffset			+= bump;
    		m_SpecularOffset		+= bump;
    		m_TexCoord0Offset		+= bump;
    		m_TexCoord1Offset		+= bump;
    		m_TexCoord2Offset		+= bump;
    		m_TexCoord3Offset		+= bump;
    		m_TexCoord4Offset		+= bump;
    		m_TexCoord5Offset		+= bump;
    		m_TexCoord6Offset		+= bump;
    		m_TexCoord7Offset		+= bump;
    		m_Stride				+= bump;
    	}

    	if ( ( m_Desc.FVF & D3DFVF_PSIZE ) != 0 )
    	{
    		bump					= sizeof( float );
    		m_DiffuseOffset			+= bump;
    		m_SpecularOffset		+= bump;
    		m_TexCoord0Offset		+= bump;
    		m_TexCoord1Offset		+= bump;
    		m_TexCoord2Offset		+= bump;
    		m_TexCoord3Offset		+= bump;
    		m_TexCoord4Offset		+= bump;
    		m_TexCoord5Offset		+= bump;
    		m_TexCoord6Offset		+= bump;
    		m_TexCoord7Offset		+= bump;
    		m_Stride				+= bump;
    	}

    	if ( ( m_Desc.FVF & D3DFVF_DIFFUSE ) != 0 )
    	{
    		bump					= sizeof( DWORD );
    		m_SpecularOffset		+= bump;
    		m_TexCoord0Offset		+= bump;
    		m_TexCoord1Offset		+= bump;
    		m_TexCoord2Offset		+= bump;
    		m_TexCoord3Offset		+= bump;
    		m_TexCoord4Offset		+= bump;
    		m_TexCoord5Offset		+= bump;
    		m_TexCoord6Offset		+= bump;
    		m_TexCoord7Offset		+= bump;
    		m_Stride				+= bump;
    	}

    	if ( ( m_Desc.FVF & D3DFVF_SPECULAR ) != 0 )
    	{
    		bump					= sizeof( DWORD );
    		m_TexCoord0Offset		+= bump;
    		m_TexCoord1Offset		+= bump;
    		m_TexCoord2Offset		+= bump;
    		m_TexCoord3Offset		+= bump;
    		m_TexCoord4Offset		+= bump;
    		m_TexCoord5Offset		+= bump;
    		m_TexCoord6Offset		+= bump;
    		m_TexCoord7Offset		+= bump;
    		m_Stride				+= bump;
    	}

    	switch ( m_Desc.FVF & D3DFVF_TEXCOUNT_MASK )
    	{
    	case D3DFVF_TEX8:
    		bump = ( ( ( ( m_Desc.FVF >> 30 ) + 1 ) & 3 ) + 1 ) * sizeof( float );
    		m_Stride				+= bump;
    		/* fall through */

    	case D3DFVF_TEX7:
    		bump = ( ( ( ( m_Desc.FVF >> 28 ) + 1 ) & 3 ) + 1 ) * sizeof( float );
    		m_TexCoord7Offset		+= bump;
    		m_Stride				+= bump;
    		/* fall through */

    	case D3DFVF_TEX6:
    		bump = ( ( ( ( m_Desc.FVF >> 26 ) + 1 ) & 3 ) + 1 ) * sizeof( float );
    		m_TexCoord6Offset		+= bump;
    		m_TexCoord7Offset		+= bump;
    		m_Stride				+= bump;
    		/* fall through */

    	case D3DFVF_TEX5:
    		bump = ( ( ( ( m_Desc.FVF >> 24 ) + 1 ) & 3 ) + 1 ) * sizeof( float );
    		m_TexCoord5Offset		+= bump;
    		m_TexCoord6Offset		+= bump;
    		m_TexCoord7Offset		+= bump;
    		m_Stride				+= bump;
    		/* fall through */

    	case D3DFVF_TEX4:
    		bump = ( ( ( ( m_Desc.FVF >> 22 ) + 1 ) & 3 ) + 1 ) * sizeof( float );
    		m_TexCoord4Offset		+= bump;
    		m_TexCoord5Offset		+= bump;
    		m_TexCoord6Offset		+= bump;
    		m_TexCoord7Offset		+= bump;
    		m_Stride				+= bump;
    		/* fall through */

    	case D3DFVF_TEX3:
    		bump = ( ( ( ( m_Desc.FVF >> 20 ) + 1 ) & 3 ) + 1 ) * sizeof( float );
    		m_TexCoord3Offset		+= bump;
    		m_TexCoord4Offset		+= bump;
    		m_TexCoord5Offset		+= bump;
    		m_TexCoord6Offset		+= bump;
    		m_TexCoord7Offset		+= bump;
    		m_Stride				+= bump;
    		/* fall through */

    	case D3DFVF_TEX2:
    		bump = ( ( ( ( m_Desc.FVF >> 18 ) + 1 ) & 3 ) + 1 ) * sizeof( float );
    		m_TexCoord2Offset		+= bump;
    		m_TexCoord3Offset		+= bump;
    		m_TexCoord4Offset		+= bump;
    		m_TexCoord5Offset		+= bump;
    		m_TexCoord6Offset		+= bump;
    		m_TexCoord7Offset		+= bump;
    		m_Stride				+= bump;
    		/* fall through */

    	case D3DFVF_TEX1:
    		bump = ( ( ( ( m_Desc.FVF >> 16 ) + 1 ) & 3 ) + 1 ) * sizeof( float );
    		m_TexCoord1Offset		+= bump;
    		m_TexCoord2Offset		+= bump;
    		m_TexCoord3Offset		+= bump;
    		m_TexCoord4Offset		+= bump;
    		m_TexCoord5Offset		+= bump;
    		m_TexCoord6Offset		+= bump;
    		m_TexCoord7Offset		+= bump;
    		m_Stride				+= bump;
    	}
    }

    } // namespace Dxx

Currently browsing [VBP.zip] (4,783 bytes) - [VertexBufferProxy.h] - (9,364 bytes)

    #if !defined( DXX_VERTEXBUFFERPROXY_H_INCLUDED )
    #define DXX_VERTEXBUFFERPROXY_H_INCLUDED

    #pragma once

    /** @file *//********************************************************************************************************

                                                         VertexBufferProxy.h

    	--------------------------------------------------------------------------------------------------------------

    	$Header: //depot/Libraries/Dxx/VertexBufferProxy.h#5 $

    	$NoKeywords: $

    *********************************************************************************************************************/

    #define WIN32_LEAN_AND_MEAN
    #define NOMINMAX
    #include <d3d9.h>
    #include <d3dx9.h>

    namespace Dxx
    {

    /// @defgroup	VertexBufferProxy	VertexBufferProxy Classes
    /// Classes associated with VertexBufferProxy
    /// @ingroup	D3dx

    /********************************************************************************************************************/
    /*																													*/
    /*																													*/
    /********************************************************************************************************************/

    /// A class that gives structured access to vertices in a vertex buffer.

    /// @ingroup VertexBufferProxy

    class VertexBufferProxy
    {
    	friend class VRefBase;

    public:

    	class VRefBase;	// Declared below
    	class VRef;		// Declared below
    	class VPtr;		// Declared below

    	/// Constructor
    	VertexBufferProxy( ID3DXMesh * pMesh );

    	/// Constructor
    	VertexBufferProxy( IDirect3DVertexBuffer9 * pBuffer );

    	/// Destructor
    	~VertexBufferProxy();

    	/// Returns the vertex buffer
    	IDirect3DVertexBuffer9 * GetVertexBuffer() const;

    	/// Locks the buffer
    	HRESULT Lock( UINT OffsetToLock, UINT SizeToLock, DWORD Flags );

    	/// Unlocks the buffer
    	HRESULT Unlock();

    	/// Returns a pointer to a vertex (in the form of a VPtr).
    	void * GetVertex( int i ) const;

    	/// Returns a reference to a vertex (in the form of a VRef).
    	VRef operator[]( int i ) const;

    private:

    	/// Initializes the offset values
    	void InitializeOffsets();

    	IDirect3DVertexBuffer9 *	m_pBuffer;				///< The vertex buffer.
    	D3DVERTEXBUFFER_DESC		m_Desc;					///< The "Desc" data for the buffer.
    	void * 						m_pData;				///< Pointer to vertex buffer data (valid only while locked)
    	int 						m_LockOffset;			///< Offset to beginning of the locked data
    	int 						m_WOffset;				///< Offset to the W value.
    	int 						m_Blend0Offset;			///< Offset to the 1st blending weight value.
    	int 						m_Blend1Offset;			///< Offset to the 2nd blending weight value.
    	int 						m_Blend2Offset;			///< Offset to the 3rd blending weight value.
    	int 						m_Blend3Offset;			///< Offset to the 4th blending weight value.
    	int 						m_BlendIndexesOffset;	///< Offset to the blending weight indexes.
    	int 						m_NormalOffset;			///< Offset to the normal value.
    	int 						m_PointSizeOffset;		///< Offset to the point size value.
    	int 						m_DiffuseOffset;		///< Offset to the diffuse color value.
    	int 						m_SpecularOffset;		///< Offset to the specular value.
    	int 						m_TexCoord0Offset;		///< Offset to the 1st set of texture coordinates.
    	int 						m_TexCoord1Offset;		///< Offset to the 2nd set of texture coordinates.
    	int 						m_TexCoord2Offset;		///< Offset to the 3rd set of texture coordinates.
    	int 						m_TexCoord3Offset;		///< Offset to the 4th set of texture coordinates.
    	int 						m_TexCoord4Offset;		///< Offset to the 5th set of texture coordinates.
    	int 						m_TexCoord5Offset;		///< Offset to the 6th set of texture coordinates.
    	int 						m_TexCoord6Offset;		///< Offset to the 7th set of texture coordinates.
    	int 						m_TexCoord7Offset;		///< Offset to the 8th set of texture coordinates.
    	int							m_Stride;				///< Size of a vertex in bytes.
    };

    /********************************************************************************************************************/
    /*																													*/
    /*																													*/
    /********************************************************************************************************************/

    /// A class that refers to a vertex in a vertex buffer. For use by VRef and VPtr.

    /// @ingroup VertexBufferProxy

    /// This class is common to both VRef and VPtr and is used to enable access to vertex values through both pointer
    /// and reference interfaces.

    class VertexBufferProxy::VRefBase
    {
    public:

    	/// Constructor
    	VRefBase( VertexBufferProxy const * pProxy, void * pVertex );

    	/// Returns a reference to the position value.
    	D3DXVECTOR3 & Position() const;

    	/// Returns a reference to the W value.
    	float & W() const;

    	/// Returns a reference to the 1st blending weight value.
    	float & Blend0() const;

    	/// Returns a reference to the 2nd blending weight value.
    	float & Blend1() const;

    	/// Returns a reference to the 3rd blending weight value.
    	float & Blend2() const;

    	/// Returns a reference to the 4th blending weight value.
    	float & Blend3() const;

    	/// Returns a reference to the blending weight indexes.
    	float & BlendIndexes() const;

    	/// Returns a reference to the normal value.
    	D3DXVECTOR3 & Normal() const;

    	/// Returns a reference to the point size value.
    	float & PointSize() const;

    	/// Returns a reference to the diffuse color value.
    	DWORD & Diffuse() const;

    	/// Returns a reference to the specular value.
    	DWORD & Specular() const;

    	/// Returns a pointer to the 1st set of texture coordinates.
    	float * TexCoord0() const;

    	/// Returns a pointer to the 2nd set of texture coordinates.
    	float * TexCoord1() const;

    	/// Returns a pointer to the 3rd set of texture coordinates.
    	float * TexCoord2() const;

    	/// Returns a pointer to the 4th set of texture coordinates.
    	float * TexCoord3() const;

    	/// Returns a pointer to the 5th set of texture coordinates.
    	float * TexCoord4() const;

    	/// Returns a pointer to the 6th set of texture coordinates.
    	float * TexCoord5() const;

    	/// Returns a pointer to the 7th set of texture coordinates.
    	float * TexCoord6() const;

    	/// Returns a pointer to the 8th set of texture coordinates.
    	float * TexCoord7() const;

    protected:

    	VertexBufferProxy const *	m_pProxy;	///< Which vertex buffer proxy this vertex belongs to.
    	void *						m_pVertex;	///< Start of this vertex's data.
    };

    /********************************************************************************************************************/
    /*																													*/
    /*																													*/
    /********************************************************************************************************************/

    /// A class that acts as a pointer to a vertex in a vertex buffer

    /// @ingroup VertexBufferProxy

    class VertexBufferProxy::VPtr : private VertexBufferProxy::VRefBase
    {
    public:

    	/// Constructor
    	VPtr( VertexBufferProxy const * pProxy, void * pVertex );

    	/// @name Overloaded Operators
    	//@{

    	/// Dereference
    	VertexBufferProxy::VRef operator*() const;

    	/// Subscript
    	VertexBufferProxy::VRef operator[]( int i ) const;

    	/// Member selection by reference
    	VertexBufferProxy::VRefBase const * operator->() const;

    	/// Member selection by reference
    	VertexBufferProxy::VRefBase * operator->();

    	/// Pre-increment
    	VPtr & operator++();

    	/// Post-increment
    	VPtr operator++( int );

    	/// Pre-decrement
    	VPtr & operator--();

    	/// Post-decrement
    	VPtr operator--( int );

    	/// Addition assignment
    	VPtr & operator+=( int i );

    	/// Subtraction assignment
    	VPtr & operator-=( int i );

    	/// Converion to void *
    	operator void*() const;

    	//@}
    };

    } // namespace Dxx

    /********************************************************************************************************************/
    /*																													*/
    /*																													*/
    /********************************************************************************************************************/

    /// @name Binary Operators for VertexBufferProxy::VPtr
    /// @ingroup VertexBufferProxy
    //@{

    /// Vptr addition operator
    Dxx::VertexBufferProxy::VPtr operator+( Dxx::VertexBufferProxy::VPtr const & vptr, int i );

    /// Vptr subtraction operator
    Dxx::VertexBufferProxy::VPtr operator-( Dxx::VertexBufferProxy::VPtr const & vptr, int i );

    /// Vptr addition operator
    Dxx::VertexBufferProxy::VPtr operator+( int i, Dxx::VertexBufferProxy::VPtr const & vptr );

    //@}

    /********************************************************************************************************************/
    /*																													*/
    /*																													*/
    /********************************************************************************************************************/
    namespace Dxx
    {

    /// A class that refers a vertex in a vertex buffer

    /// @ingroup VertexBufferProxy

    class VertexBufferProxy::VRef : public VertexBufferProxy::VRefBase
    {
    public:

    	/// Constructor
    	VRef( VertexBufferProxy const * pProxy, void * pVertex );

    	/// Returns a pointer to the vertex data (in the form of a VPtr)
    	VPtr operator &();
    };

    } // namespace Dxx

    // Inline functions

    #include "VertexBufferProxy.inl"

    #endif // !defined( DXX_VERTEXBUFFERPROXY_H_INCLUDED )

The zip file viewer built into the Developer Toolbox made use of the zlib library, as well as the zlibdll source additions.

Copyright 1999-2008 (C) FLIPCODE.COM and/or the original content author(s). All rights reserved.
Please read our Terms, Conditions, and Privacy information.