1

我是 WPF3D 的新手。我想弄清楚 wpf3d 是否能满足我的需要。为了测试,我编写了一个简单的程序,将大约 15,000 个球体渲染到场景中。当我在 Release 模式下运行测试时,场景显示大约需要 30 秒,之后每帧需要大约 3 秒来绘制。难道我做错了什么 ?或者 WPF 渲染 15000 个球体太多。任何帮助是极大的赞赏。我的测试代码发布在下面。

公共 Simple3DSceneInCode() {

        Title = "Simple 3D Scene in Code";

        // Make DockPanel content of window.
        DockPanel dock = new DockPanel();
        Content = dock;

        // Create Viewport3D for 3D scene.
        viewport = new Viewport3D();
        dock.Children.Add(viewport);

        // Create the camera.
        cam = new PerspectiveCamera(new Point3D(-20, -20, -20), new Vector3D(20, 20, 20), new Vector3D(0, 1, 0), 45);
        viewport.Camera = cam;

        ModelVisual3D modvis = new ModelVisual3D();
        modvis.Content = new AmbientLight(Colors.Gray);
        viewport.Children.Add(modvis);

        modvis = new ModelVisual3D();
        modvis.Content = new DirectionalLight(Colors.Silver, new Vector3D(2, -3, -1));
        viewport.Children.Add(modvis);

        Model3DGroup geogroup = new Model3DGroup();
        MeshGeometry3D sphereGeom = GenerateSphere(new Point3D(0.2, 0.2, 0.2), 0.3, 25, 25);
        DiffuseMaterial d1 = new DiffuseMaterial(Brushes.Green);
        DiffuseMaterial d2 = new DiffuseMaterial(Brushes.Red);


        for (int i = 0; i < 25; i++)
        {
            for (int j = 0; j < 25; j++)
            {
                for (int k = 0; k < 25; k++)
                {
                    GeometryModel3D sphereMode = new GeometryModel3D();
                    sphereMode.Geometry = sphereGeom;
                    sphereMode.Material = d1;
                    sphereMode.BackMaterial = d2;
                    sphereMode.Transform = new TranslateTransform3D((double)i / 2.0, (double)j / 2.0, -(double)k / 2.0);
                    geogroup.Children.Add(sphereMode);
                }
            }
        }

        ModelVisual3D mvgeom = new ModelVisual3D();
        mvgeom.Content = geogroup;

        viewport.Children.Add(mvgeom);

    }



    MeshGeometry3D GenerateSphere(Point3D center, double radius,
                                  int slices, int stacks)
    {
        // Create the MeshGeometry3D.
        MeshGeometry3D mesh = new MeshGeometry3D();

        // Fill the Position, Normals, and TextureCoordinates collections.
        for (int stack = 0; stack <= stacks; stack++)
        {
            double phi = Math.PI / 2 - stack * Math.PI / stacks;
            double y = radius * Math.Sin(phi);
            double scale = -radius * Math.Cos(phi);

            for (int slice = 0; slice <= slices; slice++)
            {
                double theta = slice * 2 * Math.PI / slices;
                double x = scale * Math.Sin(theta);
                double z = scale * Math.Cos(theta);

                Vector3D normal = new Vector3D(x, y, z);
                mesh.Normals.Add(normal);
                mesh.Positions.Add(normal + center);
                mesh.TextureCoordinates.Add(
                        new Point((double)slice / slices,
                                  (double)stack / stacks));
            }
        }

        // Fill the TriangleIndices collection.
        for (int stack = 0; stack < stacks; stack++)
            for (int slice = 0; slice < slices; slice++)
            {
                int n = slices + 1; // Keep the line length down.

                if (stack != 0)
                {
                    mesh.TriangleIndices.Add((stack + 0) * n + slice);
                    mesh.TriangleIndices.Add((stack + 1) * n + slice);
                    mesh.TriangleIndices.Add((stack + 0) * n + slice + 1);
                }
                if (stack != stacks - 1)
                {
                    mesh.TriangleIndices.Add((stack + 0) * n + slice + 1);
                    mesh.TriangleIndices.Add((stack + 1) * n + slice);
                    mesh.TriangleIndices.Add((stack + 1) * n + slice + 1);
                }
            }
        return mesh;
    }
4

2 回答 2

1

如果您不打算在创建后更改 GeometryModel3D 对象,那么您可以“冻结”它们。

public void Simple3DSceneInCode()
{
    Title = "Simple 3D Scene in Code";

    // Make DockPanel content of window.
    DockPanel dock = new DockPanel();
    Content = dock;

    // Create Viewport3D for 3D scene.
    var viewport = new Viewport3D();
    dock.Children.Add(viewport);

    // Create the camera.
    var cam = new PerspectiveCamera(new Point3D(-20, -20, -20), new Vector3D(20, 20, 20), new Vector3D(0, 1, 0), 45);
    viewport.Camera = cam;

    ModelVisual3D modvis = new ModelVisual3D();
    modvis.Content = new AmbientLight(Colors.Gray);
    viewport.Children.Add(modvis);

    modvis = new ModelVisual3D();
    modvis.Content = new DirectionalLight(Colors.Silver, new Vector3D(2, -3, -1));
    viewport.Children.Add(modvis);

    Model3DGroup geogroup = new Model3DGroup();
    MeshGeometry3D sphereGeom = GenerateSphere(new Point3D(0.2, 0.2, 0.2), 0.3, 25, 25);
    sphereGeom.Freeze();
    DiffuseMaterial d1 = new DiffuseMaterial(Brushes.Green);
    DiffuseMaterial d2 = new DiffuseMaterial(Brushes.Red);

    for (int i = 0; i < 25; i++)
    {
        for (int j = 0; j < 25; j++)
        {
            for (int k = 0; k < 25; k++)
            {
                GeometryModel3D sphereMode = new GeometryModel3D();
                sphereMode.Geometry = sphereGeom;
                sphereMode.Material = d1;
                sphereMode.BackMaterial = d2;
                sphereMode.Transform = new TranslateTransform3D((double)i / 2.0, (double)j / 2.0, -(double)k / 2.0);
                sphereMode.Freeze();
                geogroup.Children.Add(sphereMode);
            }
        }
    }

    ModelVisual3D mvgeom = new ModelVisual3D();
    mvgeom.Content = geogroup;

    viewport.Children.Add(mvgeom);
}
于 2013-11-02T14:09:48.703 回答
1

以下是我发现有用的两个资源:

在 WPF 中优化 3D 集合

在第 2 层硬件上最大化 WPF 3D 性能

于 2015-03-10T17:58:58.823 回答