細(xì)節(jié)決定那啥來著,一些細(xì)節(jié)雖然不是什么難事,但是一旦卡住總是會很煩心,需要太多時間去調(diào)試,耽誤的是寶貴的項目進(jìn)度,所以我將在這里把一些總結(jié)貼出來,愿能給國內(nèi)的游戲技術(shù)圈同僚們一點小幫助,節(jié)約寶貴的時間,畢竟總是在網(wǎng)絡(luò)上攝取營養(yǎng),算是回報社會吧。
本文記錄最近發(fā)現(xiàn)的一些 MFC 和 OGRE1.7.2版本 聯(lián)姻的注意事項:
問題1:創(chuàng)建Ogre的CView窗口后,無法截獲鼠標(biāo)點擊和移動信息,只能獲取鼠標(biāo)滾輪信息。
原因及解決方案:傳遞CView窗口句柄時,請一定使用externedWindowHandle的屬性key,切記不要使用parentWindowHandle,因為parentWindowHandle是讓CView成為渲染窗口的父窗口,鼠標(biāo)鍵盤消息都不會路由到CView上,而是在渲染窗口里被截獲;而externedWindowHandle是讓CView窗口本身成為渲染窗口,所以CView才能正常截獲到輸入消息。
問題2:當(dāng)解決問題1之后,發(fā)現(xiàn)使用externedWindowHandle繪制出的窗口很小,而使用parentWindowHandle時則正常
原因及解決方案:注意繼承CView::OnSize()函數(shù)響應(yīng)WM_SIZE消息,但請切記:千萬別在OnSize中調(diào)用Ogre::RenderWindow::resize()函數(shù),這會導(dǎo)致OnSize()函數(shù)的遞歸回調(diào),因為Ogre::RenderWindow::resize()函數(shù)中會調(diào)用AdjustWindow()和SetWindowPos()函數(shù),這會導(dǎo)致發(fā)送WM_SIZE消息并縮小窗口,從而導(dǎo)致問題的發(fā)生。
問題3:如何解決窗口重置大小的問題
解決方案:在OnSize()中
不能調(diào)用Ogre::RenderWindow::resize()函數(shù),而
應(yīng)該調(diào)用Ogre::RenderWindow::windowMovedOrResized()函數(shù),通知RenderWindow在渲染前重新設(shè)置Viewport的寬高比例。
問題4:怎樣確保主渲染循環(huán)
分析:上網(wǎng)看了一些相關(guān)的解決方案,發(fā)現(xiàn)大多使用WM_TIMER消息來維持OGRE的主渲染循環(huán),這應(yīng)該是下下策的方案了吧......當(dāng)然還有其他的實現(xiàn)方案,譬如開另一個線程,這個方法還是可行的,但是總有些不對味,因為渲染明明應(yīng)該在主線程中才是最佳方案。于是我就看了一下MFC閑下來的時候都干了些什么,最后發(fā)現(xiàn)了以下解決方案,應(yīng)該算是很不錯但并不難的解決辦法了,為什么沒見網(wǎng)上有人提供這樣的方案讓我很不理解,窩著藏著也得不到半點好處:
解決方案:使用空閑回調(diào)。該回調(diào)是需要繼承CWinApp::OnIdle()函數(shù)(好像是叫這個,反正肯定帶Idle這個單詞),當(dāng)主線程中的消息循環(huán)沒有取到消息時(調(diào)用PeekMessage()沒有獲取到消息),就會去調(diào)用這個函數(shù),于是......就在這個函數(shù)里調(diào)用繪制一幀吧:Ogre::RenderWindow::update(),另外有動畫的話還需要調(diào)用Ogre::Root::_fireFrameRenderingQueued(),因為動畫更新在這里。如果是想讓所有渲染對象都更新一幀的話,直接調(diào)用Ogre::Root::renderOneFrame()吧。
解決方案不一定最好,也不一定適合你的情況,但愿能盡微薄之力,也是作為我個人的備忘吧。