06搜索并控制开关节点和自由度节点

更新时间:2023-10-19 23:09:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

搜索并控制开关节点和自由度节点

对于包含开关节点和DOF(自由度)节点的场景图形,可以搜索指定的节点并更新其内容。模型文件可能包含了各种不同的节点类型,用户通过对这些节点的使用来更新和表达模型的各个部分。

使用osgSim::MultiSwitch多重节点可以在多个模型渲染状态间进行选择。例如,对坦克模型使用多重节点,用户即可自行选择与完整的或者损坏的坦克相关联的几何体以及渲染状态。模型中还可以包含DOF节点,以便清晰表达坦克的某个部分。例如炮塔节点可以旋转,机枪节点可以升高。炮塔旋转时,炮塔体(包括机枪)的航向角(heading)与坦克的航向角相关联,而机枪抬升时,机枪的俯仰角(pitch)与炮塔的俯仰角相关联。

对这些节点进行更新时,我们需要一个指向节点的指针。而我们首先要获取节点的名字,才能得到该节点的指针。而获取节点的名称,主要有这样一些方法:咨询建模人员;使用其它文件浏览器(对于.flt文件,可以使用Creator或者Vega)浏览模型;或者使OpenSceneGraph。 用户可以根据自己的需要自由运用OSG的功能。例如在场景图形中载入flt文件,并且在仿真过程中将整个场景保存成.osg文件。osg文件使用ASCII格式保存,因此用户可以使用各种文本处理软件(写字板,记事本)对其进行编辑。在坦克模型文件中,你可以发现一个名为“sw1”的开关节点,它有两个子节点“good”和“bad”,分别指向坦克未损坏和损坏的状态。

findNodeVisitor.h

#ifndef FIND_NODE_VISITOR_H #define FIND_NODE_VISITOR_H

#include #include

#include #include #include

//构造用户类

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 nodeListType;

nodeListType& getNodeList() { return foundNodeList; } private:

std::string searchForName; nodeListType foundNodeList; }; #endif

findNodeVisitor.cpp

#include \

// 默认构造函数,初始化searchForName函数,设置遍历方式为向子节点遍历 findNodeVisitor::findNodeVisitor() : osg::NodeVisitor(TRAVERSE_ALL_CHILDREN), searchForName() { }

// 带有字符串参数的构造函数

// 用用户自定义的字符串初始化searchForName函数 // 设置遍历方式为向子节点遍历

findNodeVisitor::findNodeVisitor(const std::string &searchName) :

osg::NodeVisitor(TRAVERSE_ALL_CHILDREN), searchForName(searchName) { }

//通过apply()方法获取传入的节点对象 //比较searchForName和节点名称

//如果字符串完全匹配,将节点加入搜索列表 void findNodeVisitor::apply(osg::Node &searchNode) {

if (searchNode.getName() == searchForName) {

foundNodeList.push_back(&searchNode); }

traverse(searchNode); }

// 搜索和用户自定义的名称相同的节点

void findNodeVisitor::setNameToFind(const std::string &searchName) {

searchForName = searchName; foundNodeList.clear(); }

void findNodeVisitor::apply(osg::Transform &searchNode) {

osgSim::DOFTransform* dofNode =

dynamic_cast (&searchNode); if (dofNode) {

dofNode->setAnimationOn(false); }

apply ( (osg::Node&) searchNode); traverse(searchNode); }

osg::Node* findNodeVisitor::getFirst() {

return *(foundNodeList.begin()); }

Main函数

#include #include

#include #include #include #include #include \

#include

#include #include

// 添加文字在模型节点下作为标签

