osg资料收集 - 图文 联系客服

发布时间 : 星期日 文章osg资料收集 - 图文更新完毕开始阅读

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

现在,我们创建的类可以做到:启动一次节点访问遍历,访问指定场景子树的每个子节点,将节点的名称与用户指定的字符串作比较,并建立一个列表用于保存名字与搜索字符串相同的节点。那么如何启动这个过程呢?我们可以使用osg::Node的“accept”方法来实现节点访问器的启动。选择某个执行accept方法的节点,我们就可以控制遍历开始的位置。(遍历的方向是通过选择遍历模式来决定的,而节点类型的区分则是通过重载相应的apply方法来实现)“accpet”方法将响应某一类的遍历请求,并执行用户指定节点的所有子类节点的apply方法。在这里我们将重载一般节点的apply方法,并选择TRAVERSE_ALL_CHILDREN的遍历模式,因此,触发accept方法的场景子树中所有的节点,均会执行这一apply方法。

在这个例子中,我们将读入三种不同状态的坦克。第一个模型没有任何变化,第二个模型将使用多重开关(multSwitch)来关联损坏状态,而第三个模型中,坦克的炮塔将旋转不同的角度,同时枪管也会升高。

下面的代码实现了从文件中读入三个坦克模型并将其添加到场景的过程。其中两个坦克将作为变换节点(PositionAttitudeTransform)的子节点载入,以便将其位置设置到坐标原点之外。 // 定义场景树的根节点,以及三个独立的坦克模型节点 osg::Group* root = new osg::Group(); osg::Group* tankOneGroup = NULL; osg::Group* tankTwoGroup = NULL; osg::Group* tankThreeGroup = NULL; // 从文件中读入坦克模型

tankOneGroup = dynamic_cast

