(二)OSG初学者入门基础教程

Day02

13.模型的简单控制:在场景中添加多个模型

#include<osgViewer/Viewer>

#include<osgDB/ReadFile>

#include <osg/MatrixTransform>

 

int main(int argc, char **argv)

{

    osgViewer::Viewer viewer;

    osg::Node *cow = osgDB::readNodeFile("cow.osg");

    osg::Node *glider = osgDB::readNodeFile("glider.osg");

    osg::MatrixTransform* translateMT = new osg::MatrixTransform;

    translateMT->setMatrix(osg::Matrix::translate(10, 0, 0));

    translateMT->addChild(glider);

    osg::Group *root = new osg::Group;

    root->addChild(cow);

    root->addChild(translateMT);

    //把牛放到场景中

    viewer.setSceneData(root);

    return viewer.run();

}

会显示一个滑翔机和一个奶牛,因为体积差距过大,则会重叠只显示一个模型。

 

14.代码解析

#include<osgViewer/Viewer>

#include<osgDB/ReadFile>

#include <osg/MatrixTransform>

添加头文件,其中需要添加 node 头文件,因为 group 是 node 的派生类,头文件可不加,即便 加了也不会重复包含。

 

osgViewer::Viewer viewer;

申请一个 viewer

 

osg::Group *root = new osg::Group;

申请一个 root 结点,即根结点,该结点下会组织所有的场景结点。

 

osg::Node *cow = osgDB::readNodeFile("cow.osg");

osg::Node *glider = osgDB::readNodeFile("glider.osg");

在根结点下加入两个node,一个是 cow.osg 另一个是 glider.osg,默认时两结点是加在场景的中间。

osg::MatrixTransform* translateMT = new osg::MatrixTransform;

translateMT->setMatrix(osg::Matrix::translate(10, 0, 0));

translateMT->addChild(glider);

对glider进行变换,平移。

15.删除节点

可以通过 removeChild 方法,删 除多个孩子也可以通过 removeChildren 方法,里面的参数有些需要索引值,有些需要结点本身的指针。

官方文档方法如下:

如果要删除一个结点,那么该结点下的所有结点都会被删除。如果一个结点被加入 到一个组中两次,那么这两次是分别存在的,删除一次还有另一次。

16.隐藏模型

只让模型暂时消失,如果删除模型,则其会在内存中消失,再次调用会浪费很长时间,隐藏模型就解决了这个问题。

隐藏模型其实模型仍在渲染当中,因此损耗并未减少,只不过隐藏了而已,隐藏的确不是个什么好操作, 但是有时候对小模型确实也很实用。node ->setNodeMask 可以设置隐藏与显示。

NodeMask文档解释如下:

我们可以看到它的默认值是0XFFFFFFF,在C语言中十六进制数必需以0x开头,以0x开头的数即表明它是一个十六进制的数,真正的数是0x后的值,所以,这种颜色值,0x不用管,接着的两位数ff是表示透明度,再接着的六位数就是平常看的#ffffff了。

17.隐藏模型代码解释:

#include<osgViewer/Viewer>

#include<osgDB/ReadFile>

#include <osg/MatrixTransform>

 

int main(int argc, char **argv)

{

    osgViewer::Viewer viewer;

    osg::Node *cow = osgDB::readNodeFile("cow.osg");

    osg::Node *glider = osgDB::readNodeFile("glider.osg");

    osg::MatrixTransform* translateMT = new osg::MatrixTransform;

    translateMT->setMatrix(osg::Matrix::translate(10, 0, 0));

    translateMT->addChild(glider);

    osg::Group *root = new osg::Group;

    root->addChild(cow);

    root->addChild(glider);

    root->addChild(translateMT);

    cow->setNodeMask(0x0) ;

    viewer.setSceneData(root);

    viewer.realize();

    return viewer.run();

}

原本cow和glider是重叠的,由于cow的体型大遮住了glider,现在cow不见了,只有glider。

cow->setNodeMask(0x0) ;

其中 osgcool ->setNodeMask(0x0) ;代表隐藏。osgcool ->setNodeMask(1) 代表显示。

如何来判断该模型确实在场景当中而且被隐藏了呢。在运行程序时按空格键时会回到中心点, 该中心点是面向cow的中心,如果不存在 cow,那么按空格会把飞机置于场景中映,而有了 cow飞机会被放置左边,因为有cow事实存在,只是没有显示。

 

18.结点开关

隐藏一个结点,它还在内存当中消失,而且想要的时候它才能出来。因为可能 很久才要用到它,所以不想让它一直停留在内存当中,OSG 中提供了相应方法,叫做开关。

在 OSG 当中,专门有一个类来负责打开与关闭结点,该类名为 osg::Switch,里面有相应的方法来控制它所 管理的结点的打开与关闭。

我们可以看到第二个方法解释中出现了了SHALLOW_COPY,与之相对应的还有DEEP_COPY

他们的解释如下:

浅拷贝就是成员数据之间的一一赋值:把值赋给一一赋给要拷贝的值。但是可能会有这样的情况:对象还包含资源,这里的资源可以值堆资源,或者一个文件。
当值拷贝的时候,两个对象就有用共同的资源,同时对资源可以访问,这样就会出问题。深拷贝就是用来解决这样的问题的,它把资源也赋值一次,使对象拥有不同的资源,但资源的内容是一样的。对于堆资源来说,就是在开辟一片堆内存,把原来的内容拷贝。

即浅拷贝复制后对象与原对象共用同一个堆,而深拷贝,复制后对象新开辟一个堆。

 

Switch的类引用如下:

 

19.开关代码如下:

#include<osgViewer/Viewer>

#include<osgDB/ReadFile>

#include <osg/MatrixTransform>

#include <osg/Switch>

#include <osg/Node>

 

int main(int argc, char **argv)

{

    osgViewer::Viewer viewer;

    osg::Node *cow = osgDB::readNodeFile("cow.osg");

    osg::Node *glider = osgDB::readNodeFile("glider.osg");

    osg::MatrixTransform* translateMT = new osg::MatrixTransform;

    translateMT->setMatrix(osg::Matrix::translate(10, 0, 0));

    translateMT->addChild(glider);

    osg::Group *root = new osg::Group;

    osg::Switch *sw = new osg::Switch() ;

    //root->addChild(cow);

    root->addChild(glider);

    root->addChild(translateMT);

    //cow->setNodeMask(0x0) ;

    sw ->addChild(cow,false) ;

    root ->addChild(sw) ;

    viewer.setSceneData(root);

    viewer.realize();

    return viewer.run();

}

osg::Switch *sw = new osg::Switch() ;

声明一个switch开关

 

sw ->addChild(cow,false) ;

往开关中添加 cow 但是关掉它,第二个参数为 false

 

root ->addChild(sw) ;

把 cow.osg 添加到开关,并把开关添加到root 中。

Published by

风君子

独自遨游何稽首 揭天掀地慰生平