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

来源:互联网 发布:淘宝的洗衣机中国质造 编辑:程序博客网 时间:2024/06/09 21:35
  • 简介

这节课我们将讨论凹凸纹理技术,使用凹凸纹理可以让物体表面更有质感。本节课实现的其实是一种被称为浮雕纹理的技术(Emboss Bump Mapping),并不能算真正的凹凸纹理实现方式(It is a Hack)。

光滑的表面它上面各点法线的方向是一致的,凹凸纹理通过扰乱它表面的法线方向,在进行光照计算的时候(像素光照计算)会使得光滑表面产生明暗不同的颜色,从而"欺骗"我们的大脑,让我们以为它的表面是凹凸不平的。凹凸纹理最早是由James F. Blinn在1978年提的

NeHe课程中的实现原理可以参考凹凸纹理随笔, 在开始之前先说明一下NeHe课程中的实现方式:

NeHe教程中通过空格切换在三种模式下进行:

1. 未使用多重纹理(MultiTexture)技术进行凹凸纹理处理

2.使用多重纹理(MultiTexture)技术进行凹凸纹理处理

3.渲染不带凹凸纹理的场景

这三个过程分别对应doMesh1TexelUnits、doMesh1Texe2Units、doMeshNoBumps三个函数。本课只实现了在1情形下的凹凸纹理。2的实现也在源码中,但是未找到对应的OpenGL API,希望知道的读者指点一二。

下面简单说一下Emboss Bump Mapping的实现过程:

浮雕纹理需要对模型表面贴两次纹理,第一次纹理的纹理坐标不进行偏移、第二次的纹理坐标会在光照方向上进行偏移。偏移量的计算方法可以参考PPT Emboss Bump Mapping

  • 实现

首先和NeHe教程一下初始化我们需要的纹理:

这里面需要使用osg中的Image类和处理Image的ImageUtil中的内容:部分代码如下:

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. osg::Image *image1 = new osg::Image;  
  2. image1 = osgDB::readImageFile("Data/Base.bmp");  
  3.   
  4. texture[0] = new osg::Texture2D;  
  5. texture[0]->setFilter(osg::Texture::MAG_FILTER, osg::Texture::NEAREST);  
  6. texture[0]->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST);  
  7. texture[0]->setImage(image1);  
  8.   
  9. texture[1] = new osg::Texture2D;  
  10. texture[1]->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);  
  11. texture[1]->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);  
  12. texture[1]->setImage(image1);  
另外我们需要把进行纹理贴图的图像亮度减半,代码如下:

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. osg::Image *image2 = new osg::Image;  
  2. image2 = osgDB::readImageFile("Data/Bump.bmp");  
  3. osg::offsetAndScaleImage(image2, osg::Vec4(), osg::Vec4(0.5, 0.5, 0.5, 1)); // RGB值都减半  
  4.   
  5. bump[0] = new osg::Texture2D;  
  6. bump[0]->setFilter(osg::Texture::MAG_FILTER, osg::Texture::NEAREST);  
  7. bump[0]->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST);  
  8. bump[0]->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP);  
  9. bump[0]->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP);  
  10. bump[0]->setBorderColor(osg::Vec4(0.5, 0.5, 0.5, 1.0));  
  11. bump[0]->setImage(image2);  
此外反转图像RGB值,使得凹的纹理变成凸的纹理:

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. osg::Image *image3 = osgDB::readImageFile("Data/Bump.bmp");  
  2. osg::offsetAndScaleImage(image3, osg::Vec4(), osg::Vec4(0.5,0.5,0.5,1));  
  3. osg::offsetAndScaleImage(image3, osg::Vec4(-128, -128, -128, 1), osg::Vec4(-1,-1,-1,1));  
  4.   
  5. invbump[0] = new osg::Texture2D;  
  6. invbump[0]->setFilter(osg::Texture::MAG_FILTER, osg::Texture::NEAREST);  
  7. invbump[0]->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST);  
  8. invbump[0]->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP);  
  9. invbump[0]->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP);  
  10. invbump[0]->setBorderColor(osg::Vec4(0.5, 0.5, 0.5, 1.0));  
  11. invbump[0]->setImage(image3);  
创建正常显示立方体的代码在createCube函数中。

为了进行凹凸纹理,我们先设置第一次纹理部分,代码如下:

可以看到这一次贴的纹理的纹理坐标并没有偏移,全部用到了data中的原始数据

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. osg::Geode* createUpMappingCube()  
  2. {  
  3.     osg::Geode *cubeGeode = new osg::Geode;  
  4.     osg::Geometry *cubeGeometry = new osg::Geometry;  
  5.   
  6.     osg::Vec3Array *vertices = new osg::Vec3Array;  
  7.     osg::Vec3Array *normals = new osg::Vec3Array;  
  8.     osg::Vec2Array *texcoords = new osg::Vec2Array;  
  9.   
  10.     for (unsigned i = 0; i < 24; ++i)  
  11.     {  
  12.         texcoords->push_back(osg::Vec2(data[5*i],data[5*i + 1]));  //第一次贴纹理不需要偏移  
  13.         vertices->push_back(osg::Vec3(data[5*i + 2], data[5*i +3], data[5*i + 4]));  
  14.     }  
  15.   
  16.     cubeGeometry->setVertexArray(vertices);  
  17.     cubeGeometry->setTexCoordArray(0, texcoords);  
  18.     cubeGeometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, vertices->size()));  
  19.     cubeGeometry->getOrCreateStateSet()->setMode(GL_LIGHTING, false);  
  20.     cubeGeometry->getOrCreateStateSet()->setTextureAttributeAndModes(0, bump[1]);  
  21.     osg::Depth *depth = new osg::Depth(osg::Depth::LEQUAL);  
  22.     cubeGeometry->getOrCreateStateSet()->setAttributeAndModes(depth);  
  23.     cubeGeode->addDrawable(cubeGeometry);  
  24.     return cubeGeode;  
  25. }  
在进行第二次贴纹理时由于要把光源位置变换到物体表面的切空间中,需要获取此时模型的模型视图矩阵,在设置中难以获得,在回调中获取:

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. //第二次贴纹理,这里面并没有纹理坐标,因为纹理坐标需要偏移,在回调中计算  
  2. osg::Geode* createDownMappingCube()  
  3. {  
  4.     osg::Geode *cubeGeode = new osg::Geode;  
  5.     osg::Geometry *cubeGeometry = new osg::Geometry;  
  6.     cubeGeometry->setUpdateCallback(new TextureCallback());  
  7.   
  8.     osg::Vec3Array *vertices = new osg::Vec3Array;  
  9.   
  10.     for (unsigned i = 0; i < 24; ++i)  
  11.     {  
  12.         vertices->push_back(osg::Vec3(data[5*i + 2], data[5*i +3], data[5*i + 4]));  
  13.     }  
  14.   
  15.     cubeGeometry->setVertexArray(vertices);  
  16.     cubeGeometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, vertices->size()));  
  17.   
  18.     cubeGeode->addDrawable(cubeGeometry);  
  19.     return cubeGeode;  
  20. }  

