3D開發基礎知識和簡單示例

引言

222249124196156

如今物聯網概念這麼火,若是監控的信息可以實時在手機的客服端中以3D形式展現給咱們,那種體驗你們能夠發揮本身的想象。php

image

那生活中咱們還有不少地方用到這些,如上圖所示的Kinect 在醫療上的應用,固然還有體感遊戲等等。git

 

3D 用來增長視覺效果,給人以更加直觀,真實的感受。github

3D如此美妙,那咱們在WPF中又該從何處入手開啓咱們的3D編程旅程?算法

 

WPF中3D開發技術的基礎知識應該有如下幾點:編程

  • 3D開發基礎知識
  • WPF中3D開發的基礎元素(Elements)
  • WPF中3D變換和動畫
  • 經常使用輔助類

3D開發基礎知識

座標系 Coodinate System

WPF中二維圖形的座標系將原點定位在呈現區域(一般是屏幕)的左上角。 在二維繫統中,x 軸上的正值朝右,y 軸上的正值朝下。而在三維座標系中,原點位於呈現區域的中心,x 軸上的正值朝右,可是 y 軸上的正值朝上,z 軸上的正值從原點向外朝向觀察者。傳統的二維和三維座標系表示形式以下圖windows

 

CoordinateSystem

由這些軸定義的空間是三維對象在 WPF 中的固定參考框架。app

當您在該空間中生成模型並建立光源和照相機以查看這些模型時,必定要在向每一個模型應用變換時,將固定參考框架或「全局空間」與您爲該模型建立的局部參考框架區分開。框架

另請記住,根據光源和照相機設置,全局空間中的對象可能會看上去徹底不一樣或者根本不可見,可是照相機的位置不會改變對象在全局空間中的位置。ide

3D的世界都是三角形的王國

 

以下圖:post

 

triangle_model

在3D的世界裏全部的東西都是用一些列的「三角形」來描述的。那你必定會問爲何是「三角形」?

緣由是三角形是用來描述一個平面的最細微的幾何體,渲染引擎可以依據每一個三角形的材質以及場景中的燈光角度來計算它的顏色。

其實就是三點肯定一個平面,在一個平面上作計算最簡單,考慮的因素最少。若是用三維空間中大於三個點來作渲染基本單位,那麼若是這些點不在同一個平面上的話,渲染計算是至關複雜的。

3D 對象的表面叫作網格(Mesh),一個網格是由許多3D 點來定義的,這些點叫作頂點(vertices)。這些頂點經過纏繞模式(winding pattern)鏈接在一塊兒組成一個一個的三角形(facet)(以下圖箭頭所示)。

vertex

三角形(facet)又分爲「前」和「後」兩面,能看到的部分爲前面,看不到的部分爲後面。

那怎麼斷定是前面仍是後面?

若是三角形的三個點順時針方向組成的面那麼這個面就是前面。以下圖

Facet

按照0,1,2的順序三個點組成了的這個面是上面咱們能夠看到

目前主流(Direct3D and/or OpenGL)都會把三角形分爲兩個面(前面和後面)。

 

爲幫助你們記憶(facet)「前面」的三維座標,大拇指是Z+的方向正對着咱們(及前面圖示中Up方向),食指是y+方向,而中指是Y+方向。(+表示正數的方向)

righthandrule

 

 

WPF 3D的關鍵元素(Elements)

maciej-progtech-wpf-3d-projection-2d

3D 畫布

要畫畫總的有個畫布,WPF中呈現3D也須要一個相似功能的東西。Viewport3D(投影3D場景的平面)是WPF中的3D畫布,類於2D中的Canvas。其實WPF中也有一個名字開起來相似的東東Viewbox ,不過和3D沒啥關係,它處理的都是2D的。

1

2

3

<Viewport3D>

Children…

</Viewport3D>

該圖形系統將 Viewport3D 視爲一個像 WPF 中的許多其餘元素同樣的二維可視化元素。 Viewport3D充當三維場景中的窗口(即視區)。 更準確地說,它是三維場景所投影到的圖面。

相機

處理二維對象的開發人員習慣於將繪圖基元置於二維屏幕上。 當您建立三維場景時,必定要記住您其實是要建立三維對象的二維表示形式。 因爲三維場景的外觀會因觀察者的觀察位置不一樣而異,所以您必須指定觀察位置。而觀察位置就是由相機(Camera 類)來爲三維場景指定的。

 

