WPF中的3D特性和常见的几个类

简介: 原文:WPF中的3D特性和常见的几个类 WPF 3D 常用的几个类及其关系 1.  Visual 类      所有二维可视化元素的基类,为 WPF 中的呈现提供支持,其中包括命中测试、坐标转换和边界框计算。
原文: WPF中的3D特性和常见的几个类

WPF 3D 常用的几个类及其关系

1.  Visual 类

     所有二维可视化元素的基类,为 WPF 中的呈现提供支持,其中包括命中测试、坐标转换和边界框计算。

     Visual 对象是一个核心 WPF 对象,其主要作用是提供呈现支持。用户界面控件(例如 Button 和 TextBox)派生自 Visual 类,并使用 Visual 定义的属性来保存它们所呈现的数据。Visual 对象可对下列功能提供支持:

输出显示:为可视对象呈现持久的序列化绘图内容。
转换:对可视对象执行转换。
剪辑:为可视对象提供剪辑区域支持。
命中测试:确定指定的坐标(点)或几何图形是否包含在可视对象的边界内。
边界框计算:确定可视对象的边框。
 

2. Visual3D 类

      所有三维可视化元素的基类,提供可视三维对象通用的服务和属性,其中包括命中测试、坐标转换和边界框计算。

 

3.  Viewport3D类

      为三维可视内容提供呈现图面。


      此控件显示三维内容,同时提供与二维布局(如剪辑、高度和宽度及鼠标事件)一致的属性。

当此控件作为布局元素(如 Canvas)的内容包含时,可通过设置其 Height 和 Width 属性(继承自 FrameworkElement)来指定 Viewport3D 的大小。

      Viewport3D 可提供三维场景级别的命中测试。 调用 HitTest 方法可返回有关命中可视对象、模型、网格和交点的详细命中结果信息。


 

4. Viewport3DVisual 类

在指定的二维视区边界内呈现 Visual3D 子对象。

Viewport3DVisual 是具有三维子对象的二维 Visual 对象。Viewport3DVisual 为 Viewport3D 元素提供了必需的基础结构。 大多数用户都需要使用 Viewport3D 元素。

Viewport3DVisual 在二维 Visual 和 Visual3D 对象之间起到桥梁作用。Visual3D 类是所有三维可视化元素的基类。Viewport3DVisual 要求您定义一个 Camera 值和一个 Viewport 值。可以借助照相机来查看场景。投影映射到二维图面的区域称作视区。


 继承层次结构
System..::.Object
  System.Windows.Threading..::.DispatcherObject
    System.Windows..::.DependencyObject
      System.Windows.Media..::.Visual
        System.Windows.Media.Media3D..::.Viewport3DVisual

5. Model3D 类
      为三维模型提供功能的抽象类。此类对象包括 GeometryModel3D 和 Light。
     
 继承层次结构
System..::.Object
  System.Windows.Threading..::.DispatcherObject
    System.Windows..::.DependencyObject
      System.Windows..::.Freezable
        System.Windows.Media.Animation..::.Animatable
          System.Windows.Media.Media3D..::.Model3D
            System.Windows.Media.Media3D..::.GeometryModel3D
            System.Windows.Media.Media3D..::.Light
            System.Windows.Media.Media3D..::.Model3DGroup


6. ModelVisual3D 类
包含三维模型的 Visual。提供所有可视对象通用的服务和属性,其中包括命中测试、坐标转换和边界框计算。
 继承层次结构
System..::.Object
  System.Windows.Threading..::.DispatcherObject
    System.Windows..::.DependencyObject
      System.Windows.Media.Media3D..::.Visual3D
        System.Windows.Media.Media3D..::.ModelVisual3D


7. GeometryModel3D 类
      创建由一个 MeshGeometry3D 和一个 Material 构成的三维模型。
 继承层次结构
System..::.Object
  System.Windows.Threading..::.DispatcherObject
    System.Windows..::.DependencyObject
      System.Windows..::.Freezable
        System.Windows.Media.Animation..::.Animatable
          System.Windows.Media.Media3D..::.Model3D
            System.Windows.Media.Media3D..::.GeometryModel3D


8.  MeshGeometry3D 类
 
用于生成三维形状的三角形基元。

 

 继承层次结构
