使用XNA 4.0从fbx模型中提取顶点

时间:2013-05-01 18:27:23

标签: c# xna-4.0 extraction vertices fbx

我试图使用C#和XNA 4.0遍历FBX模型的顶点。我认为如果我可以访问顶点,那么我将能够自己访问其他部分,例如面法线,边缘,PolygonVertexIndex等。

我发现Jon Watte的一篇文章讨论了如何使用XNA 3.0做到这一点, Extracting Vertices and Triangles from an XNA Model 但他使用的3.0结构似乎并不存在于4.0中。

特别是,他访问这样的顶点:

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

但在XNA 4中,VertexBuffer似乎不是MeshModel的属性。

有人可以指导我对Model个顶点的基本迭代吗?

谢谢。

@ user2340634感谢您的回复 我的尝试使用了远远低于实际的顶点数 我想我不知道如何使用VertexBuffer。你能否对这段代码发表评论?

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() + ")");
            }
        }
    }
}

你有一个可以迭代到顶点的工作样本吗?

3 个答案:

答案 0 :(得分:2)

“模型”没有“VertexBuffer”。 “ModelMesh”也没有“VertexBuffer”。但是,我发现“ModelMeshPart”确实有“VertexBuffer”。我也是第一次从.fbx中提取数据。我们在项目中包含的任何模型都必须存储在ModelMeshPart中。那不是那么糟糕。 .fbx中的整个网格可以被视为一个部分。

答案 1 :(得分:0)

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);

这是来自主类。这就是我将Model转换为ModelMeshPart的方法。在从.fbx中提取数据之前,我没有创建顶点缓冲区。 for循环(及其内部的代码行)通过将提取的顶点数据写入控制台窗口来为其提供列表。

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

这些是我的ModelExtractor类的字段。它们通过以下方法使用。

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;
    }
}

我提取了“Vector3”类型的数据。 .fbx中的每个顶点都有一个用于posistion的Vector3和另一个用于法线的顶点。只有这样我才能将组件中的位置组件从Vector3s数组移动到VertexPositionColors数组。请注意,for循环将“a”增加2而不是1.这样我就可以跳过法线的Vector3s。

答案 2 :(得分:0)

这是我的解决方案(如果模型有几个部分,你必须循环使用它们)

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);

}