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

  • 简介

这节课NeHe教我们怎么在场景中实现3D光晕的效果,光晕会在摄像机镜头对准太阳的时候就会出现,实现的原理是在光源与摄像机视点之间绘制一系列贴好纹理的四边形,并且让这些四边形正对着视点(Billboard)

  • 实现

在OSG中的实现与OpenGL中有一些不同,在OpenGL中很容易得到屏幕上某一点的深度值从而判断遮挡,在OSG中需要在获取到OpenGL RC的时候才能获取屏幕中像素的深度值,需要在相机里面进行操作。我尝试使用一个PRE_RENDER的相机先绘制其他模型,判断遮挡然后再根据是否遮挡绘制光源节点,在运行的时候发现需要拖动窗口才能得到正确的效果,目前尚未找到原因,希望知道的读者指点一下。有鉴于此,在计算遮挡的时候我使用了OSG中线求交器,通过判断从试点到光源连线是否与场景中模型相交来判断遮挡。

判断遮挡的代码如下:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. osg::Vec3 eyePos = camera->getInverseViewMatrix().getTrans();  
  2.   
  3. osgUtil::LineSegmentIntersector *intersector = new osgUtil::LineSegmentIntersector(eyePos, g_LightPosition);  
  4. osgUtil::IntersectionVisitor intersectVisitor(intersector);  
  5. g_Root->accept(intersectVisitor);  
  6.   
  7. if(intersector->containsIntersections())  

我们需要绘制一系列的模拟光晕的四边形:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. osg::Node*    createBigGlow(const osg::Vec4& color, osg::Vec3 p, float scale)  
  2. osg::Node*    createGlow(const osg::Vec4& color, osg::Vec3 p, float scale)  
  3. osg::Node*    createStreaks(const osg::Vec4& color, osg::Vec3 p, float scale)  
  4. osg::Node*    createHalo(const osg::Vec4& color, osg::Vec3 p, float scale)  

由于需要得到视点位置等一些与相机有关的参数,因此将添加光晕的节点放在了相机的PreDrawCallback中,同时在Switch节点中判断当前光源是否被圆柱体遮挡:


[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1.     virtual void  operator() (const osg::Camera &camera) const    
  2.     {  
  3.         if(_isAdded)  
  4.             return;  
  5.         _isAdded = true;  
  6.   
  7.         g_SwitchNode = new osg::Switch;  
  8.         g_SwitchNode->setUpdateCallback(new SwitchNodeCallback);  
  9.   
  10.         osg::Vec3 eyePos = camera.getInverseViewMatrix().getTrans();  
  11.   
  12.         GLfloat Length = 0.0f;  
  13.         osg::Vec3 vLightSourceToCamera = eyePos - g_LightPosition;  
  14.         Length = vLightSourceToCamera.length();  
  15.         osg::Matrix viewMatrix = camera.getViewMatrix();  
  16.         osg::Vec3 diretion = osg::Vec3(viewMatrix(2, 0), viewMatrix(2,1), -viewMatrix(2,2));  
  17.         osg::Vec3 ptIntersect = diretion * Length;                
  18.         ptIntersect += eyePos;  
  19.         osg::Vec3 vLightSourceToIntersect = ptIntersect - g_LightPosition;    
  20.         Length = vLightSourceToIntersect.length();  
  21.         vLightSourceToIntersect.normalize();  
  22.   
  23.         osg::Group *renderGroup = new osg::Group;  
  24.         osg::Vec3 pt;  
  25. ......  
  26. }  

绘制光晕的位置与NeHe课程中一样。

此外在本课中与NeHe课程不同的另一个地方是:NeHe中使用的二次曲面生成的圆柱体上下地面是不存在的,但是在OSG中的Cylinder却包含上下地面,因此为了让光源可以出现,对圆柱体的位置和旋转方式进行了一些修改:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. osg::MatrixTransform *zoomMT = new osg::MatrixTransform;  
  2. zoomMT->setMatrix(osg::Matrix::translate(0, 0, -20));  
  3.   
  4. osg::MatrixTransform *rotXMT = new osg::MatrixTransform;  
  5. osg::MatrixTransform *rotYMT = new osg::MatrixTransform;  
  6. rotYMT->addUpdateCallback(new osg::AnimationPathCallback(osg::Vec3(3, 0, 0), osg::Y_AXIS, 0.3));  
  7. zoomMT->addChild(rotXMT);  
  8. rotXMT->addChild(rotYMT);  
  9. rotYMT->addChild(createCylinderNode());  

此外在OSG中相机操作和OpenGL不太相同,因此交互部分的代码尚未实现,希望读者可以进一步完善。

编译运行程序:


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

[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/ShapeDrawable>  
  13.   
  14. #include <osg/AnimationPath>  
  15. #include <osg/Viewport>  
  16. #include <osg/BlendFunc>  
  17. #include <osg/Texture2D>  
  18.   
  19. #include <osgUtil/IntersectVisitor>  
  20.   
  21.   
  22. osg::Vec3       g_LightPosition;  
  23. osgViewer::Viewer       *g_View = NULL;  
  24.   
  25. bool isLightPositionOccluder;  
  26.   
  27. osg::Group *g_Root;  
  28. osg::Switch *g_SwitchNode;  
  29.   
  30. //  
  31. //  
  32. //  
  33. osg::Node*  createBigGlow(const osg::Vec4& color, osg::Vec3 p, float scale)  
  34. {  
  35.     osg::Vec3 q[4];  
  36.   
  37.     q[0].x() = (p.x() - scale);                                       
  38.     q[0].y() = (p.y() - scale);  
  39.   
  40.     q[1].x() = (p.x() - scale);  
  41.     q[1].y() = (p.y() + scale);  
  42.   
  43.     q[2].x() = (p.x() + scale);  
  44.     q[2].y() = (p.y() - scale);  
  45.   
  46.     q[3].x() = (p.x() + scale);  
  47.     q[3].y() = (p.y() + scale);  
  48.   
  49.     osg::MatrixTransform *posMT = new osg::MatrixTransform;  
  50.     posMT->setMatrix(osg::Matrix::translate(p));  
  51.   
  52.     osg::MatrixTransform *rotMT = new osg::MatrixTransform;  
  53.       
  54.     osg::Geode *geode = new osg::Geode;  
  55.     osg::Geometry *geometry = new osg::Geometry;  
  56.     osg::Vec2Array *texArray = new osg::Vec2Array;  
  57.     osg::Vec2Array *vertexArray = new osg::Vec2Array;  
  58.     osg::Vec4Array *colorArray = new osg::Vec4Array;  
  59.   
  60.     colorArray->push_back(color);  
  61.   
  62.     vertexArray->push_back(osg::Vec2(q[0].x(), q[0].y()));  
  63.     vertexArray->push_back(osg::Vec2(q[1].x(), q[1].y()));  
  64.     vertexArray->push_back(osg::Vec2(q[2].x(), q[2].y()));  
  65.     vertexArray->push_back(osg::Vec2(q[3].x(), q[3].y()));  
  66.   
  67.     texArray->push_back(osg::Vec2(0.0f, 0.0f));  
  68.     texArray->push_back(osg::Vec2(0.0f, 1.0f));  
  69.     texArray->push_back(osg::Vec2(1.0f, 0.0f));  
  70.     texArray->push_back(osg::Vec2(1.0f, 1.0f));  
  71.   
  72.     geometry->setVertexArray(vertexArray);  
  73.     geometry->setColorArray(colorArray, osg::Array::BIND_OVERALL);  
  74.     geometry->setTexCoordArray(0, texArray, osg::Array::BIND_PER_VERTEX);  
  75.     geometry->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);  
  76.     geometry->getOrCreateStateSet()->setMode(GL_DEPTH_TEST, false);  
  77.     geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLE_STRIP, 0, vertexArray->size()));  
  78.       
  79.     osg::Texture2D *texture2D = new osg::Texture2D;  
  80.     texture2D->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);  
  81.     texture2D->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);  
  82.     texture2D->setImage(osgDB::readImageFile("Data/BigGlow3.bmp"));  
  83.       
  84.     osg::BlendFunc *blendFunc = new osg::BlendFunc(GL_SRC_ALPHA, GL_ONE);  
  85.   
  86.     geometry->getOrCreateStateSet()->setTextureAttributeAndModes(0, texture2D);  
  87.     geometry->getOrCreateStateSet()->setAttributeAndModes(blendFunc);  
  88.     geode->addDrawable(geometry);  
  89.   
  90.     posMT->addChild(rotMT);  
  91.     rotMT->addChild(geode);  
  92.   
  93.     return posMT;  
  94. }  
  95.   
  96.   
  97. osg::Node*  createGlow(const osg::Vec4& color, osg::Vec3 p, float scale)  
  98. {  
  99.     osg::Vec3 q[4];  
  100.   
  101.     q[0].x() = (p.x() - scale);                                       
  102.     q[0].y() = (p.y() - scale);  
  103.   
  104.     q[1].x() = (p.x() - scale);  
  105.     q[1].y() = (p.y() + scale);  
  106.   
  107.     q[2].x() = (p.x() + scale);  
  108.     q[2].y() = (p.y() - scale);  
  109.   
  110.     q[3].x() = (p.x() + scale);  
  111.     q[3].y() = (p.y() + scale);  
  112.   
  113.     osg::MatrixTransform *posMT = new osg::MatrixTransform;  
  114.     posMT->setMatrix(osg::Matrix::translate(p));  
  115.   
  116.     osg::MatrixTransform *rotMT = new osg::MatrixTransform;  
  117.   
  118.     osg::Geode *geode = new osg::Geode;  
  119.     osg::Geometry *geometry = new osg::Geometry;  
  120.     osg::Vec2Array *texArray = new osg::Vec2Array;  
  121.     osg::Vec2Array *vertexArray = new osg::Vec2Array;  
  122.     osg::Vec4Array *colorArray = new osg::Vec4Array;  
  123.   
  124.     colorArray->push_back(color);  
  125.   
  126.     vertexArray->push_back(osg::Vec2(q[0].x(), q[0].y()));  
  127.     vertexArray->push_back(osg::Vec2(q[1].x(), q[1].y()));  
  128.     vertexArray->push_back(osg::Vec2(q[2].x(), q[2].y()));  
  129.     vertexArray->push_back(osg::Vec2(q[3].x(), q[3].y()));  
  130.   
  131.     texArray->push_back(osg::Vec2(0.0f, 0.0f));  
  132.     texArray->push_back(osg::Vec2(0.0f, 1.0f));  
  133.     texArray->push_back(osg::Vec2(1.0f, 0.0f));  
  134.     texArray->push_back(osg::Vec2(1.0f, 1.0f));  
  135.   
  136.     geometry->setVertexArray(vertexArray);  
  137.     geometry->setColorArray(colorArray, osg::Array::BIND_OVERALL);  
  138.     geometry->setTexCoordArray(0, texArray, osg::Array::BIND_PER_VERTEX);  
  139.     geometry->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);  
  140.     geometry->getOrCreateStateSet()->setMode(GL_DEPTH_TEST, false);  
  141.     geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLE_STRIP, 0, vertexArray->size()));  
  142.   
  143.     osg::Texture2D *texture2D = new osg::Texture2D;  
  144.     texture2D->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);  
  145.     texture2D->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);  
  146.     texture2D->setImage(osgDB::readImageFile("Data/HardGlow2.bmp"));  
  147.   
  148.     osg::BlendFunc *blendFunc = new osg::BlendFunc(GL_SRC_ALPHA, GL_ONE);  
  149.   
  150.     geometry->getOrCreateStateSet()->setTextureAttributeAndModes(0, texture2D);  
  151.     geometry->getOrCreateStateSet()->setAttributeAndModes(blendFunc);  
  152.     geode->addDrawable(geometry);  
  153.   
  154.     posMT->addChild(rotMT);  
  155.     rotMT->addChild(geode);  
  156.   
  157.     return posMT;  
  158. }  
  159.   
  160.   
  161. osg::Node*  createStreaks(const osg::Vec4& color, osg::Vec3 p, float scale)  
  162. {  
  163.     osg::Vec3 q[4];  
  164.   
  165.     q[0].x() = (p.x() - scale);                                       
  166.     q[0].y() = (p.y() - scale);  
  167.   
  168.     q[1].x() = (p.x() - scale);  
  169.     q[1].y() = (p.y() + scale);  
  170.   
  171.     q[2].x() = (p.x() + scale);  
  172.     q[2].y() = (p.y() - scale);  
  173.   
  174.     q[3].x() = (p.x() + scale);  
  175.     q[3].y() = (p.y() + scale);  
  176.   
  177.     osg::MatrixTransform *posMT = new osg::MatrixTransform;  
  178.     posMT->setMatrix(osg::Matrix::translate(p));  
  179.   
  180.     osg::MatrixTransform *rotMT = new osg::MatrixTransform;  
  181.   
  182.     osg::Geode *geode = new osg::Geode;  
  183.     osg::Geometry *geometry = new osg::Geometry;  
  184.     osg::Vec2Array *texArray = new osg::Vec2Array;  
  185.     osg::Vec2Array *vertexArray = new osg::Vec2Array;  
  186.     osg::Vec4Array *colorArray = new osg::Vec4Array;  
  187.   
  188.     colorArray->push_back(color);  
  189.   
  190.     vertexArray->push_back(osg::Vec2(q[0].x(), q[0].y()));  
  191.     vertexArray->push_back(osg::Vec2(q[1].x(), q[1].y()));  
  192.     vertexArray->push_back(osg::Vec2(q[2].x(), q[2].y()));  
  193.     vertexArray->push_back(osg::Vec2(q[3].x(), q[3].y()));  
  194.   
  195.     texArray->push_back(osg::Vec2(0.0f, 0.0f));  
  196.     texArray->push_back(osg::Vec2(0.0f, 1.0f));  
  197.     texArray->push_back(osg::Vec2(1.0f, 0.0f));  
  198.     texArray->push_back(osg::Vec2(1.0f, 1.0f));  
  199.   
  200.     geometry->setVertexArray(vertexArray);  
  201.     geometry->setColorArray(colorArray, osg::Array::BIND_OVERALL);  
  202.     geometry->setTexCoordArray(0, texArray, osg::Array::BIND_PER_VERTEX);  
  203.     geometry->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);  
  204.     geometry->getOrCreateStateSet()->setMode(GL_DEPTH_TEST, false);  
  205.     geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLE_STRIP, 0, vertexArray->size()));  
  206.   
  207.     osg::Texture2D *texture2D = new osg::Texture2D;  
  208.     texture2D->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);  
  209.     texture2D->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);  
  210.     texture2D->setImage(osgDB::readImageFile("Data/Streaks4.bmp"));  
  211.   
  212.     osg::BlendFunc *blendFunc = new osg::BlendFunc(GL_SRC_ALPHA, GL_ONE);  
  213.   
  214.     geometry->getOrCreateStateSet()->setTextureAttributeAndModes(0, texture2D);  
  215.     geometry->getOrCreateStateSet()->setAttributeAndModes(blendFunc);  
  216.     geode->addDrawable(geometry);  
  217.   
  218.     posMT->addChild(rotMT);  
  219.     rotMT->addChild(geode);  
  220.   
  221.     return posMT;  
  222. }  
  223.   
  224.   
  225. osg::Node*  createHalo(const osg::Vec4& color, osg::Vec3 p, float scale)  
  226. {  
  227.     osg::Vec3 q[4];  
  228.   
  229.     q[0].x() = (p.x() - scale);                                       
  230.     q[0].y() = (p.y() - scale);  
  231.   
  232.     q[1].x() = (p.x() - scale);  
  233.     q[1].y() = (p.y() + scale);  
  234.   
  235.     q[2].x() = (p.x() + scale);  
  236.     q[2].y() = (p.y() - scale);  
  237.   
  238.     q[3].x() = (p.x() + scale);  
  239.     q[3].y() = (p.y() + scale);  
  240.   
  241.     osg::MatrixTransform *posMT = new osg::MatrixTransform;  
  242.     posMT->setMatrix(osg::Matrix::translate(p));  
  243.   
  244.     osg::MatrixTransform *rotMT = new osg::MatrixTransform;  
  245.   
  246.     osg::Geode *geode = new osg::Geode;  
  247.     osg::Geometry *geometry = new osg::Geometry;  
  248.     osg::Vec2Array *texArray = new osg::Vec2Array;  
  249.     osg::Vec2Array *vertexArray = new osg::Vec2Array;  
  250.     osg::Vec4Array *colorArray = new osg::Vec4Array;  
  251.   
  252.     colorArray->push_back(color);  
  253.   
  254.     vertexArray->push_back(osg::Vec2(q[0].x(), q[0].y()));  
  255.     vertexArray->push_back(osg::Vec2(q[1].x(), q[1].y()));  
  256.     vertexArray->push_back(osg::Vec2(q[2].x(), q[2].y()));  
  257.     vertexArray->push_back(osg::Vec2(q[3].x(), q[3].y()));  
  258.   
  259.     texArray->push_back(osg::Vec2(0.0f, 0.0f));  
  260.     texArray->push_back(osg::Vec2(0.0f, 1.0f));  
  261.     texArray->push_back(osg::Vec2(1.0f, 0.0f));  
  262.     texArray->push_back(osg::Vec2(1.0f, 1.0f));  
  263.   
  264.     geometry->setVertexArray(vertexArray);  
  265.     geometry->setColorArray(colorArray, osg::Array::BIND_OVERALL);  
  266.     geometry->setTexCoordArray(0, texArray, osg::Array::BIND_PER_VERTEX);  
  267.     geometry->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);  
  268.     geometry->getOrCreateStateSet()->setMode(GL_DEPTH_TEST, false);  
  269.     geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLE_STRIP, 0, vertexArray->size()));  
  270.   
  271.     osg::Texture2D *texture2D = new osg::Texture2D;  
  272.     texture2D->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);  
  273.     texture2D->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);  
  274.     texture2D->setImage(osgDB::readImageFile("Data/Halo3.bmp"));  
  275.   
  276.     osg::BlendFunc *blendFunc = new osg::BlendFunc(GL_SRC_ALPHA, GL_ONE);  
  277.   
  278.     geometry->getOrCreateStateSet()->setTextureAttributeAndModes(0, texture2D);  
  279.     geometry->getOrCreateStateSet()->setAttributeAndModes(blendFunc);  
  280.     geode->addDrawable(geometry);  
  281.   
  282.     posMT->addChild(rotMT);  
  283.     rotMT->addChild(geode);  
  284.   
  285.     return posMT;  
  286. }  
  287.   
  288. //  
  289. //想法一中的判断遮挡方式:原理与NeHe课程中的一样  
  290. //  
  291. //class TestOccludeCallback : public osg::Camera::DrawCallback  
  292. //{  
  293. //public:  
  294. //  virtual void  operator() (const osg::Camera &camera) const    
  295. //  {  
  296. //      osg::Matrix viewMatrix = camera.getViewMatrix();  
  297. //      osg::Matrix proMatrix = camera.getProjectionMatrix();  
  298. //      osg::Matrix vpMatrix = camera.getViewport()->computeWindowMatrix();  
  299. //  
  300. //      osg::Vec3 winPos = g_LightPosition * viewMatrix * proMatrix * vpMatrix;  
  301. //  
  302. //      double flareZ = winPos.z();  
  303. //  
  304. //      osg::Image *image = new osg::Image;  
  305. //      image->readPixels(winPos.x(), winPos.y(), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT);  
  306. //      float *bufferZ = reinterpret_cast<float*>(image->data());  
  307. //  
  308. //      if (*bufferZ < flareZ)  
  309. //          isLightPositionOccluder = true;  
  310. //      else  
  311. //          isLightPositionOccluder = false;  
  312. //  }  
  313. //};  
  314.   
  315.   
  316. osg::Node*  createCylinderNode()  
  317. {  
  318.     osg::MatrixTransform *zoomMT = new osg::MatrixTransform;  
  319.     zoomMT->setMatrix(osg::Matrix::translate(0, 0, -2));  
  320.   
  321.     osg::Geode *cylinder = new osg::Geode;  
  322.     osg::ShapeDrawable *cylinderDrawable = new osg::ShapeDrawable(new osg::Cylinder(osg::Vec3(0,0,0), 0.5, 4.0));  
  323.     cylinderDrawable->setColor(osg::Vec4(0,0,1,1));  
  324.     cylinder->addDrawable(cylinderDrawable);  
  325.       
  326.     zoomMT->addChild(cylinder);  
  327.   
  328.     return zoomMT;  
  329. }  
  330.   
  331. //想法一:在绘制场景之前,先使用PRE_RENDER的方式  
  332. //绘制圆柱体,同时进行遮挡判断  
  333. //TODO:需要调整窗口位置才能正确显示,目前未找到原因???  
  334. //osg::Camera*  createRenderToTextureCamera(int w, int h)  
  335. //{  
  336. //  osg::Camera *rtt = new osg::Camera;  
  337. //  rtt->setClearColor(osg::Vec4(0.0f, 0.0f, 0.0f, 0.5));      
  338. //  rtt->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  
  339. //  rtt->setReferenceFrame(osg::Transform::ABSOLUTE_RF);  
  340. //  rtt->setViewport(0, 0, w, h);  
  341. //  rtt->setRenderOrder(osg::Camera::PRE_RENDER);  
  342. //  rtt->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);  
  343. //  rtt->setProjectionMatrixAsPerspective(45.0f, static_cast<double>(640)/static_cast<double>(480), 1.0f, 1000.0f );  
  344. //  rtt->setViewMatrixAsLookAt(osg::Vec3d(0, 0, 0), osg::Vec3d(0, 0, -1), osg::Vec3d(0, 1, 0));  
  345. //  
  346. //  osg::MatrixTransform *zoomMT = new osg::MatrixTransform;  
  347. //  zoomMT->setMatrix(osg::Matrix::translate(0, 0, -20));  
  348. //  
  349. //  osg::MatrixTransform *rotXMT = new osg::MatrixTransform;  
  350. //  osg::MatrixTransform *rotYMT = new osg::MatrixTransform;  
  351. //  rotYMT->addUpdateCallback(new osg::AnimationPathCallback(osg::Vec3(3, 0, 0), osg::Y_AXIS, 0.3));  
  352. //  
  353. //  zoomMT->addChild(rotXMT);  
  354. //  rotXMT->addChild(rotYMT);  
  355. //  rotYMT->addChild(createCylinderNode());  
  356. //  
  357. //  rtt->addChild(zoomMT);  
  358. //  
  359. //  rtt->setPostDrawCallback(new TestOccludeCallback);  
  360. //  
  361. //  return rtt;  
  362. //}  
  363.   
  364.   
  365. class SwitchNodeCallback : public osg::NodeCallback  
  366. {  
  367. public:  
  368.     virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)  
  369.     {  
  370.         osg::Switch *s = dynamic_cast<osg::Switch*>(node);  
  371.         if (!s)  
  372.             return;  
  373.         if(!g_View)  
  374.             return;  
  375.         osg::Camera *camera = g_View->getCamera();  
  376.         if(!camera)  
  377.             return;  
  378.   
  379.         osg::Vec3 eyePos = camera->getInverseViewMatrix().getTrans();  
  380.           
  381.         osgUtil::LineSegmentIntersector *intersector = new osgUtil::LineSegmentIntersector(eyePos, g_LightPosition);  
  382.         osgUtil::IntersectionVisitor intersectVisitor(intersector);  
  383.         g_Root->accept(intersectVisitor);  
  384.   
  385.         if(intersector->containsIntersections())  
  386.             g_SwitchNode->setAllChildrenOff();  
  387.         else  
  388.             g_SwitchNode->setAllChildrenOn();  
  389.     }  
  390. };  
  391.   
  392.   
  393. class LensFlareCallback : public osg::Camera::DrawCallback  
  394. {  
  395. public:  
  396.     LensFlareCallback() : _isAdded(false){}  
  397.   
  398.     virtual void  operator() (const osg::Camera &camera) const    
  399.     {  
  400.         if(_isAdded)  
  401.             return;  
  402.         _isAdded = true;  
  403.   
  404.         g_SwitchNode = new osg::Switch;  
  405.         g_SwitchNode->setUpdateCallback(new SwitchNodeCallback);  
  406.   
  407.         osg::Vec3 eyePos = camera.getInverseViewMatrix().getTrans();  
  408.   
  409.         GLfloat Length = 0.0f;  
  410.         osg::Vec3 vLightSourceToCamera = eyePos - g_LightPosition;  
  411.         Length = vLightSourceToCamera.length();  
  412.         osg::Matrix viewMatrix = camera.getViewMatrix();  
  413.         osg::Vec3 diretion = osg::Vec3(viewMatrix(2, 0), viewMatrix(2,1), -viewMatrix(2,2));  
  414.         osg::Vec3 ptIntersect = diretion * Length;                
  415.         ptIntersect += eyePos;  
  416.         osg::Vec3 vLightSourceToIntersect = ptIntersect - g_LightPosition;    
  417.         Length = vLightSourceToIntersect.length();  
  418.         vLightSourceToIntersect.normalize();  
  419.   
  420.         osg::Group *renderGroup = new osg::Group;  
  421.         osg::Vec3 pt;  
  422.   
  423.         renderGroup->addChild(createBigGlow(osg::Vec4(0.60f, 0.60f, 0.8f, 1.0f), g_LightPosition, 16.0f));  
  424.         renderGroup->addChild(createStreaks(osg::Vec4(0.60f, 0.60f, 0.8f, 1.0f), g_LightPosition, 16.0f));  
  425.         renderGroup->addChild(createGlow(osg::Vec4(0.8f, 0.8f, 1.0f, 0.5f), g_LightPosition, 3.5f));  
  426.   
  427.         pt = vLightSourceToIntersect * (Length * 0.1f);             // Lets compute a point that is 20%  
  428.         pt += g_LightPosition;                                      // away from the light source in the  
  429.         renderGroup->addChild(createGlow(osg::Vec4(0.9f, 0.6f, 0.4f, 0.5f), pt, 0.6f));  
  430.   
  431.         pt = vLightSourceToIntersect * (Length * 0.15f);            // Lets compute a point that is 30%  
  432.         pt += g_LightPosition;                                      // away from the light source in the      
  433.         renderGroup->addChild(createHalo(osg::Vec4(0.8f, 0.5f, 0.6f, 0.5f), pt, 1.7f));  
  434.   
  435.         pt = vLightSourceToIntersect * (Length * 0.175f);           // Lets compute a point that is 35%  
  436.         pt += g_LightPosition;                                      // away from the light source in the  
  437.         renderGroup->addChild(createHalo(osg::Vec4(0.9f, 0.2f, 0.1f, 0.5f), pt, 0.83f));  
  438.   
  439.         pt = vLightSourceToIntersect * (Length * 0.285f);           // Lets compute a point that is 57%  
  440.         pt += g_LightPosition;                                      // away from the light source in the  
  441.         renderGroup->addChild(createHalo(osg::Vec4(0.7f, 0.7f, 0.4f, 0.5f), pt, 1.6f));  
  442.   
  443.         pt = vLightSourceToIntersect * (Length * 0.2755f);          // Lets compute a point that is 55.1%  
  444.         pt += g_LightPosition;                                      // away from the light source in the  
  445.         renderGroup->addChild(createGlow(osg::Vec4(0.9f, 0.9f, 0.2f, 0.5f), pt, 0.8f));  
  446.   
  447.         pt = vLightSourceToIntersect * (Length * 0.4775f);          // Lets compute a point that is 95.5%  
  448.         pt += g_LightPosition;                                      // away from the light source in the  
  449.         renderGroup->addChild(createGlow(osg::Vec4(0.93f, 0.82f, 0.73f, 0.5f), pt, 1.0f));  
  450.   
  451.         pt = vLightSourceToIntersect * (Length * 0.49f);            // Lets compute a point that is 98%  
  452.         pt += g_LightPosition;                                      // away from the light source in the  
  453.         renderGroup->addChild(createHalo(osg::Vec4(0.7f, 0.6f, 0.5f, 0.5f), pt, 1.4f));  
  454.   
  455.         pt = vLightSourceToIntersect * (Length * 0.65f);            // Lets compute a point that is 130%  
  456.         pt += g_LightPosition;                                      // away from the light source in the  
  457.         renderGroup->addChild(createGlow(osg::Vec4(0.7f, 0.8f, 0.3f, 0.5f), pt, 1.8f));  
  458.   
  459.   
  460.         pt = vLightSourceToIntersect * (Length * 0.63f);            // Lets compute a point that is 126%  
  461.         pt += g_LightPosition;                                      // away from the light source in the  
  462.         renderGroup->addChild(createGlow(osg::Vec4(0.4f, 0.3f, 0.2f, 0.5f), pt, 1.4f));  
  463.   
  464.   
  465.         pt = vLightSourceToIntersect * (Length * 0.8f);             // Lets compute a point that is 160%  
  466.         pt += g_LightPosition;                                      // away from the light source in the  
  467.         renderGroup->addChild(createHalo(osg::Vec4(0.7f, 0.5f, 0.5f, 0.5f), pt, 1.4f));  
  468.   
  469.   
  470.         pt = vLightSourceToIntersect * (Length * 0.7825f);          // Lets compute a point that is 156.5%  
  471.         pt += g_LightPosition;                                      // away from the light source in the  
  472.         renderGroup->addChild(createGlow(osg::Vec4(0.8f, 0.5f, 0.1f, 0.5f), pt, 0.6f));  
  473.   
  474.   
  475.         pt = vLightSourceToIntersect * (Length * 1.0f);  
  476.         pt += g_LightPosition;    
  477.         renderGroup->addChild(createHalo(osg::Vec4(0.5f, 0.5f, 0.7f, 0.5f), pt, 1.7f));  
  478.   
  479.   
  480.         pt = vLightSourceToIntersect * (Length * 0.975f);  
  481.         pt += g_LightPosition;    
  482.         renderGroup->addChild(createGlow(osg::Vec4(0.4f, 0.1f, 0.9f, 0.5f), pt, 2.0f));  
  483.   
  484.         g_SwitchNode->addChild(renderGroup);  
  485.   
  486.         g_Root->addChild(g_SwitchNode);  
  487.     }  
  488.   
  489.     mutable bool _isAdded;  
  490. };  
  491.   
  492.   
  493. //  
  494. class ManipulatorSceneHandler : public osgGA::GUIEventHandler  
  495. {  
  496. public:  
  497.     ManipulatorSceneHandler()  
  498.     {  
  499.     }  
  500.   
  501. public:  
  502.     virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)  
  503.     {  
  504.         osgViewer::View *viewer = dynamic_cast<osgViewer::View*>(&aa);  
  505.         if (!viewer)  
  506.             return false;  
  507.         if (!viewer->getSceneData())  
  508.             return false;  
  509.         if (ea.getHandled())   
  510.             return false;  
  511.   
  512.         osg::Group *root = viewer->getSceneData()->asGroup();  
  513.   
  514.         switch(ea.getEventType())  
  515.         {  
  516.         case (osgGA::GUIEventAdapter::FRAME):  
  517.             {  
  518.                 osg::Vec3 eye, center, up;  
  519.                 viewer->getCamera()->getViewMatrixAsLookAt(eye, center, up);  
  520.                 g_LightPosition.z() = eye.z() - 50.0f;  
  521.             }     
  522.             break;  
  523.         case(osgGA::GUIEventAdapter::KEYDOWN):  
  524.             {     
  525.                 if (ea.getKey() == osgGA::GUIEventAdapter::KEY_W)  
  526.                 {  
  527.                     //TODO:OSG中相机的变换和OpenGL中不一致  
  528.                 }  
  529.                 if (ea.getKey() == osgGA::GUIEventAdapter::KEY_S)  
  530.                 {  
  531.   
  532.                 }  
  533.                 if (ea.getKey() == osgGA::GUIEventAdapter::KEY_A)  
  534.                 {  
  535.   
  536.                 }  
  537.                 if (ea.getKey() == osgGA::GUIEventAdapter::KEY_D)  
  538.                 {  
  539.   
  540.                 }  
  541.             }  
  542.             break;  
  543.   
  544.         defaultbreak;  
  545.         }  
  546.         return false;  
  547.     }  
  548. };  
  549.   
  550.   
  551. //  
  552.   
  553.   
  554.   
  555. class ViewerWidget : public QWidget, public osgViewer::Viewer  
  556. {  
  557. public:  
  558.     ViewerWidget(osg::Node *scene = NULL)  
  559.     {  
  560.         QWidget* renderWidget = getRenderWidget( createGraphicsWindow(0,0,640,480), scene);  
  561.           
  562.         QVBoxLayout* layout = new QVBoxLayout;  
  563.         layout->addWidget(renderWidget);  
  564.         layout->setContentsMargins(0, 0, 0, 1);  
  565.         setLayout( layout );  
  566.   
  567.         connect( &_timer, SIGNAL(timeout()), this, SLOT(update()) );  
  568.         _timer.start( 10 );  
  569.     }  
  570.   
  571.     QWidget* getRenderWidget( osgQt::GraphicsWindowQt* gw, osg::Node* scene )  
  572.     {  
  573.         osg::Camera* camera = this->getCamera();  
  574.         camera->setGraphicsContext( gw );  
  575.   
  576.         const osg::GraphicsContext::Traits* traits = gw->getTraits();  
  577.   
  578.         camera->setClearColor( osg::Vec4(0.0, 0.0, 0.0, 0.5) );  
  579.         camera->setViewport( new osg::Viewport(0, 0, traits->width, traits->height) );  
  580.         camera->setProjectionMatrixAsPerspective(45.0f, static_cast<double>(traits->width)/static_cast<double>(traits->height), 1.0f, 1000.0f );  
  581.         camera->setViewMatrixAsLookAt(osg::Vec3d(0, 0, 0), osg::Vec3d(0, 0, -1), osg::Vec3d(0, 1, 0));  
  582.         camera->setClearDepth(1.0f);  
  583.           
  584.         camera->setPreDrawCallback(new LensFlareCallback);  
  585.           
  586.         g_View = this;  
  587.   
  588.         this->setSceneData( scene );  
  589.         this->addEventHandler(new ManipulatorSceneHandler);  
  590.       
  591.         return gw->getGLWidget();  
  592.     }  
  593.   
  594.     osgQt::GraphicsWindowQt* createGraphicsWindow( int x, int y, int w, int h, const std::string& name=""bool windowDecoration=false )  
  595.     {  
  596.         osg::DisplaySettings* ds = osg::DisplaySettings::instance().get();  
  597.         osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;  
  598.         traits->windowName = name;  
  599.         traits->windowDecoration = windowDecoration;  
  600.         traits->x = x;  
  601.         traits->y = y;  
  602.         traits->width = w;  
  603.         traits->height = h;  
  604.         traits->doubleBuffer = true;  
  605.         traits->alpha = ds->getMinimumNumAlphaBits();  
  606.         traits->stencil = ds->getMinimumNumStencilBits();  
  607.         traits->sampleBuffers = ds->getMultiSamples();  
  608.         traits->samples = ds->getNumMultiSamples();  
  609.   
  610.         return new osgQt::GraphicsWindowQt(traits.get());  
  611.     }  
  612.   
  613.     virtual void paintEvent( QPaintEvent* event )  
  614.     {   
  615.         frame();   
  616.     }  
  617.   
  618. protected:  
  619.   
  620.     QTimer _timer;  
  621. };  
  622.   
  623.   
  624.   
  625. osg::Node*  buildScene()  
  626. {  
  627.     osg::Group *root = new osg::Group;  
  628.     g_Root = root;  
  629.   
  630.     osg::MatrixTransform *zoomMT = new osg::MatrixTransform;  
  631.     zoomMT->setMatrix(osg::Matrix::translate(0, 0, -20));  
  632.   
  633.     osg::MatrixTransform *rotXMT = new osg::MatrixTransform;  
  634.     osg::MatrixTransform *rotYMT = new osg::MatrixTransform;  
  635.     rotYMT->addUpdateCallback(new osg::AnimationPathCallback(osg::Vec3(3, 0, 0), osg::Y_AXIS, 0.3));  
  636.     zoomMT->addChild(rotXMT);  
  637.     rotXMT->addChild(rotYMT);  
  638.     rotYMT->addChild(createCylinderNode());  
  639.   
  640.   
  641.     root->addChild(zoomMT);  
  642.     return root;  
  643. }  
  644.   
  645.   
  646.   
  647. int main( int argc, char** argv )  
  648. {  
  649.     QApplication app(argc, argv);  
  650.     ViewerWidget* viewWidget = new ViewerWidget(buildScene());  
  651.     viewWidget->setGeometry( 100, 100, 640, 481 );  
  652.     viewWidget->show();  
  653.     return app.exec();  
  654. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值