System..::.Object
  System.Windows.Threading..::.DispatcherObject
    System.Windows..::.DependencyObject
      System.Windows.Media..::.Visual
        System.Windows..::.UIElement
          System.Windows..::.FrameworkElement
            System.Windows.Controls..::.Viewport3D


 

 继承层次结构
System..::.Object
  System.Windows.Threading..::.DispatcherObject
    System.Windows..::.DependencyObject
      System.Windows.Media..::.Visual
        System.Windows..::.UIElement
          System.Windows..::.FrameworkElement
            System.Windows.Controls..::.Viewport3D

 

 

 

WPF中的3D特性,其中包含了开始使用该特性的信息。

提示:

WPF中的3D特性在System.Windows.Media.Media3D命名空间中。

为了理解WPF中的3D特性,一定要知道坐标系统之间的区别。图35-22显示了WPF 3D中的坐标系统。原点位于中心。X轴的正值在右边,负值在左边。Y轴是垂直的,正值在上边,负值在下边。Z轴在指向观察者的方向上定义了正值。

 
图  35-22

表35-9描述了最重要的类及其功能。

表  35-9

   

ViewPort3D

ViewPort3D定义了3D对象的渲染表面。这个元素包含3D绘图的所有可见元素

ModelVisual3D

ModelVisual3D包含在ViewPort3D中,它包含了所有可见元素。可以给完整的模型指定变换

GeometryModel3D

GeometryModel3D包含在ModelVisual3D中,它包含网格和材质

Geometry3D

Geometry3D是一个抽象基类,定义了几何形状。派生于Geometry3D的类是MeshGeometry3D。使用MeshGeometry3D可以定义三角形的位置,建立3D模型

Material

Material是一个抽象基类,定义了MeshGeometry3D指定的三角形的前边和后边。Material包含在GeometryModel3D中。.NET 3.5定义了几个材质类,例如DiffuseMaterialEmissiveMaterialSpecularMaterial。根据材质的类型,以不同的方式计算灯光。EmissiveMaterial利用灯光的计算,使材质发出等于笔刷颜色的光。DiffuseMaterial使用漫射光,SpecularMaterial定义了镜面发光模型。使用MaterialGroup类可以创建由其他材质合并而成的材质

Light

Light是灯光的抽象基类。其派生类有AmbientLightDirectionalLightPointLightSpotLightAmbientLight是不自然的光,会近似照亮整个场景。使用这种光看不到边界。DirectionalLight定义了定向光。太阳光就是一种定向光,光线来自一边,此时可以看到边界和阴影。PointLight是一种位于指定位置的光,会照亮所有的方向。SpotLight照亮指定的方向。这个光定义了一个圆锥,会得到一个发出光亮的区域

Camera

Camera是摄像机的抽象基类,用于把3D场景映射为2D显示。其派生类是PerspectiveCameraOrthographicCameraMatrixCamera。在PerspectiveCamera中,3D对象离得越远就越小,这不同于OrthographicCamera,在Orthographic Camera中,摄像机的距离对对象的大小没有影响。在MatrixCamera中,可以在矩阵中定义视图和变换

Transform3D

Transform3D3D变换的抽象基类。其派生类是RotateTransform3DScaleTransform3DTranslateTransform3DMatrixTransform3DTransform3D GroupTranslateTransform3D允许在xyz向上变换对象,ScaleTransform3D可以重置对象的大小。RotateTransform3D可以在xyz向上把对象旋转指定的角度。Transform3DGroup可以合并其他变换效果

三角形

本节从一个简单的3D示例开始。3D模型由三角形组成,所以最简单的模型是一个三角形。三角形用MeshGeometry3D的Positions属性定义。3个顶点都使用相同的z坐标-4,x、y坐标分别为-1-1、1-1和01。属性TriangleIndices指定了逆时针的位置顺序。使用这个属性可以确定三角形的哪一边是可见的。三角形的一边显示了用GeometryModel3D类的Meterial属性定义的颜色,其他边显示了BackMeterial属性定义的颜色。

用于显示场景的摄像机位于坐标0,0,0,其方向指向0,0,-8。把摄像机的位置改变到左边,矩形就移动到右边,反之亦然。改变摄像机的y位置,矩形就会变大或变小。

