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

来源:互联网 发布:ubuntu terminal替换 编辑:程序博客网 时间:2024/06/06 12:30
  • 简介

NeHe教程在这节课向我们介绍了轨迹球技术。轨迹球技术可以让用户使用鼠标直接旋转物体,这是所有交互式3D软件必须提供的最基本的功能。在OSG中已经提供了功能强大的漫游器,包括TrackballManipulator、FirstPersonManipulator、DriveManipulator等等,具体实现的代码可以参看osgGA库中的源码部分。

  • 实现

首先创建场景中的两个几何体:

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. osg::Geode* createSphereGeode()  
  2. osg::Geode* createTorusGeode(float MinorRadius, float MajorRadius)  

将两者添加到场景根节点中

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. osg::MatrixTransform *torusMT = new osg::MatrixTransform;  
  2. torusMT->setMatrix(osg::Matrix::translate(-1.5, 0.0, -6.0));   
  3. torusMT->addChild(createTorusGeode(0.3,1.0));  
  4.   
  5. osg::MatrixTransform *sphereMT = new osg::MatrixTransform;  
  6. sphereMT->setMatrix(osg::Matrix::translate(1.5, 0.0, -6.0));  
  7. sphereMT->addChild(createSphereGeode());  
  8.   
  9. root->addChild(torusMT);  
  10. root->addChild(sphereMT);  

最后只需要添加一行代码,将漫游器添加到场景之中:

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. this->setCameraManipulator(new osgGA::TrackballManipulator);  

编译运行程序:


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

