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.