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

  • 简介

这节课NeHe教我们实现了卡通纹理。卡通渲染(英语:Cel-shading或者Toon Shading)是一种去真实感的渲染方法,旨在使电脑生成的图像呈现出手绘般的效果。为了使图像可以与漫画或者卡通达到形似的效果,专业人员通常使用卡通渲染着色器进行处理。卡通渲染是在大约21世纪初期,作为计算机图形学的副产物出现的新技术,并且主要应用于电子游戏中;然而,它可以呈现出如手绘动画一样简洁明了的效果。更多卡通渲染的内容可以参考Wiki:卡通渲染

  • 实现

首先我们需要创建模型,模型来自文件model.txt,读取该模型并生成节点:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. BOOL ReadMesh ()                                                // Reads The Contents Of The "model.txt" File ( NEW )  
  2. {  
  3.     FILE *In = fopen ("Data\\model.txt""rb");                 // Open The File ( NEW )  
  4.   
  5.     if (!In)  
  6.         return FALSE;                                           // Return FALSE If File Not Opened ( NEW )  
  7.   
  8.     fread (&polyNum, sizeof (int), 1, In);                      // Read The Header (i.e. Number Of Polygons) ( NEW )  
  9.   
  10.     polyData = new POLYGON [polyNum];                           // Allocate The Memory ( NEW )  
  11.   
  12.     fread (&polyData[0], sizeof (POLYGON) * polyNum, 1, In);    // Read In All Polygon Data ( NEW )  
  13.   
  14.     fclose (In);                                                // Close The File ( NEW )  
  15.   
  16.     return TRUE;                                                // It Worked ( NEW )  
  17. }  
之后我们需要创建本课所实现的两种效果:

1.卡通渲染着色:

首先创建一维纹理:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. osg::Image *image = new osg::Image;  
  2. image->allocateImage(32, 1, 1, GL_RGB, GL_FLOAT);  
  3. osg::Vec3 *dataPtr = (osg::Vec3*)(image->data());  
  4. for (int i = 0; i < 32; ++i)  
  5. {  
  6.     *dataPtr++ = osg::Vec3(shaderData[i][0], shaderData[i][1], shaderData[i][2]);  
  7. }  
  8.   
  9. g_Texture1D = new osg::Texture1D;  
  10. g_Texture1D->setFilter(osg::Texture::MAG_FILTER, osg::Texture::NEAREST);  
  11. g_Texture1D->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST);  
  12. g_Texture1D->setImage(image);  
卡通着色的原理:用几何体的一条表面法线以及光线方向来找到光线撞击这个模型表面的强度,这两个向量的点积产生一个在0-1之间的值,可以将这个值作为一维纹理坐标来使用。

在节点的更新回调中计算纹理坐标(纹理坐标计算需要法线方向和光线方向):光线的方向一直不变是(0,0,1),而法线方向随着旋转会改变,我们通过获取旋转量来计算法线的实时方向,然后通过二者点乘得到纹理坐标,实现如下:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. osg::FloatArray *textureArray = new osg::FloatArray;  
  2.   
  3. for (int i = 0; i < polyNum; i++)  
  4. {  
  5.     for (int j = 0; j < 3; j++)  
  6.     {  
  7.         osg::Vec3 nor;  
  8.   
  9.         nor.x() = polyData[i].Verts[j].Nor.X;  
  10.         nor.y() = polyData[i].Verts[j].Nor.Y;  
  11.         nor.z() = polyData[i].Verts[j].Nor.Z;  
  12.   
  13.         RotAxisCallback *rotCallback = dynamic_cast<RotAxisCallback*>(g_RotMT->getUpdateCallback());  
  14.         double angle = rotCallback->getCurrentAngle();  
  15.         nor = nor * osg::Matrix::rotate(angle, osg::Y_AXIS);  
  16.         nor.normalize();  
  17.   
  18.         osg::Vec3 lightDir = osg::Vec3(lightAngle.X, lightAngle.Y, lightAngle.Z);  
  19.   
  20.         float TmpShade = nor * lightDir;  
  21.   
  22.         if (TmpShade < 0.0f)  
  23.             TmpShade = 0.0f;  
  24.   
  25.         textureArray->push_back(TmpShade);  
  26.     }  
  27. }  

