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

Posted

技术标签:

【中文标题】使用 XNA 4.0 从 fbx 模型中提取顶点【英文标题】:Extracting vertices from fbx model using XNA 4.0 【发布时间】:2013-04-25 19:11:03 【问题描述】:

我正在尝试使用 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() + ")");
            
        
    

请问您有可以迭代的工作示例吗?

【问题讨论】:

【参考方案1】:

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

【讨论】:

我在使用 VertexBuffer 方面需要帮助。我拼凑在一起的代码示例没有给我在 fbx 文件中可以看到的顶点。我认为这是我使用 VertexBuffer 的技能不足。你有一个基本的迭代示例可以给我看吗?【参考方案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);

这是来自主类。这就是我将模型转换为 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 中的每个顶点都有一个 Vector3 用于位置,另一个用于法线。只有这样我才能将位置组件从 Vector3s 数组逐个移动到 VertexPositionColors 数组中。请注意,for 循环将“a”增加 2 而不是 1。这样我就可以跳过 Vector3s 以获取法线。

【讨论】:

谢谢,这让我得到了顶点。太糟糕了,其他数据没有相应的缓冲区。 好像你真的需要一个法线向量的缓冲区。缓冲区实际上只是用于绘图。【参考方案3】:

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

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


【讨论】:

以上是关于使用 XNA 4.0 从 fbx 模型中提取顶点的主要内容,如果未能解决你的问题,请参考以下文章

如何使用XNA编程动画FBX模型

如何以编程方式使用 xna 为 fbx 模型设置动画

将纹理 3d 模型和纹理从搅拌机导出到 xna 4.0

XNA 4.0 在 Windows 上加载外部 3D 对象

我可以从哪里获得免费的 XNA 兼容 FBX 型号?

如何使用切线和纹理坐标从3DSMAX导出到FBX