三、 繪圖演算法
3.2 三維模型資訊萃取
3.2.2 去除隱蔽線
17) -(3 0.5
N N
1 • 2 > ⇒
3.2.2 去除隱蔽線
由圖 18 我們發現位於最右邊的輪廓線被其他物體遮擋,對觀察者而言是看不到的,
然而就基本定義的計算上是可見的,因此本節將說明如何處理該項問題。首先我們依基 本定義計算偵測出輪廓線與特徵線,並指定唯一的顏色值由 OpenGL 直接繪製成 ID 參 考影像[20](ID Reference Image)如圖 19 所示,並開啟 Z-Buffer 來解決物體遮擋問題,
另外我們將偵測出輪廓線與特徵線記錄起來,紀錄的內容包括:兩端點座標位置、兩端 點的二維平面投影值、輪廓線編號(唯一大於 128 的顏色值)及可能相鄰的輪廓線與特 徵線等資訊,我們稱之為線段(Segment)。
當所有的模型繪製完後,由後端的視框緩衝區中將 ID 參考影像讀至主記憶體,根 據所有先前紀錄的可見線段兩端點的二維平面投影值,逐一掃描 ID 參考影像作線段可 見確認,為避免電腦數值表示與運算產生的誤差,我們以 3x3 像素(Pixel)為掃描 ID 參考影像的範圍,對於可見線段的重疊與產生的小鋸齒現象,我們藉由實作毛筆筆觸時 的加以覆蓋來消除,然而重疊的筆觸部份更可表現出墨水較濃的效果。
圖 19 被選擇的棋子與場景的 ID 參考影像(為加快執行速度)
3.2.3 線段連結與產生控制點
作完上面的可見線段確認後,接著我們根據每一個可見線段的兩端點的二維平面投 影值,來搜尋 ID 參考影像,並以可見線段之間最大 45 度的夾角與最大 5x5 的像素,作 為 ID 參考影像的搜尋範圍,將找出的可能相鄰可見線段加以紀錄,最後我們再將每一 個可見線段與紀錄的相鄰可見線段連結成較長的線段。演算法如圖 20 所示:
連結成較長的線段後,接下來是產生控制點,我們應用的是 Cardinal Spline 如 3-18 式所示,Cardinal Spline 的優點是:以內插的方法產生曲線,並且會經過我們所指定的 控制點,其精確度高且較具彈性。我們以可見線段的端點作為 Cardinal Spline 的控制 點,並藉由調整 Cardinal Spline 的張量(Tensor)參數 t 以改變曲線的柔軟效果如圖 21 所示,最後我們再沿著曲線模擬毛筆水墨筆觸,以呈現水墨風格。
[ ]
3.3 白描技法模擬
我們於第一章介紹過,中國水墨人物白描技法有十八種之多,依線條之變化可分類 為無粗細變化(鐵絲描類)、有粗細變化(蘭葉描類)及快速減化筆線(減筆描類)等 三種,本節將說明我們模擬的無粗細變化的琴弦描、有粗細變化的柳葉描與棗核描及快 速減化筆線的減筆描與竹葉描,最後是前述的綜合技法模擬。
在白描技法的模擬上,主要是以線條的粗細變化來寫意的,因此我們以改變毛筆模 組中的壓力參數 p ,及配合連結的線段長度與毛筆模組的控制機制,模擬出中國水墨人 物白描技法的效果,說明如下:
1. 無粗細變化的琴弦描:此白描技法下垂時有如琴弦一般長而平行的線好幾條向同一 方向伸去,下筆時力量均勻而細勁,沒有明顯起伏波折。我們根據連結的線段長度,
設定不同的橢圓主軸與主副軸比率大小,及以固定的壓力值來模擬。
2. 有粗細變化的柳葉描與棗核描:柳葉描筆意比較柔軟,重撇後輕輕轉折如柳葉,我 們根據連結的線段長度,設定不同的橢圓主軸與主副軸比率大小,並以壓力值由 0Æ 1Æ 0 的變化來模擬,其中 0Æ1 與 1Æ0 的線段長度以亂數決定,使產生的效果不 致太過規律。棗核描用尖筆藏峰,頓挫如棗核,我們只對長度在 20Æ 40 之間的連 結線段作棗核描模擬,依據長度不同設定其橢圓的主軸與主副軸比率大小,及將該 線段分成若干等分,每等分以壓力值由 0Æ 1Æ 0 的急速變化模擬。]
3. 快速減化筆線的減筆描與竹葉描:兩著相似,比柳葉描更為粗短,像大筆撇竹葉一 般,線條較硬下筆後急速提筆,我們根據連結的線段長度,設定不同的橢圓主軸與 主副軸比率大小,並以壓力值由 1Æ 0 的急速變化模擬。我們以中鋒模擬減筆描,
而竹葉描則以側鋒模擬之。
4. 前述的綜合技法模擬:我們依連結的線段長度,分別依前述的柳葉描、棗核描與減 筆描模擬之。
四、 繪圖狀態機
我們知道在 NPR 的繪圖研究上,繪圖的速度是個重要關鍵因素,主要是因為輪廓 線會隨著視點改變而跟著需要重新計算,因此在傳統的繪圖機制上每重畫一次視框就得 重新計算一次,導致 CPU 的負載加重使得繪圖的速度變慢,通常維持在互動的速率上
(Interactive Rate),對於 NPR 的繪圖速度提昇上我們提出繪圖狀態機[25]的機制,企圖 用於提昇三維電腦遊戲引擎對輸出入裝置之反應速度,使畫面顯示與遊戲之操作得以更 加順暢。下面我們分別說明動畫繪圖狀態機、靜態繪圖狀態機與兩著的效果分析。
4.1 動畫繪圖狀態機
所謂的動畫繪圖狀態機,是針對動畫的場景做分類的,通常在動畫的場景中每次會 變動的物體為場景中較少部分,因此我們根據此項特性,將傳統的繪圖機制拆成四個狀 態分別是:全部繪製(並儲存影像)、先繪靜態部份(並儲存影像與深度值)再繪動畫 物件、回存靜態部份深度值再繪動畫物件與將儲存影像直接輸出至螢幕等四個不同繪圖 狀態,狀態的改變會依據系統目前所處的狀態及其變化情形,選擇下一個繪圖狀態來繪 圖,下面我們說明狀態圖、真值表與導出的邏輯式子,如圖 22、表 1 至表 4 及 4-1 式所 示:
1. 狀態圖
圖 22 動畫繪圖狀態圖
2. 真值表
其中 Qn表示目前狀態,Qn+1表示下個狀態。
表 1 動態狀態 A 的真值表
Qn x1 x0 Qn+1
A 0 0 D A 0 1 B A 1 0 A A 1 1 A
表 2 動態狀態 B 的真值表
Qn x1 x0 Qn+1
B 0 0 C B 0 1 C B 1 0 A B 1 1 A
A
D C
B
1 ∅ 0 1
1 ∅
0 0 1 ∅
0 0
0/1 0 ∅
0 ∅ 1 ∅或
x2 = 1
x
1x
0Initial
表 3 動態狀態 C 的真值表
表 6 靜態狀態 D 的真值表 服,就是除了回存靜態部份的深度值(Depth value)於 Z-Buffer,仍需於繪製完動畫物 件後,再掃描 Z-Buffer 中的值是否被改變,若被改變則表示該點的靜態影像需為該點的 動態影像所取代,這將造成 CPU 額外的負擔,因此進入此狀態時系統的繪圖速度約比 傳統每次重畫的方式提昇 1 到 2 個視框(Frame),我們也藉由系統經常回到 D 狀態的優 勢(約 59FPS),使動畫場景的平均速率大於 11FPS、靜態場景的平均速率大於 20FPS,
來提昇系統對輸出入裝置之反應速度,以符合電腦遊戲對速度的要求。
然而另一項的負擔是在我們的場景模擬毛筆水墨筆觸後,因為模擬的筆觸範圍比 OpenGL 繪圖的線條寬度還寬,以致回存的深度值無法含蓋模型邊緣外的筆觸如圖 24 所示,為保留原有的毛筆水墨筆觸效果則需額外的負擔,因此造成動畫狀態機的 C 狀態
繪圖速度與傳統每次重畫的繪圖速度相當,這是我們當初始料未及的,但此動畫繪圖狀 態機仍可應用於 PR 的複雜場景繪圖上。
(a)模型邊緣外的筆觸被覆蓋
圖 24(b)保留模型邊緣外的筆觸 被覆蓋部份
保留
五、 電腦象棋
5.1 簡介
象棋是中國流傳已久的智力比賽遊戲,端賴下棋者所能思考的步數程度,與實際經 驗方能贏得比賽,電腦人工智慧(Artificial Intelligence)[9]發展以來電腦下棋此一研究 領域一直是印證人工智慧理論與應用的項目[37]。一般來說,在製作電腦象棋程式時通 常會劃分成開局、中盤、殘局三個階段,其演算法也會有所不同,開局階段可以資料庫 儲存開局棋譜,下棋時就由資料庫查詢得知下一步棋要怎麼走,當然啦不可能儲存無限 多個棋譜,因此當局勢發展超出資料庫所存範圍後,就進入了中盤階段。
如果要求的棋力不高,或是初次製作電腦象棋,可將中盤和殘局合併,使用同樣的 演算法,一般來說程式中一定會有個評估函數和一個遊戲樹(是一個 Min-Max Tree),
為電腦象棋的核心所在,棋力的高低決定於此,然而評估函數會搜尋遊戲樹,並計算出 估計值以決定下一步棋的走法,當進入殘局階段,因為象棋的殘局有許多特例,通常電 腦象棋也會特別為這些特例建立一個殘局資料庫和特殊的演算法,在實作上我們採用共 創軟體聯盟 CChessUG 所開發的的電腦象棋程式,因為他們的程式模組很容易了解與 應用,只需稍加修改即可符合我們的系統需求。
5.2 人工智慧演算法
我們知道電腦象棋之所以會思考主要是依賴核心的評估函數,而評估函數主要的功 用在於評估盤面的敵我情勢,透過評估值可以判斷目前的局勢消長,以決定下一步棋的 走法,其中影響評估函數的估計結果,主要有下列三項:
1. 棋子的價值
棋子的價值是評估局勢最簡單的方法,高手讓對手雙馬或一車來平衡雙方的棋力,
就是最好的說明,我們可以看看前人怎麼來設計,應該特別注意的是,象棋的規則勝負 在於看誰先吃掉對方的主帥,所以將(帥)的重要性最大但他的價值並不高,我們引用的 人工智慧程式其棋子的價值如下所示:
// 將 士 象 馬 車 炮 兵
const base[7] = {300 ,300 ,300 ,500 , 850 ,500 ,300}; //平均價值
const range[7] = { 0 , 0, 0, 20, 10, 0 , 40}; //價值的變動範圍 const int BV1[7] = { //計算基本價值
base[0]-base[0]*range[0]/100, base[1]-base[1]*range[1]/100, base[3]-base[2]*range[2]/100, base[3]-base[3]*range[3]/100, base[4]-base[4]*range[4]/100, base[5]-base[5]*range[5]/100, base[6]-base[6]*range[6]/100 };
2. 棋子的棋盤位置價值
在象棋的開局裡,比賽雙方通常會儘速的將車馬包移到重要位置上,尤其是車一定 要搶住重要的線,可見棋盤位置對局勢的影響。在為位置評分時,可以為每個不同的棋 子設計一個二維陣列,用以記錄棋盤上每一個位置的重要性,下面是兵(卒)在棋盤位 置的價值設定例子。
//兵卒在不同位置的價值,數位越大價值越高 const int ManBPlus[2][12][11]={
{{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, { 0, 1, 2, 3, 4, 4, 4, 3, 2, 1, 0}, { 0, 1, 2, 3, 4, 4, 4, 3, 2, 1, 0}, { 0, 1, 2, 3, 3, 3, 3, 3, 2, 1, 0}, { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0}, { 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0}, { 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0}, { 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0}, { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0}, { 0, 1, 2, 3, 3, 3, 3, 3, 2, 1, 0}, { 0, 1, 2, 3, 4, 4, 4, 3, 2, 1, 0}, { 0, 1, 2, 3, 4, 4, 4, 3, 2, 1, 0}, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} } };
3. 棋子在棋盤位置上的靈活度
在棋盤裡,每一種棋子都有它自己的走法與可走的範圍,如果在下棋的過程中,讓
在棋盤裡,每一種棋子都有它自己的走法與可走的範圍,如果在下棋的過程中,讓