bool addTextLabel(osg::Group* g, std::string s); int main() {

// 构造一个主节点作为场景树的根节点,三个主节点包含三个独立的坦克模型 osg::Group* root = new osg::Group(); osg::Group* tankOneGroup = NULL; osg::Group* tankTwoGroup = NULL; osg::Group* tankThreeGroup = NULL;

osgViewer::Viewer viewer;

// 从同一个文件加载坦克模型

tankOneGroup = dynamic_cast(osgDB::readNodeFile(\)); tankTwoGroup = dynamic_cast(osgDB::readNodeFile(\)); tankThreeGroup = dynamic_cast(osgDB::readNodeFile(\));

// findNodeVisitor将屏蔽osgSim::DOFTransform节点的作用动画域 //因此不传入用户搜索的字符串

tankOneGroup->accept( *(new findNodeVisitor(\)) );

// 如果加载模型失败则退出

if (! (tankOneGroup && tankTwoGroup && tankThreeGroup) ) {

std::cout << \ << std::endl; return -1; }

// 将第一个坦克加入根节点

root->addChild(tankOneGroup);

// 定义一个transform节点来放置第二个坦克 osg::PositionAttitudeTransform* tankTwoPAT = new osg::PositionAttitudeTransform(); tankTwoPAT->setPosition( osg::Vec3(8,8,0) );

// 将这个坦克加入到transform的子节点并将transform加入到场景中 root->addChild(tankTwoPAT);

tankTwoPAT->addChild(tankTwoGroup);

// 定义一个transform节点来放置第三个坦克 osg::PositionAttitudeTransform* tankThreePAT = new osg::PositionAttitudeTransform(); tankThreePAT->setPosition( osg::Vec3(10,-3,0) ); //将坦克向左旋转.5度

tankThreePAT->setAttitude( osg::Quat(3.14159/2.0, osg::Vec3(0,0,1) )); // 将这个坦克加入到transform的子节点并将transform加入到场景中 root->addChild(tankThreePAT);

tankThreePAT->addChild(tankThreeGroup);

// 定义一个findNodeVisitor类的实例并设置其默认搜索名称为\ findNodeVisitor findNode(\);

// 第二个坦克初始化findNodeVisitor的实例,开始遍历节点的所有子节点 // 建立一个和搜索名称相同的所有节点的列表 tankTwoGroup->accept(findNode);

// 定义一个switch类型,并将其关联到第一个搜索到的节点 osgSim::MultiSwitch* tankSwitch = NULL;

tankSwitch = dynamic_cast (findNode.getFirst());

// 如果是合法的句柄,改变其状态 if (tankSwitch) {

// tankSwitch->setSingleChildOn(0,false); // good model tankSwitch->setSingleChildOn(0,true); // bad model }

//定义一个findNodeVisitor的实例,设置其搜索turret节点 findNodeVisitor findTurretNode(\);

// 遍历第三个坦克的子树

tankThreeGroup->accept(findTurretNode);

// 确定搜索到的是所需的节点并且是正确的类型 osgSim::DOFTransform * turretDOF =

dynamic_cast (findTurretNode.getFirst()) ;

// 如果是正确的自由变换节点,将坦克的炮塔向左旋转.5度 if (turretDOF) {

turretDOF->setCurrentHPR( osg::Vec3(-3.14159/4.0,0.0,0.0) ); }

// 定义一个findNodeVisitor的实例来搜索名称为gun的节点 findNodeVisitor findGunNode(\); // 遍历第三个坦克的子树

tankThreeGroup->accept(findGunNode);

// 确定搜索到的是所需的节点并且是正确的类型 osgSim::DOFTransform * gunDOF =

dynamic_cast (findGunNode.getFirst()) ;

// 如果是正确的自由变换节点,将坦克的炮向上提升.5度 if (gunDOF) {

gunDOF->setCurrentHPR( osg::Vec3(0.0,3.14159/4.0,0.0) ); }

//为每个坦克添加文字标签

addTextLabel(tankOneGroup,\); addTextLabel(tankTwoGroup,\); addTextLabel(tankThreeGroup,\);

viewer.setSceneData( root );

viewer.setCameraManipulator(new osgGA::TrackballManipulator()); viewer.realize();

//开始仿真循环 while( !viewer.done() ) {

viewer.frame(); } }

bool addTextLabel(osg::Group* g, std::string s) { if (!g)

{

return false; }

osg::Geode* textLabelGeode = new osg::Geode(); osgText::Text* textOne = new osgText::Text(); g->addChild(textLabelGeode);

textLabelGeode->addDrawable(textOne);

textOne->setCharacterSize(1); textOne->setFont(\); textOne->setText(s);

textOne->setAxisAlignment(osgText::Text::SCREEN); textOne->setColor( osg::Vec4(1,0,0,1.0f) ); textOne->setPosition( osg::Vec3(2,1,-1) ); textOne->setDrawMode(osgText::Text::TEXT |

osgText::Text::ALIGNMENT | osgText::Text::BOUNDINGBOX); textOne->setAlignment(osgText::Text::CENTER_TOP); return true; }

本文来源:https://www.bwwdw.com/article/16wf.html

Top