摘 要: 介紹了在Windows系統(tǒng)平臺(tái)及Visual C++ 6.0的MFC基礎(chǔ)類庫環(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)境,通過人的視覺,、觸覺等作用于人[1],。 用戶以客觀世界的實(shí)際動(dòng)作或以人類熟悉的方式操作虛擬系統(tǒng),從而實(shí)現(xiàn)立體交互,使人產(chǎn)生身臨其境的感覺,。虛擬現(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)所開發(fā)的三維圖形庫,,在當(dāng)前已經(jīng)成為事實(shí)上的高性能圖形和交互式視景處理的標(biāo)準(zhǔn)[2]。OpenGL是一個(gè)獨(dú)立的工作平臺(tái),,用它編寫的程序可以在不同的硬件平臺(tái)(如工作站或個(gè)人微機(jī))中使用,,也可以在多種操作系統(tǒng)(如Windows系列、OS/2等)下運(yùn)行,。
經(jīng)過近幾年來的發(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)來實(shí)現(xiàn)高度仿真的飛行模擬器運(yùn)動(dòng),。
1 構(gòu)建應(yīng)用程序框架
應(yīng)用Visual C++ 6.0建立一個(gè)基于MFC的應(yīng)用程序框架,并將VC庫文件opengl32.lib,、glu32.lib和glaux.lib包含在應(yīng)用程序中,。
為使OpenGL函數(shù)庫的調(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í)先通過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)來表示,,通過設(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)備工作
開始繪制場(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ì)這些問題進(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)打開設(shè)置的光源。
3 繪制飛行器
飛行器是一個(gè)較為復(fù)雜的三維圖形對(duì)象,,它需要使用二次曲面和多邊形鑲嵌工具來創(chuàng)作,,并通過OpenGL的紋理映射技術(shù)給飛行器穿上漂亮的外衣。
3.1 飛行器構(gòu)造原理
按照組成飛行器對(duì)象的幾何形體的特點(diǎn),,可將飛行器構(gòu)造用二次曲面(quadric)和多邊形(polygon)表示,。具體來說,機(jī)頭用錐形表示;機(jī)體是柱形,;尾部的發(fā)動(dòng)機(jī)用錐形的柱體來表示,;飛行器的頂棚可以用一個(gè)拉長(zhǎng)的球體來表示,把球體的透明度設(shè)為0.65,,使之具有玻璃的效果,,這些部分是二次曲面。例如機(jī)體繪制命令為:
gluCylinder(quadric,,0.25,,0.25,3.5,,20,,2);
而機(jī)翼和機(jī)尾的各個(gè)部分都是多邊形的,,應(yīng)使用多邊形鑲嵌工具來繪制,。例如機(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ǔ)起來了,。
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)基于力控制原理,,通過集成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)部的微型六維力敏感元件,接著通過鼠標(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)過一定算法的變換后產(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控件。該控件通過串行端口傳送和接收數(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)將串口初始化及打開命令放在視圖類的OnCreate()事件中,。在應(yīng)用程序建立時(shí)就打開串口,準(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),。接下來編寫接收數(shù)據(jù)的過程,,實(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é) 論
本文所開發(fā)的飛行器仿真系統(tǒng)使用Visual C++ 6.0作為軟件平臺(tái),,應(yīng)用OpenGL來開發(fā)具有六維運(yùn)動(dòng)能力的飛行模擬器和高度真實(shí)感的三維地形,以六維鼠標(biāo)作為飛行器的控制輸入設(shè)備,,通過串行通信機(jī)制控制計(jì)算機(jī)中的仿真系統(tǒng),。用戶通過給六維鼠標(biāo)施加不同方向,、不同大小的力來自由控制系統(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)用.圖書情報(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