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

  • 简介

NeHe教程在这节课向我们介绍了如何模拟一根绳子的运动状态,简单的说,就是把绳子先离散化,把它想象成一个个紧密排列的点,每两个点之间有弹性约束。其实这就是简单的有限元思想。这节课的内容和上节课一样,主要是和物理、数学有关系,和图形图像的关系不大。

  • 实现

首先我们同样是创建场景中的几何体:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. root->addChild(createGround());   //地面  
  2. root->addChild(createRopeShadow()); //绳子阴影  
  3. root->addChild(createRope());   //绳子  

接下来设置各个几何体的更新回调:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. osg::Geode* createRope()  
  2. {  
  3.     osg::Geode *geode = new osg::Geode;  
  4.     osg::Geometry *geometry = new osg::Geometry;  
  5.     geometry->setUpdateCallback(new RopeUpdateCallback);  
  6.     osg::Vec3Array *vertexArray = new osg::Vec3Array;  
  7.     osg::Vec3Array *colorArray = new osg::Vec3Array;  
  8.   
  9.     colorArray->push_back(osg::Vec3(1, 1, 0));  
  10.   
  11.     for (int a = 0; a < ropeSimulation->numOfMasses - 1; ++a)  
  12.     {  
  13.         Mass* mass1 = ropeSimulation->getMass(a);  
  14.         Vector3D* pos1 = &mass1->pos;  
  15.   
  16.         Mass* mass2 = ropeSimulation->getMass(a + 1);  
  17.         Vector3D* pos2 = &mass2->pos;  
  18.   
  19.         vertexArray->push_back(osg::Vec3(pos1->x, pos1->y, pos1->z));     
  20.         vertexArray->push_back(osg::Vec3(pos2->x, pos2->y, pos2->z));  
  21.     }  
  22.   
  23.     geometry->setVertexArray(vertexArray);  
  24.     geometry->setColorArray(colorArray, osg::Array::BIND_OVERALL);  
  25.     geometry->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);  
  26.     geometry->getOrCreateStateSet()->setMode(GL_DEPTH_TEST, false);  
  27.     geometry->getOrCreateStateSet()->setAttributeAndModes(new osg::LineWidth(4.0));  
  28.     geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES, 0, vertexArray->size()));  
  29.     geode->addDrawable(geometry);  
  30.     return geode;  
  31. }  

在帧循环中更新绳子的各项参数:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. case (osgGA::GUIEventAdapter::FRAME):  
  2.     {  
  3.         double dt = 0.0;  
  4.         _currentTick = osg::Timer::instance()->tick();  
  5.         if (_currentTick != _lastTick)  
  6.         {         
  7.             dt = osg::Timer::instance()->delta_s(_lastTick, _currentTick);  
  8.             _lastTick = _currentTick;  
  9.         }  
  10.   
  11.         ropeSimulation->setRopeConnectionVel(ropeConnectionVel);       
  12.   
  13.         float maxPossible_dt = 0.002f;                                        
  14.   
  15.         int numOfIterations = (int)(dt / maxPossible_dt) + 1;             
  16.         if (numOfIterations != 0)  
  17.             dt = dt / numOfIterations;    
  18.   
  19.         for (int a = 0; a < numOfIterations; ++a)  
  20.             ropeSimulation->operate(dt);  
  21.     }  

将各部分添加到场景根节点,编译运行程序:


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

