摘 要: 介紹了在Windows系統(tǒng)平臺(tái)及Visual C++ 6.0的MFC基礎(chǔ)類庫(kù)環(huán)境下,采用OpenGL技術(shù)與串口通信技術(shù)實(shí)現(xiàn)的飛行仿真系統(tǒng)的設(shè)計(jì)思想與程序?qū)崿F(xiàn)方法。
關(guān)鍵詞: 虛擬現(xiàn)實(shí) OpenGL 六維鼠標(biāo) 串行口
虛擬現(xiàn)實(shí)是一種創(chuàng)建和體驗(yàn)虛擬世界的計(jì)算機(jī)系統(tǒng)。利用虛擬現(xiàn)實(shí)技術(shù),計(jì)算機(jī)可以產(chǎn)生一個(gè)三維的虛擬環(huán)境,通過(guò)人的視覺(jué)、觸覺(jué)等作用于人[1]。 用戶以客觀世界的實(shí)際動(dòng)作或以人類熟悉的方式操作虛擬系統(tǒng),從而實(shí)現(xiàn)立體交互,使人產(chǎn)生身臨其境的感覺(jué)。虛擬現(xiàn)實(shí)系統(tǒng)一般由輸入設(shè)備、輸出設(shè)備、虛擬環(huán)境生成器和高性能的計(jì)算機(jī)系統(tǒng)四大部分構(gòu)成。
目前,OpenGL在虛擬現(xiàn)實(shí)領(lǐng)域是功能較強(qiáng),最具發(fā)展前途的實(shí)現(xiàn)工具。OpenGL是美國(guó)高級(jí)圖形和高性能計(jì)算機(jī)系統(tǒng)公司(SGI)所開(kāi)發(fā)的三維圖形庫(kù),在當(dāng)前已經(jīng)成為事實(shí)上的高性能圖形和交互式視景處理的標(biāo)準(zhǔn)[2]。OpenGL是一個(gè)獨(dú)立的工作平臺(tái),用它編寫(xiě)的程序可以在不同的硬件平臺(tái)(如工作站或個(gè)人微機(jī))中使用,也可以在多種操作系統(tǒng)(如Windows系列、OS/2等)下運(yùn)行。
經(jīng)過(guò)近幾年來(lái)的發(fā)展,虛擬現(xiàn)實(shí)技術(shù)及設(shè)備被很多領(lǐng)域應(yīng)用,而飛行仿真是最重要的應(yīng)用領(lǐng)域之一。本文所研究的飛行仿真系統(tǒng)采用新型六維控制器(六自由度鼠標(biāo))作為輸入設(shè)備,監(jiān)視器作為輸出設(shè)備,以O(shè)penGL作虛擬環(huán)境生成器,構(gòu)成一套高性能計(jì)算機(jī)處理系統(tǒng)來(lái)實(shí)現(xiàn)高度仿真的飛行模擬器運(yùn)動(dòng)。
1 構(gòu)建應(yīng)用程序框架
應(yīng)用Visual C++ 6.0建立一個(gè)基于MFC的應(yīng)用程序框架,并將VC庫(kù)文件opengl32.lib、glu32.lib和glaux.lib包含在應(yīng)用程序中。
為使OpenGL函數(shù)庫(kù)的調(diào)用有效,首先應(yīng)設(shè)置渲染窗口。OpenGL的渲染處理完全不同于Windows的圖形設(shè)備接口GDI。要使Windows的窗口格式為OpenGL所接受,需進(jìn)行下列設(shè)置。
1.1 建立圖形操作描述表
OpenGL作圖窗口必須設(shè)置為WM_CLIPSIBLINGS和WM_CLIPCHILDREN風(fēng)格。
在Windows98/2000系統(tǒng)下,窗口程序首先要處理設(shè)備描述表(Device Contexts,DC),它包括若干在窗口上如何顯示圖形的信息。而在OpenGL程序中,必須創(chuàng)建圖形操作描述表(Rending Context,RC),這是DC中專用于OpenGL的一種。但是RC不同于其他的DC,它只需要一個(gè)句柄就可以任意調(diào)用OpenGL函數(shù),而其他DC調(diào)用每個(gè)GDI函數(shù)時(shí)都需要一個(gè)句柄。
使用時(shí)先通過(guò)wglCreateContext()函數(shù)創(chuàng)建一個(gè)RC,然后調(diào)用wglMakeCurrent()函數(shù)啟動(dòng)它,就可在所定義的窗口內(nèi)調(diào)用OpenGL函數(shù)繪制飛行器了。
m_pDC=new CClientDC(this);
hrc=wglCreateContext(m_pDC->GetSafeHdc( ));
wglMakeCurrent(m_pDC->GetSafeHdc( ),hrc);
1.2 設(shè)置像素格式
像素格式指定設(shè)備的繪圖屬性,包括繪圖界面的顏色表示模式、顏色位數(shù)、累積緩存區(qū)、深度緩存區(qū)和模板緩存區(qū)的位數(shù)。每個(gè)OpenGL顯示設(shè)備都支持某一特定的像素格式。像素格式用PIXELFORMATDESCRIPTOR結(jié)構(gòu)來(lái)表示,通過(guò)設(shè)置這一結(jié)構(gòu)的成員值使之支持OpenGL。建立了圖形操作描述表并初始化PIXELFORMATDESCRIPTOR結(jié)構(gòu)后,應(yīng)以此結(jié)構(gòu)為變量調(diào)用ChoosePixelFormat( )函數(shù)為設(shè)備描述表選擇像素格式,最后調(diào)用SetPixelFormat( )將其設(shè)置為當(dāng)前像素格式。
int pixelformat;
pixelformat=ChoosePixelFormat(m_pDC->GetSafeHdc( ),&pfd);
SetPixelFormat(m_pDC->GetSafeHdc( ),pixelformat,&pfd);
2 繪制場(chǎng)景
2.1 準(zhǔn)備工作
開(kāi)始繪制場(chǎng)景之前,需要用背景顏色刷新顯存。飛行器在天空的背景中飛行,因此應(yīng)將清除顏色緩沖區(qū)的顏色設(shè)為淡藍(lán)色,然后刷新顏色緩沖區(qū)和深度緩沖區(qū)。
glClearColor(0.75,0.75,1.0,1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
準(zhǔn)備工作還要考慮計(jì)算機(jī)屏幕是二維的,要用它顯示逼真的三維物體就要用到圖形變換技術(shù)。同時(shí)程序還要保證,當(dāng)用戶隨意改變窗口大小時(shí),飛行器不會(huì)變形失真。因此需要定義初始的坐標(biāo)變換。視圖類的OnSize事件對(duì)這些問(wèn)題進(jìn)行處理。
2.2 設(shè)置光照效果
創(chuàng)建三維立體的場(chǎng)景時(shí),添加光線效果對(duì)于飛行器的真實(shí)感非常重要。OpenGL的光照模型將光照成分劃分為四個(gè)獨(dú)立的部分:發(fā)射光、環(huán)境光、散射光和鏡面反射光。OpenGL獨(dú)立計(jì)算這四種光照成分,然后將其結(jié)果疊加,從而得到最終的效果。
設(shè)置光照應(yīng)分二步進(jìn)行。首先使用glLightfv( )函數(shù)設(shè)置光源的屬性和值,創(chuàng)建系統(tǒng)光源。本文定義了四個(gè)GLfloat數(shù)組sunposition、suncolor、sunambient和sunspecular,分別作為光源位置、光源的散射光亮度、環(huán)境光亮度和鏡面反射光亮度的屬性值。然后用glEnable(GL_LIGHTING)啟動(dòng)OpenGL的光照處理功能。再用glEnable(GL_LIGHT0)打開(kāi)設(shè)置的光源。
3 繪制飛行器
飛行器是一個(gè)較為復(fù)雜的三維圖形對(duì)象,它需要使用二次曲面和多邊形鑲嵌工具來(lái)創(chuàng)作,并通過(guò)OpenGL的紋理映射技術(shù)給飛行器穿上漂亮的外衣。
3.1 飛行器構(gòu)造原理
按照組成飛行器對(duì)象的幾何形體的特點(diǎn),可將飛行器構(gòu)造用二次曲面(quadric)和多邊形(polygon)表示。具體來(lái)說(shuō),機(jī)頭用錐形表示;機(jī)體是柱形;尾部的發(fā)動(dòng)機(jī)用錐形的柱體來(lái)表示;飛行器的頂棚可以用一個(gè)拉長(zhǎng)的球體來(lái)表示,把球體的透明度設(shè)為0.65,使之具有玻璃的效果,這些部分是二次曲面。例如機(jī)體繪制命令為:
gluCylinder(quadric,0.25,0.25,3.5,20,2);
而機(jī)翼和機(jī)尾的各個(gè)部分都是多邊形的,應(yīng)使用多邊形鑲嵌工具來(lái)繪制。例如機(jī)尾繪制命令為:
gluTessBeginPolygon(tess,NULL);
gluTessBeginContour(tess);
for (i=0;i<6;i ++)
gluTessVertex(tess,tail[i],tail[i]);
gluTessEndContour(tess);
gluTessEndPolygon(tess);
3.2 程序?qū)崿F(xiàn)方法
程序?qū)崿F(xiàn)應(yīng)用了顯示列表技術(shù)。OpenGL的顯示列表是事先存儲(chǔ)的用于稍后執(zhí)行的一組OpenGL命令序列。分析了飛行器的幾何形體構(gòu)造、設(shè)置完繪制命令并進(jìn)行紋理貼圖美化飛行器外表后,就可將各個(gè)部分的構(gòu)造程序代碼編輯到顯示列表里存儲(chǔ)起來(lái)了。
F16Body=glGenLists(1);
glNewList(F16Body,GL_COMPILE);
最后調(diào)用函數(shù)glEndList( ),標(biāo)志一個(gè)顯示列表的結(jié)束。
在視圖類的DrawScene( )事件的適當(dāng)位置用函數(shù)glCall-
List(F16Body)調(diào)用顯示列表,從而按照預(yù)先定義的順序執(zhí)行飛行器模型的繪制。
4 六維鼠標(biāo)控制的飛行仿真系統(tǒng)總體設(shè)計(jì)
4.1 六維鼠標(biāo)的工作原理
現(xiàn)實(shí)中飛行器是可以進(jìn)行三維移動(dòng)以及三維旋轉(zhuǎn)運(yùn)動(dòng)的,因此在飛行仿真系統(tǒng)中就需要一種可以實(shí)現(xiàn)上述運(yùn)動(dòng)模式的輸入控制設(shè)備。這里選擇了一種新型并聯(lián)結(jié)構(gòu)六維控制器,即六維鼠標(biāo)。
該六維鼠標(biāo)基于力控制原理,通過(guò)集成A/D轉(zhuǎn)換器的動(dòng)態(tài)應(yīng)變儀與計(jì)算機(jī)的COM1口(串行口1)相連,采用串行通信機(jī)制。操作者握住鼠標(biāo),向所要移動(dòng)或轉(zhuǎn)動(dòng)的方向用力,鼠標(biāo)將受到的六維力傳遞到內(nèi)部的微型六維力敏感元件,接著通過(guò)鼠標(biāo)內(nèi)部機(jī)制生成與該力成正比的電壓信號(hào),并將電壓信號(hào)放大后采集進(jìn)計(jì)算機(jī),利用力Jacobian矩陣求出鼠標(biāo)受到的空間作用力情況[3]。六維鼠標(biāo)的控制系統(tǒng)軟件實(shí)現(xiàn)將三個(gè)力分量分別乘以某個(gè)大于零的系數(shù),生成飛行器作空間直線運(yùn)動(dòng)的位移分量,從而控制仿真系統(tǒng)中飛行器的平移運(yùn)動(dòng);將三個(gè)力矩分量經(jīng)過(guò)一定算法的變換后產(chǎn)生飛行器繞X、Y、Z三個(gè)坐標(biāo)軸轉(zhuǎn)動(dòng)的角位移,從而控制飛行器的旋轉(zhuǎn)運(yùn)動(dòng), 在算法中應(yīng)用到了六維鼠標(biāo)的標(biāo)定矩陣G6×6。具體變換算法請(qǐng)查閱文獻(xiàn)3。圖1描述了六維鼠標(biāo)的工作原理流程。
4.2 仿真系統(tǒng)總體設(shè)計(jì)
六維鼠標(biāo)和計(jì)算機(jī)之間采用串口通信,所以在程序設(shè)計(jì)中選用了MSComm控件。該控件通過(guò)串行端口傳送和接收數(shù)據(jù),從而為應(yīng)用程序?qū)崿F(xiàn)串行通信功能[4]。MSComm控件將通信的大部分底層操作都封裝在控件內(nèi)部,應(yīng)用程序只需獲取和設(shè)置相應(yīng)的控件屬性即可,簡(jiǎn)化了編程的復(fù)雜度。在Visual C++ 6.0中使用該控件的基本流程如圖2所示。
本仿真系統(tǒng)中當(dāng)控件插入工程后,應(yīng)將串口初始化及打開(kāi)命令放在視圖類的OnCreate()事件中。在應(yīng)用程序建立時(shí)就打開(kāi)串口,準(zhǔn)備接收鼠標(biāo)數(shù)據(jù)。
應(yīng)用MSComm控件的OnComm( )事件作為對(duì)六維鼠標(biāo)輸入數(shù)據(jù)的響應(yīng)事件,并在事件處理中實(shí)現(xiàn)對(duì)飛行器的運(yùn)動(dòng)控制。首先檢測(cè)串口的GetCommEvent( )事件,如果該事件返回值為2,表示接收緩沖區(qū)內(nèi)的字符數(shù)達(dá)到Rthreshold值,發(fā)生接收事件(comEvReceive)。接下來(lái)編寫(xiě)接收數(shù)據(jù)的過(guò)程,實(shí)現(xiàn)將鼠標(biāo)傳輸?shù)臄?shù)據(jù)轉(zhuǎn)化為三個(gè)平移分量(Xp、Yp、Zp)和三個(gè)旋轉(zhuǎn)分量(Xr、Yr、Zr)。將Xp、Yp、Zp、Xr、Yr、Zr六個(gè)控制變量傳遞給DrawScene( )函數(shù),在飛行器繪制之前修改視景坐標(biāo)系,從而控制飛行器的運(yùn)動(dòng)。
glTranslatef(Xp,0.0f,0.0f);
glTranslatef(0.0f,Yp/10,0.0f);
glTranslatef(0.0f,0.0f,-Zp);
glRotated(Xr-37,1.0,0.0,0.0);
glRotated(Yr-7,0.0,1.0,0.0);
glRotated(Zr-2,0.0,0.0,1.0);
glCallList(F16Body);
系統(tǒng)總體實(shí)現(xiàn)流程如圖3所示。
5 結(jié) 論
本文所開(kāi)發(fā)的飛行器仿真系統(tǒng)使用Visual C++ 6.0作為軟件平臺(tái),應(yīng)用OpenGL來(lái)開(kāi)發(fā)具有六維運(yùn)動(dòng)能力的飛行模擬器和高度真實(shí)感的三維地形,以六維鼠標(biāo)作為飛行器的控制輸入設(shè)備,通過(guò)串行通信機(jī)制控制計(jì)算機(jī)中的仿真系統(tǒng)。用戶通過(guò)給六維鼠標(biāo)施加不同方向、不同大小的力來(lái)自由控制系統(tǒng)中飛行模擬器的運(yùn)動(dòng),實(shí)現(xiàn)飛行器在虛擬地形環(huán)境中的三維移動(dòng)和三維轉(zhuǎn)動(dòng),從而實(shí)現(xiàn)對(duì)真實(shí)世界中飛行器運(yùn)動(dòng)的仿真。
參考文獻(xiàn)
1 毛玉姣,王梅,陳遠(yuǎn).虛擬現(xiàn)實(shí)技術(shù)及其應(yīng)用.圖書(shū)情報(bào)知識(shí),1997;(4)
2 戴達(dá)強(qiáng),姜曉彤,朱欣華.OpenGL在圖形仿真系統(tǒng)中的應(yīng)用.現(xiàn)代電子技術(shù),2001;(9)
3 趙現(xiàn)朝,金振林.六維鼠標(biāo)中力矩與轉(zhuǎn)角轉(zhuǎn)換的一種新方法. 計(jì)算機(jī)工程,2002;(7)
4 李現(xiàn)勇.Visual C++串口通信技術(shù)與工程實(shí)踐.北京:人民郵電出版社,2002