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

  • 简介

本文实现从外部文件中加载场景,并进行简单的场景漫游操作。

一般来说,场景都是通过外部建模工具生成的,然后再通过osg进行读取加载,一方面直接通过顶点生成场景对程序员来说十分困难,另一方面通过外部建模的方式加载场景使得程序变得十分灵活。像我们玩的CS游戏就是通过加载一些地图文件实现在不同的场景之中战斗。

  • 实现

在NeHe教程中实现的过程介绍的非常清楚,不熟悉的读者可以参考NeHe教程第十课。在这里我们同样使用NeHe中读取文件的方式以及行进的方式,代码如下

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. typedef struct tagVERTEX  
  2. {  
  3.     float x,y,z;  
  4.     float u,v;  
  5. }VERTEX;  
  6.   
  7. typedef struct tagTRIANGLE  
  8. {  
  9.     VERTEX  vertex[3];  
  10. }TRIANGLE;  
  11.   
  12. typedef struct tagSECTOR  
  13. {  
  14.     int iNumTriangle;  
  15.     TRIANGLE *pTriangle;  
  16. }SECTOR;  
  17. SECTOR  Sector;  
  18.   
  19. void readstr(FILE *f,char *string)  
  20. {  
  21.     do  
  22.     {  
  23.         fgets(string, 255, f);  
  24.     } while ((string[0] == '/') || (string[0] == '\n'));  
  25. }  
  26.   
  27. void SetupWorld()  
  28. {  
  29.     float x, y, z, u, v;  
  30.     int numtriangles;  
  31.     FILE *filein;  
  32.     char oneline[255];  
  33.     filein = fopen("Data/world.txt""rt");             // File To Load World Data From  
  34.   
  35.     readstr(filein,oneline);  
  36.     sscanf(oneline, "NUMPOLLIES %d\n", &numtriangles);  
  37.   
  38.     Sector.iNumTriangle = numtriangles;  
  39.     Sector.pTriangle = new TRIANGLE[numtriangles];  
  40.     for(int i = 0; i < numtriangles; i++)  
  41.     {  
  42.         for(int j = 0; j < 3; j++)  
  43.         {  
  44.             readstr(filein,oneline);  
  45.             sscanf(oneline, "%f %f %f %f %f", &x, &y, &z, &u, &v);  
  46.             Sector.pTriangle[i].vertex[j].x = x;  
  47.             Sector.pTriangle[i].vertex[j].y = y;  
  48.             Sector.pTriangle[i].vertex[j].z = z;  
  49.             Sector.pTriangle[i].vertex[j].u = u;  
  50.             Sector.pTriangle[i].vertex[j].v = v;  
  51.         }  
  52.     }  
  53.     fclose(filein);  
  54. }  

读取文件的方式有很多种,(在我们的Qt框架中可以通过QFile和QTextStream等方式读取)为了节省时间此处借用了NeHe源码中的读取方式

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. const float piover180 = 0.0174532925f;  
  2. float heading;   
  3. float xpos;  
  4. float zpos;  
  5. GLfloat yrot;  
  6.   
  7. GLfloat walkbias = 0;  
  8. GLfloat walkbiasangle = 0;  
  9. GLfloat lookupdown = 0.0f;  