(osgDB::readNodeFile(\ tankTwoGroup = dynamic_cast

(osgDB::readNodeFile(\ tankThreeGroup = dynamic_cast

(osgDB::readNodeFile(\ // 将第一个坦克作为根节点的子节点载入 root->addChild(tankOneGroup); // 为第二个坦克定义一个位置变换

osg::PositionAttitudeTransform* tankTwoPAT = new osg::PositionAttitudeTransform();

// 将第二个坦克向右移动5个单位,向前移动5个单位 tankTwoPAT->setPosition( osg::Vec3(5,5,0) );

// 将第二个坦克作为变换节点的子节点载入场景 root->addChild(tankTwoPAT);

tankTwoPAT->addChild(tankTwoGroup); // 为第三个坦克定义一个位置变换

osg::PositionAttitudeTransform* tankThreePAT = new osg::PositionAttitudeTransform();

// 将第二个坦克向右移动10个单位

tankThreePAT->setPosition( osg::Vec3(10,0,0) );

// 将坦克模型向左旋转22.5度(为此,炮塔的旋转应当与坦克的头部关联) tankThreePAT->setAttitude( osg::Quat(3.14159/8.0, osg::Vec3(0,0,1) ));

// 将第三个坦克作为变换节点的子节点载入场景 root->addChild(tankThreePAT);

tankThreePAT->addChild(tankThreeGroup); 我们准备将第二个模型设置为损坏的状态,因此我们使用findNodeVisitor类获取控制状态的多重开关(multiSwitch)的句柄。这个节点访问器需要从包含了第二个坦克的组节点开始执行。下面的代码演示了声明和初始化一个findNodeVisitor实例并执行场景遍历的方法。遍历完成之后,我们即可得到节点列表中符合搜索字符串的第一个节点的句柄。这也就是我们准备使用multiSwitch来进行控制的节点句柄。

// 声明一个findNodeVisitor类的实例,设置搜索字符串为“sw1” findNodeVisitor findNode(\

// 开始执行访问器实例的遍历过程,起点是tankTwoGroup,搜索它所有的子节点 // 并创建一个列表,用于保存所有符合搜索条件的节点 tankTwoGroup->accept(findNode);

// 声明一个开关类型,并将其关联给搜索结果列表中的第一个节点。 osgSim::MultiSwitch* tankSwitch = NULL;

tankSwitch = dynamic_cast (findNode.getFirst());

更新开关节点

当我们获取了一个合法的开关节点句柄后,下一步就是从一个模型状态变换到另一个状态。我们可以使用setSingleChildOn方法来实现这个操作。setSingleChildOn()方法包括两个参数:第一个无符号整型量相当于多重开关组(switchSet)的索引号;第二个无符号整型量相当于开关的位置。在这个例子中,我们只有一个多重开关,其值可以设置为未损坏状态或者损坏状态,如下所示:

// 首先确认节点是否合法,然后设置其中的第一个(也是唯一的)多重开关 if (tankSwitch) {

//tankSwitch->setSingleChildOn(0,false); // 未损坏的模型 tankSwitch->setSingleChildOn(0,true); // 损坏的模型 }

更新DOF节点

坦克模型还包括了两个DOF(自由度)节点“turret”和“gun”。这两个节点的句柄也可以使用上文所述的findNodeVisitor来获取。(此时,访问器的场景遍历应当从包含第三个模型的组节点处开始执行)一旦我们获取了某个DOF节点的合法句柄之后,即可使用setCurrentHPR方法来更新与这些节点相关的变换矩阵。setCurrentHPR方法只有一个参数:这个osg::Vec3量相当于三个欧拉角heading,pitch和roll的弧度值。(如果要使用角度来描述这个值,可以使用osg::DegreesToRadians方法)

// 声明一个findNodeVisitor实例,设置搜索字符串为“turret”

findNodeVisitor findTurretNode(\

// 遍历将从包含第三个坦克模型的组节点处开始执行 tankThreeGroup->accept(findTurretNode); // 确认我们找到了正确类型的节点 osgSim::DOFTransform * turretDOF =

dynamic_cast (findTurretNode.getFirst()) ; // 如果节点句柄合法,则设置炮塔的航向角为向右22.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()) ; // 如果节点句柄合法,则设置机枪的俯仰角为向上22.5度。 if (gunDOF) {

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

就是这样了!然后再编写仿真循环的代码即可。 20:01 | 添加评论 | 固定链接 | 写入日志 | NPS教程 11月5日

Navy07 - 搜索并控制开关和DOF节点(1) 开始翻译Navy的OSG教程

Navy,也就是美国海军……他们一直以来都是OSG的重要客户之一。在美国军方的支持和资助下,Navy研究学院还开发了基于OSG的著名游戏与仿真引擎Delta3D,它融合了OSG,OpenAL,ODE(物理仿真)和Cal3D(角色动画)等诸多开发库,形成了一个极其强大的可视化开发高级API库系统。同时,Delta3D也是开放源代码的。

Navy的官方网站提供了很好的OSG系列教程,截止到本文编写时为止,共有18个章节,每章以一个功能的实现为目的,并辅以简洁的文字介绍和源代码。对于初学者来说十分实用。 Navy OSG教程的官方链接为:

http://www.nps.navy.mil/cs/sullivan/osgTutorials/index.htm

国内的访客可能无法登陆这个网址(具体原因……不言而喻吧),可以使用网页代理来观看原文,并下载模型文件和例子源代码。也可以向我索取。 本教程的前几章已经有人翻译过了,具体请参见

http://blog.donews.com/kevinwhite/archive/2006/06.aspx 因为我并不知道这些文章是否允许转载(我不认识作者),所以只提供了他的链接,

由于Navy的教程很多是源代码的罗列,因此我会在翻译的同时给出对于代码的中文注解和我自己的见解~~其中有不妥当的地方,请大家参阅原文并提出,我会及时改正。

我的翻译和解释工作将从第7章“Finding nodes, DOFs and Switches”开始。

Navy教程的后面章节我会逐步解析并发布上来~~请大家多多支持,多多指正。 ----------------------------------------------------------

Navy教程第七课 - 搜索并控制开关节点和DOF(自由度)节点

----------------------------------------------------------

搜索场景图形中的一个有名节点

模型文件可能包含了各种不同的节点类型,用户通过对这些节点的使用来更新和表达模型的各个部分。使用osgSim::MultiSwitch多重节点可以在多个模型渲染状态间进行选择。例如,对坦克模型使用多重节点,用户即可自行选择与完整的或者损坏的坦克相关联的几何体以及渲染状态。模型中还可以包含DOF节点,以便清晰表达坦克的某个部分。例如炮塔节点可以旋转,机枪节点可以升高。炮塔旋转时,炮塔体(包括机枪)的航向角(heading)与坦克的航向角相关联,而机枪抬升时,机枪的俯仰角(pitch)与炮塔的俯仰角相关联。 对这些节点进行更新时,我们需要一个指向节点的指针。而我们首先要获取节点的名字,才能得到该节点的指针。而获取节点的名称,主要有这样一些方法:咨询建模人员;使用其它文件浏览器(对于.flt文件,可以使用Creator或者Vega)浏览模型;或者使用OpenSceneGraph。用户可以根据自己的需要自由运用OSG的功能。例如在场景图形中载入flt文件,并且在仿真过程中将整个场景保存成.osg文件。osg文件使用ASCII格式保存,因此用户可以使用各种文本处理软件(写字板,记事本)对其进行编辑。在坦克模型文件中,你可以发现一个名为“sw1”的开关节点,它有两个子节点“good”和“bad”,分别指向坦克未损坏和损坏的状态。坦克模型的.osg文件可以从这里下载:

http://www.nps.navy.mil/cs/sullivan/osgTutorials/Download/T72Tank.osg 现在我们已经获得了需要控制的开关节点的名称(sw1),亦可获取其指针对象。获取节点指针的方法有两种:一是编写代码遍历整个场景图形;二是使用后面将会介绍的访问器(visitor)。在以前的教程中,我们已经知道如何加载flight文件,将其添加到场景并进入仿