OSG QuickStartGuide - eiichiromomma/CVMLAB GitHub Wiki
(OSG) Quick Start Guide
Quick Start Guideに沿ったメモ書き
-
OpenSceneGraph Quick Start Guide | OpenSceneGraph Books
- 入手には登録が必要だがPaypalを選択すればカードの入力は不要。
- root nodeからのツリー構造
- メモリ管理はGCがあるのでroot nodeをdeleteするだけで連鎖反応で消える
- 殆どのオブジェクトはリファレンスカウンタを持っている
- smart pointerのosg::ref_ptr<>を使うこと
- C++のレギュラーなポインタは使わない
- ref(),unref()は直接使わない
- get()でprivateなpointerを得る
- valid()でtrueならnullでない
- ref_ptrを返り値にしたい場合はreturn obj.get()とする
//
// OpenSceneGraph Quick Start Guide
// http://www.lulu.com/content/767629
// http://www.openscenegraph.com/osgwiki/pmwiki.php/Documentation/QuickStartGuide
//
// Simple Example, Basic Geode and Geometry class usage
#include <osg/Geode>
#include <osg/Geometry>
osg::ref_ptr<osg::Node>
createSceneGraph()
{
// Create an object to store geometry in.
osg::ref_ptr<osg::Geometry> geom = new osg::Geometry;
// Create an array of four vertices.
#if 1
// Using the push_back interface
osg::ref_ptr<osg::Vec3Array> v = new osg::Vec3Array;
geom->setVertexArray( v.get() );
v->push_back( osg::Vec3( -1.f, 0.f, -1.f ) );
v->push_back( osg::Vec3( 1.f, 0.f, -1.f ) );
v->push_back( osg::Vec3( 1.f, 0.f, 1.f ) );
v->push_back( osg::Vec3( -1.f, 0.f, 1.f ) );
#else
// Using resize() and operator[]().
osg::ref_ptr<osg::Vec3Array> v = new osg::Vec3Array;
geom->setVertexArray( v.get() );
v->resize( 4 );
(*v)[ 0 ] = osg::Vec3( -1.f, 0.f, -1.f );
(*v)[ 1 ] = osg::Vec3( 1.f, 0.f, -1.f );
(*v)[ 2 ] = osg::Vec3( 1.f, 0.f, 1.f );
(*v)[ 3 ] = osg::Vec3( -1.f, 0.f, 1.f );
#endif
// Create an array of four colors.
osg::ref_ptr<osg::Vec4Array> c = new osg::Vec4Array;
geom->setColorArray( c.get() );
geom->setColorBinding( osg::Geometry::BIND_PER_VERTEX );
c->push_back( osg::Vec4( 1.f, 0.f, 0.f, 1.f ) );
c->push_back( osg::Vec4( 0.f, 1.f, 0.f, 1.f ) );
c->push_back( osg::Vec4( 0.f, 0.f, 1.f, 1.f ) );
c->push_back( osg::Vec4( 1.f, 1.f, 1.f, 1.f ) );
// Create an array for the single normal.
osg::ref_ptr<osg::Vec3Array> n = new osg::Vec3Array;
geom->setNormalArray( n.get() );
geom->setNormalBinding( osg::Geometry::BIND_OVERALL );
n->push_back( osg::Vec3( 0.f, -1.f, 0.f ) );
// Draw a four-vertex quad from the stored data.
geom->addPrimitiveSet(
new osg::DrawArrays( osg::PrimitiveSet::QUADS, 0, 4 ) );
// Add the Geometry (Drawable) to a Geode and return the Geode.
osg::ref_ptr<osg::Geode> geode = new osg::Geode;
geode->addDrawable( geom.get() );
return geode.get();
}
-
Vectorはpush_back()でストア、単品で宣言してもresize()で配列にできる
osg::ref_ptrosg::Vec3Array v = new osg::Vec3Array; geom->setVertexArray(v.get()); v.resize(4); (*v)[0] = osg::Vec3(-1.f, 0.f, -1.f); (*v)[1] = ...
みたいな感じ
- osg::Drawableは仮想基本クラス。直接扱うことはない。3つのサブクラスがある。
- osg::DrawPixels - glDrawPixelsのラッパー
- osg::ShapeDrawable - 円柱、球等のpredefinedなShapeへのアクセス
- osg::Geometry - フレキシブルでジオメトリやレンダリングに用いる。最も使われる。
- Vec3Array - setVertexArray(),setNormalArray() <-> glVertexPointer(), glNormalPointer()
- Vec4Array - setColorArray() <-> glColorPointer()
- setColorBinding(), setNormalBinding() - どう色と法線を扱うか。enumになっている
- osg::Geometry::BIND_PER_VERTEX - 各頂点(ソースでは色に使ってる)
- osg::Geometry::BIND_OVERALL - 共通(法線に使った)
- addPrimitiveSet() - Geometryにどうレンダーすれば良いか教える。osg::PrimitiveSetを引数にするが、これは仮想基本クラス
- osg::DrawArraysはPrimitiveSetの派生。glDrawArraysのラップみたいなもん osg::DrawArrays:DrawArrays(GLenum mode, GList first, GLsizei count)
と定義されるので、modeはGLのプリミティブでもosg::PrimitiveSet::POINTSのenumでも良い。firstはOSGが扱うエレメントの数。countは頂点の数。2,6なら
頂点 | 0 | 1 | 2 | 3 | 4 | 5 | 0 | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
エレメント | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 |
って事か?
- Geodeはレンダリングに使うGeometryをストアするためのleaf node。 osg::Nodeの派生。
- Geode is short for "geometry node" (a node contains geometry)とある
- いかなるgeometryもGeodeにattachされなければレンダリングできない
- GeodeのaddDrawable()によってgeometryをGeodeにattachできる
- Geode::addDrawable()はDrawableへのポインタが引数。geometryのget()でポインタを入れる
Group NodesはReferencedおよびNodeからの派生。Transform, LOD, Switch等に派生する
- nodeの殆どはGroupからの派生 = 殆どのnodeがChild Interfaceを持つ
- std::vector<ref_ptr>にchildrenを持つ(子ノードに関するI/F)
- addChild, removeChild, replaceChild, getNumChildren, containsNode
- std::vector<Group*>に親リストを持つ
- 通常は1つの親しか持たないが、同一の物を別の手法でレンダリングしたい場合などに複数となる
- getParents, getParent, getNumParents
- std::vector<ref_ptr>にchildrenを持つ(子ノードに関するI/F)
Groupからの派生。仮想クラスでosg::MatrixTransformやosg::PositionAttitudeTransformへ派生
内部でMatrixを使う
- MatrixはReferencedからの派生ではないのでローカルに消滅する値として扱う
- OpenGLのように1次元16個で4x4でも表現可
- m(0,1)みたいな指定も可
- osg::Matrix mで宣言し、m.set(....)としてmt.setMatrix(m)のように指定する
位置ベクトル(Vec3)とクォータニオンを使う
- osg::Quat - クォータニオン。Referencedからの派生ではないのでローカルに扱う
- 回転軸+角度の指定でも、ヨー、ピッチ、ロールの軸と回転角の指定でも作れる
Levels of Detail。Groupからの派生。
- distanceのmaxとminを指定でき、外れると表示されない
- addChildで指定
- デフォルトでdistanceは視点からbounding volumeの中心
- setCenterMode(osg::LOD::USER_DEFINED_CENTER)でsetCenter
- distanceの代わりにピクセルサイズを基準にもできる(setRangeMode)
Groupからの派生。LOD Nodeのdistanceの代わりに直接的なスイッチがありtrue, falseで表示、非表示
OpenGLのパイプラインレンダリング(ライティング、ブレンディング、クリッピング、カラーマスク、カル、フォグ、デプス、ステンシル、ラスタライズなどなど)をサポート。StateSetクラスを使う
-
頂点およびフラグメントshaderが使える
-
Node, Drawableへattachして使う
-
冗長性の排除は自動的に最適化される
-
OpenGLの属性も利用可能
-
NodeやDrawableごとにstateが保持される
-
Referencedからの派生でもあるため、NodeやDrawableで余計なことを考えずに共有できる
-
属性(Attributes)とモード(Modes)に分類される
- Attributes:レンダリングの特徴量をコントロールする(フォグ、ブレンド等)
- Modes:OpenGLのglEnable(), glDisableに対応する。(テクスチャ、ライティング) 要するにオンオフ
-
NodeかDrawableのgetOrCreateStateSet()でStateSetのポインタを取得して使う
-
設定する属性のクラスはStateAttributeから派生
- テクスチャだけは特別な扱いが必要
-
Attributeの設定はosg::StateSet::setAttribute()
-
Modeの設定はosg::StateSet::setMode()
-
いっぺんに両方設定するにはosg::StateSet::setAttributeAndModes()
- ModeがデフォルトでオンのsetAttribute()みたいなもん
-
Stateの継承は子ノードがその項目を弄ってなければ行なわれる
- osg::StateAttribute::OVERRIDE - とりあえず上書き
- osg::StateAttribute::PROTECTED - 独自の属性は保護される
- osg::StateAttribute::INHERIT - 子のstateは消去され常に親のstate を参照する
テクスチャ座標をgeometryに割り当て、texture attributeオブジェクトを作成し、テクスチャ用image dataをstoreする。そしてStateSetに適当なtexture attributeとmodeをsetする。
- Geometryはテクスチャ座標を設定できる
- 当然対応するテクスチャunitを設定する必要もある
- OSGはtexture unit valueをmulti textureのために使う
- 座標はosg::Vec2Array
- osg::Vec2をbushu_back()する
- geom->setTexCoordArray(texture unit, Vec2Array)
- ちなみにbindingについては常にbound per pixelなので宣言不要
- osg::Texture2Dとosg::Imageが2Dテクスチャマッピングに必要
- Texture2DはOpenGLテクスチャオブジェクトをmanageするStateAttribute
- Imageはピクセルデータをmanageする
- ファイルから2D画像を得るにはosgDBライブラリを使う
- Imageオブジェクトを作って、ImageをTexture2Dにattachする役割 (P65にソース)
readImageFIle()は新しいImageオブジェクトを作成し、ファイルを読みImageへstoreし、Imageオブジェクトを返す(詳細はI/Oの所)
- Texture2D attributeを設定したらStateSetへattachする
- この処理はメモリをガシガシ食うのでImageはReferencedから派生され、Texture2DはImageのref_ptr<>を保持する
- メモリをカツカツに節約したい場合は、レンダーすると勝手に生成されるOpenGL managedなデータとImageオブジェクトの2つのうち、後者をreleaseすれば良い
- デフォルトでは放置
- メモリをカツカツに節約したい場合は、レンダーすると勝手に生成されるOpenGL managedなデータとImageオブジェクトの2つのうち、後者をreleaseすれば良い
- 中身は前述のnon-textureなstateとほぼ同じ
- StateSetへattachするにはosg::StateSet::setTextureAttribute()
- 第一引数はtexture unit, 第二はStateAttributeからの派生のtexture attribute
- texture attributeにはTexture1D, Texture2D, Texture3D, TextureCubeMap, TextureREctangleとテクスチャ座標生成のosg::TexGenがある (P66参照)
- 第一引数はtexture unit, 第二はStateAttributeからの派生のtexture attribute
- モードはosg::StateSet::setTextureMode()
- non-textureなmodeとほぼ同じ
- OpenGLのlightingを完全サポート
- OpenGL同様に光源は見えない
- bulbその他の物理的約束事はレンダーしない
- shading効果は生成するが影(shadow)は作らない
- NodeKitのosgShadowを使う
- geometryの法線を設定する
- lightingを有効にし、その他のlighting stateを設定する
- 光源のpropertiesを設定し、シーングラフにattachする
- surface material propertiesを設定する
- Chapter3のosgViewerライブラリを使う場合はGL_LIGHT0が定義済みなので注意
-
性格なlightingには単位長を持った法線ベクトルが必要
- Geodes and GEometry(2.2)で解説済み
-
必ず正規化するのを忘れないこと
- 変換処理をしているとnormalのscaleも変わってくる
- StateSetでrescaleが望ましい
- これはuniform scalingによる影響を受けた時のみ作用する
- non uniformの場合はGL_NORMALIZEとするが、計算コストがかかるので極力避ける
osg::StateSet* state = geode->getOrCreateStateSet(); state->setMode(GL_RESCALE_NORMAL, osg::StateAttribute::ON);
- lightingを有効にして少なくとも1つは光源を用意する
- osgviewerアプリではroot nodeのStateSetに設定している
- P68のソースはroot nodeのStateSetに2つのライトを設定している
- osg::LightModelStateAttributeでOpenGLのlightingの特性をコントロールする
- osg::Lightをosg::LightSourceノードに加え、これをシーングラフに加える
- 最大8子まで使用可 GL_LIGHT0〜7(OpenGLの実装に依存)
- 応用的な方法はこのガイドでは述べない
- setLightNum(2)とするとGL_LIGHT2になる
- glLight()と同様に色々設定可能(P69)
- LightSource nodeを作成
- LightをLightSourceに加える
- シーングラフにLightSourceをattach
- どこのシーンに突っ込むかでLightの位置に影響する
- LightSource nodeのあるレベルで位置変換の影響を受ける
- よくやるのはMatrixTransformのchildとしてLightSourceをattachする
(P70 source)
Transformノードでのやり方と同様に変換されないようにもできる(2.3.3) osg::ref_ptrosg::LightSource ls = new osg::LightSource; ls->setReferenceFrame(osg::LightSource::ABSOLUTE_RF);
- OpenGLのglMaterial()やglColorMaterial()と同様
- Materialオブジェクトを作成し、パラメータ設定してからシーングラフにattachする
- カラーモードは有効にしただけコストがかかるので、使わなければ勝手にOFFになる。setAttributeAndModels()は不要