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

  • 简介

NeHe教程在这节课向我们介绍了如何从一个2D的灰度图创建地形。这节课的内容比较简单,只是从一个2D灰度图中读取灰度数据,然后将灰度数据转换成高度数据,最后将这些数据显示出来就可以了。

  • 实现

首先读取raw格式的图片,将里面的灰度值转换成Y值:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. void LoadRawFile(LPSTR strName, int nSize, BYTE *pHeightMap) //读取灰度图  
  2. {  
  3.     FILE *pFile = NULL;  
  4.     pFile = fopen( strName, "rb" );  
  5.     if ( pFile == NULL )      
  6.     {  
  7.         return;  
  8.     }  
  9.     fread( pHeightMap, 1, nSize, pFile );  
  10.     int result = ferror( pFile );  
  11.     fclose(pFile);  
  12. }  
[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. int Height(BYTE *pHeightMap, int X, int Y)              // This Returns The Height From A Height Map Index  
  2. {  
  3.     int x = X % MAP_SIZE;                               // Error Check Our x Value  
  4.     int y = Y % MAP_SIZE;                               // Error Check Our y Value  
  5.   
  6.     if(!pHeightMap) return 0;                           // Make Sure Our Data Is Valid  
  7.   
  8.     return pHeightMap[x + (y * MAP_SIZE)];              // Index Into Our Height Array And Return The Height  
  9. }  
读取完成之后,创建整个网格:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. osg::Geode* RenderHeightMap(BYTE pHeightMap[])  

最后在与鼠标的交互中切换显示的模式:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. case(osgGA::GUIEventAdapter::PUSH):  
  2.     {  
  3.         if (ea.getButtonMask() == osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON)  
  4.         {  
  5.             if (!g_TerrainGeometry)  
  6.                 return false;  
  7.             osg::Vec3Array *vertexArray = dynamic_cast<osg::Vec3Array*>(g_TerrainGeometry->getVertexArray());  
  8.             if (!vertexArray)  
  9.                 return false;  
  10.               
  11.             static bool flag = true;  
  12.             if (flag){  
  13.                 g_TerrainGeometry->setPrimitiveSet(0, new osg::DrawArrays(osg::PrimitiveSet::LINES, 0, vertexArray->size()));  
  14.                 flag = !flag;  
  15.             } else {  
  16.                 g_TerrainGeometry->setPrimitiveSet(0, new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, vertexArray->size()));  
  17.                 flag = !flag;  
  18.             }  
  19.         }  
  20.     }  
将所有部分添加到场景,编译运行程序:


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

