NodeVisitor

来源:互联网 发布:阿儿法营编程学校 编辑:程序博客网 时间:2024/06/05 20:36

OSG中节点的访问使用的是一种访问器模式。
一个典型的访问器涉及抽象访问者角色(Visitor), 具体访问者(Concrete Visitor), 节点角色(Node)。

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)。

对于节点的访问是从节点接收一个访问器开始的,用户执行某个节点的accept()函数,将一个具体的访问器对象传递给节点。

第二步,节点反过来执行访问器的apply()函数,并将自身传入访问器。

这两步的实现过程可以用一行十分简单的函数代码来表达:

void Node::accept(NodeVisitor& nv){    nv.apply(*this);}

1. 从根遍历节点

#ifdef _DEBUG#pragma comment(lib, "osgd.lib")#pragma comment(lib, "osgDBd.lib")#pragma comment(lib, "osgViewerd.lib")#pragma comment(lib, "OpenThreadsd.lib")#pragma comment(lib, "osgUtild.lib")#else#pragma comment(lib, "osg.lib")#pragma comment(lib, "osgDB.lib")#pragma comment(lib, "osgViewer.lib")#pragma comment(lib, "osgUtil.lib")#pragma comment(lib, "OpenThreads.lib")#endif#include <osg/GraphicsContext>#include <osgGA/GUIEventHandler>#include <osgGA/GUIActionAdapter>#include <osgViewer/Viewer>#include <osgDB/ReadFile>#include <osg/Geode>#include <iostream>#include <osg/MatrixTransform>#include <osg/NodeVisitor>class VisitorNodePath : public osg::NodeVisitor{public:    VisitorNodePath():osg::NodeVisitor(TRAVERSE_ALL_CHILDREN) {}    void apply(osg::Node &node)    {        std::cout<<"Apply node:"<< node.getName()<<std::endl;        if(node.getName() == "glider")        {            //Do something        }        traverse(node);    }    void apply(osg::Group &group)    {        std::cout<<"Apply group:"<< group.getName()<<std::endl;        if(group.getName() == "root")        {            //Do something        }        traverse(group);    }    void app(osg::MatrixTransform &mt)    {        std::cout<<"Apply mtransfor:"<<mt.getName()<<std::endl;        if(mt.getName() == "child2")        {            //Do something        }        traverse(mt);    }};int main(){    osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer;    osg::ref_ptr<osg::Group> root = new osg::Group;    osg::ref_ptr<osg::Node> glider = osgDB::readNodeFile("glider.osg");    osg::ref_ptr<osg::Node> cow = osgDB::readNodeFile("cow.osg");       osg::ref_ptr<osg::MatrixTransform> child1 = new osg::MatrixTransform;    osg::ref_ptr<osg::MatrixTransform> child2 = new osg::MatrixTransform;    osg::ref_ptr<osg::MatrixTransform> child3 = new osg::MatrixTransform;    osg::ref_ptr<osg::MatrixTransform> child4 = new osg::MatrixTransform;    osg::ref_ptr<osg::MatrixTransform> child5 = new osg::MatrixTransform;    VisitorNodePath vn;    root->setName("root");    glider->setName("glider");    cow->setName("cow");    root->addChild(glider);//root->glider    root->addChild(child1);    root->addChild(child2);    child1->setName("child1");    child1->setMatrix(osg::Matrix::translate(-5, -5, 0));    child1->addChild(glider);    child1->addChild(child3);    child1->addChild(child4);    child2->setName("child2");    child2->setMatrix(osg::Matrix::translate(5, -5, 0));    child2->addChild(glider);    child2->addChild(child5);    child3->setName("child3");    child3->setMatrix(osg::Matrix::translate(-5, -5, 0));    child3->addChild(cow);    child4->setName("child4");    child4->setMatrix(osg::Matrix::translate(5, -5, 0));    child4->addChild(cow);    child5->setName("child5");    child5->setMatrix(osg::Matrix::translate(5, -5, 0));    child5->addChild(cow);    root->addChild(glider);    viewer->setSceneData(root);    root->accept(vn);    return viewer->run();}

2.从叶节点遍历

#ifdef _DEBUG#pragma comment(lib, "osgd.lib")#pragma comment(lib, "osgDBd.lib")#pragma comment(lib, "osgViewerd.lib")#pragma comment(lib, "OpenThreadsd.lib")#pragma comment(lib, "osgUtild.lib")#else#pragma comment(lib, "osg.lib")#pragma comment(lib, "osgDB.lib")#pragma comment(lib, "osgViewer.lib")#pragma comment(lib, "osgUtil.lib")#pragma comment(lib, "OpenThreads.lib")#endif#include <osg/GraphicsContext>#include <osgGA/GUIEventHandler>#include <osgGA/GUIActionAdapter>#include <osgViewer/Viewer>#include <osgDB/ReadFile>#include <osg/Geode>#include <iostream>#include <osg/MatrixTransform>#include <osg/NodeVisitor>class VisitorNodePath : public osg::NodeVisitor{public:    //从根节点开始遍历    //VisitorNodePath():osg::NodeVisitor(TRAVERSE_ALL_CHILDREN) {}    //从叶节点开始遍历    VisitorNodePath():osg::NodeVisitor(TRAVERSE_PARENTS) {}    void apply(osg::Node &node)    {        std::cout<<"Apply node:"<< node.getName()<<std::endl;        if(node.getName() == "glider")        {            //Do something        }        traverse(node);    }    void apply(osg::Group &group)    {        std::cout<<"Apply group:"<< group.getName()<<std::endl;        if(group.getName() == "root")        {            //Do something        }        traverse(group);    }    void app(osg::MatrixTransform &mt)    {        std::cout<<"Apply mtransfor:"<<mt.getName()<<std::endl;        if(mt.getName() == "child2")        {            //Do something        }        traverse(mt);    }};int main(){    osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer;    osg::ref_ptr<osg::Group> root = new osg::Group;    osg::ref_ptr<osg::Node> glider = osgDB::readNodeFile("glider.osg");    osg::ref_ptr<osg::Node> cow = osgDB::readNodeFile("cow.osg");       osg::ref_ptr<osg::MatrixTransform> child1 = new osg::MatrixTransform;    osg::ref_ptr<osg::MatrixTransform> child2 = new osg::MatrixTransform;    osg::ref_ptr<osg::MatrixTransform> child3 = new osg::MatrixTransform;    osg::ref_ptr<osg::MatrixTransform> child4 = new osg::MatrixTransform;    osg::ref_ptr<osg::MatrixTransform> child5 = new osg::MatrixTransform;    VisitorNodePath vn;    root->setName("root");    glider->setName("glider");    cow->setName("cow");    root->addChild(glider);//root->glider    root->addChild(child1);    root->addChild(child2);    child1->setName("child1");    child1->setMatrix(osg::Matrix::translate(-5, -5, 0));    child1->addChild(glider);    child1->addChild(child3);    child1->addChild(child4);    child2->setName("child2");    child2->setMatrix(osg::Matrix::translate(5, -5, 0));    child2->addChild(glider);    child2->addChild(child5);    child3->setName("child3");    child3->setMatrix(osg::Matrix::translate(-5, -5, 0));    child3->addChild(cow);    child4->setName("child4");    child4->setMatrix(osg::Matrix::translate(5, -5, 0));    child4->addChild(cow);    child5->setName("child5");    child5->setMatrix(osg::Matrix::translate(5, -5, 0));    child5->addChild(cow);    root->addChild(glider);    viewer->setSceneData(root);    //从叶节点开始遍历    cow->accept(vn);    return viewer->run();}
原创粉丝点击