这个场景中使用的光线是AmbientLight,它用白色光照亮了整个场景。图35-23显示了三角形的效果。

< Window Width="300" >
< Grid >
< Viewport3D >
< Viewport3D.Camera >
< PerspectiveCamera Position="0 0 0" LookDirection="0 0 -8" / >
< /Viewport3D.Camera >
< ModelVisual3D >
< ModelVisual3D.Content >
< AmbientLight Color="White" / >
< /ModelVisual3D.Content >
< /ModelVisual3D >
< ModelVisual3D >
< ModelVisual3D.Content >
< GeometryModel3D >
< GeometryModel3D.Geometry >
< MeshGeometry3D
Positions="-1 -1 -4, 1 -1 -4, 0 1 -4"
TriangleIndices="0, 1, 2" / >
< /GeometryModel3D.Geometry >
< GeometryModel3D.Material >
< MaterialGroup >
< DiffuseMaterial >
< DiffuseMaterial.Brush >
< SolidColorBrush Color="Red" / >
< /DiffuseMaterial.Brush >
< /DiffuseMaterial >
< /MaterialGroup >
< /GeometryModel3D.Material >
< /GeometryModel3D >
< /ModelVisual3D.Content >
< /ModelVisual3D >
< /Viewport3D >
< /Grid >
< /Window >

 

  
图  35-23

1. 改变光线

图35-23仅显示了一个简单的三角形,它与2D的效果相同。但是,下面将继续添加3D特性。例如,用SpotLight元素把环境光改为聚光灯,就可以看到三角形的另一个外观,使用聚光灯可以定义光源的位置和光线的照射方向。给光源的位置指定-1 1 2,光就位于三角形的左边顶点处,其y坐标是三角形的高度。之后,光线向下向左照射。图35-24显示了三角形的新外观。

< ModelVisual3D >
< ModelVisual3D.Content >
< SpotLight Position="-1 1 -2" Color="White"
Direction="-1.5, -1, -5" / >
< /ModelVisual3D.Content >
< /ModelVisual3D >

 

 
图  35-24

2. 添加纹理

除了给三角形的材质使用纯色笔刷之外,还可以使用其他笔刷,例如LinearGradient- Brush,如下面的XAML代码所示。用DiffuseMeterial定义的LinearGradientBrush元素指定了黄色、橙色、红色、蓝色和紫罗兰色的渐变点。要把使用这种笔刷的对象的2D表面映射到3D几何体上,必须设置TextCoordinates属性。TextCoordinates定义了2D点的集合,它可以映射到3D位置上。图35-25显示了示例应用程序中笔刷的2D坐标。三角形中的第一个位置-1-1映射到笔刷坐标0 1上,右下角的位置1 -1映射到笔刷的1 1上,即紫罗兰色;0 1映射到0.5 0上。图35-26显示了材质为渐变笔刷的三角形,这里也使用了环境光。

 
图  35-25

 
图  35-26

 

< ModelVisual3D >
< ModelVisual3D.Content >
< GeometryModel3D >
< GeometryModel3D.Geometry >
< MeshGeometry3D
Positions="-1 -1 -4, 1 -1 -4, 0 1 -4"
TriangleIndices="0, 1, 2"
TextureCoordinates="0 1, 1 1, 0.5 0" / >
< /GeometryModel3D.Geometry >
< GeometryModel3D.Material >
< MaterialGroup >
< DiffuseMaterial >
< DiffuseMaterial.Brush >
< LinearGradientBrush StartPoint="0,0"
EndPoint="1,1" >
< GradientStop Color="Yellow" Offset="0" / >
< GradientStop Color="Orange" Offset="0.25" / >
< GradientStop Color="Red" Offset="0.50" / >
< GradientStop Color="Blue" Offset="0.75" / >
< GradientStop Color="Violet" Offset="1" / >
< /LinearGradientBrush >
< /DiffuseMaterial.Brush >
< /DiffuseMaterial >
< /MaterialGroup >
< /GeometryModel3D.Material >
< /GeometryModel3D >
< /ModelVisual3D.Content >
< /ModelVisual3D >

提示:

可以用类似的方式添加文本和其他控件。为此,只需用要绘制的元素创建VisualBrush。

