作者:trcj1
博客:FadeIn to Bloom


  成熟图像引擎往往对底层操作做了层层封装,用户或许能轻易地将复杂模型加入到游戏里,却在画一个三角形时摸不着头脑。本文阐述如何在Ogre里画三角形,如果有些许DirectX或者OpenGL的基础知识,理解起来会更加容易。
 

  1.  
  2.   Ogre用树结构来组织场景,所有希望被遍历到的实体都需要挂接在树节点下,此类有挂接能
  3. 力的实体需要继承自MovableObject类;而如果实体想被赋予渲染的能力,则要继承Renderable类。
  4. 如此一来,我们的三角形类如下:
  5.  
  6.  
  7. class Triangle : public Ogre::MovableObject, public Ogre::Renderable
  8.  
  9.  
  10.   接下来要做的基本上就是填充两个父类中的十多个纯虚方法,这里我们仅挑出最主要的几个
  11. 进行说明。
  12.  
  13.   1. 来自MovableObject的_updateRenderQueue()函数。它在场景遍历到本实体时被调用,你
  14. 可以选择此时将待渲染的对象加入到渲染队列中,由于我们的三角形本身即继承自Renderable,
  15. 所以我们将自己加入到队列里:
  16.  
  17.  
  18. void Triangle::_updateRenderQueue(Ogre::RenderQueue* queue)
  19. {
  20. queue-gt;addRenderable(this);
  21. }
  22.  
  23.  
  24.   2. 接着是来自Renderable的getRenderOperation()函数。它在渲染队列稍后遍历每一个待渲
  25. 单位时被调用,你需要选择这个时刻把渲染相关的数据(顶点数据、组织方式、数目、索引等等)
  26. 以RenderOperation数据结构的形式提交给引擎。可见RenderOperation决定了你将渲染出何种东西,
  27. 其实本文展示的核心即是对RenderOperation的定制。
  28.  
  29.   我们在初始化三角形时构建RenderOperation相关数据:
  30.  
  31.  
  32. void Triangle::_createBuffers()
  33. {
  34. // 三角形的三个顶点位置数据
  35. float vertices[3][3] = {
  36. -1.0f, 1.0f, 0.0f, // 0 position
  37. 1.0f, 1.0f, 0.0f, // 1 position
  38. 0.0f, -1.0f, 0.0f, // 2 position
  39. };
  40.  
  41. // 顶点颜色
  42. Ogre::RenderSystem* rs = Ogre::Root::getSingleton().getRenderSystem();
  43. Ogre::RGBA colours[3];
  44. rs-gt;convertColourValue(Ogre::ColourValue(1.0f, 0.0f, 0.0f), amp;colours[0]); // 0 colour
  45. rs-gt;convertColourValue(Ogre::ColourValue(0.0f, 1.0f, 0.0f), amp;colours[1]); // 1 colour
  46. rs-gt;convertColourValue(Ogre::ColourValue(0.0f, 0.0f, 1.0f), amp;colours[2]); // 2 colour
  47.  
  48. // 顶点索引
  49. Ogre::ushort faces[3] = {
  50. 0, 1, 2, // 0 face
  51. };
  52.  
  53. // 创建VertexData对象管理顶点数据
  54. mVertexData = new Ogre::VertexData();
  55. mVertexData-gt;vertexStart = 0;
  56. mVertexData-gt;vertexCount = 3;
  57.  
  58. Ogre::VertexDeclaration* decl = mVertexData-gt;vertexDeclaration;
  59. Ogre::VertexBufferBinding* binding = mVertexData-gt;vertexBufferBinding;
  60.  
  61. // 设置顶点声明,我们的顶点声明仅有一个数据流且只包含位置、颜色
  62. size_t offset = 0;
  63. decl-gt;addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_POSITION);
  64. offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
  65. decl-gt;addElement(0, offset, Ogre::VET_COLOUR, Ogre::VES_DIFFUSE);
  66. offset += Ogre::VertexElement::getTypeSize(Ogre::VET_COLOUR);
  67.  
  68. // 创建顶点缓存并将顶点数据填充进去
  69. Ogre::HardwareVertexBufferSharedPtr vertexBuffer = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(
  70. decl-gt;getVertexSize(0), 3,
  71. Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);
  72. float* lockPtr = static_castlt;float*gt;(vertexBuffer-gt;lock(0, vertexBuffer-gt;getSizeInBytes(), Ogre::HardwareBuffer::HBL_DISCARD));
  73. Ogre::RGBA* pCol;
  74. for (int i = 0; i lt; 3; ++i)
  75. {
  76. *lockPtr++ = vertices[i][0];
  77. *lockPtr++ = vertices[i][1];
  78. *lockPtr++ = vertices[i][2];
  79. pCol = static_castlt;Ogre::RGBA*gt;(static_castlt;void*gt;(lockPtr));
  80. *pCol++ = colours[i];
  81. lockPtr = static_castlt;float*gt;(static_castlt;void*gt;(pCol));
  82. }
  83. vertexBuffer-gt;unlock();
  84.  
  85. // 将顶点缓存绑定到0号数据流
  86. binding-gt;setBinding(0, vertexBuffer);
  87.  
  88. // 创建IndexData对象管理顶点索引
  89. mIndexData = new Ogre::IndexData();
  90. mIndexData-gt;indexStart = 0;
  91. mIndexData-gt;indexCount = 3;
  92.  
  93. // 创建顶点索引缓存并填充数据
  94. mIndexData-gt;indexBuffer = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer(
  95. Ogre::HardwareIndexBuffer::IT_16BIT,
  96. mIndexData-gt;indexCount,
  97. Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);
  98. mIndexData-gt;indexBuffer-gt;writeData(0, mIndexData-gt;indexBuffer-gt;getSizeInBytes(), faces, true);
  99.  
  100. // 设置包围盒
  101. mAABB.merge(Ogre::Vector3(vertices[0][1], vertices[0][2], vertices[0][3]));
  102. mAABB.merge(Ogre::Vector3(vertices[1][1], vertices[1][2], vertices[1][3]));
  103. mAABB.merge(Ogre::Vector3(vertices[2][1], vertices[2][2], vertices[2][3]));
  104. mBoundingRadius = Ogre::Math::boundingRadiusFromAABB(mAABB);
  105. }
  106.  
  107.  
  108.   然后在getRenderOperation()函数中将其提交上去:
  109.  
  110.  
  111. void Triangle::getRenderOperation(Ogre::RenderOperationamp; op)
  112. {
  113. op.operationType = Ogre::RenderOperation::OT_TRIANGLE_LIST;
  114. op.useIndexes = true;
  115. op.vertexData = mVertexData;
  116. op.indexData = mIndexData;
  117. }
  118.  
  119.  
  120.   3. 最后还需要提一下来自Renderable的getMaterial()函数,顾名思义,引擎籍此获知待渲物
  121. 体的材质,这里我们创建一个只使用物体顶点色的材质:
  122.  
  123.  
  124. Ogre::MaterialPtr material = Ogre::MaterialManager::getSingleton().create(quot;TriangleMaterialquot;, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
  125. material-gt;getTechnique(0)-gt;getPass(0)-gt;setLightingEnabled(false);
  126. material-gt;getTechnique(0)-gt;getPass(0)-gt;setCullingMode(Ogre::CULL_NONE);
  127.  
  128.  
  129.   之后这个材质将通过setMaterialName()函数赋给三角形以供其渲染时刻提交。
  130.  
  131.   完成了以上步骤,在主构建函数里进行如下调用:
  132.  
  133.  
  134. Ogre::SceneNode* node = mSceneMgr-gt;getRootSceneNode()-gt;createChildSceneNode(quot;TriangleNodequot;);
  135. mTriangle = new Triangle();
  136. mTriangle-gt;setMaterialName(quot;TriangleMaterialquot;);
  137. node-gt;attachObject(mTriangle);
  138.  
  139.  
  140.   运行程序,你将看到一枚彩色的三角形。
  141.  

 


  某种程度上,在3D世界里,学会了画三角形,你就学会了画任何东西。

  文章配套工程源码可移步此处下载:http://download.csdn.net/source/3562886,开发环境为VS2008+ Ogre1.7.3。

下载配套代码
锐亚教育

锐亚教育,游戏开发论坛|游戏制作人|游戏策划|游戏开发|独立游戏|游戏产业|游戏研发|游戏运营| unity|unity3d|unity3d官网|unity3d 教程|金融帝国3|8k8k8k|mcafee8.5i|游戏蛮牛|蛮牛 unity|蛮牛