سؤال

I am attempting to iterate through the vertices of an FBX model using C# and XNA 4.0. I think that if I can get access to the vertices, then I'll be able to access the other parts such as face normals, edges, PolygonVertexIndex, etc. on my own.

I found an article by Jon Watte discussing how to do this using XNA 3.0, Extracting Vertices and Triangles from an XNA Model but the 3.0 structure that he used doesn't seem to exist in 4.0.

In particular, he accesses the vertices like this:

Vector3[] a = new Vector3[myModelMeshPart.NumVertices];
myModelMesh.VertexBuffer.GetData<Vector3>(myModelMeshPart.StreamOffset + myModelMeshPart.BaseVertex * myModelMeshPart.VertexStride,
          a, 0, myModelMeshPart.NumVertices, myModelMeshPart.VertexStride);

but in XNA 4, VertexBuffer does not seem to be a property of MeshModel.

Can anyone please direct me to a basic iteration of a Model's vertices?

Thank you.

@user2340634 Thank you for your response.
My attempt to use came up w/far less than actual # of verts.
I think I don't know how to use VertexBuffer. Could you please comment on this code?

private void getVerts(Model mdl)
{
    foreach (ModelMesh mm in mdl.Meshes)
    {
        foreach (ModelMeshPart mp in mm.MeshParts)
        {
            VertexBuffer vb = mp.VertexBuffer;
            short[] s = new short[mp.PrimitiveCount * 3];
            IndexBuffer ib = mp.IndexBuffer;
            ib.GetData<short>(mp.StartIndex * 2, s, 0, mp.PrimitiveCount * 3);

            Vector3[] v = new Vector3[4];
            VertexPositionNormalTexture[] vert = new VertexPositionNormalTexture[4];
            mp.VertexBuffer.GetData<VertexPositionNormalTexture>(vert, 0, mp.NumVertices);
            for (int i = 0; i < v.Length; i++)
            {
                v[i] = vert[i].Position;
                trace("(" + v[i].X.ToString() + ", " + v[i].Y.ToString() + ", " + v[i].Z.ToString() + ")");
            }
        }
    }
}

Do you have a working sample that iterates thru verts, please?

هل كانت مفيدة؟

المحلول 2

modModel = Content.Load<Model>("Cube1");
foreach (ModelMesh modmModel in modModel.Meshes)
{
    foreach (ModelMeshPart mmpModel in modmModel.MeshParts)
    {
        modelExtractor = new ModelExtractor(mmpModel, new Vector3[mmpModel.NumVertices * 2], new VertexPositionColor[mmpModel.NumVertices]);
        modelExtractor.ExtractVertices();
    }
}
for (int a = 0; a < modelExtractor.ArrVectors.Length; a++)
{
    Console.WriteLine(modelExtractor.ArrVectors[a]);
}
vertexBuffer = new VertexBuffer(GraphicsDevice, typeof(VertexPositionColor), modelExtractor.VpcVertices.Length, BufferUsage.None);
vertexBuffer.SetData(modelExtractor.VpcVertices);

This is from the main class. This is how I converted the Model into a ModelMeshPart. I didn't make a vertex buffer until after I extracted the data from the .fbx. The for loop (and the line of code inside of it) gives you a list of the extracted vertex data by writing it to the console window.

private ModelMeshPart mmpModel;
private Vector3[] arrVectors;
private VertexPositionColor[] vpcVertices;

These are the fields of my ModelExtractor class. They are used by the following method.

public void ExtractVertices()
{
    this.mmpModel.VertexBuffer.GetData<Vector3>(this.arrVectors);
    for (int a = 0; a < vpcVertices.Length; a += 2)
    {
        this.vpcVertices[a].Position.X = arrVectors[a].X;
        this.vpcVertices[a].Position.Y = arrVectors[a].Y;
        this.vpcVertices[a].Position.Z = arrVectors[a].Z;
    }
}

I extracted data of type "Vector3". Every vertex in the .fbx has a Vector3 for posistion and another for the normal. Only then do I move the position component by component from the array of Vector3s to an array of VertexPositionColors. Notice that the for loop increments "a" by 2 instead of 1. This is so that I can skip over the Vector3s for the normals.

نصائح أخرى

"Model" doesn't have "VertexBuffer". "ModelMesh" doesn't have "VertexBuffer" either. But, I found out that "ModelMeshPart" does indeed have "VertexBuffer". I'm doing data extraction from a .fbx for the first time as well. Any model we include in a project will have to be stored in a ModelMeshPart. That's not so bad. The whole mesh in the .fbx can be considered one part.

This is my solution (if the model has several parts you have to loop through them of course)

public static void ModelData(Model model)
{
    ModelMeshPart part = model.Meshes[0].MeshParts[0];

    VertexPositionNormalTexture[] vertices = new VertexPositionNormalTexture[part.VertexBuffer.VertexCount];
    part.VertexBuffer.GetData<VertexPositionNormalTexture>(vertices);

    ushort[] drawOrder = new ushort[part.IndexBuffer.IndexCount];
    part.IndexBuffer.GetData<ushort>(drawOrder);

}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top