摘要:介紹了基于Vega平臺的虛擬現(xiàn)實系統(tǒng);GL Studio平臺的工作流程;針對GL Studio制作的儀表仿真模型不能在Vega場景中直接應(yīng)用的問題,分析了Vega和GL Studio的底層軟件開發(fā)原理;對GL Studio模型向Vega場景移植的幾項關(guān)鍵技術(shù)進(jìn)行了研究,解決了坐標(biāo)系差異、坐標(biāo)系基本單位轉(zhuǎn)換、模型載入以及場景中的模型操作等問題。
關(guān)鍵詞:Vega;GL Studio;視景仿真;虛擬座艙
0引言
虛擬現(xiàn)實技術(shù)的最初應(yīng)用是針對飛行員的飛行訓(xùn)練的,時至今日,利用虛擬現(xiàn)實技術(shù)來實現(xiàn)虛擬座艙仍是個熱門的話題。之所以如此,是因為飛機(jī)座艙系統(tǒng)復(fù)雜,利用單一的系統(tǒng)仿真軟件開發(fā)平臺進(jìn)行模擬往往會顧此失彼。就拿Vega來說,作為一款優(yōu)秀的視景驅(qū)動軟件平臺,利用它可以很好地對飛機(jī)及其座艙的3D環(huán)境進(jìn)行模擬仿真,然而,其自身提供的儀表仿真組件的功能相對較弱,儀表的模型建立要在沒有程序開發(fā)接口支持的Creator中完成,這對于飛機(jī)艙內(nèi)復(fù)雜儀表的全面仿真是不可能的。因而,對儀表的仿真多數(shù)人的目光還是要投向?qū)I(yè)的儀表仿真平臺GL Studio。但是純粹的GL Studio應(yīng)用又似乎有些單調(diào),對于飛機(jī)座艙環(huán)境及其飛行環(huán)境難以模擬,仿真過程往往缺乏沉浸式的真實感。因此,若能將GL Studio的儀表仿真模型載入到Vega場景中將會是多數(shù)人的理想選擇。然而,Vega本身對于GL Studio是不直接支持的,需要開發(fā)人員從底層將代碼植入。本文結(jié)合某型飛機(jī)虛擬座艙的實現(xiàn),對這一問題進(jìn)行研究解決。
1 Veqa簡介
Vega是MultiGen-Paradigm公司為視景仿真軟件開發(fā)提供的一套系統(tǒng)解決方案,它由LynX圖形界面、Vega API以及一些可選的功能模塊組成。
通過LynX及其提供的功能模塊,用戶只需對一些參數(shù)進(jìn)行簡單的設(shè)置,不需要編寫任何代碼就可實現(xiàn)視景仿真對象的構(gòu)造,創(chuàng)建對象屬性及其之間的關(guān)系,并可生成ADF(程序定義)文件供Vega API調(diào)用。
在Windows環(huán)境中,可以利用Vc++或其它軟件開發(fā)平臺通過調(diào)用Vega API,來實現(xiàn)對LynX中定義的場景對象的管理,進(jìn)而實現(xiàn)復(fù)雜的視景仿真系統(tǒng)開發(fā)。Vega API來源于SGI圖形工作站的OpenGL Performer,因此,其底層具有與OpenGL的完美接口,使開發(fā)者能夠根據(jù)不同需要,直接利用OpenGL開發(fā)出具有自身特色和功能的組件嵌入到Vega場景中。其開發(fā)流程如圖1所示。
本文就是采用對Vega底層API的調(diào)用來實現(xiàn)GL Studio模型向Vega場景的移植。
2 GL Studio簡介
GL Studio是DISTI公司為儀表仿真軟件開發(fā)提供的一套系統(tǒng)解決方案。用戶可以利用其圖形交互界面以所見即所得的方式來完成儀表面板的制作,通過其代碼編輯器來完成儀表內(nèi)部邏輯仿真。其代碼生成器能夠?qū)⒂脩舻闹谱鹘Y(jié)果自動生成c++和OpenGL源代碼,用戶既可以將其代碼進(jìn)行單獨(dú)編譯也可嵌入到其它程序中進(jìn)行編譯,從而避免了大量繁瑣的底層OpenGL開發(fā)細(xì)節(jié)。其邏輯結(jié)構(gòu)如圖2所示。
3 GL Studio向Vega移植的關(guān)鍵問題
將OpenGL實現(xiàn)的功能嵌入到Vega場景中,一般利用Vega的回調(diào)函數(shù)來實現(xiàn),而GL Studio對儀表的繪制也是通過OpenGL編程實現(xiàn)的,因此,GL Studio模型向Vega場景的移植自然也要通過回調(diào)函數(shù)來實現(xiàn)。但是,移植過程中有如下幾個問題要解決。
3.1 GL Studio與Vega坐標(biāo)系的差異問題
雖然GL Studio與Vega都是在OpenGL基礎(chǔ)上的應(yīng)用,使用的都是右手坐標(biāo)系,但是Vega的坐標(biāo)系與OpenGL的坐標(biāo)系又有所差別,如圖3所示。
從圖3中可以看出,Vega坐標(biāo)系是在OpenGL坐標(biāo)系的基礎(chǔ)上繞x軸逆時針旋轉(zhuǎn)90。得到的,因此,若要在Vega場景中繪制或添加GL Studio模型,首先要保存坐標(biāo)系的一致。這可以通過兩種途徑來實現(xiàn):
(1)在GL Studio環(huán)境中制作虛擬儀表時直接在XZ平面上繪制(這里所指的均是繪制二維儀表)。這樣,在移植過程中就不需要旋轉(zhuǎn)儀表模型,但是會給單獨(dú)調(diào)試虛擬儀表帶來不便。
(2)在GL Studio環(huán)境中制作虛擬儀表時仍在XY平面上繪制,只是在移植時要將儀表在原來基礎(chǔ)上繞x軸順時針旋轉(zhuǎn)90°。
本文中采用的是第二種方式。但是無論采用哪種方式,在將GL Studio模型放入Vega場景中之前,都要先保存Vega當(dāng)前的顯示狀態(tài),繪制完之后再恢復(fù)其顯示狀態(tài)。
3.2 GL Studio與Vega坐標(biāo)系中基本單位變換問題
在Vega中根據(jù)場景及模型的大小不同,坐標(biāo)所采用的基本單位可以是米、千米、英尺或英寸,而在GL Studio中制作虛擬儀表是以像素為基本單位的。因此在移植過程中存在著基本單位的轉(zhuǎn)換問題。
筆者經(jīng)過多次試驗發(fā)現(xiàn),GL Studio在移植過程中以Vega場景中的基本單位為基準(zhǔn)進(jìn)行l(wèi):l轉(zhuǎn)換,即若Vega中以米為基本單位,轉(zhuǎn)換后GL Studio的1像素即為Vega中的l米。那么,GL Studio模型在無縮放載入場景時,就會變得非常大,需要將其按要求進(jìn)行縮小。一般情況下GL Studio模型在載入場景時都要以現(xiàn)有的Creator模型為背景,因為GLStudio所模擬的往往是在Creator建模時難以完成的某些儀表面盤,因此,在進(jìn)行縮放時應(yīng)根據(jù)Creator模型某個面的大小來制定縮放比例。
3.3將GL Studio模型載入場景的問題
在將GL Studio模型載入Vega場景時,應(yīng)對其繪制過程進(jìn)行合理封裝。本文采用在Vega場景中首先利用MakeObj()函數(shù)動態(tài)構(gòu)建Object數(shù)據(jù)模型,然后將GL Studio模型作為一個Node節(jié)點(diǎn)添加到該Object,并為該節(jié)點(diǎn)增加回調(diào)函數(shù)Obj_CB()將其載入場景。具體代碼實現(xiàn)如下:
vgObject*MakeObj()
{vgObject*oglObj=NULL;
vgDataSet*dataset=NULL;//創(chuàng)建空的vgDataSet數(shù)據(jù)結(jié)構(gòu)
pfGroup*group=NULL;//創(chuàng)建空的Group節(jié)點(diǎn)
DfNode*node=NULL;
//該Node節(jié)點(diǎn)指向新創(chuàng)建Object的Node節(jié)點(diǎn)
dataset=vgNewDS():
group=pfNewGroup():
……
if(vgMakeDS(dataset,group,VGDS_GEOMETRY)
==VG_SUCCESS、
{oglObj=vgNewObj():
vgName(oglObj,“_oglobj”):
vgProp(oglObj,VGOBJ_CS,VGOBJ_DYNAMIC);
vgObjDS(oglObj.dataset);
//利用DataSet數(shù)據(jù)結(jié)構(gòu)創(chuàng)建新的Object
vgMakeObj(oglObj,VGOBJ_USE);
vgUpdate(oglObj):+
}
……
node=(#Node*)vgGetObjPfNode(oglObj):
……
pfNodeTravFuncs(node.PFTRAV_DRAW,Obj_CB,NULL);
//為新創(chuàng)建的Object增加回調(diào)函數(shù)pfNodeTmvData(node。PFTRAV_DRAW,NULL);return oglObj;
//返回新創(chuàng)建的Object地址指針
}
為創(chuàng)建的Object的Node節(jié)點(diǎn)增加的回調(diào)函數(shù)體:int obj_cB(onraverser*trav.void。data){pfPushState():
pfPushMatrix():
pfBasicState()://保存當(dāng)前場景狀態(tài)
GIsObj·>Draw()://GL Studio模型繪制過程
……
glFlush()://恢復(fù)保存的場景狀態(tài)
glPopARdb():
pfPopMatrix():
pfPopState();
return PFTRAV_CONT;
}
3.4 GL Studio模型在Vega場景中的交互問題
在將GL Studio模型移植到Vega場景之后,它并不能自動捕獲用戶的輸入事件,這是由GL Studio本身底層的消息管理機(jī)制決定的。因此,若要它能夠響應(yīng)窗口消息,就需要手動將消息發(fā)送給GL Studio模型,讓其處理。這里,我們在Windows窗體消息循環(huán)中增加了一個HandleEvent()函數(shù),讓其主動捕獲消息事件發(fā)給GL Studio模型處理。其函數(shù)體如下:
Void HandleEvent(int eventType,int eventSubtype.inl
buttonMask,UINT nFlags.CPoint point)
{MouseEvent eV://定義GL Studio環(huán)境下的鼠標(biāo)事件ev.eventType。eventType;
//將Windows消息轉(zhuǎn)化為GL Studio能夠識別的消息ev.eventSubtype=eventSubtype;eV.buttonMask=buttonMask;
GIs_O bj->handle(ev);//將消息發(fā)給GL Studio模型處理
}
4結(jié)束語
本文詳細(xì)介紹了用GL Studio制作的儀表模型向Vega場景移植過程中的一些關(guān)鍵問題及其解決方法,并對Vega和GLStudio的底層工作原理作了簡要介紹。所述方法解決了Vega場景中不能直接支持GL Studio虛擬儀表的問題,對于在Vega場景中復(fù)雜儀表的仿真有一定的參考和應(yīng)用價值。移植到Vega場景中某型飛機(jī)虛擬座艙面板的效果如圖4所示。
(注:本文中所涉及到的圖表、注解、公式等內(nèi)容請以PDF格式閱讀原文。)