<!-- Wanted to avoid copying .css to each folder, so copied default .css from doxyen in here, kicked out most stuff we don't need for examples and modified some a little bit.
Target was having a single html in each example folder which is created from the main.cpp files and needs no files besides some images below media folder.
<p>This tutorial will briefly show how to use the terrain renderer of Irrlicht. It will also show the terrain renderer triangle selector to be able to do collision detection with terrain.</p>
<p>Note that the Terrain Renderer in Irrlicht is based on Spintz' GeoMipMapSceneNode, lots of thanks go to him. DeusXL provided a new elegant simple solution for building larger area on small heightmaps -> terrain smoothing.</p>
<p>In the beginning there is nothing special. We include the needed header files and create an event listener to listen if the user presses a key: The 'W' key switches to wireframe mode, the 'P' key to pointcloud mode, and the 'D' key toggles between solid and detail mapped material. </p><divclass="fragment"><divclass="line"><spanclass="preprocessor">#include <irrlicht.h></span></div><divclass="line"><spanclass="preprocessor">#include "driverChoice.h"</span></div><divclass="line"></div><divclass="line"><spanclass="keyword">using namespace </span>irr;</div><divclass="line"></div><divclass="line"><spanclass="preprocessor">#ifdef _MSC_VER</span></div><divclass="line"><spanclass="preprocessor">#pragma comment(lib, "Irrlicht.lib")</span></div><divclass="line"><spanclass="preprocessor">#endif</span></div><divclass="line"></div><divclass="line"></div><divclass="line"><spanclass="keyword">class </span>MyEventReceiver : <spanclass="keyword">public</span> IEventReceiver</div><divclass="line">{</div><divclass="line"><spanclass="keyword">public</span>:</div><divclass="line"></div><divclass="line"> MyEventReceiver(scene::ISceneNode* terrain, scene::ISceneNode* skybox, scene::ISceneNode* skydome) :</div><divclass="line"> Terrain(terrain), Skybox(skybox), Skydome(skydome), showBox(true), showDebug(false)</div><divclass="line"> {</div><divclass="line"> Skybox->setVisible(showBox);</div><divclass="line"> Skydome->setVisible(!showBox);</div><divclass="line"> }</div><divclass="line"></div><divclass="line"><spanclass="keywordtype">bool</span> OnEvent(<spanclass="keyword">const</span> SEvent& event)</div><divclass="line"> {</div><divclass="line"><spanclass="comment">// check if user presses the key 'W' or 'D'</span></div><divclass="line"><spanclass="keywordflow">if</span> (event.EventType == irr::EET_KEY_INPUT_EVENT && !event.KeyInput.PressedDown)</div><divclass="line"> {</div><divclass="line"><spanclass="keywordflow">switch</span> (event.KeyInput.Key)</div><divclass="line"> {</div><divclass="line"><spanclass="keywordflow">case</span> irr::KEY_KEY_W: <spanclass="comment">// switch wire frame mode</span></div><divclass="line"> Terrain->setMaterialFlag(video::EMF_WIREFRAME,</div><divclass="line"> !Terrain->getMaterial(0).Wireframe);</div><divclass="line"> Terrain->setMaterialFlag(video::EMF_POINTCLOUD, <spanclass="keyword">false</span>);</div><divclass="line"><spanclass="keywordflow">return</span><spanclass="keyword">true</span>;</div><divclass="line"><spanclass="keywordflow">case</span> irr::KEY_KEY_P: <spanclass="comment">// switch wire frame mode</span></div><divclass="line"> Terrain->setMaterialFlag(video::EMF_POINTCLOUD,</div><divclass="line"> !Terrain->getMaterial(0).PointCloud);</div><divclass="line"> Terrain->setMaterialFlag(video::EMF_WIREFRAME, <spanclass="keyword">false</span>);</div><divclass="line"><spanclass="keywordflow">return</span><spanclass="keyword">true</span>;</div><divclass="line"><spanclass="keywordflow">case</span> irr::KEY_KEY_D: <spanclass="comment">// toggle detail map</span></div><divclass="line"> Terrain->setMaterialType(</div><divclass="line"> Terrain->getMaterial(0).MaterialType == video::EMT_SOLID ?</div><divclass="line"> video::EMT_DETAIL_MAP : video::EMT_SOLID);</div><divclass="line"><spanclass="keywordflow">return</span><spanclass="keyword">true</span>;</div><divclass="line"><spanclass="keywordflow">case</span> irr::KEY_KEY_S: <spanclass="comment">// toggle skies</span></div><divclass="line"> showBox=!showBox;</div><divclass="line"> Skybox->setVisible(showBox);</div><divclass="line
<p>To make the terrain look more big, we change the scale factor of it to (40, 4.4, 40). Because we don't have any dynamic lights in the scene, we switch off the lighting, and we set the file terrain-texture.jpg as texture for the terrain and detailmap3.jpg as second texture, called detail map. At last, we set the scale values for the texture: The first texture will be repeated only one time over the whole terrain, and the second one (detail map) 20 times. </p><divclass="fragment"><divclass="line"><spanclass="comment">// add terrain scene node</span></div><divclass="line">scene::ITerrainSceneNode* terrain = smgr->addTerrainSceneNode(</div><divclass="line"><spanclass="stringliteral">"../../media/terrain-heightmap.bmp"</span>,</div><divclass="line"> 0, <spanclass="comment">// parent node</span></div><divclass="line"> -1, <spanclass="comment">// node id</span></div><divclass="line"> core::vector3df(0.f, 0.f, 0.f), <spanclass="comment">// position</span></div><divclass="line"> core::vector3df(0.f, 0.f, 0.f), <spanclass="comment">// rotation</span></div><divclass="line"> core::vector3df(40.f, 4.4f, 40.f), <spanclass="comment">// scale</span></div><divclass="line"> video::SColor ( 255, 255, 255, 255 ), <spanclass="comment">// vertexColor</span></div><divclass="line"> 5, <spanclass="comment">// maxLOD</span></div><divclass="line"> scene::ETPS_17, <spanclass="comment">// patchSize</span></div><divclass="line"> 4 <spanclass="comment">// smoothFactor</span></div><divclass="line"> );</div><divclass="line"></div><divclass="line">terrain->setMaterialFlag(video::EMF_LIGHTING, <spanclass="keyword">false</span>);</div><divclass="line"></div><divclass="line">terrain->setMaterialTexture(0,</div><divclass="line"> driver->getTexture(<spanclass="stringliteral">"../../media/terrain-texture.jpg"</span>));</div><divclass="line">terrain->setMaterialTexture(1,</div><divclass="line"> driver->getTexture(<spanclass="stringliteral">"../../media/detailmap3.jpg"</span>));</div><divclass="line"></div><divclass="line">terrain->setMaterialType(video::EMT_DETAIL_MAP);</div><divclass="line"></div><divclass="line">terrain->scaleTexture(1.0f, 20.0f);</div></div><!-- fragment --><p> To be able to do collision with the terrain, we create a triangle selector. If you want to know what triangle selectors do, just take a look into the collision tutorial. The terrain triangle selector works together with the terrain. To demonstrate this, we create a collision response animator and attach it to the camera, so that the camera will not be able to fly through the terrain. </p><divclass="fragment"><divclass="line"><spanclass="comment">// create triangle selector for the terrain </span></div><divclass="line">scene::ITriangleSelector* selector</div><divclass="line"> = smgr->createTerrainTriangleSelector(terrain, 0);</div><divclass="line">terrain->setTriangleSelector(selector);</div><divclass="line"></div><divclass="line"><spanclass="comment">// create collision response animator and attach it to the camera</span></div><divclass="line">scene::ISceneNodeAnimator* anim = smgr->createCollisionResponseAnimator(</div><divclass="line"> selector, camera, core::vector3df(60,100,60),</div><divclass="line"> core::vector3df(0,0,0),</div><divclass="line"> core::vector3df(0,50,0));</div><divclass="line">selector->drop();</div><divclass="line">camera->addAnimator(anim);</div><divclass="line">anim->drop();</div></div><!-- fragment --><p> If you need access to the terrain data you can also do this directly via the following code fragment. </p><divclass="fragment"><divclass="line">scene::CDynamicMeshBuffer* buffer = <spanclass="keyword">new</span> scene::CDynamicMeshBuffer(video::EVT_2TCOORDS, video::EIT_16BIT);</div><divclass="line">terrain->getMeshBufferForLOD(*buffer, 0);</div><divclass="line">video::S3DVe