天天看點

Flash/Flex學習筆記(55):背面剔除與 3D 燈光

在這一篇的學習中,我将帶大家一起學習如何将背面(即看不見的面)删除掉,即所謂的“背面剔除”。

先做一些預備知識的鋪墊:立方體中每個面都有一個"外面"和"裡面"。外面即正對觀察者向外的這一面,裡面指朝向立方體内部的這一面。我們在3D程式設計裡,通常指的都是“外面”

Flash/Flex學習筆記(55):背面剔除與 3D 燈光

如上圖:這是立方體的前面,分解為0-1-2和0-2-3二個三角形(注意三個頂點的順序為"順時針"方向),當立方體的"前面"旋轉到"後面"所處位置時,三角形的頂點順序由“順時針”改變為“逆時針”。

言外之意:如果我們能判斷出某個三角形的頂點順序為“逆時針”時,這個三角形肯定處于背面,這時應該将它隐藏或不繪制。

是以,如果我們在建構立方體每個面的三角形時,都遵守上面的“三角形頂點順時針法則”,那麼上面的解決辦法應該就能滿足要求了,回顧一下立方體三角形數組的建構代碼:

建議大家去買一個立體魔方玩具,每個點按照上一篇裡的頂點數字拿筆标記起來,對比上面的代碼發現,這樣的代碼正好是遵守這一規則的,當然代碼不必完全跟這一樣,比如:

也可以寫成:

隻要滿足順時針規則即可.ok,已經成功了一半,如何判斷三角形處于背面?

在Triangle.cs中增加這個私有方法即可(我也不知道怎麼來的,反正這個函數确實管用,就當公式死記下來好了.)

最後一個小問題:在旋轉的過程中,三角形的三個頂點“z軸深度”(zPos值)都在變化,有可能出現某個三角形的頂點擋住了另外一個三角形的頂點。是以我們還得解決三角形的z軸排序問題,這裡有一個法則,可以把三個頂點中離觀察者最近的一個頂zPos值,認為是三角形的z軸深度,是以Triangle.cs中還得增加一個z軸屬性:depth,最終Triangle.cs的内容如下:

羅嗦了一堆,激動人心的時刻終于來了,原來的立方體示例代碼中,隻要增加一行代碼:

編譯運作,最終将得到一個僅2.7k的swf動畫,而且還帶有滑鼠互動的3D立方體,cool 吧!

其它示例修改後,效果如下:

3D光線:

這部分内容比較難了解(需要有一定的線性代數基礎),先上最終的效果圖(光源的位置在左頂點,z軸“-100”處--即flash動畫左上頂點距離螢幕垂直向外100的地方,需要一點想象力)

Flash/Flex學習筆記(55):背面剔除與 3D 燈光

如上圖,對于每個三角形必須先确定其“法向”向量norm,norm即為向量ab與向量bc的叉積。然後光源light本身也是一個向量,向量light與向量norm會形成一個夾角θ,θ的取值範圍在0~PI(即180度)之間,θ為180度時即為正面直射,θ為0度時即為背面照射(實際上小于等于90度時,已經照不到了),直射意味着三角形所在平面顔色應該正常顯示(最明亮),背面或照不到時,應該顔色變暗,接近黑色。

關于這個結論,可以先來看下面的示範:(光源的位置我設定為動畫中心,距離螢幕向外100px的位置,即正對着螢幕中心照射)

一步一步來,先定義Light向量類:

那麼,如果計算向量的矢量積,以及夾角呢?先給出數學公式:

叉積公式:

Flash/Flex學習筆記(55):背面剔除與 3D 燈光

夾角公式

Flash/Flex學習筆記(55):背面剔除與 3D 燈光

點積(也稱數量積或内積)公式

Flash/Flex學習筆記(55):背面剔除與 3D 燈光

ok,理論知識準備得差不多了,下面來改造Triangle三角形基類:

可以看到,我們幾乎把所有的處理工作都放在Triangle.cs中完成了,好好體會一下。這一切完成之後,主動畫中就能自動展現出3D光線的效果了麼?No,我們還沒給立方體添加光源呢!不過這個很容易,改一個地方即可:

注意打星号的部分,隻需要給三角形數組中的每個三角形指派同樣的光源執行個體即可,其它地方都不用動。

總算寫完了,累啊,這一章确實有些難度,想起了毛主席的經典語錄:“學好數理化,走遍天下都不怕!”

繼續閱讀