1. 程式人生 > >【WPF】用三角形網格構建三維圖形

【WPF】用三角形網格構建三維圖形

遊戲 輸入 angle 結構 dash bsp 來看 適應 鼠標

雖然WPF只能支持部分三維模型,不過從應用功能開發的角度看,也已經夠用了(非遊戲開發)。WPF 的三維圖形,說得簡單一點,也就兩種而已。

1、把二維對象放到三維空間中,這個應該較為好辦,像 Image 控件,Shape 類型等,或者我們常用的一些控件,都可以放進三維空間中,用這種方式構建模型可能更為實用,也好弄(至少不借助專門的建模工具的前提下)。

2、完全利用坐標建模。實際上是用 N 個三角形來組合成三維模型。

雖然你會看到基類型 Visual3D 派生出了好幾個類型,但總體上說也就劃分為上述兩類。Viewport2DVisual3D 類就是專門把二維對象放入三維空間中的,而 ModelVisual3D 和 UIElement3D 差不多,不同的是,UIElement3D 可以捕捉用戶輸入行為,如鼠標鍵盤觸控等,如果你的三維模型要與用戶交互,那麽你可以選用這個類。

本文老周重點介紹第二種建模方法,就是用三角形來組建。為啥要用三角形呢?我們以前都學過幾何,你想想,要多少個點才能確定一個面?是三個吧。兩個點只能確定一條線,一個點就算了,那是無限射線。正是如此,所以三維圖形中的所謂面,至少得要三個點才能確定下來,所以,要使用三角形來作為圖形基元。

在介紹三角形坐標設置之前,老周先用廢話來各大夥補充一點東東。

在WPF中承載三維模型是這樣的:首先,你應該聲明一個 Viewport3D 對象,它包含我們要建立的模型,前些天,老周寫過一篇文章,介紹過三維型中的照相機,就是 Viewport3D 的 Camera 屬性,你必須設置一個照相機,這樣才能看到三維模型中的東西,它好比我們透過實體相機的取景器來觀察客觀事物,具體可以點這裏查看。

之後呢,Viewport3D會包含一個子元素集合,每個元素必須是 Visual3D 的子類,由於是集合,你可以在其中添加 N 個。

用坐標來構建模型,應當用 ModelVisual3D 類,這個類很好玩,它自身又公開一個集合,可以再添加 ModelVisual3D 對象。也就是說,ModelVisual3D 對象是可以像樹形結構一樣嵌套,這樣做可以方便你建立復雜的三維圖形,並且可以有效分組。很多人會覺得,WPF 的三維模型很復雜很難懂,除了三維空間本身的復雜性外,估計可能是因為這種可視化元素之間的可嵌套性,剛開始接觸時容易頭暈。不過不用害怕,這世界上沒有誰天生就會的,不要急,學習的時候,不要建太復雜的模型,這樣思路也容易適應,只要你熟悉了就很輕松了,再復雜的東西,也是由各種簡單的元素構成的。

ModelVisual3D 類有個Content屬性,這個才是真正用來設置模型坐標的,它的類型是Model3D,它是個抽象類,它的派生類有兩大塊:一是GeometryModel3D,用來定義構成三維圖形的坐標點;再者就是Light,表示用於照亮三維模型的燈光,因為三維圖形是模擬現實中的事物的,所以會考慮到燈光照射的問題,它的實現類型有比如環境光(AmbientLight),這個像我們房間裏的大燈,它可以照亮屋內所有角落;方向光(DirectionalLight),像手電筒的光吧,具有照射方向……

在GeometryModel3D類,也公開了三個屬性:

Geometry:設置三維圖形的坐標點集合,不僅只有點,還有索引、法向量、紋理映射等。

Material:圖形正面的材質,就像金屬表面,反射鏡面類似的效果。

BackMaterial:有正面就會有背面,這是指圖形背面的材質。

下面就是建立模型的重點了,即 Geometry屬性,WPF 框架只公開了一個實現類——MeshGeometry3D,就是使用三角形網絡來建立物體的表面。其中也有三個屬性比要重要。

Positions:這個很重要,組成圖形表面的各個坐標點的集合。

TriangleIndices:這個也很重要,它是一組整數集,從0開始,就是指定哪三個點組成一個三角形。

TextureCoordinates:紋理映射。之個有點像你把某妹子的照片貼在一塊玻璃上,照片相當於紋理,經的每個點與玻璃的對應關系。比如,通常,我們會把照片的左上角的點對準玻璃左上角的點,右上角的點對準玻璃右上角的點。如果把照片左上角的點對準玻璃右下角的點,照片左上角的點對準玻璃左下角的點,這樣貼出來的照片就是倒過來的。

Normals:構成圖形的各個坐標點的法向量,默認全是 0,0,1。這個東西還真不知道怎麽解釋,一般我們可以不指定,用默認值就可以,大概是指面與面之間的關系吧。

咱們來看看演示吧。

                        <GeometryModel3D>
                            <GeometryModel3D.Geometry>
                                <MeshGeometry3D Positions="-2,2,0 3,-2,2 5,3,3 7,1,-2" TriangleIndices="0,1,2,1,3,2" TextureCoordinates="0,0 1,0 1,0 1,1" Normals="0,0,1 0,0,1 0,0,1 0,0,1"/>
                            </GeometryModel3D.Geometry>
                            <GeometryModel3D.Material>
                                <DiffuseMaterial>
                                    <DiffuseMaterial.Brush>
                                        ……
                                    </DiffuseMaterial.Brush>
                                </DiffuseMaterial>
                            </GeometryModel3D.Material>
                        </GeometryModel3D>

上面代碼中,定義了四個坐標點,註意 TriangleIndices 屬性的值,它有六個值,表明這四個點可以構成兩個三角形。即它有兩個面組成。

0-1-2 表示第一個點,第二個點和第三個點,這三個點構成了一個三角形。就像這樣。

技術分享

然後是 1-3-2,即第二個點,第四個點,第三個點又組成了一個三角型。

技術分享

大夥要註意一個法則—— 組成三角形的點,如果是按逆時針排序的(就像上面例子),表示的是物體的正面;如果是順時針的,表示的則是物體的反面。

再比如,咱們再寫成這樣,這回有五個點。

<MeshGeometry3D Positions="0,3,0 -3,-2,0 -1,-3,1 1,-3,1 3,-2,0" TriangleIndices="0,1,2,0,2,3,0,3,4" TextureCoordinates="0,0 1,1 1,1 1,1 1,1" />

第一個點在頂部,其余四個在下方,構成三個三角形。

技術分享

好了,由於劇組嚴重缺乏資金,老周今天只能說到這裏了。為了弄到更多資金來寫後面的文章,老周要去玩《狂野撞車》來賺現金。

【WPF】用三角形網格構建三維圖形