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

来源:互联网 发布:js style.display 编辑:程序博客网 时间:2024/05/29 03:41
  • 简介

这节课NeHe课程主要向我们演示了怎么使用OpenGL中的VertexBufferObject,VBO的介绍可以参考另一篇文章VA VAO和VBO API备忘

在OSG中默认绘制Drawable的时候采用了显示列表的方式,另外也可以通过

virtual void setUseVertexBufferObjects (bool flag)来在VBO和显示列表之间进行切换。在我们之前的课程中,当需要修改Geometry中顶点位置和颜色等属性时(一般在OSG::Drawable::Update),都会使用这个函数切换几何体的绘制方式为VBO,从而实现修改其中的数据。

  • 实现

本课的实现过程十分简单,从灰度图中读取像素灰度值然后转换成顶点的高度:

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. int nPos = ( ( nX % image->s() )  + ( ( nY % image->t() ) * image->s() ) ) * 3;  
  2. float flR = (float) image->data()[ nPos ];  
  3. float flG = (float) image->data()[ nPos + 1 ];  
  4. float flB = (float) image->data()[ nPos + 2 ];  
  5. return ( 0.299f * flR + 0.587f * flG + 0.114f * flB );  

绘制整个地形:

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. osg::Geode*  loadHeightmap( char* szPath, float flHeightScale, float flResolution )  
  2. {  
  3.     FILE* fTest = fopen( szPath, "r" );  
  4.     if( !fTest )  
  5.         return false;  
  6.     fclose( fTest );  
  7.   
  8.     osg::Geode *geode = new osg::Geode;  
  9.     osg::Geometry *geometry = new osg::Geometry;  
  10.   
  11.     osg::Image *image = osgDB::readImageFile("Terrain.bmp");  
  12.     int nVertexCount = (int)(image->s() * image->t() * 6 / (flResolution * flResolution));  
  13.   
  14.     osg::Vec3Array *vertexArray = new osg::Vec3Array;  
  15.     osg::Vec2Array *textureArray = new osg::Vec2Array;  
  16.   
  17.     int nX, nZ, nTri, nIndex=0;  
  18.     float flX, flZ;  
  19.     for( nZ = 0; nZ < image->t(); nZ += (int) flResolution )  
  20.     {  
  21.         for( nX = 0; nX < image->s(); nX += (int) flResolution )  
  22.         {  
  23.             for( nTri = 0; nTri < 6; nTri++ )  
  24.             {  
  25.                 flX = (float) nX + ( ( nTri == 1 || nTri == 2 || nTri == 5 ) ? flResolution : 0.0f );  
  26.                 flZ = (float) nZ + ( ( nTri == 2 || nTri == 4 || nTri == 5 ) ? flResolution : 0.0f );  
  27.                 vertexArray->push_back(osg::Vec3(flX - ( image->s() / 2 ), ptHeight( (int) flX, (int) flZ, image ) *  flHeightScale, flZ - ( image->t() / 2 )));  
  28.                 textureArray->push_back(osg::Vec2(flX / image->s(), flZ / image->t()));  
  29.                 nIndex++;  
  30.             }  
  31.         }  
  32.     }  
  33.       
  34.     osg::Texture2D *texture2D = new osg::Texture2D;  
  35.     texture2D->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);  
  36.     texture2D->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);  
  37.     texture2D->setImage(image);  
  38.     geometry->setVertexArray(vertexArray);  
  39.     geometry->setTexCoordArray(0, textureArray);  
  40.     geometry->getOrCreateStateSet()->setTextureAttributeAndModes(0, texture2D);  
  41.     geometry->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);  
  42.     geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES, 0, vertexArray->size()));  
  43.     geometry->setUseVertexBufferObjects(true);  
  44.     geode->addDrawable(geometry);  
  45.   
  46.     return geode;  
  47. }  

编译运行程序:


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

