涂瑤瑤,徐承志,梅 超
(湖北工業(yè)大學計算機學院,湖北 武漢430068)
Virtools是一套具備豐富的互動行為模塊的實時3D環(huán)境虛擬實境編輯軟件,其提供了500多個Building Blocks(BB)行為交互模塊可供使用,特點是方便操作,應(yīng)用領(lǐng)域廣泛[1]。可以讓沒有任何編程基礎(chǔ)的開發(fā)者在一個可視化圖形開發(fā)界面中拖放BB,使得各種格式的資源整合在一起,如3D模型、2D圖形、音頻或者視頻等[2],從而制作出各種用途的3D互動多媒體產(chǎn)品,例如虛擬裝配、仿真訓練、網(wǎng)上游戲等諸多3D軟件。正是由于該軟件的簡易性,對開發(fā)者的編程素養(yǎng)要求不高,可能導致開發(fā)者陷入代碼贅余的問題中。這些贅余的代碼,既增加了開發(fā)人員的負擔,又不便于系統(tǒng)后期維護。而對這些贅余代碼進行封裝和管理能大大提高團隊開發(fā)效率。
本文作者參與國家級大學生創(chuàng)新創(chuàng)業(yè)項目——“基于虛擬校園的軟件生態(tài)系統(tǒng)研究”,項目開發(fā)過程中出現(xiàn)大量重復操作,例如上百次對相機進行操作[3],其中包括相機的旋轉(zhuǎn)、平移、拉伸等。根據(jù)項目開發(fā)經(jīng)驗,筆者利用BG+Array解決了項目中virtools腳本重復代碼過多,不易維護的問題。
Behavior Building Blocks(BB)是用來執(zhí)行特定動作的可視化功能模塊[4],BB的輸入分為流程輸入bIn(Behavior Input)和參數(shù)輸入pIn(Parameter Input),輸出分為流程輸出bOut(Behavior Output)和參數(shù)輸出pOut(Parameter Output)(圖1)。
圖1 BB的輸入輸出
根據(jù)運行方式的不同,BB有三種類型:
1)On/Off 一旦On被觸發(fā),BB就持續(xù)執(zhí)行,直到Off被觸發(fā)才會停止運作(圖2a)。
圖2 BB的運行方式
2)In/Out 一旦In被觸發(fā)就執(zhí)行BB的功能,完成后會觸發(fā)Out并停止運作(圖2b)。
3)Loop In/Loop Out 一旦In被觸發(fā)BB就開始運作,隨即在Loop Out和Loop In間執(zhí)行外部回圈,直到完成BB設(shè)定的某個條件才會觸發(fā)Out并停止運作。而對BB的停止條件設(shè)定可在BB參數(shù)的設(shè)置中完成,如圖2中的(c)。
Virtools可以利用拖放BB的方式,使用Link-Delay[5]線將BB連接起來,賦予在適當?shù)腛bject(對象)或者Character(虛擬角色)上,以類似流程圖的方式,決定BB行為交互模塊的前后處理順序,從而實現(xiàn)可視化的交互腳本設(shè)計。腳本圖類似于傳統(tǒng)的代碼程序,特別是程序的三個基本結(jié)構(gòu)可以完全用腳本圖來實現(xiàn)。
如圖3所示,程序先執(zhí)行”Rotate”BB,后執(zhí)行”Translate”BB。
圖3 順序結(jié)構(gòu)
如圖4所示,程序先執(zhí)行”Test”BB,Test BB判斷為真則執(zhí)行Rotate BB,為假則執(zhí)行Translate BB。
圖4 選擇結(jié)構(gòu)
如圖5所示,程序先執(zhí)行”Counter”BB,Counter BB有三個輸入?yún)?shù),第一個是程序循環(huán)的次數(shù),第二個是變量的初始值,第三個是變量的遞增(減)值,若循環(huán)次數(shù)不滿足設(shè)定值,則執(zhí)行Rotate BB,循環(huán)次數(shù)加1,變量加上遞增(減)值,否則執(zhí)行Translate BB。
圖5 循環(huán)結(jié)構(gòu)
將多種BB組合封裝起來,就可以形成一個具有某項功能的行為模組,即BG(Behavior Graph)。BG是Virtools里面的一大特色,利用BG可以將一個或多個BB(也可以是BG)進行二次封裝,或多次封裝。如果將BB比作傳統(tǒng)程序里面的函數(shù),那么BG就相當于是傳統(tǒng)程序里面函數(shù)的嵌套調(diào)用。BG與BB對外接口形式是一樣的,輸入?yún)?shù)分為bIn,pIn,輸出參數(shù)分為bOut,pOut。BB和BG可以相互嵌套使用(圖6)。
圖6 BG的嵌套使用
Array即陣列,可用于建立數(shù)據(jù)、事件變量的集中存放管理等等,由Column(列)與Row(行)組成[6],Array里面每列就是一個字段,每行存儲的數(shù)據(jù)就是一個記錄,Array還可以與數(shù)據(jù)庫里面的表進行數(shù)據(jù)交換,在訪問一些簡單的輕量數(shù)據(jù)時,使用Array十分方便,Array的結(jié)構(gòu)見圖7。
圖7 Array的構(gòu)造
鑒于BG和Array在Virtools中有上述這些性質(zhì),可以使用BG+Array這種組合在Virtools的程序開發(fā)中實現(xiàn)功能重復的代碼整合。即使用BG將行為邏輯進行二次封裝,使用Array存取動畫中不同的行為參數(shù),通過參數(shù)解析和動作驅(qū)動模塊遍歷Array中的行為參數(shù),就可能產(chǎn)生多組操作相同但效果不同的動畫。BG+Array組合的功能等效圖見圖8。
圖8 BG+Array功能等效圖
2.1.1 設(shè)計動作模板,并封裝成BG 對一組動畫進行動作分類,同類的動作就是程序重復執(zhí)行的功能模塊,即動作模板,這些動作模板通過接收不同的行為參數(shù),產(chǎn)生不同的效果,將這些動作模板封裝成BG。
2.1.2 構(gòu)建BG中的接口 BG中的接口,就是上一步中驅(qū)動模板的行為參數(shù),將這些行為參數(shù)的標記拖放到BG的邊界,構(gòu)成BG的輸入?yún)?shù)接口。
2.1.3 建立參數(shù)陣列 創(chuàng)建一個Array,并在Array中創(chuàng)建與BG輸入?yún)?shù)類型一致的字段,再根據(jù)具體的要求,在參數(shù)陣列中保存相應(yīng)的參數(shù)值。
2.1.4 遍歷Array 建立循環(huán)結(jié)構(gòu),遍歷Array里面存儲的記錄,并將記錄中的參數(shù)解析出來依次傳遞給動作驅(qū)動模板。
至此,通過BG+Array的組合實現(xiàn)相同代碼調(diào)用不同參數(shù)來完成一連串的不同動作的功能就實現(xiàn)了。
下面通過一個例子來說明如何在Virtools里面具體運用BG+Array的組合。在“虛擬校園”項目里面經(jīng)常要針對某棟建筑進行頻繁的鏡頭變換操作,這些鏡頭變換大致可以歸納為移動相機、旋轉(zhuǎn)相機、拉伸相機操作,以上三種操作即為相機操作的三大類,可以按照上面提到的步驟構(gòu)造出一個BG+Array的組合。
2.2.1 構(gòu)建動作模板,并封裝成BG 攝像機操作的三個主要動作模板分別為:旋轉(zhuǎn)相機、移動相機以及拉伸相機。
構(gòu)造的BG如圖9至圖11所示,其中”Bezier Progression”BB的作用是在一定的時間內(nèi)讓一個變量按照指定的貝塞爾函數(shù)[7]進行變化,圖9中Multiplication BB接收 Bezier Progression BB傳進的值,并乘以指定的一個角度,將得到的值賦給Rotate Around BB,Rotate Around BB按照這個值進行相機旋轉(zhuǎn),所以這一組BB的作用就是在一定的時間內(nèi)(由Bezier Progression BB決定)將相機旋轉(zhuǎn)一定的角度(由Multiplication BB決定)。
圖9 旋轉(zhuǎn)相機
圖10 中 Multiplication BB 接 收 Bezier Pro-gression BB傳進的值,并乘以一個指定的向量,將得到的值賦給 Translate BB,Translate BB按照這個值來操作相機進行移動。
圖10 移動相機
圖11 中 Multiplication BB 接 收 Bezier Progression BB傳進的值,并乘以一個指定的向量,將得到的值賦給Set FOV BB,Set FOV BB按照這個值對相機進行拉伸動作。
圖11 拉伸相機
2.2.2 構(gòu)建BG接口 提取行為參數(shù)后的BG如圖12所示。
圖12 提取行為參數(shù)后的BG
將BG中的行為參數(shù)提取出來,并拖放到BG的邊界,由于BG可以相互嵌套使用,所以內(nèi)層BG也可以像BB一樣,將內(nèi)層BG的運行參數(shù)的標記拖放到外層BG的邊界,作為外層BG的輸入?yún)?shù)。當一個BG中包含幾個小的BG時,即一個大的功能模塊中包含幾個小的功能模塊,可以考慮使用”Binary Switch”BB(二進制開關(guān))來控制是否啟動這幾個小的功能模塊。
圖12中第一個Binary Switch控制Camera Rotate(相機旋轉(zhuǎn)),如果Binary Switch接收到的參數(shù)為True,則程序會從True出口(圖12中Binary Switch連接Camera Rotate的出口)出發(fā),并運行Camera Rotate這個BG,否則程序會從False出口(圖12中Binary Switch連接第二個Binary Switch的出口)出發(fā),并直接運行第二個Binary Switch。同理第二個Binary Switch控制Camera Move(相機移動),第三個Binary Switch控制Camera FOV(相機拉伸),這些Binary Switch只有在接收到輸入?yún)?shù)為True時才會執(zhí)行其對應(yīng)的功能模塊,否則程序會跳轉(zhuǎn)到下一個功能模塊去執(zhí)行。通常使用這個BG時,可能只需要使用這個BG中的部分功能模塊,如果不用開關(guān)進行控制,那么程序就會運行這個BG中的所有功能模塊,勢必造成許多資源浪費,所以,巧用開關(guān)也是節(jié)約系統(tǒng)資源的一個小技巧。
2.2.3 建立參數(shù)陣列 創(chuàng)建好后的Array屬性如表1所示。
表1 Array
2.2.4 遍歷Array 程序整體流程如圖13所示。
圖13 程序整體流程圖
圖13 中的Camera Operation是圖12中將行為參數(shù)提取出來后的BG,使用”Iterator”BB來遍歷Array,并將取出的記錄賦給BG,BG通過接收Array里面存儲的記錄,運行BG里面的功能模塊,程序就會按照BG里面的功能模塊來執(zhí)行并顯示相應(yīng)的動作效果了。
至此,使用BG+Array的組合,便將攝像機的操作整合起來了,以后凡涉及到對攝像機的操作,只需要修改Array里面的行為參數(shù)便可以直接使用此BG+Array的組合了。
BG+Array組合不僅適用于對相機的操作,在機械拆裝上也同樣適用。機械拆裝的操作和相機類似,有移動零件、旋轉(zhuǎn)零件以及縮放零件等,通過BG+Array組合,將這些操作進行模塊化的整合,便于系統(tǒng)的開發(fā)和后期維護。
總體來說,BG+Array的優(yōu)點有如下三點:
1)代碼量少 這里說的代碼量少并不意味著減少了代碼的數(shù)量,而是說將代碼整合起來,便于閱讀與理解,將原來復雜龐大的代碼用BG整合起來,使得每個功能都很清楚,也方便維護。
2)便于程序調(diào)試與維護 每個BG都實現(xiàn)了特定的功能,而將它需要的參數(shù)提取出來,并存在Array里面,這樣只需要對Array里面的數(shù)據(jù)進行修改,就可以通過BG+Array這種組合實現(xiàn)行為邏輯與動作參數(shù)的解耦,便于日后的調(diào)試與維護。
3)代碼共享 代碼封裝不僅僅是讓自己編程簡單,最主要的是要實現(xiàn)代碼的共享,這種將業(yè)務(wù)邏輯高度抽象的方法是代碼封裝的先決條件。同時,使用BG這種模式,將一些常用的BB組合起來,封裝為常用的功能模塊,更利于給其他人共享使用。
介紹了BG+Array這種組合在Virtools里面的運用,合理利用這種組合,可以減少程序中很多冗余的代碼,大大提高系統(tǒng)開發(fā)的效率,同時也可以提高代碼的復用率,為開發(fā)高質(zhì)量的系統(tǒng)帶來很多便利。本文只是介紹了Virtools中代碼封裝的一部分技巧,同時BG+Array這種組合還有很大的改進空間,例如可以將這種組合與數(shù)據(jù)庫操作結(jié)合起來,通過數(shù)據(jù)庫驅(qū)動BG+Array組合,從數(shù)據(jù)庫中讀取數(shù)據(jù)并操作對象進行運動。
[1] 陳玉川,王麗娟,胡青泥,等.基于Virtools機械加工實驗系統(tǒng)的研究[C].第三屆東北、華北8省區(qū)市工程圖學學術(shù)研討會論文集.2010:156-159.
[2] 劉明昆.三維游戲設(shè)計[M].成都:四川出版集團,四川電子音像出版中心,2005.
[3] 楊 琳,朱元昌,邸彥強,等.基于Virtools的光電經(jīng)緯儀成像系統(tǒng)仿真[J].彈箭與制導學報,2012(05):193-195,198.
[4] 梁冠輝,朱元昌,邸彥強,等.基于 HLA/Virtools的高炮火控系統(tǒng)仿真平臺設(shè)計[J].系統(tǒng)仿真學報,2009,21(21):6 954-6 958,6 963.
[5] 王 欣,賀建飚.精確同步Markov測試幀的研究與設(shè)計[J].信息化縱橫,2009(06):33-35.
[6] 劉明昆.三維游戲設(shè)計師寶典——Virtools游戲開發(fā)工具篇[M].四川:四川電子音像出版中心,2005.
[7] 伍 剛.貝塞爾函數(shù)的計算機仿真研究[J].攀枝花學院學報,2013,30(06):105-107.