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

  • 简介

这节课在第七课的基础上修改了部分代码,用来在场景中显示圆球、圆柱、圆锥等二次几何体。在osg中定义了一些基本的几何体,主要有如下几种:

Fig1. osg内置定义的几何体类型

  • 实现

在本课中通过切换空格键实现几何体的切换,在osg中开关节点osg::Switch用在这里再合适不过了,它可以切换不同的子节点进行显示

我们定义如下:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. //  
  2.     //新增代码,使用开关节点管理  
  3.     g_Switch = new osg::Switch;  
  4.   
  5.     //添加立方体  
  6.     osg::Geode *box = new osg::Geode;  
  7.     osg::ShapeDrawable *boxDrawable = new osg::ShapeDrawable;  
  8.     osg::Box *boxShape = new osg::Box(osg::Vec3(0, 0,0), 2);  
  9.     boxDrawable->setShape(boxShape);  
  10.     box->addDrawable(boxDrawable);  
  11.     g_Switch->addChild(box);  
  12.   
  13.     //添加圆柱体  
  14.     osg::Geode *cylinder = new osg::Geode;  
  15.     osg::ShapeDrawable *cylinderDrawable = new osg::ShapeDrawable(new osg::Cylinder(osg::Vec3(0,0,0), 0.5, 2.0));  
  16.     cylinder->addDrawable(cylinderDrawable);  
  17.     g_Switch->addChild(cylinder);  
  18.   
  19.     //添加圆盘  
  20.     osg::Geode *disk = new osg::Geode;  
  21.     osg::ShapeDrawable *diskDrawable = new osg::ShapeDrawable(new osg::Cylinder(osg::Vec3(0,0,0), 0.5, 0.001));  
  22.     disk->addDrawable(diskDrawable);  
  23.     g_Switch->addChild(disk);  
  24.   
  25.     //添加圆球  
  26.     osg::Geode *sphere = new osg::Geode;  
  27.     osg::ShapeDrawable *sphereDrawable = new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(0,0,0), 1.3));  
  28.     sphere->addDrawable(sphereDrawable);  
  29.     g_Switch->addChild(sphere);  
  30.   
  31.     //添加圆锥  
  32.     osg::Geode *cone = new osg::Geode;  
  33.     osg::ShapeDrawable *coneDrawable = new osg::ShapeDrawable(new osg::Cone(osg::Vec3(0,0,0), 0.5, 2));  
  34.     cone->addDrawable(coneDrawable);  
  35.     g_Switch->addChild(cone);  
  36.   
  37.     g_Switch->setSingleChildOn(0);  
  38. //  
使用setSingleChildOn来让其中一个显示,我们让立方体先显示,所以用的是它的索引值0

在键盘交互处理中同样调用这个函数来切换:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Space)  
  2. {  
  3.     static int index = 0;  
  4.     g_Switch->setSingleChildOn(++index % 5);  
  5. }  

其余部分和第七课代码是一样的,编译运行程序:

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

