1

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

我发现 Jon Watte 的一篇文章讨论了如何使用 XNA 3.0 执行此操作, 从 XNA 模型中提取顶点和三角形, 但他使用的 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.

谁能指导我了解 aModel顶点的基本迭代?

谢谢你。

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

请问你有一个可以迭代的工作样本吗?

4

3 回答 3

2

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

于 2013-05-01T19:34:41.473 回答
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);

这是来自主课。这就是我将模型转换为 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 以获取法线。

于 2013-05-03T06:00:00.770 回答
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);

}
于 2014-06-13T15:51:52.553 回答