OSG:先导篇 访问器机制

一.简介

osg::NodeVisitor 类是设计模式 Visitor (观察者模式)的实现,osg::NodeVisitor 类继承自 osg::Reference 类

osg::NodeVisitor是一个虚基类,在程序中无法实例化

osg::NodeVisitor中主要有 apply():决定了遍历的方式,可以获得各个节点的属性,也可以修改节点属性

            accept():关联需要访问的节点,并启动访问器进行遍历

 

在用户应用程序中,可以编写继承自osg::NodeVisitor的新类,再通过重载 apply() 来实现功能

 

二.顶点访问器

 

三.纹理访问器

 

四.节点访问器

 

//main.cpp

#include "osgViewer/Viewer"

#include "osg/Node"
#include "osg/Geode"
#include <osg/Group>

#include "osgDB/ReadFile"
#include "osgDB/WriteFile"

#include "osgUtil/Optimizer"

#include "FindNodeVisitor.h"

int main()
{
    //创建Viewer对象,场景浏览器
    osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();
    osg::ref_ptr<osg::Group> root = new osg::Group();

    //创建一个节点,读取牛的模型
    osg::ref_ptr<osg::Node> node = osgDB::readNodeFile("cow.osg");

    //创建节点查找访问器
    FindNodeVisitor cow("cow.osg");

    //启动访问器,开始执行遍历
    node->accept(cow);

    if(!cow.getFirst()){
        std::cout<<"无法找到节点,查找失败"<<std::endl;
    }
    else{
        std::cout<<"查找节点成功,成功找到节点"<<std::endl;
    }

    root->addChild(node.get());
    

    //优化场景数据
    osgUtil::Optimizer optimizer;
    optimizer.optimize(root.get());

    viewer->setSceneData(root.get());
    viewer->realize();
    viewer->run();
    return 0;

}

 

//FindNodeVisitor.h

#ifndef FIND_NODE_VISITOR_H
#define FIND_NODE_VISITOR_H

#include <osg/NodeVisitor>
#include <osg/Node>

#include <osgSim/DOFTransform>
#include <iostream>
#include <vector>
#include <string>

//节点查找访问器,继承自osg::NodeVisitor
class FindNodeVisitor:public osg::NodeVisitor
{
public:

    //构造函数,参数为需要查找的节点名
    FindNodeVisitor(const std::string& searchName);

    //重载apply()方法
    virtual void apply(osg::Node& searchNode);

    virtual void apply(osg::Geode& geode);

    virtual void apply(osg::Transform& searchNode);

    //设置要查找的节点名
    void setNameToFind(const std::string& searchName);

    //得到查找节点向量的第一个节点
    osg::Node* getFirst();

    //定义一个节点向量
    typedef std::vector<osg::Node*> nodeListType;

    //得到查找节点向量
    nodeListType& getNodeList()
    {
        return foundNodeList;
    }

private:

    //节点名
    std::string searchForName;

    //用来保存查找的节点
    nodeListType foundNodeList;

};

#endif

 

//FindNodeVisitor.cpp

#include "FindNodeVisitor.h"

//构造函数,初始化并设置遍历所有的子节点
FindNodeVisitor::FindNodeVisitor(const std::string& searchName):
    osg::NodeVisitor(TRAVERSE_ALL_CHILDREN),
    searchForName(searchName)
{

}


//重载apply()方法
void FindNodeVisitor::apply(osg::Node& searchNode)
{
    //判断节点名称是否与查找的节点名称一样
    if(searchNode.getName() == searchForName)
    {
        //添加到节点系列
        foundNodeList.push_back(&searchNode);
    }

    //继续遍历
    traverse(searchNode);
}

//重载apply()方法
void FindNodeVisitor::apply(osg::Transform& searchNode)
{
    //判断节点名称是否与查找的节点名称一样
    if(searchNode.getName() == searchForName)
    {
        //添加到节点系列
        foundNodeList.push_back(&searchNode);
    }

    //继续遍历
    traverse(searchNode);
}

//重载apply()方法
void FindNodeVisitor::apply(osg::Geode& geode)
{
    apply((osg::Node&)geode);
    traverse((osg::Node&)geode);
}

//设置要查找的节点名称
void FindNodeVisitor::setNameToFind(const std::string& searchName)
{

    searchForName = searchName;
    foundNodeList.clear();
}

//得到查找节点向量中的第一个节点
osg::Node* FindNodeVisitor::getFirst()
{
    return *(foundNodeList.begin());
}

 

posted @ 2019-09-04 18:29  言午丶  阅读(706)  评论(0编辑  收藏  举报