Changes are all related to automatic creation of documentation. Note: It's not yet fully working in trunk due to changes since 1.8 git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@6200 dfc29bdd-3216-0410-991c-e03cc46cb475
		
			
				
	
	
		
			210 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			210 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
| <!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 23: SMeshBufferHandling</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 23: SMeshBufferHandling </div>  </div>
 | |
| </div><!--header-->
 | |
| <div class="contents">
 | |
| <div class="textblock"><div class="image">
 | |
| <img src="../../media/023shot.jpg" alt="023shot.jpg"/>
 | |
| </div>
 | |
|  <p>A tutorial by geoff.</p>
 | |
| <p>In this tutorial we'll learn how to create custom meshes and deal with them with Irrlicht. We'll create an interesting heightmap with some lighting effects. With keys 1,2,3 you can choose a different mesh layout, which is put into the mesh buffers as desired. All positions, normals, etc. are updated accordingly.</p>
 | |
| <p>Ok, let's start with the headers (I think there's nothing to say about it) </p><div class="fragment"><div class="line"><span class="preprocessor">#include <irrlicht.h></span></div><div class="line"><span class="preprocessor">#include "driverChoice.h"</span></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, "Irrlicht.lib")</span></div><div class="line"><span class="preprocessor">#endif</span></div><div class="line"></div><div class="line"><span class="comment">//Namespaces for the engine</span></div><div class="line"><span class="keyword">using namespace </span>irr;</div><div class="line"><span class="keyword">using namespace </span>video;</div><div class="line"><span class="keyword">using namespace </span>core;</div><div class="line"><span class="keyword">using namespace </span>scene;</div><div class="line"><span class="keyword">using namespace </span>io;</div><div class="line"><span class="keyword">using namespace </span>gui;</div></div><!-- fragment --><p> This is the type of the functions which work out the colour.</p><div class="fragment"><div class="line"><span class="keyword">typedef</span> SColor colour_func(f32 x, f32 y, f32 z);</div></div><!-- fragment --><p> Here comes a set of functions which can be used for coloring the nodes while creating the mesh.</p><div class="fragment"><div class="line"><span class="comment">// Greyscale, based on the height.</span></div><div class="line">SColor grey(f32, f32, f32 z)</div><div class="line">{</div><div class="line">    u32 n = (u32)(255.f * z);</div><div class="line">    <span class="keywordflow">return</span> SColor(255, n, n, n);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="comment">// Interpolation between blue and white, with red added in one</span></div><div class="line"><span class="comment">// direction and green in the other.</span></div><div class="line">SColor yellow(f32 x, f32 y, f32)</div><div class="line">{</div><div class="line">    <span class="keywordflow">return</span> SColor(255, 128 + (u32)(127.f * x), 128 + (u32)(127.f * y), 255);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="comment">// Pure white.</span></div><div class="line">SColor white(f32, f32, f32) { <span class="keywordflow">return</span> SColor(255, 255, 255, 255); }</div></div><!-- fragment --><p> The type of the functions which generate the heightmap. x and y range between -0.5 and 0.5, and s is the scale of the heightmap.</p><div class="fragment"><div class="line"><span class="keyword">typedef</span> f32 generate_func(s16 x, s16 y, f32 s);</div><div class="line"></div><div class="line"><span class="comment">// An interesting sample function :-)</span></div><div class="line">f32 eggbox(s16 x, s16 y, f32 s)</div><div class="line">{</div><div class="line">    <span class="keyword">const</span> f32 r = 4.f*sqrtf((f32)(x*x + y*y))/s;</div><div class="line">    <span class="keyword">const</span> f32 z = expf(-r * 2) * (cosf(0.2f * x) + cosf(0.2f * y));</div><div class="line">    <span class="keywordflow">return</span> 0.25f+0.25f*z;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="comment">// A rather dumb sine function :-/</span></div><div class="line">f32 moresine(s16 x, s16 y, f32 s)</div><div class="line">{</div><div class="line">    <span class="keyword">const</span> f32 xx=0.3f*(f32)x/s;</div><div class="line">    <span class="keyword">const</span> f32 yy=12*y/s;</div><div class="line">    <span class="keyword">const</span> f32 z = sinf(xx*xx+yy)*sinf(xx+yy*yy);</div><div class="line">    <span class="keywordflow">return</span> 0.25f + 0.25f * z;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="comment">// A simple function</span></div><div class="line">f32 justexp(s16 x, s16 y, f32 s)</div><div class="line">{</div><div class="line">    <span class="keyword">const</span> f32 xx=6*x/s;</div><div class="line">    <span class="keyword">const</span> f32 yy=6*y/s;</div><div class="line">    <span class="keyword">const</span> f32 z = (xx*xx+yy*yy);</div><div class="line">    <span class="keywordflow">return</span> 0.3f*z*cosf(xx*yy);</div><div class="line">}</div></div><!-- fragment --><p> A simple class for representing heightmaps. Most of this should be obvious.</p><div class="fragment"><div class="line"><span class="keyword">class </span>HeightMap</div><div class="line">{</div><div class="line"><span class="keyword">private</span>:</div><div class="line">    <span class="keyword">const</span> u16 Width;</div><div class="line">    <span class="keyword">const</span> u16 Height;</div><div class="line">    f32 s;</div><div class="line">    core::array<f32> data;</div><div class="line"><span class="keyword">public</span>:</div><div class="line">    HeightMap(u16 _w, u16 _h) : Width(_w), Height(_h), s(0.f), data(0)</div><div class="line">    {</div><div class="line">        s = sqrtf((f32)(Width * Width + Height * Height));</div><div class="line">        data.set_used(Width * Height);</div><div class="line">    }</div><div class="line"></div><div class="line">    <span class="comment">// Fill the heightmap with values generated from f.</span></div><div class="line">    <span class="keywordtype">void</span> generate(generate_func f)</div><div class="line">    {</div><div class="line">        u32 i=0;</div><div class="line">        <span class="keywordflow">for</span>(u16 y = 0; y < Height; ++y)</div><div class="line">            <span class="keywordflow">for</span>(u16 x = 0; x < Width; ++x)</div><div class="line">                <span class="keyword">set</span>(i++, calc(f, x, y));</div><div class="line">    }</div><div class="line"></div><div class="line">    u16 height()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> Height; }</div><div class="line">    u16 width()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> Width; }</div><div class="line"></div><div class="line">    f32 calc(generate_func f, u16 x, u16 y)<span class="keyword"> const</span></div><div class="line"><span class="keyword">    </span>{</div><div class="line">        <span class="keyword">const</span> f32 xx = (f32)x - Width*0.5f;</div><div class="line">        <span class="keyword">const</span> f32 yy = (f32)y - Height*0.5f;</div><div class="line">        <span class="keywordflow">return</span> f((u16)xx, (u16)yy, s);</div><div class="line">    }</div><div class="line"></div><div class="line">    <span class="comment">// The height at (x, y) is at position y * Width + x.</span></div><div class="line"></div><div class="line">    <span class="keywordtype">void</span> <span class="keyword">set</span>(u16 x, u16 y, f32 z) { data[y * Width + x] = z; }</div><div class="line">    <span class="keywordtype">void</span> <span class="keyword">set</span>(u32 i, f32 z) { data[i] = z; }</div><div class="line">    f32 <span class="keyword">get</span>(u16 x, u16 y) <span class="keyword">const</span> { <span class="keywordflow">return</span> data[y * Width + x]; }</div></div><!-- fragment --><p> The only difficult part. This considers the normal at (x, y) to be the cross product of the vectors between the adjacent points in the horizontal and vertical directions.</p>
 | |