另外一種理解三維場景在二維圖上的描述方法就是,將3D場景投影到一個2D平面的表面。以下圖:

3d2d

從座標系的角度來看下咱們的ProjectionCamera(透視相機)和3D模型的位置,以及2D 投影屏幕的位置關係:

IC210304

更詳細的圖解以下:

Graphics3D_ClipVolume

 

ProjectionCameraNearPlaneDistanceFarPlaneDistance 屬性限制照相機的投影範圍。因爲照相機能夠位於場景中的任何位置,所以照相機實際上可能會位於模型內部或者緊靠模型,這使正確區分對象變得很困難。 經過 NearPlaneDistance,能夠指定一個距離照相機的最小距離,超過該距離後即不繪製對象。 相反,使用 FarPlaneDistance,能夠指定一個距離照相機的距離(即,在超過該距離後將不繪製對象),從而確保因距離太遠而沒法識別的對象將不包括在場景中。

 

對比WPF中兩種相機

  • PerspectiveCamera 能夠指定不一樣的投影及其屬性以更改觀察者查看三維模型的方式。
  • OrthographicCamera 指定三維模型到二維可視化圖面上的正投影與其餘照相機同樣,它指定位置、觀察方向和「向上」方向。 可是,與 PerspectiveCamera 不一樣的是,OrthographicCamera 描述了不包括透視收縮的投影。或者說OrthographicCamera 描述了一個側面平行的取景框,而不是側面聚集在場景中一點的取景框。

下圖演示使用PerspectiveCameraOrthographicCamera 查看同一模型時的不一樣效果。

 

42450b_figure2

 

燈光

和現實生活中同樣,若是沒有光咱們將什麼也看不到。所以咱們須要在咱們的場景中至少放置一盞燈來照亮咱們場景中的模型。

WPF中支持不一樣類型的光源,以下:

  • AmbientLight(環境光) 它所提供的環境光會照亮全部的對象,而不考慮對象的位置或方向。
  • DirectionalLight(平行光) 像遠處的光源那樣照亮(如太陽光)。將方向光的 Direction 指定爲 Vector3D,可是沒有爲方向光指定位置。
  • PointLight(點光源) 像近處的光源那樣照亮。 PointLight 具備一個位置並從該位置投射光。 場景中的對象是根據對象相對於光源的位置和距離而被照亮的。 PointLightBase 公開 Range 屬性,該屬性肯定一個距離,超過該距離後模型將沒法由光源照亮。 PointLight 還公開了多個衰減屬性,這些屬性肯定光源的亮度如何隨距離的增長而減少。 您能夠爲光源的衰減指定恆定、線性或二次內插算法。
  • SpotLight(聚光燈) 從 PointLight 繼承。 Spotlight 的照亮方式與 PointLight 相似,可是它既具備位置又具備方向。 它們在 InnerConeAngle 和 OuterConeAngle 屬性所設置的錐形區域(以度爲單位指定)中投射光。

下圖展現了各類光源的狀況:

lights

光源是 Model3D 對象,所以您能夠轉換光源對象並對光源屬性(包括位置、顏色、方向和範圍)進行動畫處理。

組合燈光的效果

  • Ambient color : Red
  • Difusse color : Red

emisive-ambient-specular-diffuse_3_m

 

3D模型

說了半天啦,怎麼主角還沒出現了 ??

對,全部的一切都服務於咱們的3D Model。

image

Model3D 是三維對象的抽象基類。若要生成三維場景,須要一些要查看的對象,並且構成場景圖的對象必須派生自 Model3D。 目前,WPF 支持用 GeometryModel3D 對幾何形狀進行建模。 此模型的 Geometry 屬性採用網格基元。

要生成模型,首先生成一個基元或網格。 三維基元是一系列構成單個三維實體的頂點。 大多數三維繫統都提供在最簡單的閉合圖(由三個頂點定義的三角形)上建模的基元。 因爲三角形的三個點在一個平面上,所以您能夠繼續添加三角形,以便對網格這樣較爲複雜的形狀建模。