3. 3D对象

下面研究真正的3D对象:立方体。立方体由5个矩形组成:后面、前面、左面、右面和底面。每个矩形都由两个三角形组成,因为这是网格的核心。在WPF和3D术语中,网格用于描述建立3D形状的基本三角形。

下面是立方体中前面矩形的代码,该矩形由两个三角形组成。三角形的位置按TriangleIndies定义的逆时针设置。立方体的前面用红色的笔刷绘制,后面用灰色笔刷绘制。这两个笔刷都是SolidColorBrush类型,用Window的资源定义。

< !-- Front -- >
< GeometryModel3D >
< GeometryModel3D.Geometry >
< MeshGeometry3D
Positions="-1 -1 1, 1 -1 1, 1 1 1, 1 1 1,
-1 1 1, -1 -1 1"
TriangleIndices="0 1 2, 3 4 5" / >
< /GeometryModel3D.Geometry >
< GeometryModel3D.Material >
< DiffuseMaterial Brush="{StaticResource redBrush}" / >
< /GeometryModel3D.Material >
< GeometryModel3D.BackMaterial >
< DiffuseMaterial Brush="{StaticResource grayBrush}" / >
< /GeometryModel3D.BackMaterial >
< /GeometryModel3D >

其他矩形非常类似,只是在不同的位置上。下面是立方体左面的XAML代码:

< !-- Left side -- >
< GeometryModel3D >
< GeometryModel3D.Geometry >
< MeshGeometry3D
Positions="-1 -1 1, -1 1 1, -1 -1 -1, -1 -1 -1, -1 1 1,
-1 1 -1"
TriangleIndices="0 1 2, 3 4 5" / >
< /GeometryModel3D.Geometry >
< GeometryModel3D.Material >
< DiffuseMaterial Brush="{StaticResource redBrush}" / >
< /GeometryModel3D.Material >
< GeometryModel3D.BackMaterial >
< DiffuseMaterial Brush="{StaticResource grayBrush}" / >
< /GeometryModel3D.BackMaterial >
< /GeometryModel3D >

提示:

示例代码为立方体的每个面定义了一个GeometryModel3D,仅是为了更好地理解代码。只要每个面都使用相同的材质,就可以定义一个网格,它包含立方体所有面的全部10个三角形。

所有的矩形都在Model3DGroup中组合,所以可以对立方体的所有面进行变换:

< !-- the model -- >
< ModelVisual3D >
< ModelVisual3D.Content >
< Model3DGroup >
< ! - GeometryModel3D elements for every side of the box -- >
< /Model3DGroup >

使用Model3DGroup的Transform属性,就可以变换这个组中的所有几何体。下面使用RotateTransform3D定义一个AxisAngleRotation3D。要在运行期间旋转立方体,Angle属性要绑定到Slider控件的值上。

< !-- Transformation of the complete model -- >
< Model3DGroup.Transform >
< RotateTransform3D CenterX="0" CenterY="0" CenterZ="0" >
< RotateTransform3D.Rotation >
< AxisAngleRotation3D x:Name="axisRotation"
Axis="0, 0, 0"
Angle="{Binding Path=Value,
ElementName=axisAngle}" / >
< /RotateTransform3D.Rotation >
< /RotateTransform3D >
< /Model3DGroup.Transform >

为了查看立方体,需要一个摄像机。这里使用PerspectiveCamera,因此立方体离摄像机越远,就越小。摄像机的位置的方向在运行期间设置。

< !-- Camera -- >
< Viewport3D.Camera >
< PerspectiveCamera x:Name="camera"
Position="{Binding Path=Text,
ElementName=textCameraPosition}"
LookDirection="{Binding Path=Text,
ElementName=textCameraDirection}" / >
< /Viewport3D.Camera >

应用程序使用两个不同的光源,其中一个光源是DirectionalLight:

< !-- directional light -- >
< ModelVisual3D >
< ModelVisual3D.Content >
< DirectionalLight Color="White" x:Name="directionalLight" >
< DirectionalLight.Direction >
< Vector3D X="1" Y="2" Z="3" / >
< /DirectionalLight.Direction >
< /DirectionalLight >
< /ModelVisual3D.Content >
< /ModelVisual3D >

