OpenSceneGraph实现的NeHe OpenGL教程 - 第十二课

  • 简介

本课NeHe教程主要是使用了OpenGL中的显示列表。OpenGL的显示列表是加速OpenGL性能的一种重要的手段。OpenGl的几何体绘制方法主要包括立即模式、顶点数组、显示列表和VBO。在OSG中显示列表是大部分OSG程序所使用的默认绘制优化行为,因此不需要我们去像OpenGL那样进行设置。

  • 实现

首先创建整个场景,本课中我使用了OSG中预定义的几种基本形体,(osg::Box)来绘制立方体

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. osg::Node*  buildScene()  
  2. {  
  3.     osg::Group *root = new osg::Group;  
  4.   
  5.     for (int yloop=1;yloop<6;yloop++)  
  6.     {  
  7.         osg::Group *cubeGroup = new osg::Group;  
  8.   
  9.         for (int xloop=0;xloop<yloop;xloop++)  
  10.         {  
  11.             osg::MatrixTransform *posMT = new osg::MatrixTransform;  
  12.             posMT->setMatrix(osg::Matrix::translate(1.4f+(float(xloop)*2.8f)-(float(yloop)*1.4f),((6.0f-float(yloop))*2.4f)-7.0f,-20.0f));  
  13.             cubeGroup->addChild(posMT);  
  14.               
  15.             osg::MatrixTransform *rotXMT = new osg::MatrixTransform;  
  16.             rotXMT->setName("XRotMT");  
  17.             posMT->addChild(rotXMT);  
  18.             XRotCallback* xrot = new XRotCallback(osg::DegreesToRadians(45.0f-(2.0f*yloop)));  
  19.             rotXMT->setUpdateCallback(xrot);  
  20.   
  21.             osg::MatrixTransform *rotYMT = new osg::MatrixTransform;  
  22.             rotXMT->addChild(rotYMT);  
  23.             rotYMT->setName("YRotMT");  
  24.             YRotCallback* yrot = new YRotCallback(osg::DegreesToRadians(45.0f));  
  25.             rotYMT->setUpdateCallback(yrot);  
  26.   
  27.             osg::Geode *cube = createCube(yloop-1);  
  28.             rotYMT->addChild(cube);  
  29.         }  
  30.         root->addChild(cubeGroup);  
  31.     }  
  32.   
  33.     return root;  
  34. }  
参照NeHe教程中平移量进行(glTranslate对应一个osg::MatrixTransform),对于每一个几何体叶节点,通过不同的颜色索引值创建它

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. osg::Geode* createCube(int colorIndex)  
  2. {  
  3.     osg::Image *textureImage = osgDB::readImageFile("Data/Cube.bmp");  
  4.     osg::Texture2D *texture2D = new osg::Texture2D;  
  5.     texture2D->setImage(textureImage);  
  6.     texture2D->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);  
  7.     texture2D->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);  
  8.   
  9.     osg::ShapeDrawable *sd = new osg::ShapeDrawable(new osg::Box(osg::Vec3(0, 0, 0), 2));  
  10.     sd->setColor(osg::Vec4d(boxcol[colorIndex][0], boxcol[colorIndex][1], boxcol[colorIndex][2], 1));  
  11.   
  12.     osg::Geode *cubeGeode = new osg::Geode;  
  13.     cubeGeode->addDrawable(sd);  
  14.     cubeGeode->getOrCreateStateSet()->setTextureAttributeAndModes(0, texture2D);  
  15.   
  16.     return cubeGeode;  
  17. }  

可以看到场景中对每一个MatrixTransform均设置了UpdateCallback,为的是通过键盘对它们进行操作。首先先通过名字找到所有这些节点

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. class FindNamedNodeVisitor : public osg::NodeVisitor  
  2. {  
  3. public:  
  4.     FindNamedNodeVisitor(const std::string& name):  
  5.       osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),  
  6.           _name(name), _foundNode(NULL) {}  
  7.   
  8.       virtual void apply(osg::Node& node)  
  9.       {  
  10.           if (node.getName()==_name)  
  11.           {  
  12.               _foundNode.push_back(&node);  
  13.           }  
  14.           traverse(node);  
  15.       }  
  16.   
  17.       std::string _name;  
  18.       std::vector<osg::Node*> _foundNode;  
  19. };  