[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/PolygonMode>  
  13.   
  14. #include <osg/Image>  
  15. #include <osg/Texture2D>  
  16.   
  17. #include <osg/AnimationPath>  
  18.   
  19.   
  20. #define MESH_RESOLUTION 4.0f  
  21. #define MESH_HEIGHTSCALE 1.0f  
  22.   
  23. //////////////////////////////////////////////////////////////////////////  
  24.   
  25. float ptHeight( int nX, int nY, osg::Image *image)  
  26. {  
  27.     int nPos = ( ( nX % image->s() )  + ( ( nY % image->t() ) * image->s() ) ) * 3;  
  28.     float flR = (float) image->data()[ nPos ];  
  29.     float flG = (float) image->data()[ nPos + 1 ];  
  30.     float flB = (float) image->data()[ nPos + 2 ];  
  31.     return ( 0.299f * flR + 0.587f * flG + 0.114f * flB );  
  32. }  
  33.   
  34.   
  35. osg::Geode*  loadHeightmap( char* szPath, float flHeightScale, float flResolution )  
  36. {  
  37.     FILE* fTest = fopen( szPath, "r" );  
  38.     if( !fTest )  
  39.         return false;  
  40.     fclose( fTest );  
  41.   
  42.     osg::Geode *geode = new osg::Geode;  
  43.     osg::Geometry *geometry = new osg::Geometry;  
  44.   
  45.     osg::Image *image = osgDB::readImageFile("Terrain.bmp");  
  46.     int nVertexCount = (int)(image->s() * image->t() * 6 / (flResolution * flResolution));  
  47.   
  48.     osg::Vec3Array *vertexArray = new osg::Vec3Array;  
  49.     osg::Vec2Array *textureArray = new osg::Vec2Array;  
  50.   
  51.     int nX, nZ, nTri, nIndex=0;  
  52.     float flX, flZ;  
  53.     for( nZ = 0; nZ < image->t(); nZ += (int) flResolution )  
  54.     {  
  55.         for( nX = 0; nX < image->s(); nX += (int) flResolution )  
  56.         {  
  57.             for( nTri = 0; nTri < 6; nTri++ )  
  58.             {  
  59.                 flX = (float) nX + ( ( nTri == 1 || nTri == 2 || nTri == 5 ) ? flResolution : 0.0f );  
  60.                 flZ = (float) nZ + ( ( nTri == 2 || nTri == 4 || nTri == 5 ) ? flResolution : 0.0f );  
  61.                 vertexArray->push_back(osg::Vec3(flX - ( image->s() / 2 ), ptHeight( (int) flX, (int) flZ, image ) *  flHeightScale, flZ - ( image->t() / 2 )));  
  62.                 textureArray->push_back(osg::Vec2(flX / image->s(), flZ / image->t()));  
  63.                 nIndex++;  
  64.             }  
  65.         }  
  66.     }  
  67.       
  68.     osg::Texture2D *texture2D = new osg::Texture2D;  
  69.     texture2D->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);  
  70.     texture2D->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);  
  71.     texture2D->setImage(image);  
  72.     geometry->setVertexArray(vertexArray);  
  73.     geometry->setTexCoordArray(0, textureArray);  
  74.     geometry->getOrCreateStateSet()->setTextureAttributeAndModes(0, texture2D);  
  75.     geometry->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);  
  76.     geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES, 0, vertexArray->size()));  
  77.     geometry->setUseVertexBufferObjects(true);  
  78.     geode->addDrawable(geometry);  
  79.   
  80.     return geode;  
  81. }  
  82.   
  83.   
  84.   
  85. class ViewerWidget : public QWidget, public osgViewer::Viewer  
  86. {  
  87. public:  
  88.     ViewerWidget(osg::Node *scene = NULL)  
  89.     {  
  90.         QWidget* renderWidget = getRenderWidget( createGraphicsWindow(0,0,640,480), scene);  
  91.   
  92.         QVBoxLayout* layout = new QVBoxLayout;  
  93.         layout->addWidget(renderWidget);  
  94.         layout->setContentsMargins(0, 0, 0, 1);  
  95.         setLayout( layout );  
  96.   
  97.         connect( &_timer, SIGNAL(timeout()), this, SLOT(update()) );  
  98.         _timer.start( 10 );  
  99.     }  
  100.   
  101.     QWidget* getRenderWidget( osgQt::GraphicsWindowQt* gw, osg::Node* scene )  
  102.     {  
  103.         osg::Camera* camera = this->getCamera();  
  104.         camera->setGraphicsContext( gw );  
  105.   
  106.         const osg::GraphicsContext::Traits* traits = gw->getTraits();  
  107.   
  108.         camera->setClearColor( osg::Vec4(0.0, 0.0, 0.0, 1.0) );  
  109.         camera->setViewport( new osg::Viewport(0, 0, traits->width, traits->height) );  
  110.         camera->setProjectionMatrixAsPerspective(45.0f, static_cast<double>(traits->width)/static_cast<double>(traits->height), 0.1f, 100.0f );          
  111.         camera->setViewMatrixAsLookAt(osg::Vec3d(0.0f, 0.0f, 1.0f), osg::Vec3d(0, 0, 0), osg::Vec3d(0, 1, 0));  
  112.   
  113.         this->setSceneData( scene );  
  114.   
  115.         return gw->getGLWidget();  
  116.     }  
  117.   
  118.     osgQt::GraphicsWindowQt* createGraphicsWindow( int x, int y, int w, int h, const std::string& name=""bool windowDecoration=false )  
  119.     {  
  120.         osg::DisplaySettings* ds = osg::DisplaySettings::instance().get();  
  121.         osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;  
  122.         traits->windowName = name;  
  123.         traits->windowDecoration = windowDecoration;  
  124.         traits->x = x;  
  125.         traits->y = y;  
  126.         traits->width = w;  
  127.         traits->height = h;  
  128.         traits->doubleBuffer = true;  
  129.         traits->alpha = ds->getMinimumNumAlphaBits();  
  130.         traits->stencil = ds->getMinimumNumStencilBits();  
  131.         traits->sampleBuffers = ds->getMultiSamples();  
  132.         traits->samples = ds->getNumMultiSamples();  
  133.   
  134.         return new osgQt::GraphicsWindowQt(traits.get());  
  135.     }  
  136.   
  137.     virtual void paintEvent( QPaintEvent* event )  
  138.     {   
  139.         frame();   
  140.     }  
  141.   
  142. protected:  
  143.   
  144.     QTimer _timer;  
  145. };  
  146.   
  147.   
  148.   
  149. osg::Node*  buildScene()  
  150. {  
  151.     osg::Group *root = new osg::Group;  
  152.   
  153.     osg::MatrixTransform *zoomMT = new osg::MatrixTransform;  
  154.     zoomMT->setMatrix(osg::Matrix::translate(0.0f, -220.0f, 0.0f));  
  155.   
  156.     osg::MatrixTransform *rotateSlightMT = new osg::MatrixTransform;  
  157.     rotateSlightMT->setMatrix(osg::Matrix::rotate(osg::DegreesToRadians(10.0), osg::X_AXIS));  
  158.   
  159.     osg::MatrixTransform *rotateYMT = new osg::MatrixTransform;  
  160.     rotateYMT->addUpdateCallback(new osg::AnimationPathCallback(osg::Vec3(), osg::Y_AXIS, 0.3));  
  161.   
  162.     root->addChild(zoomMT);  
  163.     zoomMT->addChild(rotateSlightMT);  
  164.     rotateSlightMT->addChild(rotateYMT);  
  165.     rotateYMT->addChild(loadHeightmap("terrain.bmp", MESH_HEIGHTSCALE, MESH_RESOLUTION));  
  166.   
  167.     return root;  
  168. }  
  169.   
  170.   
  171.   
  172. int main( int argc, char** argv )  
  173. {  
  174.     QApplication app(argc, argv);  
  175.     ViewerWidget* viewWidget = new ViewerWidget(buildScene());  
  176.     viewWidget->setGeometry( 100, 100, 640, 480 );  
  177.     viewWidget->show();  
  178.     return app.exec();  
  179. }  
0 0
原创粉丝点击