| <p>s is a scaling factor, which is necessary if the height units are different from the coordinate units; for example, if your map has heights in metres and the coordinates are in units of a kilometer.</p><div class="fragment"><div class="line">    vector3df getnormal(u16 x, u16 y, f32 s)<span class="keyword"> const</span></div><div class="line"><span class="keyword">    </span>{</div><div class="line">        <span class="keyword">const</span> f32 zc = <span class="keyword">get</span>(x, y);</div><div class="line">        f32 zl, zr, zu, zd;</div><div class="line"></div><div class="line">        <span class="keywordflow">if</span> (x == 0)</div><div class="line">        {</div><div class="line">            zr = <span class="keyword">get</span>(x + 1, y);</div><div class="line">            zl = zc + zc - zr;</div><div class="line">        }</div><div class="line">        <span class="keywordflow">else</span> <span class="keywordflow">if</span> (x == Width - 1)</div><div class="line">        {</div><div class="line">            zl = <span class="keyword">get</span>(x - 1, y);</div><div class="line">            zr = zc + zc - zl;</div><div class="line">        }</div><div class="line">        <span class="keywordflow">else</span></div><div class="line">        {</div><div class="line">            zr = <span class="keyword">get</span>(x + 1, y);</div><div class="line">            zl = <span class="keyword">get</span>(x - 1, y);</div><div class="line">        }</div><div class="line"></div><div class="line">        <span class="keywordflow">if</span> (y == 0)</div><div class="line">        {</div><div class="line">            zd = <span class="keyword">get</span>(x, y + 1);</div><div class="line">            zu = zc + zc - zd;</div><div class="line">        }</div><div class="line">        <span class="keywordflow">else</span> <span class="keywordflow">if</span> (y == Height - 1)</div><div class="line">        {</div><div class="line">            zu = <span class="keyword">get</span>(x, y - 1);</div><div class="line">            zd = zc + zc - zu;</div><div class="line">        }</div><div class="line">        <span class="keywordflow">else</span></div><div class="line">        {</div><div class="line">            zd = <span class="keyword">get</span>(x, y + 1);</div><div class="line">            zu = <span class="keyword">get</span>(x, y - 1);</div><div class="line">        }</div><div class="line"></div><div class="line">        <span class="keywordflow">return</span> vector3df(s * 2 * (zl - zr), 4, s * 2 * (zd - zu)).normalize();</div><div class="line">    }</div><div class="line">};</div></div><!-- fragment --><p> A class which generates a mesh from a heightmap.</p><div class="fragment"><div class="line"><span class="keyword">class </span>TMesh</div><div class="line">{</div><div class="line"><span class="keyword">private</span>:</div><div class="line">    u16 Width;</div><div class="line">    u16 Height;</div><div class="line">    f32 Scale;</div><div class="line"><span class="keyword">public</span>:</div><div class="line">    SMesh* Mesh;</div><div class="line"></div><div class="line">    TMesh() : Mesh(0), Width(0), Height(0), Scale(1.f)</div><div class="line">    {</div><div class="line">        Mesh = <span class="keyword">new</span> SMesh();</div><div class="line">    }</div><div class="line"></div><div class="line">    ~TMesh()</div><div class="line">    {</div><div class="line">        Mesh->drop();</div><div class="line">    }</div><div class="line"></div><div class="line">    <span class="comment">// Unless the heightmap is small, it won't all fit into a single</span></div><div class="line">    <span class="comment">// SMeshBuffer. This function chops it into pieces and generates a</span></div><div class="line">    <span class="comment">// buffer from each one.</span></div><div class="line"></div><div class="line">    <span class="keywordtype">void</span> init(<span class="keyword">const</span> HeightMap &hm, f32 scale, colour_func cf, IVideoDriver *driver)</div><div class="line">    {</div><div class="line">        Scale = scale;</div><div class="line"></div><div class="line">        <span class="keyword">const</span> u32 mp = driver -> getMaximalPrimitiveCount();</div><div class="line">        Width = hm.width();</div><div class="line">        Height = hm.height();</div><div class="line">        </div><div class="line">        <span class="keyword">const</span> u32 sw = mp / (6 * Height); <span class="comment">// the width of each piece</span></div><div class="line"></div><div class="line">        u32 i=0;</div><div class="line">        <span class="keywordflow">for</span>(u32 y0 = 0; y0 < Height; y0 += sw)</div><div class="line">        {</div><div class="line">            u16 y1 = y0 + sw;</div><div class="line">            <span class="keywordflow">if</span> (y1 >= Height)</div><div class="line">                y1 = Height - 1; <span class="comment">// the last one might be narrower</span></div><div class="line">            addstrip(hm, cf, y0, y1, i);</div><div class="line">            ++i;</div><div class="line">        }</div><div class="line">        <span class="keywordflow">if</span> (i<Mesh->getMeshBufferCount())</div><div class="line">        {</div><div class="line">            <span class="comment">// clear the rest</span></div><div class="line">            <span class="keywordflow">for</span> (u32 j=i; j<Mesh->getMeshBufferCount(); ++j)</div><div class="line">            {</div><div class="line">                Mesh->getMeshBuffer(j)->drop();</div><div class="line">            }</div><div class="line">            Mesh->MeshBuffers.erase(i,Mesh->getMeshBufferCount()-i);</div><div class="line">        }</div><div class="line">        <span class="comment">// set dirty flag to make sure that hardware copies of this</span></div><div class="line">        <span class="comment">// buffer are also updated, see IMesh::setHardwareMappingHint</span></div><div class="line">        Mesh->setDirty();</div><div class="line">        Mesh->recalculateBoundingBox();</div><div class="line">    }</div><div class="line"></div><div class="line">    <span class="comment">// Generate a SMeshBuffer which represents all the vertices and</span></div><div class="line">    <span class="comment">// indices for values of y between y0 and y1, and add it to the</span></div><div class="line">    <span class="comment">// mesh.</span></div><div class="line"></div><div class="line">    <span class="keywordtype">void</span> addstrip(<span class="keyword">const</span> HeightMap &hm, colour_func cf, u16 y0, u16 y1, u32 bufNum)</div><div class="line">    {</div><div class="line">        SMeshBuffer *buf = 0;</div><div class="line">        <span class="keywordflow">if</span> (bufNum<Mesh->getMeshBufferCount())</div><div class="line">        {</div><div class="line">            buf = (SMeshBuffer*)Mesh->getMeshBuffer(bufNum);</div><div class="line">        }</div><div class="line">        <span class="keywordflow">else</span></div><div class="line">        {</div><div class="line">            <span class="comment">// create new buffer</span></div><div class="line">            buf = <span class="keyword">new</span> SMeshBuffer();</div><div class="line">            Mesh->addMeshBuffer(buf);</div><div class="line">            <span class="comment">// to simplify things we drop here but continue using buf</span></div><div class="line">            buf->drop();</div><div class="line">        }</div><div class="line">        buf->Vertices.set_used((1 + y1 - y0) * Width);</div><div class="line"></div><div class="line">        u32 i=0;</div><div class="line">        <span class="keywordflow">for</span> (u16 y = y0; y <= y1; ++y)</div><div class="line">        {</div><div class="line">            <span class="keywordflow">for</span> (u16 x = 0; x < Width; ++x)</div><div class="line">            {</div><div class="line">                <span class="keyword">const</span> f32 z = hm.get(x, y);</div><div class="line">                <span class="keyword">const</span> f32 xx = (f32)x/(f32)Width;</div><div class="line">                <span class="keyword">const</span> f32 yy = (f32)y/(f32)Height;</div><div class="line"></div><div class="line">                S3DVertex& v = buf->Vertices[i++];</div><div class="line">                v.Pos.set(x, Scale * z, y);</div><div class="line">                v.Normal.set(hm.getnormal(x, y, Scale));</div><div class="line">                v.Color=cf(xx, yy, z);</div><div class="line">                v.TCoords.set(xx, yy);</div><div class="line">            }</div><div class="line">        }</div><div class="line"></div><div class="line">        buf->Indices.set_used(6 * (Width - 1) * (y1 - y0));</div><div class="line">        i=0;</div><div class="line">        <span class="keywordflow">for</span>(u16 y = y0; y < y1; ++y)</div><div class="line">        {</div><div class="line">            <span class="keywordflow">for</span>(u16 x = 0; x < Width - 1; ++x)</div><div class="line">            {</div><div class="line">                <span class="keyword">const</span> u16 n = (y-y0) * Width + x;</div><div class="line">                buf->Indices[i]=n;</div><div class="line">                buf->Indices[++i]=n + Width;</div><div class="line">                buf->Indices[++i]=n + Width + 1;</div><div class="line">                buf->Indices[++i]=n + Width + 1;</div><div class="line">                buf->Indices[++i]=n + 1;</div><div class="line">                buf->Indices[++i]=n;</div><div class="line">                ++i;</div><div class="line">            }</div><div class="line">        }</div><div class="line"></div><div class="line">        buf->recalculateBoundingBox();</div><div class="line">    }</div><div class="line">};</div></div><!-- fragment --><p> Our event receiver implementation, taken from tutorial 4. </p><div class="fragment"><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">    <span class="comment">// This is the one method that we have to implement</span></div><div class="line">    <span class="keyword">virtual</span> <span class="keywordtype">bool</span> OnEvent(<span class="keyword">const</span> SEvent& event)</div><div class="line">    {</div><div class="line">        <span class="comment">// Remember whether each key is down or up</span></div><div class="line">        <span class="keywordflow">if</span> (event.EventType == irr::EET_KEY_INPUT_EVENT)</div><div class="line">            KeyIsDown[<span class="keyword">event</span>.KeyInput.Key] = <span class="keyword">event</span>.KeyInput.PressedDown;</div><div class="line"></div><div class="line">        <span class="keywordflow">return</span> <span class="keyword">false</span>;</div><div class="line">    }</div><div class="line"></div><div class="line">    <span class="comment">// This is used to check whether a key is being held down</span></div><div class="line">    <span class="keyword">virtual</span> <span class="keywordtype">bool</span> IsKeyDown(EKEY_CODE keyCode)<span class="keyword"> const</span></div><div class="line"><span class="keyword">    </span>{</div><div class="line">        <span class="keywordflow">return</span> KeyIsDown[keyCode];</div><div class="line">    }</div><div class="line"></div><div class="line">    MyEventReceiver()</div><div class="line">    {</div><div class="line">        <span class="keywordflow">for</span> (u32 i=0; i<KEY_KEY_CODES_COUNT; ++i)</div><div class="line">            KeyIsDown[i] = <span class="keyword">false</span>;</div><div class="line">    }</div><div class="line"></div><div class="line"><span class="keyword">private</span>:</div><div class="line">    <span class="comment">// We use this array to store the current state of each key</span></div><div class="line">    <span class="keywordtype">bool</span> KeyIsDown[KEY_KEY_CODES_COUNT];</div><div class="line">};</div></div><!-- fragment --><p> Much of this is code taken from some of the examples. We merely set up a mesh from a heightmap, light it with a moving light, and allow the user to navigate around it. </p><div class="fragment"><div class="line"><span class="keywordtype">int</span> main(<span class="keywordtype">int</span> argc, <span class="keywordtype">char</span>* argv[])</div><div class="line">{</div><div class="line">    <span class="comment">// ask user for driver</span></div><div class="line">    video::E_DRIVER_TYPE driverType=driverChoiceConsole();</div><div class="line">    <span class="keywordflow">if</span> (driverType==video::EDT_COUNT)</div><div class="line">        <span class="keywordflow">return</span> 1;</div><div class="line"></div><div class="line">    MyEventReceiver receiver;</div><div class="line">    IrrlichtDevice* device = createDevice(driverType,</div><div class="line">            core::dimension2du(800, 600), 32, <span class="keyword">false</span>, <span class="keyword">false</span>, <span class="keyword">false</span>,</div><div class="line">            &receiver);</div><div class="line"></div><div class="line">    <span class="keywordflow">if</span>(device == 0)</div><div class="line">        <span class="keywordflow">return</span> 1;</div><div class="line"> </div><div class="line">    IVideoDriver *driver = device->getVideoDriver();</div><div class="line">    ISceneManager *smgr = device->getSceneManager();</div><div class="line">    device->setWindowCaption(L<span class="stringliteral">"Irrlicht Example for SMesh usage."</span>);</div></div><!-- fragment --><p> Create the custom mesh and initialize with a heightmap </p><div class="fragment"><div class="line">TMesh mesh;</div><div class="line">HeightMap hm = HeightMap(255, 255);</div><div class="line">hm.generate(eggbox);</div><div class="line">mesh.init(hm, 50.f, grey, driver);</div><div class="line"></div><div class="line"><span class="comment">// Add the mesh to the scene graph</span></div><div class="line">IMeshSceneNode* meshnode = smgr -> addMeshSceneNode(mesh.Mesh);</div><div class="line">meshnode->setMaterialFlag(video::EMF_BACK_FACE_CULLING, <span class="keyword">false</span>);</div><div class="line"></div><div class="line"><span class="comment">// light is just for nice effects</span></div><div class="line">ILightSceneNode *node = smgr->addLightSceneNode(0, vector3df(0,100,0),</div><div class="line">    SColorf(1.0f, 0.6f, 0.7f, 1.0f), 500.0f);</div><div class="line"><span class="keywordflow">if</span> (node)</div><div class="line">{</div><div class="line">    node->getLightData().Attenuation.set(0.f, 1.f/500.f, 0.f);</div><div class="line">    ISceneNodeAnimator* anim = smgr->createFlyCircleAnimator(vector3df(0,150,0),250.0f);</div><div class="line">    <span class="keywordflow">if</span> (anim)</div><div class="line">    {</div><div class="line">        node->addAnimator(anim);</div><div class="line">        anim->drop();</div><div class="line">    }</div><div class="line">}</div><div class="line"></div><div class="line">ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS();</div><div class="line"><span class="keywordflow">if</span> (camera)</div><div class="line">{</div><div class="line">    camera->setPosition(vector3df(-20.f, 150.f, -20.f));</div><div class="line">    camera->setTarget(vector3df(200.f, -80.f, 150.f));</div><div class="line">    camera->setFarValue(20000.0f);</div><div class="line">}</div></div><!-- fragment --><p> Just a usual render loop with event handling. The custom mesh is a usual part of the scene graph which gets rendered by drawAll. </p><div class="fragment"><div class="line">    <span class="keywordflow">while</span>(device->run())</div><div class="line">    {</div><div class="line">        <span class="keywordflow">if</span>(!device->isWindowActive())</div><div class="line">        {</div><div class="line">            device->sleep(100);</div><div class="line">            <span class="keywordflow">continue</span>;</div><div class="line">        }</div><div class="line"></div><div class="line">        <span class="keywordflow">if</span>(receiver.IsKeyDown(irr::KEY_KEY_W))</div><div class="line">        {</div><div class="line">            meshnode->setMaterialFlag(video::EMF_WIREFRAME, !meshnode->getMaterial(0).Wireframe);</div><div class="line">        }</div><div class="line">        <span class="keywordflow">else</span> <span class="keywordflow">if</span>(receiver.IsKeyDown(irr::KEY_KEY_1))</div><div class="line">        {</div><div class="line">            hm.generate(eggbox);</div><div class="line">            mesh.init(hm, 50.f, grey, driver);</div><div class="line">        }</div><div class="line">        <span class="keywordflow">else</span> <span class="keywordflow">if</span>(receiver.IsKeyDown(irr::KEY_KEY_2))</div><div class="line">        {</div><div class="line">            hm.generate(moresine);</div><div class="line">            mesh.init(hm, 50.f, yellow, driver);</div><div class="line">        }</div><div class="line">        <span class="keywordflow">else</span> <span class="keywordflow">if</span>(receiver.IsKeyDown(irr::KEY_KEY_3))</div><div class="line">        {</div><div class="line">            hm.generate(justexp);</div><div class="line">            mesh.init(hm, 50.f, yellow, driver);</div><div class="line">        }</div><div class="line"></div><div class="line">        driver->beginScene(<span class="keyword">true</span>, <span class="keyword">true</span>, SColor(0xff000000));</div><div class="line">        smgr->drawAll();</div><div class="line">        driver->endScene();</div><div class="line">    }</div><div class="line"></div><div class="line">    device->drop();</div><div class="line"></div><div class="line">    <span class="keywordflow">return</span> 0;</div><div class="line">}</div></div><!-- fragment --><p> That's it! Just compile and play around with the program. </p>
 | |
| </div></div><!-- contents -->
 | |
| <!-- HTML footer for doxygen 1.8.13-->
 | |
| <!-- start footer part -->
 | |
| <p> </p>
 | |
| </body>
 | |
| </html>
 |