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

  • 简介

这节课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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
编译运行 OpenSceneGraph-OpenSceneGraph-3.6.4 需要按照以下步骤进行操作: 1. 首先,确保你的计算机上已经安装了 CMake,C++ 编译器和 OpenGL 兼容的图形驱动程序。这些是编译和运行 OpenSceneGraph 所必需的工具和库。 2. 下载 OpenSceneGraph-OpenSceneGraph-3.6.4 的源代码,可以在官方网站或开源项目托管网站上找到。确保下载的版本正确,避免出错。 3. 解压源代码文件并进入解压后的目录。 4. 创建一个用于构建的构建目录,并进入该目录。例如:mkdir build && cd build。 5. 运行 CMake 命令来生成构建系统所需的文件和配置。命令可能类似于:cmake path/to/OpenSceneGraph-OpenSceneGraph-3.6.4。你可以使用其他参数和选项来自定义构建过程。 6. 确保 CMake 执行成功并生成了构建系统所需的文件。 7. 使用你的 C++ 编译器来构建 OpenSceneGraph。可以使用 make 命令,或者其他编译工具,根据你的操作系统和编译环境来选择。例如:make。 8. 等待编译完成,这可能需要一段时间,具体取决于你的计算机性能。 9. 构建完成后,检查是否有错误或警告信息。如果有,需要解决它们,并重新运行编译步骤。 10. 运行编译好的 OpenSceneGraph 可执行文件,这将启动 OpenSceneGraph 程序并运行示例或其他自定义的应用程序。 总之,编译和运行 OpenSceneGraph-OpenSceneGraph-3.6.4 需要先安装必需的工具和库,然后使用 CMake 生成构建系统所需的文件,再使用 C++ 编译器进行编译,最后运行生成的可执行文件。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值