在EventHandler交互类中进行设置如下:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Left)  
  2. {  
  3.     FindNamedNodeVisitor fnnv("YRotMT");  
  4.     root->accept(fnnv);  
  5.   
  6.     for (unsigned i = 0; i < fnnv._foundNode.size(); ++i)  
  7.     {  
  8.         yrot = dynamic_cast<YRotCallback*>(fnnv._foundNode.at(i)->getUpdateCallback());  
  9.         if (yrot)  
  10.         {  
  11.             yrot->setAngle(yrot->getAngle() - osg::DegreesToRadians(2.0));  
  12.         }  
  13.     }  
  14. }  
编译运行程序


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

[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.   
  13. #include <osgDB/ReadFile>  
  14. #include <osg/Texture2D>  
  15.   
  16. #include <osg/ShapeDrawable>  
  17. #include <osg/NodeVisitor>  
  18.   
  19. static GLfloat boxcol[5][3]=  
  20. {  
  21.     {1.0f,0.0f,0.0f},{1.0f,0.5f,0.0f},{1.0f,1.0f,0.0f},{0.0f,1.0f,0.0f},{0.0f,1.0f,1.0f}  
  22. };  
  23.   
  24. //  
  25. //RotCallback  
  26.   
  27. class XRotCallback : public osg::NodeCallback  
  28. {  
  29. public:  
  30.   
  31.     XRotCallback(double angle) : _angle(angle){}  
  32.   
  33.     virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)  
  34.     {  
  35.   
  36.         if (dynamic_cast<osg::MatrixTransform*>(node))  
  37.         {  
  38.             osg::MatrixTransform *rot = dynamic_cast<osg::MatrixTransform*>(node);  
  39.             rot->setMatrix(osg::Matrix::rotate(_angle, osg::X_AXIS));  
  40.         }  
  41.   
  42.         traverse(node, nv);  
  43.     }  
  44.   
  45.     void setAngle(double angle)  
  46.     {  
  47.         _angle = angle;  
  48.     }  
  49.   
  50.     double getAngle() const  
  51.     {  
  52.         return _angle;  
  53.     }  
  54.   
  55.     double _angle;  
  56. };  
  57.   
  58.   
  59. class YRotCallback : public osg::NodeCallback  
  60. {  
  61. public:  
  62.   
  63.     YRotCallback(double angle) : _angle(angle){}  
  64.   
  65.     virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)  
  66.     {  
  67.   
  68.         if (dynamic_cast<osg::MatrixTransform*>(node))  
  69.         {  
  70.             osg::MatrixTransform *rot = dynamic_cast<osg::MatrixTransform*>(node);  
  71.             rot->setMatrix(osg::Matrix::rotate(_angle, osg::Y_AXIS));  
  72.         }  
  73.   
  74.         traverse(node, nv);  
  75.     }  
  76.   
  77.     void setAngle(double angle)  
  78.     {  
  79.         _angle = angle;  
  80.     }  
  81.   
  82.     double getAngle() const  
  83.     {  
  84.         return _angle;  
  85.     }  
  86.   
  87.     double _angle;  
  88. };  
  89.   
  90. //End  
  91. //  
  92.   
  93. class FindNamedNodeVisitor : public osg::NodeVisitor  
  94. {  
  95. public:  
  96.     FindNamedNodeVisitor(const std::string& name):  
  97.       osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),  
  98.           _name(name), _foundNode(NULL) {}  
  99.   
  100.       virtual void apply(osg::Node& node)  
  101.       {  
  102.           if (node.getName()==_name)  
  103.           {  
  104.               _foundNode.push_back(&node);  
  105.           }  
  106.           traverse(node);  
  107.       }  
  108.   
  109.       std::string _name;  
  110.       std::vector<osg::Node*> _foundNode;  
  111. };  
  112.   
  113.   
  114.   
  115. //  
  116. //EventHandler  
  117. class ManipulatorSceneHandler : public osgGA::GUIEventHandler  
  118. {  
  119. public:  
  120.     ManipulatorSceneHandler()  
  121.     {  
  122.     }  
  123.   
  124.     virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)  
  125.     {  
  126.         osgViewer::Viewer *viewer = dynamic_cast<osgViewer::Viewer*>(&aa);  
  127.         if (!viewer)  
  128.             return false;  
  129.         if (!viewer->getSceneData())  
  130.             return false;  
  131.         if (ea.getHandled())   
  132.             return false;  
  133.   
  134.         osg::Group *root = viewer->getSceneData()->asGroup();  
  135.   
  136.         switch(ea.getEventType())  
  137.         {  
  138.         case(osgGA::GUIEventAdapter::KEYDOWN):  
  139.             {  
  140.                 XRotCallback *xrot;  
  141.                 YRotCallback *yrot;  
  142.   
  143.                 if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Left)  
  144.                 {  
  145.                     FindNamedNodeVisitor fnnv("YRotMT");  
  146.                     root->accept(fnnv);  
  147.   
  148.                     for (unsigned i = 0; i < fnnv._foundNode.size(); ++i)  
  149.                     {  
  150.                         yrot = dynamic_cast<YRotCallback*>(fnnv._foundNode.at(i)->getUpdateCallback());  
  151.                         if (yrot)  
  152.                         {  
  153.                             yrot->setAngle(yrot->getAngle() - osg::DegreesToRadians(2.0));  
  154.                         }  
  155.                     }  
  156.                 }  
  157.   
  158.                 if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Right)  
  159.                 {  
  160.                     FindNamedNodeVisitor fnnv("YRotMT");  
  161.                     root->accept(fnnv);  
  162.   
  163.                     for (unsigned i = 0; i < fnnv._foundNode.size(); ++i)  
  164.                     {  
  165.                         yrot = dynamic_cast<YRotCallback*>(fnnv._foundNode.at(i)->getUpdateCallback());  
  166.                         if (yrot)  
  167.                         {  
  168.                             yrot->setAngle(yrot->getAngle() + osg::DegreesToRadians(2.0));  
  169.                         }  
  170.                     }  
  171.                 }  
  172.   
  173.                 if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Up)  
  174.                 {  
  175.                     FindNamedNodeVisitor fnnv("XRotMT");  
  176.                     root->accept(fnnv);  
  177.   
  178.                     for (unsigned i = 0; i < fnnv._foundNode.size(); ++i)  
  179.                     {  
  180.                         xrot = dynamic_cast<XRotCallback*>(fnnv._foundNode.at(i)->getUpdateCallback());  
  181.                         if (xrot)  
  182.                         {  
  183.                             xrot->setAngle(xrot->getAngle() - osg::DegreesToRadians(2.0));  
  184.                         }  
  185.                     }  
  186.                 }  
  187.   
  188.                 if (ea.getKey()== osgGA::GUIEventAdapter::KEY_Down)  
  189.                 {  
  190.                     FindNamedNodeVisitor fnnv("XRotMT");  
  191.                     root->accept(fnnv);  
  192.   
  193.                     for (unsigned i = 0; i < fnnv._foundNode.size(); ++i)  
  194.                     {  
  195.                         xrot = dynamic_cast<XRotCallback*>(fnnv._foundNode.at(i)->getUpdateCallback());  
  196.                         if (xrot)  
  197.                         {  
  198.                             xrot->setAngle(xrot->getAngle() + osg::DegreesToRadians(2.0));  
  199.                         }  
  200.                     }  
  201.                 }  
  202.             }  
  203.         defaultbreak;  
  204.         }  
  205.         return false;  
  206.     }  
  207. };  
  208.   
  209.   
  210. //End  
  211. //  
  212.   
  213.   
  214. class ViewerWidget : public QWidget, public osgViewer::Viewer  
  215. {  
  216. public:  
  217.     ViewerWidget(osg::Node *scene = NULL)  
  218.     {  
  219.         QWidget* renderWidget = getRenderWidget( createGraphicsWindow(0,0,100,100), scene);  
  220.   
  221.         QVBoxLayout* layout = new QVBoxLayout;  
  222.         layout->addWidget(renderWidget);  
  223.         layout->setContentsMargins(0, 0, 0, 1);  
  224.         setLayout( layout );  
  225.   
  226.         connect( &_timer, SIGNAL(timeout()), this, SLOT(update()) );  
  227.         _timer.start( 10 );  
  228.     }  
  229.   
  230.     QWidget* getRenderWidget( osgQt::GraphicsWindowQt* gw, osg::Node* scene )  
  231.     {  
  232.         osg::Camera* camera = this->getCamera();  
  233.         camera->setGraphicsContext( gw );  
  234.   
  235.         const osg::GraphicsContext::Traits* traits = gw->getTraits();  
  236.   
  237.         camera->setClearColor( osg::Vec4(0.0, 0.0, 0.0, 1.0) );  
  238.         camera->setViewport( new osg::Viewport(0, 0, traits->width, traits->height) );  
  239.         camera->setProjectionMatrixAsPerspective(45.0f, static_cast<double>(traits->width)/static_cast<double>(traits->height), 0.1f, 100.0f );  
  240.         camera->setViewMatrixAsLookAt(osg::Vec3d(0, 0, 1), osg::Vec3d(0, 0, 0), osg::Vec3d(0, 1, 0));  
  241.   
  242.         this->setSceneData( scene );  
  243.         this->addEventHandler(new ManipulatorSceneHandler);  
  244.   
  245.         return gw->getGLWidget();  
  246.     }  
  247.   
  248.     osgQt::GraphicsWindowQt* createGraphicsWindow( int x, int y, int w, int h, const std::string& name=""bool windowDecoration=false )  
  249.     {  
  250.         osg::DisplaySettings* ds = osg::DisplaySettings::instance().get();  
  251.         osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;  
  252.         traits->windowName = name;  
  253.         traits->windowDecoration = windowDecoration;  
  254.         traits->x = x;  
  255.         traits->y = y;  
  256.         traits->width = w;  
  257.         traits->height = h;  
  258.         traits->doubleBuffer = true;  
  259.         traits->alpha = ds->getMinimumNumAlphaBits();  
  260.         traits->stencil = ds->getMinimumNumStencilBits();  
  261.         traits->sampleBuffers = ds->getMultiSamples();  
  262.         traits->samples = ds->getNumMultiSamples();  
  263.   
  264.         return new osgQt::GraphicsWindowQt(traits.get());  
  265.     }  
  266.   
  267.     virtual void paintEvent( QPaintEvent* event )  
  268.     {   
  269.         frame();   
  270.     }  
  271.   
  272. protected:  
  273.   
  274.     QTimer _timer;  
  275. };  
  276.   
  277.   
  278. osg::Geode* createCube(int colorIndex)  
  279. {  
  280.     osg::Image *textureImage = osgDB::readImageFile("Data/Cube.bmp");  
  281.     osg::Texture2D *texture2D = new osg::Texture2D;  
  282.     texture2D->setImage(textureImage);  
  283.     texture2D->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);  
  284.     texture2D->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);  
  285.   
  286.     osg::ShapeDrawable *sd = new osg::ShapeDrawable(new osg::Box(osg::Vec3(0, 0, 0), 2));  
  287.     sd->setColor(osg::Vec4d(boxcol[colorIndex][0], boxcol[colorIndex][1], boxcol[colorIndex][2], 1));  
  288.   
  289.     osg::Geode *cubeGeode = new osg::Geode;  
  290.     cubeGeode->addDrawable(sd);  
  291.     cubeGeode->getOrCreateStateSet()->setTextureAttributeAndModes(0, texture2D);  
  292.   
  293.     return cubeGeode;  
  294. }  
  295.   
  296.   
  297. osg::Node*  buildScene()  
  298. {  
  299.     osg::Group *root = new osg::Group;  
  300.   
  301.     for (int yloop=1;yloop<6;yloop++)  
  302.     {  
  303.         osg::Group *cubeGroup = new osg::Group;  
  304.   
  305.         for (int xloop=0;xloop<yloop;xloop++)  
  306.         {  
  307.             osg::MatrixTransform *posMT = new osg::MatrixTransform;  
  308.             posMT->setMatrix(osg::Matrix::translate(1.4f+(float(xloop)*2.8f)-(float(yloop)*1.4f),((6.0f-float(yloop))*2.4f)-7.0f,-20.0f));  
  309.             cubeGroup->addChild(posMT);  
  310.               
  311.             osg::MatrixTransform *rotXMT = new osg::MatrixTransform;  
  312.             rotXMT->setName("XRotMT");  
  313.             posMT->addChild(rotXMT);  
  314.             XRotCallback* xrot = new XRotCallback(osg::DegreesToRadians(45.0f-(2.0f*yloop)));  
  315.             rotXMT->setUpdateCallback(xrot);  
  316.   
  317.             osg::MatrixTransform *rotYMT = new osg::MatrixTransform;  
  318.             rotXMT->addChild(rotYMT);  
  319.             rotYMT->setName("YRotMT");  
  320.             YRotCallback* yrot = new YRotCallback(osg::DegreesToRadians(45.0f));  
  321.             rotYMT->setUpdateCallback(yrot);  
  322.   
  323.             osg::Geode *cube = createCube(yloop-1);  
  324.             rotYMT->addChild(cube);  
  325.         }  
  326.         root->addChild(cubeGroup);  
  327.     }  
  328.   
  329.     return root;  
  330. }  
  331.   
  332.   
  333.   
  334. int main( int argc, char** argv )  
  335. {  
  336.     QApplication app(argc, argv);  
  337.     ViewerWidget* viewWidget = new ViewerWidget(buildScene());  
  338.     viewWidget->setGeometry( 100, 100, 640, 480 );  
  339.     viewWidget->show();  
  340.     return app.exec();  
  341. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值