diff options
author | David Walter Seikel | 2016-03-28 22:28:34 +1000 |
---|---|---|
committer | David Walter Seikel | 2016-03-28 22:28:34 +1000 |
commit | 7028cbe09c688437910a25623098762bf0fa592d (patch) | |
tree | 10b5af58277d9880380c2251f109325542c4e6eb /src/others/irrlicht-1.8.1/source/Irrlicht/CSceneManager.cpp | |
parent | Move lemon to the src/others directory. (diff) | |
download | SledjHamr-7028cbe09c688437910a25623098762bf0fa592d.zip SledjHamr-7028cbe09c688437910a25623098762bf0fa592d.tar.gz SledjHamr-7028cbe09c688437910a25623098762bf0fa592d.tar.bz2 SledjHamr-7028cbe09c688437910a25623098762bf0fa592d.tar.xz |
Move Irrlicht to src/others.
Diffstat (limited to 'src/others/irrlicht-1.8.1/source/Irrlicht/CSceneManager.cpp')
-rw-r--r-- | src/others/irrlicht-1.8.1/source/Irrlicht/CSceneManager.cpp | 2522 |
1 files changed, 2522 insertions, 0 deletions
diff --git a/src/others/irrlicht-1.8.1/source/Irrlicht/CSceneManager.cpp b/src/others/irrlicht-1.8.1/source/Irrlicht/CSceneManager.cpp new file mode 100644 index 0000000..dd3652b --- /dev/null +++ b/src/others/irrlicht-1.8.1/source/Irrlicht/CSceneManager.cpp | |||
@@ -0,0 +1,2522 @@ | |||
1 | // Copyright (C) 2002-2012 Nikolaus Gebhardt | ||
2 | // This file is part of the "Irrlicht Engine". | ||
3 | // For conditions of distribution and use, see copyright notice in irrlicht.h | ||
4 | |||
5 | #include "IrrCompileConfig.h" | ||
6 | #include "CSceneManager.h" | ||
7 | #include "IVideoDriver.h" | ||
8 | #include "IFileSystem.h" | ||
9 | #include "SAnimatedMesh.h" | ||
10 | #include "CMeshCache.h" | ||
11 | #include "IXMLWriter.h" | ||
12 | #include "ISceneUserDataSerializer.h" | ||
13 | #include "IGUIEnvironment.h" | ||
14 | #include "IMaterialRenderer.h" | ||
15 | #include "IReadFile.h" | ||
16 | #include "IWriteFile.h" | ||
17 | #include "ISceneLoader.h" | ||
18 | |||
19 | #include "os.h" | ||
20 | |||
21 | // We need this include for the case of skinned mesh support without | ||
22 | // any such loader | ||
23 | #ifdef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_ | ||
24 | #include "CSkinnedMesh.h" | ||
25 | #endif | ||
26 | |||
27 | #ifdef _IRR_COMPILE_WITH_IRR_MESH_LOADER_ | ||
28 | #include "CIrrMeshFileLoader.h" | ||
29 | #endif | ||
30 | |||
31 | #ifdef _IRR_COMPILE_WITH_BSP_LOADER_ | ||
32 | #include "CBSPMeshFileLoader.h" | ||
33 | #endif | ||
34 | |||
35 | #ifdef _IRR_COMPILE_WITH_MD2_LOADER_ | ||
36 | #include "CMD2MeshFileLoader.h" | ||
37 | #endif | ||
38 | |||
39 | #ifdef _IRR_COMPILE_WITH_HALFLIFE_LOADER_ | ||
40 | #include "CAnimatedMeshHalfLife.h" | ||
41 | #endif | ||
42 | |||
43 | #ifdef _IRR_COMPILE_WITH_MS3D_LOADER_ | ||
44 | #include "CMS3DMeshFileLoader.h" | ||
45 | #endif | ||
46 | |||
47 | #ifdef _IRR_COMPILE_WITH_3DS_LOADER_ | ||
48 | #include "C3DSMeshFileLoader.h" | ||
49 | #endif | ||
50 | |||
51 | #ifdef _IRR_COMPILE_WITH_X_LOADER_ | ||
52 | #include "CXMeshFileLoader.h" | ||
53 | #endif | ||
54 | |||
55 | #ifdef _IRR_COMPILE_WITH_OCT_LOADER_ | ||
56 | #include "COCTLoader.h" | ||
57 | #endif | ||
58 | |||
59 | #ifdef _IRR_COMPILE_WITH_CSM_LOADER_ | ||
60 | #include "CCSMLoader.h" | ||
61 | #endif | ||
62 | |||
63 | #ifdef _IRR_COMPILE_WITH_LMTS_LOADER_ | ||
64 | #include "CLMTSMeshFileLoader.h" | ||
65 | #endif | ||
66 | |||
67 | #ifdef _IRR_COMPILE_WITH_MY3D_LOADER_ | ||
68 | #include "CMY3DMeshFileLoader.h" | ||
69 | #endif | ||
70 | |||
71 | #ifdef _IRR_COMPILE_WITH_COLLADA_LOADER_ | ||
72 | #include "CColladaFileLoader.h" | ||
73 | #endif | ||
74 | |||
75 | #ifdef _IRR_COMPILE_WITH_DMF_LOADER_ | ||
76 | #include "CDMFLoader.h" | ||
77 | #endif | ||
78 | |||
79 | #ifdef _IRR_COMPILE_WITH_OGRE_LOADER_ | ||
80 | #include "COgreMeshFileLoader.h" | ||
81 | #endif | ||
82 | |||
83 | #ifdef _IRR_COMPILE_WITH_OBJ_LOADER_ | ||
84 | #include "COBJMeshFileLoader.h" | ||
85 | #endif | ||
86 | |||
87 | #ifdef _IRR_COMPILE_WITH_MD3_LOADER_ | ||
88 | #include "CMD3MeshFileLoader.h" | ||
89 | #endif | ||
90 | |||
91 | #ifdef _IRR_COMPILE_WITH_B3D_LOADER_ | ||
92 | #include "CB3DMeshFileLoader.h" | ||
93 | #endif | ||
94 | |||
95 | #ifdef _IRR_COMPILE_WITH_LWO_LOADER_ | ||
96 | #include "CLWOMeshFileLoader.h" | ||
97 | #endif | ||
98 | |||
99 | #ifdef _IRR_COMPILE_WITH_STL_LOADER_ | ||
100 | #include "CSTLMeshFileLoader.h" | ||
101 | #endif | ||
102 | |||
103 | #ifdef _IRR_COMPILE_WITH_PLY_LOADER_ | ||
104 | #include "CPLYMeshFileLoader.h" | ||
105 | #endif | ||
106 | |||
107 | #ifdef _IRR_COMPILE_WITH_SMF_LOADER_ | ||
108 | #include "CSMFMeshFileLoader.h" | ||
109 | #endif | ||
110 | |||
111 | #ifdef _IRR_COMPILE_WITH_IRR_SCENE_LOADER_ | ||
112 | #include "CSceneLoaderIrr.h" | ||
113 | #endif | ||
114 | |||
115 | #ifdef _IRR_COMPILE_WITH_COLLADA_WRITER_ | ||
116 | #include "CColladaMeshWriter.h" | ||
117 | #endif | ||
118 | |||
119 | #ifdef _IRR_COMPILE_WITH_IRR_WRITER_ | ||
120 | #include "CIrrMeshWriter.h" | ||
121 | #endif | ||
122 | |||
123 | #ifdef _IRR_COMPILE_WITH_STL_WRITER_ | ||
124 | #include "CSTLMeshWriter.h" | ||
125 | #endif | ||
126 | |||
127 | #ifdef _IRR_COMPILE_WITH_OBJ_WRITER_ | ||
128 | #include "COBJMeshWriter.h" | ||
129 | #endif | ||
130 | |||
131 | #ifdef _IRR_COMPILE_WITH_PLY_WRITER_ | ||
132 | #include "CPLYMeshWriter.h" | ||
133 | #endif | ||
134 | |||
135 | #include "CCubeSceneNode.h" | ||
136 | #include "CSphereSceneNode.h" | ||
137 | #include "CAnimatedMeshSceneNode.h" | ||
138 | #include "COctreeSceneNode.h" | ||
139 | #include "CCameraSceneNode.h" | ||
140 | #include "CLightSceneNode.h" | ||
141 | #include "CBillboardSceneNode.h" | ||
142 | #include "CMeshSceneNode.h" | ||
143 | #include "CSkyBoxSceneNode.h" | ||
144 | #include "CSkyDomeSceneNode.h" | ||
145 | #include "CParticleSystemSceneNode.h" | ||
146 | #include "CDummyTransformationSceneNode.h" | ||
147 | #include "CWaterSurfaceSceneNode.h" | ||
148 | #include "CTerrainSceneNode.h" | ||
149 | #include "CEmptySceneNode.h" | ||
150 | #include "CTextSceneNode.h" | ||
151 | #include "CQuake3ShaderSceneNode.h" | ||
152 | #include "CVolumeLightSceneNode.h" | ||
153 | |||
154 | #include "CDefaultSceneNodeFactory.h" | ||
155 | |||
156 | #include "CSceneCollisionManager.h" | ||
157 | #include "CTriangleSelector.h" | ||
158 | #include "COctreeTriangleSelector.h" | ||
159 | #include "CTriangleBBSelector.h" | ||
160 | #include "CMetaTriangleSelector.h" | ||
161 | #include "CTerrainTriangleSelector.h" | ||
162 | |||
163 | #include "CSceneNodeAnimatorRotation.h" | ||
164 | #include "CSceneNodeAnimatorFlyCircle.h" | ||
165 | #include "CSceneNodeAnimatorFlyStraight.h" | ||
166 | #include "CSceneNodeAnimatorTexture.h" | ||
167 | #include "CSceneNodeAnimatorCollisionResponse.h" | ||
168 | #include "CSceneNodeAnimatorDelete.h" | ||
169 | #include "CSceneNodeAnimatorFollowSpline.h" | ||
170 | #include "CSceneNodeAnimatorCameraFPS.h" | ||
171 | #include "CSceneNodeAnimatorCameraMaya.h" | ||
172 | #include "CDefaultSceneNodeAnimatorFactory.h" | ||
173 | |||
174 | #include "CGeometryCreator.h" | ||
175 | |||
176 | namespace irr | ||
177 | { | ||
178 | namespace scene | ||
179 | { | ||
180 | |||
181 | //! constructor | ||
182 | CSceneManager::CSceneManager(video::IVideoDriver* driver, io::IFileSystem* fs, | ||
183 | gui::ICursorControl* cursorControl, IMeshCache* cache, | ||
184 | gui::IGUIEnvironment* gui) | ||
185 | : ISceneNode(0, 0), Driver(driver), FileSystem(fs), GUIEnvironment(gui), | ||
186 | CursorControl(cursorControl), CollisionManager(0), | ||
187 | ActiveCamera(0), ShadowColor(150,0,0,0), AmbientLight(0,0,0,0), | ||
188 | MeshCache(cache), CurrentRendertime(ESNRP_NONE), LightManager(0), | ||
189 | IRR_XML_FORMAT_SCENE(L"irr_scene"), IRR_XML_FORMAT_NODE(L"node"), IRR_XML_FORMAT_NODE_ATTR_TYPE(L"type") | ||
190 | { | ||
191 | #ifdef _DEBUG | ||
192 | ISceneManager::setDebugName("CSceneManager ISceneManager"); | ||
193 | ISceneNode::setDebugName("CSceneManager ISceneNode"); | ||
194 | #endif | ||
195 | |||
196 | // root node's scene manager | ||
197 | SceneManager = this; | ||
198 | |||
199 | // set scene parameters | ||
200 | Parameters.setAttribute( DEBUG_NORMAL_LENGTH, 1.f ); | ||
201 | Parameters.setAttribute( DEBUG_NORMAL_COLOR, video::SColor(255, 34, 221, 221)); | ||
202 | |||
203 | if (Driver) | ||
204 | Driver->grab(); | ||
205 | |||
206 | if (FileSystem) | ||
207 | FileSystem->grab(); | ||
208 | |||
209 | if (CursorControl) | ||
210 | CursorControl->grab(); | ||
211 | |||
212 | if (GUIEnvironment) | ||
213 | GUIEnvironment->grab(); | ||
214 | |||
215 | // create mesh cache if not there already | ||
216 | if (!MeshCache) | ||
217 | MeshCache = new CMeshCache(); | ||
218 | else | ||
219 | MeshCache->grab(); | ||
220 | |||
221 | // create collision manager | ||
222 | CollisionManager = new CSceneCollisionManager(this, Driver); | ||
223 | |||
224 | // create geometry creator | ||
225 | GeometryCreator = new CGeometryCreator(); | ||
226 | |||
227 | // add file format loaders. add the least commonly used ones first, | ||
228 | // as these are checked last | ||
229 | |||
230 | // TODO: now that we have multiple scene managers, these should be | ||
231 | // shallow copies from the previous manager if there is one. | ||
232 | |||
233 | #ifdef _IRR_COMPILE_WITH_STL_LOADER_ | ||
234 | MeshLoaderList.push_back(new CSTLMeshFileLoader()); | ||
235 | #endif | ||
236 | #ifdef _IRR_COMPILE_WITH_PLY_LOADER_ | ||
237 | MeshLoaderList.push_back(new CPLYMeshFileLoader(this)); | ||
238 | #endif | ||
239 | #ifdef _IRR_COMPILE_WITH_SMF_LOADER_ | ||
240 | MeshLoaderList.push_back(new CSMFMeshFileLoader(Driver)); | ||
241 | #endif | ||
242 | #ifdef _IRR_COMPILE_WITH_OCT_LOADER_ | ||
243 | MeshLoaderList.push_back(new COCTLoader(this, FileSystem)); | ||
244 | #endif | ||
245 | #ifdef _IRR_COMPILE_WITH_CSM_LOADER_ | ||
246 | MeshLoaderList.push_back(new CCSMLoader(this, FileSystem)); | ||
247 | #endif | ||
248 | #ifdef _IRR_COMPILE_WITH_LMTS_LOADER_ | ||
249 | MeshLoaderList.push_back(new CLMTSMeshFileLoader(FileSystem, Driver, &Parameters)); | ||
250 | #endif | ||
251 | #ifdef _IRR_COMPILE_WITH_MY3D_LOADER_ | ||
252 | MeshLoaderList.push_back(new CMY3DMeshFileLoader(this, FileSystem)); | ||
253 | #endif | ||
254 | #ifdef _IRR_COMPILE_WITH_DMF_LOADER_ | ||
255 | MeshLoaderList.push_back(new CDMFLoader(this, FileSystem)); | ||
256 | #endif | ||
257 | #ifdef _IRR_COMPILE_WITH_OGRE_LOADER_ | ||
258 | MeshLoaderList.push_back(new COgreMeshFileLoader(FileSystem, Driver)); | ||
259 | #endif | ||
260 | #ifdef _IRR_COMPILE_WITH_HALFLIFE_LOADER_ | ||
261 | MeshLoaderList.push_back(new CHalflifeMDLMeshFileLoader( this )); | ||
262 | #endif | ||
263 | #ifdef _IRR_COMPILE_WITH_MD3_LOADER_ | ||
264 | MeshLoaderList.push_back(new CMD3MeshFileLoader( this)); | ||
265 | #endif | ||
266 | #ifdef _IRR_COMPILE_WITH_LWO_LOADER_ | ||
267 | MeshLoaderList.push_back(new CLWOMeshFileLoader(this, FileSystem)); | ||
268 | #endif | ||
269 | #ifdef _IRR_COMPILE_WITH_MD2_LOADER_ | ||
270 | MeshLoaderList.push_back(new CMD2MeshFileLoader()); | ||
271 | #endif | ||
272 | #ifdef _IRR_COMPILE_WITH_IRR_MESH_LOADER_ | ||
273 | MeshLoaderList.push_back(new CIrrMeshFileLoader(this, FileSystem)); | ||
274 | #endif | ||
275 | #ifdef _IRR_COMPILE_WITH_BSP_LOADER_ | ||
276 | MeshLoaderList.push_back(new CBSPMeshFileLoader(this, FileSystem)); | ||
277 | #endif | ||
278 | #ifdef _IRR_COMPILE_WITH_COLLADA_LOADER_ | ||
279 | MeshLoaderList.push_back(new CColladaFileLoader(this, FileSystem)); | ||
280 | #endif | ||
281 | #ifdef _IRR_COMPILE_WITH_3DS_LOADER_ | ||
282 | MeshLoaderList.push_back(new C3DSMeshFileLoader(this, FileSystem)); | ||
283 | #endif | ||
284 | #ifdef _IRR_COMPILE_WITH_X_LOADER_ | ||
285 | MeshLoaderList.push_back(new CXMeshFileLoader(this, FileSystem)); | ||
286 | #endif | ||
287 | #ifdef _IRR_COMPILE_WITH_MS3D_LOADER_ | ||
288 | MeshLoaderList.push_back(new CMS3DMeshFileLoader(Driver)); | ||
289 | #endif | ||
290 | #ifdef _IRR_COMPILE_WITH_OBJ_LOADER_ | ||
291 | MeshLoaderList.push_back(new COBJMeshFileLoader(this, FileSystem)); | ||
292 | #endif | ||
293 | #ifdef _IRR_COMPILE_WITH_B3D_LOADER_ | ||
294 | MeshLoaderList.push_back(new CB3DMeshFileLoader(this)); | ||
295 | #endif | ||
296 | |||
297 | // scene loaders | ||
298 | #ifdef _IRR_COMPILE_WITH_IRR_SCENE_LOADER_ | ||
299 | SceneLoaderList.push_back(new CSceneLoaderIrr(this, FileSystem)); | ||
300 | #endif | ||
301 | |||
302 | |||
303 | // factories | ||
304 | ISceneNodeFactory* factory = new CDefaultSceneNodeFactory(this); | ||
305 | registerSceneNodeFactory(factory); | ||
306 | factory->drop(); | ||
307 | |||
308 | ISceneNodeAnimatorFactory* animatorFactory = new CDefaultSceneNodeAnimatorFactory(this, CursorControl); | ||
309 | registerSceneNodeAnimatorFactory(animatorFactory); | ||
310 | animatorFactory->drop(); | ||
311 | } | ||
312 | |||
313 | |||
314 | //! destructor | ||
315 | CSceneManager::~CSceneManager() | ||
316 | { | ||
317 | clearDeletionList(); | ||
318 | |||
319 | //! force to remove hardwareTextures from the driver | ||
320 | //! because Scenes may hold internally data bounded to sceneNodes | ||
321 | //! which may be destroyed twice | ||
322 | if (Driver) | ||
323 | Driver->removeAllHardwareBuffers(); | ||
324 | |||
325 | if (FileSystem) | ||
326 | FileSystem->drop(); | ||
327 | |||
328 | if (CursorControl) | ||
329 | CursorControl->drop(); | ||
330 | |||
331 | if (CollisionManager) | ||
332 | CollisionManager->drop(); | ||
333 | |||
334 | if (GeometryCreator) | ||
335 | GeometryCreator->drop(); | ||
336 | |||
337 | if (GUIEnvironment) | ||
338 | GUIEnvironment->drop(); | ||
339 | |||
340 | u32 i; | ||
341 | for (i=0; i<MeshLoaderList.size(); ++i) | ||
342 | MeshLoaderList[i]->drop(); | ||
343 | |||
344 | for (i=0; i<SceneLoaderList.size(); ++i) | ||
345 | SceneLoaderList[i]->drop(); | ||
346 | |||
347 | if (ActiveCamera) | ||
348 | ActiveCamera->drop(); | ||
349 | ActiveCamera = 0; | ||
350 | |||
351 | if (MeshCache) | ||
352 | MeshCache->drop(); | ||
353 | |||
354 | for (i=0; i<SceneNodeFactoryList.size(); ++i) | ||
355 | SceneNodeFactoryList[i]->drop(); | ||
356 | |||
357 | for (i=0; i<SceneNodeAnimatorFactoryList.size(); ++i) | ||
358 | SceneNodeAnimatorFactoryList[i]->drop(); | ||
359 | |||
360 | if (LightManager) | ||
361 | LightManager->drop(); | ||
362 | |||
363 | // remove all nodes and animators before dropping the driver | ||
364 | // as render targets may be destroyed twice | ||
365 | |||
366 | removeAll(); | ||
367 | removeAnimators(); | ||
368 | |||
369 | if (Driver) | ||
370 | Driver->drop(); | ||
371 | } | ||
372 | |||
373 | |||
374 | //! gets an animateable mesh. loads it if needed. returned pointer must not be dropped. | ||
375 | IAnimatedMesh* CSceneManager::getMesh(const io::path& filename) | ||
376 | { | ||
377 | IAnimatedMesh* msh = MeshCache->getMeshByName(filename); | ||
378 | if (msh) | ||
379 | return msh; | ||
380 | |||
381 | io::IReadFile* file = FileSystem->createAndOpenFile(filename); | ||
382 | if (!file) | ||
383 | { | ||
384 | os::Printer::log("Could not load mesh, because file could not be opened: ", filename, ELL_ERROR); | ||
385 | return 0; | ||
386 | } | ||
387 | |||
388 | // iterate the list in reverse order so user-added loaders can override the built-in ones | ||
389 | s32 count = MeshLoaderList.size(); | ||
390 | for (s32 i=count-1; i>=0; --i) | ||
391 | { | ||
392 | if (MeshLoaderList[i]->isALoadableFileExtension(filename)) | ||
393 | { | ||
394 | // reset file to avoid side effects of previous calls to createMesh | ||
395 | file->seek(0); | ||
396 | msh = MeshLoaderList[i]->createMesh(file); | ||
397 | if (msh) | ||
398 | { | ||
399 | MeshCache->addMesh(filename, msh); | ||
400 | msh->drop(); | ||
401 | break; | ||
402 | } | ||
403 | } | ||
404 | } | ||
405 | |||
406 | file->drop(); | ||
407 | |||
408 | if (!msh) | ||
409 | os::Printer::log("Could not load mesh, file format seems to be unsupported", filename, ELL_ERROR); | ||
410 | else | ||
411 | os::Printer::log("Loaded mesh", filename, ELL_INFORMATION); | ||
412 | |||
413 | return msh; | ||
414 | } | ||
415 | |||
416 | |||
417 | //! gets an animateable mesh. loads it if needed. returned pointer must not be dropped. | ||
418 | IAnimatedMesh* CSceneManager::getMesh(io::IReadFile* file) | ||
419 | { | ||
420 | if (!file) | ||
421 | return 0; | ||
422 | |||
423 | io::path name = file->getFileName(); | ||
424 | IAnimatedMesh* msh = MeshCache->getMeshByName(file->getFileName()); | ||
425 | if (msh) | ||
426 | return msh; | ||
427 | |||
428 | // iterate the list in reverse order so user-added loaders can override the built-in ones | ||
429 | s32 count = MeshLoaderList.size(); | ||
430 | for (s32 i=count-1; i>=0; --i) | ||
431 | { | ||
432 | if (MeshLoaderList[i]->isALoadableFileExtension(name)) | ||
433 | { | ||
434 | // reset file to avoid side effects of previous calls to createMesh | ||
435 | file->seek(0); | ||
436 | msh = MeshLoaderList[i]->createMesh(file); | ||
437 | if (msh) | ||
438 | { | ||
439 | MeshCache->addMesh(file->getFileName(), msh); | ||
440 | msh->drop(); | ||
441 | break; | ||
442 | } | ||
443 | } | ||
444 | } | ||
445 | |||
446 | if (!msh) | ||
447 | os::Printer::log("Could not load mesh, file format seems to be unsupported", file->getFileName(), ELL_ERROR); | ||
448 | else | ||
449 | os::Printer::log("Loaded mesh", file->getFileName(), ELL_INFORMATION); | ||
450 | |||
451 | return msh; | ||
452 | } | ||
453 | |||
454 | |||
455 | //! returns the video driver | ||
456 | video::IVideoDriver* CSceneManager::getVideoDriver() | ||
457 | { | ||
458 | return Driver; | ||
459 | } | ||
460 | |||
461 | |||
462 | //! returns the GUI Environment | ||
463 | gui::IGUIEnvironment* CSceneManager::getGUIEnvironment() | ||
464 | { | ||
465 | return GUIEnvironment; | ||
466 | } | ||
467 | |||
468 | //! Get the active FileSystem | ||
469 | /** \return Pointer to the FileSystem | ||
470 | This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ | ||
471 | io::IFileSystem* CSceneManager::getFileSystem() | ||
472 | { | ||
473 | return FileSystem; | ||
474 | } | ||
475 | |||
476 | //! Adds a text scene node, which is able to display | ||
477 | //! 2d text at a position in three dimensional space | ||
478 | ITextSceneNode* CSceneManager::addTextSceneNode(gui::IGUIFont* font, | ||
479 | const wchar_t* text, video::SColor color, ISceneNode* parent, | ||
480 | const core::vector3df& position, s32 id) | ||
481 | { | ||
482 | if (!font) | ||
483 | return 0; | ||
484 | |||
485 | if (!parent) | ||
486 | parent = this; | ||
487 | |||
488 | ITextSceneNode* t = new CTextSceneNode(parent, this, id, font, | ||
489 | getSceneCollisionManager(), position, text, color); | ||
490 | t->drop(); | ||
491 | |||
492 | return t; | ||
493 | } | ||
494 | |||
495 | |||
496 | //! Adds a text scene node, which uses billboards | ||
497 | IBillboardTextSceneNode* CSceneManager::addBillboardTextSceneNode(gui::IGUIFont* font, | ||
498 | const wchar_t* text, ISceneNode* parent, | ||
499 | const core::dimension2d<f32>& size, | ||
500 | const core::vector3df& position, s32 id, | ||
501 | video::SColor colorTop, video::SColor colorBottom) | ||
502 | { | ||
503 | if (!font && GUIEnvironment) | ||
504 | font = GUIEnvironment->getBuiltInFont(); | ||
505 | |||
506 | if (!font) | ||
507 | return 0; | ||
508 | |||
509 | if (!parent) | ||
510 | parent = this; | ||
511 | |||
512 | IBillboardTextSceneNode* node = new CBillboardTextSceneNode(parent, this, id, font, text, position, size, | ||
513 | colorTop, colorBottom); | ||
514 | node->drop(); | ||
515 | |||
516 | return node; | ||
517 | |||
518 | } | ||
519 | |||
520 | |||
521 | //! Adds a scene node, which can render a quake3 shader | ||
522 | IMeshSceneNode* CSceneManager::addQuake3SceneNode(const IMeshBuffer* meshBuffer, | ||
523 | const quake3::IShader * shader, | ||
524 | ISceneNode* parent, s32 id ) | ||
525 | { | ||
526 | #ifdef _IRR_COMPILE_WITH_BSP_LOADER_ | ||
527 | if (!shader) | ||
528 | return 0; | ||
529 | |||
530 | if (!parent) | ||
531 | parent = this; | ||
532 | |||
533 | CQuake3ShaderSceneNode* node = new CQuake3ShaderSceneNode( parent, | ||
534 | this, id, FileSystem, | ||
535 | meshBuffer, shader ); | ||
536 | node->drop(); | ||
537 | |||
538 | return node; | ||
539 | #else | ||
540 | return 0; | ||
541 | #endif | ||
542 | } | ||
543 | |||
544 | |||
545 | //! adds Volume Lighting Scene Node. | ||
546 | //! the returned pointer must not be dropped. | ||
547 | IVolumeLightSceneNode* CSceneManager::addVolumeLightSceneNode( | ||
548 | ISceneNode* parent, s32 id, | ||
549 | const u32 subdivU, const u32 subdivV, | ||
550 | const video::SColor foot, const video::SColor tail, | ||
551 | const core::vector3df& position, const core::vector3df& rotation, const core::vector3df& scale) | ||
552 | { | ||
553 | if (!parent) | ||
554 | parent = this; | ||
555 | |||
556 | IVolumeLightSceneNode* node = new CVolumeLightSceneNode(parent, this, id, subdivU, subdivV, foot, tail, position, rotation, scale); | ||
557 | node->drop(); | ||
558 | |||
559 | return node; | ||
560 | } | ||
561 | |||
562 | |||
563 | //! adds a test scene node for test purposes to the scene. It is a simple cube of (1,1,1) size. | ||
564 | //! the returned pointer must not be dropped. | ||
565 | IMeshSceneNode* CSceneManager::addCubeSceneNode(f32 size, ISceneNode* parent, | ||
566 | s32 id, const core::vector3df& position, | ||
567 | const core::vector3df& rotation, const core::vector3df& scale) | ||
568 | { | ||
569 | if (!parent) | ||
570 | parent = this; | ||
571 | |||
572 | IMeshSceneNode* node = new CCubeSceneNode(size, parent, this, id, position, rotation, scale); | ||
573 | node->drop(); | ||
574 | |||
575 | return node; | ||
576 | } | ||
577 | |||
578 | |||
579 | //! Adds a sphere scene node for test purposes to the scene. | ||
580 | IMeshSceneNode* CSceneManager::addSphereSceneNode(f32 radius, s32 polyCount, | ||
581 | ISceneNode* parent, s32 id, const core::vector3df& position, | ||
582 | const core::vector3df& rotation, const core::vector3df& scale) | ||
583 | { | ||
584 | if (!parent) | ||
585 | parent = this; | ||
586 | |||
587 | IMeshSceneNode* node = new CSphereSceneNode(radius, polyCount, polyCount, parent, this, id, position, rotation, scale); | ||
588 | node->drop(); | ||
589 | |||
590 | return node; | ||
591 | } | ||
592 | |||
593 | |||
594 | //! adds a scene node for rendering a static mesh | ||
595 | //! the returned pointer must not be dropped. | ||
596 | IMeshSceneNode* CSceneManager::addMeshSceneNode(IMesh* mesh, ISceneNode* parent, s32 id, | ||
597 | const core::vector3df& position, const core::vector3df& rotation, | ||
598 | const core::vector3df& scale, bool alsoAddIfMeshPointerZero) | ||
599 | { | ||
600 | if (!alsoAddIfMeshPointerZero && !mesh) | ||
601 | return 0; | ||
602 | |||
603 | if (!parent) | ||
604 | parent = this; | ||
605 | |||
606 | IMeshSceneNode* node = new CMeshSceneNode(mesh, parent, this, id, position, rotation, scale); | ||
607 | node->drop(); | ||
608 | |||
609 | return node; | ||
610 | } | ||
611 | |||
612 | |||
613 | //! Adds a scene node for rendering a animated water surface mesh. | ||
614 | ISceneNode* CSceneManager::addWaterSurfaceSceneNode(IMesh* mesh, f32 waveHeight, f32 waveSpeed, f32 waveLength, | ||
615 | ISceneNode* parent, s32 id, const core::vector3df& position, | ||
616 | const core::vector3df& rotation, const core::vector3df& scale) | ||
617 | { | ||
618 | if (!parent) | ||
619 | parent = this; | ||
620 | |||
621 | ISceneNode* node = new CWaterSurfaceSceneNode(waveHeight, waveSpeed, waveLength, | ||
622 | mesh, parent, this, id, position, rotation, scale); | ||
623 | |||
624 | node->drop(); | ||
625 | |||
626 | return node; | ||
627 | } | ||
628 | |||
629 | |||
630 | //! adds a scene node for rendering an animated mesh model | ||
631 | IAnimatedMeshSceneNode* CSceneManager::addAnimatedMeshSceneNode(IAnimatedMesh* mesh, ISceneNode* parent, s32 id, | ||
632 | const core::vector3df& position, const core::vector3df& rotation, | ||
633 | const core::vector3df& scale, bool alsoAddIfMeshPointerZero) | ||
634 | { | ||
635 | if (!alsoAddIfMeshPointerZero && !mesh) | ||
636 | return 0; | ||
637 | |||
638 | if (!parent) | ||
639 | parent = this; | ||
640 | |||
641 | IAnimatedMeshSceneNode* node = | ||
642 | new CAnimatedMeshSceneNode(mesh, parent, this, id, position, rotation, scale); | ||
643 | node->drop(); | ||
644 | |||
645 | return node; | ||
646 | } | ||
647 | |||
648 | |||
649 | //! Adds a scene node for rendering using a octree to the scene graph. This a good method for rendering | ||
650 | //! scenes with lots of geometry. The Octree is built on the fly from the mesh, much | ||
651 | //! faster then a bsp tree. | ||
652 | IMeshSceneNode* CSceneManager::addOctreeSceneNode(IAnimatedMesh* mesh, ISceneNode* parent, | ||
653 | s32 id, s32 minimalPolysPerNode, bool alsoAddIfMeshPointerZero) | ||
654 | { | ||
655 | if (!alsoAddIfMeshPointerZero && (!mesh || !mesh->getFrameCount())) | ||
656 | return 0; | ||
657 | |||
658 | return addOctreeSceneNode(mesh ? mesh->getMesh(0) : 0, | ||
659 | parent, id, minimalPolysPerNode, | ||
660 | alsoAddIfMeshPointerZero); | ||
661 | } | ||
662 | |||
663 | |||
664 | //! Adds a scene node for rendering using a octree. This a good method for rendering | ||
665 | //! scenes with lots of geometry. The Octree is built on the fly from the mesh, much | ||
666 | //! faster then a bsp tree. | ||
667 | IMeshSceneNode* CSceneManager::addOctreeSceneNode(IMesh* mesh, ISceneNode* parent, | ||
668 | s32 id, s32 minimalPolysPerNode, bool alsoAddIfMeshPointerZero) | ||
669 | { | ||
670 | if (!alsoAddIfMeshPointerZero && !mesh) | ||
671 | return 0; | ||
672 | |||
673 | if (!parent) | ||
674 | parent = this; | ||
675 | |||
676 | COctreeSceneNode* node = new COctreeSceneNode(parent, this, id, minimalPolysPerNode); | ||
677 | |||
678 | if (node) | ||
679 | { | ||
680 | node->setMesh(mesh); | ||
681 | node->drop(); | ||
682 | } | ||
683 | |||
684 | return node; | ||
685 | } | ||
686 | |||
687 | |||
688 | //! Adds a camera scene node to the tree and sets it as active camera. | ||
689 | //! \param position: Position of the space relative to its parent where the camera will be placed. | ||
690 | //! \param lookat: Position where the camera will look at. Also known as target. | ||
691 | //! \param parent: Parent scene node of the camera. Can be null. If the parent moves, | ||
692 | //! the camera will move too. | ||
693 | //! \return Returns pointer to interface to camera | ||
694 | ICameraSceneNode* CSceneManager::addCameraSceneNode(ISceneNode* parent, | ||
695 | const core::vector3df& position, const core::vector3df& lookat, s32 id, | ||
696 | bool makeActive) | ||
697 | { | ||
698 | if (!parent) | ||
699 | parent = this; | ||
700 | |||
701 | ICameraSceneNode* node = new CCameraSceneNode(parent, this, id, position, lookat); | ||
702 | |||
703 | if (makeActive) | ||
704 | setActiveCamera(node); | ||
705 | node->drop(); | ||
706 | |||
707 | return node; | ||
708 | } | ||
709 | |||
710 | |||
711 | //! Adds a camera scene node which is able to be controlled with the mouse similar | ||
712 | //! to in the 3D Software Maya by Alias Wavefront. | ||
713 | //! The returned pointer must not be dropped. | ||
714 | ICameraSceneNode* CSceneManager::addCameraSceneNodeMaya(ISceneNode* parent, | ||
715 | f32 rotateSpeed, f32 zoomSpeed, f32 translationSpeed, s32 id, f32 distance, | ||
716 | bool makeActive) | ||
717 | { | ||
718 | ICameraSceneNode* node = addCameraSceneNode(parent, core::vector3df(), | ||
719 | core::vector3df(0,0,100), id, makeActive); | ||
720 | if (node) | ||
721 | { | ||
722 | ISceneNodeAnimator* anm = new CSceneNodeAnimatorCameraMaya(CursorControl, | ||
723 | rotateSpeed, zoomSpeed, translationSpeed, distance); | ||
724 | |||
725 | node->addAnimator(anm); | ||
726 | anm->drop(); | ||
727 | } | ||
728 | |||
729 | return node; | ||
730 | } | ||
731 | |||
732 | |||
733 | //! Adds a camera scene node which is able to be controlled with the mouse and keys | ||
734 | //! like in most first person shooters (FPS): | ||
735 | ICameraSceneNode* CSceneManager::addCameraSceneNodeFPS(ISceneNode* parent, | ||
736 | f32 rotateSpeed, f32 moveSpeed, s32 id, SKeyMap* keyMapArray, | ||
737 | s32 keyMapSize, bool noVerticalMovement, f32 jumpSpeed, | ||
738 | bool invertMouseY, bool makeActive) | ||
739 | { | ||
740 | ICameraSceneNode* node = addCameraSceneNode(parent, core::vector3df(), | ||
741 | core::vector3df(0,0,100), id, makeActive); | ||
742 | if (node) | ||
743 | { | ||
744 | ISceneNodeAnimator* anm = new CSceneNodeAnimatorCameraFPS(CursorControl, | ||
745 | rotateSpeed, moveSpeed, jumpSpeed, | ||
746 | keyMapArray, keyMapSize, noVerticalMovement, invertMouseY); | ||
747 | |||
748 | // Bind the node's rotation to its target. This is consistent with 1.4.2 and below. | ||
749 | node->bindTargetAndRotation(true); | ||
750 | node->addAnimator(anm); | ||
751 | anm->drop(); | ||
752 | } | ||
753 | |||
754 | return node; | ||
755 | } | ||
756 | |||
757 | |||
758 | //! Adds a dynamic light scene node. The light will cast dynamic light on all | ||
759 | //! other scene nodes in the scene, which have the material flag video::MTF_LIGHTING | ||
760 | //! turned on. (This is the default setting in most scene nodes). | ||
761 | ILightSceneNode* CSceneManager::addLightSceneNode(ISceneNode* parent, | ||
762 | const core::vector3df& position, video::SColorf color, f32 range, s32 id) | ||
763 | { | ||
764 | if (!parent) | ||
765 | parent = this; | ||
766 | |||
767 | ILightSceneNode* node = new CLightSceneNode(parent, this, id, position, color, range); | ||
768 | node->drop(); | ||
769 | |||
770 | return node; | ||
771 | } | ||
772 | |||
773 | |||
774 | //! Adds a billboard scene node to the scene. A billboard is like a 3d sprite: A 2d element, | ||
775 | //! which always looks to the camera. It is usually used for things like explosions, fire, | ||
776 | //! lensflares and things like that. | ||
777 | IBillboardSceneNode* CSceneManager::addBillboardSceneNode(ISceneNode* parent, | ||
778 | const core::dimension2d<f32>& size, const core::vector3df& position, s32 id, | ||
779 | video::SColor colorTop, video::SColor colorBottom | ||
780 | ) | ||
781 | { | ||
782 | if (!parent) | ||
783 | parent = this; | ||
784 | |||
785 | IBillboardSceneNode* node = new CBillboardSceneNode(parent, this, id, position, size, | ||
786 | colorTop, colorBottom); | ||
787 | node->drop(); | ||
788 | |||
789 | return node; | ||
790 | } | ||
791 | |||
792 | |||
793 | //! Adds a skybox scene node. A skybox is a big cube with 6 textures on it and | ||
794 | //! is drawn around the camera position. | ||
795 | ISceneNode* CSceneManager::addSkyBoxSceneNode(video::ITexture* top, video::ITexture* bottom, | ||
796 | video::ITexture* left, video::ITexture* right, video::ITexture* front, | ||
797 | video::ITexture* back, ISceneNode* parent, s32 id) | ||
798 | { | ||
799 | if (!parent) | ||
800 | parent = this; | ||
801 | |||
802 | ISceneNode* node = new CSkyBoxSceneNode(top, bottom, left, right, | ||
803 | front, back, parent, this, id); | ||
804 | |||
805 | node->drop(); | ||
806 | return node; | ||
807 | } | ||
808 | |||
809 | |||
810 | //! Adds a skydome scene node. A skydome is a large (half-) sphere with a | ||
811 | //! panoramic texture on it and is drawn around the camera position. | ||
812 | ISceneNode* CSceneManager::addSkyDomeSceneNode(video::ITexture* texture, | ||
813 | u32 horiRes, u32 vertRes, f32 texturePercentage,f32 spherePercentage, f32 radius, | ||
814 | ISceneNode* parent, s32 id) | ||
815 | { | ||
816 | if (!parent) | ||
817 | parent = this; | ||
818 | |||
819 | ISceneNode* node = new CSkyDomeSceneNode(texture, horiRes, vertRes, | ||
820 | texturePercentage, spherePercentage, radius, parent, this, id); | ||
821 | |||
822 | node->drop(); | ||
823 | return node; | ||
824 | } | ||
825 | |||
826 | |||
827 | //! Adds a particle system scene node. | ||
828 | IParticleSystemSceneNode* CSceneManager::addParticleSystemSceneNode( | ||
829 | bool withDefaultEmitter, ISceneNode* parent, s32 id, | ||
830 | const core::vector3df& position, const core::vector3df& rotation, | ||
831 | const core::vector3df& scale) | ||
832 | { | ||
833 | if (!parent) | ||
834 | parent = this; | ||
835 | |||
836 | IParticleSystemSceneNode* node = new CParticleSystemSceneNode(withDefaultEmitter, | ||
837 | parent, this, id, position, rotation, scale); | ||
838 | node->drop(); | ||
839 | |||
840 | return node; | ||
841 | } | ||
842 | |||
843 | |||
844 | //! Adds a terrain scene node to the scene graph. | ||
845 | ITerrainSceneNode* CSceneManager::addTerrainSceneNode( | ||
846 | const io::path& heightMapFileName, | ||
847 | ISceneNode* parent, s32 id, | ||
848 | const core::vector3df& position, | ||
849 | const core::vector3df& rotation, | ||
850 | const core::vector3df& scale, | ||
851 | video::SColor vertexColor, | ||
852 | s32 maxLOD, E_TERRAIN_PATCH_SIZE patchSize, s32 smoothFactor, | ||
853 | bool addAlsoIfHeightmapEmpty) | ||
854 | { | ||
855 | io::IReadFile* file = FileSystem->createAndOpenFile(heightMapFileName); | ||
856 | |||
857 | if (!file && !addAlsoIfHeightmapEmpty) | ||
858 | { | ||
859 | os::Printer::log("Could not load terrain, because file could not be opened.", | ||
860 | heightMapFileName, ELL_ERROR); | ||
861 | return 0; | ||
862 | } | ||
863 | |||
864 | ITerrainSceneNode* terrain = addTerrainSceneNode(file, parent, id, | ||
865 | position, rotation, scale, vertexColor, maxLOD, patchSize, | ||
866 | smoothFactor, addAlsoIfHeightmapEmpty); | ||
867 | |||
868 | if (file) | ||
869 | file->drop(); | ||
870 | |||
871 | return terrain; | ||
872 | } | ||
873 | |||
874 | //! Adds a terrain scene node to the scene graph. | ||
875 | ITerrainSceneNode* CSceneManager::addTerrainSceneNode( | ||
876 | io::IReadFile* heightMapFile, | ||
877 | ISceneNode* parent, s32 id, | ||
878 | const core::vector3df& position, | ||
879 | const core::vector3df& rotation, | ||
880 | const core::vector3df& scale, | ||
881 | video::SColor vertexColor, | ||
882 | s32 maxLOD, E_TERRAIN_PATCH_SIZE patchSize, | ||
883 | s32 smoothFactor, | ||
884 | bool addAlsoIfHeightmapEmpty) | ||
885 | { | ||
886 | if (!parent) | ||
887 | parent = this; | ||
888 | |||
889 | if (!heightMapFile && !addAlsoIfHeightmapEmpty) | ||
890 | { | ||
891 | os::Printer::log("Could not load terrain, because file could not be opened.", ELL_ERROR); | ||
892 | return 0; | ||
893 | } | ||
894 | |||
895 | CTerrainSceneNode* node = new CTerrainSceneNode(parent, this, FileSystem, id, | ||
896 | maxLOD, patchSize, position, rotation, scale); | ||
897 | |||
898 | if (!node->loadHeightMap(heightMapFile, vertexColor, smoothFactor)) | ||
899 | { | ||
900 | if (!addAlsoIfHeightmapEmpty) | ||
901 | { | ||
902 | node->remove(); | ||
903 | node->drop(); | ||
904 | return 0; | ||
905 | } | ||
906 | } | ||
907 | |||
908 | node->drop(); | ||
909 | return node; | ||
910 | } | ||
911 | |||
912 | |||
913 | //! Adds an empty scene node. | ||
914 | ISceneNode* CSceneManager::addEmptySceneNode(ISceneNode* parent, s32 id) | ||
915 | { | ||
916 | if (!parent) | ||
917 | parent = this; | ||
918 | |||
919 | ISceneNode* node = new CEmptySceneNode(parent, this, id); | ||
920 | node->drop(); | ||
921 | |||
922 | return node; | ||
923 | } | ||
924 | |||
925 | |||
926 | //! Adds a dummy transformation scene node to the scene graph. | ||
927 | IDummyTransformationSceneNode* CSceneManager::addDummyTransformationSceneNode( | ||
928 | ISceneNode* parent, s32 id) | ||
929 | { | ||
930 | if (!parent) | ||
931 | parent = this; | ||
932 | |||
933 | IDummyTransformationSceneNode* node = new CDummyTransformationSceneNode( | ||
934 | parent, this, id); | ||
935 | node->drop(); | ||
936 | |||
937 | return node; | ||
938 | } | ||
939 | |||
940 | //! Adds a Hill Plane mesh to the mesh pool. The mesh is generated on the fly | ||
941 | //! and looks like a plane with some hills on it. You can specify how many hills | ||
942 | //! there should be on the plane and how high they should be. Also you must | ||
943 | //! specify a name for the mesh, because the mesh is added to the mesh pool, | ||
944 | //! and can be retrieved again using ISceneManager::getMesh with the name as | ||
945 | //! parameter. | ||
946 | IAnimatedMesh* CSceneManager::addHillPlaneMesh(const io::path& name, | ||
947 | const core::dimension2d<f32>& tileSize, | ||
948 | const core::dimension2d<u32>& tileCount, | ||
949 | video::SMaterial* material, f32 hillHeight, | ||
950 | const core::dimension2d<f32>& countHills, | ||
951 | const core::dimension2d<f32>& textureRepeatCount) | ||
952 | { | ||
953 | if (MeshCache->isMeshLoaded(name)) | ||
954 | return MeshCache->getMeshByName(name); | ||
955 | |||
956 | IMesh* mesh = GeometryCreator->createHillPlaneMesh(tileSize, | ||
957 | tileCount, material, hillHeight, countHills, | ||
958 | textureRepeatCount); | ||
959 | if (!mesh) | ||
960 | return 0; | ||
961 | |||
962 | SAnimatedMesh* animatedMesh = new SAnimatedMesh(); | ||
963 | if (!animatedMesh) | ||
964 | { | ||
965 | mesh->drop(); | ||
966 | return 0; | ||
967 | } | ||
968 | |||
969 | animatedMesh->addMesh(mesh); | ||
970 | mesh->drop(); | ||
971 | animatedMesh->recalculateBoundingBox(); | ||
972 | |||
973 | MeshCache->addMesh(name, animatedMesh); | ||
974 | animatedMesh->drop(); | ||
975 | |||
976 | return animatedMesh; | ||
977 | } | ||
978 | |||
979 | |||
980 | //! Adds a terrain mesh to the mesh pool. | ||
981 | IAnimatedMesh* CSceneManager::addTerrainMesh(const io::path& name, | ||
982 | video::IImage* texture, video::IImage* heightmap, | ||
983 | const core::dimension2d<f32>& stretchSize, | ||
984 | f32 maxHeight, | ||
985 | const core::dimension2d<u32>& defaultVertexBlockSize) | ||
986 | { | ||
987 | if (MeshCache->isMeshLoaded(name)) | ||
988 | return MeshCache->getMeshByName(name); | ||
989 | |||
990 | const bool debugBorders=false; | ||
991 | IMesh* mesh = GeometryCreator->createTerrainMesh(texture, heightmap, | ||
992 | stretchSize, maxHeight, Driver, | ||
993 | defaultVertexBlockSize, debugBorders); | ||
994 | if (!mesh) | ||
995 | return 0; | ||
996 | |||
997 | SAnimatedMesh* animatedMesh = new SAnimatedMesh(); | ||
998 | if (!animatedMesh) | ||
999 | { | ||
1000 | mesh->drop(); | ||
1001 | return 0; | ||
1002 | } | ||
1003 | |||
1004 | animatedMesh->addMesh(mesh); | ||
1005 | mesh->drop(); | ||
1006 | animatedMesh->recalculateBoundingBox(); | ||
1007 | |||
1008 | MeshCache->addMesh(name, animatedMesh); | ||
1009 | animatedMesh->drop(); | ||
1010 | |||
1011 | return animatedMesh; | ||
1012 | } | ||
1013 | |||
1014 | |||
1015 | //! Adds an arrow mesh to the mesh pool. | ||
1016 | IAnimatedMesh* CSceneManager::addArrowMesh(const io::path& name, | ||
1017 | video::SColor vtxColor0, video::SColor vtxColor1, | ||
1018 | u32 tesselationCylinder, u32 tesselationCone, f32 height, | ||
1019 | f32 cylinderHeight, f32 width0,f32 width1) | ||
1020 | { | ||
1021 | if (MeshCache->isMeshLoaded(name)) | ||
1022 | return MeshCache->getMeshByName(name); | ||
1023 | |||
1024 | IMesh* mesh = GeometryCreator->createArrowMesh( tesselationCylinder, | ||
1025 | tesselationCone, height, cylinderHeight, width0,width1, | ||
1026 | vtxColor0, vtxColor1); | ||
1027 | if (!mesh) | ||
1028 | return 0; | ||
1029 | |||
1030 | SAnimatedMesh* animatedMesh = new SAnimatedMesh(); | ||
1031 | if (!animatedMesh) | ||
1032 | { | ||
1033 | mesh->drop(); | ||
1034 | return 0; | ||
1035 | } | ||
1036 | |||
1037 | animatedMesh->addMesh(mesh); | ||
1038 | mesh->drop(); | ||
1039 | animatedMesh->recalculateBoundingBox(); | ||
1040 | |||
1041 | MeshCache->addMesh(name, animatedMesh); | ||
1042 | animatedMesh->drop(); | ||
1043 | |||
1044 | return animatedMesh; | ||
1045 | } | ||
1046 | |||
1047 | |||
1048 | //! Adds a static sphere mesh to the mesh pool. | ||
1049 | IAnimatedMesh* CSceneManager::addSphereMesh(const io::path& name, | ||
1050 | f32 radius, u32 polyCountX, u32 polyCountY) | ||
1051 | { | ||
1052 | if (MeshCache->isMeshLoaded(name)) | ||
1053 | return MeshCache->getMeshByName(name); | ||
1054 | |||
1055 | IMesh* mesh = GeometryCreator->createSphereMesh(radius, polyCountX, polyCountY); | ||
1056 | if (!mesh) | ||
1057 | return 0; | ||
1058 | |||
1059 | SAnimatedMesh* animatedMesh = new SAnimatedMesh(); | ||
1060 | if (!animatedMesh) | ||
1061 | { | ||
1062 | mesh->drop(); | ||
1063 | return 0; | ||
1064 | } | ||
1065 | |||
1066 | animatedMesh->addMesh(mesh); | ||
1067 | mesh->drop(); | ||
1068 | animatedMesh->recalculateBoundingBox(); | ||
1069 | |||
1070 | MeshCache->addMesh(name, animatedMesh); | ||
1071 | animatedMesh->drop(); | ||
1072 | |||
1073 | return animatedMesh; | ||
1074 | } | ||
1075 | |||
1076 | |||
1077 | |||
1078 | //! Adds a static volume light mesh to the mesh pool. | ||
1079 | IAnimatedMesh* CSceneManager::addVolumeLightMesh(const io::path& name, | ||
1080 | const u32 SubdivideU, const u32 SubdivideV, | ||
1081 | const video::SColor FootColor, const video::SColor TailColor) | ||
1082 | { | ||
1083 | if (MeshCache->isMeshLoaded(name)) | ||
1084 | return MeshCache->getMeshByName(name); | ||
1085 | |||
1086 | IMesh* mesh = GeometryCreator->createVolumeLightMesh(SubdivideU, SubdivideV, FootColor, TailColor); | ||
1087 | if (!mesh) | ||
1088 | return 0; | ||
1089 | |||
1090 | SAnimatedMesh* animatedMesh = new SAnimatedMesh(); | ||
1091 | if (!animatedMesh) | ||
1092 | { | ||
1093 | mesh->drop(); | ||
1094 | return 0; | ||
1095 | } | ||
1096 | |||
1097 | animatedMesh->addMesh(mesh); | ||
1098 | mesh->drop(); | ||
1099 | animatedMesh->recalculateBoundingBox(); | ||
1100 | |||
1101 | MeshCache->addMesh(name, animatedMesh); | ||
1102 | animatedMesh->drop(); | ||
1103 | |||
1104 | return animatedMesh; | ||
1105 | } | ||
1106 | |||
1107 | |||
1108 | //! Returns the root scene node. This is the scene node wich is parent | ||
1109 | //! of all scene nodes. The root scene node is a special scene node which | ||
1110 | //! only exists to manage all scene nodes. It is not rendered and cannot | ||
1111 | //! be removed from the scene. | ||
1112 | //! \return Returns a pointer to the root scene node. | ||
1113 | ISceneNode* CSceneManager::getRootSceneNode() | ||
1114 | { | ||
1115 | return this; | ||
1116 | } | ||
1117 | |||
1118 | |||
1119 | //! Returns the current active camera. | ||
1120 | //! \return The active camera is returned. Note that this can be NULL, if there | ||
1121 | //! was no camera created yet. | ||
1122 | ICameraSceneNode* CSceneManager::getActiveCamera() const | ||
1123 | { | ||
1124 | return ActiveCamera; | ||
1125 | } | ||
1126 | |||
1127 | |||
1128 | //! Sets the active camera. The previous active camera will be deactivated. | ||
1129 | //! \param camera: The new camera which should be active. | ||
1130 | void CSceneManager::setActiveCamera(ICameraSceneNode* camera) | ||
1131 | { | ||
1132 | if (camera) | ||
1133 | camera->grab(); | ||
1134 | if (ActiveCamera) | ||
1135 | ActiveCamera->drop(); | ||
1136 | |||
1137 | ActiveCamera = camera; | ||
1138 | } | ||
1139 | |||
1140 | |||
1141 | //! renders the node. | ||
1142 | void CSceneManager::render() | ||
1143 | { | ||
1144 | } | ||
1145 | |||
1146 | |||
1147 | //! returns the axis aligned bounding box of this node | ||
1148 | const core::aabbox3d<f32>& CSceneManager::getBoundingBox() const | ||
1149 | { | ||
1150 | _IRR_DEBUG_BREAK_IF(true) // Bounding Box of Scene Manager wanted. | ||
1151 | |||
1152 | // should never be used. | ||
1153 | return *((core::aabbox3d<f32>*)0); | ||
1154 | } | ||
1155 | |||
1156 | |||
1157 | //! returns if node is culled | ||
1158 | bool CSceneManager::isCulled(const ISceneNode* node) const | ||
1159 | { | ||
1160 | const ICameraSceneNode* cam = getActiveCamera(); | ||
1161 | if (!cam) | ||
1162 | { | ||
1163 | _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; | ||
1164 | return false; | ||
1165 | } | ||
1166 | bool result = false; | ||
1167 | |||
1168 | // has occlusion query information | ||
1169 | if (node->getAutomaticCulling() & scene::EAC_OCC_QUERY) | ||
1170 | { | ||
1171 | result = (Driver->getOcclusionQueryResult(const_cast<ISceneNode*>(node))==0); | ||
1172 | } | ||
1173 | |||
1174 | // can be seen by a bounding box ? | ||
1175 | if (!result && (node->getAutomaticCulling() & scene::EAC_BOX)) | ||
1176 | { | ||
1177 | core::aabbox3d<f32> tbox = node->getBoundingBox(); | ||
1178 | node->getAbsoluteTransformation().transformBoxEx(tbox); | ||
1179 | result = !(tbox.intersectsWithBox(cam->getViewFrustum()->getBoundingBox() )); | ||
1180 | } | ||
1181 | |||
1182 | // can be seen by a bounding sphere | ||
1183 | if (!result && (node->getAutomaticCulling() & scene::EAC_FRUSTUM_SPHERE)) | ||
1184 | { // requires bbox diameter | ||
1185 | } | ||
1186 | |||
1187 | // can be seen by cam pyramid planes ? | ||
1188 | if (!result && (node->getAutomaticCulling() & scene::EAC_FRUSTUM_BOX)) | ||
1189 | { | ||
1190 | SViewFrustum frust = *cam->getViewFrustum(); | ||
1191 | |||
1192 | //transform the frustum to the node's current absolute transformation | ||
1193 | core::matrix4 invTrans(node->getAbsoluteTransformation(), core::matrix4::EM4CONST_INVERSE); | ||
1194 | //invTrans.makeInverse(); | ||
1195 | frust.transform(invTrans); | ||
1196 | |||
1197 | core::vector3df edges[8]; | ||
1198 | node->getBoundingBox().getEdges(edges); | ||
1199 | |||
1200 | for (s32 i=0; i<scene::SViewFrustum::VF_PLANE_COUNT; ++i) | ||
1201 | { | ||
1202 | bool boxInFrustum=false; | ||
1203 | for (u32 j=0; j<8; ++j) | ||
1204 | { | ||
1205 | if (frust.planes[i].classifyPointRelation(edges[j]) != core::ISREL3D_FRONT) | ||
1206 | { | ||
1207 | boxInFrustum=true; | ||
1208 | break; | ||
1209 | } | ||
1210 | } | ||
1211 | |||
1212 | if (!boxInFrustum) | ||
1213 | { | ||
1214 | result = true; | ||
1215 | break; | ||
1216 | } | ||
1217 | } | ||
1218 | } | ||
1219 | |||
1220 | _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; | ||
1221 | return result; | ||
1222 | } | ||
1223 | |||
1224 | |||
1225 | //! registers a node for rendering it at a specific time. | ||
1226 | u32 CSceneManager::registerNodeForRendering(ISceneNode* node, E_SCENE_NODE_RENDER_PASS pass) | ||
1227 | { | ||
1228 | u32 taken = 0; | ||
1229 | |||
1230 | switch(pass) | ||
1231 | { | ||
1232 | // take camera if it is not already registered | ||
1233 | case ESNRP_CAMERA: | ||
1234 | { | ||
1235 | taken = 1; | ||
1236 | for (u32 i = 0; i != CameraList.size(); ++i) | ||
1237 | { | ||
1238 | if (CameraList[i] == node) | ||
1239 | { | ||
1240 | taken = 0; | ||
1241 | break; | ||
1242 | } | ||
1243 | } | ||
1244 | if (taken) | ||
1245 | { | ||
1246 | CameraList.push_back(node); | ||
1247 | } | ||
1248 | } | ||
1249 | break; | ||
1250 | |||
1251 | case ESNRP_LIGHT: | ||
1252 | // TODO: Point Light culling.. | ||
1253 | // Lighting model in irrlicht has to be redone.. | ||
1254 | //if (!isCulled(node)) | ||
1255 | { | ||
1256 | LightList.push_back(node); | ||
1257 | taken = 1; | ||
1258 | } | ||
1259 | break; | ||
1260 | |||
1261 | case ESNRP_SKY_BOX: | ||
1262 | SkyBoxList.push_back(node); | ||
1263 | taken = 1; | ||
1264 | break; | ||
1265 | case ESNRP_SOLID: | ||
1266 | if (!isCulled(node)) | ||
1267 | { | ||
1268 | SolidNodeList.push_back(node); | ||
1269 | taken = 1; | ||
1270 | } | ||
1271 | break; | ||
1272 | case ESNRP_TRANSPARENT: | ||
1273 | if (!isCulled(node)) | ||
1274 | { | ||
1275 | TransparentNodeList.push_back(TransparentNodeEntry(node, camWorldPos)); | ||
1276 | taken = 1; | ||
1277 | } | ||
1278 | break; | ||
1279 | case ESNRP_TRANSPARENT_EFFECT: | ||
1280 | if (!isCulled(node)) | ||
1281 | { | ||
1282 | TransparentEffectNodeList.push_back(TransparentNodeEntry(node, camWorldPos)); | ||
1283 | taken = 1; | ||
1284 | } | ||
1285 | break; | ||
1286 | case ESNRP_AUTOMATIC: | ||
1287 | if (!isCulled(node)) | ||
1288 | { | ||
1289 | const u32 count = node->getMaterialCount(); | ||
1290 | |||
1291 | taken = 0; | ||
1292 | for (u32 i=0; i<count; ++i) | ||
1293 | { | ||
1294 | video::IMaterialRenderer* rnd = | ||
1295 | Driver->getMaterialRenderer(node->getMaterial(i).MaterialType); | ||
1296 | if (rnd && rnd->isTransparent()) | ||
1297 | { | ||
1298 | // register as transparent node | ||
1299 | TransparentNodeEntry e(node, camWorldPos); | ||
1300 | TransparentNodeList.push_back(e); | ||
1301 | taken = 1; | ||
1302 | break; | ||
1303 | } | ||
1304 | } | ||
1305 | |||
1306 | // not transparent, register as solid | ||
1307 | if (!taken) | ||
1308 | { | ||
1309 | SolidNodeList.push_back(node); | ||
1310 | taken = 1; | ||
1311 | } | ||
1312 | } | ||
1313 | break; | ||
1314 | case ESNRP_SHADOW: | ||
1315 | if (!isCulled(node)) | ||
1316 | { | ||
1317 | ShadowNodeList.push_back(node); | ||
1318 | taken = 1; | ||
1319 | } | ||
1320 | break; | ||
1321 | |||
1322 | case ESNRP_NONE: // ignore this one | ||
1323 | break; | ||
1324 | } | ||
1325 | |||
1326 | #ifdef _IRR_SCENEMANAGER_DEBUG | ||
1327 | s32 index = Parameters.findAttribute ( "calls" ); | ||
1328 | Parameters.setAttribute ( index, Parameters.getAttributeAsInt ( index ) + 1 ); | ||
1329 | |||
1330 | if (!taken) | ||
1331 | { | ||
1332 | index = Parameters.findAttribute ( "culled" ); | ||
1333 | Parameters.setAttribute ( index, Parameters.getAttributeAsInt ( index ) + 1 ); | ||
1334 | } | ||
1335 | #endif | ||
1336 | |||
1337 | return taken; | ||
1338 | } | ||
1339 | |||
1340 | |||
1341 | //! This method is called just before the rendering process of the whole scene. | ||
1342 | //! draws all scene nodes | ||
1343 | void CSceneManager::drawAll() | ||
1344 | { | ||
1345 | if (!Driver) | ||
1346 | return; | ||
1347 | |||
1348 | #ifdef _IRR_SCENEMANAGER_DEBUG | ||
1349 | // reset attributes | ||
1350 | Parameters.setAttribute ( "culled", 0 ); | ||
1351 | Parameters.setAttribute ( "calls", 0 ); | ||
1352 | Parameters.setAttribute ( "drawn_solid", 0 ); | ||
1353 | Parameters.setAttribute ( "drawn_transparent", 0 ); | ||
1354 | Parameters.setAttribute ( "drawn_transparent_effect", 0 ); | ||
1355 | #endif | ||
1356 | |||
1357 | u32 i; // new ISO for scoping problem in some compilers | ||
1358 | |||
1359 | // reset all transforms | ||
1360 | Driver->setMaterial(video::SMaterial()); | ||
1361 | Driver->setTransform ( video::ETS_PROJECTION, core::IdentityMatrix ); | ||
1362 | Driver->setTransform ( video::ETS_VIEW, core::IdentityMatrix ); | ||
1363 | Driver->setTransform ( video::ETS_WORLD, core::IdentityMatrix ); | ||
1364 | for (i=video::ETS_COUNT-1; i>=video::ETS_TEXTURE_0; --i) | ||
1365 | Driver->setTransform ( (video::E_TRANSFORMATION_STATE)i, core::IdentityMatrix ); | ||
1366 | |||
1367 | // TODO: This should not use an attribute here but a real parameter when necessary (too slow!) | ||
1368 | Driver->setAllowZWriteOnTransparent(Parameters.getAttributeAsBool( ALLOW_ZWRITE_ON_TRANSPARENT) ); | ||
1369 | |||
1370 | // do animations and other stuff. | ||
1371 | OnAnimate(os::Timer::getTime()); | ||
1372 | |||
1373 | /*! | ||
1374 | First Scene Node for prerendering should be the active camera | ||
1375 | consistent Camera is needed for culling | ||
1376 | */ | ||
1377 | camWorldPos.set(0,0,0); | ||
1378 | if (ActiveCamera) | ||
1379 | { | ||
1380 | ActiveCamera->render(); | ||
1381 | camWorldPos = ActiveCamera->getAbsolutePosition(); | ||
1382 | } | ||
1383 | |||
1384 | // let all nodes register themselves | ||
1385 | OnRegisterSceneNode(); | ||
1386 | |||
1387 | if (LightManager) | ||
1388 | LightManager->OnPreRender(LightList); | ||
1389 | |||
1390 | //render camera scenes | ||
1391 | { | ||
1392 | CurrentRendertime = ESNRP_CAMERA; | ||
1393 | Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRendertime) != 0); | ||
1394 | |||
1395 | if (LightManager) | ||
1396 | LightManager->OnRenderPassPreRender(CurrentRendertime); | ||
1397 | |||
1398 | for (i=0; i<CameraList.size(); ++i) | ||
1399 | CameraList[i]->render(); | ||
1400 | |||
1401 | CameraList.set_used(0); | ||
1402 | |||
1403 | if (LightManager) | ||
1404 | LightManager->OnRenderPassPostRender(CurrentRendertime); | ||
1405 | } | ||
1406 | |||
1407 | //render lights scenes | ||
1408 | { | ||
1409 | CurrentRendertime = ESNRP_LIGHT; | ||
1410 | Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRendertime) != 0); | ||
1411 | |||
1412 | if (LightManager) | ||
1413 | { | ||
1414 | LightManager->OnRenderPassPreRender(CurrentRendertime); | ||
1415 | } | ||
1416 | else | ||
1417 | { | ||
1418 | // Sort the lights by distance from the camera | ||
1419 | core::vector3df camWorldPos(0, 0, 0); | ||
1420 | if (ActiveCamera) | ||
1421 | camWorldPos = ActiveCamera->getAbsolutePosition(); | ||
1422 | |||
1423 | core::array<DistanceNodeEntry> SortedLights; | ||
1424 | SortedLights.set_used(LightList.size()); | ||
1425 | for (s32 light = (s32)LightList.size() - 1; light >= 0; --light) | ||
1426 | SortedLights[light].setNodeAndDistanceFromPosition(LightList[light], camWorldPos); | ||
1427 | |||
1428 | SortedLights.set_sorted(false); | ||
1429 | SortedLights.sort(); | ||
1430 | |||
1431 | for(s32 light = (s32)LightList.size() - 1; light >= 0; --light) | ||
1432 | LightList[light] = SortedLights[light].Node; | ||
1433 | } | ||
1434 | |||
1435 | Driver->deleteAllDynamicLights(); | ||
1436 | |||
1437 | Driver->setAmbientLight(AmbientLight); | ||
1438 | |||
1439 | u32 maxLights = LightList.size(); | ||
1440 | |||
1441 | if (!LightManager) | ||
1442 | maxLights = core::min_ ( Driver->getMaximalDynamicLightAmount(), maxLights); | ||
1443 | |||
1444 | for (i=0; i< maxLights; ++i) | ||
1445 | LightList[i]->render(); | ||
1446 | |||
1447 | if (LightManager) | ||
1448 | LightManager->OnRenderPassPostRender(CurrentRendertime); | ||
1449 | } | ||
1450 | |||
1451 | // render skyboxes | ||
1452 | { | ||
1453 | CurrentRendertime = ESNRP_SKY_BOX; | ||
1454 | Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRendertime) != 0); | ||
1455 | |||
1456 | if (LightManager) | ||
1457 | { | ||
1458 | LightManager->OnRenderPassPreRender(CurrentRendertime); | ||
1459 | for (i=0; i<SkyBoxList.size(); ++i) | ||
1460 | { | ||
1461 | ISceneNode* node = SkyBoxList[i]; | ||
1462 | LightManager->OnNodePreRender(node); | ||
1463 | node->render(); | ||
1464 | LightManager->OnNodePostRender(node); | ||
1465 | } | ||
1466 | } | ||
1467 | else | ||
1468 | { | ||
1469 | for (i=0; i<SkyBoxList.size(); ++i) | ||
1470 | SkyBoxList[i]->render(); | ||
1471 | } | ||
1472 | |||
1473 | SkyBoxList.set_used(0); | ||
1474 | |||
1475 | if (LightManager) | ||
1476 | LightManager->OnRenderPassPostRender(CurrentRendertime); | ||
1477 | } | ||
1478 | |||
1479 | |||
1480 | // render default objects | ||
1481 | { | ||
1482 | CurrentRendertime = ESNRP_SOLID; | ||
1483 | Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRendertime) != 0); | ||
1484 | |||
1485 | SolidNodeList.sort(); // sort by textures | ||
1486 | |||
1487 | if (LightManager) | ||
1488 | { | ||
1489 | LightManager->OnRenderPassPreRender(CurrentRendertime); | ||
1490 | for (i=0; i<SolidNodeList.size(); ++i) | ||
1491 | { | ||
1492 | ISceneNode* node = SolidNodeList[i].Node; | ||
1493 | LightManager->OnNodePreRender(node); | ||
1494 | node->render(); | ||
1495 | LightManager->OnNodePostRender(node); | ||
1496 | } | ||
1497 | } | ||
1498 | else | ||
1499 | { | ||
1500 | for (i=0; i<SolidNodeList.size(); ++i) | ||
1501 | SolidNodeList[i].Node->render(); | ||
1502 | } | ||
1503 | |||
1504 | #ifdef _IRR_SCENEMANAGER_DEBUG | ||
1505 | Parameters.setAttribute("drawn_solid", (s32) SolidNodeList.size() ); | ||
1506 | #endif | ||
1507 | SolidNodeList.set_used(0); | ||
1508 | |||
1509 | if (LightManager) | ||
1510 | LightManager->OnRenderPassPostRender(CurrentRendertime); | ||
1511 | } | ||
1512 | |||
1513 | // render shadows | ||
1514 | { | ||
1515 | CurrentRendertime = ESNRP_SHADOW; | ||
1516 | Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRendertime) != 0); | ||
1517 | |||
1518 | if (LightManager) | ||
1519 | { | ||
1520 | LightManager->OnRenderPassPreRender(CurrentRendertime); | ||
1521 | for (i=0; i<ShadowNodeList.size(); ++i) | ||
1522 | { | ||
1523 | ISceneNode* node = ShadowNodeList[i]; | ||
1524 | LightManager->OnNodePreRender(node); | ||
1525 | node->render(); | ||
1526 | LightManager->OnNodePostRender(node); | ||
1527 | } | ||
1528 | } | ||
1529 | else | ||
1530 | { | ||
1531 | for (i=0; i<ShadowNodeList.size(); ++i) | ||
1532 | ShadowNodeList[i]->render(); | ||
1533 | } | ||
1534 | |||
1535 | if (!ShadowNodeList.empty()) | ||
1536 | Driver->drawStencilShadow(true,ShadowColor, ShadowColor, | ||
1537 | ShadowColor, ShadowColor); | ||
1538 | |||
1539 | ShadowNodeList.set_used(0); | ||
1540 | |||
1541 | if (LightManager) | ||
1542 | LightManager->OnRenderPassPostRender(CurrentRendertime); | ||
1543 | } | ||
1544 | |||
1545 | // render transparent objects. | ||
1546 | { | ||
1547 | CurrentRendertime = ESNRP_TRANSPARENT; | ||
1548 | Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRendertime) != 0); | ||
1549 | |||
1550 | TransparentNodeList.sort(); // sort by distance from camera | ||
1551 | if (LightManager) | ||
1552 | { | ||
1553 | LightManager->OnRenderPassPreRender(CurrentRendertime); | ||
1554 | |||
1555 | for (i=0; i<TransparentNodeList.size(); ++i) | ||
1556 | { | ||
1557 | ISceneNode* node = TransparentNodeList[i].Node; | ||
1558 | LightManager->OnNodePreRender(node); | ||
1559 | node->render(); | ||
1560 | LightManager->OnNodePostRender(node); | ||
1561 | } | ||
1562 | } | ||
1563 | else | ||
1564 | { | ||
1565 | for (i=0; i<TransparentNodeList.size(); ++i) | ||
1566 | TransparentNodeList[i].Node->render(); | ||
1567 | } | ||
1568 | |||
1569 | #ifdef _IRR_SCENEMANAGER_DEBUG | ||
1570 | Parameters.setAttribute ( "drawn_transparent", (s32) TransparentNodeList.size() ); | ||
1571 | #endif | ||
1572 | TransparentNodeList.set_used(0); | ||
1573 | |||
1574 | if (LightManager) | ||
1575 | LightManager->OnRenderPassPostRender(CurrentRendertime); | ||
1576 | } | ||
1577 | |||
1578 | // render transparent effect objects. | ||
1579 | { | ||
1580 | CurrentRendertime = ESNRP_TRANSPARENT_EFFECT; | ||
1581 | Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRendertime) != 0); | ||
1582 | |||
1583 | TransparentEffectNodeList.sort(); // sort by distance from camera | ||
1584 | |||
1585 | if (LightManager) | ||
1586 | { | ||
1587 | LightManager->OnRenderPassPreRender(CurrentRendertime); | ||
1588 | |||
1589 | for (i=0; i<TransparentEffectNodeList.size(); ++i) | ||
1590 | { | ||
1591 | ISceneNode* node = TransparentEffectNodeList[i].Node; | ||
1592 | LightManager->OnNodePreRender(node); | ||
1593 | node->render(); | ||
1594 | LightManager->OnNodePostRender(node); | ||
1595 | } | ||
1596 | } | ||
1597 | else | ||
1598 | { | ||
1599 | for (i=0; i<TransparentEffectNodeList.size(); ++i) | ||
1600 | TransparentEffectNodeList[i].Node->render(); | ||
1601 | } | ||
1602 | #ifdef _IRR_SCENEMANAGER_DEBUG | ||
1603 | Parameters.setAttribute ( "drawn_transparent_effect", (s32) TransparentEffectNodeList.size() ); | ||
1604 | #endif | ||
1605 | TransparentEffectNodeList.set_used(0); | ||
1606 | } | ||
1607 | |||
1608 | if (LightManager) | ||
1609 | LightManager->OnPostRender(); | ||
1610 | |||
1611 | LightList.set_used(0); | ||
1612 | clearDeletionList(); | ||
1613 | |||
1614 | CurrentRendertime = ESNRP_NONE; | ||
1615 | } | ||
1616 | |||
1617 | void CSceneManager::setLightManager(ILightManager* lightManager) | ||
1618 | { | ||
1619 | if (lightManager) | ||
1620 | lightManager->grab(); | ||
1621 | if (LightManager) | ||
1622 | LightManager->drop(); | ||
1623 | |||
1624 | LightManager = lightManager; | ||
1625 | } | ||
1626 | |||
1627 | |||
1628 | //! Sets the color of stencil buffers shadows drawn by the scene manager. | ||
1629 | void CSceneManager::setShadowColor(video::SColor color) | ||
1630 | { | ||
1631 | ShadowColor = color; | ||
1632 | } | ||
1633 | |||
1634 | |||
1635 | //! Returns the current color of shadows. | ||
1636 | video::SColor CSceneManager::getShadowColor() const | ||
1637 | { | ||
1638 | return ShadowColor; | ||
1639 | } | ||
1640 | |||
1641 | |||
1642 | //! creates a rotation animator, which rotates the attached scene node around itself. | ||
1643 | ISceneNodeAnimator* CSceneManager::createRotationAnimator(const core::vector3df& rotationPerSecond) | ||
1644 | { | ||
1645 | ISceneNodeAnimator* anim = new CSceneNodeAnimatorRotation(os::Timer::getTime(), | ||
1646 | rotationPerSecond); | ||
1647 | |||
1648 | return anim; | ||
1649 | } | ||
1650 | |||
1651 | |||
1652 | //! creates a fly circle animator, which lets the attached scene node fly around a center. | ||
1653 | ISceneNodeAnimator* CSceneManager::createFlyCircleAnimator( | ||
1654 | const core::vector3df& center, f32 radius, f32 speed, | ||
1655 | const core::vector3df& direction, | ||
1656 | f32 startPosition, | ||
1657 | f32 radiusEllipsoid) | ||
1658 | { | ||
1659 | const f32 orbitDurationMs = (core::DEGTORAD * 360.f) / speed; | ||
1660 | const u32 effectiveTime = os::Timer::getTime() + (u32)(orbitDurationMs * startPosition); | ||
1661 | |||
1662 | ISceneNodeAnimator* anim = new CSceneNodeAnimatorFlyCircle( | ||
1663 | effectiveTime, center, | ||
1664 | radius, speed, direction,radiusEllipsoid); | ||
1665 | return anim; | ||
1666 | } | ||
1667 | |||
1668 | |||
1669 | //! Creates a fly straight animator, which lets the attached scene node | ||
1670 | //! fly or move along a line between two points. | ||
1671 | ISceneNodeAnimator* CSceneManager::createFlyStraightAnimator(const core::vector3df& startPoint, | ||
1672 | const core::vector3df& endPoint, u32 timeForWay, bool loop,bool pingpong) | ||
1673 | { | ||
1674 | ISceneNodeAnimator* anim = new CSceneNodeAnimatorFlyStraight(startPoint, | ||
1675 | endPoint, timeForWay, loop, os::Timer::getTime(), pingpong); | ||
1676 | |||
1677 | return anim; | ||
1678 | } | ||
1679 | |||
1680 | |||
1681 | //! Creates a texture animator, which switches the textures of the target scene | ||
1682 | //! node based on a list of textures. | ||
1683 | ISceneNodeAnimator* CSceneManager::createTextureAnimator(const core::array<video::ITexture*>& textures, | ||
1684 | s32 timePerFrame, bool loop) | ||
1685 | { | ||
1686 | ISceneNodeAnimator* anim = new CSceneNodeAnimatorTexture(textures, | ||
1687 | timePerFrame, loop, os::Timer::getTime()); | ||
1688 | |||
1689 | return anim; | ||
1690 | } | ||
1691 | |||
1692 | |||
1693 | //! Creates a scene node animator, which deletes the scene node after | ||
1694 | //! some time automaticly. | ||
1695 | ISceneNodeAnimator* CSceneManager::createDeleteAnimator(u32 when) | ||
1696 | { | ||
1697 | return new CSceneNodeAnimatorDelete(this, os::Timer::getTime() + when); | ||
1698 | } | ||
1699 | |||
1700 | |||
1701 | //! Creates a special scene node animator for doing automatic collision detection | ||
1702 | //! and response. | ||
1703 | ISceneNodeAnimatorCollisionResponse* CSceneManager::createCollisionResponseAnimator( | ||
1704 | ITriangleSelector* world, ISceneNode* sceneNode, const core::vector3df& ellipsoidRadius, | ||
1705 | const core::vector3df& gravityPerSecond, | ||
1706 | const core::vector3df& ellipsoidTranslation, f32 slidingValue) | ||
1707 | { | ||
1708 | ISceneNodeAnimatorCollisionResponse* anim = new | ||
1709 | CSceneNodeAnimatorCollisionResponse(this, world, sceneNode, | ||
1710 | ellipsoidRadius, gravityPerSecond, | ||
1711 | ellipsoidTranslation, slidingValue); | ||
1712 | |||
1713 | return anim; | ||
1714 | } | ||
1715 | |||
1716 | |||
1717 | //! Creates a follow spline animator. | ||
1718 | ISceneNodeAnimator* CSceneManager::createFollowSplineAnimator(s32 startTime, | ||
1719 | const core::array< core::vector3df >& points, | ||
1720 | f32 speed, f32 tightness, bool loop, bool pingpong) | ||
1721 | { | ||
1722 | ISceneNodeAnimator* a = new CSceneNodeAnimatorFollowSpline(startTime, points, | ||
1723 | speed, tightness, loop, pingpong); | ||
1724 | return a; | ||
1725 | } | ||
1726 | |||
1727 | |||
1728 | //! Adds an external mesh loader. | ||
1729 | void CSceneManager::addExternalMeshLoader(IMeshLoader* externalLoader) | ||
1730 | { | ||
1731 | if (!externalLoader) | ||
1732 | return; | ||
1733 | |||
1734 | externalLoader->grab(); | ||
1735 | MeshLoaderList.push_back(externalLoader); | ||
1736 | } | ||
1737 | |||
1738 | |||
1739 | //! Returns the number of mesh loaders supported by Irrlicht at this time | ||
1740 | u32 CSceneManager::getMeshLoaderCount() const | ||
1741 | { | ||
1742 | return MeshLoaderList.size(); | ||
1743 | } | ||
1744 | |||
1745 | |||
1746 | //! Retrieve the given mesh loader | ||
1747 | IMeshLoader* CSceneManager::getMeshLoader(u32 index) const | ||
1748 | { | ||
1749 | if (index < MeshLoaderList.size()) | ||
1750 | return MeshLoaderList[index]; | ||
1751 | else | ||
1752 | return 0; | ||
1753 | } | ||
1754 | |||
1755 | |||
1756 | //! Adds an external scene loader. | ||
1757 | void CSceneManager::addExternalSceneLoader(ISceneLoader* externalLoader) | ||
1758 | { | ||
1759 | if (!externalLoader) | ||
1760 | return; | ||
1761 | |||
1762 | externalLoader->grab(); | ||
1763 | SceneLoaderList.push_back(externalLoader); | ||
1764 | } | ||
1765 | |||
1766 | |||
1767 | //! Returns the number of scene loaders | ||
1768 | u32 CSceneManager::getSceneLoaderCount() const | ||
1769 | { | ||
1770 | return SceneLoaderList.size(); | ||
1771 | } | ||
1772 | |||
1773 | |||
1774 | //! Retrieve the given scene loader | ||
1775 | ISceneLoader* CSceneManager::getSceneLoader(u32 index) const | ||
1776 | { | ||
1777 | if (index < SceneLoaderList.size()) | ||
1778 | return SceneLoaderList[index]; | ||
1779 | else | ||
1780 | return 0; | ||
1781 | } | ||
1782 | |||
1783 | |||
1784 | //! Returns a pointer to the scene collision manager. | ||
1785 | ISceneCollisionManager* CSceneManager::getSceneCollisionManager() | ||
1786 | { | ||
1787 | return CollisionManager; | ||
1788 | } | ||
1789 | |||
1790 | |||
1791 | //! Returns a pointer to the mesh manipulator. | ||
1792 | IMeshManipulator* CSceneManager::getMeshManipulator() | ||
1793 | { | ||
1794 | return Driver->getMeshManipulator(); | ||
1795 | } | ||
1796 | |||
1797 | |||
1798 | //! Creates a simple ITriangleSelector, based on a mesh. | ||
1799 | ITriangleSelector* CSceneManager::createTriangleSelector(IMesh* mesh, ISceneNode* node) | ||
1800 | { | ||
1801 | if (!mesh) | ||
1802 | return 0; | ||
1803 | |||
1804 | return new CTriangleSelector(mesh, node); | ||
1805 | } | ||
1806 | |||
1807 | |||
1808 | //! Creates a simple and updatable ITriangleSelector, based on a the mesh owned by an | ||
1809 | //! animated scene node | ||
1810 | ITriangleSelector* CSceneManager::createTriangleSelector(IAnimatedMeshSceneNode* node) | ||
1811 | { | ||
1812 | if (!node || !node->getMesh()) | ||
1813 | return 0; | ||
1814 | |||
1815 | return new CTriangleSelector(node); | ||
1816 | } | ||
1817 | |||
1818 | |||
1819 | //! Creates a simple dynamic ITriangleSelector, based on a axis aligned bounding box. | ||
1820 | ITriangleSelector* CSceneManager::createTriangleSelectorFromBoundingBox(ISceneNode* node) | ||
1821 | { | ||
1822 | if (!node) | ||
1823 | return 0; | ||
1824 | |||
1825 | return new CTriangleBBSelector(node); | ||
1826 | } | ||
1827 | |||
1828 | |||
1829 | //! Creates a simple ITriangleSelector, based on a mesh. | ||
1830 | ITriangleSelector* CSceneManager::createOctreeTriangleSelector(IMesh* mesh, | ||
1831 | ISceneNode* node, s32 minimalPolysPerNode) | ||
1832 | { | ||
1833 | if (!mesh) | ||
1834 | return 0; | ||
1835 | |||
1836 | return new COctreeTriangleSelector(mesh, node, minimalPolysPerNode); | ||
1837 | } | ||
1838 | |||
1839 | |||
1840 | //! Creates a meta triangle selector. | ||
1841 | IMetaTriangleSelector* CSceneManager::createMetaTriangleSelector() | ||
1842 | { | ||
1843 | return new CMetaTriangleSelector(); | ||
1844 | } | ||
1845 | |||
1846 | |||
1847 | //! Creates a triangle selector which can select triangles from a terrain scene node | ||
1848 | ITriangleSelector* CSceneManager::createTerrainTriangleSelector( | ||
1849 | ITerrainSceneNode* node, s32 LOD) | ||
1850 | { | ||
1851 | return new CTerrainTriangleSelector(node, LOD); | ||
1852 | } | ||
1853 | |||
1854 | |||
1855 | |||
1856 | //! Adds a scene node to the deletion queue. | ||
1857 | void CSceneManager::addToDeletionQueue(ISceneNode* node) | ||
1858 | { | ||
1859 | if (!node) | ||
1860 | return; | ||
1861 | |||
1862 | node->grab(); | ||
1863 | DeletionList.push_back(node); | ||
1864 | } | ||
1865 | |||
1866 | |||
1867 | //! clears the deletion list | ||
1868 | void CSceneManager::clearDeletionList() | ||
1869 | { | ||
1870 | if (DeletionList.empty()) | ||
1871 | return; | ||
1872 | |||
1873 | for (u32 i=0; i<DeletionList.size(); ++i) | ||
1874 | { | ||
1875 | DeletionList[i]->remove(); | ||
1876 | DeletionList[i]->drop(); | ||
1877 | } | ||
1878 | |||
1879 | DeletionList.clear(); | ||
1880 | } | ||
1881 | |||
1882 | |||
1883 | //! Returns the first scene node with the specified name. | ||
1884 | ISceneNode* CSceneManager::getSceneNodeFromName(const char* name, ISceneNode* start) | ||
1885 | { | ||
1886 | if (start == 0) | ||
1887 | start = getRootSceneNode(); | ||
1888 | |||
1889 | if (!strcmp(start->getName(),name)) | ||
1890 | return start; | ||
1891 | |||
1892 | ISceneNode* node = 0; | ||
1893 | |||
1894 | const ISceneNodeList& list = start->getChildren(); | ||
1895 | ISceneNodeList::ConstIterator it = list.begin(); | ||
1896 | for (; it!=list.end(); ++it) | ||
1897 | { | ||
1898 | node = getSceneNodeFromName(name, *it); | ||
1899 | if (node) | ||
1900 | return node; | ||
1901 | } | ||
1902 | |||
1903 | return 0; | ||
1904 | } | ||
1905 | |||
1906 | |||
1907 | //! Returns the first scene node with the specified id. | ||
1908 | ISceneNode* CSceneManager::getSceneNodeFromId(s32 id, ISceneNode* start) | ||
1909 | { | ||
1910 | if (start == 0) | ||
1911 | start = getRootSceneNode(); | ||
1912 | |||
1913 | if (start->getID() == id) | ||
1914 | return start; | ||
1915 | |||
1916 | ISceneNode* node = 0; | ||
1917 | |||
1918 | const ISceneNodeList& list = start->getChildren(); | ||
1919 | ISceneNodeList::ConstIterator it = list.begin(); | ||
1920 | for (; it!=list.end(); ++it) | ||
1921 | { | ||
1922 | node = getSceneNodeFromId(id, *it); | ||
1923 | if (node) | ||
1924 | return node; | ||
1925 | } | ||
1926 | |||
1927 | return 0; | ||
1928 | } | ||
1929 | |||
1930 | |||
1931 | //! Returns the first scene node with the specified type. | ||
1932 | ISceneNode* CSceneManager::getSceneNodeFromType(scene::ESCENE_NODE_TYPE type, ISceneNode* start) | ||
1933 | { | ||
1934 | if (start == 0) | ||
1935 | start = getRootSceneNode(); | ||
1936 | |||
1937 | if (start->getType() == type || ESNT_ANY == type) | ||
1938 | return start; | ||
1939 | |||
1940 | ISceneNode* node = 0; | ||
1941 | |||
1942 | const ISceneNodeList& list = start->getChildren(); | ||
1943 | ISceneNodeList::ConstIterator it = list.begin(); | ||
1944 | for (; it!=list.end(); ++it) | ||
1945 | { | ||
1946 | node = getSceneNodeFromType(type, *it); | ||
1947 | if (node) | ||
1948 | return node; | ||
1949 | } | ||
1950 | |||
1951 | return 0; | ||
1952 | } | ||
1953 | |||
1954 | |||
1955 | //! returns scene nodes by type. | ||
1956 | void CSceneManager::getSceneNodesFromType(ESCENE_NODE_TYPE type, core::array<scene::ISceneNode*>& outNodes, ISceneNode* start) | ||
1957 | { | ||
1958 | if (start == 0) | ||
1959 | start = getRootSceneNode(); | ||
1960 | |||
1961 | if (start->getType() == type || ESNT_ANY == type) | ||
1962 | outNodes.push_back(start); | ||
1963 | |||
1964 | const ISceneNodeList& list = start->getChildren(); | ||
1965 | ISceneNodeList::ConstIterator it = list.begin(); | ||
1966 | |||
1967 | for (; it!=list.end(); ++it) | ||
1968 | { | ||
1969 | getSceneNodesFromType(type, outNodes, *it); | ||
1970 | } | ||
1971 | } | ||
1972 | |||
1973 | |||
1974 | //! Posts an input event to the environment. Usually you do not have to | ||
1975 | //! use this method, it is used by the internal engine. | ||
1976 | bool CSceneManager::postEventFromUser(const SEvent& event) | ||
1977 | { | ||
1978 | bool ret = false; | ||
1979 | ICameraSceneNode* cam = getActiveCamera(); | ||
1980 | if (cam) | ||
1981 | ret = cam->OnEvent(event); | ||
1982 | |||
1983 | _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; | ||
1984 | return ret; | ||
1985 | } | ||
1986 | |||
1987 | |||
1988 | //! Removes all children of this scene node | ||
1989 | void CSceneManager::removeAll() | ||
1990 | { | ||
1991 | ISceneNode::removeAll(); | ||
1992 | setActiveCamera(0); | ||
1993 | // Make sure the driver is reset, might need a more complex method at some point | ||
1994 | if (Driver) | ||
1995 | Driver->setMaterial(video::SMaterial()); | ||
1996 | } | ||
1997 | |||
1998 | |||
1999 | //! Clears the whole scene. All scene nodes are removed. | ||
2000 | void CSceneManager::clear() | ||
2001 | { | ||
2002 | removeAll(); | ||
2003 | } | ||
2004 | |||
2005 | |||
2006 | //! Returns interface to the parameters set in this scene. | ||
2007 | io::IAttributes* CSceneManager::getParameters() | ||
2008 | { | ||
2009 | return &Parameters; | ||
2010 | } | ||
2011 | |||
2012 | |||
2013 | //! Returns current render pass. | ||
2014 | E_SCENE_NODE_RENDER_PASS CSceneManager::getSceneNodeRenderPass() const | ||
2015 | { | ||
2016 | return CurrentRendertime; | ||
2017 | } | ||
2018 | |||
2019 | |||
2020 | //! Returns an interface to the mesh cache which is shared beween all existing scene managers. | ||
2021 | IMeshCache* CSceneManager::getMeshCache() | ||
2022 | { | ||
2023 | return MeshCache; | ||
2024 | } | ||
2025 | |||
2026 | |||
2027 | //! Creates a new scene manager. | ||
2028 | ISceneManager* CSceneManager::createNewSceneManager(bool cloneContent) | ||
2029 | { | ||
2030 | CSceneManager* manager = new CSceneManager(Driver, FileSystem, CursorControl, MeshCache, GUIEnvironment); | ||
2031 | |||
2032 | if (cloneContent) | ||
2033 | manager->cloneMembers(this, manager); | ||
2034 | |||
2035 | return manager; | ||
2036 | } | ||
2037 | |||
2038 | |||
2039 | //! Returns the default scene node factory which can create all built in scene nodes | ||
2040 | ISceneNodeFactory* CSceneManager::getDefaultSceneNodeFactory() | ||
2041 | { | ||
2042 | return getSceneNodeFactory(0); | ||
2043 | } | ||
2044 | |||
2045 | |||
2046 | //! Adds a scene node factory to the scene manager. | ||
2047 | void CSceneManager::registerSceneNodeFactory(ISceneNodeFactory* factoryToAdd) | ||
2048 | { | ||
2049 | if (factoryToAdd) | ||
2050 | { | ||
2051 | factoryToAdd->grab(); | ||
2052 | SceneNodeFactoryList.push_back(factoryToAdd); | ||
2053 | } | ||
2054 | } | ||
2055 | |||
2056 | |||
2057 | //! Returns amount of registered scene node factories. | ||
2058 | u32 CSceneManager::getRegisteredSceneNodeFactoryCount() const | ||
2059 | { | ||
2060 | return SceneNodeFactoryList.size(); | ||
2061 | } | ||
2062 | |||
2063 | |||
2064 | //! Returns a scene node factory by index | ||
2065 | ISceneNodeFactory* CSceneManager::getSceneNodeFactory(u32 index) | ||
2066 | { | ||
2067 | if (index < SceneNodeFactoryList.size()) | ||
2068 | return SceneNodeFactoryList[index]; | ||
2069 | |||
2070 | return 0; | ||
2071 | } | ||
2072 | |||
2073 | |||
2074 | //! Returns the default scene node animator factory which can create all built-in scene node animators | ||
2075 | ISceneNodeAnimatorFactory* CSceneManager::getDefaultSceneNodeAnimatorFactory() | ||
2076 | { | ||
2077 | return getSceneNodeAnimatorFactory(0); | ||
2078 | } | ||
2079 | |||
2080 | //! Adds a scene node animator factory to the scene manager. | ||
2081 | void CSceneManager::registerSceneNodeAnimatorFactory(ISceneNodeAnimatorFactory* factoryToAdd) | ||
2082 | { | ||
2083 | if (factoryToAdd) | ||
2084 | { | ||
2085 | factoryToAdd->grab(); | ||
2086 | SceneNodeAnimatorFactoryList.push_back(factoryToAdd); | ||
2087 | } | ||
2088 | } | ||
2089 | |||
2090 | |||
2091 | //! Returns amount of registered scene node animator factories. | ||
2092 | u32 CSceneManager::getRegisteredSceneNodeAnimatorFactoryCount() const | ||
2093 | { | ||
2094 | return SceneNodeAnimatorFactoryList.size(); | ||
2095 | } | ||
2096 | |||
2097 | |||
2098 | //! Returns a scene node animator factory by index | ||
2099 | ISceneNodeAnimatorFactory* CSceneManager::getSceneNodeAnimatorFactory(u32 index) | ||
2100 | { | ||
2101 | if (index < SceneNodeAnimatorFactoryList.size()) | ||
2102 | return SceneNodeAnimatorFactoryList[index]; | ||
2103 | |||
2104 | return 0; | ||
2105 | } | ||
2106 | |||
2107 | |||
2108 | //! Saves the current scene into a file. | ||
2109 | //! \param filename: Name of the file . | ||
2110 | bool CSceneManager::saveScene(const io::path& filename, ISceneUserDataSerializer* userDataSerializer, ISceneNode* node) | ||
2111 | { | ||
2112 | bool ret = false; | ||
2113 | io::IWriteFile* file = FileSystem->createAndWriteFile(filename); | ||
2114 | if (file) | ||
2115 | { | ||
2116 | ret = saveScene(file, userDataSerializer, node); | ||
2117 | file->drop(); | ||
2118 | } | ||
2119 | else | ||
2120 | os::Printer::log("Unable to open file", filename, ELL_ERROR); | ||
2121 | |||
2122 | _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; | ||
2123 | return ret; | ||
2124 | } | ||
2125 | |||
2126 | |||
2127 | //! Saves the current scene into a file. | ||
2128 | bool CSceneManager::saveScene(io::IWriteFile* file, ISceneUserDataSerializer* userDataSerializer, ISceneNode* node) | ||
2129 | { | ||
2130 | if (!file) | ||
2131 | { | ||
2132 | return false; | ||
2133 | } | ||
2134 | |||
2135 | bool result=false; | ||
2136 | io::IXMLWriter* writer = FileSystem->createXMLWriter(file); | ||
2137 | if (!writer) | ||
2138 | { | ||
2139 | os::Printer::log("Unable to create XML writer", file->getFileName(), ELL_ERROR); | ||
2140 | } | ||
2141 | else | ||
2142 | { | ||
2143 | result = saveScene(writer, FileSystem->getFileDir(FileSystem->getAbsolutePath(file->getFileName())), userDataSerializer, node); | ||
2144 | writer->drop(); | ||
2145 | } | ||
2146 | return result; | ||
2147 | } | ||
2148 | |||
2149 | |||
2150 | //! Saves the current scene into a file. | ||
2151 | bool CSceneManager::saveScene(io::IXMLWriter* writer, const io::path& currentPath, ISceneUserDataSerializer* userDataSerializer, ISceneNode* node) | ||
2152 | { | ||
2153 | if (!writer) | ||
2154 | return false; | ||
2155 | |||
2156 | if (!node) | ||
2157 | node=this; | ||
2158 | |||
2159 | writer->writeXMLHeader(); | ||
2160 | writeSceneNode(writer, node, userDataSerializer, currentPath.c_str(), true); | ||
2161 | |||
2162 | return true; | ||
2163 | } | ||
2164 | |||
2165 | |||
2166 | //! Loads a scene. | ||
2167 | bool CSceneManager::loadScene(const io::path& filename, ISceneUserDataSerializer* userDataSerializer, ISceneNode* rootNode) | ||
2168 | { | ||
2169 | io::IReadFile* file = FileSystem->createAndOpenFile(filename); | ||
2170 | if (!file) | ||
2171 | { | ||
2172 | os::Printer::log("Unable to open scene file", filename.c_str(), ELL_ERROR); | ||
2173 | return false; | ||
2174 | } | ||
2175 | |||
2176 | const bool ret = loadScene(file, userDataSerializer, rootNode); | ||
2177 | file->drop(); | ||
2178 | |||
2179 | return ret; | ||
2180 | } | ||
2181 | |||
2182 | |||
2183 | //! Loads a scene. Note that the current scene is not cleared before. | ||
2184 | bool CSceneManager::loadScene(io::IReadFile* file, ISceneUserDataSerializer* userDataSerializer, ISceneNode* rootNode) | ||
2185 | { | ||
2186 | if (!file) | ||
2187 | { | ||
2188 | os::Printer::log("Unable to open scene file", ELL_ERROR); | ||
2189 | return false; | ||
2190 | } | ||
2191 | |||
2192 | bool ret = false; | ||
2193 | |||
2194 | // try scene loaders in reverse order | ||
2195 | s32 i = SceneLoaderList.size()-1; | ||
2196 | for (; i >= 0 && !ret; --i) | ||
2197 | if (SceneLoaderList[i]->isALoadableFileFormat(file)) | ||
2198 | ret = SceneLoaderList[i]->loadScene(file, userDataSerializer, rootNode); | ||
2199 | |||
2200 | if (!ret) | ||
2201 | os::Printer::log("Could not load scene file, perhaps the format is unsupported: ", file->getFileName().c_str(), ELL_ERROR); | ||
2202 | |||
2203 | return ret; | ||
2204 | } | ||
2205 | |||
2206 | |||
2207 | //! writes a scene node | ||
2208 | void CSceneManager::writeSceneNode(io::IXMLWriter* writer, ISceneNode* node, ISceneUserDataSerializer* userDataSerializer, | ||
2209 | const fschar_t* currentPath, bool init) | ||
2210 | { | ||
2211 | if (!writer || !node || node->isDebugObject()) | ||
2212 | return; | ||
2213 | |||
2214 | const wchar_t* name; | ||
2215 | ISceneNode* tmpNode=node; | ||
2216 | |||
2217 | if (init) | ||
2218 | { | ||
2219 | name = IRR_XML_FORMAT_SCENE.c_str(); | ||
2220 | writer->writeElement(name, false); | ||
2221 | node=this; | ||
2222 | } | ||
2223 | else | ||
2224 | { | ||
2225 | name = IRR_XML_FORMAT_NODE.c_str(); | ||
2226 | writer->writeElement(name, false, IRR_XML_FORMAT_NODE_ATTR_TYPE.c_str(), | ||
2227 | core::stringw(getSceneNodeTypeName(node->getType())).c_str()); | ||
2228 | } | ||
2229 | |||
2230 | writer->writeLineBreak(); | ||
2231 | |||
2232 | // write properties | ||
2233 | |||
2234 | io::IAttributes* attr = FileSystem->createEmptyAttributes(Driver); | ||
2235 | io::SAttributeReadWriteOptions options; | ||
2236 | if (currentPath) | ||
2237 | { | ||
2238 | options.Filename=currentPath; | ||
2239 | options.Flags|=io::EARWF_USE_RELATIVE_PATHS; | ||
2240 | } | ||
2241 | node->serializeAttributes(attr, &options); | ||
2242 | |||
2243 | if (attr->getAttributeCount() != 0) | ||
2244 | { | ||
2245 | attr->write(writer); | ||
2246 | writer->writeLineBreak(); | ||
2247 | } | ||
2248 | |||
2249 | // write materials | ||
2250 | |||
2251 | if (node->getMaterialCount() && Driver) | ||
2252 | { | ||
2253 | const wchar_t* materialElement = L"materials"; | ||
2254 | |||
2255 | writer->writeElement(materialElement); | ||
2256 | writer->writeLineBreak(); | ||
2257 | |||
2258 | for (u32 i=0; i < node->getMaterialCount(); ++i) | ||
2259 | { | ||
2260 | io::IAttributes* tmp_attr = | ||
2261 | Driver->createAttributesFromMaterial(node->getMaterial(i), &options); | ||
2262 | tmp_attr->write(writer); | ||
2263 | tmp_attr->drop(); | ||
2264 | } | ||
2265 | |||
2266 | writer->writeClosingTag(materialElement); | ||
2267 | writer->writeLineBreak(); | ||
2268 | } | ||
2269 | |||
2270 | // write animators | ||
2271 | |||
2272 | if (!node->getAnimators().empty()) | ||
2273 | { | ||
2274 | const wchar_t* animatorElement = L"animators"; | ||
2275 | writer->writeElement(animatorElement); | ||
2276 | writer->writeLineBreak(); | ||
2277 | |||
2278 | ISceneNodeAnimatorList::ConstIterator it = node->getAnimators().begin(); | ||
2279 | for (; it != node->getAnimators().end(); ++it) | ||
2280 | { | ||
2281 | attr->clear(); | ||
2282 | attr->addString("Type", getAnimatorTypeName((*it)->getType())); | ||
2283 | |||
2284 | (*it)->serializeAttributes(attr); | ||
2285 | |||
2286 | attr->write(writer); | ||
2287 | } | ||
2288 | |||
2289 | writer->writeClosingTag(animatorElement); | ||
2290 | writer->writeLineBreak(); | ||
2291 | } | ||
2292 | |||
2293 | // write possible user data | ||
2294 | |||
2295 | if (userDataSerializer) | ||
2296 | { | ||
2297 | io::IAttributes* userData = userDataSerializer->createUserData(node); | ||
2298 | if (userData) | ||
2299 | { | ||
2300 | const wchar_t* userDataElement = L"userData"; | ||
2301 | |||
2302 | writer->writeLineBreak(); | ||
2303 | writer->writeElement(userDataElement); | ||
2304 | writer->writeLineBreak(); | ||
2305 | |||
2306 | userData->write(writer); | ||
2307 | |||
2308 | writer->writeClosingTag(userDataElement); | ||
2309 | writer->writeLineBreak(); | ||
2310 | writer->writeLineBreak(); | ||
2311 | |||
2312 | userData->drop(); | ||
2313 | } | ||
2314 | } | ||
2315 | // reset to actual root node | ||
2316 | if (init) | ||
2317 | node=tmpNode; | ||
2318 | |||
2319 | // write children once root node is written | ||
2320 | // if parent is not scene manager, we need to write out node first | ||
2321 | if (init && (node != this)) | ||
2322 | { | ||
2323 | writeSceneNode(writer, node, userDataSerializer, currentPath); | ||
2324 | } | ||
2325 | else | ||
2326 | { | ||
2327 | ISceneNodeList::ConstIterator it = node->getChildren().begin(); | ||
2328 | for (; it != node->getChildren().end(); ++it) | ||
2329 | writeSceneNode(writer, (*it), userDataSerializer, currentPath); | ||
2330 | } | ||
2331 | |||
2332 | attr->drop(); | ||
2333 | |||
2334 | writer->writeClosingTag(name); | ||
2335 | writer->writeLineBreak(); | ||
2336 | writer->writeLineBreak(); | ||
2337 | } | ||
2338 | |||
2339 | |||
2340 | //! Returns a typename from a scene node type or null if not found | ||
2341 | const c8* CSceneManager::getSceneNodeTypeName(ESCENE_NODE_TYPE type) | ||
2342 | { | ||
2343 | const char* name = 0; | ||
2344 | |||
2345 | for (s32 i=(s32)SceneNodeFactoryList.size()-1; !name && i>=0; --i) | ||
2346 | name = SceneNodeFactoryList[i]->getCreateableSceneNodeTypeName(type); | ||
2347 | |||
2348 | return name; | ||
2349 | } | ||
2350 | |||
2351 | //! Adds a scene node to the scene by name | ||
2352 | ISceneNode* CSceneManager::addSceneNode(const char* sceneNodeTypeName, ISceneNode* parent) | ||
2353 | { | ||
2354 | ISceneNode* node = 0; | ||
2355 | |||
2356 | for (s32 i=(s32)SceneNodeFactoryList.size()-1; i>=0 && !node; --i) | ||
2357 | node = SceneNodeFactoryList[i]->addSceneNode(sceneNodeTypeName, parent); | ||
2358 | |||
2359 | return node; | ||
2360 | } | ||
2361 | |||
2362 | ISceneNodeAnimator* CSceneManager::createSceneNodeAnimator(const char* typeName, ISceneNode* target) | ||
2363 | { | ||
2364 | ISceneNodeAnimator *animator = 0; | ||
2365 | |||
2366 | for (s32 i=(s32)SceneNodeAnimatorFactoryList.size()-1; i>=0 && !animator; --i) | ||
2367 | animator = SceneNodeAnimatorFactoryList[i]->createSceneNodeAnimator(typeName, target); | ||
2368 | |||
2369 | return animator; | ||
2370 | } | ||
2371 | |||
2372 | |||
2373 | //! Returns a typename from a scene node animator type or null if not found | ||
2374 | const c8* CSceneManager::getAnimatorTypeName(ESCENE_NODE_ANIMATOR_TYPE type) | ||
2375 | { | ||
2376 | const char* name = 0; | ||
2377 | |||
2378 | for (s32 i=SceneNodeAnimatorFactoryList.size()-1; !name && i >= 0; --i) | ||
2379 | name = SceneNodeAnimatorFactoryList[i]->getCreateableSceneNodeAnimatorTypeName(type); | ||
2380 | |||
2381 | return name; | ||
2382 | } | ||
2383 | |||
2384 | |||
2385 | //! Writes attributes of the scene node. | ||
2386 | void CSceneManager::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const | ||
2387 | { | ||
2388 | out->addString ("Name", Name.c_str()); | ||
2389 | out->addInt ("Id", ID ); | ||
2390 | out->addColorf ("AmbientLight", AmbientLight); | ||
2391 | |||
2392 | // fog attributes from video driver | ||
2393 | video::SColor color; | ||
2394 | video::E_FOG_TYPE fogType; | ||
2395 | f32 start, end, density; | ||
2396 | bool pixelFog, rangeFog; | ||
2397 | |||
2398 | Driver->getFog(color, fogType, start, end, density, pixelFog, rangeFog); | ||
2399 | |||
2400 | out->addEnum("FogType", fogType, video::FogTypeNames); | ||
2401 | out->addColorf("FogColor", color); | ||
2402 | out->addFloat("FogStart", start); | ||
2403 | out->addFloat("FogEnd", end); | ||
2404 | out->addFloat("FogDensity", density); | ||
2405 | out->addBool("FogPixel", pixelFog); | ||
2406 | out->addBool("FogRange", rangeFog); | ||
2407 | } | ||
2408 | |||
2409 | //! Reads attributes of the scene node. | ||
2410 | void CSceneManager::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) | ||
2411 | { | ||
2412 | Name = in->getAttributeAsString("Name"); | ||
2413 | ID = in->getAttributeAsInt("Id"); | ||
2414 | AmbientLight = in->getAttributeAsColorf("AmbientLight"); | ||
2415 | |||
2416 | // fog attributes | ||
2417 | video::SColor color; | ||
2418 | video::E_FOG_TYPE fogType; | ||
2419 | f32 start, end, density; | ||
2420 | bool pixelFog, rangeFog; | ||
2421 | if (in->existsAttribute("FogType")) | ||
2422 | { | ||
2423 | fogType = (video::E_FOG_TYPE) in->getAttributeAsEnumeration("FogType", video::FogTypeNames); | ||
2424 | color = in->getAttributeAsColorf("FogColor").toSColor(); | ||
2425 | start = in->getAttributeAsFloat("FogStart"); | ||
2426 | end = in->getAttributeAsFloat("FogEnd"); | ||
2427 | density = in->getAttributeAsFloat("FogDensity"); | ||
2428 | pixelFog = in->getAttributeAsBool("FogPixel"); | ||
2429 | rangeFog = in->getAttributeAsBool("FogRange"); | ||
2430 | Driver->setFog(color, fogType, start, end, density, pixelFog, rangeFog); | ||
2431 | } | ||
2432 | |||
2433 | RelativeTranslation.set(0,0,0); | ||
2434 | RelativeRotation.set(0,0,0); | ||
2435 | RelativeScale.set(1,1,1); | ||
2436 | IsVisible = true; | ||
2437 | AutomaticCullingState = scene::EAC_BOX; | ||
2438 | DebugDataVisible = scene::EDS_OFF; | ||
2439 | IsDebugObject = false; | ||
2440 | |||
2441 | updateAbsolutePosition(); | ||
2442 | } | ||
2443 | |||
2444 | |||
2445 | //! Sets ambient color of the scene | ||
2446 | void CSceneManager::setAmbientLight(const video::SColorf &ambientColor) | ||
2447 | { | ||
2448 | AmbientLight = ambientColor; | ||
2449 | } | ||
2450 | |||
2451 | |||
2452 | //! Returns ambient color of the scene | ||
2453 | const video::SColorf& CSceneManager::getAmbientLight() const | ||
2454 | { | ||
2455 | return AmbientLight; | ||
2456 | } | ||
2457 | |||
2458 | |||
2459 | //! Get a skinned mesh, which is not available as header-only code | ||
2460 | ISkinnedMesh* CSceneManager::createSkinnedMesh() | ||
2461 | { | ||
2462 | #ifdef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_ | ||
2463 | return new CSkinnedMesh(); | ||
2464 | #else | ||
2465 | return 0; | ||
2466 | #endif | ||
2467 | } | ||
2468 | |||
2469 | //! Returns a mesh writer implementation if available | ||
2470 | IMeshWriter* CSceneManager::createMeshWriter(EMESH_WRITER_TYPE type) | ||
2471 | { | ||
2472 | switch(type) | ||
2473 | { | ||
2474 | case EMWT_IRR_MESH: | ||
2475 | #ifdef _IRR_COMPILE_WITH_IRR_WRITER_ | ||
2476 | return new CIrrMeshWriter(Driver, FileSystem); | ||
2477 | #else | ||
2478 | return 0; | ||
2479 | #endif | ||
2480 | case EMWT_COLLADA: | ||
2481 | #ifdef _IRR_COMPILE_WITH_COLLADA_WRITER_ | ||
2482 | return new CColladaMeshWriter(this, Driver, FileSystem); | ||
2483 | #else | ||
2484 | return 0; | ||
2485 | #endif | ||
2486 | case EMWT_STL: | ||
2487 | #ifdef _IRR_COMPILE_WITH_STL_WRITER_ | ||
2488 | return new CSTLMeshWriter(this); | ||
2489 | #else | ||
2490 | return 0; | ||
2491 | #endif | ||
2492 | case EMWT_OBJ: | ||
2493 | #ifdef _IRR_COMPILE_WITH_OBJ_WRITER_ | ||
2494 | return new COBJMeshWriter(this, FileSystem); | ||
2495 | #else | ||
2496 | return 0; | ||
2497 | #endif | ||
2498 | |||
2499 | case EMWT_PLY: | ||
2500 | #ifdef _IRR_COMPILE_WITH_PLY_WRITER_ | ||
2501 | return new CPLYMeshWriter(); | ||
2502 | #else | ||
2503 | return 0; | ||
2504 | #endif | ||
2505 | } | ||
2506 | |||
2507 | return 0; | ||
2508 | } | ||
2509 | |||
2510 | |||
2511 | // creates a scenemanager | ||
2512 | ISceneManager* createSceneManager(video::IVideoDriver* driver, | ||
2513 | io::IFileSystem* fs, gui::ICursorControl* cursorcontrol, | ||
2514 | gui::IGUIEnvironment *guiEnvironment) | ||
2515 | { | ||
2516 | return new CSceneManager(driver, fs, cursorcontrol, 0, guiEnvironment ); | ||
2517 | } | ||
2518 | |||
2519 | |||
2520 | } // end namespace scene | ||
2521 | } // end namespace irr | ||
2522 | |||