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

来源:互联网 发布:美女主播秀软件 编辑:程序博客网 时间:2024/05/16 08:34
  • 简介

这节课NeHe课程主要向我们展示了将物理运动规律引入到三维场景中,模拟真实物体的位置变化过程。这节课分别模拟了如下几种运动方式:

(1)在重力作用下的抛物线运动;

(2)匀速运动

(3)一种类似于弹簧一样的来回运动

这些运动的方程在Physics.h头文件中描述的很清楚,稍有物理知识应该不难理解。

  • 实现

首先我们在场景中添加各种几何体:

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. root->addChild(createBackGroundGeode()); //网状背景  
  2. root->addChild(constantVelocityNode());  //匀速模拟  
  3. root->addChild(underGravitationNode());  // 重力模拟  
  4. root->addChild(massConnectedWithSpringNode()); //弹簧来回运动模拟  
另外需要添加场景中的说明文字:

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. osg::Node *timeEllapsedNode = glPrint(-15.0f, 14, 0, osg::Vec4(1,1,1,1), "Time elapsed (seconds): %.2f", timeElapsed);  
  2. timeEllapsedNode->addUpdateCallback(new TimeEllapsedUpdateCallback);  
  3. root->addChild(timeEllapsedNode);  
  4.   
  5. osg::Node *ratioNode = glPrint(-15.0f, 13, 0, osg::Vec4(1,1,1,1),"Slow motion ratio: %.2f", slowMotionRatio);  
  6. ratioNode->addUpdateCallback(new RatioUpdateCallback);  
  7.   
  8. root->addChild(ratioNode);  
  9. root->addChild(glPrint(-15.0f, 12, 0, osg::Vec4(1,1,1,1),"Press F2 for normal motion"));  
  10. root->addChild(glPrint(-15.0f, 11, 0, osg::Vec4(1,1,1,1),"Press F3 for slow motion"));  

接下来便是一系列的更新回调,按照物理运动的规律更新节点位置:

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. //Constant Callback  
  2.   
  3. class ConstantPointUpdateCallback : public osg::Drawable::UpdateCallback  
  4. {  
  5. public:  
  6.   
  7.     virtual void update(osg::NodeVisitor*, osg::Drawable* drawable)  
  8.     {  
  9.         osg::Geometry *geometry = dynamic_cast<osg::Geometry*>(drawable);  
  10.         if (!geometry)  
  11.             return;  
  12.           
  13.         osg::Vec3Array *vertexArray = dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray());  
  14.         if (!vertexArray)  
  15.             return;  
  16.   
  17.         vertexArray->clear();  
  18.           
  19.         for (int a = 0; a < constantVelocity->numOfMasses; ++a)  
  20.         {  
  21.             Mass* mass = constantVelocity->getMass(a);  
  22.             Vector3D* pos = &mass->pos;  
  23.             vertexArray->push_back(osg::Vec3(pos->x, pos->y, pos->z));  
  24.         }  
  25.         geometry->setVertexArray(vertexArray);  
  26.         vertexArray->dirty();  
  27.     }  
  28. };  
  29.   
  30.   
  31. class ConstantWordUpdateCallback : public osg::NodeCallback  
  32. {  
  33. public:  
  34.     virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)  
  35.     {  
  36.         osg::MatrixTransform *mt = dynamic_cast<osg::MatrixTransform*>(node);  
  37.         if (!mt)  
  38.             return;  
  39.   
  40.         for (int a = 0; a < constantVelocity->numOfMasses; ++a)  
  41.         {  
  42.             Mass* mass = constantVelocity->getMass(a);  
  43.             Vector3D* pos = &mass->pos;  
  44.             mt->setMatrix(osg::Matrix::translate(pos->x, pos->y + 1, pos->z));  
  45.         }  
  46.           
  47.         traverse(node, nv);  
  48.     }  
  49. };  
为了篇幅限制,这里只给出匀速运动的回调代码,其他部分参看附录中的源码。

