1 // Copyright (C) 2002-2012 Nikolaus Gebhardt
\r
2 // This file is part of the "Irrlicht Engine".
\r
3 // For conditions of distribution and use, see copyright notice in irrlicht.h
\r
5 #include "CSceneManager.h"
\r
6 #include "IVideoDriver.h"
\r
7 #include "IFileSystem.h"
\r
8 #include "SAnimatedMesh.h"
\r
9 #include "CMeshCache.h"
\r
10 #include "IGUIEnvironment.h"
\r
11 #include "IMaterialRenderer.h"
\r
12 #include "IReadFile.h"
\r
13 #include "IWriteFile.h"
\r
17 #include "CSkinnedMesh.h"
\r
18 #include "CXMeshFileLoader.h"
\r
19 #include "COBJMeshFileLoader.h"
\r
20 #include "CB3DMeshFileLoader.h"
\r
21 #include "CBillboardSceneNode.h"
\r
22 #include "CAnimatedMeshSceneNode.h"
\r
23 #include "CCameraSceneNode.h"
\r
24 #include "CLightSceneNode.h"
\r
25 #include "CMeshSceneNode.h"
\r
27 #ifdef _IRR_COMPILE_WITH_SHADOW_VOLUME_SCENENODE_
\r
28 #include "CShadowVolumeSceneNode.h"
\r
30 #include "IShadowVolumeSceneNode.h"
\r
31 #endif // _IRR_COMPILE_WITH_SHADOW_VOLUME_SCENENODE_
\r
33 #include "CDummyTransformationSceneNode.h"
\r
34 #include "CEmptySceneNode.h"
\r
36 #include "CSceneCollisionManager.h"
\r
44 CSceneManager::CSceneManager(video::IVideoDriver* driver,
\r
45 gui::ICursorControl* cursorControl, IMeshCache* cache)
\r
46 : ISceneNode(0, 0), Driver(driver),
\r
47 CursorControl(cursorControl),
\r
48 ActiveCamera(0), ShadowColor(150,0,0,0), AmbientLight(0,0,0,0), Parameters(0),
\r
49 MeshCache(cache), CurrentRenderPass(ESNRP_NONE), LightManager(0)
\r
52 ISceneManager::setDebugName("CSceneManager ISceneManager");
\r
53 ISceneNode::setDebugName("CSceneManager ISceneNode");
\r
56 // root node's scene manager
\r
57 SceneManager = this;
\r
63 CursorControl->grab();
\r
65 // create mesh cache if not there already
\r
67 MeshCache = new CMeshCache();
\r
71 // set scene parameters
\r
72 Parameters = new io::CAttributes();
\r
74 // create collision manager
\r
75 CollisionManager = new CSceneCollisionManager(this, Driver);
\r
77 // add file format loaders. add the least commonly used ones first,
\r
78 // as these are checked last
\r
80 // TODO: now that we have multiple scene managers, these should be
\r
81 // shallow copies from the previous manager if there is one.
\r
83 MeshLoaderList.push_back(new CXMeshFileLoader(this));
\r
84 MeshLoaderList.push_back(new COBJMeshFileLoader(this));
\r
85 MeshLoaderList.push_back(new CB3DMeshFileLoader(this));
\r
90 CSceneManager::~CSceneManager()
\r
92 clearDeletionList();
\r
94 //! force to remove hardwareTextures from the driver
\r
95 //! because Scenes may hold internally data bounded to sceneNodes
\r
96 //! which may be destroyed twice
\r
98 Driver->removeAllHardwareBuffers();
\r
101 CursorControl->drop();
\r
103 if (CollisionManager)
\r
104 CollisionManager->drop();
\r
107 for (i=0; i<MeshLoaderList.size(); ++i)
\r
108 MeshLoaderList[i]->drop();
\r
111 ActiveCamera->drop();
\r
118 Parameters->drop();
\r
121 LightManager->drop();
\r
123 // remove all nodes before dropping the driver
\r
124 // as render targets may be destroyed twice
\r
133 //! gets an animateable mesh. loads it if needed. returned pointer must not be dropped.
\r
134 IAnimatedMesh* CSceneManager::getMesh(io::IReadFile* file)
\r
139 io::path name = file->getFileName();
\r
140 IAnimatedMesh* msh = MeshCache->getMeshByName(name);
\r
144 msh = getUncachedMesh(file, name, name);
\r
149 // load and create a mesh which we know already isn't in the cache and put it in there
\r
150 IAnimatedMesh* CSceneManager::getUncachedMesh(io::IReadFile* file, const io::path& filename, const io::path& cachename)
\r
152 IAnimatedMesh* msh = 0;
\r
154 // iterate the list in reverse order so user-added loaders can override the built-in ones
\r
155 s32 count = MeshLoaderList.size();
\r
156 for (s32 i=count-1; i>=0; --i)
\r
158 if (MeshLoaderList[i]->isALoadableFileExtension(filename))
\r
160 // reset file to avoid side effects of previous calls to createMesh
\r
162 msh = MeshLoaderList[i]->createMesh(file);
\r
165 MeshCache->addMesh(cachename, msh);
\r
173 os::Printer::log("Could not load mesh, file format seems to be unsupported", filename, ELL_ERROR);
\r
175 os::Printer::log("Loaded mesh", filename, ELL_DEBUG);
\r
180 //! returns the video driver
\r
181 video::IVideoDriver* CSceneManager::getVideoDriver()
\r
187 //! adds a scene node for rendering a static mesh
\r
188 //! the returned pointer must not be dropped.
\r
189 IMeshSceneNode* CSceneManager::addMeshSceneNode(IMesh* mesh, ISceneNode* parent, s32 id,
\r
190 const core::vector3df& position, const core::vector3df& rotation,
\r
191 const core::vector3df& scale, bool alsoAddIfMeshPointerZero)
\r
193 if (!alsoAddIfMeshPointerZero && !mesh)
\r
199 IMeshSceneNode* node = new CMeshSceneNode(mesh, parent, this, id, position, rotation, scale);
\r
206 //! adds a scene node for rendering an animated mesh model
\r
207 IAnimatedMeshSceneNode* CSceneManager::addAnimatedMeshSceneNode(IAnimatedMesh* mesh, ISceneNode* parent, s32 id,
\r
208 const core::vector3df& position, const core::vector3df& rotation,
\r
209 const core::vector3df& scale, bool alsoAddIfMeshPointerZero)
\r
211 if (!alsoAddIfMeshPointerZero && !mesh)
\r
217 IAnimatedMeshSceneNode* node =
\r
218 new CAnimatedMeshSceneNode(mesh, parent, this, id, position, rotation, scale);
\r
225 //! Adds a camera scene node to the tree and sets it as active camera.
\r
226 //! \param position: Position of the space relative to its parent where the camera will be placed.
\r
227 //! \param lookat: Position where the camera will look at. Also known as target.
\r
228 //! \param parent: Parent scene node of the camera. Can be null. If the parent moves,
\r
229 //! the camera will move too.
\r
230 //! \return Returns pointer to interface to camera
\r
231 ICameraSceneNode* CSceneManager::addCameraSceneNode(ISceneNode* parent,
\r
232 const core::vector3df& position, const core::vector3df& lookat, s32 id,
\r
238 ICameraSceneNode* node = new CCameraSceneNode(parent, this, id, position, lookat);
\r
241 setActiveCamera(node);
\r
248 //! Adds a dynamic light scene node. The light will cast dynamic light on all
\r
249 //! other scene nodes in the scene, which have the material flag video::MTF_LIGHTING
\r
250 //! turned on. (This is the default setting in most scene nodes).
\r
251 ILightSceneNode* CSceneManager::addLightSceneNode(ISceneNode* parent,
\r
252 const core::vector3df& position, video::SColorf color, f32 range, s32 id)
\r
257 ILightSceneNode* node = new CLightSceneNode(parent, this, id, position, color, range);
\r
264 //! Adds a billboard scene node to the scene. A billboard is like a 3d sprite: A 2d element,
\r
265 //! which always looks to the camera. It is usually used for things like explosions, fire,
\r
266 //! lensflares and things like that.
\r
267 IBillboardSceneNode* CSceneManager::addBillboardSceneNode(ISceneNode* parent,
\r
268 const core::dimension2d<f32>& size, const core::vector3df& position, s32 id,
\r
269 video::SColor colorTop, video::SColor colorBottom
\r
275 IBillboardSceneNode* node = new CBillboardSceneNode(parent, this, id, position, size,
\r
276 colorTop, colorBottom);
\r
283 //! Adds an empty scene node.
\r
284 ISceneNode* CSceneManager::addEmptySceneNode(ISceneNode* parent, s32 id)
\r
289 ISceneNode* node = new CEmptySceneNode(parent, this, id);
\r
296 //! Adds a dummy transformation scene node to the scene graph.
\r
297 IDummyTransformationSceneNode* CSceneManager::addDummyTransformationSceneNode(
\r
298 ISceneNode* parent, s32 id)
\r
303 IDummyTransformationSceneNode* node = new CDummyTransformationSceneNode(
\r
311 //! Returns the root scene node. This is the scene node which is parent
\r
312 //! of all scene nodes. The root scene node is a special scene node which
\r
313 //! only exists to manage all scene nodes. It is not rendered and cannot
\r
314 //! be removed from the scene.
\r
315 //! \return Returns a pointer to the root scene node.
\r
316 ISceneNode* CSceneManager::getRootSceneNode()
\r
322 //! Returns the current active camera.
\r
323 //! \return The active camera is returned. Note that this can be NULL, if there
\r
324 //! was no camera created yet.
\r
325 ICameraSceneNode* CSceneManager::getActiveCamera() const
\r
327 return ActiveCamera;
\r
331 //! Sets the active camera. The previous active camera will be deactivated.
\r
332 //! \param camera: The new camera which should be active.
\r
333 void CSceneManager::setActiveCamera(ICameraSceneNode* camera)
\r
338 ActiveCamera->drop();
\r
340 ActiveCamera = camera;
\r
344 //! renders the node.
\r
345 void CSceneManager::render()
\r
350 //! returns the axis aligned bounding box of this node
\r
351 const core::aabbox3d<f32>& CSceneManager::getBoundingBox() const
\r
353 _IRR_DEBUG_BREAK_IF(true) // Bounding Box of Scene Manager should never be used.
\r
355 static const core::aabbox3d<f32> dummy;
\r
360 //! returns if node is culled
\r
361 bool CSceneManager::isCulled(const ISceneNode* node) const
\r
363 const ICameraSceneNode* cam = getActiveCamera();
\r
368 bool result = false;
\r
370 // has occlusion query information
\r
371 if (node->getAutomaticCulling() & scene::EAC_OCC_QUERY)
\r
373 result = (Driver->getOcclusionQueryResult(const_cast<ISceneNode*>(node))==0);
\r
376 // can be seen by a bounding box ?
\r
377 if (!result && (node->getAutomaticCulling() & scene::EAC_BOX))
\r
379 core::aabbox3d<f32> tbox = node->getBoundingBox();
\r
380 node->getAbsoluteTransformation().transformBoxEx(tbox);
\r
381 result = !(tbox.intersectsWithBox(cam->getViewFrustum()->getBoundingBox() ));
\r
384 // can be seen by a bounding sphere
\r
385 if (!result && (node->getAutomaticCulling() & scene::EAC_FRUSTUM_SPHERE))
\r
387 const core::aabbox3df nbox = node->getTransformedBoundingBox();
\r
388 const float rad = nbox.getRadius();
\r
389 const core::vector3df center = nbox.getCenter();
\r
391 const float camrad = cam->getViewFrustum()->getBoundingRadius();
\r
392 const core::vector3df camcenter = cam->getViewFrustum()->getBoundingCenter();
\r
394 const float dist = (center - camcenter).getLengthSQ();
\r
395 const float maxdist = (rad + camrad) * (rad + camrad);
\r
397 result = dist > maxdist;
\r
400 // can be seen by cam pyramid planes ?
\r
401 if (!result && (node->getAutomaticCulling() & scene::EAC_FRUSTUM_BOX))
\r
403 SViewFrustum frust = *cam->getViewFrustum();
\r
405 //transform the frustum to the node's current absolute transformation
\r
406 core::matrix4 invTrans(node->getAbsoluteTransformation(), core::matrix4::EM4CONST_INVERSE);
\r
407 //invTrans.makeInverse();
\r
408 frust.transform(invTrans);
\r
410 core::vector3df edges[8];
\r
411 node->getBoundingBox().getEdges(edges);
\r
413 for (s32 i=0; i<scene::SViewFrustum::VF_PLANE_COUNT; ++i)
\r
415 bool boxInFrustum=false;
\r
416 for (u32 j=0; j<8; ++j)
\r
418 if (frust.planes[i].classifyPointRelation(edges[j]) != core::ISREL3D_FRONT)
\r
437 //! registers a node for rendering it at a specific time.
\r
438 u32 CSceneManager::registerNodeForRendering(ISceneNode* node, E_SCENE_NODE_RENDER_PASS pass)
\r
444 // take camera if it is not already registered
\r
448 for (u32 i = 0; i != CameraList.size(); ++i)
\r
450 if (CameraList[i] == node)
\r
458 CameraList.push_back(node);
\r
463 // TODO: Point Light culling..
\r
464 // Lighting model in irrlicht has to be redone..
\r
465 //if (!isCulled(node))
\r
467 LightList.push_back(node);
\r
471 case ESNRP_SKY_BOX:
\r
472 SkyBoxList.push_back(node);
\r
476 if (!isCulled(node))
\r
478 SolidNodeList.push_back(node);
\r
482 case ESNRP_TRANSPARENT:
\r
483 if (!isCulled(node))
\r
485 TransparentNodeList.push_back(TransparentNodeEntry(node, camWorldPos));
\r
489 case ESNRP_TRANSPARENT_EFFECT:
\r
490 if (!isCulled(node))
\r
492 TransparentEffectNodeList.push_back(TransparentNodeEntry(node, camWorldPos));
\r
496 case ESNRP_AUTOMATIC:
\r
497 if (!isCulled(node))
\r
499 const u32 count = node->getMaterialCount();
\r
502 for (u32 i=0; i<count; ++i)
\r
504 if (Driver->needsTransparentRenderPass(node->getMaterial(i)))
\r
506 // register as transparent node
\r
507 TransparentNodeEntry e(node, camWorldPos);
\r
508 TransparentNodeList.push_back(e);
\r
514 // not transparent, register as solid
\r
517 SolidNodeList.push_back(node);
\r
523 if (!isCulled(node))
\r
525 ShadowNodeList.push_back(node);
\r
530 if (!isCulled(node))
\r
532 GuiNodeList.push_back(node);
\r
536 case ESNRP_NONE: // ignore this one
\r
543 void CSceneManager::clearAllRegisteredNodesForRendering()
\r
545 CameraList.clear();
\r
547 SkyBoxList.clear();
\r
548 SolidNodeList.clear();
\r
549 TransparentNodeList.clear();
\r
550 TransparentEffectNodeList.clear();
\r
551 ShadowNodeList.clear();
\r
552 GuiNodeList.clear();
\r
555 //! This method is called just before the rendering process of the whole scene.
\r
556 //! draws all scene nodes
\r
557 void CSceneManager::drawAll()
\r
562 u32 i; // new ISO for scoping problem in some compilers
\r
564 // reset all transforms
\r
565 Driver->setMaterial(video::SMaterial());
\r
566 Driver->setTransform ( video::ETS_PROJECTION, core::IdentityMatrix );
\r
567 Driver->setTransform ( video::ETS_VIEW, core::IdentityMatrix );
\r
568 Driver->setTransform ( video::ETS_WORLD, core::IdentityMatrix );
\r
569 for (i=video::ETS_COUNT-1; i>=video::ETS_TEXTURE_0; --i)
\r
570 Driver->setTransform ( (video::E_TRANSFORMATION_STATE)i, core::IdentityMatrix );
\r
571 // TODO: This should not use an attribute here but a real parameter when necessary (too slow!)
\r
572 Driver->setAllowZWriteOnTransparent(Parameters->getAttributeAsBool(ALLOW_ZWRITE_ON_TRANSPARENT));
\r
574 // do animations and other stuff.
\r
575 OnAnimate(os::Timer::getTime());
\r
578 First Scene Node for prerendering should be the active camera
\r
579 consistent Camera is needed for culling
\r
581 camWorldPos.set(0,0,0);
\r
584 ActiveCamera->render();
\r
585 camWorldPos = ActiveCamera->getAbsolutePosition();
\r
588 // let all nodes register themselves
\r
589 OnRegisterSceneNode();
\r
592 LightManager->OnPreRender(LightList);
\r
594 //render camera scenes
\r
596 CurrentRenderPass = ESNRP_CAMERA;
\r
597 Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRenderPass) != 0);
\r
600 LightManager->OnRenderPassPreRender(CurrentRenderPass);
\r
602 for (i=0; i<CameraList.size(); ++i)
\r
603 CameraList[i]->render();
\r
605 CameraList.set_used(0);
\r
608 LightManager->OnRenderPassPostRender(CurrentRenderPass);
\r
611 //render lights scenes
\r
613 CurrentRenderPass = ESNRP_LIGHT;
\r
614 Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRenderPass) != 0);
\r
618 LightManager->OnRenderPassPreRender(CurrentRenderPass);
\r
622 // Sort the lights by distance from the camera
\r
623 core::vector3df camWorldPos(0, 0, 0);
\r
625 camWorldPos = ActiveCamera->getAbsolutePosition();
\r
627 core::array<DistanceNodeEntry> SortedLights;
\r
628 SortedLights.set_used(LightList.size());
\r
629 for (s32 light = (s32)LightList.size() - 1; light >= 0; --light)
\r
630 SortedLights[light].setNodeAndDistanceFromPosition(LightList[light], camWorldPos);
\r
632 SortedLights.set_sorted(false);
\r
633 SortedLights.sort();
\r
635 for(s32 light = (s32)LightList.size() - 1; light >= 0; --light)
\r
636 LightList[light] = SortedLights[light].Node;
\r
639 Driver->deleteAllDynamicLights();
\r
641 Driver->setAmbientLight(AmbientLight);
\r
643 u32 maxLights = LightList.size();
\r
646 maxLights = core::min_ ( Driver->getMaximalDynamicLightAmount(), maxLights);
\r
648 for (i=0; i< maxLights; ++i)
\r
649 LightList[i]->render();
\r
652 LightManager->OnRenderPassPostRender(CurrentRenderPass);
\r
657 CurrentRenderPass = ESNRP_SKY_BOX;
\r
658 Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRenderPass) != 0);
\r
662 LightManager->OnRenderPassPreRender(CurrentRenderPass);
\r
663 for (i=0; i<SkyBoxList.size(); ++i)
\r
665 ISceneNode* node = SkyBoxList[i];
\r
666 LightManager->OnNodePreRender(node);
\r
668 LightManager->OnNodePostRender(node);
\r
673 for (i=0; i<SkyBoxList.size(); ++i)
\r
674 SkyBoxList[i]->render();
\r
677 SkyBoxList.set_used(0);
\r
680 LightManager->OnRenderPassPostRender(CurrentRenderPass);
\r
683 // render default objects
\r
685 CurrentRenderPass = ESNRP_SOLID;
\r
686 Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRenderPass) != 0);
\r
688 SolidNodeList.sort(); // sort by textures
\r
692 LightManager->OnRenderPassPreRender(CurrentRenderPass);
\r
693 for (i=0; i<SolidNodeList.size(); ++i)
\r
695 ISceneNode* node = SolidNodeList[i].Node;
\r
696 LightManager->OnNodePreRender(node);
\r
698 LightManager->OnNodePostRender(node);
\r
703 for (i=0; i<SolidNodeList.size(); ++i)
\r
704 SolidNodeList[i].Node->render();
\r
707 SolidNodeList.set_used(0);
\r
710 LightManager->OnRenderPassPostRender(CurrentRenderPass);
\r
715 CurrentRenderPass = ESNRP_SHADOW;
\r
716 Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRenderPass) != 0);
\r
720 LightManager->OnRenderPassPreRender(CurrentRenderPass);
\r
721 for (i=0; i<ShadowNodeList.size(); ++i)
\r
723 ISceneNode* node = ShadowNodeList[i];
\r
724 LightManager->OnNodePreRender(node);
\r
726 LightManager->OnNodePostRender(node);
\r
731 for (i=0; i<ShadowNodeList.size(); ++i)
\r
732 ShadowNodeList[i]->render();
\r
735 if (!ShadowNodeList.empty())
\r
736 Driver->drawStencilShadow(true,ShadowColor, ShadowColor,
\r
737 ShadowColor, ShadowColor);
\r
739 ShadowNodeList.set_used(0);
\r
742 LightManager->OnRenderPassPostRender(CurrentRenderPass);
\r
745 // render transparent objects.
\r
747 CurrentRenderPass = ESNRP_TRANSPARENT;
\r
748 Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRenderPass) != 0);
\r
750 TransparentNodeList.sort(); // sort by distance from camera
\r
753 LightManager->OnRenderPassPreRender(CurrentRenderPass);
\r
755 for (i=0; i<TransparentNodeList.size(); ++i)
\r
757 ISceneNode* node = TransparentNodeList[i].Node;
\r
758 LightManager->OnNodePreRender(node);
\r
760 LightManager->OnNodePostRender(node);
\r
765 for (i=0; i<TransparentNodeList.size(); ++i)
\r
766 TransparentNodeList[i].Node->render();
\r
769 TransparentNodeList.set_used(0);
\r
772 LightManager->OnRenderPassPostRender(CurrentRenderPass);
\r
775 // render transparent effect objects.
\r
777 CurrentRenderPass = ESNRP_TRANSPARENT_EFFECT;
\r
778 Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRenderPass) != 0);
\r
780 TransparentEffectNodeList.sort(); // sort by distance from camera
\r
784 LightManager->OnRenderPassPreRender(CurrentRenderPass);
\r
786 for (i=0; i<TransparentEffectNodeList.size(); ++i)
\r
788 ISceneNode* node = TransparentEffectNodeList[i].Node;
\r
789 LightManager->OnNodePreRender(node);
\r
791 LightManager->OnNodePostRender(node);
\r
796 for (i=0; i<TransparentEffectNodeList.size(); ++i)
\r
797 TransparentEffectNodeList[i].Node->render();
\r
800 TransparentEffectNodeList.set_used(0);
\r
803 // render custom gui nodes
\r
805 CurrentRenderPass = ESNRP_GUI;
\r
806 Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRenderPass) != 0);
\r
810 LightManager->OnRenderPassPreRender(CurrentRenderPass);
\r
812 for (i=0; i<GuiNodeList.size(); ++i)
\r
814 ISceneNode* node = GuiNodeList[i];
\r
815 LightManager->OnNodePreRender(node);
\r
817 LightManager->OnNodePostRender(node);
\r
822 for (i=0; i<GuiNodeList.size(); ++i)
\r
823 GuiNodeList[i]->render();
\r
826 GuiNodeList.set_used(0);
\r
831 LightManager->OnPostRender();
\r
833 LightList.set_used(0);
\r
834 clearDeletionList();
\r
836 CurrentRenderPass = ESNRP_NONE;
\r
839 void CSceneManager::setLightManager(ILightManager* lightManager)
\r
842 lightManager->grab();
\r
844 LightManager->drop();
\r
846 LightManager = lightManager;
\r
850 //! Sets the color of stencil buffers shadows drawn by the scene manager.
\r
851 void CSceneManager::setShadowColor(video::SColor color)
\r
853 ShadowColor = color;
\r
857 //! Returns the current color of shadows.
\r
858 video::SColor CSceneManager::getShadowColor() const
\r
860 return ShadowColor;
\r
863 IShadowVolumeSceneNode* CSceneManager::createShadowVolumeSceneNode(const IMesh* shadowMesh, ISceneNode* parent, s32 id, bool zfailmethod, f32 infinity)
\r
865 #ifdef _IRR_COMPILE_WITH_SHADOW_VOLUME_SCENENODE_
\r
866 return new CShadowVolumeSceneNode(shadowMesh, parent, this, id, zfailmethod, infinity);
\r
874 //! Adds an external mesh loader.
\r
875 void CSceneManager::addExternalMeshLoader(IMeshLoader* externalLoader)
\r
877 if (!externalLoader)
\r
880 externalLoader->grab();
\r
881 MeshLoaderList.push_back(externalLoader);
\r
885 //! Returns the number of mesh loaders supported by Irrlicht at this time
\r
886 u32 CSceneManager::getMeshLoaderCount() const
\r
888 return MeshLoaderList.size();
\r
892 //! Retrieve the given mesh loader
\r
893 IMeshLoader* CSceneManager::getMeshLoader(u32 index) const
\r
895 if (index < MeshLoaderList.size())
\r
896 return MeshLoaderList[index];
\r
902 //! Returns a pointer to the scene collision manager.
\r
903 ISceneCollisionManager* CSceneManager::getSceneCollisionManager()
\r
905 return CollisionManager;
\r
909 //! Returns a pointer to the mesh manipulator.
\r
910 IMeshManipulator* CSceneManager::getMeshManipulator()
\r
912 return Driver->getMeshManipulator();
\r
916 //! Adds a scene node to the deletion queue.
\r
917 void CSceneManager::addToDeletionQueue(ISceneNode* node)
\r
923 DeletionList.push_back(node);
\r
927 //! clears the deletion list
\r
928 void CSceneManager::clearDeletionList()
\r
930 if (DeletionList.empty())
\r
933 for (u32 i=0; i<DeletionList.size(); ++i)
\r
935 DeletionList[i]->remove();
\r
936 DeletionList[i]->drop();
\r
939 DeletionList.clear();
\r
943 //! Returns the first scene node with the specified name.
\r
944 ISceneNode* CSceneManager::getSceneNodeFromName(const char* name, ISceneNode* start)
\r
947 start = getRootSceneNode();
\r
949 if (!strcmp(start->getName(),name))
\r
952 ISceneNode* node = 0;
\r
954 const ISceneNodeList& list = start->getChildren();
\r
955 ISceneNodeList::const_iterator it = list.begin();
\r
956 for (; it!=list.end(); ++it)
\r
958 node = getSceneNodeFromName(name, *it);
\r
967 //! Returns the first scene node with the specified id.
\r
968 ISceneNode* CSceneManager::getSceneNodeFromId(s32 id, ISceneNode* start)
\r
971 start = getRootSceneNode();
\r
973 if (start->getID() == id)
\r
976 ISceneNode* node = 0;
\r
978 const ISceneNodeList& list = start->getChildren();
\r
979 ISceneNodeList::const_iterator it = list.begin();
\r
980 for (; it!=list.end(); ++it)
\r
982 node = getSceneNodeFromId(id, *it);
\r
991 //! Returns the first scene node with the specified type.
\r
992 ISceneNode* CSceneManager::getSceneNodeFromType(scene::ESCENE_NODE_TYPE type, ISceneNode* start)
\r
995 start = getRootSceneNode();
\r
997 if (start->getType() == type || ESNT_ANY == type)
\r
1000 ISceneNode* node = 0;
\r
1002 const ISceneNodeList& list = start->getChildren();
\r
1003 ISceneNodeList::const_iterator it = list.begin();
\r
1004 for (; it!=list.end(); ++it)
\r
1006 node = getSceneNodeFromType(type, *it);
\r
1015 //! returns scene nodes by type.
\r
1016 void CSceneManager::getSceneNodesFromType(ESCENE_NODE_TYPE type, core::array<scene::ISceneNode*>& outNodes, ISceneNode* start)
\r
1019 start = getRootSceneNode();
\r
1021 if (start->getType() == type || ESNT_ANY == type)
\r
1022 outNodes.push_back(start);
\r
1024 const ISceneNodeList& list = start->getChildren();
\r
1025 ISceneNodeList::const_iterator it = list.begin();
\r
1027 for (; it!=list.end(); ++it)
\r
1029 getSceneNodesFromType(type, outNodes, *it);
\r
1034 //! Posts an input event to the environment. Usually you do not have to
\r
1035 //! use this method, it is used by the internal engine.
\r
1036 bool CSceneManager::postEventFromUser(const SEvent& event)
\r
1039 ICameraSceneNode* cam = getActiveCamera();
\r
1041 ret = cam->OnEvent(event);
\r
1047 //! Removes all children of this scene node
\r
1048 void CSceneManager::removeAll()
\r
1050 ISceneNode::removeAll();
\r
1051 setActiveCamera(0);
\r
1052 // Make sure the driver is reset, might need a more complex method at some point
\r
1054 Driver->setMaterial(video::SMaterial());
\r
1058 //! Clears the whole scene. All scene nodes are removed.
\r
1059 void CSceneManager::clear()
\r
1065 //! Returns interface to the parameters set in this scene.
\r
1066 io::IAttributes* CSceneManager::getParameters()
\r
1068 return Parameters;
\r
1072 //! Returns current render pass.
\r
1073 E_SCENE_NODE_RENDER_PASS CSceneManager::getSceneNodeRenderPass() const
\r
1075 return CurrentRenderPass;
\r
1079 //! Returns an interface to the mesh cache which is shared between all existing scene managers.
\r
1080 IMeshCache* CSceneManager::getMeshCache()
\r
1086 //! Creates a new scene manager.
\r
1087 ISceneManager* CSceneManager::createNewSceneManager(bool cloneContent)
\r
1089 CSceneManager* manager = new CSceneManager(Driver, CursorControl, MeshCache);
\r
1092 manager->cloneMembers(this, manager);
\r
1098 //! Sets ambient color of the scene
\r
1099 void CSceneManager::setAmbientLight(const video::SColorf &ambientColor)
\r
1101 AmbientLight = ambientColor;
\r
1105 //! Returns ambient color of the scene
\r
1106 const video::SColorf& CSceneManager::getAmbientLight() const
\r
1108 return AmbientLight;
\r
1112 //! Get a skinned mesh, which is not available as header-only code
\r
1113 ISkinnedMesh* CSceneManager::createSkinnedMesh()
\r
1115 return new CSkinnedMesh();
\r
1118 //! Returns a mesh writer implementation if available
\r
1119 IMeshWriter* CSceneManager::createMeshWriter(EMESH_WRITER_TYPE type)
\r
1125 // creates a scenemanager
\r
1126 ISceneManager* createSceneManager(video::IVideoDriver* driver, gui::ICursorControl* cursorcontrol)
\r
1128 return new CSceneManager(driver, cursorcontrol, nullptr);
\r
1132 } // end namespace scene
\r
1133 } // end namespace irr
\r