diff options
Diffstat (limited to '')
-rw-r--r-- | libraries/irrlicht-1.8/examples/03.CustomSceneNode/main.cpp | 534 |
1 files changed, 267 insertions, 267 deletions
diff --git a/libraries/irrlicht-1.8/examples/03.CustomSceneNode/main.cpp b/libraries/irrlicht-1.8/examples/03.CustomSceneNode/main.cpp index 534f0d3..5586168 100644 --- a/libraries/irrlicht-1.8/examples/03.CustomSceneNode/main.cpp +++ b/libraries/irrlicht-1.8/examples/03.CustomSceneNode/main.cpp | |||
@@ -1,267 +1,267 @@ | |||
1 | /** Example 003 Custom SceneNode | 1 | /** Example 003 Custom SceneNode |
2 | 2 | ||
3 | This Tutorial is more advanced than the previous ones. | 3 | This Tutorial is more advanced than the previous ones. |
4 | If you are currently just playing around with the Irrlicht | 4 | If you are currently just playing around with the Irrlicht |
5 | engine, you may want to look at other examples first. | 5 | engine, you may want to look at other examples first. |
6 | This tutorials shows how to create a custom scene node and | 6 | This tutorials shows how to create a custom scene node and |
7 | how to use it in the engine. A custom scene node is needed | 7 | how to use it in the engine. A custom scene node is needed |
8 | if you want to implement a render technique the Irrlicht | 8 | if you want to implement a render technique the Irrlicht |
9 | Engine currently does not support. For example, you can write | 9 | Engine currently does not support. For example, you can write |
10 | an indoor portal based renderer or an advanced terrain scene | 10 | an indoor portal based renderer or an advanced terrain scene |
11 | node with it. By creating custom scene nodes, you can | 11 | node with it. By creating custom scene nodes, you can |
12 | easily extend the Irrlicht Engine and adapt it to your own | 12 | easily extend the Irrlicht Engine and adapt it to your own |
13 | needs. | 13 | needs. |
14 | 14 | ||
15 | I will keep the tutorial simple: Keep everything very | 15 | I will keep the tutorial simple: Keep everything very |
16 | short, everything in one .cpp file, and I'll use the engine | 16 | short, everything in one .cpp file, and I'll use the engine |
17 | here as in all other tutorials. | 17 | here as in all other tutorials. |
18 | 18 | ||
19 | To start, I include the header files, use the irr namespace, | 19 | To start, I include the header files, use the irr namespace, |
20 | and tell the linker to link with the .lib file. | 20 | and tell the linker to link with the .lib file. |
21 | */ | 21 | */ |
22 | #include <irrlicht.h> | 22 | #include <irrlicht.h> |
23 | #include "driverChoice.h" | 23 | #include "driverChoice.h" |
24 | 24 | ||
25 | using namespace irr; | 25 | using namespace irr; |
26 | 26 | ||
27 | #ifdef _MSC_VER | 27 | #ifdef _MSC_VER |
28 | #pragma comment(lib, "Irrlicht.lib") | 28 | #pragma comment(lib, "Irrlicht.lib") |
29 | #endif | 29 | #endif |
30 | 30 | ||
31 | /* | 31 | /* |
32 | Here comes the more sophisticated part of this tutorial: | 32 | Here comes the more sophisticated part of this tutorial: |
33 | The class of our very own custom scene node. To keep it simple, | 33 | The class of our very own custom scene node. To keep it simple, |
34 | our scene node will not be an indoor portal renderer nor a terrain | 34 | our scene node will not be an indoor portal renderer nor a terrain |
35 | scene node, but a simple tetraeder, a 3d object consisting of 4 | 35 | scene node, but a simple tetraeder, a 3d object consisting of 4 |
36 | connected vertices, which only draws itself and does nothing more. | 36 | connected vertices, which only draws itself and does nothing more. |
37 | Note that this scenario does not require a custom scene node in Irrlicht. | 37 | Note that this scenario does not require a custom scene node in Irrlicht. |
38 | Instead one would create a mesh from the geometry and pass it to a | 38 | Instead one would create a mesh from the geometry and pass it to a |
39 | irr::scene::IMeshSceneNode. This example just illustrates creation of a custom | 39 | irr::scene::IMeshSceneNode. This example just illustrates creation of a custom |
40 | scene node in a very simple setting. | 40 | scene node in a very simple setting. |
41 | 41 | ||
42 | To let our scene node be able to be inserted into the Irrlicht | 42 | To let our scene node be able to be inserted into the Irrlicht |
43 | Engine scene, the class we create needs to be derived from the | 43 | Engine scene, the class we create needs to be derived from the |
44 | irr::scene::ISceneNode class and has to override some methods. | 44 | irr::scene::ISceneNode class and has to override some methods. |
45 | */ | 45 | */ |
46 | 46 | ||
47 | class CSampleSceneNode : public scene::ISceneNode | 47 | class CSampleSceneNode : public scene::ISceneNode |
48 | { | 48 | { |
49 | 49 | ||
50 | /* | 50 | /* |
51 | First, we declare some member variables: | 51 | First, we declare some member variables: |
52 | The bounding box, 4 vertices, and the material of the tetraeder. | 52 | The bounding box, 4 vertices, and the material of the tetraeder. |
53 | */ | 53 | */ |
54 | core::aabbox3d<f32> Box; | 54 | core::aabbox3d<f32> Box; |
55 | video::S3DVertex Vertices[4]; | 55 | video::S3DVertex Vertices[4]; |
56 | video::SMaterial Material; | 56 | video::SMaterial Material; |
57 | 57 | ||
58 | /* | 58 | /* |
59 | The parameters of the constructor specify the parent of the scene node, | 59 | The parameters of the constructor specify the parent of the scene node, |
60 | a pointer to the scene manager, and an id of the scene node. | 60 | a pointer to the scene manager, and an id of the scene node. |
61 | In the constructor we call the parent class' constructor, | 61 | In the constructor we call the parent class' constructor, |
62 | set some properties of the material, and | 62 | set some properties of the material, and |
63 | create the 4 vertices of the tetraeder we will draw later. | 63 | create the 4 vertices of the tetraeder we will draw later. |
64 | */ | 64 | */ |
65 | 65 | ||
66 | public: | 66 | public: |
67 | 67 | ||
68 | CSampleSceneNode(scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id) | 68 | CSampleSceneNode(scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id) |
69 | : scene::ISceneNode(parent, mgr, id) | 69 | : scene::ISceneNode(parent, mgr, id) |
70 | { | 70 | { |
71 | Material.Wireframe = false; | 71 | Material.Wireframe = false; |
72 | Material.Lighting = false; | 72 | Material.Lighting = false; |
73 | 73 | ||
74 | Vertices[0] = video::S3DVertex(0,0,10, 1,1,0, | 74 | Vertices[0] = video::S3DVertex(0,0,10, 1,1,0, |
75 | video::SColor(255,0,255,255), 0, 1); | 75 | video::SColor(255,0,255,255), 0, 1); |
76 | Vertices[1] = video::S3DVertex(10,0,-10, 1,0,0, | 76 | Vertices[1] = video::S3DVertex(10,0,-10, 1,0,0, |
77 | video::SColor(255,255,0,255), 1, 1); | 77 | video::SColor(255,255,0,255), 1, 1); |
78 | Vertices[2] = video::S3DVertex(0,20,0, 0,1,1, | 78 | Vertices[2] = video::S3DVertex(0,20,0, 0,1,1, |
79 | video::SColor(255,255,255,0), 1, 0); | 79 | video::SColor(255,255,255,0), 1, 0); |
80 | Vertices[3] = video::S3DVertex(-10,0,-10, 0,0,1, | 80 | Vertices[3] = video::S3DVertex(-10,0,-10, 0,0,1, |
81 | video::SColor(255,0,255,0), 0, 0); | 81 | video::SColor(255,0,255,0), 0, 0); |
82 | 82 | ||
83 | /* | 83 | /* |
84 | The Irrlicht Engine needs to know the bounding box of a scene node. | 84 | The Irrlicht Engine needs to know the bounding box of a scene node. |
85 | It will use it for automatic culling and other things. Hence, we | 85 | It will use it for automatic culling and other things. Hence, we |
86 | need to create a bounding box from the 4 vertices we use. | 86 | need to create a bounding box from the 4 vertices we use. |
87 | If you do not want the engine to use the box for automatic culling, | 87 | If you do not want the engine to use the box for automatic culling, |
88 | and/or don't want to create the box, you could also call | 88 | and/or don't want to create the box, you could also call |
89 | irr::scene::ISceneNode::setAutomaticCulling() with irr::scene::EAC_OFF. | 89 | irr::scene::ISceneNode::setAutomaticCulling() with irr::scene::EAC_OFF. |
90 | */ | 90 | */ |
91 | Box.reset(Vertices[0].Pos); | 91 | Box.reset(Vertices[0].Pos); |
92 | for (s32 i=1; i<4; ++i) | 92 | for (s32 i=1; i<4; ++i) |
93 | Box.addInternalPoint(Vertices[i].Pos); | 93 | Box.addInternalPoint(Vertices[i].Pos); |
94 | } | 94 | } |
95 | 95 | ||
96 | /* | 96 | /* |
97 | Before it is drawn, the irr::scene::ISceneNode::OnRegisterSceneNode() | 97 | Before it is drawn, the irr::scene::ISceneNode::OnRegisterSceneNode() |
98 | method of every scene node in the scene is called by the scene manager. | 98 | method of every scene node in the scene is called by the scene manager. |
99 | If the scene node wishes to draw itself, it may register itself in the | 99 | If the scene node wishes to draw itself, it may register itself in the |
100 | scene manager to be drawn. This is necessary to tell the scene manager | 100 | scene manager to be drawn. This is necessary to tell the scene manager |
101 | when it should call irr::scene::ISceneNode::render(). For | 101 | when it should call irr::scene::ISceneNode::render(). For |
102 | example, normal scene nodes render their content one after another, | 102 | example, normal scene nodes render their content one after another, |
103 | while stencil buffer shadows would like to be drawn after all other | 103 | while stencil buffer shadows would like to be drawn after all other |
104 | scene nodes. And camera or light scene nodes need to be rendered before | 104 | scene nodes. And camera or light scene nodes need to be rendered before |
105 | all other scene nodes (if at all). So here we simply register the | 105 | all other scene nodes (if at all). So here we simply register the |
106 | scene node to render normally. If we would like to let it be rendered | 106 | scene node to render normally. If we would like to let it be rendered |
107 | like cameras or light, we would have to call | 107 | like cameras or light, we would have to call |
108 | SceneManager->registerNodeForRendering(this, SNRT_LIGHT_AND_CAMERA); | 108 | SceneManager->registerNodeForRendering(this, SNRT_LIGHT_AND_CAMERA); |
109 | After this, we call the actual | 109 | After this, we call the actual |
110 | irr::scene::ISceneNode::OnRegisterSceneNode() method of the base class, | 110 | irr::scene::ISceneNode::OnRegisterSceneNode() method of the base class, |
111 | which simply lets also all the child scene nodes of this node register | 111 | which simply lets also all the child scene nodes of this node register |
112 | themselves. | 112 | themselves. |
113 | */ | 113 | */ |
114 | virtual void OnRegisterSceneNode() | 114 | virtual void OnRegisterSceneNode() |
115 | { | 115 | { |
116 | if (IsVisible) | 116 | if (IsVisible) |
117 | SceneManager->registerNodeForRendering(this); | 117 | SceneManager->registerNodeForRendering(this); |
118 | 118 | ||
119 | ISceneNode::OnRegisterSceneNode(); | 119 | ISceneNode::OnRegisterSceneNode(); |
120 | } | 120 | } |
121 | 121 | ||
122 | /* | 122 | /* |
123 | In the render() method most of the interesting stuff happens: The | 123 | In the render() method most of the interesting stuff happens: The |
124 | Scene node renders itself. We override this method and draw the | 124 | Scene node renders itself. We override this method and draw the |
125 | tetraeder. | 125 | tetraeder. |
126 | */ | 126 | */ |
127 | virtual void render() | 127 | virtual void render() |
128 | { | 128 | { |
129 | u16 indices[] = { 0,2,3, 2,1,3, 1,0,3, 2,0,1 }; | 129 | u16 indices[] = { 0,2,3, 2,1,3, 1,0,3, 2,0,1 }; |
130 | video::IVideoDriver* driver = SceneManager->getVideoDriver(); | 130 | video::IVideoDriver* driver = SceneManager->getVideoDriver(); |
131 | 131 | ||
132 | driver->setMaterial(Material); | 132 | driver->setMaterial(Material); |
133 | driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); | 133 | driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); |
134 | driver->drawVertexPrimitiveList(&Vertices[0], 4, &indices[0], 4, video::EVT_STANDARD, scene::EPT_TRIANGLES, video::EIT_16BIT); | 134 | driver->drawVertexPrimitiveList(&Vertices[0], 4, &indices[0], 4, video::EVT_STANDARD, scene::EPT_TRIANGLES, video::EIT_16BIT); |
135 | } | 135 | } |
136 | 136 | ||
137 | /* | 137 | /* |
138 | And finally we create three small additional methods. | 138 | And finally we create three small additional methods. |
139 | irr::scene::ISceneNode::getBoundingBox() returns the bounding box of | 139 | irr::scene::ISceneNode::getBoundingBox() returns the bounding box of |
140 | this scene node, irr::scene::ISceneNode::getMaterialCount() returns the | 140 | this scene node, irr::scene::ISceneNode::getMaterialCount() returns the |
141 | amount of materials in this scene node (our tetraeder only has one | 141 | amount of materials in this scene node (our tetraeder only has one |
142 | material), and irr::scene::ISceneNode::getMaterial() returns the | 142 | material), and irr::scene::ISceneNode::getMaterial() returns the |
143 | material at an index. Because we have only one material here, we can | 143 | material at an index. Because we have only one material here, we can |
144 | return the only one material, assuming that no one ever calls | 144 | return the only one material, assuming that no one ever calls |
145 | getMaterial() with an index greater than 0. | 145 | getMaterial() with an index greater than 0. |
146 | */ | 146 | */ |
147 | virtual const core::aabbox3d<f32>& getBoundingBox() const | 147 | virtual const core::aabbox3d<f32>& getBoundingBox() const |
148 | { | 148 | { |
149 | return Box; | 149 | return Box; |
150 | } | 150 | } |
151 | 151 | ||
152 | virtual u32 getMaterialCount() const | 152 | virtual u32 getMaterialCount() const |
153 | { | 153 | { |
154 | return 1; | 154 | return 1; |
155 | } | 155 | } |
156 | 156 | ||
157 | virtual video::SMaterial& getMaterial(u32 i) | 157 | virtual video::SMaterial& getMaterial(u32 i) |
158 | { | 158 | { |
159 | return Material; | 159 | return Material; |
160 | } | 160 | } |
161 | }; | 161 | }; |
162 | 162 | ||
163 | /* | 163 | /* |
164 | That's it. The Scene node is done. Now we simply have to start | 164 | That's it. The Scene node is done. Now we simply have to start |
165 | the engine, create the scene node and a camera, and look at the result. | 165 | the engine, create the scene node and a camera, and look at the result. |
166 | */ | 166 | */ |
167 | int main() | 167 | int main() |
168 | { | 168 | { |
169 | // ask user for driver | 169 | // ask user for driver |
170 | video::E_DRIVER_TYPE driverType=driverChoiceConsole(); | 170 | video::E_DRIVER_TYPE driverType=driverChoiceConsole(); |
171 | if (driverType==video::EDT_COUNT) | 171 | if (driverType==video::EDT_COUNT) |
172 | return 1; | 172 | return 1; |
173 | 173 | ||
174 | // create device | 174 | // create device |
175 | 175 | ||
176 | IrrlichtDevice *device = createDevice(driverType, | 176 | IrrlichtDevice *device = createDevice(driverType, |
177 | core::dimension2d<u32>(640, 480), 16, false); | 177 | core::dimension2d<u32>(640, 480), 16, false); |
178 | 178 | ||
179 | if (device == 0) | 179 | if (device == 0) |
180 | return 1; // could not create selected driver. | 180 | return 1; // could not create selected driver. |
181 | 181 | ||
182 | // create engine and camera | 182 | // create engine and camera |
183 | 183 | ||
184 | device->setWindowCaption(L"Custom Scene Node - Irrlicht Engine Demo"); | 184 | device->setWindowCaption(L"Custom Scene Node - Irrlicht Engine Demo"); |
185 | 185 | ||
186 | video::IVideoDriver* driver = device->getVideoDriver(); | 186 | video::IVideoDriver* driver = device->getVideoDriver(); |
187 | scene::ISceneManager* smgr = device->getSceneManager(); | 187 | scene::ISceneManager* smgr = device->getSceneManager(); |
188 | 188 | ||
189 | smgr->addCameraSceneNode(0, core::vector3df(0,-40,0), core::vector3df(0,0,0)); | 189 | smgr->addCameraSceneNode(0, core::vector3df(0,-40,0), core::vector3df(0,0,0)); |
190 | 190 | ||
191 | /* | 191 | /* |
192 | Create our scene node. I don't check the result of calling new, as it | 192 | Create our scene node. I don't check the result of calling new, as it |
193 | should throw an exception rather than returning 0 on failure. Because | 193 | should throw an exception rather than returning 0 on failure. Because |
194 | the new node will create itself with a reference count of 1, and then | 194 | the new node will create itself with a reference count of 1, and then |
195 | will have another reference added by its parent scene node when it is | 195 | will have another reference added by its parent scene node when it is |
196 | added to the scene, I need to drop my reference to it. Best practice is | 196 | added to the scene, I need to drop my reference to it. Best practice is |
197 | to drop it only *after* I have finished using it, regardless of what | 197 | to drop it only *after* I have finished using it, regardless of what |
198 | the reference count of the object is after creation. | 198 | the reference count of the object is after creation. |
199 | */ | 199 | */ |
200 | CSampleSceneNode *myNode = | 200 | CSampleSceneNode *myNode = |
201 | new CSampleSceneNode(smgr->getRootSceneNode(), smgr, 666); | 201 | new CSampleSceneNode(smgr->getRootSceneNode(), smgr, 666); |
202 | 202 | ||
203 | /* | 203 | /* |
204 | To animate something in this boring scene consisting only of one | 204 | To animate something in this boring scene consisting only of one |
205 | tetraeder, and to show that you now can use your scene node like any | 205 | tetraeder, and to show that you now can use your scene node like any |
206 | other scene node in the engine, we add an animator to the scene node, | 206 | other scene node in the engine, we add an animator to the scene node, |
207 | which rotates the node a little bit. | 207 | which rotates the node a little bit. |
208 | irr::scene::ISceneManager::createRotationAnimator() could return 0, so | 208 | irr::scene::ISceneManager::createRotationAnimator() could return 0, so |
209 | should be checked. | 209 | should be checked. |
210 | */ | 210 | */ |
211 | scene::ISceneNodeAnimator* anim = | 211 | scene::ISceneNodeAnimator* anim = |
212 | smgr->createRotationAnimator(core::vector3df(0.8f, 0, 0.8f)); | 212 | smgr->createRotationAnimator(core::vector3df(0.8f, 0, 0.8f)); |
213 | 213 | ||
214 | if(anim) | 214 | if(anim) |
215 | { | 215 | { |
216 | myNode->addAnimator(anim); | 216 | myNode->addAnimator(anim); |
217 | 217 | ||
218 | /* | 218 | /* |
219 | I'm done referring to anim, so must | 219 | I'm done referring to anim, so must |
220 | irr::IReferenceCounted::drop() this reference now because it | 220 | irr::IReferenceCounted::drop() this reference now because it |
221 | was produced by a createFoo() function. As I shouldn't refer to | 221 | was produced by a createFoo() function. As I shouldn't refer to |
222 | it again, ensure that I can't by setting to 0. | 222 | it again, ensure that I can't by setting to 0. |
223 | */ | 223 | */ |
224 | anim->drop(); | 224 | anim->drop(); |
225 | anim = 0; | 225 | anim = 0; |
226 | } | 226 | } |
227 | 227 | ||
228 | /* | 228 | /* |
229 | I'm done with my CSampleSceneNode object, and so must drop my reference. | 229 | I'm done with my CSampleSceneNode object, and so must drop my reference. |
230 | This won't delete the object, yet, because it is still attached to the | 230 | This won't delete the object, yet, because it is still attached to the |
231 | scene graph, which prevents the deletion until the graph is deleted or the | 231 | scene graph, which prevents the deletion until the graph is deleted or the |
232 | custom scene node is removed from it. | 232 | custom scene node is removed from it. |
233 | */ | 233 | */ |
234 | myNode->drop(); | 234 | myNode->drop(); |
235 | myNode = 0; // As I shouldn't refer to it again, ensure that I can't | 235 | myNode = 0; // As I shouldn't refer to it again, ensure that I can't |
236 | 236 | ||
237 | /* | 237 | /* |
238 | Now draw everything and finish. | 238 | Now draw everything and finish. |
239 | */ | 239 | */ |
240 | u32 frames=0; | 240 | u32 frames=0; |
241 | while(device->run()) | 241 | while(device->run()) |
242 | { | 242 | { |
243 | driver->beginScene(true, true, video::SColor(0,100,100,100)); | 243 | driver->beginScene(true, true, video::SColor(0,100,100,100)); |
244 | 244 | ||
245 | smgr->drawAll(); | 245 | smgr->drawAll(); |
246 | 246 | ||
247 | driver->endScene(); | 247 | driver->endScene(); |
248 | if (++frames==100) | 248 | if (++frames==100) |
249 | { | 249 | { |
250 | core::stringw str = L"Irrlicht Engine ["; | 250 | core::stringw str = L"Irrlicht Engine ["; |
251 | str += driver->getName(); | 251 | str += driver->getName(); |
252 | str += L"] FPS: "; | 252 | str += L"] FPS: "; |
253 | str += (s32)driver->getFPS(); | 253 | str += (s32)driver->getFPS(); |
254 | 254 | ||
255 | device->setWindowCaption(str.c_str()); | 255 | device->setWindowCaption(str.c_str()); |
256 | frames=0; | 256 | frames=0; |
257 | } | 257 | } |
258 | } | 258 | } |
259 | 259 | ||
260 | device->drop(); | 260 | device->drop(); |
261 | 261 | ||
262 | return 0; | 262 | return 0; |
263 | } | 263 | } |
264 | 264 | ||
265 | /* | 265 | /* |
266 | That's it. Compile and play around with the program. | 266 | That's it. Compile and play around with the program. |
267 | **/ | 267 | **/ |