曹莉,宋學坤,張佩江
一種用于虛擬校園漫游的三維引擎的研究
曹莉,宋學坤,張佩江
在對三維引擎技術OSG進行分析和研究的基礎上,提出并實現(xiàn)了一種用于虛擬校園漫游的三維引擎系統(tǒng),該系統(tǒng)使用OSG所提供的類和接口,實現(xiàn)了虛擬校園場景的渲染以及漫游的交互控制功能,同時在引擎中添加了語音介紹功能,豐富了瀏覽者的視聽感受。實踐證明,該引擎具有良好的移植性與通用性,為虛擬校園漫游技術向虛擬校園系統(tǒng)和虛擬學習平臺方面的遷移提供了支持。
開放式視景圖形;三維引擎;虛擬校園;漫游交互
隨著科學技術的迅猛發(fā)展,虛擬現(xiàn)實技術已經成為人機交互技術的新生力量,而虛擬漫游技術是虛擬現(xiàn)實技術的重要分支,在建筑、旅游、游戲、航空航天等多種行業(yè)發(fā)展的很快。而通過虛擬現(xiàn)實技術全面展示校園建筑物、校園設施以及校園地貌,可以為學校樹立良好的形象,提高知名度,還可以作為校園規(guī)劃的輔助工具。
三維引擎作為實現(xiàn)虛擬校園漫游的一種重要方式,它的主要作用是在計算機上創(chuàng)造出一個虛擬的校園環(huán)境,通過提供與該虛擬環(huán)境的交互體驗,人們可以在個人PC上進入一個虛擬的校園環(huán)境,并在虛擬場景中進行實時瀏覽。
本文中三維引擎的目標是以OSG技術作為基礎,并結合其他虛擬現(xiàn)實技術在計算機上模擬虛擬校園漫游的過程。
三維引擎作為虛擬現(xiàn)實的核心,多數(shù)采用OpenGL的開發(fā)接口進行開發(fā),這種開發(fā)接口仍然停留在幾何體級別的操作層面,是一種明顯帶有面向過程特征的API。OSG(Open Scene Graph)是一個跨平臺的開源的圖形開發(fā)包,它基于場景圖的概念,提供一個構建于OpenGL函數(shù)庫之上的面向對象的框架,為圖形程序的開發(fā)提供場景管理和渲染優(yōu)化功能,從而使系統(tǒng)開發(fā)脫離幾何體操作,轉而處理具體的場景,大大提升開發(fā)效率。也為虛擬校園漫游技術今后在虛擬校園系統(tǒng)、虛擬學習平臺等方面的擴展提供充分的技術支持。
1.1 OSG的場景管理
OSG采用場景圖結構來管理場景,它是一種自頂向下的,分層的樹狀數(shù)據(jù)結構,如圖1所示:

圖1 場景圖結構
該結構以根節(jié)點表示整個三維場景;以組節(jié)點(osg::Group)表示物體屬性信息,如矩陣變換、狀態(tài)切換、細節(jié)層次等,在實現(xiàn)過程中,又以組節(jié)點為基類派生出變換節(jié)點(osg::Transform),開關節(jié)點(osg::Switch),細節(jié)層次節(jié)點(osg::LOD)等類,對屬性信息進行分別管理;而葉子節(jié)點(osg::Geode)則代表物理對象本身或幾何模型。這種結構既反映了場景的空間結構,也反映了對象的狀態(tài),便于提取數(shù)據(jù)節(jié)點之間的共有行為和屬性。
場景圖是一種中間件(middleware),它構建于底層API函數(shù)之上,提供了高性能3D程序所需的空間數(shù)據(jù)組織能力及其它特性。一個典型的OSG程序層次結構,如圖2所示:

圖2 3D程序層次結構
1.2 OSG的場景渲染
一個場景圖系統(tǒng)執(zhí)行繪圖遍歷時,所有幾何體是以OpenGL指令的形式發(fā)送到硬件設備上。這種機制無法實現(xiàn)諸如細節(jié)層次、渲染特效等高級特性。為了實現(xiàn)動態(tài)的幾何體更新,揀選,排序和高效渲染,OSG場景圖形提供3個遍歷過程:
更新:更新遍歷允許修改幾何體、渲染狀態(tài),或者節(jié)點參數(shù),保證場景圖形的更新對應當前幀;
揀選:在揀選遍歷中檢查可見性,將幾何體和狀態(tài)量置入新的結構(在OSG中稱為渲染圖形,render graph)之中。
繪制:在繪制遍歷中(有時也稱作渲染遍歷),場景圖形將遍歷由揀選遍歷過程生成的幾何體列表,并調用底層API,實現(xiàn)幾何體的渲染。
一般地,這3種遍歷操作在每一個渲染幀中只執(zhí)行一次,但有時一些渲染特例需要將同一個場景(不同或相同部分)在多個視口中進行同步顯示,這樣更新遍歷仍然只執(zhí)行一次,但揀選和繪制遍歷則需要在每個視口內各執(zhí)行一次,以保證多處理器和多顯卡的系統(tǒng)實現(xiàn)并行場景圖形處理。
2.1 場景的渲染
OSG所提供的Viewer類包含了在渲染OSG圖形的代碼,要實現(xiàn)場景渲染首先是Viewer實例化一個osgViewer::Viewer 對象,而后將一個場景圖形關聯(lián)到該對象,并進行渲染。osgviewer 在使用Viewer 類在實現(xiàn)場景的渲染的基礎上增加了改變視口的功能。
Viewer類在內部創(chuàng)建了一個osg::Camera 攝像機對象來管理OSG 的模型-視圖矩陣。設置Camera 對象的投影矩陣和觀察矩陣為自定義的矩陣值,就可以保證用戶程序能夠完全控制視口的瀏覽動作,可以編寫一個小的循環(huán)來代替Viewer::run(),循環(huán)中反復更新視口并渲染單幀圖像。下面的代碼段實現(xiàn)了直接控制Viewer 中的Camera 對象,從而改變每一幀的視口顯示。
osgViewer::Viewer viewer;
viewer.setSceneData(osgDB::readNodeFile("xiaoyuan.ive"));
view
er.getCamera()->setProjectionMatrixAsPerspective(40.,1.,1.,10 0.);
// 創(chuàng)建矩陣,指定到視點的距離
osg::Matrix trans;
trans.makeTranslate(0.,0.,-12.);
// 旋轉一定角度(弧度值)
double angle(0.);
while (!viewer.done())
{
// 創(chuàng)建旋轉矩陣
osg::Matrix rot;
rot.makeRotate(angle,osg::Vec3(1.,0.,0.));
angle+=0.01;
// 設置視口矩陣(旋轉矩陣和平移矩陣連乘)
viewer.getCamera()->setViewMatrix(rot * trans);
// 繪制下一幀
viewer.frame();
}
在渲染循環(huán)中,代碼每幀都會更新Camera 的視口矩陣以增加旋轉角度值。代碼中使用setViewMatrix()方法來設置視口矩陣,Camera類還提供了與之相似setViewMatrixAsLookat() 方法。
2.2 漫游交互控制
OSG中的GUIEventHandler類為任何想要處理GUI事件的類提供了一個基本接口。處理事件的方法是:virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::G UIActionAdapter& aa);方法中的第一個參數(shù)是GUI事件的供給者,第二個參數(shù)用于handle方法對GUI進行反饋, G UIEventHandler根據(jù)輸入事件讓GUI進行一些動作。如果要進行事件處理,可以從GUIEventHandler派生出一個新類,然后覆蓋handle方法,在其中重寫事件處理。osgProducer:: Viewer類維護一個GUIEventHandler隊列,事件在這個隊列里依次傳遞,handle的返回值決定這個事件是否繼續(xù)讓后面的GUIEventHandler處理,如果返回true,則停止處理,如果返回false,后面的GUIEventHandler還有機會繼續(xù)對這個事件進行響應。
(1) 鍵盤控制
鍵盤控制是攝像機控制中的一個功能實現(xiàn),要求鍵盤的“↑”“↓”“←”“→”來控制攝像機前后左右的移動,在OSG事件處理函數(shù)中實現(xiàn)。重載handle函數(shù)實現(xiàn)鍵盤上的方向鍵控制攝像機視口:
bool handle(
const osgGA::GUIEventAdapter& ea,
osgGA::GUIActionAdapter& us)
{
case(GUIEventAdapter::KEYDOWN/ KEYUP):
{
if(ea.getKey()==GUIEventAdapter::KEY_Space)
{ // 返回初始位置
flushMouseEventStack();
home(ea,us);
return true; }
//實現(xiàn)上,下,左,右方向鍵控制視口
else if
(ea.getKey()==osgGA::GUIEventAdapter::KEY_Up)
{ return true; }
else if
(ea.getKey()==osgGA::GUIEventAdapter::KEY_Down)
{ return true; }
else if
(ea.getKey()==osgGA::GUIEventAdapter::KEY_Left )
{ return true; }
else if
(ea.getKey()==osgGA::GUIEventAdapter::KEY_Right)
{ return true; }
}
這是實現(xiàn)鍵盤響應函數(shù)的代碼,getKey()是獲取鍵盤響應值,使用OSG的事件響應函數(shù)完成的。系統(tǒng)中用到的語音,以及對語音的控制,同樣用到了鍵盤控制。
(2)鼠標控制
鼠標控制實現(xiàn)的是對于攝像機視口上下左右的移動,同樣用到了OSG的事件處理函數(shù)——鼠標響應事件。鼠標的移動用到矩陣運算來計算新的位置,鼠標左右鍵的響應用到的是事件處理函數(shù)。
①控制器鼠標移動函數(shù)主要是對于鼠標位置的設置。
double CMyManipulator::Mouse_Move(int wndWidth, int wndHeight)
②控制器鼠標旋轉的實現(xiàn),是在bool CMyManipulator::calcMovement()中利用旋轉矩陣的運算實現(xiàn)的。具體如下:
osg::CoordinateFrame cf=getCoordinateFrame(_eye);
osg::Matrix rotation_matrix; //定義旋轉矩陣
rotation_matrix.makeRotate(_rotation);
// 旋轉矩陣運算
//利用矩陣相乘確定攝像機的三個變量的位置
osg::Vec3d up = osg::Vec3d(0.0,1.0,0.0) * rotation_matrix;
osg::Vec3d lv = osg::Vec3d(0.0,0.0,-1.0) * rotation_matrix;
osg::Vec3d sv = osg::Vec3d(1.0,0.0,0.0) * rotation_matrix;
③鼠標按鍵控制,包括旋轉速度的實現(xiàn)
case(USE_MOUSE_Y_FOR_SPEED):
{double dy =
_ga_t0->getYnormalized();
_velocity = _modelScale*0.2f*dy;
break;
}
case(USE_MOUSE_BUTTONS_FOR_SPEED):
{
unsigned int buttonMask
= _ga_t1->getButtonMask();
if (button-
Mask==GUIEventAdapter::LEFT_MOUSE_BUTTON)
{_velocity += dt*_modelScale*0.01;
}
else if
(button-
Mask==GUIEventAdapter::MIDDLE_MOUSE_BUTTON ||
button-
Mask==(GUIEventAdapter::LEFT_MOUSE_BUTTON|GUIEv entAdapter::RIGHT_MOUSE_BUTTON))
{_velocity = 0.0;}
else if
(button-
Mask==GUIEventAdapter::RIGHT_MOUSE_BUTTON)
{_velocity -=
dt*_modelScale*0.01;
}
鼠標的控制,在漫游過程中,旋轉操作是利用鼠標來控制攝像機視口,因為攝像機的位置的三個參數(shù)中包含視口的控制。鼠標的控制還要在攝像機控制中添加鼠標響應事件以及刷新鼠標事件,用來檢查更新鼠標的狀態(tài)。
2.3 添加語音介紹
虛擬校園漫游配以語音介紹,能讓瀏覽者更全面的了解學校信息,將事先錄制好的語音保存為mp3格式,將Direct Show中播放音樂的接口封裝到一個自定義的類中,并重寫這個媒體音樂的接口。實現(xiàn)如下:
(1)設置接口指針為空。
(2)通過一個媒體控制器m_pGraph,初始化接口庫。
(3)創(chuàng)建filter graph manager 濾波器控制器,來控制音樂格式和各種格式的接口。
(4)定義接口對象,查詢要使用的接口。
定義接口對象,可以完成的函數(shù)有:
run()播放音樂函數(shù);
render(CMyPlayer * ptr)通過指針設置循環(huán)播放;
pause()和stop()暫停和停止音樂;
setStartPosition();設置語音初始播放位置;
setMp3FileName()和getMp3FileName()設置和獲取語音文件名;
setVolume()和getVolume()設置和獲取音量函數(shù)。
語音實現(xiàn)的具體過程:
class MusicCallBack : public osgGA::GUIEventHandler
{ public:
MusicCallBack()
{ myPlay
er.setMp3FileName(L"C:/jieshao.mp3");//設置語音文件名稱
myPlayer.run(); //播放音樂
}
用鍵盤控制語音:
bool handle(const GUIEventAdapter& ea,GUIActionAdapter& aa, osg::Object*, osg::NodeVisitor*)
{ if(ea.getEventType() ==
GUIEventAdapter::KEYDOWN)
{
if(ea.getKey() == '=' || ea.getKey() == '+')
{ long lVolume = myPlayer.getVolume();//獲取當前音量
lVolume += 100;
myPlayer.setVolume(lVolume);//增加音量后的新音量
return true;
}
else
if(ea.getKey() == '-' || ea.getKey() == '_')
{ long lVolume =
myPlayer.getVolume();
lVolume -= 100;
myPlayer.setVolume(lVolume); //減弱音量
return true;
}
else
if(ea.getKey() == '1' || ea.getKey() == '!')
{ myPlayer.pause(); //暫停
return true;
}
else
if(ea.getKey() == '2' || ea.getKey() == '@')
{ myPlayer.run(); //播放
return true;
}
else
{ CMyPlayer::render(&myPlayer); //設置循環(huán)播放
return false;
}
}
CMyPlayer::render(&myPlayer);
return false;
}
protected:
CMyPlayer myPlayer;
};
本文在對三維引擎技術進行分析和研究的基礎上,提出并實現(xiàn)了一種用于虛擬校園漫游的三維引擎系統(tǒng),該引擎具有良好的移植性與通用性,并配有有錄制好的語音介紹,良好的可擴展性和結構設計使得數(shù)據(jù)的擴展并不需要修改引擎本身,因此可用于不同數(shù)據(jù)規(guī)模的應用。
[1] 曹莉.基于OSG的三維引擎關鍵技術研究[J].微型電腦應用,2013,29(10):31-34
[2] 熊磊.一種用于虛擬旅游體驗的三維引擎的研究[D].武漢:華中師范大學,2007.
[3] 華艷.三維虛擬校園漫游系統(tǒng)的研究與應用 [J] .應用技術與研究,2013,(10):63-64.
[4] 溫轉萍,等.基于OSG的虛擬校園漫游系統(tǒng)的設計與實現(xiàn)[J].計算機技術與發(fā)展,2009,19(01):217-220.
[5] 王銳,等.OpenSceneGraph三維渲染引擎設計與實踐[M].北京:清華大學出版社,2009.
[6] 葉偉,基于OSG的虛擬校園漫游系統(tǒng)研究與實現(xiàn)[D].南昌:南昌航空大學,2013.
The Research of 3D Engine for Virtual Campus Ramble
Cao Li, Song Xuekun, Zhang Peijiang
(Henan University of TCM, Zhengzhou450000, China)
After analyzing the 3D engine technology named OSG, it presents and realizes the 3D engine for campus ramble. Some classes and interfaces of OSG are used to accomplish the interaction control and rendering the scene of virtual campus in the system. In addition, the audio introduce function can enrich the audio-visual sensation of users. The practice has proved that the engine has portability and universality and it supplies support for the transfer of campus ramble technology to virtual campus system and the virtual learning platform.
Open Scene Graph (OSG), 3D Engine, Virtual Campus, Ramble Interaction
TP391.9
A
1007-757X(2014)10-0028-04
2014.07.16)
河南中醫(yī)學院苗圃項目課題(MP2013-74);河南省教育廳2011年自然科學研究項目(No.2011A520027);河南省信息技術教育研究項目(No.ITE12088);2013河南省教育廳人文社會科學研究項目(No.2013-MFD-137);2014年度河南省教育廳科學技術研究重點項目(No.14A520070);2013河南中醫(yī)學院教育教學改革研究項目(No.2013JX21);河南中醫(yī)學院人才培養(yǎng)模式創(chuàng)新實驗區(qū)建設項目(No.XJZLGC[2010]22)
曹 莉(1979-),女,漢族,河南新鄉(xiāng)人,河南中醫(yī)學院,實驗師,研究方向:虛擬現(xiàn)實技術,鄭州,450000宋學坤(1982-),男,漢族,河南商丘人,河南中醫(yī)學院,講師,研究方向:生物信息學、醫(yī)學信息處理和智能計算,鄭州,450000張佩江(1961-),男,漢族,河南開封人,河南中醫(yī)學院,副教授,研究方向:基于Web的大型分布式數(shù)據(jù)庫應用技術,鄭州,450000