探索未知种族之osg类生物---呼吸分解之更新循环一
上節(jié)總結
前幾天我們大體上介紹完成了osg的事件循環(huán)的介紹,總結一下osg的時間循環(huán)主要就是得到平臺(windows)的所有消息,并遍歷所有的node的eventCallback,并對他們進行處理。接下來我們就要進入osg的另一個維持生命的循環(huán)---更新循環(huán)。
更新循環(huán)
OSG 更新循環(huán)的作用與事件回調(diào)有類似之處:由專門的訪問器對象_updateVisitor 的負 責場景圖形更新遍歷;所有的節(jié)點和 Drawable 幾何體對象都可以使用 setUpdateCallback 設 置更新回調(diào);通過具現(xiàn) NodeCallback::operator()或者 Drawable::UpdateCallback::update 函數(shù), 可以在回調(diào)對象中添加自定義的工作。
但是,更新回調(diào)與事件回調(diào)不同之處在于:事件循環(huán)是在當一個用戶交互動作或系統(tǒng)事件產(chǎn)生時,每個節(jié)點(以及 Drawable 對象)的事件回調(diào)才會被調(diào)用一次;而節(jié)點(以及 Drawable 對象)的更新回調(diào)只會在每幀中被調(diào)用一次。這一區(qū)別決定了我們應當在什么時候使用事件回調(diào), 以及在什么時候使用更新回調(diào)。
osgViewer::Viewer::updateTraversal()
那我們就開始進入osgViewer::Viewer::updateTraversal(),updateTraversal和eventTraversal一樣首先都要定義目前處在的時間以及幀數(shù),并進行記錄,這樣有利于進行統(tǒng)計分析。下面我們就要進入osgViewer::Viewer::updateTraversal()里最重要的函數(shù)osgViewer::Scene::updateSceneGraph()函數(shù)。
這個函數(shù)中我們先介紹一下它的主體功能,再去介紹這里遇到的一些新的概念。主要功能:
1、使用DatabasePager::updateSceneGraph函數(shù)更新場景的分頁數(shù)據(jù)庫,異步處理在分頁數(shù)據(jù)庫處理線程中。
2、ImagePager::updateSceneGraph函數(shù), 更新場景的分頁圖像庫,異步處理在分頁數(shù)據(jù)庫處理線程中。
3、設置圖片請求的處理器。
我們先介紹一下DatabasePager和ImagePager
DatabasePager:分頁數(shù)據(jù)庫。在大型三維場景中采用數(shù)據(jù)分頁的方式進行動態(tài)調(diào)度。這里“分頁”的意思是隨著視口范圍的變化,場景只加載和渲染當前視口范圍內(nèi)數(shù)據(jù),并將離開視口范圍內(nèi)的數(shù)據(jù)清除內(nèi)存(可以設定不同的數(shù)據(jù)卸載策略),不再渲染。保證內(nèi)存中只有有限的數(shù)據(jù)量,場景的每一幀也只有有限的數(shù)據(jù)被送到圖形渲染管道,從而提高渲染性能。
ImagePager: 分頁圖像庫。查看ImagePager 的相關內(nèi)容了。這個類的工作 性質(zhì)與 DatabasePager 沒什么大的區(qū)別,它主要負責的是紋理圖片文件的運行時加載工作。
DatabasePager和ImagePager都會用到獨立的線程進行他們自己的工作。我們想要進入讀懂他們代碼的內(nèi)容,首先我們得具備openThread的基本知識。
openThread的基本知識
面向?qū)ο蟮目缙脚_線程庫 OpenThreads 原本是獨立的開源工程,OSG 2.x 以后的版本將 其納入了自己的體系結構當中,成為 OSG 基本庫的一份子。 OpenThreads 庫包含了以下幾個主要的線程處理類:?Thread 類:線程實現(xiàn)類。它是一個面向?qū)ο蟮木€程實現(xiàn)接口,每定義一個 Thread 類, 就相當于定義了一個共享進程資源,但是可以獨立調(diào)度的線程。通過重寫 run()和 cancel()這 兩個成員函數(shù),即可實現(xiàn)線程運行時和取消時的操作;通過調(diào)用 start()和 cancel(),可以啟 動或中止已經(jīng)定義的進程對象。?Mutex 類:互斥體接口類。如同 pthread 等常用的線程庫那樣,OpenThreads 也提供了互 斥體操作的機制,它有效地避免了各個線程對同一資源的相互競爭,即,某一線程欲操作某 一共享資源時,首先使用互斥體成員的 lock()函數(shù)加鎖,操作完成之后再使用 unlock 函數(shù)解鎖。一個線程類中可以存在多個 Mutex 成員,用于在不同的地點或情形下為共享區(qū)域加鎖; 但是一定要在適當?shù)臅r候解鎖,以免造成線程的共享數(shù)據(jù)無法再訪問。?Condition 類:條件量接口類。它依賴于某個 Mutex 互斥體,互斥體加鎖時阻塞所在的 線程,解鎖或者超過時限則釋放此線程,允許其繼續(xù)運行。 這里涉及了幾個線程操作中重要的概念:同步,阻塞以及條件變量。線程同步,簡單來 說就是使同一進程的多個線程可以協(xié)調(diào)工作,例如讓它們都在指定的執(zhí)行點等待對方,直到 全員到期之后才開始同步運行;擁塞,即強制一個線程在某個執(zhí)行點上等待,直到滿足繼續(xù) 運行的條件為止。例如其它的線程到達同一執(zhí)行點,某個變量初始化完成等等,可以通過條 件變量來設計各種條件。?Block 類:阻塞器類。顧名思義,這個類的作用就是阻塞線程的執(zhí)行,使用 block()阻塞 執(zhí)行它的線程(注意,不一定是定義它的 Thread 線程,而是當前執(zhí)行了 block 函數(shù)的線程, 包括系統(tǒng)主進程),并使用 release()釋放之前被阻塞的線程。 下圖所示的代碼實現(xiàn)了一個簡單的線程,并演示了 Block 類的使用方法。運行程序后 可以發(fā)現(xiàn),Block::block()函數(shù)將首先阻塞主進程,被釋放后再次阻塞的是 TestThread 線程, 這與它是誰的成員變量并無關系。BlockCount 類:計數(shù)阻塞器類。它與阻塞器類的使用方法基本相同:block()阻塞線程, release()釋放線程;不過除此之外,BlockCount 的構造函數(shù)還可以設置一個阻塞計數(shù)值。計 數(shù)的作用是:每當阻塞器對象的 completed()函數(shù)被執(zhí)行一次,計數(shù)器就減一,直至減到零 就釋放被阻塞的線程。?Barrier 類:線程柵欄類。這是一個對于線程同步頗為重要的阻塞器接口,它的構造函 數(shù)與 BlockCount 類似,可以設置一個整數(shù)值,我們可以把這個值理解成柵欄的“強度”。每 個執(zhí)行了 Barrier::block()函數(shù)的線程都將被阻塞;當被阻塞在柵欄處的線程達到指定的數(shù)目時,就好比柵欄無法支撐那么大的強度一樣,柵欄將被沖開,所有的線程將被釋放。重要的 是,這些線程是幾乎同時釋放的,也就保證了線程執(zhí)行的同步性。 注意 BlockCount 與 Barrier 的區(qū)別,前者是由其它任意線程執(zhí)行指定次數(shù)的 completed() 函數(shù),即可釋放被阻塞的線程;而后者則是必須阻塞指定個數(shù)的線程之后,所有的線程才會 同時被釋放。 ScopedLock 模板:這個模板是與 Mutex 配合出現(xiàn)的,它的作用域之內(nèi)將對共享資源進 行加鎖,作用域之外則自動解鎖。
?
原文鏈接? ?http://www.3wwang.cn/blog/article.ftl?id=22
轉載于:https://www.cnblogs.com/wang985850293/p/10469727.html
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎總結
以上是生活随笔為你收集整理的探索未知种族之osg类生物---呼吸分解之更新循环一的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 笔记本电脑风扇控制软件
- 下一篇: 黑盒测试方法|测试用例的设计方法--等价