之后把节点加到场景中就完成卡通着色的效果。

2.Outline外框

实质上是通过一系列状态的组合来得到这种效果:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. osg::Geode *outlineModel = createModelGeode();  
  2. g_OutlineGeode = outlineModel;  
  3. osg::Geometry *d = dynamic_cast<osg::Geometry*>(outlineModel->getDrawable(0));  
  4. if(d)  
  5. {  
  6.     osg::Vec3Array *vecArray = dynamic_cast<osg::Vec3Array*>(d->getColorArray());  
  7.     vecArray->at(0).set(osg::Vec3(0,0,0));  
  8.     d->setColorArray(vecArray, osg::Array::BIND_OVERALL);  
  9. }  
  10. osg::BlendFunc *blendFunc = new osg::BlendFunc(osg::BlendFunc::SRC_ALPHA, osg::BlendFunc::ONE_MINUS_SRC_ALPHA);  
  11. osg::PolygonMode    *polygonMode = new osg::PolygonMode(osg::PolygonMode::BACK, osg::PolygonMode::LINE);  
  12. osg::LineWidth *lineWidth = new osg::LineWidth(3.0f);  
  13. osg::CullFace *cullFace = new osg::CullFace(osg::CullFace::FRONT);  
  14.   
  15. outlineModel->getOrCreateStateSet()->setAttributeAndModes(blendFunc);  
  16. outlineModel->getOrCreateStateSet()->setAttributeAndModes(polygonMode);  
  17. outlineModel->getOrCreateStateSet()->setAttributeAndModes(lineWidth);  
  18. outlineModel->getOrCreateStateSet()->setAttributeAndModes(cullFace);  

在与键盘的交互代码中完成旋转和变换边框线的宽度:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. case(osgGA::GUIEventAdapter::KEYDOWN):  
  2.     {  
  3.         if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Space)  
  4.         {  
  5.             static bool flag = true;  
  6.   
  7.             if (!g_RotMT)  
  8.                 return false;  
  9.             RotAxisCallback *rotCallback = dynamic_cast<RotAxisCallback*>(g_RotMT->getUpdateCallback());  
  10.             if (!rotCallback)  
  11.                 return false;  
  12.   
  13.             if(flag)  
  14.             {  
  15.                 double speed = rotCallback->getRotateSpeed();  
  16.                 speed -= 0.02;  
  17.                 rotCallback->setRotateSpeed(speed);  
  18.             }  
  19.             else  
  20.             {  
  21.                 rotCallback->setRotateSpeed(0);  
  22.             }  
  23.             flag = !flag;  
  24.         }  
  25.   
  26.         if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Up)  
  27.         {  
  28.             if (!g_OutlineGeode)  
  29.                 return false;  
  30.             osg::LineWidth *lineWidth = dynamic_cast<osg::LineWidth*>( g_OutlineGeode->getOrCreateStateSet()->getAttribute(osg::StateAttribute::LINEWIDTH));  
  31.             float w = lineWidth->getWidth();  
  32.             w += 1.0f;  
  33.             lineWidth->setWidth(w);    
  34.         }  
  35.         if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Down)  
  36.         {  
  37.             if (!g_OutlineGeode)  
  38.                 return false;  
  39.             osg::LineWidth *lineWidth = dynamic_cast<osg::LineWidth*>(g_OutlineGeode->getOrCreateStateSet()->getAttribute(osg::StateAttribute::LINEWIDTH));  
  40.             float w = lineWidth->getWidth();  
  41.             w -= 1.0f;  
  42.             lineWidth->setWidth(w);    
  43.         }  
