摘要:介紹了基于Vega平臺的虛擬現實系統;GL Studio平臺的工作流程;針對GL Studio制作的儀表仿真模型不能在Vega場景中直接應用的問題,分析了Vega和GL Studio的底層軟件開發原理;對GL Studio模型向Vega場景移植的幾項關鍵技術進行了研究,解決了坐標系差異、坐標系基本單位轉換、模型載入以及場景中的模型操作等問題。
關鍵詞:Vega;GL Studio;視景仿真;虛擬座艙
0引言
虛擬現實技術的最初應用是針對飛行員的飛行訓練的,時至今日,利用虛擬現實技術來實現虛擬座艙仍是個熱門的話題。之所以如此,是因為飛機座艙系統復雜,利用單一的系統仿真軟件開發平臺進行模擬往往會顧此失彼。就拿Vega來說,作為一款優秀的視景驅動軟件平臺,利用它可以很好地對飛機及其座艙的3D環境進行模擬仿真,然而,其自身提供的儀表仿真組件的功能相對較弱,儀表的模型建立要在沒有程序開發接口支持的Creator中完成,這對于飛機艙內復雜儀表的全面仿真是不可能的。因而,對儀表的仿真多數人的目光還是要投向專業的儀表仿真平臺GL Studio。但是純粹的GL Studio應用又似乎有些單調,對于飛機座艙環境及其飛行環境難以模擬,仿真過程往往缺乏沉浸式的真實感。因此,若能將GL Studio的儀表仿真模型載入到Vega場景中將會是多數人的理想選擇。然而,Vega本身對于GL Studio是不直接支持的,需要開發人員從底層將代碼植入。本文結合某型飛機虛擬座艙的實現,對這一問題進行研究解決。
1 Veqa簡介
Vega是MultiGen-Paradigm公司為視景仿真軟件開發提供的一套系統解決方案,它由LynX圖形界面、Vega API以及一些可選的功能模塊組成。
通過LynX及其提供的功能模塊,用戶只需對一些參數進行簡單的設置,不需要編寫任何代碼就可實現視景仿真對象的構造,創建對象屬性及其之間的關系,并可生成ADF(程序定義)文件供Vega API調用。
在Windows環境中,可以利用Vc++或其它軟件開發平臺通過調用Vega API,來實現對LynX中定義的場景對象的管理,進而實現復雜的視景仿真系統開發。Vega API來源于SGI圖形工作站的OpenGL Performer,因此,其底層具有與OpenGL的完美接口,使開發者能夠根據不同需要,直接利用OpenGL開發出具有自身特色和功能的組件嵌入到Vega場景中。其開發流程如圖1所示。
本文就是采用對Vega底層API的調用來實現GL Studio模型向Vega場景的移植。
2 GL Studio簡介
GL Studio是DISTI公司為儀表仿真軟件開發提供的一套系統解決方案。用戶可以利用其圖形交互界面以所見即所得的方式來完成儀表面板的制作,通過其代碼編輯器來完成儀表內部邏輯仿真。其代碼生成器能夠將用戶的制作結果自動生成c++和OpenGL源代碼,用戶既可以將其代碼進行單獨編譯也可嵌入到其它程序中進行編譯,從而避免了大量繁瑣的底層OpenGL開發細節。其邏輯結構如圖2所示。

