Now that I had a basic application running and managed to import model data, I needed to look into how to get said data into a DirectX compatible format. So, without going into too many details: For each mesh I needed a Vertex Buffer, a Vertex Declaration and an Index Buffer. Since each mesh can come with a variety of different vertex data, I opted to implement a somewhat generic approach: I added an abstraction layer called DataConverter
. A DataConverter
has an input data type (either a assimp value type or an array of assimp values) and a function Copy()
which will convert the data to a desired type and store it into a target array. Data Converters also know about the corresponding DirectX Vertex formats, they can generate a list of D3DVERTEXELEMENT9
elements and copy them to an array via the function CopyType()
. Here’s the interface definition for a basic Data Converter
class DataConverter { protected: D3DDECLUSAGE mUsageType; int mUsageIndex; int mOffset; public: DataConverter( D3DDECLUSAGE usageType, int usageIndex, int offsetInBytes ) : mUsageType( usageType ) , mUsageIndex( usageIndex ) , mOffset( offsetInBytes ) {} virtual int Size() = 0; virtual void CopyType( std::vector<D3DVERTEXELEMENT9>& out_Type ) = 0; virtual void CopyData( BYTE* destination, int index ) = 0; };
In order to make working with assimp value arrays easier I derived an ArrayDataConverter
from DataConverter
template< typename T > class ArrayDataConverter : public DataConverter { const T* mSourceData; const int mSourceSize; public: ArrayDataConverter( D3DDECLUSAGE usageType, int usageIndex, int& offsetInBytes, const T* sourceData, int sourceSize ) : DataConverter( usageType, usageIndex, offsetInBytes ) , mSourceData( sourceData ) , mSourceSize( sourceSize ) {} const T& GetElement( int index ) { assert( index >= 0 && index < mSourceSize ); return mSourceData[index]; } };
which basically adds a GetElement()
function that lets us retrieve an element from the underlying source data. So, give these two definitions here’s the simple and elegant definition of the
struct aiVector3DToFloat2Converter : public ArrayDataConverter<aiVector3D> { aiVector3DToFloat2Converter( D3DDECLUSAGE usageType, int usageIndex, int& offsetInBytes, const aiVector3D* sourceData, int sourceSize ) : ArrayDataConverter<aiVector3D>( usageType, usageIndex, offsetInBytes, sourceData, sourceSize ) {} int Size() { return 2 * sizeof(float); } virtual void CopyType( std::vector<D3DVERTEXELEMENT9>& out_Type ) { D3DVERTEXELEMENT9 _result = { 0, mOffset, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, mUsageType, mUsageIndex }; out_Type.push_back( _result ); } void CopyData( BYTE* destination, int elementIndex ) { const aiVector3D& element = GetElement( elementIndex ); float data[] = { element[0], element[1] }; memcpy( destination + mOffset, data, Size() ); } };
Some more praise to the Assimp developers: The scene data is stored in a very understandable and easy to access format. Only took me a couple of hours to get that into DirectX compatible buffers. Great work guys!!