问题的提出:
有时我们需要按节点名称找出模型中的节点,例如如下代码:
class findNodeVisitor : public osg::NodeVisitor
{
public:
findNodeVisitor();
findNodeVisitor(const std::string &searchName);
virtual void apply(osg::Node &searchNode);
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;
};
findNodeVisitor::findNodeVisitor() : osg::NodeVisitor(TRAVERSE_ALL_CHILDREN), searchForName()
{
}
findNodeVisitor::findNodeVisitor(const std::string &searchName) : osg::NodeVisitor(TRAVERSE_ALL_CHILDREN), searchForName(searchName)
{
}
void findNodeVisitor::setNameToFind(const std::string &searchName)
{
searchForName = searchName;
foundNodeList.clear();
}
osg::Node* findNodeVisitor::getFirst()
{
return *(foundNodeList.begin());
}
void findNodeVisitor::apply(osg::Node &searchNode)
{
if (searchNode.getName() == searchForName)
{
foundNodeList.push_back(&searchNode);
}
traverse(searchNode);
}
void findNodeVisitor::apply(osg::Transform &searchNode)
{
osgSim::DOFTransform* dofNode =
dynamic_cast<osgSim::DOFTransform*> (&searchNode);
if (dofNode)
{
dofNode->setAnimationOn(false);
}
apply((osg::Node&) searchNode);
traverse(searchNode);
}
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> tankNode = osgDB::readNodeFile("d:\\1.OSGB");
root->addChild(tankNode.get());
findNodeVisitor findGun("gun");
root->accept(findGun);
//优化场景数据
osgUtil::Optimizer optimizer;
optimizer.optimize(root.get());
//设置场景数据
viewer->setSceneData(root.get());
//初始化并创建窗口
viewer->realize();
//开始渲染
viewer->run();
return 0;
}
在上面的代码段main函数中的如下代码:
findNodeVisitor findGun("gun");
中的”gun“表示按节点名称来查找,只找模型中名称为"gun"的节点,有时我们从3D建模人员拿到的模型文件他们也不记得模型中各个节点的名称了,那我们怎么办呢?我们可以用如下代码枚举出模型中的每个节点的名称、库名、类名,如下:
#include <iostream>
#include <osgViewer/Viewer>
#include <osgDB/ReadFile>
#include <osg/NodeVisitor>
#include <osg/Node>
#include <osg/Group>
#include <osgSim/DOFTransform>
#include <osgUtil/Optimizer>
#include <osg/NodeVisitor>
#include <iostream>
#include <vector>
#include <codecvt>
#include <locale>
using namespace std;
#ifdef WIN32
#include<Windows.h>
#endif
string Utf8ToGB2312(const std::string& strUtf8)
{
std::wstring_convert<std::codecvt_utf8<wchar_t>> cutf8;
std::wstring wTemp = cutf8.from_bytes(strUtf8);
#ifdef _MSC_VER
std::locale loc("zh-CN");
#else
std::locale loc("zh_CN.GB18030");
#endif
const wchar_t* pwszNext = nullptr;
char* pszNext = nullptr;
mbstate_t state = {};
std::vector<char> buff(wTemp.size() * 2);
int res = std::use_facet<std::codecvt<wchar_t, char, mbstate_t> >
(loc).out(state,
wTemp.data(), wTemp.data() + wTemp.size(), pwszNext,
buff.data(), buff.data() + buff.size(), pszNext);
if (std::codecvt_base::ok == res)
{
return std::string(buff.data(), pszNext);
}
return "";
}
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() << "----" << Utf8ToGB2312(node.getName()) << endl;
_indent++;
traverse(node);
_indent--;
for (int i = 0; i < _indent; i++)
cout << " ";
cout << "[" << _indent << "] " << node.libraryName()
<< "::" << node.className() << "----" << Utf8ToGB2312(node.getName()) << endl;
}
virtual void apply(osg::Geode& node)
{
for (int i = 0; i < _indent; i++)
cout << " ";
cout << "[" << _indent << "] " << node.libraryName()
<< "::" << node.className() << "----" << Utf8ToGB2312(node.getName()) << 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() << "----" << Utf8ToGB2312(node.getName()) << endl;
}
traverse(node);
_indent--;
for (int i = 0; i < _indent; i++)
cout << " ";
cout << "[" << _indent << "]" << node.libraryName()
<< "::" << node.className() << "----" << Utf8ToGB2312(node.getName()) << endl;
}
private:
int _indent;
};
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> tankNode = osgDB::readNodeFile("d:\\1.OSGB");
root->addChild(tankNode.get());
InfoVisitor infoVisitor;
if (root)
{
root->accept(infoVisitor);
}
//优化场景数据
osgUtil::Optimizer optimizer;
optimizer.optimize(root.get());
//设置场景数据
viewer->setSceneData(root.get());
//初始化并创建窗口
viewer->realize();
//开始渲染
viewer->run();
return 0;
}
注意:上述的node.getName()即节点名称要用Utf8ToGB2312函数转换一下,否则对于中文的名称会出现乱码。运行截图如下: