2013-11-02 4 views
1

Я новичок в WPF3D. Я пытаюсь выяснить, будет ли wpf3d работать для моей потребности. Чтобы проверить, я написал простую программу, которая отображает около 15 000 сфер. Когда я запускаю свой тест в режиме Release, для сцены появляется около 30 секунд, после чего каждый кадр занимает около 3 секунд для рисования. Я делаю что-то неправильно ? или 15000 сфер слишком много для WPF для рендеринга. Любая помощь приветствуется. Мой тестовый код размещен ниже.WPF 3D Performance - Как я могу сделать это быстрее

общественного 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; 
    } 

ответ

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

Привет colinsminth, это действительно помогло. Начальное время создания составляло от 30 секунд до 4 секунд. Спасибо. Жеребьевка занимает около 3-4 секунд. Есть ли что-нибудь, что я могу сделать, чтобы это сделать? –

Смежные вопросы