private static void ExtractModelMeshPartData(ModelMeshPart meshPart, ref Matrix transform, List<Vector3> vertices, List<Triangle> indices)
{
// Before we add any more where are we starting from
int offset = vertices.Count;
// Vertices
// Read the format of the vertex buffer
VertexDeclaration declaration = meshPart.VertexBuffer.VertexDeclaration;
VertexElement[] vertexElements = declaration.GetVertexElements();
// Find the element that holds the position
VertexElement vertexPosition = new VertexElement();
foreach (VertexElement vert in vertexElements)
{
if (vert.VertexElementUsage == VertexElementUsage.Position &&
vert.VertexElementFormat == VertexElementFormat.Vector3)
{
vertexPosition = vert;
// There should only be one
break;
}
}
// Check the position element found is valid
if (vertexPosition == null ||
vertexPosition.VertexElementUsage != VertexElementUsage.Position ||
vertexPosition.VertexElementFormat != VertexElementFormat.Vector3)
{
throw new Exception("Model uses unsupported vertex format!");
}
// This where we store the vertices until transformed
Vector3[] allVertex = new Vector3[meshPart.NumVertices];
// Read the vertices from the buffer in to the array
meshPart.VertexBuffer.GetData<Vector3>(
meshPart.VertexOffset * declaration.VertexStride + vertexPosition.Offset,
allVertex,
0,
meshPart.NumVertices,
declaration.VertexStride);
// Transform them based on the relative bone location and the world if provided
for (int i = 0; i != allVertex.Length; ++i)
{
Vector3.Transform(ref allVertex[i], ref transform, out allVertex[i]);
}
// Store the transformed vertices with those from all the other meshes in this model
vertices.AddRange(allVertex);
// Indices
// Find out which vertices make up which triangles
if (meshPart.IndexBuffer.IndexElementSize != IndexElementSize.SixteenBits)
{
// This could probably be handled by using int in place of short but is unnecessary
throw new Exception("Model uses 32-bit indices, which are not supported.");
}
// Each primitive is a triangle
short[] indexElements = new short[meshPart.PrimitiveCount * 3];
meshPart.IndexBuffer.GetData<short>(
meshPart.StartIndex * 2,
indexElements,
0,
meshPart.PrimitiveCount * 3);
// Each TriangleVertexIndices holds the three indexes to each vertex that makes up a triangle
Triangle[] tvi = new Triangle[meshPart.PrimitiveCount];
for (int i = 0; i != tvi.Length; ++i)
{
// The offset is because we are storing them all in the one array and the
// vertices were added to the end of the array.
tvi[i].a = indexElements[i * 3 + 0] + offset;
tvi[i].b = indexElements[i * 3 + 1] + offset;
tvi[i].c = indexElements[i * 3 + 2] + offset;
}
// Store our triangles
indices.AddRange(tvi);
}