我们需要在每帧中计算时间以及在每帧中更新物理运动的参数,这部分在交互的代码FRAME(帧循环事件)中给出:

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. case (osgGA::GUIEventAdapter::FRAME):  
  2.     {  
  3.         double dt = 0.0;  
  4.         _currentTick = osg::Timer::instance()->tick();  
  5.         if (_currentTick != _lastTick)  
  6.         {         
  7.             dt = osg::Timer::instance()->delta_s(_lastTick, _currentTick);  
  8.             _lastTick = _currentTick;  
  9.         }  
  10.         dt /= slowMotionRatio;  
  11.         timeElapsed += dt;  
  12.   
  13.         float maxPossible_dt = 0.1f;  
  14.         int numOfIterations = (int)(dt / maxPossible_dt) + 1;  
  15.         if (numOfIterations != 0)  
  16.             dt = dt / numOfIterations;    
  17.   
  18.         for (int a = 0; a < numOfIterations; ++a)  
  19.         {  
  20.             constantVelocity->operate(dt);  
  21.             motionUnderGravitation->operate(dt);  
  22.             massConnectedWithSpring->operate(dt);  
  23.         }  
  24.     }  
此外在按下F2和F3时调整运动的速度:

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. if (ea.getKey() == osgGA::GUIEventAdapter::KEY_F2)  
  2. {  
  3.     slowMotionRatio = 1.0f;  
  4. }  
  5.   
  6. if (ea.getKey() == osgGA::GUIEventAdapter::KEY_F3)  
  7. {  
  8.     slowMotionRatio = 10.0f;  
  9. }  
