赞
踩
OSG中节点的访问使用的是一种访问器模式。一个典型的访问器涉及如下角色:
OSG中访问者角色为NodeVisitor类,其基本结构如下:
- NodeVisitor(TraversalMode tm) // 构造函数,TraversalMode为节点树的遍历方式
- // TRAVERSE_NONE, 仅当前节点
- // TRAVERSE_PARENTS, 向当前节点的父节点遍历
- // TRAVERSE_ALL_CHILDREN, 向子节点遍历
- void traverse(Node& node) // 向下一个需要访问的节点推进
- void apply(Node& node) // 虚函数,访问各种节点类型,并执行访问器中的自定义操作
- void apply(Group& node)
- void apply(Geode& node)
- …………
NodeVisitor 只是访问器角色的抽象接口,要使用访问器访问节点并执行自定义操作时,需要继承并重写apply(……)函数实现自定义功能。osg::Node类中的访问接口为:
void accept(NodeVisitor& nv)
对节点的访问从节点接受一个访问器开始,将一个具体的访问器对象传递给节点,节点反过来执行访问器的apply(...)函数,并将自己传入访问器。可如下简单表示:
- void Node::accept(NodeVisitor& nv) //节点访问与遍历从这个函数开始实施
- {
- if (nv.validNodeMask(*this))
- {
- nv.pushOntoNodePath(this); //将节点Node加入到一个Vector<Node*>中
- nv.apply(*this);
- nv.popFromNodePath();
- }
- }
-
- void NodeVisitor::apply(Node& node) //基类的虚函数中没有实现操作,只需进行遍历
- {
- traverse(node);
- }
遍历节点树:
osg::Node类中有两个辅助函数:
- void ascend(NodeVisitor& nv) // 虚函数,向上一级节点推进访问器
- void traverse(NodeVisitor& nv) // 虚函数,向下一级节点推进访问器
NodeVisitor的traverse()函数实现如下:
- inline void traverse(Node& node)
- {
- if (_traversalMode == TRAVERSE_PARENTS)
- node.ascend(*this);
- else if (_traversalMode != TRAVERSE_NONE)
- node.traverse(*this); //调用子集的accept函数,关联访问器进行遍历操作
- }
Node类中的traverse()为空,具体实现是在Group类中
- void Group::traverse(NodeVisitor& nv)
- {
- for(NodeList::iterator itr=_children.begin();
- itr!=_children.end();
- ++itr)
- {
- (*itr)->accept(nv);
- }
- }
示例代码
- #include <osg/Node>
- #include <osgDB/ReadFile>
- #include <iostream>
-
-
- using namespace std;
- class InfoVisitor: public osg::NodeVisitor
- {
-
- public:
-
- InfoVisitor()
- :osg::NodeVisitor(TRAVERSE_ALL_CHILDREN), _indent(0)
-
- {}
-
- virtual void apply(osg::Node& node)
- {
-
- for(int i = 0; i < _indent; i++) cout << " ";
- cout << "[" << _indent << "]"<< node.libraryName()
-
- << "::" << node.className() << endl;
-
- _indent++;
- traverse(node);
- _indent--;
-
- for(int i = 0; i < _indent; i++) cout << " ";
- cout << "[" << _indent << "] "<< node.libraryName()
- << "::" << node.className() << endl;
-
- }
-
- virtual void apply(osg::Geode& node)
- {
-
- for(int i = 0; i < _indent; i++) cout << " ";
- cout << "[" << _indent << "] "<< node.libraryName()
- << "::" << node.className() << endl;
-
- _indent++;
- for(unsigned int n = 0; n < node.getNumDrawables(); n++)
- {
-
- osg::Drawable* draw = node.getDrawable(n);
- if(!draw)
- continue;
-
- for(int i = 0; i < _indent; i++) cout << " ";
- cout << "[" << _indent << "]" << draw->libraryName() << "::"
- << draw->className() << endl;
-
- }
-
- traverse(node);
- _indent--;
-
- for(int i = 0; i < _indent; i++) cout << " ";
- cout << "[" << _indent << "]"<< node.libraryName()
- << "::" << node.className() << endl;
-
- }
-
- private:
- int _indent;
- };
-
-
- int main(int argc, char** argv)
- {
-
- osg::ArgumentParser parser(&argc, argv);
- osg::Node* root = osgDB::readNodeFiles(parser);
-
- if(!root)
- {
- root = osgDB::readNodeFile("2.OSGB");
- }
-
- InfoVisitor infoVisitor;
- if(root)
- {
-
- root->accept(infoVisitor);
- }
-
- system("pause");
- return 0;
-
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。