WPF 3D 常用的幾個(gè)類(lèi)及其關(guān)系
1. Visual 類(lèi)
所有二維可視化元素的基類(lèi),為 WPF 中的呈現(xiàn)提供支持,其中包括命中測(cè)試、坐標(biāo)轉(zhuǎn)換和邊界框計(jì)算。
Visual 對(duì)象是一個(gè)核心 WPF 對(duì)象,其主要作用是提供呈現(xiàn)支持。用戶界面控件(例如 Button 和 TextBox)派生自 Visual 類(lèi),并使用 Visual 定義的屬性來(lái)保存它們所呈現(xiàn)的數(shù)據(jù)。Visual 對(duì)象可對(duì)下列功能提供支持:
輸出顯示:為可視對(duì)象呈現(xiàn)持久的序列化繪圖內(nèi)容。
轉(zhuǎn)換:對(duì)可視對(duì)象執(zhí)行轉(zhuǎn)換。
剪輯:為可視對(duì)象提供剪輯區(qū)域支持。
命中測(cè)試:確定指定的坐標(biāo)(點(diǎn))或幾何圖形是否包含在可視對(duì)象的邊界內(nèi)。
邊界框計(jì)算:確定可視對(duì)象的邊框。
2. Visual3D 類(lèi)
所有三維可視化元素的基類(lèi),提供可視三維對(duì)象通用的服務(wù)和屬性,其中包括命中測(cè)試、坐標(biāo)轉(zhuǎn)換和邊界框計(jì)算。
3. Viewport3D類(lèi)
為三維可視內(nèi)容提供呈現(xiàn)圖面。
此控件顯示三維內(nèi)容,同時(shí)提供與二維布局(如剪輯、高度和寬度及鼠標(biāo)事件)一致的屬性。
當(dāng)此控件作為布局元素(如 Canvas)的內(nèi)容包含時(shí),可通過(guò)設(shè)置其 Height 和 Width 屬性(繼承自 FrameworkElement)來(lái)指定 Viewport3D 的大小。
Viewport3D 可提供三維場(chǎng)景級(jí)別的命中測(cè)試。 調(diào)用 HitTest 方法可返回有關(guān)命中可視對(duì)象、模型、網(wǎng)格和交點(diǎn)的詳細(xì)命中結(jié)果信息。
4. Viewport3DVisual 類(lèi)
在指定的二維視區(qū)邊界內(nèi)呈現(xiàn) Visual3D 子對(duì)象。
Viewport3DVisual 是具有三維子對(duì)象的二維 Visual 對(duì)象。Viewport3DVisual 為 Viewport3D 元素提供了必需的基礎(chǔ)結(jié)構(gòu)。 大多數(shù)用戶都需要使用 Viewport3D 元素。
Viewport3DVisual 在二維 Visual 和 Visual3D 對(duì)象之間起到橋梁作用。Visual3D 類(lèi)是所有三維可視化元素的基類(lèi)。Viewport3DVisual 要求您定義一個(gè) Camera 值和一個(gè) Viewport 值??梢越柚障鄼C(jī)來(lái)查看場(chǎng)景。投影映射到二維圖面的區(qū)域稱作視區(qū)。
繼承層次結(jié)構(gòu)
System..::.Object
System.Windows.Threading..::.DispatcherObject
System.Windows..::.DependencyObject
System.Windows.Media..::.Visual
System.Windows.Media.Media3D..::.Viewport3DVisual
5. Model3D 類(lèi)
為三維模型提供功能的抽象類(lèi)。此類(lèi)對(duì)象包括 GeometryModel3D 和 Light。
繼承層次結(jié)構(gòu)
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 類(lèi)
包含三維模型的 Visual。提供所有可視對(duì)象通用的服務(wù)和屬性,其中包括命中測(cè)試、坐標(biāo)轉(zhuǎn)換和邊界框計(jì)算。
繼承層次結(jié)構(gòu)
System..::.Object
System.Windows.Threading..::.DispatcherObject
System.Windows..::.DependencyObject
System.Windows.Media.Media3D..::.Visual3D
System.Windows.Media.Media3D..::.ModelVisual3D
7. GeometryModel3D 類(lèi)
創(chuàng)建由一個(gè) MeshGeometry3D 和一個(gè) Material 構(gòu)成的三維模型。
繼承層次結(jié)構(gòu)
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 類(lèi)
用于生成三維形狀的三角形基元。
繼承層次結(jié)構(gòu)
System..::.Object
System.Windows.Threading..::.DispatcherObject
System.Windows..::.DependencyObject
System.Windows.Media..::.Visual
System.Windows..::.UIElement
System.Windows..::.FrameworkElement
System.Windows.Controls..::.Viewport3D
繼承層次結(jié)構(gòu)
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特性,其中包含了開(kāi)始使用該特性的信息。
提示:
WPF中的3D特性在System.Windows.Media.Media3D命名空間中。
為了理解WPF中的3D特性,一定要知道坐標(biāo)系統(tǒng)之間的區(qū)別。圖35-22顯示了WPF 3D中的坐標(biāo)系統(tǒng)。原點(diǎn)位于中心。X軸的正值在右邊,負(fù)值在左邊。Y軸是垂直的,正值在上邊,負(fù)值在下邊。Z軸在指向觀察者的方向上定義了正值。
|
圖 35-22 |
表35-9描述了最重要的類(lèi)及其功能。
表 35-9
類(lèi) |
說(shuō) 明 |
ViewPort3D |
ViewPort3D定義了3D對(duì)象的渲染表面。這個(gè)元素包含3D繪圖的所有可見(jiàn)元素 |
ModelVisual3D |
ModelVisual3D包含在ViewPort3D中,它包含了所有可見(jiàn)元素??梢越o完整的模型指定變換 |
GeometryModel3D |
GeometryModel3D包含在ModelVisual3D中,它包含網(wǎng)格和材質(zhì) |
Geometry3D |
Geometry3D是一個(gè)抽象基類(lèi),定義了幾何形狀。派生于Geometry3D的類(lèi)是MeshGeometry3D。使用MeshGeometry3D可以定義三角形的位置,建立3D模型 |
Material |
Material是一個(gè)抽象基類(lèi),定義了MeshGeometry3D指定的三角形的前邊和后邊。Material包含在GeometryModel3D中。.NET 3.5定義了幾個(gè)材質(zhì)類(lèi),例如DiffuseMaterial、EmissiveMaterial和SpecularMaterial。根據(jù)材質(zhì)的類(lèi)型,以不同的方式計(jì)算燈光。EmissiveMaterial利用燈光的計(jì)算,使材質(zhì)發(fā)出等于筆刷顏色的光。DiffuseMaterial使用漫射光,SpecularMaterial定義了鏡面發(fā)光模型。使用MaterialGroup類(lèi)可以創(chuàng)建由其他材質(zhì)合并而成的材質(zhì) |
Light |
Light是燈光的抽象基類(lèi)。其派生類(lèi)有AmbientLight、DirectionalLight、PointLight和SpotLight。AmbientLight是不自然的光,會(huì)近似照亮整個(gè)場(chǎng)景。使用這種光看不到邊界。DirectionalLight定義了定向光。太陽(yáng)光就是一種定向光,光線來(lái)自一邊,此時(shí)可以看到邊界和陰影。PointLight是一種位于指定位置的光,會(huì)照亮所有的方向。SpotLight照亮指定的方向。這個(gè)光定義了一個(gè)圓錐,會(huì)得到一個(gè)發(fā)出光亮的區(qū)域 |
Camera |
Camera是攝像機(jī)的抽象基類(lèi),用于把3D場(chǎng)景映射為2D顯示。其派生類(lèi)是PerspectiveCamera、OrthographicCamera和MatrixCamera。在PerspectiveCamera中,3D對(duì)象離得越遠(yuǎn)就越小,這不同于OrthographicCamera,在Orthographic Camera中,攝像機(jī)的距離對(duì)對(duì)象的大小沒(méi)有影響。在MatrixCamera中,可以在矩陣中定義視圖和變換 |
Transform3D |
Transform3D是3D變換的抽象基類(lèi)。其派生類(lèi)是RotateTransform3D、ScaleTransform3D、TranslateTransform3D、MatrixTransform3D和Transform3D Group。TranslateTransform3D允許在x、y和z向上變換對(duì)象,ScaleTransform3D可以重置對(duì)象的大小。RotateTransform3D可以在x、y和z向上把對(duì)象旋轉(zhuǎn)指定的角度。Transform3DGroup可以合并其他變換效果 |
三角形
本節(jié)從一個(gè)簡(jiǎn)單的3D示例開(kāi)始。3D模型由三角形組成,所以最簡(jiǎn)單的模型是一個(gè)三角形。三角形用MeshGeometry3D的Positions屬性定義。3個(gè)頂點(diǎn)都使用相同的z坐標(biāo)-4,x、y坐標(biāo)分別為-1-1、1-1和01。屬性TriangleIndices指定了逆時(shí)針的位置順序。使用這個(gè)屬性可以確定三角形的哪一邊是可見(jiàn)的。三角形的一邊顯示了用GeometryModel3D類(lèi)的Meterial屬性定義的顏色,其他邊顯示了BackMeterial屬性定義的顏色。
用于顯示場(chǎng)景的攝像機(jī)位于坐標(biāo)0,0,0,其方向指向0,0,-8。把攝像機(jī)的位置改變到左邊,矩形就移動(dòng)到右邊,反之亦然。改變攝像機(jī)的y位置,矩形就會(huì)變大或變小。
這個(gè)場(chǎng)景中使用的光線是AmbientLight,它用白色光照亮了整個(gè)場(chǎng)景。圖35-23顯示了三角形的效果。
< Window x:Class="Triangle3D.Window1" xmlns="< 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僅顯示了一個(gè)簡(jiǎn)單的三角形,它與2D的效果相同。但是,下面將繼續(xù)添加3D特性。例如,用SpotLight元素把環(huán)境光改為聚光燈,就可以看到三角形的另一個(gè)外觀,使用聚光燈可以定義光源的位置和光線的照射方向。給光源的位置指定-1 1 2,光就位于三角形的左邊頂點(diǎn)處,其y坐標(biāo)是三角形的高度。之后,光線向下向左照射。圖35-24顯示了三角形的新外觀。
< ModelVisual3D > < ModelVisual3D.Content > < SpotLight Position="-1 1 -2" Color="White" Direction="-1.5, -1, -5" / > < /ModelVisual3D.Content > < /ModelVisual3D > |
|
圖 35-24 |
2. 添加紋理
除了給三角形的材質(zhì)使用純色筆刷之外,還可以使用其他筆刷,例如LinearGradient- Brush,如下面的XAML代碼所示。用DiffuseMeterial定義的LinearGradientBrush元素指定了黃色、橙色、紅色、藍(lán)色和紫羅蘭色的漸變點(diǎn)。要把使用這種筆刷的對(duì)象的2D表面映射到3D幾何體上,必須設(shè)置TextCoordinates屬性。TextCoordinates定義了2D點(diǎn)的集合,它可以映射到3D位置上。圖35-25顯示了示例應(yīng)用程序中筆刷的2D坐標(biāo)。三角形中的第一個(gè)位置-1-1映射到筆刷坐標(biāo)0 1上,右下角的位置1 -1映射到筆刷的1 1上,即紫羅蘭色;0 1映射到0.5 0上。圖35-26顯示了材質(zhì)為漸變筆刷的三角形,這里也使用了環(huán)境光。
|
圖 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 > |
提示:
可以用類(lèi)似的方式添加文本和其他控件。為此,只需用要繪制的元素創(chuàng)建VisualBrush。
3. 3D對(duì)象
下面研究真正的3D對(duì)象:立方體。立方體由5個(gè)矩形組成:后面、前面、左面、右面和底面。每個(gè)矩形都由兩個(gè)三角形組成,因?yàn)檫@是網(wǎng)格的核心。在WPF和3D術(shù)語(yǔ)中,網(wǎng)格用于描述建立3D形狀的基本三角形。
下面是立方體中前面矩形的代碼,該矩形由兩個(gè)三角形組成。三角形的位置按TriangleIndies定義的逆時(shí)針設(shè)置。立方體的前面用紅色的筆刷繪制,后面用灰色筆刷繪制。這兩個(gè)筆刷都是SolidColorBrush類(lèi)型,用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 > |
其他矩形非常類(lèi)似,只是在不同的位置上。下面是立方體左面的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 > |
提示:
示例代碼為立方體的每個(gè)面定義了一個(gè)GeometryModel3D,僅是為了更好地理解代碼。只要每個(gè)面都使用相同的材質(zhì),就可以定義一個(gè)網(wǎng)格,它包含立方體所有面的全部10個(gè)三角形。
所有的矩形都在Model3DGroup中組合,所以可以對(duì)立方體的所有面進(jìn)行變換:
< !-- the model -- > < ModelVisual3D > < ModelVisual3D.Content > < Model3DGroup > < ! - GeometryModel3D elements for every side of the box -- > < /Model3DGroup > |
使用Model3DGroup的Transform屬性,就可以變換這個(gè)組中的所有幾何體。下面使用RotateTransform3D定義一個(gè)AxisAngleRotation3D。要在運(yùn)行期間旋轉(zhuǎn)立方體,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 > |
為了查看立方體,需要一個(gè)攝像機(jī)。這里使用PerspectiveCamera,因此立方體離攝像機(jī)越遠(yuǎn),就越小。攝像機(jī)的位置的方向在運(yùn)行期間設(shè)置。
< !-- Camera -- > < Viewport3D.Camera > < PerspectiveCamera x:Name="camera" Position="{Binding Path=Text, ElementName=textCameraPosition}" LookDirection="{Binding Path=Text, ElementName=textCameraDirection}" / > < /Viewport3D.Camera > |
應(yīng)用程序使用兩個(gè)不同的光源,其中一個(gè)光源是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 > |
另一個(gè)光源是SpotLight。使用這個(gè)光源可以突出顯示立方體的一個(gè)特定區(qū)域。SpotLight定義了屬性InnerConeAngle和OuterConeAngle,以指定完全照亮的區(qū)域:
< !-- 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 > |
運(yùn)行應(yīng)用程序,就可以改變立方體的旋轉(zhuǎn)角度、攝像機(jī)和燈光,如圖35-27所示。
|
圖 35-27 |
提示:
創(chuàng)建僅包含矩形或三角形的3D模型是很簡(jiǎn)單的。不應(yīng)手工創(chuàng)建更復(fù)雜的模型,而應(yīng)使用對(duì)應(yīng)的工具。WPF的3D工具在www.codeplex/3DTools上。