原文: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定义了几个材质类,例如DiffuseMaterial、EmissiveMaterial和SpecularMaterial。根据材质的类型,以不同的方式计算灯光。EmissiveMaterial利用灯光的计算,使材质发出等于笔刷颜色的光。DiffuseMaterial使用漫射光,SpecularMaterial定义了镜面发光模型。使用MaterialGroup类可以创建由其他材质合并而成的材质

Light

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

Camera

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

Transform3D

Transform3D是3D变换的抽象基类。其派生类是RotateTransform3D、ScaleTransform3D、TranslateTransform3D、MatrixTransform3D和Transform3D Group。TranslateTransform3D允许在x、y和z向上变换对象,ScaleTransform3D可以重置对象的大小。RotateTransform3D可以在x、y和z向上把对象旋转指定的角度。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 x:Class="Triangle3D.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="3D" Height="300" 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上。

WPF中的3D特性和常见的几个类的更多相关文章

  1. 在WPF中添加3D特性

    原文:在WPF中添加3D特性 35.4  在WPF中添加3D特性 本节介绍WPF中的3D特性,其中包含了开始使用该特性的信息. 提示: WPF中的3D特性在System.Windows.Media.M ...

  2. WPF中反转3D列表项

    原文:WPF中反转3D列表项 WPF中反转3D列表项                                                         周银辉记得在苹果电脑中有一个很酷的 ...

  3. WPF中的3D Wireframe

    原文:WPF中的3D Wireframe WPF不支持画三维线,但开发人员提供了ScreenSpaceLines3D 类用于实现这个功能.我已经在程序中实现并成功显示3D Wireframe,并能够进 ...

  4. WPF中的3D变换PlaneProjection

    在UWP中有一个比较好用的伪3D变换PlaneProjection,可以以一种轻量级和非常简单的方式实现3D的效果.这种效果在Silverlight中也有这种变换,但在WPF中确一直没有提供. 虽然W ...

  5. Python3中的新特性(2)——常见陷阱

    1.文本与字节 Python3对文本字符串(字符)和二进制数据(字节)进行了严格区分,'hello'表示一个以Unicode编码保存的文本字符串,而b'hello'表示一个字节字符串. 在Python ...

  6. WPF 中如何使用第三方控件 ,可以使用WindowsFormsHost 类

    允许在 WPF 页面上承载 Windows Forms控件的元素. 命名空间:   System.Windows.Forms.Integration 程序集:   WindowsFormsIntegr ...

  7. WPF中的简单水动画

    原文 https://stuff.seans.com/2008/08/21/simple-water-animation-in-wpf/ 很多年前(80年代中期),我在一家拥有Silicon Grap ...

  8. WPF中的三维空间(1)

    原文:WPF中的三维空间(1) WPF中可以创建三维几何图形,支持3D对象的应用,支持从3D Max等软件将3D文件obj导入设计中,但是目前还不支持将材质同时导入,这样需要在WPF中对3D对象重新设 ...

  9. WPF中的平移缩放和矩阵变换(TranslateTransform、ScaleTransform、MatrixTransform)

    在WPF中的平移缩放都是通过RenderTransform这个类来实现这些效果的,在这个类中,除了平移和缩放还有旋转.扭曲变换.矩阵变换.这些都差不多的,都是坐标的变换. 这里我就先简单弄个平移和缩放 ...

随机推荐

  1. HIVE快速入门 分类: B4_HIVE 2015-06-06 11:27 59人阅读 评论(0) 收藏

    (一)简单入门 1.创建一个表 create table if not exists ljh_emp( name string, salary float, gender string) commen ...

  2. 20、RTC驱动程序

    drivers\rtc\rtc-s3c.c s3c_rtc_init platform_driver_register s3c_rtc_probe rtc_device_register(" ...

  3. SpringCloud微服务学习笔记

    SpringCloud微服务学习笔记 项目地址: https://github.com/taoweidong/Micro-service-learning 单体架构(Monolithic架构) Mon ...

  4. 2014年武汉的IT行情好像不太好

    本周,加入武汉一起好工作一周了,也就是说本次找工作彻底结束了. 总的来说,求职行情不太行,双方都匹配的工作好少呀. 1. 武汉财富基石,过了一面,第二面没有去.   钱太少,4K多,跳楼价. 2.武汉 ...

  5. null与对象的复杂关系(typeof null的结果是object的原因)

    原文 简书原文:https://www.jianshu.com/p/c1608452d056 前言 对象是 JavaScript 的基础.在 JavaScript 中一共有六种主要类型(术语是“语言类 ...

  6. Spinlock implementation in ARM architecture

    Spinlock implementation in ARM architecture   SEV and WFE are the main instructions used for impleme ...

  7. iOS开发webView的使用一

    #import "ViewController.h" @interface ViewController () @property (weak, nonatomic) IBOutl ...

  8. javascript中0级DOM和2级DOM事件模型浅析 分类: C1_HTML/JS/JQUERY 2014-08-06 15:22 253人阅读 评论(0) 收藏

    Javascript程序使用的是事件驱动的设计模式,为一个元素添加事件监听函数,当这个元素的相应事件被触发那么其添加的事件监听函数就被调用: <input type="button&q ...

  9. Android多线程研究(9)——线程锁Lock

    在前面我们在解决线程同步问题的时候使用了synchronized关键字,今天我们来看看Java 5.0以后提供的线程锁Lock. Lock接口的实现类提供了比使用synchronized关键字更加灵活 ...

  10. C# WebAPI中DateTime类型字段在使用微软自带的方法转json格式后默认含T的解决办法

    原文:C# WebAPI中DateTime类型字段在使用微软自带的方法转json格式后默认含T的解决办法 本人新手,在.Net中写WebAPI的时候,当接口返回的json数据含有日期时间类型的字段时, ...