irrlicht/examples/03.CustomSceneNode/tutorial.html

210 lines
19 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 3: Custom SceneNode</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 3: Custom SceneNode </div> </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><div class="image">
<img src="../../media/example_screenshots/003shot.jpg" alt="003shot.jpg"/>
</div>
<p>This tutorial is more advanced than the previous ones. If you are currently just playing around with the Irrlicht engine, you may want to look at other examples first. This tutorials shows how to create a custom scene node and how to use it in the engine. A custom scene node is needed if you want to implement a render technique the Irrlicht Engine currently does not support. For example, you can write an indoor portal based renderer or an advanced terrain scene node with it. By creating custom scene nodes, you can easily extend the Irrlicht Engine and adapt it to your needs.</p>
<p>I will keep the tutorial simple: Keep everything very short and everything in one .cpp file. This is the style which will also be used in most of the following tutorials.</p>
<p>To start, I include the header files, use the irr namespace, and tell the linker to link with the .lib file. </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"></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><!-- fragment --><p> Here comes the more sophisticated part of this tutorial: The class of our very own custom scene node. To keep it simple, our scene node will not be an indoor portal renderer nor a terrain scene node, but a simple tetrahedron, a 3D object consisting of 4 connected vertices, which only draws itself and does nothing more. Note that this scenario does not require a custom scene node in Irrlicht. Instead one would create a mesh from the geometry and pass it to a irr::scene::IMeshSceneNode. This example just illustrates creation of a custom scene node in a simple setting.</p>
<p>To allow our scene node to be inserted into the Irrlicht Engine scene, the class we create needs to be derived from the irr::scene::ISceneNode class and has to override some methods. </p><div class="fragment"><div class="line"><span class="keyword">class </span>CSampleSceneNode : <span class="keyword">public</span> scene::ISceneNode</div><div class="line">{</div></div><!-- fragment --><p> First, we declare some member variables: The bounding box, 4 vertices, and the material of the tetrahedron. </p><div class="fragment"><div class="line"> core::aabbox3d&lt;f32&gt; Box;</div><div class="line"> video::S3DVertex Vertices[4];</div><div class="line"> video::SMaterial Material;</div><div class="line"></div><div class="line"><span class="keyword">public</span>:</div></div><!-- fragment --><p> The parameters of the constructor specify the parent of the scene node, a pointer to the scene manager, and an id of the scene node. In the constructor we call the parent class' constructor, set some properties of the material, and create the 4 vertices of the tetrahedron. </p><div class="fragment"><div class="line">CSampleSceneNode(scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 <span class="keywordtype">id</span>)</div><div class="line"> : scene::ISceneNode(parent, mgr, id)</div><div class="line">{</div><div class="line"> Material.Wireframe = <span class="keyword">false</span>;</div><div class="line"> Material.Lighting = <span class="keyword">false</span>;</div><div class="line"></div><div class="line"> Vertices[0] = video::S3DVertex(0,0,10, 1,1,0,</div><div class="line"> video::SColor(255,0,255,255), 0, 1);</div><div class="line"> Vertices[1] = video::S3DVertex(10,0,-10, 1,0,0,</div><div class="line"> video::SColor(255,255,0,255), 1, 1);</div><div class="line"> Vertices[2] = video::S3DVertex(0,20,0, 0,1,1,</div><div class="line"> video::SColor(255,255,255,0), 1, 0);</div><div class="line"> Vertices[3] = video::S3DVertex(-10,0,-10, 0,0,1,</div><div class="line"> video::SColor(255,0,255,0), 0, 0);</div></div><!-- fragment --><p> The Irrlicht Engine needs to know the bounding box of a scene node. It will use it for automatic culling and other things. Hence, we need to create a bounding box from the 4 vertices we use. If you do not want the engine to use the box for automatic culling, and/or don't want to create the box, you could also call irr::scene::ISceneNode::setAutomaticCulling() with irr::scene::EAC_OFF. </p><div class="fragment"><div class="line"> Box.reset(Vertices[0].Pos);</div><div class="line"> <span class="keywordflow">for</span> (s32 i=1; i&lt;4; ++i)</div><div class="line"> Box.addInternalPoint(Vertices[i].Pos);</div><div class="line">}</div></div><!-- fragment --><p> Before it is drawn, the irr::scene::ISceneNode::OnRegisterSceneNode() method of every scene node in the scene is called by the scene manager. If the scene node wishes to draw itself, it may register itself in the scene manager to be drawn. This is necessary to tell the scene manager when it should call irr::scene::ISceneNode::render(). For example, normal scene nodes render their content one after another, while stencil buffer shadows would like to be drawn after all other scene nodes. And camera or light scene nodes need to be rendered before all other scene nodes (if at all). So here we simply register the scene node to render normally. If we would like to let it be rendered like cameras or light, we would have to call SceneManager-&gt;registerNodeForRendering(this, SNRT_LIGHT_AND_CAMERA); After this, we call the actual irr::scene::ISceneNode::OnRegisterSceneNode() method of the base class, which lets all the child scene nodes of this node register themselves. </p><div class="fragment"><div class="line"><span class="keyword">virtual</span> <span class="keywordtype">void</span> OnRegisterSceneNode()</div><div class="line">{</div><div class="line"> <span class="keywordflow">if</span> (IsVisible)</div><div class="line"> SceneManager-&gt;registerNodeForRe
</div></div><!-- contents -->
<!-- HTML footer for doxygen 1.8.13-->
<!-- start footer part -->
<p>&nbsp;</p>
</body>
</html>