[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. #include <osg/MatrixTransform>  
  11.   
  12.   
  13. #define     MAP_SIZE      1024  
  14. #define     STEP_SIZE     16  
  15. #define     HEIGHT_RATIO  1.5f  
  16.   
  17. BYTE g_HeightMap[MAP_SIZE*MAP_SIZE];  
  18. float scaleValue = 0.15f;  
  19. osg::Geometry *g_TerrainGeometry = NULL;  
  20.   
  21.   
  22. void LoadRawFile(LPSTR strName, int nSize, BYTE *pHeightMap)  
  23. {  
  24.     FILE *pFile = NULL;  
  25.     pFile = fopen( strName, "rb" );  
  26.     if ( pFile == NULL )      
  27.     {  
  28.         return;  
  29.     }  
  30.     fread( pHeightMap, 1, nSize, pFile );  
  31.     int result = ferror( pFile );  
  32.     fclose(pFile);  
  33. }  
  34.   
  35.   
  36. int Height(BYTE *pHeightMap, int X, int Y)              // This Returns The Height From A Height Map Index  
  37. {  
  38.     int x = X % MAP_SIZE;                               // Error Check Our x Value  
  39.     int y = Y % MAP_SIZE;                               // Error Check Our y Value  
  40.   
  41.     if(!pHeightMap) return 0;                           // Make Sure Our Data Is Valid  
  42.   
  43.     return pHeightMap[x + (y * MAP_SIZE)];              // Index Into Our Height Array And Return The Height  
  44. }  
  45.   
  46.   
  47. osg::Vec3 SetVertexColor(BYTE *pHeightMap, int x, int y)   
  48. {  
  49.     float fColor = -0.15f + (Height(pHeightMap, x, y ) / 256.0f);  
  50.     return osg::Vec3(0, 0, fColor );  
  51. }  
  52.   
  53.   
  54. osg::Geode* RenderHeightMap(BYTE pHeightMap[])  
  55. {  
  56.     int X = 0, Y = 0;  
  57.     int x, y=0, z;    
  58.   
  59.     osg::Geode *terrainGeode = new osg::Geode;  
  60.     osg::Geometry *terrainGeomety = new osg::Geometry;  
  61.     osg::Vec3Array *vertexArray = new osg::Vec3Array;  
  62.     osg::Vec3Array *colorArray = new osg::Vec3Array;  
  63.   
  64.     for ( X = 0; X < (MAP_SIZE-STEP_SIZE); X += STEP_SIZE )  
  65.         for ( Y = 0; Y < (MAP_SIZE-STEP_SIZE); Y += STEP_SIZE )  
  66.         {  
  67.             //左下点坐标  
  68.             x = X;                            
  69.             y = Height(pHeightMap, X, Y );    
  70.             z = Y;                            
  71.             vertexArray->push_back(osg::Vec3(x, y, z));  
  72.       
  73.             osg::Vec3 colorLeftBottom = SetVertexColor(pHeightMap, x, z);  
  74.             colorArray->push_back(colorLeftBottom);  
  75.   
  76.             //左上点坐标  
  77.             x = X;                                        
  78.             y = Height(pHeightMap, X, Y + STEP_SIZE );    
  79.             z = Y + STEP_SIZE ;  
  80.             vertexArray->push_back(osg::Vec3(x, y, z));  
  81.   
  82.             osg::Vec3 colorLeftTop = SetVertexColor(pHeightMap, x, z);  
  83.             colorArray->push_back(colorLeftTop);  
  84.   
  85.             // 右上点坐标  
  86.             x = X + STEP_SIZE;   
  87.             y = Height(pHeightMap, X + STEP_SIZE, Y + STEP_SIZE );   
  88.             z = Y + STEP_SIZE ;  
  89.             vertexArray->push_back(osg::Vec3(x, y, z));  
  90.   
  91.             osg::Vec3 colorRightTop = SetVertexColor(pHeightMap, x, z);  
  92.             colorArray->push_back(colorRightTop);  
  93.   
  94.             // Get The (X, Y, Z) Value For The Bottom Right Vertex  
  95.             x = X + STEP_SIZE;   
  96.             y = Height(pHeightMap, X + STEP_SIZE, Y );   
  97.             z = Y;  
  98.             vertexArray->push_back(osg::Vec3(x, y, z));  
  99.   
  100.             osg::Vec3 colorRightBottom = SetVertexColor(pHeightMap, x, z);  
  101.             colorArray->push_back(colorRightBottom);  
  102.         }  
  103.   
  104.         terrainGeomety->setVertexArray(vertexArray);  
  105.         terrainGeomety->setColorArray(colorArray, osg::Array::BIND_PER_VERTEX);  
  106.         terrainGeomety->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, vertexArray->size()));  
  107.         terrainGeomety->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);  
  108.         g_TerrainGeometry = terrainGeomety;  
  109.   
  110.         terrainGeode->addDrawable(terrainGeomety);  
  111.         return terrainGeode;  
  112. }  
  113.   
  114.   
  115. //  
  116. class ManipulatorSceneHandler : public osgGA::GUIEventHandler  
  117. {  
  118. public:  
  119.     ManipulatorSceneHandler()  
  120.     {  
  121.     }  
  122.   
  123.     virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)  
  124.     {  
  125.         osgViewer::Viewer *viewer = dynamic_cast<osgViewer::Viewer*>(&aa);  
  126.         if (!viewer)  
  127.             return false;  
  128.         if (!viewer->getSceneData())  
  129.             return false;  
  130.         if (ea.getHandled())   
  131.             return false;  
  132.   
  133.         switch(ea.getEventType())  
  134.         {  
  135.         case(osgGA::GUIEventAdapter::PUSH):  
  136.             {  
  137.                 if (ea.getButtonMask() == osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON)  
  138.                 {  
  139.                     if (!g_TerrainGeometry)  
  140.                         return false;  
  141.                     osg::Vec3Array *vertexArray = dynamic_cast<osg::Vec3Array*>(g_TerrainGeometry->getVertexArray());  
  142.                     if (!vertexArray)  
  143.                         return false;  
  144.                       
  145.                     static bool flag = true;  
  146.                     if (flag){  
  147.                         g_TerrainGeometry->setPrimitiveSet(0, new osg::DrawArrays(osg::PrimitiveSet::LINES, 0, vertexArray->size()));  
  148.                         flag = !flag;  
  149.                     } else {  
  150.                         g_TerrainGeometry->setPrimitiveSet(0, new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, vertexArray->size()));  
  151.                         flag = !flag;  
  152.                     }  
  153.                 }  
  154.             }  
  155.         defaultbreak;  
  156.         }  
  157.         return false;  
  158.     }  
  159. };  
  160. //  
  161.   
  162.   
  163. //  
  164. /osgNeHe框架//  
  165. //  
  166.   
  167. class ViewerWidget : public QWidget, public osgViewer::Viewer  
  168. {  
  169. public:  
  170.     ViewerWidget(osg::Node *scene = NULL)  
  171.     {  
  172.         QWidget* renderWidget = getRenderWidget( createGraphicsWindow(0,0,100,100), scene);  
  173.   
  174.         QVBoxLayout* layout = new QVBoxLayout;  
  175.         layout->addWidget(renderWidget);  
  176.         layout->setContentsMargins(0, 0, 0, 1);  
  177.         setLayout( layout );  
  178.   
  179.         connect( &_timer, SIGNAL(timeout()), this, SLOT(update()) );  
  180.         _timer.start( 10 );  
  181.     }  
  182.   
  183.     QWidget* getRenderWidget( osgQt::GraphicsWindowQt* gw, osg::Node* scene )  
  184.     {  
  185.         osg::Camera* camera = this->getCamera();  
  186.         camera->setGraphicsContext( gw );  
  187.   
  188.         const osg::GraphicsContext::Traits* traits = gw->getTraits();  
  189.   
  190.         camera->setClearColor( osg::Vec4(0.0f, 0.0f, 0.0f, 0.5f) );  
  191.         camera->setViewport( new osg::Viewport(0, 0, traits->width, traits->height) );  
  192.         camera->setProjectionMatrixAsPerspective(45.0f, static_cast<double>(traits->width)/static_cast<double>(traits->height), 0.1f, 100.0f );  
  193.         camera->setViewMatrixAsLookAt(osg::Vec3d(212, 60, 194), osg::Vec3d(186, 55, 171), osg::Vec3d(0, 1, 0));  
  194.   
  195.         this->setSceneData( scene );  
  196.         this->addEventHandler(new ManipulatorSceneHandler);  
  197.         return gw->getGLWidget();  
  198.     }  
  199.   
  200.     osgQt::GraphicsWindowQt* createGraphicsWindow( int x, int y, int w, int h, const std::string& name=""bool windowDecoration=false )  
  201.     {  
  202.         osg::DisplaySettings* ds = osg::DisplaySettings::instance().get();  
  203.         osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;  
  204.         traits->windowName = name;  
  205.         traits->windowDecoration = windowDecoration;  
  206.         traits->x = x;  
  207.         traits->y = y;  
  208.         traits->width = w;  
  209.         traits->height = h;  
  210.         traits->doubleBuffer = true;  
  211.         traits->alpha = ds->getMinimumNumAlphaBits();  
  212.         traits->stencil = ds->getMinimumNumStencilBits();  
  213.         traits->sampleBuffers = ds->getMultiSamples();  
  214.         traits->samples = ds->getNumMultiSamples();  
  215.   
  216.         return new osgQt::GraphicsWindowQt(traits.get());  
  217.     }  
  218.   
  219.     virtual void paintEvent( QPaintEvent* event )  
  220.     {   
  221.         frame();   
  222.     }  
  223.   
  224. protected:  
  225.   
  226.     QTimer _timer;  
  227. };  
  228.   
  229.   
  230.   
  231. osg::Node*  buildScene()  
  232. {  
  233.     LoadRawFile("Data/Terrain.raw", MAP_SIZE * MAP_SIZE, g_HeightMap);  
  234.   
  235.     osg::Group *root = new osg::Group;  
  236.     osg::MatrixTransform *scaleMT = new osg::MatrixTransform;  
  237.     scaleMT->setMatrix(osg::Matrix::scale(scaleValue, scaleValue * HEIGHT_RATIO, scaleValue));  
  238.     scaleMT->addChild(RenderHeightMap(g_HeightMap));  
  239.     root->addChild(scaleMT);  
  240.   
  241.     return root;  
  242. }  
  243.   
  244.   
  245.   
  246. int main( int argc, char** argv )  
  247. {  
  248.     QApplication app(argc, argv);  
  249.     ViewerWidget* viewWidget = new ViewerWidget(buildScene());  
  250.     viewWidget->setGeometry( 100, 100, 640, 480 );  
  251.     viewWidget->show();  
  252.     return app.exec();  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值