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()); }