同样的定义了一些变量用来控制角色。之后为了实现在每一帧中修改角色的姿态,我们定义了三个UpdateCallback类用来响应向前行进、左右旋转(绕Y轴旋转)以及上下旋转
(绕X轴旋转)

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. class TransUpdateCallback : public osg::NodeCallback  
  2. {  
  3. public:  
  4.   
  5.     TransUpdateCallback()  
  6.     {  
  7.         GLfloat xtrans = -xpos;  
  8.         GLfloat ztrans = -zpos;  
  9.         GLfloat ytrans = -walkbias-0.25f;  
  10.         _trans = osg::Vec3d(xtrans, ytrans, ztrans);  
  11.     }  
  12.   
  13.     virtual void operator()(Node* node, NodeVisitor* nv)  
  14.     {  
  15.         if (dynamic_cast<osg::MatrixTransform*>(node))  
  16.         {  
  17.             osg::MatrixTransform *moveMT = dynamic_cast<osg::MatrixTransform*>(node);  
  18.             moveMT->setMatrix(osg::Matrix::translate(_trans));  
  19.         }  
  20.   
  21.         traverse(node, nv);  
  22.     }  
  23.   
  24.     void setTrans(osg::Vec3d trans)  
  25.     {  
  26.         _trans = trans;  
  27.     }  
  28.   
  29.     osg::Vec3d _trans;  
  30. };  

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. class RotateXUpdateCallback : public osg::NodeCallback  
  2. {  
  3.   
  4. public:  
  5.   
  6.     RotateXUpdateCallback()  
  7.     {  
  8.         _pitch = lookupdown;  
  9.     }  
  10.   
  11.     virtual void operator()(Node* node, NodeVisitor* nv)  
  12.     {  
  13.         if (dynamic_cast<osg::MatrixTransform*>(node))  
  14.         {  
  15.             osg::MatrixTransform *rotateX = dynamic_cast<osg::MatrixTransform*>(node);  
  16.             rotateX->setMatrix(osg::Matrix::rotate(_pitch, osg::X_AXIS));  
  17.         }  
  18.   
  19.         traverse(node, nv);  
  20.     }  
  21.   
  22.     void setPitch(double pitch)  
  23.     {  
  24.         _pitch = pitch;  
  25.     }  
  26.   
  27.     double _pitch;  
  28. };  
  29.   
  30.   
  31. class RotateYUpdateCallback : public osg::NodeCallback  
  32. {  
  33.   
  34. public:  
  35.   
  36.     RotateYUpdateCallback()  
  37.     {  
  38.         _heading = osg::DegreesToRadians(360.0f) - yrot;  
  39.     }  
  40.   
  41.     virtual void operator()(Node* node, NodeVisitor* nv)  
  42.     {  
  43.         if (dynamic_cast<osg::MatrixTransform*>(node))  
  44.         {  
  45.             osg::MatrixTransform *rotateY = dynamic_cast<osg::MatrixTransform*>(node);  
  46.             rotateY->setMatrix(osg::Matrix::rotate(_heading, osg::Y_AXIS));  
  47.         }  
  48.   
  49.         traverse(node, nv);  
  50.     }  
  51.   
  52.     void setHeading(double heading)  
  53.     {  
  54.         _heading = heading;  
  55.     }  
  56.   
  57.     double _heading;  
  58. };  
接着定义了三个全局的变量,用来记录场景中角色的姿态,在键盘的响应中修改它们实现角色的正确移动和旋转

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. TransUpdateCallback *g_moveMTCB;  
  2. RotateXUpdateCallback *g_xRotMTCB;  
  3. RotateYUpdateCallback *g_yRotMTCB;  
