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 中。