[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. #include <osg/Texture2D>  
  14.   
  15. #include <osgGA/GUIEventAdapter>  
  16.   
  17. #include <osg/Light>  
  18. #include <osg/LightModel>  
  19. #include <osg/LightSource>  
  20.   
  21. #include <osg/ShapeDrawable>  
  22. #include <osg/Switch>  
  23.   
  24.   
  25. //  
  26. //开关节点  
  27. osg::Switch     *g_Switch;  
  28.   
  29. //  
  30. //FindFirstNamedNodeVisitor用来遍历寻找与指定名称相同的节点  
  31.   
  32. class FindFirstNamedNodeVisitor : public osg::NodeVisitor  
  33. {  
  34. public:  
  35.     FindFirstNamedNodeVisitor(const std::string& name):  
  36.       osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),  
  37.           _name(name), _foundNode(NULL) {}  
  38.   
  39.       virtual void apply(osg::Node& node)  
  40.       {  
  41.           if (node.getName()==_name)  
  42.           {  
  43.               _foundNode = &node;  
  44.               return;  
  45.           }  
  46.           traverse(node);  
  47.       }  
  48.   
  49.       std::string _name;  
  50.       osg::Node *_foundNode;  
  51. };  
  52.   
  53. //  
  54. //RotateCallback  
  55.   
  56. class RotateCallback : public osg::NodeCallback  
  57. {  
  58.   
  59. public:  
  60.     RotateCallback(osg::Vec3d rotateAxis, double rotateSpeed) :   
  61.       osg::NodeCallback(),  
  62.           _rotateAxis(rotateAxis),   
  63.           _rotateSpeed(rotateSpeed),  
  64.           _rotateAngle(0.0)  
  65.       {  
  66.           //Nop  
  67.       }  
  68.   
  69.       void setRotateSpeed(double speed)  
  70.       {  
  71.           _rotateSpeed = speed;  
  72.       }  
  73.   
  74.       double getRotateSpeed() const  
  75.       {  
  76.           return _rotateSpeed;  
  77.       }  
  78.   
  79.       virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)  
  80.       {  
  81.           osg::MatrixTransform *currentMT = dynamic_cast<osg::MatrixTransform*>(node);  
  82.           if (currentMT)  
  83.           {  
  84.               //获取当前的平移位置  
  85.               osg::Vec3d currentTranslate = currentMT->getMatrix().getTrans();  
  86.               osg::Matrix newMatrix = osg::Matrix::rotate(_rotateAngle, _rotateAxis) * osg::Matrix::translate(currentTranslate);  
  87.               currentMT->setMatrix(newMatrix);  
  88.               _rotateAngle += _rotateSpeed;  
  89.           }  
  90.   
  91.           traverse(node, nv);  
  92.       }  
  93.   
  94.   
  95. private:  
  96.     osg::Vec3d _rotateAxis;         //旋转轴  
  97.     double        _rotateSpeed;     //旋转速度  
  98.     double        _rotateAngle;     //当前旋转的角度  
  99. };  
  100.   
  101.   
  102.   
  103.   
  104. //  
  105.   
  106. class ManipulatorSceneHandler : public osgGA::GUIEventHandler  
  107. {  
  108. public:  
  109.     ManipulatorSceneHandler()  
  110.     {  
  111.     }  
  112.   
  113.     virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)  
  114.     {  
  115.         osgViewer::Viewer *viewer = dynamic_cast<osgViewer::Viewer*>(&aa);  
  116.         if (!viewer)  
  117.             return false;  
  118.         if (!viewer->getSceneData())  
  119.             return false;  
  120.         if (ea.getHandled())   
  121.             return false;  
  122.   
  123.         osg::Group *root = viewer->getSceneData()->asGroup();  
  124.   
  125.         switch(ea.getEventType())  
  126.         {  
  127.         case(osgGA::GUIEventAdapter::KEYDOWN):  
  128.             {  
  129.                 if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Left)  
  130.                 {  
  131.                     FindFirstNamedNodeVisitor fnv("yRotMT");  
  132.                     root->accept(fnv);  
  133.   
  134.                     osg::Node *mtNode = fnv._foundNode;  
  135.                     osg::MatrixTransform *yRotMT = dynamic_cast<osg::MatrixTransform*>(mtNode);  
  136.                     if (!yRotMT)  
  137.                         return false;  
  138.   
  139.                     RotateCallback *rotCallback = dynamic_cast<RotateCallback*>(yRotMT->getUpdateCallback());  
  140.   
  141.                     if (!rotCallback)  
  142.                         return false;  
  143.   
  144.                     double speed = rotCallback->getRotateSpeed();  
  145.                     speed += 0.02;  
  146.                     rotCallback->setRotateSpeed(speed);  
  147.   
  148.                 }  
  149.   
  150.                 if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Right)  
  151.                 {  
  152.                     FindFirstNamedNodeVisitor fnv("yRotMT");  
  153.                     root->accept(fnv);  
  154.   
  155.                     osg::Node *mtNode = fnv._foundNode;  
  156.                     osg::MatrixTransform *yRotMT = dynamic_cast<osg::MatrixTransform*>(mtNode);  
  157.                     if (!yRotMT)  
  158.                         return false;  
  159.   
  160.                     RotateCallback *rotCallback = dynamic_cast<RotateCallback*>(yRotMT->getUpdateCallback());  
  161.   
  162.                     if (!rotCallback)  
  163.                         return false;  
  164.   
  165.                     double speed = rotCallback->getRotateSpeed();  
  166.                     speed -= 0.02;  
  167.                     rotCallback->setRotateSpeed(speed);  
  168.                 }  
  169.   
  170.                 if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Up)  
  171.                 {  
  172.                     FindFirstNamedNodeVisitor fnv("xRotMT");  
  173.                     root->accept(fnv);  
  174.   
  175.                     osg::Node *mtNode = fnv._foundNode;  
  176.                     osg::MatrixTransform *xRotMT = dynamic_cast<osg::MatrixTransform*>(mtNode);  
  177.                     if (!xRotMT)  
  178.                         return false;  
  179.   
  180.                     RotateCallback *rotCallback = dynamic_cast<RotateCallback*>(xRotMT->getUpdateCallback());  
  181.   
  182.                     if (!rotCallback)  
  183.                         return false;  
  184.   
  185.                     double speed = rotCallback->getRotateSpeed();  
  186.                     speed += 0.02;  
  187.                     rotCallback->setRotateSpeed(speed);  
  188.                 }  
  189.   
  190.                 if (ea.getKey()== osgGA::GUIEventAdapter::KEY_Down)  
  191.                 {  
  192.                     FindFirstNamedNodeVisitor fnv("xRotMT");  
  193.                     root->accept(fnv);  
  194.   
  195.                     osg::Node *mtNode = fnv._foundNode;  
  196.                     osg::MatrixTransform *xRotMT = dynamic_cast<osg::MatrixTransform*>(mtNode);  
  197.                     if (!xRotMT)  
  198.                         return false;  
  199.   
  200.                     RotateCallback *rotCallback = dynamic_cast<RotateCallback*>(xRotMT->getUpdateCallback());  
  201.   
  202.                     if (!rotCallback)  
  203.                         return false;  
  204.   
  205.                     double speed = rotCallback->getRotateSpeed();  
  206.                     speed -= 0.02;  
  207.                     rotCallback->setRotateSpeed(speed);  
  208.                 }  
  209.   
  210.                 if (ea.getKey()== osgGA::GUIEventAdapter::KEY_Page_Up)  
  211.                 {     
  212.                     FindFirstNamedNodeVisitor fnv("zoomMT");  
  213.                     root->accept(fnv);  
  214.   
  215.                     osg::Node *mtNode = fnv._foundNode;  
  216.                     osg::MatrixTransform *zoomMT = dynamic_cast<osg::MatrixTransform*>(mtNode);  
  217.                     if (!zoomMT)  
  218.                         return false;  
  219.   
  220.                     osg::Vec3 trans = zoomMT->getMatrix().getTrans();  
  221.                     trans.set(trans.x(), trans.y(), trans.z() + 0.2);  
  222.                     zoomMT->setMatrix(osg::Matrix::translate(trans));  
  223.                 }  
  224.   
  225.                 if (ea.getKey()== osgGA::GUIEventAdapter::KEY_Page_Down)  
  226.                 {  
  227.                     FindFirstNamedNodeVisitor fnv("zoomMT");  
  228.                     root->accept(fnv);  
  229.   
  230.                     osg::Node *mtNode = fnv._foundNode;  
  231.                     osg::MatrixTransform *zoomMT = dynamic_cast<osg::MatrixTransform*>(mtNode);  
  232.                     if (!zoomMT)  
  233.                         return false;  
  234.   
  235.                     osg::Vec3 trans = zoomMT->getMatrix().getTrans();  
  236.                     trans.set(trans.x(), trans.y(), trans.z() - 0.2);  
  237.                     zoomMT->setMatrix(osg::Matrix::translate(trans));  
  238.                 }  
  239.   
  240.                 if (ea.getKey()== osgGA::GUIEventAdapter::KEY_L)  
  241.                 {  
  242.                     static int i = 0;  
  243.                     if (i % 2 == 0) {  
  244.                         root->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);  
  245.                     } else {  
  246.                         root->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::ON);  
  247.                     }  
  248.                     ++i;  
  249.                 }  
  250.   
  251.                 if (ea.getKey()== osgGA::GUIEventAdapter::KEY_F)  
  252.                 {  
  253.                     FindFirstNamedNodeVisitor fnv("quadGeode");  
  254.                     root->accept(fnv);  
  255.   
  256.                     osg::Node *mtNode = fnv._foundNode;  
  257.                     osg::Geode *quadGeode = dynamic_cast<osg::Geode*>(mtNode);  
  258.                     if (!quadGeode)  
  259.                         return false;  
  260.   
  261.                     osg::Texture2D *texture2D = dynamic_cast<osg::Texture2D*>(quadGeode->getOrCreateStateSet()->getTextureAttribute(0, osg::StateAttribute::TEXTURE));  
  262.   
  263.                     static int i = 0;  
  264.                     if (i % 3 == 0) {  
  265.                         texture2D->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);  
  266.                         texture2D->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);  
  267.                     } else if (i % 3 == 1) {  
  268.                         texture2D->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);  
  269.                         texture2D->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR_MIPMAP_NEAREST);  
  270.                     } else {  
  271.                         texture2D->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST);  
  272.                         texture2D->setFilter(osg::Texture::MAG_FILTER, osg::Texture::NEAREST);  
  273.                     }  
  274.                     ++i;  
  275.                 }  
  276.                   
  277.                 if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Space)  
  278.                 {  
  279.                     static int index = 0;  
  280.                     g_Switch->setSingleChildOn(++index % 5);  
  281.                 }  
  282.   
  283.             }  
  284.         defaultbreak;  
  285.         }  
  286.         return false;  
  287.     }  
  288. };  
  289.   
  290. //  
  291.   
  292. class ViewerWidget : public QWidget, public osgViewer::Viewer  
  293. {  
  294. public:  
  295.     ViewerWidget(osg::Node *scene = NULL)  
  296.     {  
  297.         QWidget* renderWidget = getRenderWidget( createGraphicsWindow(0,0,100,100), scene);  
  298.   
  299.         QVBoxLayout* layout = new QVBoxLayout;  
  300.         layout->addWidget(renderWidget);  
  301.         layout->setContentsMargins(0, 0, 0, 1);  
  302.         setLayout( layout );  
  303.   
  304.         connect( &_timer, SIGNAL(timeout()), this, SLOT(update()) );  
  305.         _timer.start( 10 );  
  306.     }  
  307.   
  308.     QWidget* getRenderWidget( osgQt::GraphicsWindowQt* gw, osg::Node* scene )  
  309.     {  
  310.         osg::Camera* camera = this->getCamera();  
  311.         camera->setGraphicsContext( gw );  
  312.   
  313.         const osg::GraphicsContext::Traits* traits = gw->getTraits();  
  314.   
  315.         camera->setClearColor( osg::Vec4(0.0, 0.0, 0.0, 1.0) );  
  316.         camera->setViewport( new osg::Viewport(0, 0, traits->width, traits->height) );  
  317.         camera->setProjectionMatrixAsPerspective(45.0f, static_cast<double>(traits->width)/static_cast<double>(traits->height), 0.1f, 100.0f );  
  318.         camera->setViewMatrixAsLookAt(osg::Vec3d(0, 0, 1), osg::Vec3d(0, 0, 0), osg::Vec3d(0, 1, 0));  
  319.   
  320.         osg::StateSet* globalStateset = camera->getStateSet();  
  321.         if (globalStateset)  
  322.         {  
  323.             osg::LightModel* lightModel = new osg::LightModel;  
  324.             lightModel->setAmbientIntensity(osg::Vec4(0,0,0,0));  
  325.             globalStateset->setAttributeAndModes(lightModel, osg::StateAttribute::ON);  
  326.         }  
  327.   
  328.         this->setSceneData( scene );  
  329.         this->addEventHandler(new ManipulatorSceneHandler());  
  330.   
  331.         return gw->getGLWidget();  
  332.     }  
  333.   
  334.     osgQt::GraphicsWindowQt* createGraphicsWindow( int x, int y, int w, int h, const std::string& name=""bool windowDecoration=false )  
  335.     {  
  336.         osg::DisplaySettings* ds = osg::DisplaySettings::instance().get();  
  337.         osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;  
  338.         traits->windowName = name;  
  339.         traits->windowDecoration = windowDecoration;  
  340.         traits->x = x;  
  341.         traits->y = y;  
  342.         traits->width = w;  
  343.         traits->height = h;  
  344.         traits->doubleBuffer = true;  
  345.         traits->alpha = ds->getMinimumNumAlphaBits();  
  346.         traits->stencil = ds->getMinimumNumStencilBits();  
  347.         traits->sampleBuffers = ds->getMultiSamples();  
  348.         traits->samples = ds->getNumMultiSamples();  
  349.   
  350.         return new osgQt::GraphicsWindowQt(traits.get());  
  351.     }  
  352.   
  353.     virtual void paintEvent( QPaintEvent* event )  
  354.     {   
  355.         frame();   
  356.     }  
  357.   
  358. protected:  
  359.   
  360.     QTimer _timer;  
  361. };  
  362.   
  363.   
  364.   
  365. osg::Node*  buildScene()  
  366. {  
  367.     osg::Group *root = new osg::Group;  
  368.   
  369.     osg::Light* light = new osg::Light();  
  370.     light->setLightNum(0);  
  371.     light->setAmbient(osg::Vec4(0.5f, 0.5f, 0.5f, 1.0f));  
  372.     light->setDiffuse(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f));  
  373.     light->setPosition(osg::Vec4(0.0f, 0.0f, 2.0f, 1.0f));  
  374.     osg::LightSource* lightsource = new osg::LightSource();  
  375.     lightsource->setLight (light);  
  376.     root->addChild (lightsource);   
  377.   
  378.     osg::MatrixTransform *quadMT = new osg::MatrixTransform;  
  379.     quadMT->setName("zoomMT");  
  380.     quadMT->setMatrix(osg::Matrix::translate(0.0, 0.0, -5.0));  
  381.   
  382.     osg::MatrixTransform *quadXRotMT = new osg::MatrixTransform;  
  383.     quadXRotMT->setName("xRotMT");  
  384.     RotateCallback *xRotCallback = new RotateCallback(osg::X_AXIS, 0.0);  
  385.     quadXRotMT->setUpdateCallback(xRotCallback);  
  386.   
  387.   
  388.     osg::MatrixTransform *quadYRotMT = new osg::MatrixTransform;  
  389.     quadYRotMT->setName("yRotMT");  
  390.     RotateCallback *yRotCallback = new RotateCallback(osg::Y_AXIS, 0.0);  
  391.     quadYRotMT->setUpdateCallback(yRotCallback);  
  392.   
  393. //  
  394.     //新增代码,使用开关节点管理  
  395.     g_Switch = new osg::Switch;  
  396.   
  397.     //添加立方体  
  398.     osg::Geode *box = new osg::Geode;  
  399.     osg::ShapeDrawable *boxDrawable = new osg::ShapeDrawable;  
  400.     osg::Box *boxShape = new osg::Box(osg::Vec3(0, 0,0), 2);  
  401.     boxDrawable->setShape(boxShape);  
  402.     box->addDrawable(boxDrawable);  
  403.     g_Switch->addChild(box);  
  404.   
  405.     //添加圆柱体  
  406.     osg::Geode *cylinder = new osg::Geode;  
  407.     osg::ShapeDrawable *cylinderDrawable = new osg::ShapeDrawable(new osg::Cylinder(osg::Vec3(0,0,0), 0.5, 2.0));  
  408.     cylinder->addDrawable(cylinderDrawable);  
  409.     g_Switch->addChild(cylinder);  
  410.   
  411.     //添加圆盘  
  412.     osg::Geode *disk = new osg::Geode;  
  413.     osg::ShapeDrawable *diskDrawable = new osg::ShapeDrawable(new osg::Cylinder(osg::Vec3(0,0,0), 0.5, 0.001));  
  414.     disk->addDrawable(diskDrawable);  
  415.     g_Switch->addChild(disk);  
  416.   
  417.     //添加圆球  
  418.     osg::Geode *sphere = new osg::Geode;  
  419.     osg::ShapeDrawable *sphereDrawable = new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(0,0,0), 1.3));  
  420.     sphere->addDrawable(sphereDrawable);  
  421.     g_Switch->addChild(sphere);  
  422.   
  423.     //添加圆锥  
  424.     osg::Geode *cone = new osg::Geode;  
  425.     osg::ShapeDrawable *coneDrawable = new osg::ShapeDrawable(new osg::Cone(osg::Vec3(0,0,0), 0.5, 2));  
  426.     cone->addDrawable(coneDrawable);  
  427.     g_Switch->addChild(cone);  
  428.   
  429.     g_Switch->setSingleChildOn(0);  
  430. //  
  431.   
  432.     osg::Image *textureImage = osgDB::readImageFile("Data/Wall.bmp");  
  433.     osg::Texture2D *texture2D = new osg::Texture2D;  
  434.     texture2D->setImage(textureImage);  
  435.     texture2D->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST);  
  436.     texture2D->setFilter(osg::Texture::MAG_FILTER, osg::Texture::NEAREST);  
  437.     g_Switch->getOrCreateStateSet()->setTextureAttributeAndModes(0, texture2D);  
  438.   
  439.     quadYRotMT->addChild(g_Switch);  
  440.     quadXRotMT->addChild(quadYRotMT);  
  441.     quadMT->addChild(quadXRotMT);  
  442.   
  443.     root->addChild(quadMT);  
  444.   
  445.     return root;  
  446. }  
  447.   
  448.   
  449. int main( int argc, char** argv )  
  450. {  
  451.     QApplication app(argc, argv);  
  452.     ViewerWidget* viewWidget = new ViewerWidget(buildScene());  
  453.     viewWidget->setGeometry( 100, 100, 640, 480 );  
  454.     viewWidget->show();  
  455.     return app.exec();  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值