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