【问题标题】:wpf 3d, multiple instances of a Model3DGroup, trying to optimize performancewpf 3d,Model3DGroup的多个实例,试图优化性能
【发布时间】:2013-03-07 14:07:42
【问题描述】:

我的程序显示了一个静态场景,其中包含 3d 模型(例如树)在不同位置的多个实例。此模型可能很“重”,介于 50000 到 100000 个三角形之间,并且性能会随着实例数量的增加而迅速下降(超过 10 个实例时性能无法接受)。

我的第一个没有优化的代码如下所示:

   public partial class Vue3D : Window
   {
    public ModelVisual3D modelVisual = new ModelVisual3D();
    public Model3DGroup model3DGroup = new Model3DGroup();

    public Vue3D()
      {
        ...
        modelVisual.Content = model3DGroup;
        view1.Children.Add(modelVisual); // view1 = viewport3D
        ...
        BuildScene();
      }

    void BuildScene()
      {
        Model3DGroup model = GetModel("tree");
        foreach (Point3D pnt in <point collection>)
        {
          Model3DGroup modelClone = model.Clone();
          Transform3DGroup tg = new Transform3DGroup();
          tg.Children.Add(new TranslateTransform3D(pnt.X, pnt.Y, pnt.Z>)); 
          modelClone.Transform = tg;
          model3DGroup.Children.Add(modelClone);
        }
      }
  }

对于每个实例,我克隆完整的模型,并在转换后将克隆添加到视口。 假设树模型包含 2 个 GeometryModel3D : {mesh1(20000 个三角形),texture1} 和 {mesh2(40000 个三角形),texture2}。 如果我显示 10 棵树,我将添加 20 个 GeometryModel3D。

由于所有这些实例共享相同的 2 个纹理,我认为我可以通过仅创建 2 个 GeometryModel3D 来加快速度:一个包含与纹理 1 关联的所有三角形,一个包含与纹理 2 关联的所有三角形。这就是我在这段代码中尝试过的:

void BuildScene()
  {
    List<Transform3DGroup>> listTg = new List<Transform3DGroup>();
    foreach (Point3D pnt in <point collection>)
    {
      Transform3DGroup tg = new Transform3DGroup();
      tg.Children.Add(new TranslateTransform3D(pnt.X, pnt.Y, pnt.Z>)); 
      listTg.Add(tg);
    }
    Model3DGroup model = GetModel("tree");
    foreach (GeometryModel3D gmodel in model.Children)
    {
      MeshGeometry3D mesh = gmodel.Geometry as MeshGeometry3D;
      GeometryModel3D newgmodel = new GeometryModel3D();
      newgmodel.Material = gmodel.Material;
      newgmodel.BackMaterial = gmodel.BackMaterial;
      MeshGeometry3D newmesh = new MeshGeometry3D();
      newgmodel.Geometry = newmesh;
      foreach (Transform3DGroup tg in listTg)
      {
        foreach (int indice in mesh.TriangleIndices)
          newmesh.TriangleIndices.Add(indice + newmesh.Positions.Count);
        foreach (Point3D p3 in mesh.Positions)
          newmesh.Positions.Add(tg.Transform(p3));
        if (mesh.TextureCoordinates != null)
        {
          foreach (System.Windows.Point p in mesh.TextureCoordinates)
            newmesh.TextureCoordinates.Add(p);
        }
      }
      newmesh.TriangleIndices.Freeze();
      newmesh.TextureCoordinates.Freeze();
      newmesh.Positions.Freeze();
      newgmodel.Material.Freeze();
      newgmodel.BackMaterial.Freeze();
      newgmodel.Freeze();
      model3DGroup.Children.Add(newgmodel);
    }
  }

而且性能并没有更好,实际上更差......我在这里错过了什么?看来我的假设是错误的,即最小化 GeometryModel3D 的数量是有益的。我在某处读过,在 wpf 3d 中,三角形的数量对性能没有太大影响,但纹理的数量更为关键。这里我有大量的三角形,但只有 2 个纹理,只有一个 ModelVisual3D,而且全部都被冻结了……有什么建议吗?

【问题讨论】:

    标签: wpf performance 3d


    【解决方案1】:

    我很幸运地分离了网格,应用了任何变换,然后重新附加了网格。我从这里得到了这个想法:http://msdn.microsoft.com/en-us/library/bb613553.aspx

    【讨论】:

    • 如果不是转换问题;我在视口中添加模型的函数 BuildScene() 仅被调用一次,以创建静态场景;静态,我的意思是一旦显示视口,它的内容就不会改变,只有相机移动。我知道您的链接指向的文章,实际上我在那里读到“仅当它们需要不同的材质或变换时才创建不同的模型。否则,尝试将许多具有相同材质和变换的 GeometryModel3D 实例合并为一些更大的 GeometryModel3D 和 MeshGeometry3D实例。”
    • 嗯,这取决于到底有多大,我指的是屏幕上的大小、对象的大小以及在任何给定时间点您可以看到的对象的多少。我的意思是,如果您的对象被 viewport3d 动态裁剪,那么您将遇到动画缓慢或闪烁的问题。这包括相机四处移动的动画。老实说,我认为您最好的选择可能是至少托管 DX 迁移到 Direct X。
    猜你喜欢
    • 2011-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多