[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/LineWidth>  
  13.   
  14. #include "Physics2.h"  
  15.   
  16.   
  17. //  
  18.   
  19. RopeSimulation* ropeSimulation = new RopeSimulation(  
  20.     80,                     // 80 Particles (Masses)  
  21.     0.05f,                  // Each Particle Has A Weight Of 50 Grams  
  22.     10000.0f,               // springConstant In The Rope  
  23.     0.05f,                  // Normal Length Of Springs In The Rope  
  24.     0.2f,                   // Spring Inner Friction Constant  
  25.     Vector3D(0, -9.81f, 0), // Gravitational Acceleration  
  26.     0.02f,                  // Air Friction Constant  
  27.     100.0f,                 // Ground Repel Constant  
  28.     0.2f,                   // Ground Slide Friction Constant  
  29.     2.0f,                   // Ground Absoption Constant  
  30.     -1.5f);                 // Height Of Ground  
  31.   
  32.   
  33.   
  34. bool initialize ()  
  35. {  
  36.     ropeSimulation->getMass(ropeSimulation->numOfMasses - 1)->vel.z = 10.0f;  
  37.     return true;  
  38. }  
  39.   
  40.   
  41. //  
  42.   
  43.   
  44. class GroundUpdateCallback : public osg::Drawable::UpdateCallback  
  45. {  
  46. public:  
  47.   
  48.     virtual void update(osg::NodeVisitor*, osg::Drawable* d)  
  49.     {  
  50.         osg::Geometry *geometry = dynamic_cast<osg::Geometry*>(d);  
  51.         if (!geometry)  
  52.             return;  
  53.   
  54.         osg::Vec3Array *vertexArray = dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray());  
  55.         if (!vertexArray)  
  56.             return;  
  57.   
  58.         vertexArray->clear();  
  59.           
  60.         vertexArray->push_back(osg::Vec3(20, ropeSimulation->groundHeight, 20));  
  61.         vertexArray->push_back(osg::Vec3(-20, ropeSimulation->groundHeight, 20));  
  62.         vertexArray->push_back(osg::Vec3(-20, ropeSimulation->groundHeight, -20));  
  63.         vertexArray->push_back(osg::Vec3(20, ropeSimulation->groundHeight, -20));  
  64.       
  65.         geometry->setVertexArray(vertexArray);  
  66.         vertexArray->dirty();  
  67.     }  
  68.   
  69. };  
  70.   
  71.   
  72.   
  73. class RopeShadowUpdateCallback : public osg::Drawable::UpdateCallback  
  74. {  
  75. public:  
  76.   
  77.     virtual void update(osg::NodeVisitor*, osg::Drawable* d)  
  78.     {  
  79.         osg::Geometry *geometry = dynamic_cast<osg::Geometry*>(d);  
  80.         if (!geometry)  
  81.             return;  
  82.   
  83.         osg::Vec3Array *vertexArray = dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray());  
  84.         if (!vertexArray)  
  85.             return;  
  86.   
  87.         vertexArray->clear();  
  88.   
  89.         for (int a = 0; a < ropeSimulation->numOfMasses - 1; ++a)  
  90.         {  
  91.             Mass* mass1 = ropeSimulation->getMass(a);  
  92.             Vector3D* pos1 = &mass1->pos;  
  93.   
  94.             Mass* mass2 = ropeSimulation->getMass(a + 1);  
  95.             Vector3D* pos2 = &mass2->pos;  
  96.             vertexArray->push_back(osg::Vec3(pos1->x, ropeSimulation->groundHeight, pos1->z));      // Draw Shadow At groundHeight  
  97.             vertexArray->push_back(osg::Vec3(pos2->x, ropeSimulation->groundHeight, pos2->z));      // Draw Shadow At groundHeight  
  98.         }  
  99.   
  100.         geometry->setVertexArray(vertexArray);  
  101.         vertexArray->dirty();  
  102.     }  
  103.   
  104. };  
  105.   
  106.   
  107. class RopeUpdateCallback : public osg::Drawable::UpdateCallback  
  108. {  
  109. public:  
  110.   
  111.     virtual void update(osg::NodeVisitor*, osg::Drawable* d)  
  112.     {  
  113.         osg::Geometry *geometry = dynamic_cast<osg::Geometry*>(d);  
  114.         if (!geometry)  
  115.             return;  
  116.   
  117.         osg::Vec3Array *vertexArray = dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray());  
  118.         if (!vertexArray)  
  119.             return;  
  120.   
  121.         vertexArray->clear();  
  122.   
  123.         for (int a = 0; a < ropeSimulation->numOfMasses - 1; ++a)  
  124.         {  
  125.             Mass* mass1 = ropeSimulation->getMass(a);  
  126.             Vector3D* pos1 = &mass1->pos;  
  127.   
  128.             Mass* mass2 = ropeSimulation->getMass(a + 1);  
  129.             Vector3D* pos2 = &mass2->pos;  
  130.   
  131.             vertexArray->push_back(osg::Vec3(pos1->x, pos1->y, pos1->z));     
  132.             vertexArray->push_back(osg::Vec3(pos2->x, pos2->y, pos2->z));  
  133.         }  
  134.   
  135.         geometry->setVertexArray(vertexArray);  
  136.         vertexArray->dirty();  
  137.     }  
  138.   
  139. };  
  140.   
  141.   
  142.   
  143.   
  144.   
  145. osg::Geode* createGround()  
  146. {  
  147.     osg::Geode *geode = new osg::Geode;  
  148.     osg::Geometry *geometry = new osg::Geometry;  
  149.     geometry->setUpdateCallback(new GroundUpdateCallback);  
  150.     osg::Vec3Array *vertexArray = new osg::Vec3Array;  
  151.     osg::Vec3Array *colorArray = new osg::Vec3Array;  
  152.       
  153.     colorArray->push_back(osg::Vec3(0, 0, 1.0));  
  154.     vertexArray->push_back(osg::Vec3(20, ropeSimulation->groundHeight, 20));  
  155.     colorArray->push_back(osg::Vec3(0, 0, 1.0));  
  156.     vertexArray->push_back(osg::Vec3(-20, ropeSimulation->groundHeight, 20));  
  157.     colorArray->push_back(osg::Vec3(0,0,0));  
  158.     vertexArray->push_back(osg::Vec3(-20, ropeSimulation->groundHeight, -20));  
  159.     colorArray->push_back(osg::Vec3(0,0,0));  
  160.     vertexArray->push_back(osg::Vec3(20, ropeSimulation->groundHeight, -20));  
  161.   
  162.     geometry->setVertexArray(vertexArray);  
  163.     geometry->setColorArray(colorArray, osg::Array::BIND_PER_VERTEX);  
  164.     geometry->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);  
  165.     geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, vertexArray->size()));  
  166.     geode->addDrawable(geometry);  
  167.     return geode;  
  168. }  
  169.   
  170.   
  171. osg::Geode* createRopeShadow()  
  172. {  
  173.     osg::Geode *geode = new osg::Geode;  
  174.     osg::Geometry *geometry = new osg::Geometry;  
  175.     geometry->setUpdateCallback(new RopeShadowUpdateCallback);  
  176.     osg::Vec3Array *vertexArray = new osg::Vec3Array;  
  177.     osg::Vec3Array *colorArray = new osg::Vec3Array;  
  178.   
  179.     colorArray->push_back(osg::Vec3(0, 0, 0));  
  180.       
  181.     for (int a = 0; a < ropeSimulation->numOfMasses - 1; ++a)  
  182.     {  
  183.         Mass* mass1 = ropeSimulation->getMass(a);  
  184.         Vector3D* pos1 = &mass1->pos;  
  185.   
  186.         Mass* mass2 = ropeSimulation->getMass(a + 1);  
  187.         Vector3D* pos2 = &mass2->pos;  
  188.         vertexArray->push_back(osg::Vec3(pos1->x, ropeSimulation->groundHeight, pos1->z));      // Draw Shadow At groundHeight  
  189.         vertexArray->push_back(osg::Vec3(pos2->x, ropeSimulation->groundHeight, pos2->z));      // Draw Shadow At groundHeight  
  190.     }  
  191.       
  192.     geometry->setVertexArray(vertexArray);  
  193.     geometry->setColorArray(colorArray, osg::Array::BIND_OVERALL);  
  194.     geometry->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);  
  195.     geometry->getOrCreateStateSet()->setAttributeAndModes(new osg::LineWidth(2.0));  
  196.     geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES, 0, vertexArray->size()));  
  197.     geode->addDrawable(geometry);  
  198.     return geode;  
  199. }  
  200.   
  201.   
  202. osg::Geode* createRope()  
  203. {  
  204.     osg::Geode *geode = new osg::Geode;  
  205.     osg::Geometry *geometry = new osg::Geometry;  
  206.     geometry->setUpdateCallback(new RopeUpdateCallback);  
  207.     osg::Vec3Array *vertexArray = new osg::Vec3Array;  
  208.     osg::Vec3Array *colorArray = new osg::Vec3Array;  
  209.   
  210.     colorArray->push_back(osg::Vec3(1, 1, 0));  
  211.   
  212.     for (int a = 0; a < ropeSimulation->numOfMasses - 1; ++a)  
  213.     {  
  214.         Mass* mass1 = ropeSimulation->getMass(a);  
  215.         Vector3D* pos1 = &mass1->pos;  
  216.   
  217.         Mass* mass2 = ropeSimulation->getMass(a + 1);  
  218.         Vector3D* pos2 = &mass2->pos;  
  219.   
  220.         vertexArray->push_back(osg::Vec3(pos1->x, pos1->y, pos1->z));     
  221.         vertexArray->push_back(osg::Vec3(pos2->x, pos2->y, pos2->z));  
  222.     }  
  223.   
  224.     geometry->setVertexArray(vertexArray);  
  225.     geometry->setColorArray(colorArray, osg::Array::BIND_OVERALL);  
  226.     geometry->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);  
  227.     geometry->getOrCreateStateSet()->setMode(GL_DEPTH_TEST, false);  
  228.     geometry->getOrCreateStateSet()->setAttributeAndModes(new osg::LineWidth(4.0));  
  229.     geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES, 0, vertexArray->size()));  
  230.     geode->addDrawable(geometry);  
  231.     return geode;  
  232. }  
  233.   
  234.   
  235.   
  236. //  
  237.   
  238. class ManipulatorSceneHandler : public osgGA::GUIEventHandler  
  239. {  
  240. public:  
  241.     ManipulatorSceneHandler()  
  242.     {  
  243.         _lastTick  =  osg::Timer::instance()->tick();  
  244.         _currentTick = _lastTick;  
  245.     }  
  246.   
  247. public:  
  248.     virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)  
  249.     {  
  250.         osgViewer::Viewer *viewer = dynamic_cast<osgViewer::Viewer*>(&aa);  
  251.         if (!viewer)  
  252.             return false;  
  253.         if (!viewer->getSceneData())  
  254.             return false;  
  255.         if (ea.getHandled())   
  256.             return false;  
  257.   
  258.         osg::Group *root = viewer->getSceneData()->asGroup();  
  259.   
  260.         switch(ea.getEventType())  
  261.         {  
  262.         case (osgGA::GUIEventAdapter::FRAME):  
  263.             {  
  264.                 double dt = 0.0;  
  265.                 _currentTick = osg::Timer::instance()->tick();  
  266.                 if (_currentTick != _lastTick)  
  267.                 {         
  268.                     dt = osg::Timer::instance()->delta_s(_lastTick, _currentTick);  
  269.                     _lastTick = _currentTick;  
  270.                 }  
  271.   
  272.                 ropeSimulation->setRopeConnectionVel(ropeConnectionVel);       
  273.   
  274.                 float maxPossible_dt = 0.002f;                                        
  275.   
  276.                 int numOfIterations = (int)(dt / maxPossible_dt) + 1;             
  277.                 if (numOfIterations != 0)  
  278.                     dt = dt / numOfIterations;    
  279.   
  280.                 for (int a = 0; a < numOfIterations; ++a)  
  281.                     ropeSimulation->operate(dt);  
  282.             }  
  283.             break;  
  284.         case(osgGA::GUIEventAdapter::KEYDOWN):  
  285.             {  
  286.                 if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Up)  
  287.                 {  
  288.                         ropeConnectionVel.z -= 1.0f;      
  289.                 }  
  290.   
  291.                 if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Down)  
  292.                 {  
  293.                     ropeConnectionVel.z += 1.0f;  
  294.                 }  
  295.                 if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Left)  
  296.                 {  
  297.                     ropeConnectionVel.x -= 1.0f;  
  298.                 }  
  299.   
  300.                 if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Right)  
  301.                 {  
  302.                         ropeConnectionVel.x += 1.0f;  
  303.                 }  
  304.                 if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Home)  
  305.                 {  
  306.                     ropeConnectionVel.y += 1.0f;      
  307.                 }  
  308.   
  309.                 if (ea.getKey() == osgGA::GUIEventAdapter::KEY_End)  
  310.                 {  
  311.                     ropeConnectionVel.y -= 1.0f;  
  312.                 }  
  313.             }  
  314.             break;  
  315.   
  316.         defaultbreak;  
  317.         }  
  318.         return false;  
  319.     }  
  320.   
  321.     osg::Timer_t _lastTick;  
  322.     osg::Timer_t _currentTick;  
  323.     Vector3D ropeConnectionVel;  
  324. };  
  325.   
  326.   
  327.   
  328.   
  329.   
  330.   
  331.   
  332. class ViewerWidget : public QWidget, public osgViewer::Viewer  
  333. {  
  334. public:  
  335.     ViewerWidget(osg::Node *scene = NULL)  
  336.     {  
  337.         QWidget* renderWidget = getRenderWidget( createGraphicsWindow(0,0,100,100), scene);  
  338.   
  339.         QVBoxLayout* layout = new QVBoxLayout;  
  340.         layout->addWidget(renderWidget);  
  341.         layout->setContentsMargins(0, 0, 0, 1);  
  342.         setLayout( layout );  
  343.   
  344.         connect( &_timer, SIGNAL(timeout()), this, SLOT(update()) );  
  345.         _timer.start( 10 );  
  346.     }  
  347.   
  348.     QWidget* getRenderWidget( osgQt::GraphicsWindowQt* gw, osg::Node* scene )  
  349.     {  
  350.         osg::Camera* camera = this->getCamera();  
  351.         camera->setGraphicsContext( gw );  
  352.   
  353.         const osg::GraphicsContext::Traits* traits = gw->getTraits();  
  354.   
  355.         camera->setClearColor( osg::Vec4(0.0, 0.0, 0.0, 0.5) );  
  356.         camera->setViewport( new osg::Viewport(0, 0, traits->width, traits->height) );  
  357.         camera->setProjectionMatrixAsPerspective(45.0f, static_cast<double>(traits->width)/static_cast<double>(traits->height), 0.1f, 100.0f );  
  358.         camera->setViewMatrixAsLookAt(osg::Vec3d(0, 0, 4), osg::Vec3d(0, 0, 0), osg::Vec3d(0, 1, 0));  
  359.   
  360.         this->setSceneData( scene );  
  361.         this->addEventHandler(new ManipulatorSceneHandler);  
  362.         return gw->getGLWidget();  
  363.     }  
  364.   
  365.     osgQt::GraphicsWindowQt* createGraphicsWindow( int x, int y, int w, int h, const std::string& name=""bool windowDecoration=false )  
  366.     {  
  367.         osg::DisplaySettings* ds = osg::DisplaySettings::instance().get();  
  368.         osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;  
  369.         traits->windowName = name;  
  370.         traits->windowDecoration = windowDecoration;  
  371.         traits->x = x;  
  372.         traits->y = y;  
  373.         traits->width = w;  
  374.         traits->height = h;  
  375.         traits->doubleBuffer = true;  
  376.         traits->alpha = ds->getMinimumNumAlphaBits();  
  377.         traits->stencil = ds->getMinimumNumStencilBits();  
  378.         traits->sampleBuffers = ds->getMultiSamples();  
  379.         traits->samples = ds->getNumMultiSamples();  
  380.   
  381.         return new osgQt::GraphicsWindowQt(traits.get());  
  382.     }  
  383.   
  384.     virtual void paintEvent( QPaintEvent* event )  
  385.     {   
  386.         frame();   
  387.     }  
  388.   
  389. protected:  
  390.   
  391.     QTimer _timer;  
  392. };  
  393.   
  394.   
  395.   
  396. osg::Node*  buildScene()  
  397. {  
  398.     initialize();  
  399.   
  400.     osg::Group *root = new osg::Group;  
  401.   
  402.     root->addChild(createGround());  
  403.     root->addChild(createRopeShadow());  
  404.     root->addChild(createRope());  
  405.   
  406.     return root;  
  407. }  
  408.   
  409.   
  410.   
  411. int main( int argc, char** argv )  
  412. {  
  413.     QApplication app(argc, argv);  
  414.     ViewerWidget* viewWidget = new ViewerWidget(buildScene());  
  415.     viewWidget->setGeometry( 100, 100, 640, 480 );  
  416.     viewWidget->show();  
  417.     return app.exec();  
  418. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
创建一个OpenGL窗口: 在这个教程里,我将教你在Windows环境中创建OpenGL程序.它将显示一个空的OpenGL窗口,可以在窗口和全屏模式下切换,按ESC退出.它是我们以后应用程序的框架. 理解OpenGL如何工作非常重要,你可以在教程的末尾下载源程序,但我强烈建议你至少读一遍教程,然后再开始编程. 2.你的第一个多边形: 在第一个教程的基础上,我们添加了一个三角形和一个四边形。也许你认为这很简单,但你已经迈出了一大步,要知道任何在OpenGL中绘制的模型都会被分解为这两种简单的图形。 读完了这一,你会学到如何在空间放置模型,并且会知道深度缓存的概念。 3.添加颜色: 作为第二的扩展,我将叫你如何使用颜色。你将理解两种着色模式,在左图中,三角形用的是光滑着色,四边形用的是平面着色。 注意三角形上的颜色是如何混合的。 颜色为OpenGlL 工程增加很多。通过理解平面着色(flat coloring)和平滑着色(smooth coloring),你能显著的改善你的OpenGL Demo的样子。 4.旋转: 在这一里,我将教会你如何旋转三角形和四边形。左图中的三角形沿Y轴旋转,四边形沿着X 轴旋转。 这一章将引入两个变量, rtri 被用来存储三角形的角度, rquad存储四边形的角度。 和容易创建一个多边形组成的场景。让这些物体动起来是整个场景变得生动起来。在后面的程钟我将教给你如何绕屏幕上的一个点旋转物体,使得物体绕屏幕而不是它的轴转动。 5.3D形体: 既然我们已经领会到多边形,方形,色彩和旋转。现在该建立3D物体了。我将使用多边形和矩形c创建3D物体。这次我们将扩展上一章的教程,并且将三角形转换成一个彩色的棱锥,把正方形变为一个实心正方体。棱锥使用混合色,正方体每个面使用一种颜色。在3D空间创建物体可能很费时间,但是所获得的结果(收获)值得这样做。充分发挥你的想象力吧。 6.纹理映射: 你想要它,它现在就在这里了,那就是 ... 纹理映射!!!在这一章我将教会你如何将一幅位图(bitmap)映射到正方体的六个面上去。我们将使用第一章的OpenGL代码来创建工程。创建一个空的窗口比修改上一的代码更容易。 你将会发现第一章的代码在对于快速创建工程来说是及其有价值的。第一章的代码为你设置好了一切,你所需要做的只是集中精力为效果编程。 7.纹理滤波, 光照和键盘控制: 好的,我希望到现在你已经理解了所有的东西,因为这是一个巨大的教程。我想教给你两个新的方法来过滤(filter)你的纹理,简单的光照,键盘控制并且还可能更多 :) .如果你对到这一为止你所学的东西并不充满信心,那就回头复习一下。玩一下其它程的代码,不要操之过急。最好专心把每一学好,而不是蜻蜓点水,只知道如何把东西做出来。 8.混合 有理由等一下,一个来自很酷的Hypercosm的程序员伙伴问(我)他是否可以写一章关于混合的教程。第八通常正是讲混合的,所以太巧了。这一章教程扩展了第七章。混合是一项很酷的技术 .. 我希望你们能好好享受这一章教程。这一章的作者是Tom Stanis他在这制作一章上花费了很多精力,所以让他知道你觉得怎么样。混合可不是一个好讲的话题。 9.在3D空间中移动位图: 这一章覆盖了一些你们要求的主题,你想知道如何移动你在3D屏幕空间上创造的物体。你想要知道如何在屏幕上绘制一幅位图,并且位图的黑色部分不会覆盖它后面的东西。你想要简单的动画,想要更多的混合的应用,这一章将教会你所有这些。You'll notice there's no spinning boxes(yaker:很惭愧这一句我不是很明白)。前面的程覆盖了OpenGL的基础,每一章都基于前面的内容。前面的程涵盖了基础的OpenGL,每一都是在前一的基础上创建的。这一是前面几知识的综合,当你学习这时,请确保你已经掌握了前面几的知识。 10.加载3D世界,并在其中漫游: 你一直期待的教程来了!这一章友一个叫Lionel Brites的伙伴制作。这一里你讲学到如何导入一个3D世界。代码仍然使用第一章的,但是,程页面只是解释了新的部分,包括导入3D场景,在3D世界中移动。下载VC++代码并且在你阅读教程的同时阅读代码。按[B]键控制混合,[F]键控制滤波,[L]键控制光照(但光并不随场景移动),还有[Page UP]和[Page Down]键。我希望你能喜欢Lionel对网站的贡献。我有空的时候我会让这个教程更容易学习。 11.旗帜效果

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值