tutorial.html 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. <html>
  2. <head>
  3. <title>Irrlicht Engine Tutorial</title>
  4. <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
  5. </head>
  6. <body bgcolor="#FFFFFF" leftmargin="0" topmargin="0" marginwidth="0" marginheight="0">
  7. <br>
  8. <table width="95%" border="0" cellspacing="0" cellpadding="2" align="center">
  9. <tr>
  10. <td bgcolor="#666699" width="10"><b><a href="http://irrlicht.sourceforge.net" target="_blank"><img src="../../media/irrlichtlogo.jpg" width="88" height="31" border="0"></a></b></td>
  11. <td bgcolor="#666699" width="100%">
  12. <div align="center">
  13. <div align="center"></div>
  14. <div align="left"><b><font color="#FFFFFF">Tutorial 3.CustomSceneNode</font></b></div>
  15. </div>
  16. </td>
  17. </tr>
  18. <tr bgcolor="#eeeeff">
  19. <td height="90" colspan="2">
  20. <div align="left">
  21. <p>This Tutorial is a tutorial for more advanced developers. If you are
  22. currently just playing around with the Irrlicht engine, please look
  23. at other examples first. This tutorial shows how to create a custom
  24. scene node and how to use it in the engine. A custom scene node is needed,
  25. if you want to implement a render technique, the Irrlicht Engine is
  26. currently not supporting. For example you can write a indoor portal
  27. based renderer or a advanced terrain scene node with it. With creating
  28. custom scene nodes, you can easily extend the Irrlicht Engine and adapt
  29. it to your needs.</p>
  30. <p>I will keep the tutorial simple: Keep everything very short, everything
  31. in one .cpp file, and I'll use the engine here as in all other tutorials.
  32. At the end of the tutorial, the result will look like the image below.
  33. This looks not very exciting, but it is a complete customized scene
  34. node and a good point to start from creating you own scene nodes.</p>
  35. <p align="center"><img src="../../media/003shot.jpg" width="259" height="204"><br>
  36. </p>
  37. </div>
  38. </td>
  39. </tr>
  40. </table>
  41. <br>
  42. <table width="95%" border="0" cellspacing="0" cellpadding="2" align="center">
  43. <tr>
  44. <td bgcolor="#666699"> <div align="center"><b><font color="#FFFFFF"></font></b></div>
  45. <b><font color="#FFFFFF">Lets start!</font></b></td>
  46. </tr>
  47. <tr>
  48. <td height="90" bgcolor="#eeeeff" valign="top"> <div align="left">
  49. <p>To start, I include the header files, use the irr namespace, and tell
  50. the linker to link with the .lib file. </p>
  51. <table width="95%" border="0" cellspacing="2" cellpadding="0" bgcolor="#CCCCCC" align="center">
  52. <tr>
  53. <td> <pre>#include &lt;irrlicht.h&gt;</pre> <pre>using namespace irr;</pre> <pre>#pragma comment(lib, &quot;Irrlicht.lib&quot;)</pre></td>
  54. </tr>
  55. </table>
  56. <p>Here comes the most sophisticated part of this tutorial: The class
  57. of our very own custom scene node. To keep it simple,<br>
  58. our scene node will not be an indoor portal renderer nor a terrain scene
  59. node, but a simple tetraeder, a 3d object consiting of 4 connected vertices,
  60. which only draws itself and does nothing more.</p>
  61. <p>To let our scene node be able to be inserted into the Irrlicht Engine
  62. scene, the class we create needs only be derived from the ISceneNode
  63. class and has to override some methods.</p>
  64. <table width="95%" border="0" cellspacing="2" cellpadding="0" bgcolor="#CCCCCC" align="center">
  65. <tr>
  66. <td> <pre>class CSampleSceneNode : public scene::ISceneNode<br>{</pre> </td>
  67. </tr>
  68. </table>
  69. <p>First, we declare some member variables, to hold data for our tetraeder:
  70. The bounding box, 4 vertices, and<br>
  71. the material of the tetraeder.</p>
  72. <table width="95%" border="0" cellspacing="2" cellpadding="0" bgcolor="#CCCCCC" align="center">
  73. <tr>
  74. <td> <pre>core::aabbox3d&lt;f32&gt; Box;<br>video::S3DVertex Vertices[4];<br>video::SMaterial Material;</pre> </td>
  75. </tr>
  76. </table>
  77. <p>The parameters of the constructor specify the parent of the scene node,
  78. a pointer to the scene manager, and an id of the scene node. In the
  79. constructor itself, we call the parent classes constructor, set some
  80. properties of the material we use to draw the scene node and create
  81. the 4 vertices of the tetraeder we will draw later. </p>
  82. <table width="95%" border="0" cellspacing="2" cellpadding="0" bgcolor="#CCCCCC" align="center">
  83. <tr>
  84. <td> <pre>public:</pre> <pre>CSampleSceneNode(scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id)
  85. : scene::ISceneNode(parent, mgr, id)
  86. {
  87. Material.Wireframe = false;
  88. Material.Lighting = false;</pre>
  89. <pre> Vertices[0] = video::S3DVertex(0,0,10, 1,1,0,video::SColor(255,0,255,255),0,1);
  90. Vertices[1] = video::S3DVertex(10,0,-10, 1,0,0,video::SColor(255,255,0,255),1,1);
  91. Vertices[2] = video::S3DVertex(0,20,0, 0,1,1,video::SColor(255,255,255,0),1,0);
  92. Vertices[3] = video::S3DVertex(-10,0,-10, 0,0,1,video::SColor(255,0,255,0),0,0);
  93. </pre></td>
  94. </tr>
  95. </table>
  96. <br>
  97. The Irrlicht Engine needs to know the bounding box of your scene node.
  98. It will use it for doing automatic culling and other things. Hence we
  99. need to create a bounding box from the 4 vertices we use. If you do not
  100. want the engine to use the box for automatic culling, and/or don't want
  101. to create the box, you could also write<br>
  102. <font face="Courier New, Courier, mono">AutomaticCullingEnabled = false;</font>.<br>
  103. <br>
  104. <table width="95%" border="0" cellspacing="2" cellpadding="0" bgcolor="#CCCCCC" align="center">
  105. <tr>
  106. <td> <pre> Box.reset(Vertices[0].Pos);<br> for (s32 i=1; i&lt;4; ++i)<br> Box.addInternalPoint(Vertices[i].Pos);
  107. }</pre> </td>
  108. </tr>
  109. </table>
  110. <br>
  111. <p>Before it is drawn, the OnPreRender() method of every scene node in
  112. the scene is called by the scene manager. If the scene node wishes to
  113. draw itself, it may register itself in the scene manager to be drawn.
  114. This is necessary to tell the scene manager when it should call the
  115. ::render method. For example normal scene nodes render their content
  116. one after another, while stencil buffer shadows would like to be drawn
  117. after all other scene nodes. And camera or light scene nodes need to
  118. be rendered before all other scene nodes (if at all). <br>
  119. So here we simply register the scene node to get rendered normally.
  120. If we would like to let it be rendered like cameras or light, we would
  121. have to call SceneManager-&gt;registerNodeForRendering(this, SNRT_LIGHT_AND_CAMERA);
  122. <br>
  123. After this, we call the OnPreRender-method of the base class ISceneNode,
  124. which simply lets also all the child scene nodes of this node register
  125. themselves. </p>
  126. </div>
  127. <table width="95%" border="0" cellspacing="2" cellpadding="0" bgcolor="#CCCCCC" align="center">
  128. <tr>
  129. <td> <pre>virtual void OnPreRender()<br>{<br> if (IsVisible)<br> SceneManager-&gt;registerNodeForRendering(this);
  130. ISceneNode::OnPreRender();
  131. }</pre> </td>
  132. </tr>
  133. </table>
  134. <p>In the render() method most of the interresting stuff happenes: The Scene
  135. node renders itself. We override this method and draw the tetraeder.</p>
  136. <table width="95%" border="0" cellspacing="2" cellpadding="0" bgcolor="#CCCCCC" align="center">
  137. <tr>
  138. <td> <pre>virtual void render()<br>{<br> u16 indices[] = { 0,2,3, 2,1,3, 1,0,3, 2,0,1 };
  139. video::IVideoDriver* driver = SceneManager-&gt;getVideoDriver();</pre>
  140. <pre> driver-&gt;setMaterial(Material);
  141. driver-&gt;setTransform(video::ETS_WORLD, AbsoluteTransformation);
  142. driver-&gt;drawIndexedTriangleList(&amp;Vertices[0], 4, &amp;indices[0], 4);
  143. }</pre> </td>
  144. </tr>
  145. </table>
  146. <p> At least, we create three small additional methods. GetBoundingBox()
  147. returns the bounding box of this scene node, <br>
  148. GetMaterialCount() returns the amount of materials in this scene node
  149. (our tetraeder only has one material), and getMaterial() returns the material
  150. at an index. Because we have only one material here, we can return the
  151. only one material, assuming that no one ever calls getMaterial() with
  152. an index greater than 0. </p>
  153. <table width="95%" border="0" cellspacing="2" cellpadding="0" bgcolor="#CCCCCC" align="center">
  154. <tr>
  155. <td><pre> virtual const core::aabbox3d&lt;f32&gt;&amp; getBoundingBox() const<br> {<br> return Box;<br> }</pre> <pre> virtual u32 getMaterialCount()
  156. {
  157. return 1;
  158. }</pre> <pre> virtual video::SMaterial&amp; getMaterial(u32 i)
  159. {
  160. return Material;
  161. }
  162. };</pre></td>
  163. </tr>
  164. </table>
  165. <p>That's it. The Scene node is done. Now we simply have to start the engine,
  166. create the scene node and a camera, and look at the result.</p>
  167. <table width="95%" border="0" cellspacing="2" cellpadding="0" bgcolor="#CCCCCC" align="center">
  168. <tr>
  169. <td> <pre>int main()<br>{
  170. IrrlichtDevice *device =
  171. createDevice(video::EDT_OPENGL, core::dimension2d&lt;s32&gt;(640, 480), 16, false);</pre> <pre> device-&gt;setWindowCaption(L&quot;Custom Scene Node - Irrlicht Engine Demo&quot;);</pre> <pre> video::IVideoDriver* driver = device-&gt;getVideoDriver();
  172. scene::ISceneManager* smgr = device-&gt;getSceneManager();</pre>
  173. <pre> smgr-&gt;addCameraSceneNode(0, core::vector3df(0,-40,0), core::vector3df(0,0,0));
  174. </pre></td>
  175. </tr>
  176. </table>
  177. <p>Create our scene node. Note that it is dropped (-&gt;drop()) instantly
  178. after we create it. This is possible because the scene manager now takes
  179. care of it. This is not nessecary, it would also be possible to drop it
  180. at the end of the program.</p>
  181. <table width="95%" border="0" cellspacing="2" cellpadding="0" bgcolor="#CCCCCC" align="center">
  182. <tr>
  183. <td> <pre>CSampleSceneNode *myNode = <br> new CSampleSceneNode(smgr-&gt;getRootSceneNode(), smgr, 666);
  184. myNode-&gt;drop();</pre> </td>
  185. </tr>
  186. </table>
  187. <p>To animate something in this boring scene consisting only of one tetraeder,
  188. and to show, that you now can use your scene node like any other scene
  189. node in the engine, we add an animator to the scene node, which rotates
  190. the node a little bit. </p>
  191. <table width="95%" border="0" cellspacing="2" cellpadding="0" bgcolor="#CCCCCC" align="center">
  192. <tr>
  193. <td> <pre>scene::ISceneNodeAnimator* anim = <br> smgr-&gt;createRotationAnimator(core::vector3df(0.8f, 0, 0.8f));
  194. myNode-&gt;addAnimator(anim);
  195. anim-&gt;drop();</pre> </td>
  196. </tr>
  197. </table>
  198. <p>Now draw everything and finish.</p>
  199. <table width="95%" border="0" cellspacing="2" cellpadding="0" bgcolor="#CCCCCC" align="center">
  200. <tr>
  201. <td> <pre> while(device-&gt;run())<br> {<br> driver-&gt;beginScene(true, true, video::SColor(0,100,100,100));
  202. smgr-&gt;drawAll();
  203. driver-&gt;endScene();
  204. }
  205. device-&gt;drop();
  206. return 0;
  207. }</pre> </td>
  208. </tr>
  209. </table>
  210. <p>That's it. Compile and play around with the program. </p></td>
  211. </tr>
  212. </table>
  213. <p>&nbsp;</p>
  214. </body>
  215. </html>