接下来构建我们的场景

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. osg::Group *root = new osg::Group;  
  2.   
  3. osg::Vec3Array *vertexArray = new osg::Vec3Array;  
  4. osg::Vec2Array *textureArray = new osg::Vec2Array;  
  5.   
  6. unsigned int num = Sector.iNumTriangle;  
  7.   
  8. for (unsigned i = 0; i < num; ++i)  
  9. {  
  10.     vertexArray->push_back(osg::Vec3(Sector.pTriangle[i].vertex[0].x, Sector.pTriangle[i].vertex[0].y, Sector.pTriangle[i].vertex[0].z));  
  11.     vertexArray->push_back(osg::Vec3(Sector.pTriangle[i].vertex[1].x, Sector.pTriangle[i].vertex[1].y, Sector.pTriangle[i].vertex[1].z));  
  12.     vertexArray->push_back(osg::Vec3(Sector.pTriangle[i].vertex[2].x, Sector.pTriangle[i].vertex[2].y, Sector.pTriangle[i].vertex[2].z));  
  13.   
  14.     textureArray->push_back(osg::Vec2(Sector.pTriangle[i].vertex[0].u, Sector.pTriangle[i].vertex[0].v));  
  15.     textureArray->push_back(osg::Vec2(Sector.pTriangle[i].vertex[1].u, Sector.pTriangle[i].vertex[1].v));  
  16.     textureArray->push_back(osg::Vec2(Sector.pTriangle[i].vertex[2].u, Sector.pTriangle[i].vertex[2].v));  
  17. }  
  18.   
  19. osg::MatrixTransform *moveMT = new osg::MatrixTransform;  
  20. TransUpdateCallback *tucb = new TransUpdateCallback;  
  21. moveMT->setUpdateCallback(tucb);  
  22. g_moveMTCB = tucb;  
  23.   
  24. osg::MatrixTransform *headingMT = new osg::MatrixTransform;  
  25. RotateYUpdateCallback *ryuc = new RotateYUpdateCallback;  
  26. headingMT->setUpdateCallback(ryuc);  
  27. g_yRotMTCB = ryuc;  
  28.   
  29. osg::MatrixTransform *pitchMT = new osg::MatrixTransform;  
  30. RotateXUpdateCallback *rxuc = new RotateXUpdateCallback;  
  31. pitchMT->setUpdateCallback(rxuc);  
  32. g_xRotMTCB = rxuc;  
  33.   
  34. headingMT->addChild(pitchMT);  
  35. pitchMT->addChild(moveMT);  
  36.   
  37. osg::Geometry *triangleGeometry = new osg::Geometry;  
  38. triangleGeometry->setVertexArray(vertexArray);  
  39.   
  40. triangleGeometry->setTexCoordArray(0, textureArray);  
  41. triangleGeometry->getOrCreateStateSet()->setTextureAttributeAndModes(0, createTexture(0));  
  42.   
  43. triangleGeometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES, 0, 108));  
  44. osg::Geode *triangleGeode = new osg::Geode;  
  45. triangleGeometry->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);  
  46. triangleGeode->addDrawable(triangleGeometry);  
  47. moveMT->addChild(triangleGeode);  
  48. root->addChild(headingMT);  
构建场景中我们将Callback记录在全局变量中,在EventHandler中修改它们

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. switch(ea.getEventType())  
  2. {  
  3. case(osgGA::GUIEventAdapter::KEYDOWN):  
  4.     {  
  5.         if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Up)  
  6.         {  
  7.             xpos -= (float)sin(heading*piover180) * 0.05f;  
  8.             zpos -= (float)cos(heading*piover180) * 0.05f;  
  9.             if (walkbiasangle >= 359.0f)  
  10.             {  
  11.                 walkbiasangle = 0.0f;  
  12.             }  
  13.             else  
  14.             {  
  15.                 walkbiasangle+= 10;  
  16.             }  
  17.             walkbias = (float)sin(walkbiasangle * piover180)/20.0f;  
  18.             GLfloat ytrans = -walkbias-0.25f;  
  19.             g_moveMTCB->setTrans(osg::Vec3d(-xpos, ytrans, -zpos));  
  20.         }  
  21.   
  22.         if (ea.getKey()== osgGA::GUIEventAdapter::KEY_Down)  
  23.         {     
  24.             xpos += (float)sin(heading*piover180) * 0.05f;  
  25.             zpos += (float)cos(heading*piover180) * 0.05f;  
  26.             if (walkbiasangle <= 1.0f)  
  27.             {  
  28.                 walkbiasangle = 359.0f;  
  29.             }  
  30.             else  
  31.             {  
  32.                 walkbiasangle-= 10;  
  33.             }  
  34.             walkbias = (float)sin(walkbiasangle * piover180)/20.0f;  
  35.             GLfloat ytrans = -walkbias-0.25f;  
  36.             g_moveMTCB->setTrans(osg::Vec3d(-xpos, ytrans, -zpos));  
  37.         }  
  38.   
  39.         if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Left)  
  40.         {  
  41.             heading -= 1.0f;  
  42.             yrot = heading;  
  43.             double direction = osg::DegreesToRadians(360.0f) - osg::DegreesToRadians(yrot);  
  44.             g_yRotMTCB->setHeading(direction);  
  45.         }  
  46.           
  47.         if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Right)  
  48.         {  
  49.             heading += 1.0f;  
  50.             yrot = heading;  
  51.             double direction = osg::DegreesToRadians(360.0f) - osg::DegreesToRadians(yrot);  
  52.             g_yRotMTCB->setHeading(direction);  
  53.         }  
  54.   
  55.         if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Page_Up)  
  56.         {  
  57.             lookupdown += 1.0f;  
  58.             double direction = osg::DegreesToRadians(lookupdown);  
  59.             g_xRotMTCB->setPitch(direction);  
  60.         }  
  61.   
  62.         if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Page_Down)  
  63.         {  
  64.             lookupdown -= 1.0f;  
  65.             double direction = osg::DegreesToRadians(lookupdown);  
  66.             g_xRotMTCB->setPitch(direction);  
  67.         }  
  68.   
  69.     }  
  70. defaultbreak;  
  71. }  