[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/ShapeDrawable>  
  13. #include <osgGA/TrackballManipulator>  
  14.   
  15.   
  16.   
  17.   
  18. osg::Geode* createSphereGeode()  
  19. {  
  20.     osg::Geode *sphereGeode = new osg::Geode;  
  21.   
  22.     osg::ShapeDrawable *shapeDrawable = new osg::ShapeDrawable;  
  23.     shapeDrawable->setShape(new osg::Sphere(osg::Vec3(), 1.3));  
  24.     shapeDrawable->setColor(osg::Vec4(1.0f,0.75f,0.75f, 1.0f));  
  25.     sphereGeode->addDrawable(shapeDrawable);  
  26.   
  27.     return sphereGeode;  
  28. }  
  29.   
  30.   
  31. osg::Geode* createTorusGeode(float MinorRadius, float MajorRadius)  
  32. {  
  33.     osg::Geode *geode = new osg::Geode;  
  34.     osg::Geometry *geometry = new osg::Geometry;  
  35.     osg::Vec3Array *vertexArray = new osg::Vec3Array;  
  36.     osg::Vec3Array *normalArray = new osg::Vec3Array;  
  37.     osg::Vec3Array *colorArray = new osg::Vec3Array;  
  38.   
  39.     colorArray->push_back(osg::Vec3(0.75f,0.75f,1.0f));  
  40.   
  41.     for (int i=0; i<20; i++ )                                        // Stacks  
  42.     {  
  43.         for (int j=-1; j<20; j++)                                    // Slices  
  44.         {  
  45.             float wrapFrac = (j%20)/(float)20;  
  46.             float phi = 2* osg::PI*wrapFrac;  
  47.             float sinphi = float(sin(phi));  
  48.             float cosphi = float(cos(phi));  
  49.   
  50.             float r = MajorRadius + MinorRadius*cosphi;  
  51.   
  52.             normalArray->push_back(osg::Vec3(float(sin(2* osg::PI*(i%20+wrapFrac)/(float)20))*cosphi, sinphi, float(cos(2* osg::PI*(i%20+wrapFrac)/(float)20))*cosphi));  
  53.             vertexArray->push_back(osg::Vec3(float(sin(2* osg::PI*(i%20+wrapFrac)/(float)20))*r,MinorRadius*sinphi,float(cos(2* osg::PI*(i%20+wrapFrac)/(float)20))*r));  
  54.             normalArray->push_back(osg::Vec3(float(sin(2* osg::PI*(i+1%20+wrapFrac)/(float)20))*cosphi, sinphi, float(cos(2* osg::PI*(i+1%20+wrapFrac)/(float)20))*cosphi));  
  55.             vertexArray->push_back(osg::Vec3(float(sin(2* osg::PI*(i+1%20+wrapFrac)/(float)20))*r,MinorRadius*sinphi,float(cos(2* osg::PI*(i+1%20+wrapFrac)/(float)20))*r));  
  56.         }  
  57.     }  
  58.   
  59.     geometry->setVertexArray(vertexArray);  
  60.     geometry->setNormalArray(normalArray, osg::Array::BIND_PER_VERTEX);  
  61.     geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLE_STRIP, 0, vertexArray->size()));  
  62.     geode->addDrawable(geometry);  
  63.   
  64.     return geode;  
  65. }  
  66.   
  67.   
  68.   
  69. class ViewerWidget : public QWidget, public osgViewer::Viewer  
  70. {  
  71. public:  
  72.     ViewerWidget(osg::Node *scene = NULL)  
  73.     {  
  74.         QWidget* renderWidget = getRenderWidget( createGraphicsWindow(0,0,100,100), scene);  
  75.   
  76.         QVBoxLayout* layout = new QVBoxLayout;  
  77.         layout->addWidget(renderWidget);  
  78.         layout->setContentsMargins(0, 0, 0, 1);  
  79.         setLayout( layout );  
  80.   
  81.         connect( &_timer, SIGNAL(timeout()), this, SLOT(update()) );  
  82.         _timer.start( 10 );  
  83.     }  
  84.   
  85.     QWidget* getRenderWidget( osgQt::GraphicsWindowQt* gw, osg::Node* scene )  
  86.     {  
  87.         osg::Camera* camera = this->getCamera();  
  88.         camera->setGraphicsContext( gw );  
  89.   
  90.         const osg::GraphicsContext::Traits* traits = gw->getTraits();  
  91.   
  92.         camera->setClearColor( osg::Vec4(0.0, 0.0, 0.0, 1.0) );  
  93.         camera->setViewport( new osg::Viewport(0, 0, traits->width, traits->height) );  
  94.         camera->setProjectionMatrixAsPerspective(45.0f, static_cast<double>(traits->width)/static_cast<double>(traits->height), 0.1f, 100.0f );  
  95.         camera->setViewMatrixAsLookAt(osg::Vec3d(0, 0, 1), osg::Vec3d(0, 0, 0), osg::Vec3d(0, 1, 0));  
  96.   
  97.         this->setSceneData( scene );  
  98.   
  99.         //添加轨迹球  
  100.         this->setCameraManipulator(new osgGA::TrackballManipulator);  
  101.   
  102.         return gw->getGLWidget();  
  103.     }  
  104.   
  105.     osgQt::GraphicsWindowQt* createGraphicsWindow( int x, int y, int w, int h, const std::string& name=""bool windowDecoration=false )  
  106.     {  
  107.         osg::DisplaySettings* ds = osg::DisplaySettings::instance().get();  
  108.         osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;  
  109.         traits->windowName = name;  
  110.         traits->windowDecoration = windowDecoration;  
  111.         traits->x = x;  
  112.         traits->y = y;  
  113.         traits->width = w;  
  114.         traits->height = h;  
  115.         traits->doubleBuffer = true;  
  116.         traits->alpha = ds->getMinimumNumAlphaBits();  
  117.         traits->stencil = ds->getMinimumNumStencilBits();  
  118.         traits->sampleBuffers = ds->getMultiSamples();  
  119.         traits->samples = ds->getNumMultiSamples();  
  120.   
  121.         return new osgQt::GraphicsWindowQt(traits.get());  
  122.     }  
  123.   
  124.     virtual void paintEvent( QPaintEvent* event )  
  125.     {   
  126.         frame();   
  127.     }  
  128.   
  129. protected:  
  130.   
  131.     QTimer _timer;  
  132. };  
  133.   
  134.   
  135.   
  136. osg::Node*  buildScene()  
  137. {  
  138.     osg::Group *root = new osg::Group;  
  139.   
  140.     osg::MatrixTransform *torusMT = new osg::MatrixTransform;  
  141.     torusMT->setMatrix(osg::Matrix::translate(-1.5, 0.0, -6.0));   
  142.     torusMT->addChild(createTorusGeode(0.3,1.0));  
  143.   
  144.     osg::MatrixTransform *sphereMT = new osg::MatrixTransform;  
  145.     sphereMT->setMatrix(osg::Matrix::translate(1.5, 0.0, -6.0));  
  146.     sphereMT->addChild(createSphereGeode());  
  147.   
  148.     root->addChild(torusMT);  
  149.     root->addChild(sphereMT);  
  150.   
  151.     return root;  
  152. }  
  153.   
  154.   
  155. int main( int argc, char** argv )  
  156. {  
  157.     QApplication app(argc, argv);  
  158.     ViewerWidget* viewWidget = new ViewerWidget(buildScene());  
  159.     viewWidget->setGeometry( 100, 100, 640, 480 );  
  160.     viewWidget->show();  
  161.     return app.exec();  
  162. }  
0 0
原创粉丝点击