|
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.
|