osg 基本圖元
OSG繪製幾何體學習總結:
在osg中,場景圖形採用一種自頂向下的,分層的樹狀資料結構來組織空間資料集,以提高渲染的效率
場景圖形樹結構的頂部是一個根節點,從根節點向下延伸,各個組節點中均包含了幾何資訊和用於控制其外觀的渲染狀態資訊。根節點和各個組節點都可以有零個(實際上是沒有執行任何操作)或多個子成員。在場景圖形的最底部,各個葉節點包含了構成場景中物體的實際幾何資訊。
首先,必須明確的是,在應用程式中所有幾何體的渲染都必須與Geode節點相關聯。在osg::Geode類中,也提供了addDrawable()函式來關聯應用程式中需要渲染的幾何體資訊。一個Geode可以包含多個Drawable,Geode維護了一個Drawable的列表
在osg中,通常有三種生成幾何體的手段:一是鬆散封裝的OpenGL繪圖基元osg::Geometry,二是使用OSG中預定義的基本幾何體;三是從檔案中匯入場景模型。
不管是鬆散封裝的OpenGL的繪圖基元,還是osg自己預定義的幾何體,其基類都是osg::Drawable,它派生自osg::Object(該類派生自osg::referenced),具體繼承關係如下圖所示,
注意:最常用的是DrawPixels,Geometry,shapedrawable,osgText::TextBase
其中:DrawPixels用於繪製圖像,具體用法如下:
osg::DrawPixels* pixels = new osg::DrawPixels();
pixels->setPosition(osg::Vec3((float)vX[0],(float)vY[1] ,(float)vZ[1]));
QString imagePath = ::GetImagePath() + pWell->GetWellSymbol();
pixels->setImage(osgDB::readImageFile(imagePath.toStdString()));
//宣告一個圖片節點
osg::Geode* imagNode = new osg::Geode();
imagNode->addDrawable(pixels);
osgText用於繪製文字,具體用法如下:
QString strFont1 = ::GetImagePath() + "fonts/MicroSoftYahei.ttf";
QTextCodec *code = QTextCodec::codecForName("gb18030");
std::string strFont2 = strFont1.toStdString();
if( code )
{
strFont2 = code->fromUnicode(strFont1).data();
}
{
m_pText = new osgText::Text;
m_pText->setDataVariance(osg::Object::DYNAMIC);
//p->setUseDisplayList(false);
m_pText->setFont(strFont2 );
m_pText->setDrawMode(osgText::Text::TEXT);
m_pText->setFontResolution(15,15);
m_pText->setCharacterSize(15);
m_pText->setAlignment(osgText::Text::CENTER_CENTER );
m_pText.setAxisAlignment(osgText::Text::SCREEN);//讓文字所在平面始終對著螢幕
m_pText->setColor(osg::Vec4f(0,0,0,1) );
}
m_pGeode = new osg::Geode();
m_pGeode->clone( osg::CopyOp::DEEP_COPY_ALL );
m_pGeode->addDrawable( m_pText );
m_pSwitch = new osg::Switch;
m_pSwitch->addChild( m_pGeode );
下面重點講解Geometry和ShapeDrawable。
在實際應用中,往場景裡面新增一個幾何體,都必須先定義個geode,osg::Geode* geode =new osg::Geode;
然後要麼用自定義幾何體osg::Shape,使用方式:geode->addDrawable(new osg::ShapeDrawable(new osg::Sphere(osg::vec3(0.0f,0.0f,0.0f),radius),hints.get()));
osg中提供了大量的預定義幾何體,來簡化場景的繪製,繼承關係如圖所示。如果要渲染這些幾何體,必須將其掛到某個geode下面,但是geode只能通過adddrawable新增osg::drawable型別,因此實際應用中提供了osg::ShapeDrawable來完成這個功能。在該類的建構函式中提供了關聯osg::Shape的方法:
ShapeDrawable(Shape * shape,TessellationHints * hints=0)//第一個引數即為要繪製的幾何體,第二個為網格化類,主要用於設定幾何體的精細程度
要麼用Geometry,使用方式:
osg::ref_ptr<osg::Geode> geode1 = new osg::Geode();
osg::ref_ptr<osg::Geometry> geom1 = new osg::Geometry();
//建立頂點陣列
osg::ref_ptr<osg::Vec3Array> v = new osg::Vec3Array();
v->push_back(osg::Vec3(458000,0,-1500));
v->push_back(osg::Vec3(458000,0,-2750));
v->push_back(osg::Vec3(452000,0,-2750));
v->push_back(osg::Vec3(452000,0,-1500));
geom1->setVertexArray(v.get());
//設定顏色陣列
osg::ref_ptr<osg::Vec4Array> vc = new osg::Vec4Array();
vc->push_back(osg::Vec4(1.0f,0.0f,0.0f,1.0f));
vc->push_back(osg::Vec4(0.0f,1.0f,0.0f,1.0f));
vc->push_back(osg::Vec4(0.0f,0.0f,1.0f,1.0f));
vc->push_back(osg::Vec4(1.0f,1.0f,0.0f,1.0f));
geom1->setColorArray(vc.get());
geom1->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
//設定法線陣列
osg::ref_ptr<osg::Vec3Array> nc = new osg::Vec3Array();
nc->push_back(osg::Vec3(0,1,0));
geom1->setNormalArray(nc.get());
geom1->setNormalBinding(osg::Geometry::BIND_OVERALL);
//新增圖元,繪圖基元為四邊形
geom1->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4));
geode1->addDrawable(geom1.get());
m_pRootSwitch->addChild(geode1);
上一段程式中還設定了顏色資料,法線資料與頂點資料繫結的方式,即setColorBinding和setNormalBinding,繫結資料的方式有以下幾種:
BIND_OFF |
取消繫結 |
此時,顏色資料或者法線資料與頂點資料完全沒有關係,頂點資料的顏色和法線方向完全由預設值決定。 |
BIND_OVERALL |
繫結全部幾何體 |
此時,顏色陣列或者法線座標陣列中只需要儲存一個數據,該資料將影響此Geometry類的所有頂點座標。例如,將紅色繫結到全部幾何體上,則這個類繪製出的所有物體均是紅色的。 |
BIND_PER_PRIMITIVE |
繫結逐個幾何體 |
此時,顏色陣列或者法線座標陣列中儲存的資料數量應當與使用者將要繪製的幾何體數量相同。例如,使用者依據8個頂點來繪製兩個四邊形時,可以分別為它們設定兩個法線座標,並使用此引數進行繫結。 |
BIND_PER_VERTEX |
繫結逐個點 |
逐點繫結。比如上面的例子,將四個顏色資料分別繫結到四個頂點座標,可以實現頂點顏色之間的過渡效果。 |
osg::PrimitiveSet類,該類主要鬆散封裝了OpenGL的繪圖基元,通過指定繪圖基元來指定幾何體頂點將採用哪一種或幾種基元繪製。繼承關係如下圖所示,
PrimitiveSet:提供了opengl頂點陣列繪圖命令的高層次支援。使用者可以從Geometry中獲得儲存的資料,再使用這個類制定要繪製的幾何體資料的型別。
在給geometry設定完頂點、顏色、法線、紋理以後,必須通過
geom1->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4));
來指定要利用這些資料生成一個怎麼樣的形狀。
該行程式碼中,使用DrawArrays類向Geometry類送入了新幾何體的資訊,即,該幾何體是一個QUADS,它的頂點座標從索引陣列中讀入,從第1個索引值開始,共讀入4個索引值,組成一個四邊形圖形。
幾何體的形狀引數除了QUADS之外,還有數種方式,以用於不同的使用者需求,列表如下:
POINTS |
繪製點 |
繪製使用者指定的所有頂點。 |
LINES |
繪製直線 |
直線的起點、終點由陣列中先後相鄰的兩個點決定;使用者提供的點不止兩個時,將嘗試繼續繪製新的直線。 |
LINE_STRIP |
繪製多段直線 |
多段直線的第一段由陣列中的前兩個點決定;其餘段的起點位置為上一段的終點座標,而終點位置由陣列中隨後的點決定。 |
LINE_LOOP |
繪製封閉直線 |
繪圖方式與多段直線相同,但是最後將自動封閉該直線。 |
TRIANGLES |
繪製三角形 |
三角形的三個頂點由陣列中相鄰的三個點決定,並按照逆時針的順序進行繪製;使用者提供的點不止三個時,將嘗試繼續繪製新的三角形。 |
TRIANGLE_STRIP |
繪製多段三角形 |
第一段三角形的由陣列中的前三個點決定;其餘段三角形的繪製,起始邊由上一段三角形的後兩個點決定,第三點由陣列中隨後的一點決定。 |
TRIANGLE_FAN |
繪製三角扇面 |
第一段三角形的由陣列中的前三個點決定;其餘段三角形的繪製,起始邊由整個陣列的第一點和上一段三角形的最後一個點決定,第三點由陣列中隨後的一點決定。 |
QUADS |
繪製四邊形 |
四邊形的四個頂點由陣列中相鄰的四個點決定,並按照逆時針的順序進行繪製;使用者提供的點不止四個時,將嘗試繼續繪製新的四邊形。 |
QUAD_STRIP |
繪製多段四邊形 |
第一段四邊形的起始邊由陣列中的前兩個點決定,邊的向量方向由這兩點的延伸方向決定;起始邊的對邊由其後的兩個點決定,如果起始邊和對邊的向量方向不同,那麼四邊形將會扭曲;其餘段四邊形的繪製,起始邊由上一段決定,其對邊由隨後的兩點及其延伸方向決定。 |
POLYGON |
繪製任意多邊形 |
根據使用者提供的頂點的數量,繪製多邊形。 |
和opengl對比:
osg::PrimitiveSet::POINTS對應OpenGL中的GL_POINTS繪製單獨的點
osg::PrimitiveSet::LINES對應OpenGL中的GL_LINES繪製每兩點連線的線
osg::PrimitiveSet::LINE_STRIP對應OpenGL中的GL_LINE_STRIP繪製依次連線各點的線
osg::PrimitiveSet::LINE_LOOP對應OpenGL中的GL_LINE_LOOP繪製依次連線各點的線,首尾相連
osg::PrimitiveSet::POLYGON對應OpenGL中的GL_POLYGON繪製依次連線各點的多邊形
osg::PrimitiveSet::QUADS對應OpenGL中的GL_QUADS繪製依次連線每四點的四邊形
如:1、2、3、4、5、6、7、8點 繪製結果1、2、3、4組成四邊形,5、6、7、8組成四邊形
osg::PrimitiveSet::QUAD_STRIP對應OpenGL中的GL_QUAD_STRIP繪製四邊形
如:1、2、3、4、5、6、7、8點 繪製結果1、2、3、4組成四邊形,3、4、5、6組成四邊形、5、
6、7、8組成四邊形
osg::PrimitiveSet::TRIANGLES對應OpenGL中的GL_TRIANGLES繪製每三點連線的三角形
如:1、2、3、4、5、6點 繪製結果1、2、3組成三角形,4、5、6組成三角形
osg::PrimitiveSet::TRIANGLE_STRIP對應OpenGL中的GL_TRIANGLE_STRIP
如:1、2、3、4、5、6點 繪製結果1、2、3組成三角形,2、3、4組成三角形,3、4、5組成三角
形4、5、6組成三角形
osg::PrimitiveSet::TRIANGLE_FAN對應OpenGL中的GL_TRIANGLE_FAN
如:1、2、3、4、5、6點 繪製結果1、2、3組成三角形,1、3、4組成三角形,1、4、5組成三角
形,1、5、6組成三角形