#include "IrrCompileConfig.h"
#include "CSceneManager.h"
#include "IVideoDriver.h"
#include "IFileSystem.h"
#include "SAnimatedMesh.h"
#include "CMeshCache.h"
#include "IXMLWriter.h"
#include "ISceneUserDataSerializer.h"
#include "IGUIEnvironment.h"
#include "IMaterialRenderer.h"
#include "IReadFile.h"
#include "IWriteFile.h"
#include "ISceneLoader.h"
#include "os.h"
#ifdef _IRR_COMPILE_WITH_IRR_MESH_LOADER_
#include "CIrrMeshFileLoader.h"
#endif
#ifdef _IRR_COMPILE_WITH_BSP_LOADER_
#include "CBSPMeshFileLoader.h"
#endif
#ifdef _IRR_COMPILE_WITH_MD2_LOADER_
#include "CMD2MeshFileLoader.h"
#endif
#ifdef _IRR_COMPILE_WITH_HALFLIFE_LOADER_
#include "CAnimatedMeshHalfLife.h"
#endif
#ifdef _IRR_COMPILE_WITH_MS3D_LOADER_
#include "CMS3DMeshFileLoader.h"
#endif
#ifdef _IRR_COMPILE_WITH_3DS_LOADER_
#include "C3DSMeshFileLoader.h"
#endif
#ifdef _IRR_COMPILE_WITH_X_LOADER_
#include "CXMeshFileLoader.h"
#endif
#ifdef _IRR_COMPILE_WITH_OCT_LOADER_
#include "COCTLoader.h"
#endif
#ifdef _IRR_COMPILE_WITH_CSM_LOADER_
#include "CCSMLoader.h"
#endif
#ifdef _IRR_COMPILE_WITH_LMTS_LOADER_
#include "CLMTSMeshFileLoader.h"
#endif
#ifdef _IRR_COMPILE_WITH_MY3D_LOADER_
#include "CMY3DMeshFileLoader.h"
#endif
#ifdef _IRR_COMPILE_WITH_COLLADA_LOADER_
#include "CColladaFileLoader.h"
#endif
#ifdef _IRR_COMPILE_WITH_DMF_LOADER_
#include "CDMFLoader.h"
#endif
#ifdef _IRR_COMPILE_WITH_OGRE_LOADER_
#include "COgreMeshFileLoader.h"
#endif
#ifdef _IRR_COMPILE_WITH_OBJ_LOADER_
#include "COBJMeshFileLoader.h"
#endif
#ifdef _IRR_COMPILE_WITH_MD3_LOADER_
#include "CMD3MeshFileLoader.h"
#endif
#ifdef _IRR_COMPILE_WITH_B3D_LOADER_
#include "CB3DMeshFileLoader.h"
#endif
#ifdef _IRR_COMPILE_WITH_LWO_LOADER_
#include "CLWOMeshFileLoader.h"
#endif
#ifdef _IRR_COMPILE_WITH_STL_LOADER_
#include "CSTLMeshFileLoader.h"
#endif
#ifdef _IRR_COMPILE_WITH_PLY_LOADER_
#include "CPLYMeshFileLoader.h"
#endif
#ifdef _IRR_COMPILE_WITH_IRR_SCENE_LOADER_
#include "CSceneLoaderIrr.h"
#endif
#ifdef _IRR_COMPILE_WITH_COLLADA_WRITER_
#include "CColladaMeshWriter.h"
#endif
#ifdef _IRR_COMPILE_WITH_IRR_WRITER_
#include "CIrrMeshWriter.h"
#endif
#ifdef _IRR_COMPILE_WITH_STL_WRITER_
#include "CSTLMeshWriter.h"
#endif
#ifdef _IRR_COMPILE_WITH_OBJ_WRITER_
#include "COBJMeshWriter.h"
#endif
#ifdef _IRR_COMPILE_WITH_PLY_WRITER_
#include "CPLYMeshWriter.h"
#endif
#include "CCubeSceneNode.h"
#include "CSphereSceneNode.h"
#include "CAnimatedMeshSceneNode.h"
#include "CCameraSceneNode.h"
#include "CLightSceneNode.h"
#include "CBillboardSceneNode.h"
#include "CMeshSceneNode.h"
#include "CSkyBoxSceneNode.h"
#include "CSkyDomeSceneNode.h"
#include "CParticleSystemSceneNode.h"
#include "CDummyTransformationSceneNode.h"
#include "CWaterSurfaceSceneNode.h"
#include "CTerrainSceneNode.h"
#include "CEmptySceneNode.h"
#include "CTextSceneNode.h"
#include "CVolumeLightSceneNode.h"
#include "CDefaultSceneNodeFactory.h"
#include "CSceneCollisionManager.h"
#include "CTriangleSelector.h"
#include "COctreeTriangleSelector.h"
#include "CTriangleBBSelector.h"
#include "CMetaTriangleSelector.h"
#include "CTerrainTriangleSelector.h"
#include "CSceneNodeAnimatorRotation.h"
#include "CSceneNodeAnimatorFlyCircle.h"
#include "CSceneNodeAnimatorFlyStraight.h"
#include "CSceneNodeAnimatorTexture.h"
#include "CSceneNodeAnimatorCollisionResponse.h"
#include "CSceneNodeAnimatorDelete.h"
#include "CSceneNodeAnimatorFollowSpline.h"
#include "CSceneNodeAnimatorCameraFPS.h"
#include "CSceneNodeAnimatorCameraMaya.h"
#include "CDefaultSceneNodeAnimatorFactory.h"
#include "CGeometryCreator.h"
#define SCENEMANAGER_DEBUG
namespace irr
{
namespace scene
{
CSceneManager::CSceneManager(video::IVideoDriver* driver, io::IFileSystem* fs,
gui::ICursorControl* cursorControl, IMeshCache* cache,
gui::IGUIEnvironment* gui)
: ISceneNode(0, 0), Driver(driver), FileSystem(fs), GUIEnvironment(gui),
CursorControl(cursorControl), CollisionManager(0),
ActiveCamera(0), ShadowColor(150,0,0,0), AmbientLight(0,0,0,0),
MeshCache(cache), CurrentRendertime(ESNRP_NONE),
IRR_XML_FORMAT_SCENE(L"irr_scene"), IRR_XML_FORMAT_NODE(L"node"), IRR_XML_FORMAT_NODE_ATTR_TYPE(L"type")
{
#ifdef _DEBUG
ISceneManager::setDebugName("CSceneManager ISceneManager");
ISceneNode::setDebugName("CSceneManager ISceneNode");
#endif
SceneManager = this;
Parameters.setAttribute( DEBUG_NORMAL_LENGTH, 1.f );
Parameters.setAttribute( DEBUG_NORMAL_COLOR, video::SColor(255, 34, 221, 221));
if (Driver)
Driver->grab();
if (FileSystem)
FileSystem->grab();
if (CursorControl)
CursorControl->grab();
if (GUIEnvironment)
GUIEnvironment->grab();
if (!MeshCache)
MeshCache = new CMeshCache();
else
MeshCache->grab();
CollisionManager = new CSceneCollisionManager(this, Driver);
GeometryCreator = new CGeometryCreator();
#ifdef _IRR_COMPILE_WITH_STL_LOADER_
MeshLoaderList.push_back(new CSTLMeshFileLoader());
#endif
#ifdef _IRR_COMPILE_WITH_PLY_LOADER_
MeshLoaderList.push_back(new CPLYMeshFileLoader());
#endif
#ifdef _IRR_COMPILE_WITH_OCT_LOADER_
MeshLoaderList.push_back(new COCTLoader(this, FileSystem));
#endif
#ifdef _IRR_COMPILE_WITH_CSM_LOADER_
MeshLoaderList.push_back(new CCSMLoader(this, FileSystem));
#endif
#ifdef _IRR_COMPILE_WITH_LMTS_LOADER_
MeshLoaderList.push_back(new CLMTSMeshFileLoader(FileSystem, Driver, &Parameters));
#endif
#ifdef _IRR_COMPILE_WITH_MY3D_LOADER_
MeshLoaderList.push_back(new CMY3DMeshFileLoader(this, FileSystem));
#endif
#ifdef _IRR_COMPILE_WITH_DMF_LOADER_
MeshLoaderList.push_back(new CDMFLoader(this, FileSystem));
#endif
#ifdef _IRR_COMPILE_WITH_OGRE_LOADER_
MeshLoaderList.push_back(new COgreMeshFileLoader(FileSystem, Driver));
#endif
#ifdef _IRR_COMPILE_WITH_HALFLIFE_LOADER_
MeshLoaderList.push_back(new CHalflifeMDLMeshFileLoader( this ));
#endif
#ifdef _IRR_COMPILE_WITH_MD3_LOADER_
MeshLoaderList.push_back(new CMD3MeshFileLoader( this));
#endif
#ifdef _IRR_COMPILE_WITH_LWO_LOADER_
MeshLoaderList.push_back(new CLWOMeshFileLoader(this, FileSystem));
#endif
#ifdef _IRR_COMPILE_WITH_MD2_LOADER_
MeshLoaderList.push_back(new CMD2MeshFileLoader());
#endif
#ifdef _IRR_COMPILE_WITH_IRR_MESH_LOADER_
MeshLoaderList.push_back(new CIrrMeshFileLoader(this, FileSystem));
#endif
#ifdef _IRR_COMPILE_WITH_BSP_LOADER_
MeshLoaderList.push_back(new CBSPMeshFileLoader(this, FileSystem));
#endif
#ifdef _IRR_COMPILE_WITH_COLLADA_LOADER_
MeshLoaderList.push_back(new CColladaFileLoader(this, FileSystem));
#endif
#ifdef _IRR_COMPILE_WITH_3DS_LOADER_
MeshLoaderList.push_back(new C3DSMeshFileLoader(this, FileSystem));
#endif
#ifdef _IRR_COMPILE_WITH_X_LOADER_
MeshLoaderList.push_back(new CXMeshFileLoader(this, FileSystem));
#endif
#ifdef _IRR_COMPILE_WITH_MS3D_LOADER_
MeshLoaderList.push_back(new CMS3DMeshFileLoader(Driver));
#endif
#ifdef _IRR_COMPILE_WITH_OBJ_LOADER_
MeshLoaderList.push_back(new COBJMeshFileLoader(this, FileSystem));
#endif
#ifdef _IRR_COMPILE_WITH_B3D_LOADER_
MeshLoaderList.push_back(new CB3DMeshFileLoader(this));
#endif
#ifdef _IRR_COMPILE_WITH_IRR_SCENE_LOADER_
SceneLoaderList.push_back(new CSceneLoaderIrr(this, FileSystem));
#endif
ISceneNodeFactory* factory = new CDefaultSceneNodeFactory(this);
registerSceneNodeFactory(factory);
factory->drop();
ISceneNodeAnimatorFactory* animatorFactory = new CDefaultSceneNodeAnimatorFactory(this, CursorControl);
registerSceneNodeAnimatorFactory(animatorFactory);
animatorFactory->drop();
}
CSceneManager::~CSceneManager()
{
clearDeletionList();
if (Driver)
Driver->removeAllHardwareBuffers();
if (FileSystem)
FileSystem->drop();
if (CursorControl)
CursorControl->drop();
if (CollisionManager)
CollisionManager->drop();
if (GeometryCreator)
GeometryCreator->drop();
if (GUIEnvironment)
GUIEnvironment->drop();
u32 i;
for (i=0; i<MeshLoaderList.size(); ++i)
MeshLoaderList[i]->drop();
for (i=0; i<SceneLoaderList.size(); ++i)
SceneLoaderList[i]->drop();
if (ActiveCamera)
ActiveCamera->drop();
ActiveCamera = 0;
if (MeshCache)
MeshCache->drop();
for (i=0; i<SceneNodeFactoryList.size(); ++i)
SceneNodeFactoryList[i]->drop();
for (i=0; i<SceneNodeAnimatorFactoryList.size(); ++i)
SceneNodeAnimatorFactoryList[i]->drop();
removeAll();
removeAnimators();
if (Driver)
Driver->drop();
}
IAnimatedMesh* CSceneManager::getMesh(const io::path& filename)
{
IAnimatedMesh* msh = MeshCache->getMeshByName(filename);
if (msh)
return msh;
io::IReadFile* file = FileSystem->createAndOpenFile(filename);
if (!file)
{
os::Printer::log("Could not load mesh, because file could not be opened: ", filename, ELL_ERROR);
return 0;
}
s32 count = MeshLoaderList.size();
for (s32 i=count-1; i>=0; --i)
{
if (MeshLoaderList[i]->isALoadableFileExtension(filename))
{
file->seek(0);
msh = MeshLoaderList[i]->createMesh(file);
if (msh)
{
MeshCache->addMesh(filename, msh);
msh->drop();
break;
}
}
}
file->drop();
if (!msh)
os::Printer::log("Could not load mesh, file format seems to be unsupported", filename, ELL_ERROR);
else
os::Printer::log("Loaded mesh", filename, ELL_INFORMATION);
return msh;
}
IAnimatedMesh* CSceneManager::getMesh(io::IReadFile* file)
{
if (!file)
return 0;
io::path name = file->getFileName();
IAnimatedMesh* msh = MeshCache->getMeshByName(file->getFileName());
if (msh)
return msh;
s32 count = MeshLoaderList.size();
for (s32 i=count-1; i>=0; --i)
{
if (MeshLoaderList[i]->isALoadableFileExtension(name))
{
file->seek(0);
msh = MeshLoaderList[i]->createMesh(file);
if (msh)
{
MeshCache->addMesh(file->getFileName(), msh);
msh->drop();
break;
}
}
}
if (!msh)
os::Printer::log("Could not load mesh, file format seems to be unsupported", file->getFileName(), ELL_ERROR);
else
os::Printer::log("Loaded mesh", file->getFileName(), ELL_INFORMATION);
return msh;
}
video::IVideoDriver* CSceneManager::getVideoDriver()
{
return Driver;
}
gui::IGUIEnvironment* CSceneManager::getGUIEnvironment()
{
return GUIEnvironment;
}
io::IFileSystem* CSceneManager::getFileSystem()
{
return FileSystem;
}
ITextSceneNode* CSceneManager::addTextSceneNode(gui::IGUIFont* font,
const wchar_t* text, video::SColor color, ISceneNode* parent,
const core::vector3df& position, s32 id)
{
if (!font)
return 0;
if (!parent)
parent = this;
ITextSceneNode* t = new CTextSceneNode(parent, this, id, font,
getSceneCollisionManager(), position, text, color);
t->drop();
return t;
}
IBillboardTextSceneNode* CSceneManager::addBillboardTextSceneNode(gui::IGUIFont* font,
const wchar_t* text, ISceneNode* parent,
const core::dimension2d<f32>& size,
const core::vector3df& position, s32 id,
video::SColor colorTop, video::SColor colorBottom)
{
if (!font && GUIEnvironment)
font = GUIEnvironment->getBuiltInFont();
if (!font)
return 0;
if (!parent)
parent = this;
IBillboardTextSceneNode* node = new CBillboardTextSceneNode(parent, this, id, font, text, position, size,
colorTop, colorBottom);
node->drop();
return node;
}
IVolumeLightSceneNode* CSceneManager::addVolumeLightSceneNode(
ISceneNode* parent, s32 id,
const u32 subdivU, const u32 subdivV,
const video::SColor foot, const video::SColor tail,
const core::vector3df& position, const core::vector3df& rotation, const core::vector3df& scale)
{
if (!parent)
parent = this;
IVolumeLightSceneNode* node = new CVolumeLightSceneNode(parent, this, id, subdivU, subdivV, foot, tail, position, rotation, scale);
node->drop();
return node;
}
IMeshSceneNode* CSceneManager::addCubeSceneNode(f32 size, ISceneNode* parent,
s32 id, const core::vector3df& position,
const core::vector3df& rotation, const core::vector3df& scale)
{
if (!parent)
parent = this;
IMeshSceneNode* node = new CCubeSceneNode(size, parent, this, id, position, rotation, scale);
node->drop();
return node;
}
IMeshSceneNode* CSceneManager::addSphereSceneNode(f32 radius, s32 polyCount,
ISceneNode* parent, s32 id, const core::vector3df& position,
const core::vector3df& rotation, const core::vector3df& scale)
{
if (!parent)
parent = this;
IMeshSceneNode* node = new CSphereSceneNode(radius, polyCount, polyCount, parent, this, id, position, rotation, scale);
node->drop();
return node;
}
IMeshSceneNode* CSceneManager::addMeshSceneNode(IMesh* mesh, ISceneNode* parent, s32 id,
const core::vector3df& position, const core::vector3df& rotation,
const core::vector3df& scale, bool alsoAddIfMeshPointerZero)
{
if (!alsoAddIfMeshPointerZero && !mesh)
return 0;
if (!parent)
parent = this;
IMeshSceneNode* node = new CMeshSceneNode(mesh, parent, this, id, position, rotation, scale);
node->drop();
return node;
}
ISceneNode* CSceneManager::addWaterSurfaceSceneNode(IMesh* mesh, f32 waveHeight, f32 waveSpeed, f32 waveLength,
ISceneNode* parent, s32 id, const core::vector3df& position,
const core::vector3df& rotation, const core::vector3df& scale)
{
if (!parent)
parent = this;
ISceneNode* node = new CWaterSurfaceSceneNode(waveHeight, waveSpeed, waveLength,
mesh, parent, this, id, position, rotation, scale);
node->drop();
return node;
}
IAnimatedMeshSceneNode* CSceneManager::addAnimatedMeshSceneNode(IAnimatedMesh* mesh, ISceneNode* parent, s32 id,
const core::vector3df& position, const core::vector3df& rotation,
const core::vector3df& scale, bool alsoAddIfMeshPointerZero)
{
if (!alsoAddIfMeshPointerZero && !mesh)
return 0;
if (!parent)
parent = this;
IAnimatedMeshSceneNode* node =
new CAnimatedMeshSceneNode(mesh, parent, this, id, position, rotation, scale);
node->drop();
return node;
}
ICameraSceneNode* CSceneManager::addCameraSceneNode(ISceneNode* parent,
const core::vector3df& position, const core::vector3df& lookat, s32 id,
bool makeActive)
{
if (!parent)
parent = this;
ICameraSceneNode* node = new CCameraSceneNode(parent, this, id, position, lookat);
if (makeActive)
setActiveCamera(node);
node->drop();
return node;
}
ICameraSceneNode* CSceneManager::addCameraSceneNodeMaya(ISceneNode* parent,
f32 rotateSpeed, f32 zoomSpeed, f32 translationSpeed, s32 id,
bool makeActive)
{
ICameraSceneNode* node = addCameraSceneNode(parent, core::vector3df(),
core::vector3df(0,0,100), id, makeActive);
if (node)
{
ISceneNodeAnimator* anm = new CSceneNodeAnimatorCameraMaya(CursorControl,
rotateSpeed, zoomSpeed, translationSpeed);
node->addAnimator(anm);
anm->drop();
}
return node;
}
ICameraSceneNode* CSceneManager::addCameraSceneNodeFPS(ISceneNode* parent,
f32 rotateSpeed, f32 moveSpeed, s32 id, SKeyMap* keyMapArray,
s32 keyMapSize, bool noVerticalMovement, f32 jumpSpeed,
bool invertMouseY, bool makeActive)
{
ICameraSceneNode* node = addCameraSceneNode(parent, core::vector3df(),
core::vector3df(0,0,100), id, makeActive);
if (node)
{
ISceneNodeAnimator* anm = new CSceneNodeAnimatorCameraFPS(CursorControl,
rotateSpeed, moveSpeed, jumpSpeed,
keyMapArray, keyMapSize, noVerticalMovement, invertMouseY);
node->bindTargetAndRotation(true);
node->addAnimator(anm);
anm->drop();
}
return node;
}
ILightSceneNode* CSceneManager::addLightSceneNode(ISceneNode* parent,
const core::vector3df& position, video::SColorf color, f32 range, s32 id)
{
if (!parent)
parent = this;
ILightSceneNode* node = new CLightSceneNode(parent, this, id, position, color, range);
node->drop();
return node;
}
IBillboardSceneNode* CSceneManager::addBillboardSceneNode(ISceneNode* parent,
const core::dimension2d<f32>& size, const core::vector3df& position, s32 id,
video::SColor colorTop, video::SColor colorBottom
)
{
if (!parent)
parent = this;
IBillboardSceneNode* node = new CBillboardSceneNode(parent, this, id, position, size,
colorTop, colorBottom);
node->drop();
return node;
}
ISceneNode* CSceneManager::addSkyBoxSceneNode(video::ITexture* top, video::ITexture* bottom,
video::ITexture* left, video::ITexture* right, video::ITexture* front,
video::ITexture* back, ISceneNode* parent, s32 id)
{
if (!parent)
parent = this;
ISceneNode* node = new CSkyBoxSceneNode(top, bottom, left, right,
front, back, parent, this, id);
node->drop();
return node;
}
ISceneNode* CSceneManager::addSkyDomeSceneNode(video::ITexture* texture,
u32 horiRes, u32 vertRes, f32 texturePercentage,f32 spherePercentage, f32 radius,
ISceneNode* parent, s32 id)
{
if (!parent)
parent = this;
ISceneNode* node = new CSkyDomeSceneNode(texture, horiRes, vertRes,
texturePercentage, spherePercentage, radius, parent, this, id);
node->drop();
return node;
}
IParticleSystemSceneNode* CSceneManager::addParticleSystemSceneNode(
bool withDefaultEmitter, ISceneNode* parent, s32 id,
const core::vector3df& position, const core::vector3df& rotation,
const core::vector3df& scale)
{
if (!parent)
parent = this;
IParticleSystemSceneNode* node = new CParticleSystemSceneNode(withDefaultEmitter,
parent, this, id, position, rotation, scale);
node->drop();
return node;
}
ITerrainSceneNode* CSceneManager::addTerrainSceneNode(
const io::path& heightMapFileName,
ISceneNode* parent, s32 id,
const core::vector3df& position,
const core::vector3df& rotation,
const core::vector3df& scale,
video::SColor vertexColor,
s32 maxLOD, E_TERRAIN_PATCH_SIZE patchSize, s32 smoothFactor,
bool addAlsoIfHeightmapEmpty)
{
io::IReadFile* file = FileSystem->createAndOpenFile(heightMapFileName);
if (!file && !addAlsoIfHeightmapEmpty)
{
os::Printer::log("Could not load terrain, because file could not be opened.",
heightMapFileName, ELL_ERROR);
return 0;
}
ITerrainSceneNode* terrain = addTerrainSceneNode(file, parent, id,
position, rotation, scale, vertexColor, maxLOD, patchSize,
smoothFactor, addAlsoIfHeightmapEmpty);
if (file)
file->drop();
return terrain;
}
ITerrainSceneNode* CSceneManager::addTerrainSceneNode(
io::IReadFile* heightMapFile,
ISceneNode* parent, s32 id,
const core::vector3df& position,
const core::vector3df& rotation,
const core::vector3df& scale,
video::SColor vertexColor,
s32 maxLOD, E_TERRAIN_PATCH_SIZE patchSize,
s32 smoothFactor,
bool addAlsoIfHeightmapEmpty)
{
if (!parent)
parent = this;
if (!heightMapFile && !addAlsoIfHeightmapEmpty)
{
os::Printer::log("Could not load terrain, because file could not be opened.", ELL_ERROR);
return 0;
}
CTerrainSceneNode* node = new CTerrainSceneNode(parent, this, FileSystem, id,
maxLOD, patchSize, position, rotation, scale);
if (!node->loadHeightMap(heightMapFile, vertexColor, smoothFactor))
{
if (!addAlsoIfHeightmapEmpty)
{
node->remove();
node->drop();
return 0;
}
}
node->drop();
return node;
}
ISceneNode* CSceneManager::addEmptySceneNode(ISceneNode* parent, s32 id)
{
if (!parent)
parent = this;
ISceneNode* node = new CEmptySceneNode(parent, this, id);
node->drop();
return node;
}
IDummyTransformationSceneNode* CSceneManager::addDummyTransformationSceneNode(
ISceneNode* parent, s32 id)
{
if (!parent)
parent = this;
IDummyTransformationSceneNode* node = new CDummyTransformationSceneNode(
parent, this, id);
node->drop();
return node;
}
IAnimatedMesh* CSceneManager::addHillPlaneMesh(const io::path& name,
const core::dimension2d<f32>& tileSize,
const core::dimension2d<u32>& tileCount,
video::SMaterial* material, f32 hillHeight,
const core::dimension2d<f32>& countHills,
const core::dimension2d<f32>& textureRepeatCount)
{
if (MeshCache->isMeshLoaded(name))
return MeshCache->getMeshByName(name);
IMesh* mesh = GeometryCreator->createHillPlaneMesh(tileSize,
tileCount, material, hillHeight, countHills,
textureRepeatCount);
if (!mesh)
return 0;
SAnimatedMesh* animatedMesh = new SAnimatedMesh();
if (!animatedMesh)
{
mesh->drop();
return 0;
}
animatedMesh->addMesh(mesh);
mesh->drop();
animatedMesh->recalculateBoundingBox();
MeshCache->addMesh(name, animatedMesh);
animatedMesh->drop();
return animatedMesh;
}
IAnimatedMesh* CSceneManager::addTerrainMesh(const io::path& name,
video::IImage* texture, video::IImage* heightmap,
const core::dimension2d<f32>& stretchSize,
f32 maxHeight,
const core::dimension2d<u32>& defaultVertexBlockSize)
{
if (MeshCache->isMeshLoaded(name))
return MeshCache->getMeshByName(name);
const bool debugBorders=false;
IMesh* mesh = GeometryCreator->createTerrainMesh(texture, heightmap,
stretchSize, maxHeight, getVideoDriver(),
defaultVertexBlockSize, debugBorders);
if (!mesh)
return 0;
SAnimatedMesh* animatedMesh = new SAnimatedMesh();
if (!animatedMesh)
{
mesh->drop();
return 0;
}
animatedMesh->addMesh(mesh);
mesh->drop();
animatedMesh->recalculateBoundingBox();
MeshCache->addMesh(name, animatedMesh);
animatedMesh->drop();
return animatedMesh;
}
IAnimatedMesh* CSceneManager::addArrowMesh(const io::path& name,
video::SColor vtxColor0, video::SColor vtxColor1,
u32 tesselationCylinder, u32 tesselationCone, f32 height,
f32 cylinderHeight, f32 width0,f32 width1)
{
if (MeshCache->isMeshLoaded(name))
return MeshCache->getMeshByName(name);
IMesh* mesh = GeometryCreator->createArrowMesh( tesselationCylinder,
tesselationCone, height, cylinderHeight, width0,width1,
vtxColor0, vtxColor1);
if (!mesh)
return 0;
SAnimatedMesh* animatedMesh = new SAnimatedMesh();
if (!animatedMesh)
{
mesh->drop();
return 0;
}
animatedMesh->addMesh(mesh);
mesh->drop();
animatedMesh->recalculateBoundingBox();
MeshCache->addMesh(name, animatedMesh);
animatedMesh->drop();
return animatedMesh;
}
IAnimatedMesh* CSceneManager::addSphereMesh(const io::path& name,
f32 radius, u32 polyCountX, u32 polyCountY)
{
if (MeshCache->isMeshLoaded(name))
return MeshCache->getMeshByName(name);
IMesh* mesh = GeometryCreator->createSphereMesh(radius, polyCountX, polyCountY);
if (!mesh)
return 0;
SAnimatedMesh* animatedMesh = new SAnimatedMesh();
if (!animatedMesh)
{
mesh->drop();
return 0;
}
animatedMesh->addMesh(mesh);
mesh->drop();
animatedMesh->recalculateBoundingBox();
MeshCache->addMesh(name, animatedMesh);
animatedMesh->drop();
return animatedMesh;
}
IAnimatedMesh* CSceneManager::addVolumeLightMesh(const io::path& name,
const u32 SubdivideU, const u32 SubdivideV,
const video::SColor FootColor, const video::SColor TailColor)
{
if (MeshCache->isMeshLoaded(name))
return MeshCache->getMeshByName(name);
IMesh* mesh = GeometryCreator->createVolumeLightMesh(SubdivideU, SubdivideV, FootColor, TailColor);
if (!mesh)
return 0;
SAnimatedMesh* animatedMesh = new SAnimatedMesh();
if (!animatedMesh)
{
mesh->drop();
return 0;
}
animatedMesh->addMesh(mesh);
mesh->drop();
animatedMesh->recalculateBoundingBox();
MeshCache->addMesh(name, animatedMesh);
animatedMesh->drop();
return animatedMesh;
}
ISceneNode* CSceneManager::getRootSceneNode()
{
return this;
}
ICameraSceneNode* CSceneManager::getActiveCamera() const
{
return ActiveCamera;
}
void CSceneManager::setActiveCamera(ICameraSceneNode* camera)
{
if (camera)
camera->grab();
if (ActiveCamera)
ActiveCamera->drop();
ActiveCamera = camera;
}
void CSceneManager::render()
{
}
const core::aabbox3d<f32>& CSceneManager::getBoundingBox() const
{
_IRR_DEBUG_BREAK_IF(true)
return *((core::aabbox3d<f32>*)0);
}
bool CSceneManager::isCulled(const ISceneNode* node) const
{
const ICameraSceneNode* cam = getActiveCamera();
if (!cam)
{
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
return false;
}
bool result = false;
if (node->getAutomaticCulling() & scene::EAC_OCC_QUERY)
{
result = (Driver->getOcclusionQueryResult(const_cast<ISceneNode*>(node))==0);
}
if (!result && (node->getAutomaticCulling() & scene::EAC_BOX))
{
core::aabbox3d<f32> tbox = node->getBoundingBox();
node->getAbsoluteTransformation().transformBoxEx(tbox);
result = !(tbox.intersectsWithBox(cam->getViewFrustum()->getBoundingBox() ));
}
if (!result && (node->getAutomaticCulling() & scene::EAC_FRUSTUM_SPHERE))
{
}
if (!result && (node->getAutomaticCulling() & scene::EAC_FRUSTUM_BOX))
{
SViewFrustum frust = *cam->getViewFrustum();
core::matrix4 invTrans(node->getAbsoluteTransformation(), core::matrix4::EM4CONST_INVERSE);
frust.transform(invTrans);
core::vector3df edges[8];
node->getBoundingBox().getEdges(edges);
for (s32 i=0; i<scene::SViewFrustum::VF_PLANE_COUNT; ++i)
{
bool boxInFrustum=false;
for (u32 j=0; j<8; ++j)
{
if (frust.planes[i].classifyPointRelation(edges[j]) != core::ISREL3D_FRONT)
{
boxInFrustum=true;
break;
}
}
if (!boxInFrustum)
{
result = true;
break;
}
}
}
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
return result;
}
u32 CSceneManager::registerNodeForRendering(ISceneNode* node, E_SCENE_NODE_RENDER_PASS pass)
{
u32 taken = 0;
switch(pass)
{
case ESNRP_CAMERA:
{
taken = 1;
for (u32 i = 0; i != CameraList.size(); ++i)
{
if (CameraList[i] == node)
{
taken = 0;
break;
}
}
if (taken)
{
CameraList.push_back(node);
}
}
break;
case ESNRP_LIGHT:
{
LightList.push_back(static_cast<ILightSceneNode*>(node));
taken = 1;
}
break;
case ESNRP_SKY_BOX:
SkyBoxList.push_back(node);
taken = 1;
break;
case ESNRP_SOLID:
if (!isCulled(node))
{
SolidNodeList.push_back(node);
taken = 1;
}
break;
case ESNRP_TRANSPARENT:
if (!isCulled(node))
{
TransparentNodeList.push_back(TransparentNodeEntry(node, camWorldPos));
taken = 1;
}
break;
case ESNRP_TRANSPARENT_EFFECT:
if (!isCulled(node))
{
TransparentEffectNodeList.push_back(TransparentNodeEntry(node, camWorldPos));
taken = 1;
}
break;
case ESNRP_AUTOMATIC:
if (!isCulled(node))
{
const u32 count = node->getMaterialCount();
taken = 0;
for (u32 i=0; i<count; ++i)
{
video::IMaterialRenderer* rnd =
Driver->getMaterialRenderer(node->getMaterial(i).MaterialType);
if (rnd && rnd->isTransparent())
{
TransparentNodeEntry e(node, camWorldPos);
TransparentNodeList.push_back(e);
taken = 1;
break;
}
}
if (!taken)
{
SolidNodeList.push_back(node);
taken = 1;
}
}
break;
case ESNRP_SHADOW:
if (!isCulled(node))
{
ShadowNodeList.push_back(node);
taken = 1;
}
break;
case ESNRP_NONE:
break;
}
#ifdef SCENEMANAGER_DEBUG
s32 index = Parameters.findAttribute ( "calls" );
Parameters.setAttribute ( index, Parameters.getAttributeAsInt ( index ) + 1 );
if (!taken)
{
index = Parameters.findAttribute ( "culled" );
Parameters.setAttribute ( index, Parameters.getAttributeAsInt ( index ) + 1 );
}
#endif
return taken;
}
void CSceneManager::drawAll()
{
if (!Driver)
return;
Parameters.setAttribute ( "culled", 0 );
Parameters.setAttribute ( "calls", 0 );
Parameters.setAttribute ( "drawn_solid", 0 );
Parameters.setAttribute ( "drawn_transparent", 0 );
Parameters.setAttribute ( "drawn_transparent_effect", 0 );
u32 i;
video::IVideoDriver* driver = getVideoDriver();
if (driver)
{
driver->setMaterial(video::SMaterial());
driver->setTransform ( video::ETS_PROJECTION, core::IdentityMatrix );
driver->setTransform ( video::ETS_VIEW, core::IdentityMatrix );
driver->setTransform ( video::ETS_WORLD, core::IdentityMatrix );
for (i=video::ETS_COUNT-1; i>=video::ETS_TEXTURE_0; --i)
driver->setTransform ( (video::E_TRANSFORMATION_STATE)i, core::IdentityMatrix );
}
driver->setAllowZWriteOnTransparent(Parameters.getAttributeAsBool( ALLOW_ZWRITE_ON_TRANSPARENT) );
OnAnimate(os::Timer::getTime());
camWorldPos.set(0,0,0);
if (ActiveCamera)
{
ActiveCamera->render();
camWorldPos = ActiveCamera->getAbsolutePosition();
}
OnRegisterSceneNode();
{
CurrentRendertime = ESNRP_CAMERA;
Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRendertime) != 0);
for (i=0; i<CameraList.size(); ++i)
CameraList[i]->render();
CameraList.set_used(0);
}
{
CurrentRendertime = ESNRP_LIGHT;
Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRendertime) != 0);
core::vector3df camWorldPos(0, 0, 0);
if (ActiveCamera)
camWorldPos = ActiveCamera->getAbsolutePosition();
core::array<DistanceNodeEntry> SortedLights;
SortedLights.set_used(LightList.size());
for (s32 light = (s32)LightList.size() - 1; light >= 0; --light)
SortedLights[light].setNodeAndDistanceFromPosition(LightList[light], camWorldPos);
SortedLights.set_sorted(false);
SortedLights.sort();
for(s32 light = (s32)LightList.size() - 1; light >= 0; --light)
LightList[light] = static_cast<ILightSceneNode*>(SortedLights[light].Node);
Driver->deleteAllDynamicLights();
Driver->setAmbientLight(AmbientLight);
u32 maxLights = LightList.size();
maxLights = core::min_ ( Driver->getMaximalDynamicLightAmount(), maxLights);
for (i=0; i< maxLights; ++i)
LightList[i]->render();
}
{
CurrentRendertime = ESNRP_SKY_BOX;
Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRendertime) != 0);
for (i=0; i<SkyBoxList.size(); ++i)
SkyBoxList[i]->render();
SkyBoxList.set_used(0);
}
{
CurrentRendertime = ESNRP_SOLID;
Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRendertime) != 0);
SolidNodeList.sort();
for (i=0; i<SolidNodeList.size(); ++i)
SolidNodeList[i].Node->render();
Parameters.setAttribute("drawn_solid", (s32) SolidNodeList.size() );
SolidNodeList.set_used(0);
}
{
CurrentRendertime = ESNRP_SHADOW;
Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRendertime) != 0);
for (i=0; i<ShadowNodeList.size(); ++i)
ShadowNodeList[i]->render();
if (!ShadowNodeList.empty())
Driver->drawStencilShadow(true,ShadowColor, ShadowColor,
ShadowColor, ShadowColor);
ShadowNodeList.set_used(0);
}
{
CurrentRendertime = ESNRP_TRANSPARENT;
Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRendertime) != 0);
TransparentNodeList.sort();
for (i=0; i<TransparentNodeList.size(); ++i)
TransparentNodeList[i].Node->render();
Parameters.setAttribute ( "drawn_transparent", (s32) TransparentNodeList.size() );
TransparentNodeList.set_used(0);
}
{
CurrentRendertime = ESNRP_TRANSPARENT_EFFECT;
Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRendertime) != 0);
TransparentEffectNodeList.sort();
for (i=0; i<TransparentEffectNodeList.size(); ++i)
TransparentEffectNodeList[i].Node->render();
Parameters.setAttribute ( "drawn_transparent_effect", (s32) TransparentEffectNodeList.size() );
TransparentEffectNodeList.set_used(0);
}
LightList.set_used(0);
clearDeletionList();
CurrentRendertime = ESNRP_NONE;
}
void CSceneManager::setShadowColor(video::SColor color)
{
ShadowColor = color;
}
video::SColor CSceneManager::getShadowColor() const
{
return ShadowColor;
}
ISceneNodeAnimator* CSceneManager::createRotationAnimator(const core::vector3df& rotationPerSecond)
{
ISceneNodeAnimator* anim = new CSceneNodeAnimatorRotation(os::Timer::getTime(),
rotationPerSecond);
return anim;
}
ISceneNodeAnimator* CSceneManager::createFlyCircleAnimator(
const core::vector3df& center, f32 radius, f32 speed,
const core::vector3df& direction,
f32 startPosition,
f32 radiusEllipsoid)
{
const f32 orbitDurationMs = (core::DEGTORAD * 360.f) / speed;
const u32 effectiveTime = os::Timer::getTime() + (u32)(orbitDurationMs * startPosition);
ISceneNodeAnimator* anim = new CSceneNodeAnimatorFlyCircle(
effectiveTime, center,
radius, speed, direction,radiusEllipsoid);
return anim;
}
ISceneNodeAnimator* CSceneManager::createFlyStraightAnimator(const core::vector3df& startPoint,
const core::vector3df& endPoint, u32 timeForWay, bool loop,bool pingpong)
{
ISceneNodeAnimator* anim = new CSceneNodeAnimatorFlyStraight(startPoint,
endPoint, timeForWay, loop, os::Timer::getTime(), pingpong);
return anim;
}
ISceneNodeAnimator* CSceneManager::createTextureAnimator(const core::array<video::ITexture*>& textures,
s32 timePerFrame, bool loop)
{
ISceneNodeAnimator* anim = new CSceneNodeAnimatorTexture(textures,
timePerFrame, loop, os::Timer::getTime());
return anim;
}
ISceneNodeAnimator* CSceneManager::createDeleteAnimator(u32 when)
{
return new CSceneNodeAnimatorDelete(this, os::Timer::getTime() + when);
}
ISceneNodeAnimatorCollisionResponse* CSceneManager::createCollisionResponseAnimator(
ITriangleSelector* world, ISceneNode* sceneNode, const core::vector3df& ellipsoidRadius,
const core::vector3df& gravityPerSecond,
const core::vector3df& ellipsoidTranslation, f32 slidingValue)
{
ISceneNodeAnimatorCollisionResponse* anim = new
CSceneNodeAnimatorCollisionResponse(this, world, sceneNode,
ellipsoidRadius, gravityPerSecond,
ellipsoidTranslation, slidingValue);
return anim;
}
ISceneNodeAnimator* CSceneManager::createFollowSplineAnimator(s32 startTime,
const core::array< core::vector3df >& points,
f32 speed, f32 tightness, bool loop, bool pingpong)
{
ISceneNodeAnimator* a = new CSceneNodeAnimatorFollowSpline(startTime, points,
speed, tightness, loop, pingpong);
return a;
}
void CSceneManager::addExternalMeshLoader(IMeshLoader* externalLoader)
{
if (!externalLoader)
return;
externalLoader->grab();
MeshLoaderList.push_back(externalLoader);
}
u32 CSceneManager::getMeshLoaderCount() const
{
return MeshLoaderList.size();
}
IMeshLoader* CSceneManager::getMeshLoader(u32 index) const
{
if (index < MeshLoaderList.size())
return MeshLoaderList[index];
else
return 0;
}
void CSceneManager::addExternalSceneLoader(ISceneLoader* externalLoader)
{
if (!externalLoader)
return;
externalLoader->grab();
SceneLoaderList.push_back(externalLoader);
}
u32 CSceneManager::getSceneLoaderCount() const
{
return SceneLoaderList.size();
}
ISceneLoader* CSceneManager::getSceneLoader(u32 index) const
{
if (index < SceneLoaderList.size())
return SceneLoaderList[index];
else
return 0;
}
ISceneCollisionManager* CSceneManager::getSceneCollisionManager()
{
return CollisionManager;
}
IMeshManipulator* CSceneManager::getMeshManipulator()
{
return Driver->getMeshManipulator();
}
ITriangleSelector* CSceneManager::createTriangleSelector(IMesh* mesh, ISceneNode* node)
{
if (!mesh)
return 0;
return new CTriangleSelector(mesh, node);
}
ITriangleSelector* CSceneManager::createTriangleSelector(IAnimatedMeshSceneNode* node)
{
if (!node || !node->getMesh())
return 0;
return new CTriangleSelector(node);
}
ITriangleSelector* CSceneManager::createTriangleSelectorFromBoundingBox(ISceneNode* node)
{
if (!node)
return 0;
return new CTriangleBBSelector(node);
}
ITriangleSelector* CSceneManager::createOctreeTriangleSelector(IMesh* mesh,
ISceneNode* node,
s32 minimalPolysPerNode)
{
if (!mesh)
return 0;
return new COctreeTriangleSelector(mesh, node, minimalPolysPerNode);
}
IMetaTriangleSelector* CSceneManager::createMetaTriangleSelector()
{
return new CMetaTriangleSelector();
}
ITriangleSelector* CSceneManager::createTerrainTriangleSelector(
ITerrainSceneNode* node, s32 LOD)
{
return new CTerrainTriangleSelector(node, LOD);
}
void CSceneManager::addToDeletionQueue(ISceneNode* node)
{
if (!node)
return;
node->grab();
DeletionList.push_back(node);
}
void CSceneManager::clearDeletionList()
{
if (DeletionList.empty())
return;
for (u32 i=0; i<DeletionList.size(); ++i)
{
DeletionList[i]->remove();
DeletionList[i]->drop();
}
DeletionList.clear();
}
ISceneNode* CSceneManager::getSceneNodeFromName(const char* name, ISceneNode* start)
{
if (start == 0)
start = getRootSceneNode();
if (!strcmp(start->getName(),name))
return start;
ISceneNode* node = 0;
const ISceneNodeList& list = start->getChildren();
ISceneNodeList::ConstIterator it = list.begin();
for (; it!=list.end(); ++it)
{
node = getSceneNodeFromName(name, *it);
if (node)
return node;
}
return 0;
}
ISceneNode* CSceneManager::getSceneNodeFromId(s32 id, ISceneNode* start)
{
if (start == 0)
start = getRootSceneNode();
if (start->getID() == id)
return start;
ISceneNode* node = 0;
const ISceneNodeList& list = start->getChildren();
ISceneNodeList::ConstIterator it = list.begin();
for (; it!=list.end(); ++it)
{
node = getSceneNodeFromId(id, *it);
if (node)
return node;
}
return 0;
}
ISceneNode* CSceneManager::getSceneNodeFromType(scene::ESCENE_NODE_TYPE type, ISceneNode* start)
{
if (start == 0)
start = getRootSceneNode();
if (start->getType() == type || ESNT_ANY == type)
return start;
ISceneNode* node = 0;
const ISceneNodeList& list = start->getChildren();
ISceneNodeList::ConstIterator it = list.begin();
for (; it!=list.end(); ++it)
{
node = getSceneNodeFromType(type, *it);
if (node)
return node;
}
return 0;
}
void CSceneManager::getSceneNodesFromType(ESCENE_NODE_TYPE type, core::array<scene::ISceneNode*>& outNodes, ISceneNode* start)
{
if (start == 0)
start = getRootSceneNode();
if (start->getType() == type || ESNT_ANY == type)
outNodes.push_back(start);
const ISceneNodeList& list = start->getChildren();
ISceneNodeList::ConstIterator it = list.begin();
for (; it!=list.end(); ++it)
{
getSceneNodesFromType(type, outNodes, *it);
}
}
bool CSceneManager::postEventFromUser(const SEvent& event)
{
bool ret = false;
ICameraSceneNode* cam = getActiveCamera();
if (cam)
ret = cam->OnEvent(event);
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
return ret;
}
void CSceneManager::removeAll()
{
ISceneNode::removeAll();
setActiveCamera(0);
if (Driver)
Driver->setMaterial(video::SMaterial());
}
void CSceneManager::clear()
{
removeAll();
}
io::IAttributes* CSceneManager::getParameters()
{
return &Parameters;
}
E_SCENE_NODE_RENDER_PASS CSceneManager::getSceneNodeRenderPass() const
{
return CurrentRendertime;
}
IMeshCache* CSceneManager::getMeshCache()
{
return MeshCache;
}
ISceneManager* CSceneManager::createNewSceneManager(bool cloneContent)
{
CSceneManager* manager = new CSceneManager(Driver, FileSystem, CursorControl, MeshCache, GUIEnvironment);
if (cloneContent)
manager->cloneMembers(this, manager);
return manager;
}
ISceneNodeFactory* CSceneManager::getDefaultSceneNodeFactory()
{
return getSceneNodeFactory(0);
}
void CSceneManager::registerSceneNodeFactory(ISceneNodeFactory* factoryToAdd)
{
if (factoryToAdd)
{
factoryToAdd->grab();
SceneNodeFactoryList.push_back(factoryToAdd);
}
}
u32 CSceneManager::getRegisteredSceneNodeFactoryCount() const
{
return SceneNodeFactoryList.size();
}
ISceneNodeFactory* CSceneManager::getSceneNodeFactory(u32 index)
{
if (index < SceneNodeFactoryList.size())
return SceneNodeFactoryList[index];
return 0;
}
ISceneNodeAnimatorFactory* CSceneManager::getDefaultSceneNodeAnimatorFactory()
{
return getSceneNodeAnimatorFactory(0);
}
void CSceneManager::registerSceneNodeAnimatorFactory(ISceneNodeAnimatorFactory* factoryToAdd)
{
if (factoryToAdd)
{
factoryToAdd->grab();
SceneNodeAnimatorFactoryList.push_back(factoryToAdd);
}
}
u32 CSceneManager::getRegisteredSceneNodeAnimatorFactoryCount() const
{
return SceneNodeAnimatorFactoryList.size();
}
ISceneNodeAnimatorFactory* CSceneManager::getSceneNodeAnimatorFactory(u32 index)
{
if (index < SceneNodeAnimatorFactoryList.size())
return SceneNodeAnimatorFactoryList[index];
return 0;
}
bool CSceneManager::saveScene(const io::path& filename, ISceneUserDataSerializer* userDataSerializer, ISceneNode* node)
{
bool ret = false;
io::IWriteFile* file = FileSystem->createAndWriteFile(filename);
if (file)
{
ret = saveScene(file, userDataSerializer, node);
file->drop();
}
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
return ret;
}
bool CSceneManager::saveScene(io::IWriteFile* file, ISceneUserDataSerializer* userDataSerializer, ISceneNode* node)
{
if (!file)
{
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
return false;
}
io::IXMLWriter* writer = FileSystem->createXMLWriter(file);
if (!writer)
{
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
return false;
}
if (!node)
node=this;
writer->writeXMLHeader();
writeSceneNode(writer, node, userDataSerializer, FileSystem->getFileDir(FileSystem->getAbsolutePath(file->getFileName())).c_str(), true);
writer->drop();
return true;
}
bool CSceneManager::loadScene(const io::path& filename, ISceneUserDataSerializer* userDataSerializer, ISceneNode* rootNode)
{
bool ret = false;
io::IReadFile* file = FileSystem->createAndOpenFile(filename);
if (!file)
{
os::Printer::log("Unable to open scene file", filename.c_str(), ELL_ERROR);
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
return false;
}
s32 i = SceneLoaderList.size()-1;
for (; i >= 0 && !ret; --i)
if (SceneLoaderList[i]->isALoadableFileExtension(filename))
ret = SceneLoaderList[i]->loadScene(file, userDataSerializer, rootNode);
if (!ret)
os::Printer::log("Could not load scene file, perhaps the format is unsupported: ", filename.c_str(), ELL_ERROR);
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
return ret;
}
bool CSceneManager::loadScene(io::IReadFile* file, ISceneUserDataSerializer* userDataSerializer, ISceneNode* rootNode)
{
if (!file)
{
os::Printer::log("Unable to open scene file", ELL_ERROR);
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
return false;
}
bool ret = false;
s32 i = SceneLoaderList.size()-1;
for (; i >= 0 && !ret; --i)
if (SceneLoaderList[i]->isALoadableFileFormat(file))
ret = SceneLoaderList[i]->loadScene(file, userDataSerializer, rootNode);
if (!ret)
os::Printer::log("Could not load scene file, perhaps the format is unsupported: ", file->getFileName().c_str(), ELL_ERROR);
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
return ret;
}
void CSceneManager::writeSceneNode(io::IXMLWriter* writer, ISceneNode* node, ISceneUserDataSerializer* userDataSerializer,
const c8* currentPath, bool init)
{
if (!writer || !node || node->isDebugObject())
return;
const wchar_t* name;
ISceneNode* tmpNode=node;
if (init)
{
name = IRR_XML_FORMAT_SCENE.c_str();
writer->writeElement(name, false);
node=this;
}
else
{
name = IRR_XML_FORMAT_NODE.c_str();
writer->writeElement(name, false, IRR_XML_FORMAT_NODE_ATTR_TYPE.c_str(),
core::stringw(getSceneNodeTypeName(node->getType())).c_str());
}
writer->writeLineBreak();
io::IAttributes* attr = FileSystem->createEmptyAttributes(Driver);
io::SAttributeReadWriteOptions options;
if (currentPath)
{
options.Filename=currentPath;
options.Flags|=io::EARWF_USE_RELATIVE_PATHS;
}
node->serializeAttributes(attr, &options);
if (attr->getAttributeCount() != 0)
{
attr->write(writer);
writer->writeLineBreak();
}
if (node->getMaterialCount() && getVideoDriver())
{
const wchar_t* materialElement = L"materials";
writer->writeElement(materialElement);
writer->writeLineBreak();
for (u32 i=0; i < node->getMaterialCount(); ++i)
{
io::IAttributes* tmp_attr =
getVideoDriver()->createAttributesFromMaterial(node->getMaterial(i));
tmp_attr->write(writer);
tmp_attr->drop();
}
writer->writeClosingTag(materialElement);
writer->writeLineBreak();
}
if (!node->getAnimators().empty())
{
const wchar_t* animatorElement = L"animators";
writer->writeElement(animatorElement);
writer->writeLineBreak();
ISceneNodeAnimatorList::ConstIterator it = node->getAnimators().begin();
for (; it != node->getAnimators().end(); ++it)
{
attr->clear();
attr->addString("Type", getAnimatorTypeName((*it)->getType()));
(*it)->serializeAttributes(attr);
attr->write(writer);
}
writer->writeClosingTag(animatorElement);
writer->writeLineBreak();
}
if (userDataSerializer)
{
io::IAttributes* userData = userDataSerializer->createUserData(node);
if (userData)
{
const wchar_t* userDataElement = L"userData";
writer->writeLineBreak();
writer->writeElement(userDataElement);
writer->writeLineBreak();
userData->write(writer);
writer->writeClosingTag(userDataElement);
writer->writeLineBreak();
writer->writeLineBreak();
userData->drop();
}
}
if (init)
node=tmpNode;
if (init && (node != this))
{
writeSceneNode(writer, node, userDataSerializer, currentPath);
}
else
{
ISceneNodeList::ConstIterator it = node->getChildren().begin();
for (; it != node->getChildren().end(); ++it)
writeSceneNode(writer, (*it), userDataSerializer, currentPath);
}
attr->drop();
writer->writeClosingTag(name);
writer->writeLineBreak();
writer->writeLineBreak();
}
const c8* CSceneManager::getSceneNodeTypeName(ESCENE_NODE_TYPE type)
{
const char* name = 0;
for (int i=(int)SceneNodeFactoryList.size()-1; !name && i>=0; --i)
name = SceneNodeFactoryList[i]->getCreateableSceneNodeTypeName(type);
return name;
}
ISceneNode* CSceneManager::addSceneNode(const char* sceneNodeTypeName, ISceneNode* parent)
{
ISceneNode* node = 0;
for (int i=(int)SceneNodeFactoryList.size()-1; i>=0 && !node; --i)
node = SceneNodeFactoryList[i]->addSceneNode(sceneNodeTypeName, parent);
return node;
}
const c8* CSceneManager::getAnimatorTypeName(ESCENE_NODE_ANIMATOR_TYPE type)
{
const char* name = 0;
for (s32 i=SceneNodeAnimatorFactoryList.size()-1; !name && i >= 0; --i)
name = SceneNodeAnimatorFactoryList[i]->getCreateableSceneNodeAnimatorTypeName(type);
return name;
}
void CSceneManager::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const
{
out->addString ("Name", Name.c_str());
out->addInt ("Id", ID );
out->addColorf ("AmbientLight", AmbientLight);
video::SColor color;
video::E_FOG_TYPE fogType;
f32 start, end, density;
bool pixelFog, rangeFog;
Driver->getFog(color, fogType, start, end, density, pixelFog, rangeFog);
out->addEnum("FogType", fogType, video::FogTypeNames);
out->addColorf("FogColor", color);
out->addFloat("FogStart", start);
out->addFloat("FogEnd", end);
out->addFloat("FogDensity", density);
out->addBool("FogPixel", pixelFog);
out->addBool("FogRange", rangeFog);
}
void CSceneManager::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)
{
Name = in->getAttributeAsString("Name");
ID = in->getAttributeAsInt("Id");
AmbientLight = in->getAttributeAsColorf("AmbientLight");
video::SColor color;
video::E_FOG_TYPE fogType;
f32 start, end, density;
bool pixelFog, rangeFog;
if (in->existsAttribute("FogType"))
{
fogType = (video::E_FOG_TYPE) in->getAttributeAsEnumeration("FogType", video::FogTypeNames);
color = in->getAttributeAsColorf("FogColor").toSColor();
start = in->getAttributeAsFloat("FogStart");
end = in->getAttributeAsFloat("FogEnd");
density = in->getAttributeAsFloat("FogDensity");
pixelFog = in->getAttributeAsBool("FogPixel");
rangeFog = in->getAttributeAsBool("FogRange");
Driver->setFog(color, fogType, start, end, density, pixelFog, rangeFog);
}
RelativeTranslation.set(0,0,0);
RelativeRotation.set(0,0,0);
RelativeScale.set(1,1,1);
IsVisible = true;
AutomaticCullingState = scene::EAC_BOX;
DebugDataVisible = scene::EDS_OFF;
IsDebugObject = false;
updateAbsolutePosition();
}
void CSceneManager::setAmbientLight(const video::SColorf &ambientColor)
{
AmbientLight = ambientColor;
}
const video::SColorf& CSceneManager::getAmbientLight() const
{
return AmbientLight;
}
ISkinnedMesh* CSceneManager::createSkinnedMesh()
{
#ifdef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_
return new CSkinnedMesh();
#else
return 0;
#endif
}
IMeshWriter* CSceneManager::createMeshWriter(EMESH_WRITER_TYPE type)
{
switch(type)
{
case EMWT_IRR_MESH:
#ifdef _IRR_COMPILE_WITH_IRR_WRITER_
return new CIrrMeshWriter(Driver, FileSystem);
#else
return 0;
#endif
case EMWT_COLLADA:
#ifdef _IRR_COMPILE_WITH_COLLADA_WRITER_
return new CColladaMeshWriter(Driver, FileSystem);
#else
return 0;
#endif
case EMWT_STL:
#ifdef _IRR_COMPILE_WITH_STL_WRITER_
return new CSTLMeshWriter(this);
#else
return 0;
#endif
case EMWT_OBJ:
#ifdef _IRR_COMPILE_WITH_OBJ_WRITER_
return new COBJMeshWriter(this, FileSystem);
#else
return 0;
#endif
case EMWT_PLY:
#ifdef _IRR_COMPILE_WITH_PLY_WRITER_
return new CPLYMeshWriter();
#else
return 0;
#endif
}
return 0;
}
ISceneManager* createSceneManager(video::IVideoDriver* driver,
io::IFileSystem* fs, gui::ICursorControl* cursorcontrol,
gui::IGUIEnvironment *guiEnvironment)
{
return new CSceneManager(driver, fs, cursorcontrol, 0, guiEnvironment );
}
}
}