OpenSceneGraph实现的NeHe OpenGL教程 - 第四课

  • 简介

本课要实现的效果是让三角形绕自身的轴线Y轴进行旋转, 四边形绕自身X轴进行旋转。

在osg中实现这种效果有很多种方法可以做到,无论哪种方法总体的思路是定时地去修改场景中的空间变换节点,本文采用最简单的一种方式进行修改:使用场景中节点的回调来修改空间变换节点从而达到旋转的效果。

  • 实现

首先我们先定义一个场景节点的Callback类,OSG中的节点主要使用回调(Callback)来完成用户临时定义的、需要每帧执行的工作。这是一种方便的扩展节点功能的方式,根据回调功能被调用的时机,OSG节点回调包括更新回调(UpdateCallback)和人机交互事件回调(EventCallback)两种,前者在每一帧系统遍历到当前节点时自动调用,后者则通过用户操作键盘、鼠标、改变窗口等动作发生,触发事件回调。此处我们需要的是一个节点的更新回调,定义如下:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. class RotateCallback : public osg::NodeCallback  
  2. {  
  3.   
  4. public:  
  5.     RotateCallback(osg::Vec3d rotateAxis, double rotateSpeed) :   
  6.       osg::NodeCallback(),  
  7.       _rotateAxis(rotateAxis),   
  8.       _rotateSpeed(rotateSpeed),  
  9.       _rotateAngle(0.0)  
  10.       {  
  11.         //Nop  
  12.       }  
  13.   
  14.   
  15.       virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)  
  16.     {  
  17.             osg::MatrixTransform *currentMT = dynamic_cast<osg::MatrixTransform*>(node);  
  18.             if (currentMT)  
  19.             {  
  20.                 //获取当前的平移位置  
  21.                 osg::Vec3d currentTranslate = currentMT->getMatrix().getTrans();  
  22.                 osg::Matrix newMatrix = osg::Matrix::rotate(_rotateAngle, _rotateAxis) * osg::Matrix::translate(currentTranslate);  
  23.                 currentMT->setMatrix(newMatrix);  
  24.                 _rotateAngle += _rotateSpeed;  
  25.             }  
  26.   
  27.             traverse(node, nv);  
  28.     }  
  29.   
  30.   
  31. private:  
  32.     osg::Vec3d _rotateAxis;         //旋转轴  
  33.     double        _rotateSpeed;     //旋转速度  
  34.     double        _rotateAngle;     //当前旋转的角度  
  35. };  

节点回调类都继承于osg::NodeCallback,我们需要做的是重载它里面的operator()方法来实现自定义的代码,定义好之后将回调加入到三角形和四边形的空间变化节点之中:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. osg::MatrixTransform *triangleMT = new osg::MatrixTransform;  
  2. triangleMT->setMatrix(osg::Matrix::translate(-1.5, 0.0, -6.0));  
  3.   
  4. RotateCallback *triangleRotateCallback = new RotateCallback(osg::Y_AXIS, 0.2);  
  5. triangleMT->addUpdateCallback(triangleRotateCallback);  
以及

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. osg::MatrixTransform *quadMT = new osg::MatrixTransform;  
  2. quadMT->setMatrix(osg::Matrix::translate(1.5, 0.0, -6.0));  
  3.   
  4. RotateCallback *quadRotateCallback = new RotateCallback(osg::X_AXIS, 0.15);  
  5. quadMT->addUpdateCallback(quadRotateCallback);  
编译并运行程序即看到动态的效果


