irrlicht/examples/12.TerrainRendering/tutorial.html

210 lines
23 KiB
HTML
Raw Normal View History

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.13"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Tutorial 12: Terrain Rendering</title>
<html xmlns="http://www.w3.org/1999/xhtml">
<!-- 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.
Feel free to improve :)
-->
<style>
body, table, div, p, dl {
font: 400 14px/22px;
}
body {
background-color: #F0F0F0;
color: black;
margin-left: 5%;
margin-right: 5%;
}
p.reference, p.definition {
font: 400 14px/22px;
}
.title {
font: 400 14px/28px;
font-size: 150%;
font-weight: bold;
margin: 10px 2px;
}
h1, h2, h3, h4, h5, h6 {
-webkit-transition: text-shadow 0.5s linear;
-moz-transition: text-shadow 0.5s linear;
-ms-transition: text-shadow 0.5s linear;
-o-transition: text-shadow 0.5s linear;
transition: text-shadow 0.5s linear;
margin-right: 15px;
}
caption {
font-weight: bold;
}
h3.version {
font-size: 90%;
text-align: center;
}
a {
color: #3D578C;
font-weight: normal;
text-decoration: none;
}
.contents a:visited {
color: #4665A2;
}
a:hover {
text-decoration: underline;
}
a.el {
font-weight: bold;
}
a.code, a.code:visited, a.line, a.line:visited {
color: #4665A2;
}
a.codeRef, a.codeRef:visited, a.lineRef, a.lineRef:visited {
color: #4665A2;
}
pre.fragment {
border: 1px solid #C4CFE5;
background-color: #FBFCFD;
padding: 4px 6px;
margin: 4px 8px 4px 2px;
overflow: auto;
word-wrap: break-word;
font-size: 9pt;
line-height: 125%;
font-family: monospace, fixed;
font-size: 105%;
}
div.fragment {
padding: 0px;
margin: 4px 8px 4px 2px;
background-color: #FBFCFD;
border: 1px solid #C4CFE5;
}
div.line {
font-family: monospace, fixed;
font-size: 13px;
min-height: 13px;
line-height: 1.0;
text-wrap: unrestricted;
white-space: -moz-pre-wrap; /* Moz */
white-space: -pre-wrap; /* Opera 4-6 */
white-space: -o-pre-wrap; /* Opera 7 */
white-space: pre-wrap; /* CSS3 */
word-wrap: break-word; /* IE 5.5+ */
text-indent: -53px;
padding-left: 53px;
padding-bottom: 0px;
margin: 0px;
-webkit-transition-property: background-color, box-shadow;
-webkit-transition-duration: 0.5s;
-moz-transition-property: background-color, box-shadow;
-moz-transition-duration: 0.5s;
-ms-transition-property: background-color, box-shadow;
-ms-transition-duration: 0.5s;
-o-transition-property: background-color, box-shadow;
-o-transition-duration: 0.5s;
transition-property: background-color, box-shadow;
transition-duration: 0.5s;
}
div.contents {
margin-top: 10px;
margin-left: 12px;
margin-right: 8px;
}
div.center {
text-align: center;
margin-top: 0px;
margin-bottom: 0px;
padding: 0px;
}
div.center img {
border: 0px;
}
span.keyword {
color: #008000
}
span.keywordtype {
color: #604020
}
span.keywordflow {
color: #e08000
}
span.comment {
color: #800000
}
span.preprocessor {
color: #806020
}
span.stringliteral {
color: #002080
}
span.charliteral {
color: #008080
}
blockquote {
background-color: #F7F8FB;
border-left: 2px solid #9CAFD4;
margin: 0 24px 0 4px;
padding: 0 12px 0 16px;
}
hr {
height: 0px;
border: none;
border-top: 1px solid #4A6AAA;
}
address {
font-style: normal;
color: #2A3D61;
}
div.header {
background-image:url('nav_h.png');
background-repeat:repeat-x;
background-color: #F9FAFC;
margin: 0px;
border-bottom: 1px solid #C4CFE5;
}
div.headertitle {
padding: 5px 5px 5px 10px;
}
.image {
text-align: center;
}
.caption {
font-weight: bold;
}
div.zoom {
border: 1px solid #90A5CE;
}
tr.heading h2 {
margin-top: 12px;
margin-bottom: 4px;
}
</style>
</head>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<!--END TITLEAREA-->
<!-- end header part -->
<!-- Generated by Doxygen 1.8.13 -->
</div><!-- top -->
<div class="header">
<div class="headertitle">
<div class="title">Tutorial 12: Terrain Rendering </div> </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><div class="image">
<img src="../../media/example_screenshots/012shot.jpg" alt="012shot.jpg"/>
</div>
<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 -&gt; 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 certain keys. </p><div class="fragment"><div class="line"><span class="preprocessor">#include &lt;irrlicht.h&gt;</span></div><div class="line"><span class="preprocessor">#include &quot;driverChoice.h&quot;</span></div><div class="line"><span class="preprocessor">#include &quot;exampleHelper.h&quot;</span></div><div class="line"></div><div class="line"><span class="keyword">using namespace </span>irr;</div><div class="line"></div><div class="line"><span class="preprocessor">#ifdef _MSC_VER</span></div><div class="line"><span class="preprocessor">#pragma comment(lib, &quot;Irrlicht.lib&quot;)</span></div><div class="line"><span class="preprocessor">#endif</span></div><div class="line"></div><div class="line"></div><div class="line"><span class="keyword">class </span>MyEventReceiver : <span class="keyword">public</span> IEventReceiver</div><div class="line">{</div><div class="line"><span class="keyword">public</span>:</div><div class="line"></div><div class="line"> MyEventReceiver(scene::ISceneNode* terrain, scene::ISceneNode* skybox, scene::ISceneNode* skydome) :</div><div class="line"> Terrain(terrain), Skybox(skybox), Skydome(skydome), showBox(true), showDebug(false)</div><div class="line"> {</div><div class="line"> Skybox-&gt;setVisible(showBox);</div><div class="line"> Skydome-&gt;setVisible(!showBox);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keywordtype">bool</span> OnEvent(<span class="keyword">const</span> SEvent&amp; event)</div><div class="line"> {</div><div class="line"> <span class="comment">// check if user presses the key &#39;W&#39; or &#39;D&#39;</span></div><div class="line"> <span class="keywordflow">if</span> (event.EventType == irr::EET_KEY_INPUT_EVENT &amp;&amp; !event.KeyInput.PressedDown)</div><div class="line"> {</div><div class="line"> <span class="keywordflow">switch</span> (event.KeyInput.Key)</div><div class="line"> {</div><div class="line"> <span class="keywordflow">case</span> irr::KEY_KEY_W: <span class="comment">// switch wire frame mode</span></div><div class="line"> Terrain-&gt;setMaterialFlag(video::EMF_WIREFRAME,</div><div class="line"> !Terrain-&gt;getMaterial(0).Wireframe);</div><div class="line"> Terrain-&gt;setMaterialFlag(video::EMF_POINTCLOUD, <span class="keyword">false</span>);</div><div class="line"> <span class="keywordflow">return</span> <span class="keyword">true</span>;</div><div class="line"> <span class="keywordflow">case</span> irr::KEY_KEY_P: <span class="comment">// switch point cloud mode</span></div><div class="line"> Terrain-&gt;setMaterialFlag(video::EMF_POINTCLOUD,</div><div class="line"> !Terrain-&gt;getMaterial(0).PointCloud);</div><div class="line"> Terrain-&gt;setMaterialFlag(video::EMF_WIREFRAME, <span class="keyword">false</span>);</div><div class="line"> <span class="keywordflow">return</span> <span class="keyword">true</span>;</div><div class="line"> <span class="keywordflow">case</span> irr::KEY_KEY_D: <span class="comment">// toggle detail map</span></div><div class="line"> Terrain-&gt;setMaterialType(</div><div class="line"> Terrain-&gt;getMaterial(0).MaterialType == video::EMT_SOLID ?</div><div class="line"> video::EMT_DETAIL_MAP : video::EMT_SOLID);</div><div class="line"> <span class="keywordflow">return</span> <span class="keyword">true</span>;</div><div class="line"> <span class="keywordflow">case</span> irr::KEY_KEY_S: <span class="comment">// toggle skies</span></div><div class="line"> showBox=!showBox;</div><div class="line"> Skybox-&gt;setVisible(showBox);</div><div class="line"> Skydome-&gt;setVis
<p>To make the terrain look bigger, we change it's scale factor 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><div class="fragment"><div class="line"><span class="comment">// add terrain scene node</span></div><div class="line">scene::ITerrainSceneNode* terrain = smgr-&gt;addTerrainSceneNode(</div><div class="line"> mediaPath + <span class="stringliteral">&quot;terrain-heightmap.bmp&quot;</span>,</div><div class="line"> 0, <span class="comment">// parent node</span></div><div class="line"> -1, <span class="comment">// node id</span></div><div class="line"> core::vector3df(0.f, 0.f, 0.f), <span class="comment">// position</span></div><div class="line"> core::vector3df(0.f, 0.f, 0.f), <span class="comment">// rotation</span></div><div class="line"> core::vector3df(40.f, 4.4f, 40.f), <span class="comment">// scale</span></div><div class="line"> video::SColor ( 255, 255, 255, 255 ), <span class="comment">// vertexColor</span></div><div class="line"> 5, <span class="comment">// maxLOD</span></div><div class="line"> scene::ETPS_17, <span class="comment">// patchSize</span></div><div class="line"> 4 <span class="comment">// smoothFactor</span></div><div class="line"> );</div><div class="line"></div><div class="line">terrain-&gt;setMaterialFlag(video::EMF_LIGHTING, <span class="keyword">false</span>);</div><div class="line"></div><div class="line">terrain-&gt;setMaterialTexture(0,</div><div class="line"> driver-&gt;getTexture(mediaPath + <span class="stringliteral">&quot;terrain-texture.jpg&quot;</span>));</div><div class="line">terrain-&gt;setMaterialTexture(1,</div><div class="line"> driver-&gt;getTexture(mediaPath + <span class="stringliteral">&quot;detailmap3.jpg&quot;</span>));</div><div class="line"></div><div class="line">terrain-&gt;setMaterialType(video::EMT_DETAIL_MAP);</div><div class="line"></div><div class="line">terrain-&gt;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><div class="fragment"><div class="line"><span class="comment">// create triangle selector for the terrain </span></div><div class="line">scene::ITriangleSelector* selector</div><div class="line"> = smgr-&gt;createTerrainTriangleSelector(terrain, 0);</div><div class="line">terrain-&gt;setTriangleSelector(selector);</div><div class="line"></div><div class="line"><span class="comment">// create collision response animator and attach it to the camera</span></div><div class="line">scene::ISceneNodeAnimator* anim = smgr-&gt;createCollisionResponseAnimator(</div><div class="line"> selector, camera, core::vector3df(60,100,60),</div><div class="line"> core::vector3df(0,0,0),</div><div class="line"> core::vector3df(0,50,0));</div><div class="line">selector-&gt;drop();</div><div class="line">camera-&gt;addAnimator(anim);</div><div class="line">anim-&gt;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><div class="fragment"><div class="line">scene::CDynamicMeshBuffer* buffer = <span class="keyword">new</span> scene::CDynamicMeshBuffer(video::EVT_2TCOORDS, video::EIT_16BIT);</div><div class="line">terrain-&gt;getMeshBufferForLOD(*buffer, 0);</div><div class="line">video::S3DVertex2TC
</div></div><!-- contents -->
<!-- HTML footer for doxygen 1.8.13-->
<!-- start footer part -->
<p>&nbsp;</p>
</body>
</html>