aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/others/irrlicht-1.8.1/source/Irrlicht/CSceneManager.cpp
diff options
context:
space:
mode:
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.cpp2522
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
176namespace irr
177{
178namespace scene
179{
180
181//! constructor
182CSceneManager::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
315CSceneManager::~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.
375IAnimatedMesh* 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.
418IAnimatedMesh* 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
456video::IVideoDriver* CSceneManager::getVideoDriver()
457{
458 return Driver;
459}
460
461
462//! returns the GUI Environment
463gui::IGUIEnvironment* CSceneManager::getGUIEnvironment()
464{
465 return GUIEnvironment;
466}
467
468//! Get the active FileSystem
469/** \return Pointer to the FileSystem
470This pointer should not be dropped. See IReferenceCounted::drop() for more information. */
471io::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
478ITextSceneNode* 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
497IBillboardTextSceneNode* 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
522IMeshSceneNode* 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.
547IVolumeLightSceneNode* 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.
565IMeshSceneNode* 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.
580IMeshSceneNode* 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.
596IMeshSceneNode* 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.
614ISceneNode* 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
631IAnimatedMeshSceneNode* 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.
652IMeshSceneNode* 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.
667IMeshSceneNode* 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
694ICameraSceneNode* 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.
714ICameraSceneNode* 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):
735ICameraSceneNode* 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).
761ILightSceneNode* 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.
777IBillboardSceneNode* 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.
795ISceneNode* 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.
812ISceneNode* 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.
828IParticleSystemSceneNode* 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.
845ITerrainSceneNode* 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.
875ITerrainSceneNode* 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.
914ISceneNode* 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.
927IDummyTransformationSceneNode* 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.
946IAnimatedMesh* 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.
981IAnimatedMesh* 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.
1016IAnimatedMesh* 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.
1049IAnimatedMesh* 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.
1079IAnimatedMesh* 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.
1113ISceneNode* 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.
1122ICameraSceneNode* 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.
1130void 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.
1142void CSceneManager::render()
1143{
1144}
1145
1146
1147//! returns the axis aligned bounding box of this node
1148const 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
1158bool 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.
1226u32 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
1343void 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
1617void 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.
1629void CSceneManager::setShadowColor(video::SColor color)
1630{
1631 ShadowColor = color;
1632}
1633
1634
1635//! Returns the current color of shadows.
1636video::SColor CSceneManager::getShadowColor() const
1637{
1638 return ShadowColor;
1639}
1640
1641
1642//! creates a rotation animator, which rotates the attached scene node around itself.
1643ISceneNodeAnimator* 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.
1653ISceneNodeAnimator* 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.
1671ISceneNodeAnimator* 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.
1683ISceneNodeAnimator* 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.
1695ISceneNodeAnimator* 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.
1703ISceneNodeAnimatorCollisionResponse* 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.
1718ISceneNodeAnimator* 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.
1729void 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
1740u32 CSceneManager::getMeshLoaderCount() const
1741{
1742 return MeshLoaderList.size();
1743}
1744
1745
1746//! Retrieve the given mesh loader
1747IMeshLoader* 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.
1757void 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
1768u32 CSceneManager::getSceneLoaderCount() const
1769{
1770 return SceneLoaderList.size();
1771}
1772
1773
1774//! Retrieve the given scene loader
1775ISceneLoader* 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.
1785ISceneCollisionManager* CSceneManager::getSceneCollisionManager()
1786{
1787 return CollisionManager;
1788}
1789
1790
1791//! Returns a pointer to the mesh manipulator.
1792IMeshManipulator* CSceneManager::getMeshManipulator()
1793{
1794 return Driver->getMeshManipulator();
1795}
1796
1797
1798//! Creates a simple ITriangleSelector, based on a mesh.
1799ITriangleSelector* 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
1810ITriangleSelector* 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.
1820ITriangleSelector* 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.
1830ITriangleSelector* 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.
1841IMetaTriangleSelector* CSceneManager::createMetaTriangleSelector()
1842{
1843 return new CMetaTriangleSelector();
1844}
1845
1846
1847//! Creates a triangle selector which can select triangles from a terrain scene node
1848ITriangleSelector* 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.
1857void 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
1868void 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.
1884ISceneNode* 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.
1908ISceneNode* 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.
1932ISceneNode* 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.
1956void 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.
1976bool 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
1989void 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.
2000void CSceneManager::clear()
2001{
2002 removeAll();
2003}
2004
2005
2006//! Returns interface to the parameters set in this scene.
2007io::IAttributes* CSceneManager::getParameters()
2008{
2009 return &Parameters;
2010}
2011
2012
2013//! Returns current render pass.
2014E_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.
2021IMeshCache* CSceneManager::getMeshCache()
2022{
2023 return MeshCache;
2024}
2025
2026
2027//! Creates a new scene manager.
2028ISceneManager* 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
2040ISceneNodeFactory* CSceneManager::getDefaultSceneNodeFactory()
2041{
2042 return getSceneNodeFactory(0);
2043}
2044
2045
2046//! Adds a scene node factory to the scene manager.
2047void 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.
2058u32 CSceneManager::getRegisteredSceneNodeFactoryCount() const
2059{
2060 return SceneNodeFactoryList.size();
2061}
2062
2063
2064//! Returns a scene node factory by index
2065ISceneNodeFactory* 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
2075ISceneNodeAnimatorFactory* CSceneManager::getDefaultSceneNodeAnimatorFactory()
2076{
2077 return getSceneNodeAnimatorFactory(0);
2078}
2079
2080//! Adds a scene node animator factory to the scene manager.
2081void 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.
2092u32 CSceneManager::getRegisteredSceneNodeAnimatorFactoryCount() const
2093{
2094 return SceneNodeAnimatorFactoryList.size();
2095}
2096
2097
2098//! Returns a scene node animator factory by index
2099ISceneNodeAnimatorFactory* 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 .
2110bool 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.
2128bool 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.
2151bool 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.
2167bool 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.
2184bool 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
2208void 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
2341const 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
2352ISceneNode* 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
2362ISceneNodeAnimator* 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
2374const 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.
2386void 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.
2410void 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
2446void CSceneManager::setAmbientLight(const video::SColorf &ambientColor)
2447{
2448 AmbientLight = ambientColor;
2449}
2450
2451
2452//! Returns ambient color of the scene
2453const 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
2460ISkinnedMesh* 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
2470IMeshWriter* 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
2512ISceneManager* 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