WPF-3D图形

WPF-3D图形

WPF的3D功能可以在不编写任何c#代码的情况下进行绘制,只需要使用xaml即可完成3D图形的渲染。本文主要讲述了WPF-3D中的关键概念, 以及常用到的命中测试、2d控件如何在3D对象中进行渲染,除此之外,还演示了如何导入外部3D模型。

关键概念

视口

视口指的是图像要展示在哪里,可以理解为展示图形的舞台。在WPF中视口使用Viewport3D标签表示。

相机

如果把视口比作舞台,那相机就可以理解为观众的眼睛,不同的眼睛位置会看到不同的角度。



    

         
            
                
                    
                        
                    
                
            
        


光源

没有光源也就看不到3D对象



    
        

            

        
    

材质

3D几何对象只是将轮廓定义出来,表面是没有定义的,所以需要使用材质来展现出不同的物体表面。也可以理解为3D几何对象只是勾勒出物体的轮廓,而材质则是上颜色。


    
        

            

                

            
            
                
            
        
    

3D对象

3D对象则是具体的对象,在WPF中视口使用标签表示。在WPF中,图形是以三角面片作为最基本的展示单元,因为三角形是最稳定的即三个点可以确定出唯一的一个平面,任何复杂的图形都是由多个三角面片组成的。在给TriangleIndices属性赋值时,一定注意三个点的顺序。

命中测试(鼠标交互)

想要使用鼠标点击得到某个图形,可以在具体的某个3D对象中,增加MouseLeftButtonDown事件

事件中可以进行改变颜色等操作

private void ModelUIElement3D_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    ModelUIElement3D mui3d = sender as ModelUIElement3D;
    var model = mui3d.Model as GeometryModel3D;
    (model.Material as DiffuseMaterial).Brush = Brushes.Orange;
}

如果有很多3D对象,在每个具体的对象上面增加事件会很麻烦,也可以直接在Viewport3D中增加事件

在时间中急性转换处理

private void Viewport3D_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    Viewport3D viewport3D=sender as Viewport3D; 
    Point location=e.GetPosition(viewport3D);
    HitTestResult hitTestResult=VisualTreeHelper.HitTest(viewport3D, location);
    if (hitTestResult != null)
    {
        ...//具体操作
    }
}

3D对象中2D控件渲染

如果要在3D对象中增加控件,可以使用Viewport2DVisual3D标签,实现如下图所示的效果。

WPF-3D图形插图


 
    
        

    

    
        
    
    
    
        
            
            
        
    
    
 

外部导入3D模型

在wpf中绘制3D模型还是非常麻烦的,在实际工作中用的比较多的是从外部导入已有的3d模型。推荐一个比较好的第三方库HelixToolKit

WPF-3D图形插图1


    
        

            
                
            

            
                
                    
                    
                
            
            

            

            

        
    

namespace WpfApp2
{
    public partial class MainWindow : Window
    {
        List modelPaths = new List();
        string basePath = AppDomain.CurrentDomain.BaseDirectory + "\ModelFiles\";
        public MainWindow()
        {
            InitializeComponent();
            modelPaths.Add("IRB4600_20kg-250_LINK1_CAD_rev04.stl");
            modelPaths.Add("IRB4600_20kg-250_LINK2_CAD_rev04.stl");
            modelPaths.Add("IRB4600_20kg-250_LINK3_CAD_rev005.stl");
            modelPaths.Add("IRB4600_20kg-250_LINK4_CAD_rev04.stl");
            modelPaths.Add("IRB4600_20kg-250_LINK5_CAD_rev04.stl");
            modelPaths.Add("IRB4600_20kg-250_LINK6_CAD_rev04.stl");
            modelPaths.Add("IRB4600_20kg-250_LINK3_CAD_rev04.stl");
            modelPaths.Add("IRB4600_20kg-250_CABLES_LINK1_rev03.stl");
            modelPaths.Add("IRB4600_20kg-250_CABLES_LINK2_rev03.stl");
            modelPaths.Add("IRB4600_20kg-250_CABLES_LINK3_rev03.stl");
            modelPaths.Add("IRB4600_20kg-250_BASE_CAD_rev04.stl");

            this.Loaded += MainWindow_Loaded;

            viewPort3d.RotateGesture = new MouseGesture(MouseAction.RightClick);
            viewPort3d.PanGesture = new MouseGesture(MouseAction.LeftClick);
        }
        private void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            viewPort3d.Camera.LookDirection = new Vector3D(2038, -5200, -2930);
            viewPort3d.Camera.UpDirection = new Vector3D(-0.145, 0.372, 0.917);
            viewPort3d.Camera.Position = new Point3D(-1571, 4801, 3774);

            this.model.Content = InitializeModels(this.modelPaths);
        }

        private Model3DGroup InitializeModels(List modelsNames)
        {
            Model3DGroup group = new Model3DGroup();
            try
            {
                ModelImporter import = new ModelImporter();

                foreach (string modelName in modelsNames)
                {
                    var materialGroup = new MaterialGroup();
                    Color mainColor = Colors.White;
                    //EmissiveMaterial emissMat = new EmissiveMaterial(new SolidColorBrush(mainColor));
                    DiffuseMaterial diffMat = new DiffuseMaterial(new SolidColorBrush(mainColor));
                    //SpecularMaterial specMat = new SpecularMaterial(new SolidColorBrush(mainColor), 2000);
                    //materialGroup.Children.Add(emissMat);
                    materialGroup.Children.Add(diffMat);
                    //materialGroup.Children.Add(specMat);

                    var link = import.Load(basePath + modelName);
                    GeometryModel3D model = link.Children[0] as GeometryModel3D;
                    model.Material = materialGroup;
                    model.BackMaterial = materialGroup;

                    group.Children.Add(link);
                }
            }
            catch (Exception e)
            {
                MessageBox.Show("未知异常:" + e.StackTrace);
            }
            return group;
        }
    }
}

HelixToolKit使用文档

文章来源于互联网:WPF-3D图形

THE END
分享
二维码