WPF-3D图形

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

{

   ModelUIElement3Dmui3d=senderasModelUIElement3D;

   varmodel=mui3d.ModelasGeometryModel3D;

   (model.MaterialasDiffuseMaterial).Brush=Brushes.Orange;

}

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

<Viewport3D MouseLeftButtonDown="Viewport3D_MouseLeftButtonDown">在时间中急性转换处理

privatevoidViewport3D_MouseLeftButtonDown(objectsender, MouseButtonEventArgse)

{

   Viewport3Dviewport3D=senderasViewport3D;

   Pointlocation=e.GetPosition(viewport3D);

   HitTestResulthitTestResult=VisualTreeHelper.HitTest(viewport3D, location);

   if (hitTestResult!=null)

   {

       ...//具体操作

   }

}

3D对象中2D控件渲染

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

<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

<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:HelixViewport3D  Name="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>();

       stringbasePath=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(objectsender, RoutedEventArgse)

       {

           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

           {

               ModelImporterimport=newModelImporter();

 

               foreach (stringmodelNameinmodelsNames)

               {

                   varmaterialGroup=newMaterialGroup();

                   ColormainColor=Colors.White;

                   //EmissiveMaterial emissMat = new EmissiveMaterial(new SolidColorBrush(mainColor));

                   DiffuseMaterialdiffMat=newDiffuseMaterial(newSolidColorBrush(mainColor));

                   //SpecularMaterial specMat = new SpecularMaterial(new SolidColorBrush(mainColor), 2000);

                   //materialGroup.Children.Add(emissMat);

                   materialGroup.Children.Add(diffMat);

                   //materialGroup.Children.Add(specMat);

 

                   varlink=import.Load(basePath+modelName);

                   GeometryModel3Dmodel=link.Children[0] asGeometryModel3D;

                   model.Material=materialGroup;

                   model.BackMaterial=materialGroup;

 

                   group.Children.Add(link);

               }

           }

           catch (Exceptione)

           {

               MessageBox.Show("未知异常:"+e.StackTrace);

           }

           returngroup;

       }

   }

}

HelixToolKit使用文档


相关文章
|
C# Windows
WPF技术之图形系列Polygon控件
WPF Polygon是Windows Presentation Foundation (WPF)框架中的一个标记元素,用于绘制多边形形状。它可以通过设置多个点的坐标来定义多边形的形状,可以绘制任意复杂度的多边形。
893 0
|
C# 前端开发
WPF - 图形设计器(Diagram Designer)
原文:WPF - 图形设计器(Diagram Designer)   OpenExpressApp计划中包括建模工具,计划是采用MetaEdit+模型来作为元模型,使用codeproject的《WPF Diagram Designer》一系列文章来做为设计器实现参考,本篇介绍一下codeprojcet的这四个文章,推荐给对图形设计器感兴趣的人去看看,通过WPF的模板功能和其他功能可以很方便的设计出图形编辑器。
3574 0
|
3月前
|
C# Windows 开发者
当WPF遇见OpenGL:一场关于如何在Windows Presentation Foundation中融入高性能跨平台图形处理技术的精彩碰撞——详解集成步骤与实战代码示例
【8月更文挑战第31天】本文详细介绍了如何在Windows Presentation Foundation (WPF) 中集成OpenGL,以实现高性能的跨平台图形处理。通过具体示例代码,展示了使用SharpGL库在WPF应用中创建并渲染OpenGL图形的过程,包括开发环境搭建、OpenGL渲染窗口创建及控件集成等关键步骤,帮助开发者更好地理解和应用OpenGL技术。
242 0
|
3月前
|
开发者 C# 容器
【独家揭秘】当WPF邂逅DirectX:看这两个技术如何联手打造令人惊艳的高性能图形渲染体验,从环境搭建到代码实践,一步步教你成为图形编程高手
【8月更文挑战第31天】本文通过代码示例详细介绍了如何在WPF应用中集成DirectX以实现高性能图形渲染。首先创建WPF项目并使用SharpDX作为桥梁,然后在XAML中定义承载DirectX内容的容器。接着,通过C#代码初始化DirectX环境,设置渲染逻辑,并在WPF窗口中绘制图形。此方法适用于从简单2D到复杂3D场景的各种图形处理需求,为WPF开发者提供了高性能图形渲染的技术支持和实践指导。
212 0
|
3月前
|
API C# 开发者
WPF图形绘制大师指南:GDI+与Direct2D完美融合,带你玩转高性能图形处理秘籍!
【8月更文挑战第31天】GDI+与Direct2D的结合为WPF图形绘制提供了强大的工具集。通过合理地使用这两种技术,开发者可以创造出性能优异且视觉效果丰富的WPF应用程序。在实际应用中,开发者应根据项目需求和技术背景,权衡利弊,选择最合适的技术方案。
146 0
|
3月前
|
存储 搜索推荐 C#
WPF/C#:让绘制的图形可以被选中并将信息显示在ListBox中
WPF/C#:让绘制的图形可以被选中并将信息显示在ListBox中
43 0
|
3月前
|
前端开发 C# Windows
WPF基础:在Canvas上绘制图形
WPF基础:在Canvas上绘制图形
126 0
|
C# 开发者 Windows
WPF技术之图形系列Path控件
WPF Path是Windows Presentation Foundation (WPF)框架中的一个标记元素,用于绘制复杂的几何路径形状。它可以通过设置一系列的路径命令以及相应的参数来定义形状,可以绘制任意复杂度的路径。
1068 0
|
前端开发 C# Windows
WPF技术之图形系列Rectangle控件
WPF Rectangle是Windows Presentation Foundation (WPF)中的一个图形控件,用于在界面上绘制矩形。它是一个非常常见的UI元素,可用于显示、布局和交互。
1168 0
|
数据可视化 前端开发 C#
WPF技术之图形系列Ellipse控件
WPF Ellipse是Windows Presentation Foundation (WPF)中的一个图形控件,它用于绘制椭圆形状。在WPF中,Ellipse可以用于创建具有椭圆形状的可视化效果,可以设置其位置、大小、填充颜色等属性。
1279 0