OpenSceneGraph几个重要功能节点练习

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenSceneGraph几个重要功能节点练习相关的知识,希望对你有一定的参考价值。

OpenSceneGraph几个重要功能节点练习

 一. 空间变换节点

 

空间变换中最重要的是坐标系和矩阵运算了。OSG坐标系中使用右手系,Z轴垂直向上,X轴水平向右,Y轴垂直屏幕向里,与OpenGL和DirectX都不同。
相关缩放、旋转和平移主要由osg::Matrix, osg::Vec3, osg::Quat几个类来完成。
局部坐标系向世界坐标系转换规则是:设在局部坐标系下顶点 V 转换成世界坐标系坐标 V‘:
    V‘ = V * Mn* Mn-1*……* M3* M2* M1* M0

其中M0到Mn一次为各个矩阵变换。从世界坐标系坐标下顶点 V‘ 转换成局部坐标系 V:
    V  = V‘ * M0-1 * M1-1 * M2-1 * M3-1 *……* Mn-1-1 * Mn-1

 

 

 

对于空间变换而言,无论是OpenGL,DirectX还是OSG,一般都会遵守SRT(Scale/Rotate/Translate)的运算顺序来完成符合矩阵的构建:
其公式为:

 

    M =Ms * Mr * Mt

osg::Matrix mt = osg::Matrix::scale( osg::Vex3(sx, sy, sz) ) *
                       osg::Matrix::rotate( osg::Quat(angle, axis) ) *
                       osg::Matrix::translate( osg::Vec3(tx, ty, tz) ) ;
osg::MatrixTransform, osg::PositionAttitudeTransform, osg::AutoTransform 示例:

 

代码
#include <osg/Node>
#include <osg/AutoTransform>
#include <osg/MatrixTransform>
#include <osg/PositionAttitudeTransform>
#include <osgDB/ReadFile>
#include <osgViewer/Viewer>

 //library for OSG
 #pragma comment(lib, "osgd.lib")
 #pragma comment(lib, "osgDBd.lib")
 #pragma comment(lib, "osgViewerd.lib")

osg::Transform*  createAutoTransform(double posX, osg::Node* node)
{
    osg::ref_ptr<osg::AutoTransform> at = new osg::AutoTransform();
    at->setAutoRotateMode( osg::AutoTransform::ROTATE_TO_SCREEN );
    at->setPosition( osg::Vec3(posX, 0, 0) );
    at->addChild( node );

    return at.release();
}

osg::Transform*  createMatrixTransform(double posX, double rotateZ, osg::Node* node)
{
    osg::ref_ptr<osg::MatrixTransform> mt = new osg::MatrixTransform();
    mt->setMatrix( osg::Matrix::rotate( rotateZ, osg::Z_AXIS) *
                         osg::Matrix::translate( posX, 0, 0) );
    mt->addChild( node );

    return mt.release();
}

osg::Transform* createPositionAttitudeTransform(double posX, double rotateZ, osg::Node* node)
{
    osg::ref_ptr<osg::PositionAttitudeTransform> pat = new osg::PositionAttitudeTransform();
    pat->setAttitude( osg::Quat(rotateZ, osg::Z_AXIS) );
    pat->setPosition( osg::Vec3(posX, 0, 0) );
    pat->addChild(node);

    return pat.release();
}

int main(int argc, char** argv)
{
    osg::ArgumentParser argument(&argc, argv);
    osg::ref_ptr<osg::Node> node = osgDB::readNodeFiles(argument);
    if( !node.get() ) node = osgDB::readNodeFile( "cow.osg" );

    osg::ref_ptr<osg::Group> root = new osg::Group();
    root->addChild( createAutoTransform(0.0, node) );
    root->addChild( createMatrixTransform(-15.0, osg::PI_4, node) );
    root->addChild( createPositionAttitudeTransform(15.0, -osg::PI_4, node) );

    osgViewer::Viewer  viewer;
    viewer.setSceneData( root.get() );
    return viewer.run();
}

 

二. 开关节点(osg::Switch)
开关节点Switch的作用是,在场景中某时刻,它的某些子节点被隐藏和忽略,而列外一些节点正常显示并完成相应功能。示例中利用开关节点的更新回调实现子节点的切换: 

 

代码
#include <osg/Switch>
#include <osg/NodeCallback>
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
#include <osgViewer/Viewer>