附:本课源码(源码中可能存在错误和不足,仅供参考)

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #include "../osgNeHe.h"  
  2.   
  3. #include <QtCore/QTimer>  
  4. #include <QtGui/QApplication>  
  5. #include <QtGui/QVBoxLayout>  
  6.   
  7. #include <osgViewer/Viewer>  
  8. #include <osgDB/ReadFile>  
  9. #include <osgQt/GraphicsWindowQt>  
  10.   
  11. #include <osg/MatrixTransform>  
  12. #include <osg/NodeVisitor>  
  13.   
  14.   
  15. class ViewerWidget : public QWidget, public osgViewer::Viewer  
  16. {  
  17. public:  
  18.     ViewerWidget(osg::Node *scene = NULL)  
  19.     {  
  20.         QWidget* renderWidget = getRenderWidget( createGraphicsWindow(0,0,100,100), scene);  
  21.   
  22.         QVBoxLayout* layout = new QVBoxLayout;  
  23.         layout->addWidget(renderWidget);  
  24.         layout->setContentsMargins(0, 0, 0, 1);  
  25.         setLayout( layout );  
  26.   
  27.         connect( &_timer, SIGNAL(timeout()), this, SLOT(update()) );  
  28.         _timer.start( 10 );  
  29.     }  
  30.   
  31.     QWidget* getRenderWidget( osgQt::GraphicsWindowQt* gw, osg::Node* scene )  
  32.     {  
  33.         osg::Camera* camera = this->getCamera();  
  34.         camera->setGraphicsContext( gw );  
  35.   
  36.         const osg::GraphicsContext::Traits* traits = gw->getTraits();  
  37.   
  38.         camera->setClearColor( osg::Vec4(0.0, 0.0, 0.0, 1.0) );  
  39.         camera->setViewport( new osg::Viewport(0, 0, traits->width, traits->height) );  
  40.         camera->setProjectionMatrixAsPerspective(45.0f, static_cast<double>(traits->width)/static_cast<double>(traits->height), 0.1f, 100.0f );  
  41.         camera->setViewMatrixAsLookAt(osg::Vec3d(0, 0, 1), osg::Vec3d(0, 0, 0), osg::Vec3d(0, 1, 0));  
  42.   
  43.         this->setSceneData( scene );  
  44.   
  45.         return gw->getGLWidget();  
  46.     }  
  47.   
  48.     osgQt::GraphicsWindowQt* createGraphicsWindow( int x, int y, int w, int h, const std::string& name=""bool windowDecoration=false )  
  49.     {  
  50.         osg::DisplaySettings* ds = osg::DisplaySettings::instance().get();  
  51.         osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;  
  52.         traits->windowName = name;  
  53.         traits->windowDecoration = windowDecoration;  
  54.         traits->x = x;  
  55.         traits->y = y;  
  56.         traits->width = w;  
  57.         traits->height = h;  
  58.         traits->doubleBuffer = true;  
  59.         traits->alpha = ds->getMinimumNumAlphaBits();  
  60.         traits->stencil = ds->getMinimumNumStencilBits();  
  61.         traits->sampleBuffers = ds->getMultiSamples();  
  62.         traits->samples = ds->getNumMultiSamples();  
  63.   
  64.         return new osgQt::GraphicsWindowQt(traits.get());  
  65.     }  
  66.   
  67.     virtual void paintEvent( QPaintEvent* event )  
  68.     {   
  69.         frame();   
  70.     }  
  71.   
  72. protected:  
  73.   
  74.     QTimer _timer;  
  75. };  
  76.   
  77.   
  78.   
  79. //  
  80. //RotateCallback  
  81.   
  82. class RotateCallback : public osg::NodeCallback  
  83. {  
  84.   
  85. public:  
  86.     RotateCallback(osg::Vec3d rotateAxis, double rotateSpeed) :   
  87.       osg::NodeCallback(),  
  88.       _rotateAxis(rotateAxis),   
  89.       _rotateSpeed(rotateSpeed),  
  90.       _rotateAngle(0.0)  
  91.       {  
  92.         //Nop  
  93.       }  
  94.   
  95.   
  96.       virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)  
  97.     {  
  98.             osg::MatrixTransform *currentMT = dynamic_cast<osg::MatrixTransform*>(node);  
  99.             if (currentMT)  
  100.             {  
  101.                 //获取当前的平移位置  
  102.                 osg::Vec3d currentTranslate = currentMT->getMatrix().getTrans();  
  103.                 osg::Matrix newMatrix = osg::Matrix::rotate(_rotateAngle, _rotateAxis) * osg::Matrix::translate(currentTranslate);  
  104.                 currentMT->setMatrix(newMatrix);  
  105.                 _rotateAngle += _rotateSpeed;  
  106.             }  
  107.   
  108.             traverse(node, nv);  
  109.     }  
  110.   
  111.   
  112. private:  
  113.     osg::Vec3d _rotateAxis;         //旋转轴  
  114.     double        _rotateSpeed;     //旋转速度  
  115.     double        _rotateAngle;     //当前旋转的角度  
  116. };  
  117.   
  118.   
  119.   
  120. osg::Node*  buildScene()  
  121. {  
  122.     osg::Group *root = new osg::Group;  
  123.   
  124.     osg::MatrixTransform *triangleMT = new osg::MatrixTransform;  
  125.     triangleMT->setMatrix(osg::Matrix::translate(-1.5, 0.0, -6.0));  
  126.   
  127.     RotateCallback *triangleRotateCallback = new RotateCallback(osg::Y_AXIS, 0.2);  
  128.     triangleMT->addUpdateCallback(triangleRotateCallback);  
  129.   
  130.     osg::Geometry *triangleGeometry = new osg::Geometry;  
  131.     osg::Vec3Array *triangleVertexArray = new osg::Vec3Array;  
  132.     triangleVertexArray->push_back(osg::Vec3(0.0f, 1.0f, 0.0f));  
  133.     triangleVertexArray->push_back(osg::Vec3(-1.0f,-1.0f, 0.0f));  
  134.     triangleVertexArray->push_back(osg::Vec3(1.0f,-1.0f, 0.0f));  
  135.     triangleGeometry->setVertexArray(triangleVertexArray);  
  136.   
  137.     osg::Vec4Array *triangleColorArray = new osg::Vec4Array;  
  138.     triangleColorArray->push_back(osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f));  
  139.     triangleColorArray->push_back(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f));  
  140.     triangleColorArray->push_back(osg::Vec4(0.0f, 0.0f, 1.0f, 1.0f));  
  141.     triangleGeometry->setColorArray(triangleColorArray);  
  142.     triangleGeometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);  
  143.   
  144.     triangleGeometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES, 0, 3));  
  145.     osg::Geode *triangleGeode = new osg::Geode;  
  146.   
  147.     triangleGeode->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);  
  148.     triangleGeode->addDrawable(triangleGeometry);  
  149.     triangleMT->addChild(triangleGeode);  
  150.   
  151.     //四边形部分  
  152.     osg::MatrixTransform *quadMT = new osg::MatrixTransform;  
  153.     quadMT->setMatrix(osg::Matrix::translate(1.5, 0.0, -6.0));  
  154.   
  155.     RotateCallback *quadRotateCallback = new RotateCallback(osg::X_AXIS, 0.15);  
  156.     quadMT->addUpdateCallback(quadRotateCallback);  
  157.   
  158.     osg::Geometry *quadGeometry = new osg::Geometry;  
  159.     osg::Vec3Array *quadVertexArray = new osg::Vec3Array;  
  160.     quadVertexArray->push_back(osg::Vec3(-1.0f, 1.0f, 0.0f));  
  161.     quadVertexArray->push_back(osg::Vec3(1.0f, 1.0f, 0.0f));  
  162.     quadVertexArray->push_back(osg::Vec3(1.0f,-1.0f, 0.0f));  
  163.     quadVertexArray->push_back(osg::Vec3(-1.0f,-1.0f, 0.0f));  
  164.     quadGeometry->setVertexArray(quadVertexArray);  
  165.   
  166.     osg::Vec4Array *quadColorArray = new osg::Vec4Array;  
  167.     quadColorArray->push_back(osg::Vec4(0.5f,0.5f,1.0f,1.0f));  
  168.     quadGeometry->setColorArray(quadColorArray);  
  169.     quadGeometry->setColorBinding(osg::Geometry::BIND_OVERALL);  
  170.   
  171.     osg::DrawElementsUByte *vertexIndices = new osg::DrawElementsUByte(osg::PrimitiveSet::QUADS, 4);  
  172.     vertexIndices->push_back(0);  
  173.     vertexIndices->push_back(1);  
  174.     vertexIndices->push_back(2);  
  175.     vertexIndices->push_back(3);  
  176.     quadGeometry->addPrimitiveSet(vertexIndices);  
  177.     osg::Geode *quadGeode = new osg::Geode;  
  178.     quadGeode->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);  
  179.     quadGeode->addDrawable(quadGeometry);  
  180.     quadMT->addChild(quadGeode);  
  181.   
  182.     root->addChild(triangleMT);  
  183.     root->addChild(quadMT);  
  184.   
  185.     return root;  
  186. }  
  187.   
  188.   
  189.   
  190. int main( int argc, char** argv )  
  191. {  
  192.     QApplication app(argc, argv);  
  193.     ViewerWidget* viewWidget = new ViewerWidget(buildScene());  
  194.     viewWidget->setGeometry( 100, 100, 640, 480 );  
  195.     viewWidget->show();  
  196.     return app.exec();  
  197. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值