另一个光源是SpotLight。使用这个光源可以突出显示立方体的一个特定区域。SpotLight定义了属性InnerConeAngle和OuterConeAngle,以指定完全照亮的区域:

< !-- spot light -- >
< ModelVisual3D >
< ModelVisual3D.Content >
< SpotLight x:Name="spotLight"
InnerConeAngle="{Binding Path=Value,
ElementName=spotInnerCone}"
OuterConeAngle="{Binding Path=Value,
ElementName=spotOuterCone}"
Color="#FFFFFF"
Direction="{Binding Path=Text, ElementName=spotDirection}"
Position="{Binding Path=Text, ElementName=spotPosition}"
Range="{Binding Path=Value, ElementName=spotRange}" / >
< /ModelVisual3D.Content >
< /ModelVisual3D >

运行应用程序,就可以改变立方体的旋转角度、摄像机和灯光,如图35-27所示。

 
图  35-27

提示:

创建仅包含矩形或三角形的3D模型是很简单的。不应手工创建更复杂的模型,而应使用对应的工具。WPF的3D工具在www.codeplex/3DTools上。

目录
相关文章
|
开发框架 .NET C#
2000条你应知的WPF小姿势 基础篇<63-68 Triggers和WPF类逻辑结构>
2000条你应知的WPF小姿势 基础篇<63-68 Triggers和WPF类逻辑结构>
63 0
|
4月前
|
开发框架 前端开发 JavaScript
循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(8) -- 使用Converter类实现内容的转义处理
循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(8) -- 使用Converter类实现内容的转义处理
|
C# Windows 图形学
优化WPF 3D性能
原文:优化WPF 3D性能 Maximize WPF 3D Performance .NET Framework 4.5   As you use the Windows Presentation Foundation (WPF) to build 3D contr...
1361 0
|
C# 小程序
WPF 3D变换应用
原文:WPF 3D变换应用  WPF可以提供的3D模型使我们可以轻松地创建3D实体,虽然目前来看还很有一些性能上的问题,不过对于一些简单的3D应用应该是可取的,毕竟其开发效率高,而且也容易上手。         下面给大家演示的是使用在WPF 3D上实现视角变换,通过鼠标拖动来变换观察视角,通过滚轮来放缩视距。
740 0
|
C#
WPF 属性变更通知类的实现
原文:WPF 属性变更通知类的实现 平时用依赖属性多一些,普通属性的变更通知知道有这个方法,但是老是忘记名字,再写一遍吧。
1024 0
|
C# 前端开发 Windows
WPF中的Application类。
原文:WPF中的Application类。 Application对象用的名称空间是system.windows 1、手动创建Application对象步骤。 1.1)、把项目中的App.Xaml文件从项目中排除。
1293 0
|
C#
WPF特效-实现3D足球效果
原文:WPF特效-实现3D足球效果 WPF 实现 3D足球效果,效果图如下:  每个面加载不同贴图。                                                          ...
921 0
|
C#
在WPF中将图片转换成3D图像并可以旋转
原文:在WPF中将图片转换成3D图像并可以旋转 时光偷走的,永远都是我们眼皮底下看不见的珍贵。   https://pan.baidu.com/s/14dk-OU2SR0nxXj2bL4bVpQ 首先先看一下源代码最初的运行效果,是否是自己需要的。
1538 0
|
前端开发 C# 开发者
WPF MVVM 架构 Step By Step(3)(把后台代码移到一个类中)
原文:WPF MVVM 架构 Step By Step(3)(把后台代码移到一个类中)   我觉得大部分开发者应该已经知道怎么去解决这个问题。一般都是把后台代码(GLUE code)移动到一个类库。这个类库用来代表UI的属性和行为。
1057 0
|
前端开发 C# 程序员
WPF整理-XAML构建后台类对象
原文:WPF整理-XAML构建后台类对象 1.XAML 接触WPF的第一眼就是XAML---XAML是用来描绘界面的。其实不然! "Actually, XAML has nothing to do with UI. It's merely a declarative way of constructing objects and setting their properties.” XAML和UI一点关系也没有,它仅仅是一种以声明方式来构建对象,设置对象属性的一种方式而已,和code behind file作用差不多。
986 0