楊 濤 姚旺生
(海軍工程大學(xué) 武漢 430033)
隨著系統(tǒng)仿真理論方法和應(yīng)用技術(shù)研究的深入,以及計算機(jī)硬件技術(shù)和軟件技術(shù)的發(fā)展,虛擬仿真技術(shù)在軍事領(lǐng)域得到了快速發(fā)展。在魚雷武器的研制生產(chǎn)中,應(yīng)用虛擬仿真技術(shù)可以縮短設(shè)計制造周期,降低了設(shè)計制造成本,提高了產(chǎn)品質(zhì)量。以往魚雷武器系統(tǒng)的戰(zhàn)術(shù)性能考核和評定,主要是通過湖海實驗確定,但由于復(fù)雜的水下環(huán)境和各種因素的干擾(例如海流、風(fēng)浪、溫度、雜質(zhì)(泥、沙)等),對整個系統(tǒng)的現(xiàn)場實驗會造成相應(yīng)的影響;另外湖海實驗的經(jīng)費、時間以及其它客觀條件的制約,使得進(jìn)行現(xiàn)場實驗的次數(shù)有限,很難得到真實、全面、可靠的實驗數(shù)據(jù)。因此,在實驗室內(nèi)建立虛擬仿真系統(tǒng),成為魚雷武器系統(tǒng)設(shè)計、實驗、評估的重要手段。而魚雷彈道顯示系統(tǒng)的實現(xiàn),綜合了計算機(jī)圖形、虛擬現(xiàn)實和多媒體等技術(shù),創(chuàng)建了仿真對象的3D模型和虛擬環(huán)境效果,構(gòu)造了具有逼真的3D視景仿真,使彈道以形象、直觀的形式表現(xiàn)在研究者面前,方便了他們對魚雷彈道分析與研究。
魚雷彈道顯示系統(tǒng)采用Visual C++6.0+3DSMax+OpenGL,模擬魚雷在水中主要場景,設(shè)計了魚雷運動狀態(tài)的彈道顯示系統(tǒng),并在計算機(jī)上成功地完成了魚雷運動的視景仿真。其中,Visual C++6.0作為開發(fā)平臺;3DSMax用來建立系統(tǒng)模型,輸出通用的 3ds文件格式,供程序使用;OpenGL命令則提供圖形軟件和硬件之間的接口,調(diào)用OpenGL子程序,生成繪圖命令和數(shù)據(jù),然后交付硬件執(zhí)行。
本文場景中的模型全部采用3DSMax軟件來建立,并在其提供的界面下建立生成3ds格式的模型文件,最終轉(zhuǎn)化成OpenGL程序?qū)崿F(xiàn)對模型的控制。這樣做的優(yōu)點是既可以避免在OpenGL程序中用較低級的命令來建立三維立體模型的繁重勞動,又可以通過OpenGL程序?qū)崿F(xiàn)對模型的交互控制,且構(gòu)建的模型能體現(xiàn)更多的細(xì)節(jié)。
本文主要采用網(wǎng)格建模為主,結(jié)合基本幾何體建模和布爾運算等方法來構(gòu)建該型魚雷模型。下面以某型魚雷為例簡單介紹建模過程。主體部分考慮用放樣建模,放樣的原理是定義一條路徑和多個截面,然后按一定的方式將截面放置到路徑上,同時可以對截面和路徑作任意的修改,例如旋轉(zhuǎn),縮放,修改幾何形狀等。另外可以用兩個與 shape正交的視圖來約束物體的外形,即適配技術(shù)。該模型圖如圖1所示。
圖1 某型魚雷建模
在魚雷彈道顯示系統(tǒng)中,需要以三維動畫的方式顯示魚雷的運行軌跡及空間姿態(tài),并且提供對圖形顯示過程進(jìn)行控制的手段,主要包括如下功能:
1)建立模型庫。實現(xiàn)模型與相關(guān)屬性的綁定,并實現(xiàn)模型的移動、旋轉(zhuǎn)、放大、縮小等功能,對不同型號的魚雷模型進(jìn)行管理。
2)實現(xiàn)全景模式、漫游模式和跟蹤模式三種觀察模式,使用戶可以從不同角度、不同位置觀看場景,為用戶評估魚雷性能提供參考。
3)建立一個逼真的虛擬水下海洋環(huán)境,包括對海底地形及海水的模擬。
4)在不影響顯示速度的條件下,盡可能模擬魚雷運行過程中各種效果,生成動態(tài)的運行特效(如音響渲染、爆炸效果等)。
系統(tǒng)總體功能結(jié)構(gòu)如圖2所示,主要由三個子模塊來實現(xiàn)。
圖2 系統(tǒng)功能結(jié)構(gòu)圖
?魚雷/環(huán)境子模塊:主要包括魚雷模型的構(gòu)建和海底環(huán)境的生成,用戶可以根據(jù)實際需求輸入建立魚雷三維實體模型以及周圍環(huán)境模型(如天空、水下、海底等)。
?數(shù)據(jù)通訊子模塊:分為網(wǎng)絡(luò)接口和數(shù)值仿真兩部分,主要作用是把魚雷運動數(shù)據(jù)傳遞給魚雷彈道顯示部分。魚雷運動數(shù)據(jù)可來自測試系統(tǒng)的數(shù)值仿真,也可來自其他系統(tǒng)的彈道仿真計算機(jī)。其中,數(shù)值仿真部分:對魚雷進(jìn)行動力學(xué)仿真,產(chǎn)生魚雷運動彈道參數(shù)。用戶可設(shè)置仿真參數(shù)(如仿真算法、仿真步長以及仿真類型)和仿真對象(如魚雷選擇或設(shè)置、仿真彈道段選擇以及起止條件設(shè)置)。網(wǎng)絡(luò)接口部分:采用TCP/IP協(xié)議與網(wǎng)絡(luò)連接。
?聲音子模塊:用以實現(xiàn)魚雷視景仿真的聲音效果。用戶可設(shè)置聲音效果的有無,音量的大小等。
3.3.1 OpenGL繪圖環(huán)境初始化
為了能夠使用OpenGL命令,首先需要在預(yù)編譯頭文件StdAfx.h中導(dǎo)入OpenGL庫頭文件,這樣預(yù)編譯頭文件才能提供對OpenGL庫和用戶庫的支持。還必須在Project菜單下的Settings項中對Link選項卡內(nèi)鏈接以下庫:glu32.lib、opengl32.lib 、glaux.lib。
3.3.2 建立OpenGL應(yīng)用程序框架
使用VC++6.0的MFC AppWizard按照軟件所需界面要求定制出相應(yīng)的程序框架后,再使用Class Wizard修改所生成的視類,就可以建立Window s下OpenGL應(yīng)用程序框架。
1)在PreCreateWindow方法中設(shè)置窗口類型為具有WS_CLIPSIBLINGS和WS_CLIPCH IL-DREN風(fēng)格的窗口,保證成功地設(shè)置像素格式。
2)改寫View類的Create,按自己的要求注冊View類,使其具有CSDWNDC風(fēng)格,為View類的整個生命期保留一個唯一的設(shè)備描述表。每次使用OpenGL函數(shù)時都要將OpenGL的圖形操作描述表和一個Windows設(shè)備描述表聯(lián)起來。為了消除額外的開銷,可以只作一次關(guān)聯(lián)。為此要為視窗口類建立一個自己的設(shè)備描述表。
3)在OnCreate()中,重新設(shè)置像素格式,創(chuàng)建圖形操作描述表,并使它成為當(dāng)前圖形操作描述表。
4)可在View的初始更新OnInitialUpdate方法中完成繪圖場景的初始化,如設(shè)置消除背景色、光源屬性、材料屬性、深度測試方式和最初的場景變換等。
5)在OnSize中,完成對窗口大小變化的響應(yīng)。必須重新定義視口大小和投影變換矩陣,以使圖形不因窗口的變化而變形。
6)在OnDraw中要完成場景的重新繪制,繪制完場景之后,加入下面一條語句:SwapBuffers(wglGetCurrentDC())。SwapBuffers()是Win32API提供的一個用于OpenGL的函數(shù)。當(dāng)OpenGL使用DoubleBuffers以支持動畫顯示時,需要使用該函數(shù)將在BackBuffer上繪制的場景交換到FrontBuffer中顯示。SwapBuffers()需要與圖形操作描述表相聯(lián)的設(shè)備描述表句柄作為參數(shù),而函數(shù)wglGetCurrentDC()恰好提供了與當(dāng)前使用的圖形操作描述表相聯(lián)的設(shè)備描述表句柄。
7)在程序退出時應(yīng)該清空當(dāng)前使用的圖形操作描述表,并刪除所創(chuàng)建的圖形操作描述表。
3.3.3 魚雷模型的讀入
系統(tǒng)使用模型3DSMax建立魚雷模型,輸出為通用的3ds文件格式。3DS文件由許多塊組成,每個塊首先描述其信息類別,即該塊是如何組成的。塊的信息類別用ID來標(biāo)識,塊還包含了下一塊的相對位置信息。物體的層次結(jié)構(gòu)并不復(fù)雜,場景中給予每個物體一個數(shù)字以標(biāo)識其在場景樹中的順序。3DS文件中也使用相同的方法標(biāo)識了物體在場景樹中的位置。作為根物體給予了數(shù)字-1(FFFF)作為其數(shù)字標(biāo)識。當(dāng)讀取文件的時候,就會得到一系列的物體數(shù)字標(biāo)識。如果當(dāng)前數(shù)字標(biāo)識比前一個大,那么當(dāng)前物體是前一個物體的子物體;反之,當(dāng)數(shù)字標(biāo)識比前一個數(shù)字標(biāo)識小,則又回到上一層結(jié)構(gòu),如圖3所示。
圖3 3DS文件結(jié)構(gòu)
本系統(tǒng)中模型讀入函數(shù)很多,主要用于讀取不同的內(nèi)容,如下所示:
int ReadKFTrackTag(long fileSize,long tagStart,long tag-Size,FILE *fp,char*nodeName,tVector*pivot,Chunk3DS chunk);
int ReadKFObjectNode(long fileSize,long nodeStart,long nodeSize,FILE*fp);
int ReadKFDATA(long fileSize,long kfdataStart,long kfdataSize,FILE*fp);
int Read3DSChunk(FILE*fp,Chunk3DS&chunk);
int ReadPercentage(FILE*fp,float&value);
int ReadColor(FILE*fp,float&red,float&green,float&blue);
int ReadPointArray(CTriObject*newchild,long fileSize,FILE*fp);
int ReadFaceArray(CTriObject*newchild,long unsigned fileSize,FILE*fp);
int ReadMeshMatGroup(CTriObject*newchild,Material-Dict*matdict,long fileSize,FILE*fp);
int ReadTriObject(MaterialDict*matdict,long fileSize,FILE*fp,long triStart,long triSize,char*group-Name);
int ReadNamedObject(MaterialDict*matdict,long file-Size,long namedStart,long namedSize,FILE*fp);
int ReadMatEntry(MaterialDict*matdict,long fileSize,long matStart,long matSize,FILE*fp);
int ReadMDATA(M aterialDict*matdict,long fileSize,long mdataStart,long mdataSize,FILE*fp);
int Read3DSFile(long fileSize,long fileStart,long fileLen,FILE*fp);
int Is3DSFile(FILE*fp);
BOOL Reader(char*filename,CTriList*_list);
3.3.4 視點的設(shè)置
為了實現(xiàn)在不同的位置對魚雷彈道進(jìn)行觀測,在本系統(tǒng)中定義了8個攝像機(jī),切換不同的攝像機(jī)可以實現(xiàn)不同角度的觀測,并且在系統(tǒng)中添加了按鍵響應(yīng)函數(shù),按不同的鍵可以切換到不同的視點。下面以第一臺攝像機(jī)的使用為例,具體函數(shù)如下:
第一步:初始化函數(shù)。
int InitGL(GLvoid)//視點模式
{camera[0].x=0;
camera[0].y=0;
camera[0].z=0;
camera[0].type=CAM_A;}
第二步:視點設(shè)置函數(shù)。
void Camera(void)
{switch(var.cameratype)
{case CAM_A:
var.xcam=var.xmis+4;
var.ycam=var.ymis+3;
var.zcam=var.zmis+15;
gluLookAt(var.xcam,var.ycam,var.zcam,var.xmis,var.ymis,var.zmis,0.0f,1.0f,0.0f);
break;}
3.3.5 光照處理
繪制好模型后,必須進(jìn)行光照處理,有了光照后物體才真正表現(xiàn)為三維物體。因此,必須創(chuàng)建光源、選擇光源模式、定義材料屬性,以得到理想中的三維模型。
GLfloat light_position[]={1.0,1.0,1.0,0.0};
glLightfv(GL_LIGHTO,GL_POSITION,light_position);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHTO);
本仿真系統(tǒng)是在Visual C++6.0平臺上,通過OpenGL圖形庫函數(shù)來實現(xiàn)可視化仿真。與內(nèi)測數(shù)據(jù)通信,在某型魚雷彈道數(shù)據(jù)和姿態(tài)數(shù)據(jù)的驅(qū)動下,在顯示屏上模擬出了魚雷啟動、運行、加速等場景,畫面連續(xù),逼真,可變視點觀察。圖4為魚雷內(nèi)測系統(tǒng)得到的運行狀態(tài)。
圖4 魚雷水下正常航行場景
本系統(tǒng)可移植性強(qiáng),不僅自帶魚雷動力學(xué)仿真計算功能,而且能通過數(shù)據(jù)通訊子模塊接受來自其他系統(tǒng)或網(wǎng)絡(luò)接口傳遞來的數(shù)據(jù),通過更換不同的對象模型就可模擬不同型號的魚雷或者其他水下航行體可視化過程,具有一定的推廣價值。下一步工作主要是完成與魚雷陸上仿真實驗系統(tǒng)的連接測試,另外還需對水下復(fù)雜環(huán)境的建模仿真、海面波浪的渲染和魚雷模型的紋理映射等方面進(jìn)一步的修改加強(qiáng),使可視化過程更加真實、可靠。
[1]Dave Shreiner,MasonWoo,Jackie Neider,et al.OpenGL Programming Guide(Sixth Edition)[M].北京:人民郵電出版社,2007
[2]Kruglinski D J.Visual C++技術(shù)內(nèi)幕(第四版)[M].潘愛民,譯.北京:清華大學(xué)出版社,1999
[3]Richard S.Wright.Jr.Michael Sweet.OpenGL超級寶典[M].北京:人民郵電出版社,2000
[4]Edward Ange.OpenGL編程基礎(chǔ)(第三版)[M].段菲,譯.北京:清華大學(xué)出版社,2008
[5]李穎,薛海斌,朱伯立,等.OpenGL函數(shù)與范例解析手冊[M].北京:國防工業(yè)出版社,2002
[6]陳玉軍,張琦.基于MFC的OpenGL仿真與3D模型的獲取[J].中國制造業(yè)信息化,2005(4):103~105
[7]張宇文.魚雷彈道與彈道設(shè)計[M].西安:西北工業(yè)大學(xué)出版社,1999,9
[8]康鳳舉.現(xiàn)代仿真技術(shù)與應(yīng)用[M].北京:國防工業(yè)出版社,2003,9