(三)OSG初學者入門基礎教程

2021-09-12 11:15:27 字數 4103 閱讀 2744

20.超級指標(難點

關於超級指標的問題由來已久,用的頗廣。在 osg 中問題是這樣提出來的,有這樣乙個場景,有一輛卡車, 卡車上有乙個箱子。如果說卡車在執行過程中,箱子突然掉了,這樣就知道該把箱子的結點刪除。那麼如 果說還有乙個箱子,在地上放著,從感覺上來講他們應該用同一塊記憶體。卡車上的箱子雖然掉了,但是地 上的箱子還在,所以箱子所佔的資源不能被粗魯的釋放掉。

這樣就引用了超級指標的機制,其實就是引用乙個計數器,這個計數器會計算這個箱子被引用的次數,被 別人引用一次這個計數器增加一,別人不用一次,即:釋放一次,則計數器減一。當減至 0 時,內存放掉 不用。

21.超級指標詳解 (難點

內容來自  openscenegraph基本渲染理論

leandro motta barros

start: august 17th 02005

譯:freesouth

讓我們來以乙個定義開講:乙個 資源 必須在它被使用之前被申請,而在它使用之後不久被釋放,也許我們有很多的應用程

序在使用同一片資源,乙個不需要了而另乙個卻還需要使用這片資源。這兩種情況都涉及到頁面(在開啟前必須處於關閉狀態)

和資料的移動(在移動前可能被加鎖或做一些包裹處理)。在 opengl 當中,也同樣有一些關於申請與釋放資源的例子(乙個示例是紋理函式的名稱被命名為 glgentextures(), 它就必須被函式 gldeletetextures()釋放)。

在事物擴充套件的事例當中,事物擁有者使用 allocateting()來分配該事物, 然後擁有者便有責任來管理他們的分配與釋放操作。

在 osg 當中,有一些稍微有些複雜的細節來實現這些操作,也就是一些事物可能有多個擁有者。比如,在場景圖 1.7 所示當中,

類 osg::geode 中含有 box 繫結到兩個父結點身上,到底哪個負責他們的分配與釋放操作呢。

在這種情況之下,只要還有乙個引用指向該資源,該資源就不應該被釋放。所以,大多數的 osg 物件都有乙個內部的計數

器用來計算有多少個指標指向它。當沒有指標指向該資源(同樣,可以稱做物件)時,它的計數器會變為 0,當計算器為 0 時就

可以放掉物件。

幸運的是,我們程式設計師不需要手工的來維護這些引用計數:這就是超級指標為什麼存在的原因。在 osg 當中超級指標被一

個稱為 osg::ref_ptr<>的類模版來實現。無論在什麼時候,只要該物件被引用,則在 osg::ref_ptr<>當中的計數器會自動增加, 通過這種方式實現了資源的自動管理,當不需要使用它時,它會在不久後釋放,在申請它時會自動分配空間。

22.超級指標**解釋

下面這個例子會示例如何使用 osg 的超級指標,例子中有一些**如下所示:

smartpointers.cpp

1 #include

2 #include

3 #include

4 #include

56 void maythrow()

7 11

12 int main()

13 35 catch (...)

36 39 }

23.**解釋:

srand(time(0));

srand(time(0)) 就是給這個演算法乙個啟動種子,也就是演算法的隨機種子數,有這個數以後才可以產生隨機數,用1970.1.1至今的秒數,初始化隨機數種子。

srand是種下隨機種子數,你每回種下的種子不一樣,用rand得到的隨機數就不一樣。為了每回種下乙個不一樣的種子,所以就選用time(0),time(0)是得到當前時時間值(因為每時每刻時間是不一樣的了)。

20 osg::ref_ptrageode (new osg::geode());

21 maythrow();

22 group->addchild (ageode.get());

第 20 行到 22 行,示例了乙個比較安全的方式來使用超級指標,乙個 osg::ref_prt<>(叫做 ageode)在第 20 行被初始

化為 osg::geode(資源)。在這一點上,關於 geode 的引用計數器在堆內會被置 1(因為 osg::ref_ptr<>中只分配了乙個geode,故可以命令為 ageode)。

在稍後的第 22 行,geode 被當做乙個孩子加入到乙個組當中。這個操作一旦執行結束,組對 geode 的引用計數就會增加 1,變為 2。

現在,有哪些比較爛的事情發生了呢?如果我們在第 21 行呼叫 maythrow()之後,會發生幹什麼事情呢?好的,ageode將會超出範圍,然後被析構掉。然而,在它的計數減至 0 之後,它仍會合適的處理該 geode,這時也沒有記憶體洩漏。

28 osg::geode* anothergeode = new osg::geode();

29 maythrow();

30 group->addchild (anothergeode);

壞的、錯誤的、危險的以及應該被責備的方式來管理記憶體是從第 28 到第 30 行的做法。它看起來和第一種是一樣的,但是 geode 是被 new 分配的且儲存在乙個普通的指標當中。如果 maythrow()在第 29 行被丟擲,沒有人會呼叫 delete,這時 geode 就發生了洩漏。

24.移動/旋轉/縮放模型

移動/旋轉/縮放其實都是對矩陣進行操作,在 osg 當中,矩陣可以當作乙個特殊的結點加入到 root 當中, 而矩陣下也可以另入結點,而加入的結點就會被這個矩陣處理過,比如移動過/旋轉過/縮放過。在 osg 中 控制矩陣的類可以為 osg::matrixtransform。下面看乙個示例,示例對 osgcool.osg 進行了各種操作。

功能:移動/旋轉/縮放模型,這裡加入了四個 glider,乙個是預設加入在最中間,乙個向上移 2 單位,一 個是向下移 2 單位且縮放 0.5 倍,另乙個是向右 4 單位,縮放 0.5 且平躺 45 度。

25.**及解釋如下:這部分**就用到了超級指標

#include

#include

#include

#include

#include

#include

#include

intmain(

intargc

, char

**ar**)

osg::

ref_ptr

< osg::

node

> glider = osgdb::readnodefile(

"glider.osg"

) ;

讀入乙個 glider.osg 模型

trans ->setmatrix(osg::

matrix

::translate(0, 0, 2)) ;

申請乙個矩陣使加入矩陣的東西沿z 軸平移 2 個單位,在 osg 中座標軸是可以設定的,預設 x 軸是 x 軸,向裡的是 y 軸,而向上是 z 軸,這與傳統的 opengl 座標軸多有不同。

scale ->setmatrix(osg::

matrix

::scale(0.5, 0.5, 0.5)*osg::

matrix

::translate(0, 0, -2)) ;

申請乙個矩陣使加入該矩陣的模型向下移動兩個單位,值得一提的是,移動和縮放以及旋轉都 是對矩陣進行操作,這些操作如果要疊加直接矩陣相乘就可以了,可以查閱一下矩陣的基本知識,最 好看圖形學的相關書籍中關於矩陣操作一節。

rot ->setmatrix(osg::

matrix

::rotate(osg::degreestoradians(45.0), 1, 0, 0)*osg::

matrix

::scale(0.5, 0.5, 0.5)*osg::

matrix

::translate(4, 0, -2)) ;

申請乙個矩陣使加入該矩陣的模型向下移動兩個單位,向右移動四個單位,且繞 x 軸轉 45 度。 這裡的幾個矩陣也是疊加的,函式 degreestoradians 可以把角度轉為弧度。

root ->addchild(glider.get()) ;

root ->addchild(trans.get()) ;

root ->addchild(scale.get()) ;

root ->addchild(rot.get()) ;

把這些矩陣都加入到 root 當中。

git初學者教程

最近把程式設計學習的 託管在github上,我作為乙個git的業餘使用者,現在把關於git的知識整理一下。1 首先找乙個 託管 像github,註冊乙個使用者名稱yourname。2 在github上新建乙個空的專案,寫好名稱,比如clang。4 設定好本地的ssh金鑰 5 選乙個本地的專案存放位置...

SASS 初學者入門

sass可以簡化你的css工作流,並可以使你的css的擴充套件和維護工作變的更加容易!例如,曾幾時何,因為客戶的需求的變更,你必須不斷的通過查詢和替換來更改乙個畫素值,或者,為了能夠確定多欄布局中某一欄的寬度,你需要使用計算畫素值軟體才能搞定。sass引入了一些新的概念如,變數,混合,巢狀和選擇器繼...

ERP初學者入門

erp初學者入門,有很多的書籍和文件。我也不是專業的文字編輯工作者,我只想從我個人多年從事這個行業的一些體會給大家一些啟示。學erp並不難,難的是如何做乙個專業的profession的顧問。乙個資深的顧問也不是天生就有的,需要像細小流滴一樣匯聚。初學erp可以考慮從下面幾個方面入手 1.了解什麼是e...