二、场景管理
2.1 遍历场景图
场景图遍历类型有以下几种:
(1) 事件遍历:在遍历节点时,处理鼠标和键盘输入。
(2) 更新遍历:用于修改场景图,添加节点,设置节点属性,执行回调。
(3) 裁剪遍历:根据节点是否位于一个视口内来筛选节点,裁剪掉不可见和不可用的节点。
(4) 绘制遍历:调用OpenGL API 来渲染场景。
1 osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(&nv); 2 if ( cv ) 3 { 4 // Do something 5 }
访问者模式用来表示在一个图结构上所执行的用户操作,而无需修改这些元素的类。访问者模式依据接收者元素与访问者本身的运行时类型,分派一定的虚函数调用。我们可以自定义访问者来来遍历场景图,无需修改场景节点的接口。要创建一个访问者子类,必须重新实现osg::NodeVisitor基类中所声明的一个或多个apply()虚重载方法。这些方法是为大多数主要的OSG节点类型所设计的。访问者会在遍历过程中为他所访问的每一个节点自动调用相应的apply()方法。自定义apply方法中,我们需要在合适的位置调用osg::NodeVisitor的traverse()方法,自动访问到其他节点。示例为自定义访问者收集节点信息。
1 #include <osgDB/ReadFile> 2 #include <osgViewer/Viewer> 3 #include <iostream> 4 class InfoVisitor : public osg::NodeVisitor 5 { 6 public: 7 InfoVisitor() : _level(0) 8 { setTraversalMode(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN); } 9 10 std::string spaces() 11 { return std::string(_level*2, ' '); } 12 13 Virtual void apply( osg::Node& node ); 14 virtual void apply( osg::Geode& geode ); 15 16 protected: 17 unsigned int _level; 18 }; 19 void InfoVisitor::apply( osg::Node& node ) 20 { 21 std::cout << spaces() << node.libraryName() << "::" 22 << node.className() << std::endl; 23 24 _level++; 25 traverse( node ); 26 _level--; 27 } 28 void apply( osg::Geode& geode ) 29 { 30 std::cout << spaces() << geode.libraryName() << "::" 31 << geode.className() << std::endl; 32 33 _level++; 34 for ( unsigned int i=0; i<geode.getNumDrawables(); ++i ) 35 { 36 osg::Drawable* drawable = geode.getDrawable(i); 37 std::cout << spaces() << drawable->libraryName() << "::" 38 << drawable->className() << std::endl; 39 } 40 41 traverse( geode ); 42 _level--; 43 } 44 int main() 45 { 46 osg::ArgumentParser arguments( &argc, argv ); 47 osg::ref_ptr<osg::Node> root = osgDB::readNodeFiles( arguments ); 48 if ( !root ) 49 { 50 OSG_FATAL << arguments.getApplicationName() <<": No data 51 loaded." << std::endl; 52 return -1; 53 } 54 InfoVisitor infoVisitor; 55 root->accept( infoVisitor ); 56 osgViewer::Viewer viewer; 57 viewer.setSceneData( root.get() ); 58 return viewer.run(); 59 }
2.2 设置渲染状态
osg::StateSet类封装了OpenGL状态机,在裁剪和渲染遍历中通过push和pop管理渲染状态。osg::StateAttribute类记录了渲染状态属性,渲染模式的作用类似于可以打开和关闭的开关,包含指示OpenGL模式类型的枚举参数。osg::StateSet类将属性与模式分为两类:纹理和非纹理。示例为设置节点属性为多边形模式。
1 osg::ref_ptr<osg::PolygonMode> pm = new osg::PolygonMode; 2 pm->setMode(osg::PolygonMode::FRONT_AND_BACK, 3 osg::PolygonMode::LINE); 4 transformation1->getOrCreateStateSet()->setAttribute( pm.get() );
多边形模式不需要使用setMode()方法。
节点的状态集将会影响当前节点和子节点。子节点将继承父节点的状态集。osg::StateAttribute::OVERRIDE表示所有子节点状态被覆盖; StateAttribute::PROTECTED表示保持子节点自身状态集不变,优先度高。示例为两个飞机模型节点,改变节点状态时分别用OVERRIDE和PROTECTED标记,结果只有transformation2状态改变。
1 transformation1->getOrCreateStateSet()->setMode( GL_LIGHTING, 2 osg::StateAttribute::OFF ); 3 transformation2->getOrCreateStateSet()->setMode( GL_LIGHTING, 4 osg::StateAttribute::OFF|osg::StateAttribute::PROTECTED); 5 root->getOrCreateStateSet()->setMode( GL_LIGHTING, 6 osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE );
osg中支持的渲染属性和模式:
示例为创建四边形并加载显示纹理。
1 #include <osg/Texture2D> 2 #include <osg/Geometry> 3 #include <osgDB/ReadFile> 4 #include <osgViewer/Viewer> 5 int main() 6 { 7 osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array; 8 vertices->push_back( osg::Vec3(-0.5f, 0.0f,-0.5f) ); 9 vertices->push_back( osg::Vec3( 0.5f, 0.0f,-0.5f) ); 10 vertices->push_back( osg::Vec3( 0.5f, 0.0f, 0.5f) ); 11 vertices->push_back( osg::Vec3(-0.5f, 0.0f, 0.5f) ); 12 osg::ref_ptr<osg::Vec3Array> normals = new osg::Vec3Array; 13 normals->push_back( osg::Vec3(0.0f,-1.0f, 0.0f) ); 14 osg::ref_ptr<osg::Vec2Array> texcoords = new osg::Vec2Array; 15 texcoords->push_back( osg::Vec2(0.0f, 0.0f) ); 16 texcoords->push_back( osg::Vec2(0.0f, 1.0f) ); 17 texcoords->push_back( osg::Vec2(1.0f, 1.0f) ); 18 texcoords->push_back( osg::Vec2(1.0f, 0.0f) ); 19 osg::ref_ptr<osg::Geometry> quad = new osg::Geometry; 20 quad->setVertexArray( vertices.get() ); 21 quad->setNormalArray( normals.get() ); 22 quad->setNormalBinding( osg::Geometry::BIND_OVERALL ); 23 quad->setTexCoordArray( 0, texcoords.get() ); 24 quad->addPrimitiveSet( new osg::DrawArrays(GL_QUADS, 0, 4) ); 25 26 osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D; 27 osg::ref_ptr<osg::Image> image = 28 osgDB::readImageFile( "Images/lz.rgb" ); 29 texture->setImage( image.get() ); 30 31 osg::ref_ptr<osg::Geode> root = new osg::Geode; 32 root->addDrawable( quad.get() ); 33 root->getOrCreateStateSet()->setTextureAttributeAndModes( 34 0, texture.get() ); 35 36 osg::ref_ptr<osg::Geode> root = new osg::Geode; 37 root->addDrawable( quad.get() ); 38 root->getOrCreateStateSet()->setTextureAttributeAndModes( 39 0, texture.get() ); 40 osgViewer::Viewer viewer; 41 viewer.setSceneData( root.get() ); 42 return viewer.run(); 43 }
osg::setRenderingHint方法设置节点渲染顺序。确保半透明对象在不透明对象之后渲染,
示例为正确显示一个半透明对象。
1 #include <osg/BlendFunc> 2 #include <osg/Texture2D> 3 #include <osg/Geometry> 4 #include <osgDB/ReadFile> 5 #include <osgViewer/Viewer> 6 int main() 7 { 8 osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array; 9 vertices->push_back( osg::Vec3(-0.5f, 0.0f,-0.5f) ); 10 vertices->push_back( osg::Vec3( 0.5f, 0.0f,-0.5f) ); 11 vertices->push_back( osg::Vec3( 0.5f, 0.0f, 0.5f) ); 12 vertices->push_back( osg::Vec3(-0.5f, 0.0f, 0.5f) ); 13 osg::ref_ptr<osg::Vec3Array> normals = new osg::Vec3Array; 14 normals->push_back( osg::Vec3(0.0f,-1.0f, 0.0f) ); 15 osg::ref_ptr<osg::Vec2Array> texcoords = new osg::Vec2Array; 16 texcoords->push_back( osg::Vec2(0.0f, 0.0f) ); 17 texcoords->push_back( osg::Vec2(0.0f, 1.0f) ); 18 texcoords->push_back( osg::Vec2(1.0f, 1.0f) ); 19 texcoords->push_back( osg::Vec2(1.0f, 0.0f) ); 20 21 osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array; 22 colors->push_back( osg::Vec4(1.0f, 1.0f, 1.0f, 0.5f) ); 23 24 osg::ref_ptr<osg::Geometry> quad = new osg::Geometry; 25 quad->setVertexArray( vertices.get() ); 26 quad->setNormalArray( normals.get() ); 27 quad->setNormalBinding( osg::Geometry::BIND_OVERALL ); 28 quad->setColorArray( colors.get() ); 29 quad->setColorBinding( osg::Geometry::BIND_OVERALL ); 30 quad->setTexCoordArray( 0, texcoords.get() ); 31 quad->addPrimitiveSet( new osg::DrawArrays(GL_QUADS, 0, 4) ); 32 osg::ref_ptr<osg::Geode> geode = new osg::Geode; 33 geode->addDrawable( quad.get() ); 34 35 osg::ref_ptr<osg::Geometry> quad = new osg::Geometry; 36 quad->setVertexArray( vertices.get() ); 37 quad->setNormalArray( normals.get() ); 38 quad->setNormalBinding( osg::Geometry::BIND_OVERALL ); 39 quad->setColorArray( colors.get() ); 40 quad->setColorBinding( osg::Geometry::BIND_OVERALL ); 41 quad->setTexCoordArray( 0, texcoords.get() ); 42 quad->addPrimitiveSet( new osg::DrawArrays(GL_QUADS, 0, 4) ); 43 osg::ref_ptr<osg::Geode> geode = new osg::Geode; 44 geode->addDrawable( quad.get() ); 45 46 osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D; 47 osg::ref_ptr<osg::Image> image = 48 osgDB::readImageFile( "Images/lz.rgb" ); 49 texture->setImage( image.get() ); 50 51 osg::ref_ptr<osg::BlendFunc> blendFunc = new osg::BlendFunc; 52 blendFunc->setFunction( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); 53 54 osg::StateSet* stateset = geode->getOrCreateStateSet(); 55 stateset->setTextureAttributeAndModes( 0, texture.get() ); 56 stateset->setAttributeAndModes( blendFunc ); 57 stateset->setRenderingHint( osg::StateSet::TRANSPARENT_BIN ); 58 59 osg::ref_ptr<osg::Group> root = new osg::Group; 60 root->addChild( geode.get() ); 61 root->addChild( osgDB::readNodeFile("glider.osg") ); 62 osgViewer::Viewer viewer; 63 viewer.setSceneData( root.get() ); 64 return viewer.run(); 65 66 }
标签:get,渲染,OSG,设置,new,quad,ref,ptr,osg From: https://www.cnblogs.com/wangxydela/p/17321607.html