3 GL Studio向Vega移植的關鍵問題
將OpenGL實現的功能嵌入到Vega場景中,一般利用Vega的回調函數來實現,而GL Studio對儀表的繪制也是通過OpenGL編程實現的,因此,GL Studio模型向Vega場景的移植自然也要通過回調函數來實現。但是,移植過程中有如下幾個問題要解決。
3.1 GL Studio與Vega坐標系的差異問題
雖然GL Studio與Vega都是在OpenGL基礎上的應用,使用的都是右手坐標系,但是Vega的坐標系與OpenGL的坐標系又有所差別,如圖3所示。
從圖3中可以看出,Vega坐標系是在OpenGL坐標系的基礎上繞x軸逆時針旋轉90。得到的,因此,若要在Vega場景中繪制或添加GL Studio模型,首先要保存坐標系的一致。這可以通過兩種途徑來實現:
(1)在GL Studio環境中制作虛擬儀表時直接在XZ平面上繪制(這里所指的均是繪制二維儀表)。這樣,在移植過程中就不需要旋轉儀表模型,但是會給單獨調試虛擬儀表帶來不便。
(2)在GL Studio環境中制作虛擬儀表時仍在XY平面上繪制,只是在移植時要將儀表在原來基礎上繞x軸順時針旋轉90°。
本文中采用的是第二種方式。但是無論采用哪種方式,在將GL Studio模型放入Vega場景中之前,都要先保存Vega當前的顯示狀態,繪制完之后再恢復其顯示狀態。
3.2 GL Studio與Vega坐標系中基本單位變換問題
在Vega中根據場景及模型的大小不同,坐標所采用的基本單位可以是米、千米、英尺或英寸,而在GL Studio中制作虛擬儀表是以像素為基本單位的。因此在移植過程中存在著基本單位的轉換問題。
筆者經過多次試驗發現,GL Studio在移植過程中以Vega場景中的基本單位為基準進行l:l轉換,即若Vega中以米為基本單位,轉換后GL Studio的1像素即為Vega中的l米。那么,GL Studio模型在無縮放載入場景時,就會變得非常大,需要將其按要求進行縮小。一般情況下GL Studio模型在載入場景時都要以現有的Creator模型為背景,因為GLStudio所模擬的往往是在Creator建模時難以完成的某些儀表面盤,因此,在進行縮放時應根據Creator模型某個面的大小來制定縮放比例。

3.3將GL Studio模型載入場景的問題
在將GL Studio模型載入Vega場景時,應對其繪制過程進行合理封裝。本文采用在Vega場景中首先利用MakeObj()函數動態構建Object數據模型,然后將GL Studio模型作為一個Node節點添加到該Object,并為該節點增加回調函數Obj_CB()將其載入場景。具體代碼實現如下:
vgObject*MakeObj()
{vgObject*oglObj=NULL;
vgDataSet*dataset=NULL;//創建空的vgDataSet數據結構
pfGroup*group=NULL;//創建空的Group節點
DfNode*node=NULL;
//該Node節點指向新創建Object的Node節點
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數據結構創建新的Object
vgMakeObj(oglObj,VGOBJ_USE);
vgUpdate(oglObj):+
}
……
node=(#Node*)vgGetObjPfNode(oglObj):
……
pfNodeTravFuncs(node.PFTRAV_DRAW,Obj_CB,NULL);
//為新創建的Object增加回調函數pfNodeTmvData(node。PFTRAV_DRAW,NULL);return oglObj;
//返回新創建的Object地址指針
}
為創建的Object的Node節點增加的回調函數體:int obj_cB(onraverser*trav.void。data){pfPushState():
pfPushMatrix():
pfBasicState()://保存當前場景狀態
GIsObj·>Draw()://GL Studio模型繪制過程
……
glFlush()://恢復保存的場景狀態
glPopARdb():
pfPopMatrix():
pfPopState();
return PFTRAV_CONT;
}
3.4 GL Studio模型在Vega場景中的交互問題
在將GL Studio模型移植到Vega場景之后,它并不能自動捕獲用戶的輸入事件,這是由GL Studio本身底層的消息管理機制決定的。因此,若要它能夠響應窗口消息,就需要手動將消息發送給GL Studio模型,讓其處理。這里,我們在Windows窗體消息循環中增加了一個HandleEvent()函數,讓其主動捕獲消息事件發給GL Studio模型處理。其函數體如下:
Void HandleEvent(int eventType,int eventSubtype.inl
buttonMask,UINT nFlags.CPoint point)
{MouseEvent eV://定義GL Studio環境下的鼠標事件ev.eventType。eventType;
//將Windows消息轉化為GL Studio能夠識別的消息ev.eventSubtype=eventSubtype;eV.buttonMask=buttonMask;
GIs_O bj->handle(ev);//將消息發給GL Studio模型處理
}
4結束語
本文詳細介紹了用GL Studio制作的儀表模型向Vega場景移植過程中的一些關鍵問題及其解決方法,并對Vega和GLStudio的底層工作原理作了簡要介紹。所述方法解決了Vega場景中不能直接支持GL Studio虛擬儀表的問題,對于在Vega場景中復雜儀表的仿真有一定的參考和應用價值。移植到Vega場景中某型飛機虛擬座艙面板的效果如圖4所示。
(注:本文中所涉及到的圖表、注解、公式等內容請以PDF格式閱讀原文。)