WPF 三維繫統目前提供 MeshGeometry3D 類,使用該類能夠指定任何幾何形狀;它目前不支持預約義的三維基元(如球體和立方體)。 首先經過將三角形頂點的列表指定爲它的Positions 屬性來建立 MeshGeometry3D。 每一個頂點都指定爲 Point3D。 (在可擴展應用程序標記語言 (XAML) 中,將該屬性指定爲三個一組的數字列表,每組中的三個數字表示每一個頂點的座標)。根據網格的幾何形狀,網格可能會由多個三角形組成,其中的一些三角形共用相同的角(頂點)。 若要正確地繪製網格,WPF 須要有關哪些頂點由哪些三角形共用的信息。 能夠經過指定具備 TriangleIndices 屬性的三角形索引列表來提供此信息。 此列表指定在 Positions 列表中指定的點將按哪一種順序肯定三角形。

 

材質(Material )

咱們生活在多彩的世界中,也不能讓咱們的3D模型如此單調,這時咱們就用到了材質。

imageimage

在二維中,可使用 Brush 類來向屏幕中的區域應用顏色、圖案、漸變或其餘可視化內容。 可是,三維對象的外觀是照明模型的功能,而不僅是應用於它們的顏色或圖案。 實際對象的圖面質量不一樣,它們反射光的方式也會有所不一樣:光亮的圖面與粗糙或不光滑的圖面看上去不一樣,某些對象彷佛能夠吸取光,而某些對象彷佛可以發光。 您能夠向三維對象應用與應用於二維對象的徹底相同的畫筆,可是您不能直接應用它們。

Material 的具體子類用來肯定模型圖面的某些外觀特徵,每一個子類還提供一個能夠向其傳遞 SolidColorBrush、TileBrush 或 VisualBrush 的 Brush 屬性。

  • DiffuseMaterial 使用 DiffuseMaterial 與直接針對二維模型使用畫筆很是類似;模型表面不反射光,就好像是自發光同樣。使用 DiffuseMaterial 與直接針對二維模型使用畫筆很是類似;模型表面不反射光,就好像是自發光同樣
  • SpecularMaterial 能夠經過爲 SpecularPower 屬性指定一個值來設置系統將爲紋理的反射特質(或「發光」)建議的度數。
  • EmissiveMaterial  能夠指定將應用紋理,就好像模型所發出的光與畫筆的顏色相同。這不會使模型成爲光源;可是,它參與陰影設置的方式將不一樣於用 DiffuseMaterial 或 SpecularMaterial 設置紋理時的狀況。

 

42370_figure6

 

爲進一步提升性能,能夠從場景中精選 GeometryModel3D 的背面(因爲它們相對於照相機位於模型的背面,所以您將看不到這些面)。若要指定要應用於模型(如飛機)背面的Material,請設置模型的 BackMaterial 屬性。

爲了實現某些圖面質量(如發光或發射效果),您可能但願向模型連續應用幾個不一樣的畫筆。 可使用 MaterialGroup 類來應用和重用多個 Material。 MaterialGroup 的子級在多個呈現過程當中按照從頭至尾的順序來應用。

 

WPF中3D變換和動畫

RotatingTransTetra

變換

當您建立模型時,它們在場景中具備固定的位置。爲了在場景中移動、旋轉這些模型或者更改這些模型的大小而更改用來定義模型自己的頂點是不切實際的。 相反,您能夠像在二維模型同樣應用轉換。

每一個模型對象都有一個可用來對模型進行移動、重定向或調整大小的 Transform 屬性。 當您應用轉換時,其實是按照由Transform 屬性指定的向量或值來偏移模型的全部點。

也就是說變換了定義模型的座標系(「模型空間」)而模型所在的整個場景的座標系(「全局空間」)卻沒有改變,從而實現了3D模型的變換。

動畫

WPF 三維實現與二維圖形參與同一個計時和動畫系統。也就是說,要對三維場景進行動畫處理,也就是對其模型的屬性進行動畫處理。 能夠直接對基元的屬性進行動畫處理,可是一般很容易更改模型位置或外觀的變換進行動畫處理。 因爲能夠向 Model3DGroup 對象及其各個模型應用轉換,所以能夠向 Model3DGroup 中某個對象應用一組動畫,也能夠向這一組子對象應用一組動畫。 還能夠經過對場景的照明屬性進行動畫處理來實現各類可視化效果。 最後,您能夠選擇經過對照相機的位置或視野進行動畫處理來對投影自己進行動畫處理。

 