接下来看看回调实现:(只给出部分代码)

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. virtual void update(osg::NodeVisitor* nv, osg::Drawable* drawable)  
  2. {  
  3.     osg::Geometry *geometry = drawable->asGeometry();  
  4.     if (!geometry)  
  5.         return;  
  6.   
  7.     osg::Vec2Array *textureArray = dynamic_cast<osg::Vec2Array*>(geometry->getTexCoordArray(0));  
  8.     if(textureArray)  
  9.         return;  
  10.     textureArray = new osg::Vec2Array;  
  11.   
  12.     osg::Vec3Array *vertices = dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray());  
  13.   
  14.     osg::Vec3 lightPos(LightPosition[0], LightPosition[1], LightPosition[2]);  
  15.               //获取当前模型视图矩阵  
  16.     osg::Matrix currentModelViewMatrix = computeLocalToWorld(nv->getNodePath()) * g_viewer->getCamera()->getViewMatrix();  
  17.     //反转模型视图矩阵  
  18.                osg::Matrix currentInvModelViewerMatrix = osg::Matrix::inverse(currentModelViewMatrix);  
  19.     //将光源变换到物体建模坐标系下  
  20.                osg::Vec3 lightInObjectSpace = lightPos * currentInvModelViewerMatrix;  
  21.   
  22. /////////////////////////////////////////////////////////////////////////  
  23.     for (int i=0; i<4; i++) {  
  24.         osg::Vec3 pos = vertices->at(i);  
  25.         osg::Vec3 orientation = lightInObjectSpace - pos;  
  26.         orientation.normalize();  
  27.                        //获取切空间中在S、T轴上的偏移量  
  28.                        double deltaS = orientation * osg::Vec3(1,0,0) * MaxEmboss;  
  29.         double deltaT = orientation * osg::Vec3(0,1,0) * MaxEmboss;  
  30.         textureArray->push_back(osg::Vec2(data[5*i]+deltaS,data[5*i + 1]+deltaT));  
  31.     }  
