0


WPF-3D图形

WPF-3D图形

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

关键概念

视口

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

Viewport3D

标签表示。

相机

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

<Viewport3D><!--相机--><Viewport3D.Camera><!--透视相机--><PerspectiveCameraPosition="8,5,10"LookDirection="-7,-2,-10"FarPlaneDistance="40"NearPlaneDistance="10"FieldOfView="60"><PerspectiveCamera.Transform><RotateTransform3DCenterX="1.5"CenterY="1"CenterZ="0.5"><RotateTransform3D.Rotation><AxisAngleRotation3DAngle="45"Axis="0,1,0"/></RotateTransform3D.Rotation></RotateTransform3D></PerspectiveCamera.Transform></PerspectiveCamera><!--正交相机,用法类似--><!--<OrthographicCamera/>--></Viewport3D.Camera>

光源

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

<!--光线--><ModelVisual3D><ModelVisual3D.Content><Model3DGroup><!--散射光线--><AmbientLightColor="#FFF"/><!--平行光--><!--<DirectionalLight Color="#FFF" Direction="0,-1,0"/>--><!--点光源--><!--<PointLight Position="0,0,0"/>--><!--锥形辐射光:手电筒--><!--<SpotLight Position="0,0,0" Direction="0,0,-3"/>--></Model3DGroup></ModelVisual3D.Content></ModelVisual3D>

材质

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

<ModelUIElement3D><ModelUIElement3D.Model><GeometryModel3D><!--材质--><GeometryModel3D.Material><!--散射材质--><DiffuseMaterialBrush="Blue"/><!--镜面材质--><!--<SpecularMaterial SpecularPower="1" Brush="Blue"/>--><!--自发光材质--><!--<EmissiveMaterial Color="Green" />--></GeometryModel3D.Material><GeometryModel3D.Geometry><MeshGeometry3DPositions="0,0,1 0,2,1 3,2,1 3,0,1
                                           0,0,0 0,2,0 3,2,0 3,0,0"TriangleIndices="2,3,7 7,6,2 1,5,4 0,1,4"/></GeometryModel3D.Geometry></GeometryModel3D></ModelUIElement3D.Model></ModelUIElement3D>

3D对象

3D对象则是具体的对象,在WPF中视口使用

<ModelUIElement3D>

标签表示。在WPF中,图形是以三角面片作为最基本的展示单元,因为三角形是最稳定的即三个点可以确定出唯一的一个平面,任何复杂的图形都是由多个三角面片组成的。在给

TriangleIndices

属性赋值时,一定注意三个点的顺序。

命中测试(鼠标交互)

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

MouseLeftButtonDown

事件

<ModelUIElement3D MouseLeftButtonDown="ModelUIElement3D_MouseLeftButtonDown">

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

privatevoidModelUIElement3D_MouseLeftButtonDown(object sender,MouseButtonEventArgs e){ModelUIElement3D mui3d = sender asModelUIElement3D;var model = mui3d.Model asGeometryModel3D;(model.Material asDiffuseMaterial).Brush = Brushes.Orange;}

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

Viewport3D

中增加事件

<Viewport3D MouseLeftButtonDown="Viewport3D_MouseLeftButtonDown">

在时间中急性转换处理

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

3D对象中2D控件渲染

如果要在3D对象中增加控件,可以使用

Viewport2DVisual3D

标签,实现如下图所示的效果。

image-20230126121543225

<Viewport3D><Viewport2DVisual3D><Viewport2DVisual3D.Geometry><MeshGeometry3DPositions="0,0,1 0,2,1 3,2,1 3,0,1
                       0,0,0 0,2,0 3,2,0 3,0,0"TriangleIndices="0,2,1 0,3,2 6,4,5 6,7,4"TextureCoordinates="0,1 0,0 1,0 1,1"/><!--TextureCoordinates:表示的二维平面坐标,原点:左上角--></Viewport2DVisual3D.Geometry><Viewport2DVisual3D.Material><DiffuseMaterialViewport2DVisual3D.IsVisualHostMaterial="True"Brush="White"/></Viewport2DVisual3D.Material><Viewport2DVisual3D.Visual><BorderBorderThickness="1"BorderBrush="Yellow"><StackPanel><TextBlockText="Hello World"Foreground="Green"/><ButtonContent="Button"Click="Button_Click"/></StackPanel></Border></Viewport2DVisual3D.Visual></Viewport2DVisual3D><Viewport3D>

