在WPF中绘制多维数据集

原文 https://stuff.seans.com/2008/08/13/drawing-a-cube-in-wpf/

是时候使用WPF绘制一个简单的3D对象了。作为WPF中3D图形的快速介绍,让我们只渲染一个最简单的对象 – 一个立方体。

在这个例子中,我将直接在XAML中定义我们需要的所有内容。与WPF中的其他内容一样,我们可以直接在代码中完成所有这些操作。但是在XAML中定义所有内容更加清晰,因为它使对象层次结构更加明显。在实际项目中,您显然会在代码中执行此操作,例如创建或加载3D网格(我们要显示的对象)。

让我们从最终的XAML开始吧。以下是Window1.xaml文件的完整内容:

1 2 3 4 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 三十 31 32 33 34 35 36 37 38 < Window x:Class = "SimpleCube.Window1"      xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"      xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"      Title = "Window1" Height = "398" Width = "608"      <Grid>          < Viewport3D Name = "viewport3D1" >              < Viewport3D.Camera >                  < PerspectiveCamera x:Name = "camMain" Position = "6 5 4" LookDirection = "-6 -5 -4" >                  </ PerspectiveCamera >              </ Viewport3D.Camera >              < ModelVisual3D >                  < ModelVisual3D.Content >                      < DirectionalLight x:Name = "dirLightMain" Direction = "-1,-1,-1" >                      </ DirectionalLight >                  </ ModelVisual3D.Content >              </ ModelVisual3D >              < ModelVisual3D >                  < ModelVisual3D.Content >                      < GeometryModel3D >                          < GeometryModel3D.Geometry >                              < MeshGeometry3D x:Name = "meshMain"                                  Positions = "0 0 0  1 0 0  0 1 0  1 1 0  0 0 1  1 0 1  0 1 1  1 1 1"                                  TriangleIndices = "2 3 1  2 1 0  7 1 3  7 5 1  6 5 7  6 4 5  6 2 0  2 0 4  2 7 3  2 6 7  0 1 5  0 5 4" >                              </ MeshGeometry3D >                          </ GeometryModel3D.Geometry >                          < GeometryModel3D.Material >                              < DiffuseMaterial x:Name = "matDiffuseMain" >                                  < DiffuseMaterial.Brush >                                      < SolidColorBrush Color = "Red" />                                  </ DiffuseMaterial.Brush >                              </ DiffuseMaterial >                          </ GeometryModel3D.Material >                      </ GeometryModel3D >                  </ ModelVisual3D.Content >              </ ModelVisual3D >          </ Viewport3D >      </ Grid > </ Window >

这里的基本思想是我们需要一个Viewport3D对象,它包含渲染立方体所需的一切。显示Viewport3D及其子对象的简化结构是:

1 2 3 4 6 7 Viewport3D      ModelVisual3D   (defines lighting)          DirectionalLight      ModelVisual3D   (defines object to render)          GeometryModel3D              MeshGeometry3D              DiffuseMaterial

以下是每个对象负责的内容:

  • Viewport3D – 渲染3D内容的地方
  • ModelVisual3D – 视口包含的3D对象,可以是灯光或几何
  • DirectionalLight – 在特定方向照射的光
  • GeometryModel3D – 一个3D几何对象
  • MeshGeometry3D – 定义3D对象的三角形集
  • DiffuseMaterial – 用于渲染3D对象的材质,例如画笔

也许这些类中最有趣的是MeshGeometry3D“网格”基本上由一系列三角形组成,通常所有三角形都连接起来形成您想要渲染的3D对象。所述MeshGeometry3D对象通过指定一系列的点,然后三角形的集合定义了一个网格。点集合表示网格中的所有顶点,并由Positions属性定义存储在TriangleIndices属性中的三角形是根据点使用索引到Positions集合中定义的。

起初这似乎有点奇怪。为什么不定义一组三角形,每个三角形由三个点组成?为什么将点定义为单独的集合,然后通过引用点来定义三角形?答案是该方案允许在多个三角形中重复使用单个点。

在我们的例子中,绘制一个立方体,我们为立方体的八个顶点定义了八个点。下图显示了从0到7编号的点,与我们将它们添加到位置的顺序相匹配立方体的左后角位于(0,0,0)。

定义点后,我们定义构成表面立方体的12个三角形 – 每个面两个三角形。我们通过仅列出构成三角形的三个点的索引来定义每个三角形。

注意我们列出每个三角形的索引的顺序也很重要。该顺序指示垂直于三角形的向量的方向,该向量指示我们可以看到的三角形的哪一侧。规则是:当您查看三角形的可见面时,逆时针添加顶点。

除了网格,我们还定义了用于渲染立方体的材质。在这种情况下,它是一个DiffuseMaterial,它允许用简单的画笔绘制立方体的表面。

我们还需要在我们的场景中添加一个摄像头,通过指定它的位置以及它所在的方向。为了看到我们的立方体,我们将摄像机置于(6,5,4),然后设置其LookDirection,向量,到(-6,-5,-4),使它回头看原点。

最后,为了看到立方体,我们需要照明。我们定义了一个单独的光源,它是一个DirectionalLight – 一个没有位置但只是在特定方向投射光线的光。

最终结果是一个简单的红色立方体。