#pragma comment(lib, "osgd.lib")
#pragma comment(lib, "osgDBd.lib")
#pragma comment(lib, "osgViewerd.lib")

class CessnaCallback: public osg::NodeCallback
{
public:
    virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
    {
        osg::Switch* sw = dynamic_cast<osg::Switch*>(node);
        if(sw && nv)
        {
            const osg::FrameStamp* fs = nv->getFrameStamp();
            if( fs )
            {
                if( _fireStartFrame < fs->getFrameNumber() )
                {
                    sw->setValue(0, false);
                    sw->setValue(1, true);
                }
            }
        }
        traverse(node, nv);
    }

private:
    static const int _fireStartFrame = 900;
};

int main(int argc, char** argv)
{    
    osg::ref_ptr<osg::Switch> root = new osg::Switch();
    root->addChild( osgDB::readNodeFile("cessna.osg"), true );
    root->addChild( osgDB::readNodeFile("cessnafire.osg"), false );
    root->addUpdateCallback(new CessnaCallback() );

    osgDB::writeNodeFile( *(root.get()), "Switch.osg" );
    osgViewer::Viewer viewer;
    viewer.setSceneData( root.get() );
    return viewer.run();
}

三. 细节层次节点(osg::LOD)

LOD节点,其基本实现功能是在不影响渲染效果的条件下 ,根据场景对象与观察者的距离,从多个预置方案中选择一种合适的来表达要渲染的物体,从而减轻系统的负担,模型越靠近观察者越精细,而远处只需要较少的多边形类表达。示例如下:

代码
#include <osg/LOD>
#include <osgDB/ReadFile>
#include <osgViewer/Viewer>
#include <osg/Notify>

#pragma comment(lib, "osgd.lib")
#pragma comment(lib, "osgDBd.lib")
#pragma comment(lib, "osgViewerd.lib")

int main(int argc, char** argv)
{
    osg::ref_ptr<osg::Node> node = osgDB::readNodeFile( "bunny-high.ive" );

    if(!node)
    {
        osg::notify(osg::NotifySeverity::ALWAYS) << "Cannot open the model bunny!\\n" ;
        return 0;
    }

    float r = node->getBound().radius();

    osg::ref_ptr<osg::LOD> lod = new osg::LOD();
    lod->addChild(node.get(), 0.0f, r*3 );
    lod->addChild( osgDB::readNodeFile("bunny-mid.ive"), r*3, r*7 );
    lod->addChild( osgDB::readNodeFile("bunny-low.ive"), r*7, FLT_MAX );

    osgViewer::Viewer viewer;
    viewer.setSceneData( lod.get() );
    viewer.run();
}

 

四. 代理节点(ProxyNode)
ProxyNode代理节点是一种用于动态加载其他模型节点的节点类型。这些节点不会立即被解析和加入场景,而是在场景运行过程中逐步载入。示例:

代码
#include <osg/ProxyNode>
#include <osgDB/ReadFile>
#include <osg/ArgumentParser>
#include <osgViewer/Viewer>
#include <osg/Notify>
#include <iostream>

#pragma comment(lib, "osgd.lib")
#pragma comment(lib, "osgDBd.lib")
#pragma comment(lib, "osgViewerd.lib")


int main(int argc, char** argv)
{
    osg::ArgumentParser argument(&argc, argv);
    osg::ref_ptr<osg::ProxyNode> pn = new osg::ProxyNode();
    unsigned int num = 0;

    for(int i = 1; i < argument.argc(); i++)
    {
        if( argument.isString(i) )
        {
            std::cout << num << ":  " << argument[i] << "\\n" ;
            pn->setFileName( num++, argument[i] );
        }
    }
    if( !pn->getNumFileNames() )
        pn->setFileName(0, "cow.osg" );

    osgViewer::Viewer viewer;
    viewer.setSceneData( pn.get() );
    return viewer.run();
}

 

以上是关于OpenSceneGraph几个重要功能节点练习的主要内容,如果未能解决你的问题,请参考以下文章

OpencascadeOpenGL和OpenSceneGraph的区别与联系

OpenSceneGraph环境搭建

OpenSceneGraph概览——组件

使用doxygengraphviz生成OpenSceneGraph文档

代写android编程作业代写游戏作业

Windows下用Cmake编译OpenSceneGraph