行进以及旋转的方式参考了NeHe教程中的描述。

编译运行程序


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

[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/Texture2D>  
  13. #include <osgGA/TrackballManipulator>  
  14.   
  15. using namespace osg;  
  16.   
  17. //  
  18. //Copied From NeHe Tutorial  
  19.   
  20. typedef struct tagVERTEX  
  21. {  
  22.     float x,y,z;  
  23.     float u,v;  
  24. }VERTEX;  
  25.   
  26. typedef struct tagTRIANGLE  
  27. {  
  28.     VERTEX  vertex[3];  
  29. }TRIANGLE;  
  30.   
  31. typedef struct tagSECTOR  
  32. {  
  33.     int iNumTriangle;  
  34.     TRIANGLE *pTriangle;  
  35. }SECTOR;  
  36. SECTOR  Sector;  
  37.   
  38. void readstr(FILE *f,char *string)  
  39. {  
  40.     do  
  41.     {  
  42.         fgets(string, 255, f);  
  43.     } while ((string[0] == '/') || (string[0] == '\n'));  
  44. }  
  45.   
  46. void SetupWorld()  
  47. {  
  48.     float x, y, z, u, v;  
  49.     int numtriangles;  
  50.     FILE *filein;  
  51.     char oneline[255];  
  52.     filein = fopen("Data/world.txt""rt");             // File To Load World Data From  
  53.   
  54.     readstr(filein,oneline);  
  55.     sscanf(oneline, "NUMPOLLIES %d\n", &numtriangles);  
  56.   
  57.     Sector.iNumTriangle = numtriangles;  
  58.     Sector.pTriangle = new TRIANGLE[numtriangles];  
  59.     for(int i = 0; i < numtriangles; i++)  
  60.     {  
  61.         for(int j = 0; j < 3; j++)  
  62.         {  
  63.             readstr(filein,oneline);  
  64.             sscanf(oneline, "%f %f %f %f %f", &x, &y, &z, &u, &v);  
  65.             Sector.pTriangle[i].vertex[j].x = x;  
  66.             Sector.pTriangle[i].vertex[j].y = y;  
  67.             Sector.pTriangle[i].vertex[j].z = z;  
  68.             Sector.pTriangle[i].vertex[j].u = u;  
  69.             Sector.pTriangle[i].vertex[j].v = v;  
  70.         }  
  71.     }  
  72.     fclose(filein);  
  73. }  
  74.   
  75. //End  
  76. //  
  77.   
  78. const float piover180 = 0.0174532925f;  
  79. float heading;  
  80. float xpos;  
  81. float zpos;  
  82. GLfloat yrot;  
  83.   
  84. GLfloat walkbias = 0;  
  85. GLfloat walkbiasangle = 0;  
  86. GLfloat lookupdown = 0.0f;  
  87.   
  88. //  
  89. //TransUpdateCallback  
  90.   
  91. class TransUpdateCallback : public osg::NodeCallback  
  92. {  
  93. public:  
  94.   
  95.     TransUpdateCallback()  
  96.     {  
  97.         GLfloat xtrans = -xpos;  
  98.         GLfloat ztrans = -zpos;  
  99.         GLfloat ytrans = -walkbias-0.25f;  
  100.         _trans = osg::Vec3d(xtrans, ytrans, ztrans);  
  101.     }  
  102.   
  103.     virtual void operator()(Node* node, NodeVisitor* nv)  
  104.     {  
  105.         if (dynamic_cast<osg::MatrixTransform*>(node))  
  106.         {  
  107.             osg::MatrixTransform *moveMT = dynamic_cast<osg::MatrixTransform*>(node);  
  108.             moveMT->setMatrix(osg::Matrix::translate(_trans));  
  109.         }  
  110.   
  111.         traverse(node, nv);  
  112.     }  
  113.   
  114.     void setTrans(osg::Vec3d trans)  
  115.     {  
  116.         _trans = trans;  
  117.     }  
  118.   
  119.     osg::Vec3d _trans;  
  120. };  
  121.   
  122.   
  123. //End  
  124. //  
  125.   
  126.   
  127. //  
  128. //RotateUpdateCallback   
  129.   
  130. class RotateXUpdateCallback : public osg::NodeCallback  
  131. {  
  132.   
  133. public:  
  134.   
  135.     RotateXUpdateCallback()  
  136.     {  
  137.         _pitch = lookupdown;  
  138.     }  
  139.   
  140.     virtual void operator()(Node* node, NodeVisitor* nv)  
  141.     {  
  142.         if (dynamic_cast<osg::MatrixTransform*>(node))  
  143.         {  
  144.             osg::MatrixTransform *rotateX = dynamic_cast<osg::MatrixTransform*>(node);  
  145.             rotateX->setMatrix(osg::Matrix::rotate(_pitch, osg::X_AXIS));  
  146.         }  
  147.   
  148.         traverse(node, nv);  
  149.     }  
  150.   
  151.     void setPitch(double pitch)  
  152.     {  
  153.         _pitch = pitch;  
  154.     }  
  155.   
  156.     double _pitch;  
  157. };  
  158.   
  159.   
  160. class RotateYUpdateCallback : public osg::NodeCallback  
  161. {  
  162.   
  163. public:  
  164.   
  165.     RotateYUpdateCallback()  
  166.     {  
  167.         _heading = osg::DegreesToRadians(360.0f) - yrot;  
  168.     }  
  169.   
  170.     virtual void operator()(Node* node, NodeVisitor* nv)  
  171.     {  
  172.         if (dynamic_cast<osg::MatrixTransform*>(node))  
  173.         {  
  174.             osg::MatrixTransform *rotateY = dynamic_cast<osg::MatrixTransform*>(node);  
  175.             rotateY->setMatrix(osg::Matrix::rotate(_heading, osg::Y_AXIS));  
  176.         }  
  177.   
  178.         traverse(node, nv);  
  179.     }  
  180.   
  181.     void setHeading(double heading)  
  182.     {  
  183.         _heading = heading;  
  184.     }  
  185.   
  186.     double _heading;  
  187. };  
  188.   
  189.   
  190. //End  
  191. //  
  192.   
  193. TransUpdateCallback *g_moveMTCB;  
  194. RotateXUpdateCallback *g_xRotMTCB;  
  195. RotateYUpdateCallback *g_yRotMTCB;  
  196.   
  197.   
  198.   
  199. osg::Texture2D*  createTexture(int mode)  
  200. {  
  201.     osg::Image *textureImage = osgDB::readImageFile("Data/Mud.bmp");  
  202.     osg::Texture2D *texture2D = new osg::Texture2D;  
  203.     texture2D->setImage(textureImage);  
  204.   
  205.     if (mode == 0)  
  206.     {  
  207.         texture2D->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST);  
  208.         texture2D->setFilter(osg::Texture::MAG_FILTER, osg::Texture::NEAREST);  
  209.     }  
  210.     else if (mode == 1)  
  211.     {  
  212.         texture2D->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);  
  213.         texture2D->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);  
  214.     }  
  215.     else if (mode == 2)  
  216.     {  
  217.         texture2D->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_NEAREST);  
  218.         texture2D->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);  
  219.     }  
  220.   
  221.     texture2D->setWrap(osg::Texture::WRAP_R, osg::Texture::REPEAT);  
  222.     texture2D->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT);  
  223.     texture2D->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT);  
  224.   
  225.     return texture2D;  
  226. }  
  227.   
  228. //  
  229.   
  230. class ManipulatorSceneHandler : public osgGA::GUIEventHandler  
  231. {  
  232. public:  
  233.     ManipulatorSceneHandler()  
  234.     {  
  235.     }  
  236.   
  237.     virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)  
  238.     {  
  239.         osgViewer::Viewer *viewer = dynamic_cast<osgViewer::Viewer*>(&aa);  
  240.         if (!viewer)  
  241.             return false;  
  242.         if (!viewer->getSceneData())  
  243.             return false;  
  244.         if (ea.getHandled())   
  245.             return false;  
  246.   
  247.         osg::Group *root = viewer->getSceneData()->asGroup();  
  248.   
  249.         switch(ea.getEventType())  
  250.         {  
  251.         case(osgGA::GUIEventAdapter::KEYDOWN):  
  252.             {  
  253.                 if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Up)  
  254.                 {  
  255.                     xpos -= (float)sin(heading*piover180) * 0.05f;  
  256.                     zpos -= (float)cos(heading*piover180) * 0.05f;  
  257.                     if (walkbiasangle >= 359.0f)  
  258.                     {  
  259.                         walkbiasangle = 0.0f;  
  260.                     }  
  261.                     else  
  262.                     {  
  263.                         walkbiasangle+= 10;  
  264.                     }  
  265.                     walkbias = (float)sin(walkbiasangle * piover180)/20.0f;  
  266.                     GLfloat ytrans = -walkbias-0.25f;  
  267.                     g_moveMTCB->setTrans(osg::Vec3d(-xpos, ytrans, -zpos));  
  268.                 }  
  269.   
  270.                 if (ea.getKey()== osgGA::GUIEventAdapter::KEY_Down)  
  271.                 {     
  272.                     xpos += (float)sin(heading*piover180) * 0.05f;  
  273.                     zpos += (float)cos(heading*piover180) * 0.05f;  
  274.                     if (walkbiasangle <= 1.0f)  
  275.                     {  
  276.                         walkbiasangle = 359.0f;  
  277.                     }  
  278.                     else  
  279.                     {  
  280.                         walkbiasangle-= 10;  
  281.                     }  
  282.                     walkbias = (float)sin(walkbiasangle * piover180)/20.0f;  
  283.                     GLfloat ytrans = -walkbias-0.25f;  
  284.                     g_moveMTCB->setTrans(osg::Vec3d(-xpos, ytrans, -zpos));  
  285.                 }  
  286.   
  287.                 if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Left)  
  288.                 {  
  289.                     heading -= 1.0f;  
  290.                     yrot = heading;  
  291.                     double direction = osg::DegreesToRadians(360.0f) - osg::DegreesToRadians(yrot);  
  292.                     g_yRotMTCB->setHeading(direction);  
  293.                 }  
  294.                   
  295.                 if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Right)  
  296.                 {  
  297.                     heading += 1.0f;  
  298.                     yrot = heading;  
  299.                     double direction = osg::DegreesToRadians(360.0f) - osg::DegreesToRadians(yrot);  
  300.                     g_yRotMTCB->setHeading(direction);  
  301.                 }  
  302.   
  303.                 if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Page_Up)  
  304.                 {  
  305.                     lookupdown += 1.0f;  
  306.                     double direction = osg::DegreesToRadians(lookupdown);  
  307.                     g_xRotMTCB->setPitch(direction);  
  308.                 }  
  309.   
  310.                 if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Page_Down)  
  311.                 {  
  312.                     lookupdown -= 1.0f;  
  313.                     double direction = osg::DegreesToRadians(lookupdown);  
  314.                     g_xRotMTCB->setPitch(direction);  
  315.                 }  
  316.   
  317.             }  
  318.         defaultbreak;  
  319.         }  
  320.         return false;  
  321.     }  
  322. };  
  323.   
  324. //  
  325.   
  326.   
  327. class ViewerWidget : public QWidget, public osgViewer::Viewer  
  328. {  
  329. public:  
  330.     ViewerWidget(osg::Node *scene = NULL)  
  331.     {  
  332.         QWidget* renderWidget = getRenderWidget( createGraphicsWindow(0,0,100,100), scene);  
  333.   
  334.         QVBoxLayout* layout = new QVBoxLayout;  
  335.         layout->addWidget(renderWidget);  
  336.         layout->setContentsMargins(0, 0, 0, 1);  
  337.         setLayout( layout );  
  338.   
  339.         connect( &_timer, SIGNAL(timeout()), this, SLOT(update()) );  
  340.         _timer.start( 10 );  
  341.     }  
  342.   
  343.     QWidget* getRenderWidget( osgQt::GraphicsWindowQt* gw, osg::Node* scene )  
  344.     {  
  345.         osg::Camera* camera = this->getCamera();  
  346.         camera->setGraphicsContext( gw );  
  347.   
  348.         const osg::GraphicsContext::Traits* traits = gw->getTraits();  
  349.   
  350.         camera->setClearColor( osg::Vec4(0.0, 0.0, 0.0, 1.0) );  
  351.         camera->setViewport( new osg::Viewport(0, 0, traits->width, traits->height) );  
  352.         camera->setProjectionMatrixAsPerspective(45.0f, static_cast<double>(traits->width)/static_cast<double>(traits->height), 0.1f, 100.0f );  
  353.         camera->setViewMatrixAsLookAt(osg::Vec3d(0, 0, 1), osg::Vec3d(0, 0, 0), osg::Vec3d(0, 1, 0));  
  354.   
  355.         this->setSceneData( scene );  
  356.         this->addEventHandler(new ManipulatorSceneHandler);  
  357.   
  358.         return gw->getGLWidget();  
  359.     }  
  360.   
  361.     osgQt::GraphicsWindowQt* createGraphicsWindow( int x, int y, int w, int h, const std::string& name=""bool windowDecoration=false )  
  362.     {  
  363.         osg::DisplaySettings* ds = osg::DisplaySettings::instance().get();  
  364.         osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;  
  365.         traits->windowName = name;  
  366.         traits->windowDecoration = windowDecoration;  
  367.         traits->x = x;  
  368.         traits->y = y;  
  369.         traits->width = w;  
  370.         traits->height = h;  
  371.         traits->doubleBuffer = true;  
  372.         traits->alpha = ds->getMinimumNumAlphaBits();  
  373.         traits->stencil = ds->getMinimumNumStencilBits();  
  374.         traits->sampleBuffers = ds->getMultiSamples();  
  375.         traits->samples = ds->getNumMultiSamples();  
  376.   
  377.         return new osgQt::GraphicsWindowQt(traits.get());  
  378.     }  
  379.   
  380.     virtual void paintEvent( QPaintEvent* event )  
  381.     {   
  382.         frame();   
  383.     }  
  384.   
  385. protected:  
  386.   
  387.     QTimer _timer;  
  388. };  
  389.   
  390.   
  391.   
  392. osg::Node*  buildScene()  
  393. {  
  394.     SetupWorld();  
  395.     osg::Group *root = new osg::Group;  
  396.   
  397.     osg::Vec3Array *vertexArray = new osg::Vec3Array;  
  398.     osg::Vec2Array *textureArray = new osg::Vec2Array;  
  399.   
  400.     unsigned int num = Sector.iNumTriangle;  
  401.   
  402.     for (unsigned i = 0; i < num; ++i)  
  403.     {  
  404.         vertexArray->push_back(osg::Vec3(Sector.pTriangle[i].vertex[0].x, Sector.pTriangle[i].vertex[0].y, Sector.pTriangle[i].vertex[0].z));  
  405.         vertexArray->push_back(osg::Vec3(Sector.pTriangle[i].vertex[1].x, Sector.pTriangle[i].vertex[1].y, Sector.pTriangle[i].vertex[1].z));  
  406.         vertexArray->push_back(osg::Vec3(Sector.pTriangle[i].vertex[2].x, Sector.pTriangle[i].vertex[2].y, Sector.pTriangle[i].vertex[2].z));  
  407.   
  408.         textureArray->push_back(osg::Vec2(Sector.pTriangle[i].vertex[0].u, Sector.pTriangle[i].vertex[0].v));  
  409.         textureArray->push_back(osg::Vec2(Sector.pTriangle[i].vertex[1].u, Sector.pTriangle[i].vertex[1].v));  
  410.         textureArray->push_back(osg::Vec2(Sector.pTriangle[i].vertex[2].u, Sector.pTriangle[i].vertex[2].v));  
  411.     }  
  412.   
  413.     osg::MatrixTransform *moveMT = new osg::MatrixTransform;  
  414.     TransUpdateCallback *tucb = new TransUpdateCallback;  
  415.     moveMT->setUpdateCallback(tucb);  
  416.     g_moveMTCB = tucb;  
  417.   
  418.     osg::MatrixTransform *headingMT = new osg::MatrixTransform;  
  419.     RotateYUpdateCallback *ryuc = new RotateYUpdateCallback;  
  420.     headingMT->setUpdateCallback(ryuc);  
  421.     g_yRotMTCB = ryuc;  
  422.   
  423.     osg::MatrixTransform *pitchMT = new osg::MatrixTransform;  
  424.     RotateXUpdateCallback *rxuc = new RotateXUpdateCallback;  
  425.     pitchMT->setUpdateCallback(rxuc);  
  426.     g_xRotMTCB = rxuc;  
  427.   
  428.     headingMT->addChild(pitchMT);  
  429.     pitchMT->addChild(moveMT);  
  430.   
  431.     osg::Geometry *triangleGeometry = new osg::Geometry;  
  432.     triangleGeometry->setVertexArray(vertexArray);  
  433.   
  434.     triangleGeometry->setTexCoordArray(0, textureArray);  
  435.     triangleGeometry->getOrCreateStateSet()->setTextureAttributeAndModes(0, createTexture(0));  
  436.   
  437.     triangleGeometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES, 0, 108));  
  438.     osg::Geode *triangleGeode = new osg::Geode;  
  439.     triangleGeometry->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);  
  440.     triangleGeode->addDrawable(triangleGeometry);  
  441.     moveMT->addChild(triangleGeode);  
  442.     root->addChild(headingMT);  
  443.   
  444.     return root;  
  445. }  
  446.   
  447.   
  448. int main( int argc, char** argv )  
  449. {  
  450.     QApplication app(argc, argv);  
  451.     ViewerWidget* viewWidget = new ViewerWidget(buildScene());  
  452.     viewWidget->setGeometry( 100, 100, 640, 480 );  
  453.     viewWidget->show();  
  454.     return app.exec();  
  455. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值