要對 WPF 中的對象進行動畫處理,能夠建立時間線、定義動畫(其實是隨着時間的推移而更改某個屬性值)並指定要向其應用動畫的屬性。 因爲三維場景中的全部對象都是Viewport3D 的子節點,所以要應用於場景的任何動畫所面向的屬性都是 Viewport3D 的屬性。

 

經常使用輔助類

  1. HelixToolkit
  2. 3DTool
  3. slimdx

實例

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

<UserControl x:Class="HostingWpfUserControlInWf.UserControl1"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    >

 

    <Grid>

 

      <!-- Place a Label control at the top of the view. -->

      <Label

                HorizontalAlignment="Center"

                TextBlock.TextAlignment="Center"

                FontSize="20"

                Foreground="Red"

                Content="Model: Cone"/>

 

      <!-- Viewport3D is the rendering surface. -->

      <Viewport3D Name="myViewport" >

 

        <!-- Add a camera. -->

        <Viewport3D.Camera>

          <PerspectiveCamera

                        FarPlaneDistance="20"

                        LookDirection="0,0,1"

                        UpDirection="0,1,0"

                        NearPlaneDistance="1"

                        Position="0,0,-3"

                        FieldOfView="45" />

        </Viewport3D.Camera>

 

        <!-- Add models. -->

        <Viewport3D.Children>

 

          <ModelVisual3D>

            <ModelVisual3D.Content>

 

              <Model3DGroup >

                <Model3DGroup.Children>

 

                  <!-- Lights, MeshGeometry3D and DiffuseMaterial objects are added to the ModelVisual3D. -->

                  <DirectionalLight Color="#FFFFFFFF" Direction="3,-4,5" />

 

                  <!-- Define a red cone. -->

                  <GeometryModel3D>

 

                    <GeometryModel3D.Geometry>

                      <MeshGeometry3D

    Positions="0.293893 -0.5 0.404509  0.475528 -0.5 0.154509  0 0.5 0  0.475528 -0.5 0.154509  0 0.5 0  0 0.5 0  0.475528 -0.5 0.154509  0.475528 -0.5 -0.154509  0 0.5 0  0.475528 -0.5 -0.154509  0 0.5 0  0 0.5 0  0.475528 -0.5 -0.154509  0.293893 -0.5 -0.404509  0 0.5 0  0.293893 -0.5 -0.404509  0 0.5 0  0 0.5 0  0.293893 -0.5 -0.404509  0 -0.5 -0.5  0 0.5 0  0 -0.5 -0.5  0 0.5 0  0 0.5 0  0 -0.5 -0.5  -0.293893 -0.5 -0.404509  0 0.5 0  -0.293893 -0.5 -0.404509  0 0.5 0  0 0.5 0  -0.293893 -0.5 -0.404509  -0.475528 -0.5 -0.154509  0 0.5 0  -0.475528 -0.5 -0.154509  0 0.5 0  0 0.5 0  -0.475528 -0.5 -0.154509  -0.475528 -0.5 0.154509  0 0.5 0  -0.475528 -0.5 0.154509  0 0.5 0  0 0.5 0  -0.475528 -0.5 0.154509  -0.293892 -0.5 0.404509  0 0.5 0  -0.293892 -0.5 0.404509  0 0.5 0  0 0.5 0  -0.293892 -0.5 0.404509  0 -0.5 0.5  0 0.5 0  0 -0.5 0.5  0 0.5 0  0 0.5 0  0 -0.5 0.5  0.293893 -0.5 0.404509  0 0.5 0  0.293893 -0.5 0.404509  0 0.5 0  0 0.5 0  "

    Normals="0.7236065,0.4472139,0.5257313  0.2763934,0.4472138,0.8506507  0.5308242,0.4294462,0.7306172  0.2763934,0.4472138,0.8506507  0,0.4294458,0.9030925  0.5308242,0.4294462,0.7306172  0.2763934,0.4472138,0.8506507  -0.2763934,0.4472138,0.8506507  0,0.4294458,0.9030925  -0.2763934,0.4472138,0.8506507  -0.5308242,0.4294462,0.7306172  0,0.4294458,0.9030925  -0.2763934,0.4472138,0.8506507  -0.7236065,0.4472139,0.5257313  -0.5308242,0.4294462,0.7306172  -0.7236065,0.4472139,0.5257313  -0.858892,0.429446,0.279071  -0.5308242,0.4294462,0.7306172  -0.7236065,0.4472139,0.5257313  -0.8944269,0.4472139,0  -0.858892,0.429446,0.279071  -0.8944269,0.4472139,0  -0.858892,0.429446,-0.279071  -0.858892,0.429446,0.279071  -0.8944269,0.4472139,0  -0.7236065,0.4472139,-0.5257313  -0.858892,0.429446,-0.279071  -0.7236065,0.4472139,-0.5257313  -0.5308242,0.4294462,-0.7306172  -0.858892,0.429446,-0.279071  -0.7236065,0.4472139,-0.5257313  -0.2763934,0.4472138,-0.8506507  -0.5308242,0.4294462,-0.7306172  -0.2763934,0.4472138,-0.8506507  0,0.4294458,-0.9030925  -0.5308242,0.4294462,-0.7306172  -0.2763934,0.4472138,-0.8506507  0.2763934,0.4472138,-0.8506507  0,0.4294458,-0.9030925  0.2763934,0.4472138,-0.8506507  0.5308249,0.4294459,-0.7306169  0,0.4294458,-0.9030925  0.2763934,0.4472138,-0.8506507  0.7236068,0.4472141,-0.5257306  0.5308249,0.4294459,-0.7306169  0.7236068,0.4472141,-0.5257306  0.8588922,0.4294461,-0.27907  0.5308249,0.4294459,-0.7306169  0.7236068,0.4472141,-0.5257306  0.8944269,0.4472139,0  0.8588922,0.4294461,-0.27907  0.8944269,0.4472139,0  0.858892,0.429446,0.279071  0.8588922,0.4294461,-0.27907  0.8944269,0.4472139,0  0.7236065,0.4472139,0.5257313  0.858892,0.429446,0.279071  0.7236065,0.4472139,0.5257313  0.5308242,0.4294462,0.7306172  0.858892,0.429446,0.279071  "                   TriangleIndices="0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 " />

                    </GeometryModel3D.Geometry>

 

                    <GeometryModel3D.Material>

                      <DiffuseMaterial>

                        <DiffuseMaterial.Brush>

                          <SolidColorBrush

                            Color="Red"

                            Opacity="1.0"/>

                        </DiffuseMaterial.Brush>

                      </DiffuseMaterial>

                    </GeometryModel3D.Material>

 

                  </GeometryModel3D>

 

                </Model3DGroup.Children>

              </Model3DGroup>

 

            </ModelVisual3D.Content>

 

          </ModelVisual3D>

 

        </Viewport3D.Children>

 

      </Viewport3D>

    </Grid>

 

