当前位置:   article > 正文

osg节点访问和遍历_osg遍历节点

osg遍历节点

        OSG中节点的访问使用的是一种访问器模式。一个典型的访问器涉及如下角色:

  • 抽象访问者角色(Visitor)。
  • 具体访问者(Concrete Visitor)。
  • 节点角色(Node)。

OSG中访问者角色为NodeVisitor类,其基本结构如下:  

  1. NodeVisitor(TraversalMode tm)    // 构造函数,TraversalMode为节点树的遍历方式
  2.                     // TRAVERSE_NONE, 仅当前节点
  3.                     // TRAVERSE_PARENTS, 向当前节点的父节点遍历
  4.                     // TRAVERSE_ALL_CHILDREN, 向子节点遍历
  5.   void traverse(Node& node)  // 向下一个需要访问的节点推进
  6.   void apply(Node& node)    // 虚函数,访问各种节点类型,并执行访问器中的自定义操作
  7.   void apply(Group& node)
  8.   void apply(Geode& node)
  9.   …………

NodeVisitor 只是访问器角色的抽象接口,要使用访问器访问节点并执行自定义操作时,需要继承并重写apply(……)函数实现自定义功能。osg::Node类中的访问接口为:

void accept(NodeVisitor& nv)

        对节点的访问从节点接受一个访问器开始,将一个具体的访问器对象传递给节点,节点反过来执行访问器的apply(...)函数,并将自己传入访问器。可如下简单表示:

  1. void Node::accept(NodeVisitor& nv)  //节点访问与遍历从这个函数开始实施
  2. {
  3.     if (nv.validNodeMask(*this)) 
  4.     {
  5.         nv.pushOntoNodePath(this);  //将节点Node加入到一个Vector<Node*>中
  6.         nv.apply(*this);
  7.         nv.popFromNodePath();
  8.     }
  9. }
  10. void NodeVisitor::apply(Node& node)  //基类的虚函数中没有实现操作,只需进行遍历
  11. {
  12.     traverse(node);
  13. }

遍历节点树
 osg::Node类中有两个辅助函数:  

  1. void ascend(NodeVisitor& nv)     // 虚函数,向上一级节点推进访问器
  2. void traverse(NodeVisitor& nv)   // 虚函数,向下一级节点推进访问器

  NodeVisitor的traverse()函数实现如下:  

  1. inline void traverse(Node& node)
  2.       {
  3.             if (_traversalMode == TRAVERSE_PARENTS) 
  4.         node.ascend(*this);
  5.             else if (_traversalMode != TRAVERSE_NONE) 
  6.         node.traverse(*this);   //调用子集的accept函数,关联访问器进行遍历操作
  7.       }

Node类中的traverse()为空,具体实现是在Group类中

  1. void Group::traverse(NodeVisitor& nv)
  2. {
  3.     for(NodeList::iterator itr=_children.begin();
  4.         itr!=_children.end();
  5.         ++itr)
  6.     {
  7.         (*itr)->accept(nv);
  8.     }
  9. }
示例代码
  1. #include <osg/Node>
  2. #include <osgDB/ReadFile>
  3. #include <iostream>
  4. using namespace std;
  5. class InfoVisitor: public osg::NodeVisitor
  6. {
  7. public:
  8. InfoVisitor()
  9. :osg::NodeVisitor(TRAVERSE_ALL_CHILDREN), _indent(0)
  10. {}
  11. virtual void apply(osg::Node& node)
  12. {
  13. for(int i = 0; i < _indent; i++) cout << " ";
  14. cout << "[" << _indent << "]"<< node.libraryName()
  15. << "::" << node.className() << endl;
  16. _indent++;
  17. traverse(node);
  18. _indent--;
  19. for(int i = 0; i < _indent; i++) cout << " ";
  20. cout << "[" << _indent << "] "<< node.libraryName()
  21. << "::" << node.className() << endl;
  22. }
  23. virtual void apply(osg::Geode& node)
  24. {
  25. for(int i = 0; i < _indent; i++) cout << " ";
  26. cout << "[" << _indent << "] "<< node.libraryName()
  27. << "::" << node.className() << endl;
  28. _indent++;
  29. for(unsigned int n = 0; n < node.getNumDrawables(); n++)
  30. {
  31. osg::Drawable* draw = node.getDrawable(n);
  32. if(!draw)
  33. continue;
  34. for(int i = 0; i < _indent; i++) cout << " ";
  35. cout << "[" << _indent << "]" << draw->libraryName() << "::"
  36. << draw->className() << endl;
  37. }
  38. traverse(node);
  39. _indent--;
  40. for(int i = 0; i < _indent; i++) cout << " ";
  41. cout << "[" << _indent << "]"<< node.libraryName()
  42. << "::" << node.className() << endl;
  43. }
  44. private:
  45. int _indent;
  46. };
  47. int main(int argc, char** argv)
  48. {
  49. osg::ArgumentParser parser(&argc, argv);
  50. osg::Node* root = osgDB::readNodeFiles(parser);
  51. if(!root)
  52. {
  53. root = osgDB::readNodeFile("2.OSGB");
  54. }
  55. InfoVisitor infoVisitor;
  56. if(root)
  57. {
  58. root->accept(infoVisitor);
  59. }
  60. system("pause");
  61. return 0;
  62. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/314999
推荐阅读
相关标签
  

闽ICP备14008679号