编译运行程序:


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

[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.   
  13. #include <osg/Texture1D>  
  14. #include <osg/BlendFunc>  
  15. #include <osg/CullFace>  
  16. #include <osg/PolygonMode>  
  17. #include <osg/LineWidth>  
  18.   
  19. // User Defined Structures  
  20. typedef struct tagMATRIX                                        // A Structure To Hold An OpenGL Matrix ( NEW )  
  21. {  
  22.     float Data[16];                                             // We Use [16] Due To OpenGL's Matrix Format ( NEW )  
  23. }  
  24. MATRIX;  
  25.   
  26. typedef struct tagVECTOR                                        // A Structure To Hold A Single Vector ( NEW )  
  27. {  
  28.     float X, Y, Z;                                              // The Components Of The Vector ( NEW )  
  29. }  
  30. VECTOR;  
  31.   
  32. typedef struct tagVERTEX                                        // A Structure To Hold A Single Vertex ( NEW )  
  33. {  
  34.     VECTOR Nor;                                                 // Vertex Normal ( NEW )  
  35.     VECTOR Pos;                                                 // Vertex Position ( NEW )  
  36. }  
  37. VERTEX;  
  38.   
  39. typedef struct tagPOLYGON                                       // A Structure To Hold A Single Polygon ( NEW )  
  40. {  
  41.     VERTEX Verts[3];                                            // Array Of 3 VERTEX Structures ( NEW )  
  42. }  
  43. POLYGON;  
  44.   
  45. // User Defined Variables  
  46. bool        outlineDraw     = true;                             // Flag To Draw The Outline ( NEW )  
  47. bool        outlineSmooth   = false;                            // Flag To Anti-Alias The Lines ( NEW )  
  48. float       outlineColor[3] = { 0.0f, 0.0f, 0.0f };             // Color Of The Lines ( NEW )  
  49. float       outlineWidth    = 3.0f;                             // Width Of The Lines ( NEW )  
  50.   
  51. VECTOR      lightAngle;                                         // The Direction Of The Light ( NEW )  
  52. bool        lightRotate     = false;                            // Flag To See If We Rotate The Light ( NEW )  
  53.   
  54. float       modelAngle      = 0.0f;                             // Y-Axis Angle Of The Model ( NEW )  
  55. bool        modelRotate     = false;                            // Flag To Rotate The Model ( NEW )  
  56.   
  57. POLYGON     *polyData       = NULL;                             // Polygon Data ( NEW )  
  58. int         polyNum         = 0;                                // Number Of Polygons ( NEW )  
  59.   
  60. //GLuint        shaderTexture[1];                                   // Storage For One Texture ( NEW )  
  61. osg::Texture1D  *g_Texture1D;  
  62. osg::MatrixTransform *g_RotMT = NULL;  
  63. osg::Geode *g_OutlineGeode = NULL;  
  64.   
  65. // File Functions  
  66. BOOL ReadMesh ()                                                // Reads The Contents Of The "model.txt" File ( NEW )  
  67. {  
  68.     FILE *In = fopen ("Data\\model.txt""rb");                 // Open The File ( NEW )  
  69.   
  70.     if (!In)  
  71.         return FALSE;                                           // Return FALSE If File Not Opened ( NEW )  
  72.   
  73.     fread (&polyNum, sizeof (int), 1, In);                      // Read The Header (i.e. Number Of Polygons) ( NEW )  
  74.   
  75.     polyData = new POLYGON [polyNum];                           // Allocate The Memory ( NEW )  
  76.   
  77.     fread (&polyData[0], sizeof (POLYGON) * polyNum, 1, In);    // Read In All Polygon Data ( NEW )  
  78.   
  79.     fclose (In);                                                // Close The File ( NEW )  
  80.   
  81.     return TRUE;                                                // It Worked ( NEW )  
  82. }  
  83.   
  84. // Math Functions  
  85. inline float DotProduct (VECTOR &V1, VECTOR &V2)                // Calculate The Angle Between The 2 Vectors ( NEW )  
  86. {  
  87.     return V1.X * V2.X + V1.Y * V2.Y + V1.Z * V2.Z;             // Return The Angle ( NEW )  
  88. }  
  89.   
  90. inline float Magnitude (VECTOR &V)                              // Calculate The Length Of The Vector ( NEW )  
  91. {  
  92.     return sqrtf (V.X * V.X + V.Y * V.Y + V.Z * V.Z);           // Return The Length Of The Vector ( NEW )  
  93. }  
  94.   
  95. void Normalize (VECTOR &V)                                      // Creates A Vector With A Unit Length Of 1 ( NEW )  
  96. {  
  97.     float M = Magnitude (V);                                    // Calculate The Length Of The Vector  ( NEW )  
  98.   
  99.     if (M != 0.0f)                                              // Make Sure We Don't Divide By 0  ( NEW )  
  100.     {  
  101.         V.X /= M;                                               // Normalize The 3 Components  ( NEW )  
  102.         V.Y /= M;  
  103.         V.Z /= M;  
  104.     }  
  105. }  
  106.   
  107. void RotateVector (MATRIX &M, VECTOR &V, VECTOR &D)             // Rotate A Vector Using The Supplied Matrix ( NEW )  
  108. {  
  109.     D.X = (M.Data[0] * V.X) + (M.Data[4] * V.Y) + (M.Data[8]  * V.Z);   // Rotate Around The X Axis ( NEW )  
  110.     D.Y = (M.Data[1] * V.X) + (M.Data[5] * V.Y) + (M.Data[9]  * V.Z);   // Rotate Around The Y Axis ( NEW )  
  111.     D.Z = (M.Data[2] * V.X) + (M.Data[6] * V.Y) + (M.Data[10] * V.Z);   // Rotate Around The Z Axis ( NEW )  
  112. }  
  113.   
  114.   
  115.   
  116. bool initialize()  
  117. {  
  118.     int i;  
  119.     char Line[255];  
  120.     float shaderData[32][3];  
  121.   
  122.     FILE *In    = NULL;  
  123.     In = fopen ("Data\\shader.txt""r");     
  124.   
  125.     if (In)  
  126.     {  
  127.         for (i = 0; i < 32; i++)  
  128.         {  
  129.             if (feof (In))  
  130.                 break;  
  131.   
  132.             fgets (Line, 255, In);  
  133.   
  134.             shaderData[i][0] = shaderData[i][1] = shaderData[i][2] = float(atof (Line));  
  135.         }  
  136.   
  137.         fclose (In);  
  138.     }  
  139.     else  
  140.         return false;  
  141.   
  142.     osg::Image *image = new osg::Image;  
  143.     image->allocateImage(32, 1, 1, GL_RGB, GL_FLOAT);  
  144.     osg::Vec3 *dataPtr = (osg::Vec3*)(image->data());  
  145.     for (int i = 0; i < 32; ++i)  
  146.     {  
  147.         *dataPtr++ = osg::Vec3(shaderData[i][0], shaderData[i][1], shaderData[i][2]);  
  148.     }  
  149.   
  150.     g_Texture1D = new osg::Texture1D;  
  151.     g_Texture1D->setFilter(osg::Texture::MAG_FILTER, osg::Texture::NEAREST);  
  152.     g_Texture1D->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST);  
  153.     g_Texture1D->setImage(image);  
  154.   
  155.     lightAngle.X = 0.0f;      
  156.     lightAngle.Y = 0.0f;      
  157.     lightAngle.Z = 1.0f;  
  158.   
  159.     Normalize (lightAngle);  
  160.   
  161.     return ReadMesh ();  
  162. }  
  163.   
  164.   
  165.   
  166. osg::Geode* createModelGeode()  
  167. {  
  168.     osg::Geode *geode = new osg::Geode;  
  169.     osg::Geometry *geometry = new osg::Geometry;  
  170.     osg::Vec3Array *vertexArray = new osg::Vec3Array;  
  171.     osg::Vec3Array *colorArray = new osg::Vec3Array;  
  172.     colorArray->push_back(osg::Vec3(1.0, 1.0, 1.0));  
  173.     geometry->setColorArray(colorArray, osg::Array::BIND_OVERALL);  
  174.       
  175.     for (int i = 0; i < polyNum; i++)  
  176.     {  
  177.         for (int j = 0; j < 3; j++)  
  178.         {  
  179.             vertexArray->push_back(osg::Vec3(polyData[i].Verts[j].Pos.X,polyData[i].Verts[j].Pos.Y,polyData[i].Verts[j].Pos.Z));  
  180.         }  
  181.     }  
  182.   
  183.     geometry->setVertexArray(vertexArray);  
  184.     geometry->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);  
  185.     geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES, 0, vertexArray->size()));  
  186.     geode->addDrawable(geometry);  
  187.     return geode;  
  188. }  
  189.   
  190. class RotAxisCallback : public osg::NodeCallback  
  191. {  
  192. public:  
  193.     RotAxisCallback(const osg::Vec3& axis, double rotSpeed = 0.0, double currentAngle = 0.0)  
  194.         : _rotAxis(axis), _rotSpeed(rotSpeed), _currentAngle(currentAngle){ }  
  195.   
  196.     virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)  
  197.     {  
  198.         osg::MatrixTransform *rotMT = dynamic_cast<osg::MatrixTransform*>(node);  
  199.         if (!rotMT)  
  200.             return;  
  201.         rotMT->setMatrix(osg::Matrix::rotate(_currentAngle, _rotAxis));  
  202.         _currentAngle += _rotSpeed;  
  203.   
  204.         traverse(node, nv);  
  205.     }  
  206.   
  207.     void setRotateSpeed(double speed)  
  208.     {  
  209.         _rotSpeed = speed;  
  210.     }  
  211.   
  212.     double getRotateSpeed() const  
  213.     {  
  214.         return _rotSpeed;  
  215.     }  
  216.       
  217.     double getCurrentAngle() const  
  218.     {  
  219.         return _currentAngle;  
  220.     }  
  221.   
  222. private:  
  223.     osg::Vec3       _rotAxis;  
  224.     double          _currentAngle;  
  225.     double          _rotSpeed;  
  226. };  
  227.   
  228. //  
  229. class ManipulatorSceneHandler : public osgGA::GUIEventHandler  
  230. {  
  231. public:  
  232.     ManipulatorSceneHandler()  
  233.     {  
  234.     }  
  235.   
  236.     virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)  
  237.     {  
  238.         osgViewer::Viewer *viewer = dynamic_cast<osgViewer::Viewer*>(&aa);  
  239.         if (!viewer)  
  240.             return false;  
  241.         if (!viewer->getSceneData())  
  242.             return false;  
  243.         if (ea.getHandled())   
  244.             return false;  
  245.   
  246.         osg::Group *root = viewer->getSceneData()->asGroup();  
  247.   
  248.         switch(ea.getEventType())  
  249.         {  
  250.         case(osgGA::GUIEventAdapter::KEYDOWN):  
  251.             {  
  252.                 if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Space)  
  253.                 {  
  254.                     static bool flag = true;  
  255.   
  256.                     if (!g_RotMT)  
  257.                         return false;  
  258.                     RotAxisCallback *rotCallback = dynamic_cast<RotAxisCallback*>(g_RotMT->getUpdateCallback());  
  259.                     if (!rotCallback)  
  260.                         return false;  
  261.   
  262.                     if(flag)  
  263.                     {  
  264.                         double speed = rotCallback->getRotateSpeed();  
  265.                         speed -= 0.02;  
  266.                         rotCallback->setRotateSpeed(speed);  
  267.                     }  
  268.                     else  
  269.                     {  
  270.                         rotCallback->setRotateSpeed(0);  
  271.                     }  
  272.                     flag = !flag;  
  273.                 }  
  274.   
  275.                 if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Up)  
  276.                 {  
  277.                     if (!g_OutlineGeode)  
  278.                         return false;  
  279.                     osg::LineWidth *lineWidth = dynamic_cast<osg::LineWidth*>( g_OutlineGeode->getOrCreateStateSet()->getAttribute(osg::StateAttribute::LINEWIDTH));  
  280.                     float w = lineWidth->getWidth();  
  281.                     w += 1.0f;  
  282.                     lineWidth->setWidth(w);    
  283.                 }  
  284.                 if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Down)  
  285.                 {  
  286.                     if (!g_OutlineGeode)  
  287.                         return false;  
  288.                     osg::LineWidth *lineWidth = dynamic_cast<osg::LineWidth*>(g_OutlineGeode->getOrCreateStateSet()->getAttribute(osg::StateAttribute::LINEWIDTH));  
  289.                     float w = lineWidth->getWidth();  
  290.                     w -= 1.0f;  
  291.                     lineWidth->setWidth(w);    
  292.                 }  
  293.             }  
  294.         defaultbreak;  
  295.         }  
  296.         return false;  
  297.     }  
  298. };  
  299.   
  300.   
  301. class ToonShadingCallback : public osg::NodeCallback  
  302. {  
  303. public:  
  304.   
  305.     virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)  
  306.     {  
  307.         osg::Geode *geode = dynamic_cast<osg::Geode*>(node);  
  308.         if(!geode)  
  309.             return;  
  310.         osg::Geometry *model = dynamic_cast<osg::Geometry*>(geode->getDrawable(0));  
  311.         if (!model)  
  312.             return;  
  313.       
  314.         osg::FloatArray *textureArray = new osg::FloatArray;  
  315.           
  316.         for (int i = 0; i < polyNum; i++)  
  317.         {  
  318.             for (int j = 0; j < 3; j++)  
  319.             {  
  320.                 osg::Vec3 nor;  
  321.   
  322.                 nor.x() = polyData[i].Verts[j].Nor.X;  
  323.                 nor.y() = polyData[i].Verts[j].Nor.Y;  
  324.                 nor.z() = polyData[i].Verts[j].Nor.Z;  
  325.   
  326.                 RotAxisCallback *rotCallback = dynamic_cast<RotAxisCallback*>(g_RotMT->getUpdateCallback());  
  327.                 double angle = rotCallback->getCurrentAngle();  
  328.                 nor = nor * osg::Matrix::rotate(angle, osg::Y_AXIS);  
  329.                 nor.normalize();  
  330.   
  331.                 osg::Vec3 lightDir = osg::Vec3(lightAngle.X, lightAngle.Y, lightAngle.Z);  
  332.   
  333.                 float TmpShade = nor * lightDir;  
  334.   
  335.                 if (TmpShade < 0.0f)  
  336.                     TmpShade = 0.0f;  
  337.   
  338.                 textureArray->push_back(TmpShade);  
  339.             }  
  340.         }  
  341.         model->setTexCoordArray(0, textureArray, osg::Array::BIND_PER_VERTEX);  
  342.         model->getOrCreateStateSet()->setTextureAttributeAndModes(0, g_Texture1D);  
  343.   
  344.         traverse(node, nv);  
  345.     }  
  346. };  
  347.   
  348.   
  349. //  
  350. //osgNeHe  
  351. //  
  352.   
  353. class ViewerWidget : public QWidget, public osgViewer::Viewer  
  354. {  
  355. public:  
  356.     ViewerWidget(osg::Node *scene = NULL)  
  357.     {  
  358.         QWidget* renderWidget = getRenderWidget( createGraphicsWindow(0,0,100,100), scene);  
  359.   
  360.         QVBoxLayout* layout = new QVBoxLayout;  
  361.         layout->addWidget(renderWidget);  
  362.         layout->setContentsMargins(0, 0, 0, 1);  
  363.         setLayout( layout );  
  364.   
  365.         connect( &_timer, SIGNAL(timeout()), this, SLOT(update()) );  
  366.         _timer.start( 10 );  
  367.     }  
  368.   
  369.     QWidget* getRenderWidget( osgQt::GraphicsWindowQt* gw, osg::Node* scene )  
  370.     {  
  371.         osg::Camera* camera = this->getCamera();  
  372.         camera->setGraphicsContext( gw );  
  373.   
  374.         const osg::GraphicsContext::Traits* traits = gw->getTraits();  
  375.   
  376.         camera->setClearColor( osg::Vec4(0.7f, 0.7f, 0.7f, 0.0f) );  
  377.         camera->setViewport( new osg::Viewport(0, 0, traits->width, traits->height) );  
  378.         camera->setProjectionMatrixAsPerspective(45.0f, static_cast<double>(traits->width)/static_cast<double>(traits->height), 0.1f, 100.0f );  
  379.         camera->setViewMatrixAsLookAt(osg::Vec3d(0, 0, 0), osg::Vec3d(0, 0, -1), osg::Vec3d(0, 1, 0));  
  380.   
  381.         this->setSceneData( scene );  
  382.         this->addEventHandler(new ManipulatorSceneHandler);  
  383.   
  384.         return gw->getGLWidget();  
  385.     }  
  386.   
  387.     osgQt::GraphicsWindowQt* createGraphicsWindow( int x, int y, int w, int h, const std::string& name=""bool windowDecoration=false )  
  388.     {  
  389.         osg::DisplaySettings* ds = osg::DisplaySettings::instance().get();  
  390.         osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;  
  391.         traits->windowName = name;  
  392.         traits->windowDecoration = windowDecoration;  
  393.         traits->x = x;  
  394.         traits->y = y;  
  395.         traits->width = w;  
  396.         traits->height = h;  
  397.         traits->doubleBuffer = true;  
  398.         traits->alpha = ds->getMinimumNumAlphaBits();  
  399.         traits->stencil = ds->getMinimumNumStencilBits();  
  400.         traits->sampleBuffers = ds->getMultiSamples();  
  401.         traits->samples = ds->getNumMultiSamples();  
  402.   
  403.         return new osgQt::GraphicsWindowQt(traits.get());  
  404.     }  
  405.   
  406.     virtual void paintEvent( QPaintEvent* event )  
  407.     {   
  408.         frame();   
  409.     }  
  410.   
  411. protected:  
  412.   
  413.     QTimer _timer;  
  414. };  
  415.   
  416.   
  417.   
  418. osg::Node*  buildScene()  
  419. {  
  420.     initialize();  
  421.   
  422.     osg::Group *root = new osg::Group;  
  423.   
  424.     osg::MatrixTransform *zoomMT = new osg::MatrixTransform;  
  425.     zoomMT->setMatrix(osg::Matrix::translate(0,0,-2));  
  426.   
  427.     osg::MatrixTransform *rotMT = new osg::MatrixTransform;  
  428.     g_RotMT = rotMT;  
  429.     rotMT->addUpdateCallback(new RotAxisCallback(osg::Y_AXIS));  
  430.   
  431.     root->addChild(zoomMT);  
  432.     zoomMT->addChild(rotMT);  
  433.       
  434.   
  435.     //  
  436.     //Cell Shading Model  
  437.     osg::Geode *cellModel = createModelGeode();  
  438.     cellModel->addUpdateCallback(new ToonShadingCallback);  
  439.     rotMT->addChild(cellModel);  
  440.   
  441.   
  442.     //  
  443.     //Outline Model  
  444.     osg::Geode *outlineModel = createModelGeode();  
  445.     g_OutlineGeode = outlineModel;  
  446.     osg::Geometry *d = dynamic_cast<osg::Geometry*>(outlineModel->getDrawable(0));  
  447.     if(d)  
  448.     {  
  449.         osg::Vec3Array *vecArray = dynamic_cast<osg::Vec3Array*>(d->getColorArray());  
  450.         vecArray->at(0).set(osg::Vec3(0,0,0));  
  451.         d->setColorArray(vecArray, osg::Array::BIND_OVERALL);  
  452.     }  
  453.     osg::BlendFunc *blendFunc = new osg::BlendFunc(osg::BlendFunc::SRC_ALPHA, osg::BlendFunc::ONE_MINUS_SRC_ALPHA);  
  454.     osg::PolygonMode    *polygonMode = new osg::PolygonMode(osg::PolygonMode::BACK, osg::PolygonMode::LINE);  
  455.     osg::LineWidth *lineWidth = new osg::LineWidth(3.0f);  
  456.     osg::CullFace *cullFace = new osg::CullFace(osg::CullFace::FRONT);  
  457.   
  458.     outlineModel->getOrCreateStateSet()->setAttributeAndModes(blendFunc);  
  459.     outlineModel->getOrCreateStateSet()->setAttributeAndModes(polygonMode);  
  460.     outlineModel->getOrCreateStateSet()->setAttributeAndModes(lineWidth);  
  461.     outlineModel->getOrCreateStateSet()->setAttributeAndModes(cullFace);  
  462.   
  463.     rotMT->addChild(outlineModel);  
  464.   
  465.     return root;  
  466. }  
  467.   
  468.   
  469.   
  470. int main( int argc, char** argv )  
  471. {  
  472.     QApplication app(argc, argv);  
  473.     ViewerWidget* viewWidget = new ViewerWidget(buildScene());  
  474.     viewWidget->setGeometry( 100, 100, 640, 480 );  
  475.     viewWidget->show();  
  476.     return app.exec();  
  477. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
编译运行 OpenSceneGraph-OpenSceneGraph-3.6.4 需要按照以下步骤进行操作: 1. 首先,确保你的计算机上已经安装了 CMake,C++ 编译器和 OpenGL 兼容的图形驱动程序。这些是编译和运行 OpenSceneGraph 所必需的工具和库。 2. 下载 OpenSceneGraph-OpenSceneGraph-3.6.4 的源代码,可以在官方网站或开源项目托管网站上找到。确保下载的版本正确,避免出错。 3. 解压源代码文件并进入解压后的目录。 4. 创建一个用于构建的构建目录,并进入该目录。例如:mkdir build && cd build。 5. 运行 CMake 命令来生成构建系统所需的文件和配置。命令可能类似于:cmake path/to/OpenSceneGraph-OpenSceneGraph-3.6.4。你可以使用其他参数和选项来自定义构建过程。 6. 确保 CMake 执行成功并生成了构建系统所需的文件。 7. 使用你的 C++ 编译器来构建 OpenSceneGraph。可以使用 make 命令,或者其他编译工具,根据你的操作系统和编译环境来选择。例如:make。 8. 等待编译完成,这可能需要一段时间,具体取决于你的计算机性能。 9. 构建完成后,检查是否有错误或警告信息。如果有,需要解决它们,并重新运行编译步骤。 10. 运行编译好的 OpenSceneGraph 可执行文件,这将启动 OpenSceneGraph 程序并运行示例或其他自定义的应用程序。 总之,编译和运行 OpenSceneGraph-OpenSceneGraph-3.6.4 需要先安装必需的工具和库,然后使用 CMake 生成构建系统所需的文件,再使用 C++ 编译器进行编译,最后运行生成的可执行文件。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值