2.3 Group
osg::Group类是OSG的根节点,它允许用户程序为其添加任意数量的子节点,子节点也可以继续分发子节点。osg::Group作为一个基类,派生出了很多节点类,如osg::LOD、osg::Switch、osg::Transform、osg::PositionAttitudeTransform、osg::PagedLOD、osg::Impostor和osg::AutoTransform等。
osg::Group类是从osg::Referenced类派生出来的,在通常情况下,只有父节点引用这个Group对象,所以当释放场景图的根节点时,会引发连锁的内存释放动作,这样就不会产生内存的泄漏。
osg::Group类作为OSG的核心部分,可以使用户程序通过Group来有效地组织场景中的数据,osg::Group类的强大之处在于管理节点的接口,同时,osg::Group类还从osg::Node类继承了用于管理父节点的接口,OSG允许节点有多个父节点。
2.3.1 位置变换节点
位置变换节点(osg::PositionAttitudeTransform)是一个位置变换节点,继承自osg::Transform,主要作用是提供模型的位置变换、大小缩放、原点位置的设置以及坐标系的变换。
osg::PositionAttitudeTransform的常用成员函数
函数名称 | 说明 |
---|---|
void setPosition(const Vec3d& pos) | 设置位置 |
const Vec3d& getPosition()const | 获取位置 |
void setAttitude(const Quat& quat) | 设置姿态,参数为四元数 |
const Quat& getQuat() const | 获取姿态 |
void setScale(const Vec3d& scale) | 设置缩放 |
const Vec3d& getScale() const | 获取缩放系数 |
const setPivodPoint(const Vec3d&pivot) | 设置原点 |
const Vec3d& getPivodPoint()const | 获取原点 |
2.3.2 位置变换节点示例
#include<osgViewer/Viewer>
#include<osg/Node>
#include<osg/Geode>
#include<osg/Group>
#include<osg/PositionAttitudeTransform>
#include<osgDB/ReadFile>
#include<osgDB/WriteFile>
#include<osgUtil/Optimizer>
int main()
{
// 创建VIewer对象,场景浏览器
osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();
osg::ref_ptr<osg::Group>root = new osg::Group();
osg::ref_ptr<osg::Node> node = osgDB::readNodeFile("cow.osg");
osg::ref_ptr<osg::PositionAttitudeTransform> pat1 = new osg::PositionAttitudeTransform();
pat1->setPosition(osg::Vec3(-10.f,0.0f,0.0f));
pat1->setScale(osg::Vec3(0.5f,0.5f,0.5f));
pat1->addChild(node.get());
osg::ref_ptr<osg::PositionAttitudeTransform> pat2 = new osg::PositionAttitudeTransform();
pat2->setPosition(osg::Vec3(10.0f,0.0f,0.0f));
pat2->addChild(node.get());
root->addChild(pat1.get());
root->addChild(pat2.get());
osgUtil::Optimizer optimizer;
optimizer.optimize(root.get());
viewer->setSceneData(root.get());
viewer->realize();
viewer->run();
return 0;
}
2.3.3 矩阵变换节点
矩阵变换节点(osg::MatixTransform)同样继承自osg::Transfom,其主要作用是负责场景中的矩阵变换、矩阵的原酸以及坐标系的变换。
osg::MatrixTransform的常用成员函数如下表:
成员函数名称 | 说明 |
---|---|
void setMatrix(const Matrix&mat) | 设置矩阵 |
const Matrix& getMatrix()const | 获取矩阵 |
void preMult(const Matrix&mat) | 递乘,类似于++a |
void postMult(const Matrix&mat) | 递乘,类似于a++ |
const Matrix&getInverseMatrix()const | 获取逆矩阵 |
2.3.4 矩阵变换节点示例
#include<osgViewer/Viewer>
#include<osg/Node>
#include<osg/Geode>
#include<osg/Group>
#include<osg/MatrixTransform>
#include<osgDB/ReadFile>
#include<osgDB/WriteFile>
#include<osgUtil/Optimizer>
int main()
{
// 创建VIewer对象,场景浏览器
osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();
osg::ref_ptr<osg::Group>root = new osg::Group();
osg::ref_ptr<osg::Node> node = osgDB::readNodeFile("cow.osg");
osg::ref_ptr<osg::MatrixTransform> mt1 = new osg::MatrixTransform();
osg::Matrix m;
m.makeTranslate(osg::Vec3(10.0f,0.0f,0.0f));// 平移
m.makeRotate(45.0f,1.0f,0.0f,0.0f);// 绕X轴转45°
mt1->setMatrix(m);
mt1->addChild(node.get());
osg::ref_ptr<osg::MatrixTransform> mt2 = new osg::MatrixTransform();
osg::Matrix t;
t.makeTranslate(osg::Vec3(-10.0f,0.0f,0.0f));// 平移
mt2->setMatrix(t);
mt2->addChild(node.get());
root->addChild(mt1.get());
root->addChild(mt2.get());
osgUtil::Optimizer optimizer;
optimizer.optimize(root.get());
viewer->setSceneData(root.get());
viewer->realize();
viewer->run();
return 0;
}
2.3.5 自动对齐节点
自动对齐节点(osg::AutoTransform)也继承自osg::Transform,它的主要作用是使节点自动对齐于摄像机或者屏幕。在实际应用中,通常可以用来显示一些不变化的文字或者其它的标识。
osg::AutoTransform有如下3种对齐模式:
enum AutoRotateMode
{
NO_ROTATION, // 无旋转
ROTATE_TO_SCREEN,// 自动朝向屏幕
ROTATE_TO_CAMERA // 自动朝向相机
}
2.3.6 自动对齐节点示例
#include<osgViewer/Viewer>
#include<osg/Node>
#include<osg/Geode>
#include<osg/Group>
#include<osg/AutoTransform>
#include<osgDB/ReadFile>
#include<osgDB/WriteFile>
#include<osgText/Text>
#include<osgUtil/Optimizer>
// 创建自动变换节点
osg::ref_ptr<osg::Node> createAutoTransform(osg::Vec3&position,float size,std::string&label,osg::AutoTransform::AutoRotateMode autoMode,osgText::Text::AxisAlignment axisAlignment)
{
osg::ref_ptr<osg::Geode> geode = new osg::Geode();
// 设置字体
std::string font("fonts/cour.ttf");
osg::ref_ptr<osgText::Text> text = new osgText::Text();
geode->addDrawable(text.get());
text->setFont(font);
text->setFontResolution(128.0f,128.0f);// 设置字体的分辨力,默认为32*32
text->setCharacterSize(size);// 设置字体大小
text->setAlignment(osgText::Text::CENTER_CENTER);// 对齐
text->setAxisAlignment(axisAlignment);// 设置方向
text->setText(label);
// 关闭光照
geode->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
// 创建自动变换节点
osg::ref_ptr<osg::AutoTransform> at = new osg::AutoTransform();
at->addChild(geode.get());
at->setAutoRotateMode(autoMode);
// 根据屏幕大小来缩放节点,默认为false,设置为true时,节点无法缩放
at->setAutoScaleToScreen(false);
// 设置缩放的最大和最小比例
at->setMinimumScale(0.0f);
at->setMaximumScale(5.0f);
at->setPosition(position);
return at.get();
}
//---------------------------------------------------------
int main()
{
// 创建VIewer对象,场景浏览器
osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();
osg::ref_ptr<osg::Group>root = new osg::Group();
std::string text("Fly To Sky");
// 添加ROTATE_TO_SCREEN模式变换节点
root->addChild(createAutoTransform(osg::Vec3(0.0f,0.0f,0.0f),60.0f,text,osg::AutoTransform::ROTATE_TO_SCREEN,osgText::Text::XY_PLANE));
// 添加NO_ROTATE模式变换节点
root->addChild(createAutoTransform(osg::Vec3(0.0f,0.0f,0.0f),60.0f,text,osg::AutoTransform::NO_ROTATE,osgText::Text::YZ_PLANE));
// 添加ROTATE_TO_CAMERA模式变换节点
root->addChild(createAutoTransform(osg::Vec3(0.0f,0.0f,0.0f),60.0f,text,osg::AutoTransform::ROTATE_TO_CAMERA,osgText::Text::XY_PLANE));
osgUtil::Optimizer optimizer;
optimizer.optimize(root.get());
viewer->setSceneData(root.get());
viewer->realize();
viewer->run();
return 0;
}
//---------------------------------------------------------