</UserControl>

 

 

Make a 3D cube with pictures on its sides with XAML and C# 源碼

howto_xaml_cube_sides

總結

3D開發首先要把三維座標系搞清楚,才能構建出想要的3D Model,才能把燈光合理的照在3D模型上(環境光除外)獲得不一樣的燈光效果,才能指定合適的相機(Camera)位置從而看到本身想要看到3D投影。

3D開發中全部的幾何體最終都是由一系列的三角形來組成的。因此在您吧三維座標系高清的前提下,您還須要考慮把您的3D模型分解成三角形。聽來就很繁瑣,幸運的是如今有一些輔助類幫助你們來處理這些三角形的分解,而您所作的就是提供關鍵點的座標系。

 

因爲WPF 3D 是基於Direct 3D,和WPF 2D同樣直接利用顯卡渲染的,而且默認開啓了全景反鋸齒(有個條件,須要你的顯卡支持 兼容WDDM-Compliant)。

 

3D開發和2D開發複雜了不少,考慮的東西多了很多。但爲了那更真實的,更炫酷的效果,這一切都值得您去學習。

 

祝各位在3D開發的旅途,一路愉快!

參考

WPF 3D Article, Tutorial with Chart Graphics C# Code

WPF-3D-Primer

Getting started with 3D in WPF

三維圖形概述

Rendering Transparent 3D Surfaces in WPF with C#

Ambient, diffuse, emissive and specular colors : some examples

VoreenVE 

相關文章
相關標籤/搜索