When working with Vertex Buffers in the xna framework is end in a lot more work than it has to be.
What is needed if we just want to create a simple vertex buffer using our own custom vertex structure?
Is all this really necessary? Why do we have to explicitly have to define the elements of the structure a second time and have to deal with byte offsets?
We don’t have to! .Net has the most powerful weapon of all, equipped by default,
Reflection
Yep reflection one of the most underestimated tools in the .net framework. When used correctly, reflection makes working at lot more easy. But we have to be aware of the performance penalty we get by using reflection, but we only create vertex buffers at load time so it doesn’t matter that much.
So if we would use reflection what do we need to do the same as before?
We need the the Vertex structure, of course
.
And one line of code
VertexBufferFactory.CreateVertexBuffer<PositionTextureTexture>
(this.GraphicsDevice, this.vertices, out vertexDeclaration,
out vertexBuffer, out sizeInBytesPerVertex);
Oh that’s magic
No it’s not. But how does it work?
So here’s a small summary of the inner workings of the library. You can download the source and a small sample project at the bottom of the post.
As we have seen at the begging we need a lot of information about the different vertex elements but those information are easy to get when using reflection.
So lets start from the top. The first thing we need is the actual vertex structure. This structure doesn’t change when using this library.
So the first step is to generate the array containing the usage of every vertex element.
Lets take a look at what we need to know to generate one.
new VertexElement(streamNumber, offset, elementFormat,
VertexElementMethod.Default, elementUsage, usageIndex)
streamNumber: it’s possible to use different vertex streams but that’s more complicated stuff so we just pass in 0.
offset: the offset in bytes from the beginning of the stream, this is easy to calculate because reflection tells us what type is used for the field and based on this we can calculate the size.
elementFormat: what format is used, mostly only float, vector2 vector3 or vector4, this is also based on the type used for the field in the vertex structure
vertexElementMethod: is always set to default because it’s rarely used differently
elementUsage: The element usage can be generated based on the name of the field. When the field name is “Position” the intended usage is clear, TexCoord0, Binormal, Tangent, and so on are also clear.
usageIndex: The usage index is by default 0 but when the field name has a number at the end, this number is used as usage Index.
When the generation engine was not able to generate the necessary data it throws an exception and we have to tell it what our indention is.
This is done through the use of attributes. Also a underestimated feature in the .net framework.
[VertexElementAttribute( VertexElementUsage.TextureCoordinate, 0)]
public Vector3 someFactor;
This tells the generation engine our intention.
After we have generated all the elements successful we can just create the vertex declaration.
The vertex buffer can be created as well because we know every element of the vertex structure, and so we know the size as well. We know the vertices so we just have to create it and set the data.
Have a look at the code and see how it works, this library is not complete and doesn’t support everything but it’s written to be extensible so when a feature is missing for you just add it, maybe you would be so kind to send me what you changed so I can make it available for everybody to use.
Download