外部导入3D模型

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

HelixToolKit

1

<Windowx:Class="WpfApp2.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:local="clr-namespace:WpfApp2"xmlns:helix="http://helix-toolkit.org/wpf"mc:Ignorable="d"Title="MainWindow"Height="450"Width="800"><Grid><helix:HelixViewport3DName="viewPort3d"ShowViewCube="True"ViewCubeBackText="后"ViewCubeFrontText="前"ViewCubeHeight="100"ViewCubeWidth="100"ViewCubeVerticalPosition="Bottom"ViewCubeHorizontalPosition="Right"ShowCoordinateSystem="True"CoordinateSystemLabelForeground="Red"CoordinateSystemHorizontalPosition="Left"CoordinateSystemVerticalPosition="Bottom"ShowFrameRate="True"IsViewCubeEdgeClicksEnabled="False"><helix:HelixViewport3D.Camera><PerspectiveCameraFieldOfView="45"LookDirection="0,0,-414.387754871885"FarPlaneDistance="30000"NearPlaneDistance="0.1"Position="9.9475983006414E-14,91.037123633789,414.387754871885"UpDirection="0,1,0"/></helix:HelixViewport3D.Camera><helix:HelixViewport3D.Background><LinearGradientBrushEndPoint="0.5,1"StartPoint="0.5,0"><GradientStopColor="#444"Offset="0"/><GradientStopColor="#EEE"Offset="1"/></LinearGradientBrush></helix:HelixViewport3D.Background><helix:GridLinesVisual3DWidth="16000"Length="16000"Thickness="2"MinorDistance="500"MajorDistance="500"Fill="Gray"/><!--很重要,没有灯光场景是黑的--><helix:DefaultLights/><ModelVisual3Dx:Name="model"></ModelVisual3D></helix:HelixViewport3D></Grid></Window>
namespaceWpfApp2{publicpartialclassMainWindow:Window{List<string> modelPaths =newList<string>();string basePath = AppDomain.CurrentDomain.BaseDirectory +"\\ModelFiles\\";publicMainWindow(){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 =newMouseGesture(MouseAction.RightClick);
            viewPort3d.PanGesture =newMouseGesture(MouseAction.LeftClick);}privatevoidMainWindow_Loaded(object sender,RoutedEventArgs e){
            viewPort3d.Camera.LookDirection =newVector3D(2038,-5200,-2930);
            viewPort3d.Camera.UpDirection =newVector3D(-0.145,0.372,0.917);
            viewPort3d.Camera.Position =newPoint3D(-1571,4801,3774);this.model.Content =InitializeModels(this.modelPaths);}privateModel3DGroupInitializeModels(List<string> modelsNames){Model3DGroupgroup=newModel3DGroup();try{ModelImporter import =newModelImporter();foreach(string modelName in modelsNames){var materialGroup =newMaterialGroup();Color mainColor = Colors.White;//EmissiveMaterial emissMat = new EmissiveMaterial(new SolidColorBrush(mainColor));DiffuseMaterial diffMat =newDiffuseMaterial(newSolidColorBrush(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]asGeometryModel3D;
                    model.Material = materialGroup;
                    model.BackMaterial = materialGroup;group.Children.Add(link);}}catch(Exception e){
                MessageBox.Show("未知异常:"+ e.StackTrace);}returngroup;}}}

HelixToolKit使用文档

标签: wpf 3d c#

本文转载自: https://blog.csdn.net/weixin_44064908/article/details/128764982
版权归原作者 步、步、为营 所有, 如有侵权,请联系我们删除。

“WPF-3D图形”的评论:

还没有评论