编译运行程序:


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

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. #include "../osgNeHe.h"  
  2.   
  3. #include "Physics1.h"  
  4. #include <QtCore/QTimer>  
  5. #include <QtGui/QApplication>  
  6. #include <QtGui/QVBoxLayout>  
  7.   
  8. #include <osgViewer/Viewer>  
  9. #include <osgDB/ReadFile>  
  10. #include <osgQt/GraphicsWindowQt>  
  11.   
  12. #include <osg/MatrixTransform>  
  13.   
  14. #include <osgText/Text>  
  15. #include <osg/Point>  
  16.   
  17. #include <osgGA/TrackballManipulator>  
  18.   
  19. //////////////////////////////////////////////////////////////////////////  
  20.   
  21. ConstantVelocity* constantVelocity = new ConstantVelocity();  
  22.   
  23. MotionUnderGravitation* motionUnderGravitation =   
  24.                                         new MotionUnderGravitation(Vector3D(0.0f, -9.81f, 0.0f));  
  25.   
  26. MassConnectedWithSpring* massConnectedWithSpring = new MassConnectedWithSpring(2.0f);  
  27.   
  28. float slowMotionRatio = 10.0f;  
  29. float timeElapsed = 0;    
  30.   
  31.   
  32.   
  33. osg::Node* glPrint(GLfloat x, GLfloat y, GLfloat z, const osg::Vec4& fontColor, const char *string, ...)  
  34. {  
  35.     char        text[256];    
  36.     va_list     ap;  
  37.   
  38.     if (string == NULL)  
  39.         return NULL;  
  40.   
  41.     va_start(ap, string);  
  42.     vsprintf(text, string, ap);  
  43.     va_end(ap);  
  44.   
  45.     osg::MatrixTransform *posMT = new osg::MatrixTransform;  
  46.     posMT->setMatrix(osg::Matrix::translate(x, y, z));  
  47.   
  48.     osgText::Text *textWords = new osgText::Text;  
  49.     textWords->setColor(fontColor);  
  50.     textWords->setText(text);  
  51.     textWords->setFont("Fonts/Arial.ttf");  
  52.     textWords->setCharacterSize(1.0f);  
  53.   
  54.     osg::Geode *fontGeode = new osg::Geode;  
  55.     fontGeode->addDrawable(textWords);  
  56.   
  57.     posMT->addChild(fontGeode);  
  58.     return posMT;  
  59. }  
  60.   
  61.   
  62. //////////////////////////////////////////////////////////////////////////  
  63. //////////////////////////////////////////////////////////////////////////  
  64. //////////////////////////////////////////////////////////////////////////  
  65.   
  66. class ManipulatorSceneHandler : public osgGA::GUIEventHandler  
  67. {  
  68. public:  
  69.     ManipulatorSceneHandler()  
  70.     {  
  71.         _lastTick  =  osg::Timer::instance()->tick();  
  72.         _currentTick = _lastTick;  
  73.     }  
  74.   
  75. public:  
  76.     virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)  
  77.     {  
  78.         osgViewer::Viewer *viewer = dynamic_cast<osgViewer::Viewer*>(&aa);  
  79.         if (!viewer)  
  80.             return false;  
  81.         if (!viewer->getSceneData())  
  82.             return false;  
  83.         if (ea.getHandled())   
  84.             return false;  
  85.   
  86.         osg::Group *root = viewer->getSceneData()->asGroup();  
  87.   
  88.         switch(ea.getEventType())  
  89.         {  
  90.         case (osgGA::GUIEventAdapter::FRAME):  
  91.             {  
  92.                 double dt = 0.0;  
  93.                 _currentTick = osg::Timer::instance()->tick();  
  94.                 if (_currentTick != _lastTick)  
  95.                 {         
  96.                     dt = osg::Timer::instance()->delta_s(_lastTick, _currentTick);  
  97.                     _lastTick = _currentTick;  
  98.                 }  
  99.                 dt /= slowMotionRatio;  
  100.                 timeElapsed += dt;  
  101.   
  102.                 float maxPossible_dt = 0.1f;  
  103.                 int numOfIterations = (int)(dt / maxPossible_dt) + 1;  
  104.                 if (numOfIterations != 0)  
  105.                     dt = dt / numOfIterations;    
  106.   
  107.                 for (int a = 0; a < numOfIterations; ++a)  
  108.                 {  
  109.                     constantVelocity->operate(dt);  
  110.                     motionUnderGravitation->operate(dt);  
  111.                     massConnectedWithSpring->operate(dt);  
  112.                 }  
  113.             }  
  114.             break;  
  115.         case(osgGA::GUIEventAdapter::KEYDOWN):  
  116.             {  
  117.                 if (ea.getKey() == osgGA::GUIEventAdapter::KEY_F2)  
  118.                 {  
  119.                     slowMotionRatio = 1.0f;  
  120.                 }  
  121.   
  122.                 if (ea.getKey() == osgGA::GUIEventAdapter::KEY_F3)  
  123.                 {  
  124.                     slowMotionRatio = 10.0f;  
  125.                 }  
  126.             }  
  127.             break;  
  128.   
  129.         defaultbreak;  
  130.         }  
  131.         return false;  
  132.     }  
  133.   
  134.     osg::Timer_t _lastTick;  
  135.     osg::Timer_t _currentTick;  
  136. };  
  137.   
  138. //////////////////////////////////////////////////////////////////////////  
  139. //////////////////////////////////////////////////////////////////////////  
  140. //////////////////////////////////////////////////////////////////////////  
  141.   
  142. //Constant Callback  
  143.   
  144. class ConstantPointUpdateCallback : public osg::Drawable::UpdateCallback  
  145. {  
  146. public:  
  147.   
  148.     virtual void update(osg::NodeVisitor*, osg::Drawable* drawable)  
  149.     {  
  150.         osg::Geometry *geometry = dynamic_cast<osg::Geometry*>(drawable);  
  151.         if (!geometry)  
  152.             return;  
  153.           
  154.         osg::Vec3Array *vertexArray = dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray());  
  155.         if (!vertexArray)  
  156.             return;  
  157.   
  158.         vertexArray->clear();  
  159.           
  160.         for (int a = 0; a < constantVelocity->numOfMasses; ++a)  
  161.         {  
  162.             Mass* mass = constantVelocity->getMass(a);  
  163.             Vector3D* pos = &mass->pos;  
  164.             vertexArray->push_back(osg::Vec3(pos->x, pos->y, pos->z));  
  165.         }  
  166.         geometry->setVertexArray(vertexArray);  
  167.         vertexArray->dirty();  
  168.     }  
  169. };  
  170.   
  171.   
  172. class ConstantWordUpdateCallback : public osg::NodeCallback  
  173. {  
  174. public:  
  175.     virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)  
  176.     {  
  177.         osg::MatrixTransform *mt = dynamic_cast<osg::MatrixTransform*>(node);  
  178.         if (!mt)  
  179.             return;  
  180.   
  181.         for (int a = 0; a < constantVelocity->numOfMasses; ++a)  
  182.         {  
  183.             Mass* mass = constantVelocity->getMass(a);  
  184.             Vector3D* pos = &mass->pos;  
  185.             mt->setMatrix(osg::Matrix::translate(pos->x, pos->y + 1, pos->z));  
  186.         }  
  187.           
  188.         traverse(node, nv);  
  189.     }  
  190. };  
  191.   
  192.   
  193. //Gravity Callback  
  194. class GravitationPointUpdateCallback : public osg::Drawable::UpdateCallback  
  195. {  
  196. public:  
  197.   
  198.     virtual void update(osg::NodeVisitor*, osg::Drawable* drawable)  
  199.     {  
  200.         osg::Geometry *geometry = dynamic_cast<osg::Geometry*>(drawable);  
  201.         if (!geometry)  
  202.             return;  
  203.   
  204.         osg::Vec3Array *vertexArray = dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray());  
  205.         if (!vertexArray)  
  206.             return;  
  207.   
  208.         vertexArray->clear();  
  209.   
  210.         for (int a = 0; a < motionUnderGravitation->numOfMasses; ++a)  
  211.         {  
  212.             Mass* mass = motionUnderGravitation->getMass(a);  
  213.             Vector3D* pos = &mass->pos;  
  214.             vertexArray->push_back(osg::Vec3(pos->x, pos->y, pos->z));  
  215.         }  
  216.         geometry->setVertexArray(vertexArray);  
  217.         vertexArray->dirty();  
  218.     }  
  219. };  
  220.   
  221.   
  222. class GravitationWordUpdateCallback : public osg::NodeCallback  
  223. {  
  224. public:  
  225.     virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)  
  226.     {  
  227.         osg::MatrixTransform *mt = dynamic_cast<osg::MatrixTransform*>(node);  
  228.         if (!mt)  
  229.             return;  
  230.   
  231.         for (int a = 0; a < motionUnderGravitation->numOfMasses; ++a)  
  232.         {  
  233.             Mass* mass = motionUnderGravitation->getMass(a);  
  234.             Vector3D* pos = &mass->pos;  
  235.             mt->setMatrix(osg::Matrix::translate(pos->x, pos->y + 1, pos->z));  
  236.         }  
  237.   
  238.         traverse(node, nv);  
  239.     }  
  240. };  
  241.   
  242.   
  243.   
  244. //SpringCallback  
  245. class SpringPointUpdateCallback : public osg::Drawable::UpdateCallback  
  246. {  
  247. public:  
  248.   
  249.     virtual void update(osg::NodeVisitor*, osg::Drawable* drawable)  
  250.     {  
  251.         osg::Geometry *geometry = dynamic_cast<osg::Geometry*>(drawable);  
  252.         if (!geometry)  
  253.             return;  
  254.   
  255.         osg::Vec3Array *vertexArray = dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray());  
  256.         if (!vertexArray)  
  257.             return;  
  258.   
  259.         vertexArray->clear();  
  260.   
  261.         for (int a = 0; a < massConnectedWithSpring->numOfMasses; ++a)  
  262.         {  
  263.             Mass* mass = massConnectedWithSpring->getMass(a);  
  264.             Vector3D* pos = &mass->pos;  
  265.             vertexArray->push_back(osg::Vec3(pos->x, pos->y, pos->z));  
  266.         }  
  267.         geometry->setVertexArray(vertexArray);  
  268.         vertexArray->dirty();  
  269.     }  
  270. };  
  271.   
  272.   
  273. class SpringWordUpdateCallback : public osg::NodeCallback  
  274. {  
  275. public:  
  276.     virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)  
  277.     {  
  278.         osg::MatrixTransform *mt = dynamic_cast<osg::MatrixTransform*>(node);  
  279.         if (!mt)  
  280.             return;  
  281.   
  282.         for (int a = 0; a < massConnectedWithSpring->numOfMasses; ++a)  
  283.         {  
  284.             Mass* mass = massConnectedWithSpring->getMass(a);  
  285.             Vector3D* pos = &mass->pos;  
  286.             mt->setMatrix(osg::Matrix::translate(pos->x, pos->y + 1, pos->z));  
  287.         }  
  288.   
  289.         traverse(node, nv);  
  290.     }  
  291. };  
  292.   
  293.   
  294. class SpringLineUpdateCallback : public osg::Drawable::UpdateCallback  
  295. {  
  296. public:  
  297.   
  298.     virtual void update(osg::NodeVisitor*, osg::Drawable* drawable)  
  299.     {  
  300.         osg::Geometry *geometry = dynamic_cast<osg::Geometry*>(drawable);  
  301.         if (!geometry)  
  302.             return;  
  303.   
  304.         osg::Vec3Array *vertexArray = dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray());  
  305.         if (!vertexArray)  
  306.             return;  
  307.   
  308.         vertexArray->clear();  
  309.   
  310.         for (int a = 0; a < massConnectedWithSpring->numOfMasses; ++a)  
  311.         {  
  312.             Mass* mass = massConnectedWithSpring->getMass(a);  
  313.             Vector3D* pos = &mass->pos;  
  314.             vertexArray->push_back(osg::Vec3(pos->x, pos->y, pos->z));  
  315.             Vector3D *tmp = &massConnectedWithSpring->connectionPos;  
  316.             vertexArray->push_back(osg::Vec3(tmp->x, tmp->y, tmp->z));  
  317.         }  
  318.         geometry->setVertexArray(vertexArray);  
  319.         vertexArray->dirty();  
  320.     }  
  321. };  
  322.   
  323.   
  324. class TimeEllapsedUpdateCallback : public osg::NodeCallback  
  325. {  
  326. public:  
  327.   
  328.     virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)  
  329.     {  
  330.         osg::MatrixTransform *mt = dynamic_cast<osg::MatrixTransform*>(node);  
  331.         if (!mt)  
  332.             return;  
  333.   
  334.         osg::Geode *geode = dynamic_cast<osg::Geode*>(mt->getChild(0));  
  335.         if (!geode)  
  336.             return;  
  337.   
  338.         osgText::Text *text = dynamic_cast<osgText::Text*>(geode->getDrawable(0));  
  339.         if (!text)  
  340.             return;  
  341.   
  342.         std::stringstream os;  
  343.         std::string str;  
  344.         os.precision(2);  
  345.         os << std::fixed << "Time elapsed (seconds): " << timeElapsed;  
  346.         str = os.str();  
  347.         text->setText(str);  
  348.   
  349.         traverse(node, nv);  
  350.     }  
  351. };  
  352.   
  353.   
  354. class RatioUpdateCallback : public osg::NodeCallback  
  355. {  
  356. public:  
  357.   
  358.     virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)  
  359.     {  
  360.         osg::MatrixTransform *mt = dynamic_cast<osg::MatrixTransform*>(node);  
  361.         if (!mt)  
  362.             return;  
  363.   
  364.         osg::Geode *geode = dynamic_cast<osg::Geode*>(mt->getChild(0));  
  365.         if (!geode)  
  366.             return;  
  367.   
  368.         osgText::Text *text = dynamic_cast<osgText::Text*>(geode->getDrawable(0));  
  369.         if (!text)  
  370.             return;  
  371.   
  372.         std::stringstream os;  
  373.         std::string str;  
  374.         os.precision(2);  
  375.         os << std::fixed << "Slow motion ratio: " << slowMotionRatio;  
  376.         str = os.str();  
  377.         text->setText(str);  
  378.   
  379.         traverse(node, nv);  
  380.     }  
  381.   
  382. };  
  383.   
  384.   
  385.   
  386. //绘制背景网格  
  387. osg::Geode* createBackGroundGeode()  
  388. {  
  389.     osg::Geode *geode = new osg::Geode;  
  390.     osg::Geometry *geometry = new osg::Geometry;  
  391.     osg::Vec3Array *vertexArray = new osg::Vec3Array;  
  392.     osg::Vec3Array *colorArray = new osg::Vec3Array;  
  393.     colorArray->push_back(osg::Vec3(0, 0, 1.0));  
  394.     geometry->setColorArray(colorArray, osg::Array::BIND_OVERALL);  
  395.   
  396.     for (float x = -20; x <= 20; x += 1.0f)                        
  397.     {  
  398.         vertexArray->push_back(osg::Vec3(x, 20, 0));  
  399.         vertexArray->push_back(osg::Vec3(x,-20, 0));  
  400.     }  
  401.   
  402.     for (float y = -20; y <= 20; y += 1.0f)  
  403.     {  
  404.         vertexArray->push_back(osg::Vec3(20, y, 0));  
  405.         vertexArray->push_back(osg::Vec3(-20, y, 0));  
  406.     }  
  407.   
  408.     geometry->setVertexArray(vertexArray);  
  409.     geometry->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);  
  410.     geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES, 0, vertexArray->size()));  
  411.     geode->addDrawable(geometry);  
  412.     return geode;  
  413. }  
  414.   
  415.   
  416. osg::Geode* createPoint(const osg::Vec3& pos, const osg::Vec3& color, float size)  
  417. {  
  418.     osg::Geode *geode = new osg::Geode;  
  419.     osg::Geometry *geometry = new osg::Geometry;  
  420.   
  421.     osg::Vec3Array *vertexArray = new osg::Vec3Array;  
  422.     osg::Vec3Array *colorArray = new osg::Vec3Array;  
  423.     colorArray->push_back(color);  
  424.     geometry->setColorArray(colorArray, osg::Array::BIND_OVERALL);  
  425.     vertexArray->push_back(pos);  
  426.     geometry->setVertexArray(vertexArray);  
  427.     geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POINTS, 0, vertexArray->size()));  
  428.       
  429.     osg::Point *point = new osg::Point;  
  430.     point->setSize(size);  
  431.     geometry->getOrCreateStateSet()->setAttributeAndModes(point);  
  432.     geometry->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);  
  433.       
  434.     geode->addDrawable(geometry);  
  435.     return geode;  
  436. }  
  437.   
  438.   
  439. osg::Geode* createLine(const osg::Vec3& posBeg, const osg::Vec3& posEnd, const osg::Vec3& color)  
  440. {  
  441.     osg::Geode *geode = new osg::Geode;  
  442.     osg::Geometry *geometry = new osg::Geometry;  
  443.   
  444.     osg::Vec3Array *vertexArray = new osg::Vec3Array;  
  445.     osg::Vec3Array *colorArray = new osg::Vec3Array;  
  446.     vertexArray->push_back(posBeg);  
  447.     vertexArray->push_back(posEnd);  
  448.     geometry->setVertexArray(vertexArray);  
  449.     colorArray->push_back(color);  
  450.     geometry->setColorArray(colorArray, osg::Array::BIND_OVERALL);  
  451.     geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES, 0, vertexArray->size()));  
  452.     geometry->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);  
  453.   
  454.     geode->addDrawable(geometry);  
  455.     return geode;  
  456. }  
  457.   
  458.   
  459. //绘制Constant Velocity  
  460.   
  461. osg::Node*  constantVelocityNode()  
  462. {  
  463.     osg::Group *constantVelocityGroup = new osg::Group;  
  464.   
  465.     for (int a = 0; a < constantVelocity->numOfMasses; ++a)  
  466.     {  
  467.         Mass* mass = constantVelocity->getMass(a);  
  468.         Vector3D* pos = &mass->pos;  
  469.   
  470.         osg::Node *node = glPrint(pos->x, pos->y + 1, pos->z, osg::Vec4(1,0,0,1), "Mass with constant vel");  
  471.         osg::Geode *geode = createPoint(osg::Vec3(pos->x, pos->y, pos->z), osg::Vec3(1,0,0), 4);  
  472.         geode->getDrawable(0)->setUpdateCallback(new ConstantPointUpdateCallback);  
  473.         node->addUpdateCallback(new ConstantWordUpdateCallback);  
  474.         constantVelocityGroup->addChild(node);  
  475.         constantVelocityGroup->addChild(geode);  
  476.     }  
  477.   
  478.     return constantVelocityGroup;  
  479. }  
  480.   
  481.   
  482. //绘制motionUnderGravitation  
  483.   
  484. osg::Node*   underGravitationNode()  
  485. {  
  486.     osg::Group *group = new osg::Group;  
  487.       
  488.     for (int a = 0; a < motionUnderGravitation->numOfMasses; ++a)  
  489.     {  
  490.         Mass* mass = motionUnderGravitation->getMass(a);  
  491.         Vector3D* pos = &mass->pos;  
  492.   
  493.         osg::Node *wordNode = glPrint(pos->x, pos->y + 1, pos->z, osg::Vec4(1,1,0,1), "Motion under gravitation");  
  494.         osg::Geode *pointNode = createPoint(osg::Vec3(pos->x, pos->y, pos->z), osg::Vec3(1,1,0), 4);  
  495.   
  496.         wordNode->addUpdateCallback(new GravitationWordUpdateCallback);  
  497.         pointNode->getDrawable(0)->setUpdateCallback(new GravitationPointUpdateCallback);  
  498.   
  499.         group->addChild(wordNode);  
  500.         group->addChild(pointNode);  
  501.     }  
  502.       
  503.     return group;  
  504. }  
  505.   
  506. //绘制massConnectedWithSpring  
  507. osg::Node*   massConnectedWithSpringNode()  
  508. {  
  509.     osg::Group *group = new osg::Group;  
  510.   
  511.     for (int a = 0; a < massConnectedWithSpring->numOfMasses; ++a)  
  512.     {  
  513.         Mass* mass = massConnectedWithSpring->getMass(a);  
  514.         Vector3D* pos = &mass->pos;  
  515.   
  516.         osg::Node *wordNode = glPrint(pos->x, pos->y + 1, pos->z, osg::Vec4(0,1,0,1), "Mass connected with spring");  
  517.         osg::Geode *pointNode = createPoint(osg::Vec3(pos->x, pos->y, pos->z), osg::Vec3(0,1,0), 8);  
  518.         group->addChild(wordNode);  
  519.         group->addChild(pointNode);  
  520.   
  521.         wordNode->addUpdateCallback(new SpringWordUpdateCallback);  
  522.         pointNode->getDrawable(0)->setUpdateCallback(new SpringPointUpdateCallback);  
  523.           
  524.         Vector3D *tmp = &massConnectedWithSpring->connectionPos;  
  525.         osg::Geode *lineNode = createLine(osg::Vec3(pos->x, pos->y, pos->z), osg::Vec3(tmp->x, tmp->y, tmp->z), osg::Vec3(0,1,0));  
  526.         //Force the lineNode Draw Upon Background  
  527.         lineNode->getOrCreateStateSet()->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);  
  528.         group->addChild(lineNode);  
  529.         lineNode->getDrawable(0)->setUpdateCallback(new SpringLineUpdateCallback);  
  530.     }  
  531.   
  532.     return group;  
  533. }  
  534.   
  535.   
  536. class ViewerWidget : public QWidget, public osgViewer::Viewer  
  537. {  
  538. public:  
  539.     ViewerWidget(osg::Node *scene = NULL)  
  540.     {  
  541.         QWidget* renderWidget = getRenderWidget( createGraphicsWindow(0,0,100,100), scene);  
  542.   
  543.         QVBoxLayout* layout = new QVBoxLayout;  
  544.         layout->addWidget(renderWidget);  
  545.         layout->setContentsMargins(0, 0, 0, 1);  
  546.         setLayout( layout );  
  547.   
  548.         connect( &_timer, SIGNAL(timeout()), this, SLOT(update()) );  
  549.         _timer.start( 10 );  
  550.     }  
  551.   
  552.     QWidget* getRenderWidget( osgQt::GraphicsWindowQt* gw, osg::Node* scene )  
  553.     {  
  554.         osg::Camera* camera = this->getCamera();  
  555.         camera->setGraphicsContext( gw );  
  556.   
  557.         const osg::GraphicsContext::Traits* traits = gw->getTraits();  
  558.   
  559.         camera->setClearColor( osg::Vec4(0.0, 0.0, 0.0, 1.0) );  
  560.         camera->setViewport( new osg::Viewport(0, 0, traits->width, traits->height) );  
  561.         camera->setProjectionMatrixAsPerspective(45.0f, static_cast<double>(traits->width)/static_cast<double>(traits->height), 0.1f, 100.0f );  
  562.         camera->setViewMatrixAsLookAt(osg::Vec3d(0, 0, 40), osg::Vec3d(0, 0, 0), osg::Vec3d(0, 1, 0));  
  563.   
  564.         //OSG默认会将点裁剪掉  
  565.         camera->setCullingMode(  
  566.             camera->getCullingMode() &  
  567.             ~osg::CullSettings::SMALL_FEATURE_CULLING);   
  568.         addEventHandler(new ManipulatorSceneHandler);  
  569.         this->setSceneData( scene );  
  570.         return gw->getGLWidget();  
  571.     }  
  572.   
  573.     osgQt::GraphicsWindowQt* createGraphicsWindow( int x, int y, int w, int h, const std::string& name=""bool windowDecoration=false )  
  574.     {  
  575.         osg::DisplaySettings* ds = osg::DisplaySettings::instance().get();  
  576.         osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;  
  577.         traits->windowName = name;  
  578.         traits->windowDecoration = windowDecoration;  
  579.         traits->x = x;  
  580.         traits->y = y;  
  581.         traits->width = w;  
  582.         traits->height = h;  
  583.         traits->doubleBuffer = true;  
  584.         traits->alpha = ds->getMinimumNumAlphaBits();  
  585.         traits->stencil = ds->getMinimumNumStencilBits();  
  586.         traits->sampleBuffers = ds->getMultiSamples();  
  587.         traits->samples = ds->getNumMultiSamples();  
  588.   
  589.         return new osgQt::GraphicsWindowQt(traits.get());  
  590.     }  
  591.   
  592.     virtual void paintEvent( QPaintEvent* event )  
  593.     {   
  594.         frame();   
  595.     }  
  596.   
  597. protected:  
  598.   
  599.     QTimer _timer;  
  600. };  
  601.   
  602.   
  603.   
  604. osg::Node*  buildScene()  
  605. {  
  606.     osg::Group *root = new osg::Group;  
  607.   
  608.     root->addChild(createBackGroundGeode());  
  609.     root->addChild(constantVelocityNode());  
  610.     root->addChild(underGravitationNode());  
  611.     root->addChild(massConnectedWithSpringNode());  
  612.   
  613.     osg::Node *timeEllapsedNode = glPrint(-15.0f, 14, 0, osg::Vec4(1,1,1,1), "Time elapsed (seconds): %.2f", timeElapsed);  
  614.     timeEllapsedNode->addUpdateCallback(new TimeEllapsedUpdateCallback);  
  615.     root->addChild(timeEllapsedNode);  
  616.   
  617.     osg::Node *ratioNode = glPrint(-15.0f, 13, 0, osg::Vec4(1,1,1,1),"Slow motion ratio: %.2f", slowMotionRatio);  
  618.     ratioNode->addUpdateCallback(new RatioUpdateCallback);  
  619.   
  620.     root->addChild(ratioNode);  
  621.     root->addChild(glPrint(-15.0f, 12, 0, osg::Vec4(1,1,1,1),"Press F2 for normal motion"));  
  622.     root->addChild(glPrint(-15.0f, 11, 0, osg::Vec4(1,1,1,1),"Press F3 for slow motion"));  
  623.   
  624.     return root;  
  625. }  
  626.   
  627.   
  628.   
  629. int main( int argc, char** argv )  
  630. {  
  631.     QApplication app(argc, argv);  
  632.     ViewerWidget* viewWidget = new ViewerWidget(buildScene());  
  633.     viewWidget->setGeometry( 100, 100, 640, 480 );  
  634.     viewWidget->show();  
  635.     return app.exec();  
  636. }  
0 0
原创粉丝点击