赞
踩
对于节点的访问是从节点接收一个访问器开始的,用户执行某个节点的accept()函数,将一个具体的访问器对象传递给节点。
第二步,节点反过来执行访问器的apply()函数,并将自身传入访问器。
这两步的实现过程可以用一行十分简单的函数代码来表达:
- void Node::accept(NodeVisitor& nv)
- {
- nv.apply(*this);
- }
最后,在具体访问器对象中重写的apply()函数中,执行节点的具体访问操作。使用一个自定义访问器UserVisitor来访问已知场景节点树:
- UserVisitor visitor;
- subgraph->accept(visitor);
- #include <osg/Node>
- #include <osgDB/ReadFile>
- #include <iostream>
-
- class InfoVisitor : public osg::NodeVisitor
- {
- public:
- InfoVisitor(): osg::NodeVisitor(TRAVERSE_ALL_CHILDREN), _indent(0){} //向子节点遍历
-
- virtual void apply( osg::Node &node){ //获取访问节点对象,并执行自定义节点操作
- //当访问到默认的Node节点时,使用该函数打印节点的名称
- //并根据节点层次适当使用_indent缩进
- for ( int i = 0; i < _indent; ++i)
- {
- std::cout<< " ";
- }
- std::cout<< "["<< _indent + 1<< "]"<< node.libraryName()
- << "::"<< node.className()<< std::endl;
-
- _indent++;
- traverse( node); //向下一个需要的节点推进
- _indent--;
- }
-
- //当访问到Geode节点时,不仅打印叶节点的名称属性,还打印叶节点所包含的所有可绘制体的名称
- virtual void apply( osg::Geode& node){
- for ( int i = 0; i < _indent; ++i)
- {
- std::cout<< " ";
- }
- std::cout<< "["<< _indent + 1<<"]"<< node.libraryName()
- << "::"<< node.className()<< std::endl;
-
- for (unsigned int n = 0; n < node.getNumDrawables(); ++n)
- {
- osg::Drawable* drawable = node.getDrawable(n);
-
- if(!drawable) continue;
-
- for(int i = 0; i <= _indent; ++i){
- std::cout<< " ";
- }
- std::cout<< drawable->libraryName()<< "::"
- << drawable->className()<< std::endl;
- }
-
- _indent ++;
- traverse( node);
- _indent --;
- }
-
- protected:
- int _indent;
- };
-
-
- int main()
- {
- osg::ref_ptr<osg::Node> root = osgDB::readNodeFile("axes.osgt");
-
- InfoVisitor infoVisitor;
- if (root)
- {
- root->accept( infoVisitor); //接受自定义访问器
- }
-
-
- return 0;
- }
root->accept( infoVisitor);
谁调用accept,就以此为根结点向下进行深度优先遍历,如果想向上遍历,就将traverse()函数改为ascend()函数;
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。