最后把这三次的结果添加到场景中
[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. osg::Switch *switchNode = new osg::Switch;  
  2. g_switch = switchNode;  
  3. rotateYAxis->addChild(switchNode);  
  4. switchNode->addChild(createUpMappingCube());  
  5. switchNode->addChild(createDownMappingCube());  
  6. switchNode->addChild(createCube());  
在交互操作中设置显示和隐藏原始的模型:

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. if (ea.getKey() == osgGA::GUIEventAdapter::KEY_E)  
  2. {  
  3.     if (g_switch->getValue(2) == true)  
  4.     {  
  5.         g_switch->setValue(2, false);  
  6.     }  
  7.     else  
  8.     {  
  9.         g_switch->setValue(2, true);   
  10.     }  
  11. }  
编译运行程序:


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

[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/LightSource>  
  13.   
  14. #include <osg/ImageUtils>  
  15. #include <osg/Texture2D>  
  16.   
  17. #include <osg/BlendFunc>  
  18. #include <osg/Depth>  
  19. #include <osg/TexEnv>  
  20. #include <osg/TexEnvCombine>  
  21. //////////////////////////////////////////////////////////////////////////  
  22.   
  23. const float MaxEmboss = 0.008f;  
  24.   
  25. bool    multitextureSupported = false;  
  26. bool useMultitexture = true;  
  27.   
  28. osgViewer::View *g_viewer;  
  29. osg::Switch *g_switch;  
  30. osg::Switch *g_switchMulti;  
  31.   
  32. GLfloat xrot;                                                 
  33. GLfloat yrot;                                                 
  34. GLfloat xspeed;                                           
  35. GLfloat yspeed;                                                       
  36. GLfloat z=-5.0f;      
  37.   
  38. GLuint  filter=1;     
  39.   
  40. osg::Texture2D  *texture[3];  
  41. osg::Texture2D  *bump[3];  
  42. osg::Texture2D  *invbump[3];  
  43. osg::Texture2D  *glLogo;  
  44. osg::Texture2D  *multiLogo;  
  45.   
  46. GLfloat LightAmbient[]  = { 0.2f, 0.2f, 0.2f};                        
  47. GLfloat LightDiffuse[]  = { 1.0f, 1.0f, 1.0f};                        
  48. GLfloat LightPosition[] = { 0.0f, 0.0f, 2.0f};  
  49.   
  50.   
  51. GLfloat data[]=   
  52. {  
  53.     // FRONT FACE  
  54.     0.0f, 0.0f,     -1.0f, -1.0f, +1.0f,  
  55.     1.0f, 0.0f,     +1.0f, -1.0f, +1.0f,  
  56.     1.0f, 1.0f,     +1.0f, +1.0f, +1.0f,  
  57.     0.0f, 1.0f,     -1.0f, +1.0f, +1.0f,  
  58.     // BACK FACE  
  59.     1.0f, 0.0f,     -1.0f, -1.0f, -1.0f,  
  60.     1.0f, 1.0f,     -1.0f, +1.0f, -1.0f,  
  61.     0.0f, 1.0f,     +1.0f, +1.0f, -1.0f,  
  62.     0.0f, 0.0f,     +1.0f, -1.0f, -1.0f,  
  63.     // Top Face  
  64.     0.0f, 1.0f,     -1.0f, +1.0f, -1.0f,  
  65.     0.0f, 0.0f,     -1.0f, +1.0f, +1.0f,  
  66.     1.0f, 0.0f,     +1.0f, +1.0f, +1.0f,  
  67.     1.0f, 1.0f,     +1.0f, +1.0f, -1.0f,  
  68.     // Bottom Face  
  69.     1.0f, 1.0f,     -1.0f, -1.0f, -1.0f,  
  70.     0.0f, 1.0f,     +1.0f, -1.0f, -1.0f,  
  71.     0.0f, 0.0f,     +1.0f, -1.0f, +1.0f,  
  72.     1.0f, 0.0f,     -1.0f, -1.0f, +1.0f,  
  73.     // Right Face  
  74.     1.0f, 0.0f,     +1.0f, -1.0f, -1.0f,  
  75.     1.0f, 1.0f,     +1.0f, +1.0f, -1.0f,  
  76.     0.0f, 1.0f,     +1.0f, +1.0f, +1.0f,  
  77.     0.0f, 0.0f,     +1.0f, -1.0f, +1.0f,  
  78.     // Left Face  
  79.     0.0f, 0.0f,     -1.0f, -1.0f, -1.0f,  
  80.     1.0f, 0.0f,     -1.0f, -1.0f,  1.0f,  
  81.     1.0f, 1.0f,     -1.0f,  1.0f,  1.0f,  
  82.     0.0f, 1.0f,     -1.0f,  1.0f, -1.0f  
  83. };  
  84.   
  85.   
  86. //////////////////////////////////////////////////////////////////////////  
  87. //FindFirstNamedNodeVisitor用来遍历寻找与指定名称相同的节点  
  88.   
  89. class FindFirstNamedNodeVisitor : public osg::NodeVisitor  
  90. {  
  91. public:  
  92.     FindFirstNamedNodeVisitor(const std::string& name):  
  93.       osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),  
  94.           _name(name), _foundNode(NULL) {}  
  95.   
  96.       virtual void apply(osg::Node& node)  
  97.       {  
  98.           if (node.getName()==_name)  
  99.           {  
  100.               _foundNode = &node;  
  101.               return;  
  102.           }  
  103.           traverse(node);  
  104.       }  
  105.   
  106.       std::string _name;  
  107.       osg::Node *_foundNode;  
  108. };  
  109.   
  110. //////////////////////////////////////////////////////////////////////////  
  111. //RotateCallback  
  112.   
  113. class RotateCallback : public osg::NodeCallback  
  114. {  
  115.   
  116. public:  
  117.     RotateCallback(osg::Vec3d rotateAxis, double rotateSpeed) :   
  118.       osg::NodeCallback(),  
  119.           _rotateAxis(rotateAxis),   
  120.           _rotateSpeed(rotateSpeed),  
  121.           _rotateAngle(0.0)  
  122.       {  
  123.           //Nop  
  124.       }  
  125.   
  126.       void setRotateSpeed(double speed)  
  127.       {  
  128.           _rotateSpeed = speed;  
  129.       }  
  130.   
  131.       double getRotateSpeed() const  
  132.       {  
  133.           return _rotateSpeed;  
  134.       }  
  135.   
  136.       virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)  
  137.       {  
  138.           osg::MatrixTransform *currentMT = dynamic_cast<osg::MatrixTransform*>(node);  
  139.           if (currentMT)  
  140.           {  
  141.               //获取当前的平移位置  
  142.               osg::Vec3d currentTranslate = currentMT->getMatrix().getTrans();  
  143.               osg::Matrix newMatrix = osg::Matrix::rotate(_rotateAngle, _rotateAxis) * osg::Matrix::translate(currentTranslate);  
  144.               currentMT->setMatrix(newMatrix);  
  145.               _rotateAngle += _rotateSpeed;  
  146.           }  
  147.   
  148.           traverse(node, nv);  
  149.       }  
  150.   
  151.   
  152. private:  
  153.     osg::Vec3d _rotateAxis;         //旋转轴  
  154.     double        _rotateSpeed;     //旋转速度  
  155.     double        _rotateAngle;     //当前旋转的角度  
  156. };  
  157.   
  158.   
  159. //////////////////////////////////////////////////////////////////////////  
  160. //////////////////////////////////////////////////////////////////////////  
  161.   
  162. class ManipulatorSceneHandler : public osgGA::GUIEventHandler  
  163. {  
  164. public:  
  165.     ManipulatorSceneHandler()  
  166.     {  
  167.     }  
  168.   
  169.     virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)  
  170.     {  
  171.         osgViewer::Viewer *viewer = dynamic_cast<osgViewer::Viewer*>(&aa);  
  172.         if (!viewer)  
  173.             return false;  
  174.         if (!viewer->getSceneData())  
  175.             return false;  
  176.         if (ea.getHandled())   
  177.             return false;  
  178.   
  179.         osg::Group *root = viewer->getSceneData()->asGroup();  
  180.   
  181.         switch(ea.getEventType())  
  182.         {  
  183.         case(osgGA::GUIEventAdapter::KEYDOWN):  
  184.             {  
  185.                 if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Left)  
  186.                 {  
  187.                     FindFirstNamedNodeVisitor fnv("yRotMT");  
  188.                     root->accept(fnv);  
  189.   
  190.                     osg::Node *mtNode = fnv._foundNode;  
  191.                     osg::MatrixTransform *yRotMT = dynamic_cast<osg::MatrixTransform*>(mtNode);  
  192.                     if (!yRotMT)  
  193.                         return false;  
  194.   
  195.                     RotateCallback *rotCallback = dynamic_cast<RotateCallback*>(yRotMT->getUpdateCallback());  
  196.   
  197.                     if (!rotCallback)  
  198.                         return false;  
  199.   
  200.                     double speed = rotCallback->getRotateSpeed();  
  201.                     speed += 0.02;  
  202.                     rotCallback->setRotateSpeed(speed);  
  203.   
  204.                 }  
  205.   
  206.                 if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Right)  
  207.                 {  
  208.                     FindFirstNamedNodeVisitor fnv("yRotMT");  
  209.                     root->accept(fnv);  
  210.   
  211.                     osg::Node *mtNode = fnv._foundNode;  
  212.                     osg::MatrixTransform *yRotMT = dynamic_cast<osg::MatrixTransform*>(mtNode);  
  213.                     if (!yRotMT)  
  214.                         return false;  
  215.   
  216.                     RotateCallback *rotCallback = dynamic_cast<RotateCallback*>(yRotMT->getUpdateCallback());  
  217.   
  218.                     if (!rotCallback)  
  219.                         return false;  
  220.   
  221.                     double speed = rotCallback->getRotateSpeed();  
  222.                     speed -= 0.02;  
  223.                     rotCallback->setRotateSpeed(speed);  
  224.                 }  
  225.   
  226.                 if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Up)  
  227.                 {  
  228.                     FindFirstNamedNodeVisitor fnv("xRotMT");  
  229.                     root->accept(fnv);  
  230.   
  231.                     osg::Node *mtNode = fnv._foundNode;  
  232.                     osg::MatrixTransform *xRotMT = dynamic_cast<osg::MatrixTransform*>(mtNode);  
  233.                     if (!xRotMT)  
  234.                         return false;  
  235.   
  236.                     RotateCallback *rotCallback = dynamic_cast<RotateCallback*>(xRotMT->getUpdateCallback());  
  237.   
  238.                     if (!rotCallback)  
  239.                         return false;  
  240.   
  241.                     double speed = rotCallback->getRotateSpeed();  
  242.                     speed += 0.02;  
  243.                     rotCallback->setRotateSpeed(speed);  
  244.                 }  
  245.   
  246.                 if (ea.getKey()== osgGA::GUIEventAdapter::KEY_Down)  
  247.                 {  
  248.                     FindFirstNamedNodeVisitor fnv("xRotMT");  
  249.                     root->accept(fnv);  
  250.   
  251.                     osg::Node *mtNode = fnv._foundNode;  
  252.                     osg::MatrixTransform *xRotMT = dynamic_cast<osg::MatrixTransform*>(mtNode);  
  253.                     if (!xRotMT)  
  254.                         return false;  
  255.   
  256.                     RotateCallback *rotCallback = dynamic_cast<RotateCallback*>(xRotMT->getUpdateCallback());  
  257.   
  258.                     if (!rotCallback)  
  259.                         return false;  
  260.   
  261.                     double speed = rotCallback->getRotateSpeed();  
  262.                     speed -= 0.02;  
  263.                     rotCallback->setRotateSpeed(speed);  
  264.                 }  
  265.   
  266.                 if (ea.getKey() == osgGA::GUIEventAdapter::KEY_E)  
  267.                 {  
  268.                     if (g_switch->getValue(2) == true)  
  269.                     {  
  270.                         g_switch->setValue(2, false);  
  271.                     }  
  272.                     else  
  273.                     {  
  274.                         g_switch->setValue(2, true);   
  275.                     }  
  276.                 }  
  277.   
  278.             }  
  279.         defaultbreak;  
  280.         }  
  281.         return false;  
  282.     }  
  283. };  
  284.   
  285. //////////////////////////////////////////////////////////////////////////  
  286.   
  287.   
  288. class ViewerWidget : public QWidget, public osgViewer::Viewer  
  289. {  
  290. public:  
  291.     ViewerWidget(osg::Node *scene = NULL)  
  292.     {  
  293.         QWidget* renderWidget = getRenderWidget( createGraphicsWindow(0,0,100,100), scene);  
  294.   
  295.         QVBoxLayout* layout = new QVBoxLayout;  
  296.         layout->addWidget(renderWidget);  
  297.         layout->setContentsMargins(0, 0, 0, 1);  
  298.         setLayout( layout );  
  299.   
  300.         connect( &_timer, SIGNAL(timeout()), this, SLOT(update()) );  
  301.         _timer.start( 10 );  
  302.     }  
  303.   
  304.     QWidget* getRenderWidget( osgQt::GraphicsWindowQt* gw, osg::Node* scene )  
  305.     {  
  306.         osg::Camera* camera = this->getCamera();  
  307.         camera->setGraphicsContext( gw );  
  308.   
  309.         const osg::GraphicsContext::Traits* traits = gw->getTraits();  
  310.   
  311.         camera->setClearColor( osg::Vec4(0.0, 0.0, 0.0, 0.5) );  
  312.         camera->setClearDepth(1.0);  
  313.         camera->setViewport( new osg::Viewport(0, 0, traits->width, traits->height) );  
  314.         camera->setProjectionMatrixAsPerspective(45.0f, static_cast<double>(traits->width)/static_cast<double>(traits->height), 0.1f, 100.0f );  
  315.         camera->setViewMatrixAsLookAt(osg::Vec3d(0, 0, 1), osg::Vec3d(0, 0, 0), osg::Vec3d(0, 1, 0));  
  316.   
  317.         this->setSceneData( scene );  
  318.         addEventHandler(new ManipulatorSceneHandler);  
  319.         g_viewer = this;  
  320.   
  321.         return gw->getGLWidget();  
  322.     }  
  323.   
  324.     osgQt::GraphicsWindowQt* createGraphicsWindow( int x, int y, int w, int h, const std::string& name=""bool windowDecoration=false )  
  325.     {  
  326.         osg::DisplaySettings* ds = osg::DisplaySettings::instance().get();  
  327.         osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;  
  328.         traits->windowName = name;  
  329.         traits->windowDecoration = windowDecoration;  
  330.         traits->x = x;  
  331.         traits->y = y;  
  332.         traits->width = w;  
  333.         traits->height = h;  
  334.         traits->doubleBuffer = true;  
  335.         traits->alpha = ds->getMinimumNumAlphaBits();  
  336.         traits->stencil = ds->getMinimumNumStencilBits();  
  337.         traits->sampleBuffers = ds->getMultiSamples();  
  338.         traits->samples = ds->getNumMultiSamples();  
  339.   
  340.         return new osgQt::GraphicsWindowQt(traits.get());  
  341.     }  
  342.   
  343.     virtual void paintEvent( QPaintEvent* event )  
  344.     {   
  345.         frame();   
  346.     }  
  347.   
  348. protected:  
  349.   
  350.     QTimer _timer;  
  351. };  
  352.   
  353. //////////////////////////////////////////////////////////////////////////  
  354. //创建纹理:代码中只是用到第二个纹理bump[1]和invbmp[1]  
  355.   
  356. void initTextures()  
  357. {  
  358.     osg::Image *image1 = new osg::Image;  
  359.     image1 = osgDB::readImageFile("Data/Base.bmp");  
  360.       
  361.     texture[0] = new osg::Texture2D;  
  362.     texture[0]->setFilter(osg::Texture::MAG_FILTER, osg::Texture::NEAREST);  
  363.     texture[0]->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST);  
  364.     texture[0]->setImage(image1);  
  365.   
  366.     texture[1] = new osg::Texture2D;  
  367.     texture[1]->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);  
  368.     texture[1]->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);  
  369.     texture[1]->setImage(image1);  
  370.   
  371.     texture[2] = new osg::Texture2D;  
  372.     texture[2]->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);  
  373.     texture[2]->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_NEAREST);  
  374.     texture[2]->setImage(image1);  
  375.   
  376.     osg::Image *image2 = new osg::Image;  
  377.     image2 = osgDB::readImageFile("Data/Bump.bmp");  
  378.     osg::offsetAndScaleImage(image2, osg::Vec4(), osg::Vec4(0.5, 0.5, 0.5, 1));  
  379.   
  380.     bump[0] = new osg::Texture2D;  
  381.     bump[0]->setFilter(osg::Texture::MAG_FILTER, osg::Texture::NEAREST);  
  382.     bump[0]->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST);  
  383.     bump[0]->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP);  
  384.     bump[0]->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP);  
  385.     bump[0]->setBorderColor(osg::Vec4(0.5, 0.5, 0.5, 1.0));  
  386.     bump[0]->setImage(image2);  
  387.   
  388.     bump[1] = new osg::Texture2D;  
  389.     bump[1]->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);  
  390.     bump[1]->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);  
  391.     bump[1]->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP);  
  392.     bump[1]->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP);  
  393.     bump[1]->setBorderColor(osg::Vec4(0.5, 0.5, 0.5, 1.0));  
  394.     bump[1]->setImage(image2);  
  395.   
  396.     bump[2] = new osg::Texture2D;  
  397.     bump[2]->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);  
  398.     bump[2]->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_NEAREST);  
  399.     bump[2]->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP);  
  400.     bump[2]->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP);  
  401.     bump[2]->setBorderColor(osg::Vec4(0.5, 0.5, 0.5, 1.0));  
  402.     bump[2]->setImage(image2);  
  403.   
  404.     osg::Image *image3 = osgDB::readImageFile("Data/Bump.bmp");  
  405.     osg::offsetAndScaleImage(image3, osg::Vec4(), osg::Vec4(0.5,0.5,0.5,1));  
  406.     osg::offsetAndScaleImage(image3, osg::Vec4(-128, -128, -128, 1), osg::Vec4(-1,-1,-1,1));  
  407.   
  408.     invbump[0] = new osg::Texture2D;  
  409.     invbump[0]->setFilter(osg::Texture::MAG_FILTER, osg::Texture::NEAREST);  
  410.     invbump[0]->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST);  
  411.     invbump[0]->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP);  
  412.     invbump[0]->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP);  
  413.     invbump[0]->setBorderColor(osg::Vec4(0.5, 0.5, 0.5, 1.0));  
  414.     invbump[0]->setImage(image3);  
  415.   
  416.     invbump[1] = new osg::Texture2D;  
  417.     invbump[1]->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);  
  418.     invbump[1]->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);  
  419.     invbump[1]->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP);  
  420.     invbump[1]->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP);  
  421.     invbump[1]->setBorderColor(osg::Vec4(0.5, 0.5, 0.5, 1.0));  
  422.     invbump[1]->setImage(image3);  
  423.   
  424.     invbump[2] = new osg::Texture2D;  
  425.     invbump[2]->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);  
  426.     invbump[2]->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_NEAREST);  
  427.     invbump[2]->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP);  
  428.     invbump[2]->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP);  
  429.     invbump[2]->setBorderColor(osg::Vec4(0.5, 0.5, 0.5, 1.0));  
  430.     invbump[2]->setImage(image3);  
  431.   
  432.     osg::Image *glLogoAlpha = osgDB::readImageFile("Data/OpenGL_ALPHA.bmp");  
  433.     osg::Image *glLogoImage = osgDB::readImageFile("Data/OpenGL.bmp");  
  434.     osg::Image *glLogoCombo = new osg::Image;  
  435.     glLogoCombo->allocateImage(glLogoImage->s(), glLogoImage->t(), 1, GL_RGBA, glLogoImage->getDataType());  
  436.     unsigned char *comboData = glLogoCombo->data();  
  437.   
  438.     for (int i = 0; i < glLogoImage->s() * glLogoImage->t(); ++i)  
  439.     {  
  440.         comboData[4*i+3] = glLogoAlpha->data()[i*3];  
  441.         comboData[4*i] = glLogoImage->data()[i*3];  
  442.         comboData[4*i+1] = glLogoImage->data()[i*3+1];  
  443.         comboData[4*i+2] = glLogoImage->data()[i*3+2];  
  444.     }  
  445.   
  446.     glLogo = new osg::Texture2D;  
  447.     glLogo->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);  
  448.     glLogo->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);  
  449.     glLogo->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP);  
  450.     glLogo->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP);  
  451.     glLogo->setBorderColor(osg::Vec4(0.5, 0.5, 0.5, 1.0));  
  452.     glLogo->setImage(glLogoCombo);  
  453.   
  454.     osg::Image *glMultiAlpha = osgDB::readImageFile("Data/multi_on_alpha.bmp");  
  455.     osg::Image *glMultiImage = osgDB::readImageFile("Data/multi_on.bmp");  
  456.     osg::Image *glMultiCombo = new osg::Image;  
  457.     glMultiCombo->allocateImage(glLogoImage->s(), glLogoImage->t(), 1, GL_RGBA, glLogoImage->getDataType());  
  458.     unsigned char *multiComboData = glMultiCombo->data();  
  459.   
  460.     for (int i = 0; i < glMultiImage->s() * glMultiImage->t(); ++i)  
  461.     {  
  462.         multiComboData[4*i+3] = glMultiAlpha->data()[i*3];  
  463.         multiComboData[4*i] = glMultiImage->data()[i*3];  
  464.         multiComboData[4*i+1] = glMultiImage->data()[i*3+1];  
  465.         multiComboData[4*i+2] = glMultiImage->data()[i*3+2];  
  466.     }  
  467.   
  468.     multiLogo = new osg::Texture2D;  
  469.     multiLogo->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);  
  470.     multiLogo->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);  
  471.     multiLogo->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP);  
  472.     multiLogo->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP);  
  473.     multiLogo->setBorderColor(osg::Vec4(0.5, 0.5, 0.5, 1.0));  
  474.     multiLogo->setImage(glMultiCombo);  
  475. }  
  476.   
  477.   
  478. osg::Group *createLogo()  
  479. {  
  480.     osg::Group *logoGroup = new osg::Group;  
  481.   
  482.     osg::Depth *depth = new osg::Depth(osg::Depth::ALWAYS);  
  483.     osg::BlendFunc *blendFunc = new osg::BlendFunc(osg::BlendFunc::SRC_ALPHA, osg::BlendFunc::ONE_MINUS_SRC_ALPHA);  
  484.   
  485.     osg::Geode *logoGeode = new osg::Geode;  
  486.     osg::Geometry *logoGeometry = new osg::Geometry;  
  487.     osg::Vec3Array *logoVertices = new osg::Vec3Array;  
  488.     logoVertices->push_back(osg::Vec3(0.23f, -0.4f,-1.0f));  
  489.     logoVertices->push_back(osg::Vec3(0.53f, -0.4f,-1.0f));  
  490.     logoVertices->push_back(osg::Vec3(0.53f, -0.25f,-1.0f));  
  491.     logoVertices->push_back(osg::Vec3(0.23f, -0.25f,-1.0f));  
  492.     osg::Vec2Array *textureVertices = new osg::Vec2Array;  
  493.     textureVertices->push_back(osg::Vec2(0.0f,0.0f));  
  494.     textureVertices->push_back(osg::Vec2(1.0f,0.0f));  
  495.     textureVertices->push_back(osg::Vec2(1.0f,1.0f));  
  496.     textureVertices->push_back(osg::Vec2(0.0f,1.0f));  
  497.     logoGeometry->setVertexArray(logoVertices);  
  498.     logoGeometry->setTexCoordArray(0, textureVertices);  
  499.     logoGeometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, 4));  
  500.     logoGeometry->getOrCreateStateSet()->setAttributeAndModes(depth);  
  501.     logoGeometry->getOrCreateStateSet()->setAttributeAndModes(blendFunc);  
  502.     logoGeometry->getOrCreateStateSet()->setTextureAttributeAndModes(0, glLogo);  
  503.     logoGeode->addDrawable(logoGeometry);  
  504.   
  505.     osg::Geode *multiGeode = new osg::Geode;  
  506.     osg::Geometry *multiGeometry = new osg::Geometry;  
  507.     osg::Vec3Array *multiVertices = new osg::Vec3Array;  
  508.     multiVertices->push_back(osg::Vec3(-0.53f, -0.4f,-1.0f));  
  509.     multiVertices->push_back(osg::Vec3(-0.33f, -0.4f,-1.0f));  
  510.     multiVertices->push_back(osg::Vec3(-0.33f, -0.3f,-1.0f));  
  511.     multiVertices->push_back(osg::Vec3(-0.53f, -0.3f,-1.0f));  
  512.     osg::Vec2Array *tVertices = new osg::Vec2Array;  
  513.     textureVertices->push_back(osg::Vec2(0.0f,0.0f));  
  514.     textureVertices->push_back(osg::Vec2(1.0f,0.0f));  
  515.     textureVertices->push_back(osg::Vec2(1.0f,1.0f));  
  516.     textureVertices->push_back(osg::Vec2(0.0f,1.0f));  
  517.     multiGeometry->setVertexArray(multiVertices);  
  518.     multiGeometry->setTexCoordArray(0, tVertices);  
  519.     multiGeometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, 4));  
  520.     multiGeometry->getOrCreateStateSet()->setAttributeAndModes(depth);  
  521.     multiGeometry->getOrCreateStateSet()->setAttributeAndModes(blendFunc);  
  522.     multiGeometry->getOrCreateStateSet()->setTextureAttributeAndModes(0, multiLogo);  
  523.     multiGeode->addDrawable(multiGeometry);  
  524.   
  525.     logoGroup->addChild(logoGeode);  
  526.     logoGroup->addChild(multiGeode);  
  527.   
  528.     return logoGroup;  
  529. }  
  530.   
  531.   
  532.   
  533. osg::Geode* createCube()  
  534. {  
  535.     osg::Geode *cubeGeode = new osg::Geode;  
  536.     osg::Geometry *cubeGeometry = new osg::Geometry;  
  537.   
  538.     osg::Vec3Array *vertices = new osg::Vec3Array;  
  539.     osg::Vec3Array *normals = new osg::Vec3Array;  
  540.     osg::Vec2Array *texcoords = new osg::Vec2Array;  
  541.   
  542.     for (unsigned i = 0; i < 24; ++i)  
  543.     {  
  544.         texcoords->push_back(osg::Vec2(data[5*i],data[5*i + 1]));  
  545.         vertices->push_back(osg::Vec3(data[5*i + 2], data[5*i +3], data[5*i + 4]));  
  546.     }  
  547.   
  548.     normals->push_back(osg::Vec3(0.0f, 0.0f, +1.0f));  
  549.     normals->push_back(osg::Vec3(0.0f, 0.0f,-1.0f));  
  550.     normals->push_back(osg::Vec3(0.0f, 1.0f, 0.0f));  
  551.     normals->push_back(osg::Vec3(0.0f,-1.0f, 0.0f));  
  552.     normals->push_back(osg::Vec3(1.0f, 0.0f, 0.0f));  
  553.     normals->push_back(osg::Vec3(-1.0f, 0.0f, 0.0f));  
  554.   
  555.     cubeGeometry->setVertexArray(vertices);  
  556.     cubeGeometry->setTexCoordArray(0, texcoords);  
  557.     cubeGeometry->setNormalArray(normals, osg::Array::BIND_PER_PRIMITIVE_SET);  
  558.     cubeGeometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, vertices->size()));  
  559.   
  560.     cubeGeometry->getOrCreateStateSet()->setTextureAttributeAndModes(0, texture[1]);  
  561.     osg::BlendFunc *blendFunc = new osg::BlendFunc(osg::BlendFunc::DST_COLOR, osg::BlendFunc::SRC_COLOR);  
  562.     cubeGeometry->getOrCreateStateSet()->setAttributeAndModes(blendFunc);  
  563.     osg::Depth *depth = new osg::Depth(osg::Depth::LEQUAL);  
  564.     cubeGeometry->getOrCreateStateSet()->setAttributeAndModes(depth);  
  565.     osg::TexEnv *texEnv = new osg::TexEnv(osg::TexEnv::MODULATE);  
  566.     cubeGeometry->getOrCreateStateSet()->setTextureAttributeAndModes(0, texEnv);  
  567.     cubeGeometry->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);  
  568.   
  569.     cubeGeode->addDrawable(cubeGeometry);  
  570.     return cubeGeode;  
  571. }  
  572.   
  573.   
  574. osg::Geode* createUpMappingCube()  
  575. {  
  576.     osg::Geode *cubeGeode = new osg::Geode;  
  577.     osg::Geometry *cubeGeometry = new osg::Geometry;  
  578.   
  579.     osg::Vec3Array *vertices = new osg::Vec3Array;  
  580.     osg::Vec3Array *normals = new osg::Vec3Array;  
  581.     osg::Vec2Array *texcoords = new osg::Vec2Array;  
  582.   
  583.     for (unsigned i = 0; i < 24; ++i)  
  584.     {  
  585.         texcoords->push_back(osg::Vec2(data[5*i],data[5*i + 1]));  
  586.         vertices->push_back(osg::Vec3(data[5*i + 2], data[5*i +3], data[5*i + 4]));  
  587.     }  
  588.   
  589.     cubeGeometry->setVertexArray(vertices);  
  590.     cubeGeometry->setTexCoordArray(0, texcoords);  
  591.     cubeGeometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, vertices->size()));  
  592.     cubeGeometry->getOrCreateStateSet()->setMode(GL_LIGHTING, false);  
  593.     cubeGeometry->getOrCreateStateSet()->setTextureAttributeAndModes(0, bump[1]);  
  594.     osg::Depth *depth = new osg::Depth(osg::Depth::LEQUAL);  
  595.     cubeGeometry->getOrCreateStateSet()->setAttributeAndModes(depth);  
  596.     cubeGeode->addDrawable(cubeGeometry);  
  597.     return cubeGeode;  
  598. }  
  599.   
  600.   
  601. class TextureCallback : public osg::Drawable::UpdateCallback  
  602. {  
  603. public:  
  604.     TextureCallback(){ }  
  605.   
  606.     virtual void update(osg::NodeVisitor* nv, osg::Drawable* drawable)  
  607.     {  
  608.         osg::Geometry *geometry = drawable->asGeometry();  
  609.         if (!geometry)  
  610.             return;  
  611.   
  612.         osg::Vec2Array *textureArray = dynamic_cast<osg::Vec2Array*>(geometry->getTexCoordArray(0));  
  613.         if(textureArray)  
  614.             return;  
  615.         textureArray = new osg::Vec2Array;  
  616.       
  617.         osg::Vec3Array *vertices = dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray());  
  618.   
  619.         osg::Vec3 lightPos(LightPosition[0], LightPosition[1], LightPosition[2]);  
  620.   
  621.         osg::Matrix currentModelViewMatrix = computeLocalToWorld(nv->getNodePath()) * g_viewer->getCamera()->getViewMatrix();  
  622.         osg::Matrix currentInvModelViewerMatrix = osg::Matrix::inverse(currentModelViewMatrix);  
  623.         osg::Vec3 lightInObjectSpace = lightPos * currentInvModelViewerMatrix;  
  624.   
  625. //////////////////////////////////////////////////////////////////////////  
  626.         for (int i=0; i<4; i++) {  
  627.             osg::Vec3 pos = vertices->at(i);  
  628.             osg::Vec3 orientation = lightInObjectSpace - pos;  
  629.             orientation.normalize();  
  630.             double deltaS = orientation * osg::Vec3(1,0,0) * MaxEmboss;  
  631.             double deltaT = orientation * osg::Vec3(0,1,0) * MaxEmboss;  
  632.             textureArray->push_back(osg::Vec2(data[5*i]+deltaS,data[5*i + 1]+deltaT));  
  633.         }  
  634.         for (int i=4; i<8; i++) {  
  635.             osg::Vec3 pos = vertices->at(i);  
  636.             osg::Vec3 orientation = lightInObjectSpace - pos;  
  637.             orientation.normalize();  
  638.             double deltaS = orientation * osg::Vec3(-1, 0, 0) * MaxEmboss;  
  639.             double deltaT = orientation * osg::Vec3(0,1,0) * MaxEmboss;  
  640.             textureArray->push_back(osg::Vec2(data[5*i]+deltaS,data[5*i + 1]+deltaT));  
  641.         }  
  642.         for (int i=8; i<12; i++) {  
  643.             osg::Vec3 pos = vertices->at(i);  
  644.             osg::Vec3 orientation = lightInObjectSpace - pos;  
  645.             orientation.normalize();  
  646.             double deltaS = orientation * osg::Vec3(1, 0, 0) * MaxEmboss;  
  647.             double deltaT = orientation * osg::Vec3(0,0,-1) * MaxEmboss;  
  648.             textureArray->push_back(osg::Vec2(data[5*i]+deltaS,data[5*i + 1]+deltaT));  
  649.         }  
  650.         for (int i=12; i<16; i++) {  
  651.             osg::Vec3 pos = vertices->at(i);  
  652.             osg::Vec3 orientation = lightInObjectSpace - pos;  
  653.             orientation.normalize();  
  654.             double deltaS = orientation * osg::Vec3(0, -1, 0) * MaxEmboss;  
  655.             double deltaT = orientation * osg::Vec3(-1,0,0) * MaxEmboss;  
  656.             textureArray->push_back(osg::Vec2(data[5*i]+deltaS,data[5*i + 1]+deltaT));  
  657.         }  
  658.         for (int i=16; i<20; i++) {  
  659.             osg::Vec3 pos = vertices->at(i);  
  660.             osg::Vec3 orientation = lightInObjectSpace - pos;  
  661.             orientation.normalize();  
  662.             double deltaS = orientation * osg::Vec3(0, 0, -1) * MaxEmboss;  
  663.             double deltaT = orientation * osg::Vec3(0,1,0) * MaxEmboss;  
  664.             textureArray->push_back(osg::Vec2(data[5*i]+deltaS,data[5*i + 1]+deltaT));  
  665.         }  
  666.         for (int i=20; i<24; i++) {  
  667.             osg::Vec3 pos = vertices->at(i);  
  668.             osg::Vec3 orientation = lightInObjectSpace - pos;  
  669.             orientation.normalize();  
  670.             double deltaS = orientation * osg::Vec3(0, 0, 1) * MaxEmboss;  
  671.             double deltaT = orientation * osg::Vec3(0,1,0) * MaxEmboss;  
  672.             textureArray->push_back(osg::Vec2(data[5*i]+deltaS,data[5*i + 1]+deltaT));  
  673.         }  
  674.             geometry->setTexCoordArray(0, textureArray);  
  675.             geometry->getOrCreateStateSet()->setTextureAttributeAndModes(0, invbump[1]);  
  676.             geometry->getOrCreateStateSet()->setMode(GL_LIGHTING, false);  
  677.             osg::BlendFunc *blendFunc = new osg::BlendFunc(osg::BlendFunc::ONE, osg::BlendFunc::ONE);  
  678.             geometry->getOrCreateStateSet()->setAttributeAndModes(blendFunc);  
  679.             osg::Depth *depth = new osg::Depth(osg::Depth::LEQUAL);  
  680.             geometry->getOrCreateStateSet()->setAttributeAndModes(depth);  
  681.     }  
  682. };  
  683.   
  684.   
  685. osg::Geode* createDownMappingCube()  
  686. {  
  687.     osg::Geode *cubeGeode = new osg::Geode;  
  688.     osg::Geometry *cubeGeometry = new osg::Geometry;  
  689.     cubeGeometry->setUpdateCallback(new TextureCallback());  
  690.   
  691.     osg::Vec3Array *vertices = new osg::Vec3Array;  
  692.   
  693.     for (unsigned i = 0; i < 24; ++i)  
  694.     {  
  695.         vertices->push_back(osg::Vec3(data[5*i + 2], data[5*i +3], data[5*i + 4]));  
  696.     }  
  697.   
  698.     cubeGeometry->setVertexArray(vertices);  
  699.     cubeGeometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, vertices->size()));  
  700.   
  701.     cubeGeode->addDrawable(cubeGeometry);  
  702.     return cubeGeode;  
  703. }  
  704.   
  705.   
  706. //////////////////////////////////////////////////////////////////////////  
  707. //Method 2:Using MultiTexture to Render  
  708. //  
  709. //TODO:使用MultiTexture的方式:  
  710. // TODO: 未在OpenGL文档中查询到  
  711. //  glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);  
  712. //glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_REPLACE);     
  713. //不清楚是否是新的扩展,请读者指点  
  714. //////////////////////////////////////////////////////////////////////////  
  715.   
  716. #if 0  
  717. class MultiTextureUpdateCallback : public osg::Drawable::UpdateCallback  
  718. {  
  719. public:  
  720.     virtual void update(osg::NodeVisitor* nv, osg::Drawable* drawable)  
  721.     {  
  722.         osg::Geometry *geometry = drawable->asGeometry();  
  723.         if (!geometry)  
  724.             return;  
  725.   
  726.         osg::Vec2Array *textureArray = dynamic_cast<osg::Vec2Array*>(geometry->getTexCoordArray(1));  
  727.         if(textureArray)  
  728.             return;  
  729.         textureArray = new osg::Vec2Array;  
  730.   
  731.         osg::Vec3Array *vertices = dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray());  
  732.   
  733.         osg::Vec3 lightPos(LightPosition[0], LightPosition[1], LightPosition[2]);  
  734.   
  735.         osg::Matrix currentModelViewMatrix = computeLocalToWorld(nv->getNodePath()) * g_viewer->getCamera()->getViewMatrix();  
  736.         osg::Matrix currentInvModelViewerMatrix = osg::Matrix::inverse(currentModelViewMatrix);  
  737.         osg::Vec3 lightInObjectSpace = lightPos * currentInvModelViewerMatrix;  
  738.   
  739.         //////////////////////////////////////////////////////////////////////////  
  740.         for (int i=0; i<4; i++) {  
  741.             osg::Vec3 pos = vertices->at(i);  
  742.             osg::Vec3 orientation = lightInObjectSpace - pos;  
  743.             orientation.normalize();  
  744.             double deltaS = orientation * osg::Vec3(1,0,0) * MaxEmboss;  
  745.             double deltaT = orientation * osg::Vec3(0,1,0) * MaxEmboss;  
  746.             textureArray->push_back(osg::Vec2(data[5*i]+deltaS,data[5*i + 1]+deltaT));  
  747.         }  
  748.         for (int i=4; i<8; i++) {  
  749.             osg::Vec3 pos = vertices->at(i);  
  750.             osg::Vec3 orientation = lightInObjectSpace - pos;  
  751.             orientation.normalize();  
  752.             double deltaS = orientation * osg::Vec3(-1, 0, 0) * MaxEmboss;  
  753.             double deltaT = orientation * osg::Vec3(0,1,0) * MaxEmboss;  
  754.             textureArray->push_back(osg::Vec2(data[5*i]+deltaS,data[5*i + 1]+deltaT));  
  755.         }  
  756.         for (int i=8; i<12; i++) {  
  757.             osg::Vec3 pos = vertices->at(i);  
  758.             osg::Vec3 orientation = lightInObjectSpace - pos;  
  759.             orientation.normalize();  
  760.             double deltaS = orientation * osg::Vec3(1, 0, 0) * MaxEmboss;  
  761.             double deltaT = orientation * osg::Vec3(0,0,-1) * MaxEmboss;  
  762.             textureArray->push_back(osg::Vec2(data[5*i]+deltaS,data[5*i + 1]+deltaT));  
  763.         }  
  764.         for (int i=12; i<16; i++) {  
  765.             osg::Vec3 pos = vertices->at(i);  
  766.             osg::Vec3 orientation = lightInObjectSpace - pos;  
  767.             orientation.normalize();  
  768.             double deltaS = orientation * osg::Vec3(0, -1, 0) * MaxEmboss;  
  769.             double deltaT = orientation * osg::Vec3(-1,0,0) * MaxEmboss;  
  770.             textureArray->push_back(osg::Vec2(data[5*i]+deltaS,data[5*i + 1]+deltaT));  
  771.         }  
  772.         for (int i=16; i<20; i++) {  
  773.             osg::Vec3 pos = vertices->at(i);  
  774.             osg::Vec3 orientation = lightInObjectSpace - pos;  
  775.             orientation.normalize();  
  776.             double deltaS = orientation * osg::Vec3(0, 0, -1) * MaxEmboss;  
  777.             double deltaT = orientation * osg::Vec3(0,1,0) * MaxEmboss;  
  778.             textureArray->push_back(osg::Vec2(data[5*i]+deltaS,data[5*i + 1]+deltaT));  
  779.         }  
  780.         for (int i=20; i<24; i++) {  
  781.             osg::Vec3 pos = vertices->at(i);  
  782.             osg::Vec3 orientation = lightInObjectSpace - pos;  
  783.             orientation.normalize();  
  784.             double deltaS = orientation * osg::Vec3(0, 0, 1) * MaxEmboss;  
  785.             double deltaT = orientation * osg::Vec3(0,1,0) * MaxEmboss;  
  786.             textureArray->push_back(osg::Vec2(data[5*i]+deltaS,data[5*i + 1]+deltaT));  
  787.         }  
  788.         geometry->setTexCoordArray(1, textureArray);  
  789.         geometry->getOrCreateStateSet()->setTextureAttributeAndModes(1, invbump[1]);  
  790.       
  791.         osg::TexEnv *tex2Env = new osg::TexEnv(osg::TexEnv::ADD);  
  792.         geometry->getOrCreateStateSet()->setTextureAttributeAndModes(0, tex2Env);  
  793.         geometry->getOrCreateStateSet()->setMode(GL_LIGHTING, false);  
  794.     }  
  795. };  
  796. #endif  
  797.   
  798.   
  799. osg::Node*  buildScene()  
  800. {  
  801.     initTextures();  
  802.     osg::Group *root = new osg::Group;  
  803.   
  804.     osg::MatrixTransform *zoomMT = new osg::MatrixTransform;  
  805.     zoomMT->setMatrix(osg::Matrix::translate(0.0, 0.0, -5.0));  
  806.   
  807.     osg::MatrixTransform *rotateXAxis = new osg::MatrixTransform;  
  808.     rotateXAxis->setName("xRotMT");  
  809.     RotateCallback *xRotCallback = new RotateCallback(osg::X_AXIS, 0.0);  
  810.     rotateXAxis->setUpdateCallback(xRotCallback);  
  811.     zoomMT->addChild(rotateXAxis);  
  812.   
  813.   
  814.     osg::MatrixTransform *rotateYAxis = new osg::MatrixTransform;  
  815.     rotateYAxis->setName("yRotMT");  
  816.     RotateCallback *yRotCallback = new RotateCallback(osg::Y_AXIS, 0.0);  
  817.     rotateYAxis->setUpdateCallback(yRotCallback);  
  818.     rotateXAxis->addChild(rotateYAxis);  
  819.   
  820.     osg::Switch *switchNode = new osg::Switch;  
  821.     g_switch = switchNode;  
  822.     rotateYAxis->addChild(switchNode);  
  823.     switchNode->addChild(createUpMappingCube());  
  824.     switchNode->addChild(createDownMappingCube());  
  825.     switchNode->addChild(createCube());  
  826.     root->addChild(zoomMT);  
  827.       
  828.     return root;  
  829. }  
  830.   
  831.   
  832.   
  833. int main( int argc, char** argv )  
  834. {  
  835.     QApplication app(argc, argv);  
  836.     ViewerWidget* viewWidget = new ViewerWidget(buildScene());  
  837.     viewWidget->setGeometry( 100, 100, 640, 480 );  
  838.     viewWidget->show();  
  839.     return app.exec();  
  840. }  
0 0
原创粉丝点击