diff --git a/examples/08.SpecialFX/main.cpp b/examples/08.SpecialFX/main.cpp index 5ac743e9..dcfc1645 100644 --- a/examples/08.SpecialFX/main.cpp +++ b/examples/08.SpecialFX/main.cpp @@ -214,6 +214,21 @@ int main() anode->setPosition(core::vector3df(-50,20,-60)); anode->setAnimationSpeed(15); + //volumetric lighting + scene::ISceneNode * n = smgr->addVolumeLightSceneNode(NULL, -1, + 32, //Sub Divid U + 32, //Sub Divid V + video::SColor(0, 180, 180, 180), //foot colour + video::SColor(0, 0, 0, 0) //tail colour + ); + + if (n) { + n->setScale(core::vector3df(56.0f, 56.0f, 56.0f)); + n->setPosition(core::vector3df(-120,60,40)); + video::SMaterial& mat = n->getMaterial(0); + mat.setTexture(0, smgr->getVideoDriver()->getTexture("../../media/lightFalloff.png")); + } + // add shadow anode->addShadowVolumeSceneNode(); smgr->setShadowColor(video::SColor(150,0,0,0)); diff --git a/include/ISceneManager.h b/include/ISceneManager.h index d17b32cf..d5790824 100644 --- a/include/ISceneManager.h +++ b/include/ISceneManager.h @@ -1,1225 +1,1250 @@ -// Copyright (C) 2002-2007 Nikolaus Gebhardt -// This file is part of the "Irrlicht Engine". -// For conditions of distribution and use, see copyright notice in irrlicht.h - -#ifndef __I_SCENE_MANAGER_H_INCLUDED__ -#define __I_SCENE_MANAGER_H_INCLUDED__ - -#include "IReferenceCounted.h" -#include "irrArray.h" -#include "vector3d.h" -#include "dimension2d.h" -#include "SColor.h" -#include "ETerrainElements.h" -#include "ESceneNodeTypes.h" -#include "EMeshWriterEnums.h" -#include "SceneParameters.h" - -namespace irr -{ - struct SKeyMap; - struct SEvent; - -namespace io -{ - class IReadFile; - class IAttributes; - class IWriteFile; -} // end namespace io - -namespace gui -{ - class IGUIFont; - class IGUIEnvironment; -} // end namespace gui - -namespace video -{ - class IVideoDriver; - class SMaterial; - class IImage; - class ITexture; -} // end namespace video - -namespace scene -{ - class IMeshWriter; - - //! Enumeration for render passes. - /** A parameter passed to the registerNodeForRendering() method of the ISceneManager, - specifying when the mode wants to be drawn in relation to the other nodes. */ - enum E_SCENE_NODE_RENDER_PASS - { - //! Camera pass. The active view is set up here. - //! The very first pass. - ESNRP_CAMERA, - - //! In this pass, lights are transformed into camera space and added to the driver - ESNRP_LIGHT, - - //! This is used for sky boxes. - ESNRP_SKY_BOX, - - //! All normal objects can use this for registering themselves. - //! This value will never be returned by ISceneManager::getSceneNodeRenderPass(). - //! The scene manager will determine by itself if an object is - //! transparent or solid and register the object as SNRT_TRANSPARENT or - //! SNRT_SOLD automatically if you call registerNodeForRendering with this - //! value (which is default). Note that it will register the node only as ONE type. - //! If your scene node has both solid and transparent material types register - //! it twice (one time as SNRT_SOLID, the other time as SNRT_TRANSPARENT) and - //! in the render() method call getSceneNodeRenderPass() to find out the current - //! render pass and render only the corresponding parts of the node. - ESNRP_AUTOMATIC, - - //! Solid scene nodes or special scene nodes without materials. - ESNRP_SOLID, - - //! Drawn after the transparent nodes, the time for drawing shadow volumes - ESNRP_SHADOW, - - //! Transparent scene nodes, drawn after shadow nodes. They are sorted from back - //! to front and drawn in that order. - ESNRP_TRANSPARENT, - - //! Never used, value specifing how much parameters there are. - ESNRP_COUNT - }; - - class IMesh; - class IMeshBuffer; - class IAnimatedMesh; - class IMeshCache; - class ISceneNode; - class ICameraSceneNode; - class IAnimatedMeshSceneNode; - class ISceneNodeAnimator; - class ISceneNodeAnimatorCollisionResponse; - class ILightSceneNode; - class IBillboardSceneNode; - class ITerrainSceneNode; - class IMeshSceneNode; - class IMeshLoader; - class ISceneCollisionManager; - class IParticleSystemSceneNode; - class IDummyTransformationSceneNode; - class ITriangleSelector; - class IMetaTriangleSelector; - class IMeshManipulator; - class ITextSceneNode; - class ISceneNodeFactory; - class ISceneNodeAnimatorFactory; - class ISceneUserDataSerializer; - - namespace quake3 - { - class SShader; - } // end namespace quake3 - - //! The Scene Manager manages scene nodes, mesh recources, cameras and all the other stuff. - /** All Scene nodes can be created only here. There is a always growing list of scene - nodes for lots of purposes: Indoor rendering scene nodes like the Octree - (addOctTreeSceneNode()) or the terrain renderer (addTerrainSceneNode()), - different Camera scene nodes (addCameraSceneNode(), addCameraSceneNodeMaya()), - scene nodes for Light (addLightSceneNode()), Billboards (addBillboardSceneNode()) - and so on. - A scene node is a node in the hierachical scene graph. Every scene node may have children, - which are other scene nodes. Children move relative the their parents position. If the parent of a node is not - visible, its children won't be visible, too. In this way, it is for example easily possible - to attach a light to a moving car or to place a walking character on a moving platform - on a moving ship. - The SceneManager is also able to load 3d mesh files of different formats. Take a look - at getMesh() to find out what formats are supported. And if these formats are not enough - use addExternalMeshLoader() to add new formats to the engine. - */ - class ISceneManager : public virtual IReferenceCounted - { - public: - - //! destructor - virtual ~ISceneManager() {} - - //! Returns pointer to an animateable mesh. Loads the file if not loaded already. - /** - * If you want to remove a loaded mesh from the cache again, use removeMesh(). - * Currently there are the following mesh formats supported: - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
FormatDescription
3D Studio (.3ds)Loader for 3D-Studio files which lots of 3D packages are able to export. - * Only static meshes are currently supported by this importer.
Bliz Basic B3D (.b3d)Loader for blitz basic files, developed by Mark Sibly, also supports animations.
Cartography shop 4 (.csm)Cartography Shop is a modeling program for creating architecture and calculating - * lighting. Irrlicht can directly import .csm files thanks to the IrrCSM library - * created by Saurav Mohapatra which is now integrated directly in Irrlicht. - * If you are using this loader, please note that you'll have to set the path - * of the textures before loading .csm files. You can do this using SceneManager->getParameters()->setParameter(scene::CSM_TEXTURE_PATH, - * "path/to/your/textures");
COLLADA (.dae, .xml)COLLADA is an open Digital Asset Exchange Schema for the interactive 3D industry. There are - * exporters and importers for this format available for most of the big 3d packages - * at http://collada.org. Irrlicht can import COLLADA files by using the - * ISceneManager::getMesh() method. COLLADA files need not contain only one single mesh - * but multiple meshes and a whole scene setup with lights, cameras and mesh instances, - * this loader can set up a scene as described by the COLLADA file instead of loading - * and returning one single mesh. By default, this loader behaves like the other loaders - * and does not create instances, but it can be switched into this mode by using - * SceneManager->getParameters()->setParameter(COLLADA_CREATE_SCENE_INSTANCES, true); - * Created scene nodes will be named as the names of the nodes in the - * COLLADA file. The returned mesh is just a dummy object in this mode. Meshes included in - * the scene will be added into the scene manager with the following naming scheme: - * path/to/file/file.dea#meshname. The loading of such meshes is logged. - * Currently, this loader is able to create meshes (made of only polygons), lights, - * and cameras. Materials and animations are currently not supported but this will - * change with future releases. - *
Delgine DeleD (.dmf)DeleD (delgine.com) is a 3D editor and level-editor combined into one and is specifically - * designed for 3D game-development. With this loader, it is possible to directly load - * all geometry is as well as textures and lightmaps from .dmf files. To set texture and - * material paths, see scene::DMF_USE_MATERIALS_DIRS and scene::DMF_TEXTURE_PATH. It is also - * possible to flip the alpha texture by setting scene::DMF_FLIP_ALPHA_TEXTURES to true and - * to set the material transparent reference value by setting scene::DMF_ALPHA_CHANNEL_REF to - * a float between 0 and 1. The loader is - * based on Salvatore Russo's .dmf loader, I just changed some parts of it. Thanks to - * Salvatore for his work and for allowing me to use his code in Irrlicht and put it under Irrlicht's - * license. For newer and more enchanced versions of the loader, take a look at delgine.com. - *
DirectX (.x)Platform independent importer (so not D3D-only) for .x files. Most 3D - * packages can export these natively and there are several tools for them - * available. (e.g. the Maya exporter included in the DX SDK) .x files can - * include skeletal animations and Irrlicht is able to play and display them. - * Currently, Irrlicht only supports uncompressed .x files.
Maya (.obj)Most 3D software can create .obj files which contain static geometry without - * material data. The material files .mtl are also supported. This importer - * for Irrlicht can load them directly.
Milkshape (.ms3d).MS3D files contain models and sometimes skeletal animations from the - * Milkshape 3D modeling and animation software. This importer for Irrlicht - * can display and/or animate these files.
My3D (.my3d).my3D is a flexible 3D file format. The My3DTools contains plug-ins to - * export .my3D files from several 3D packages. With this built-in importer, - * Irrlicht can read and display those files directly. This loader was written - * by Zhuck Dimitry who also created the whole My3DTools package. If you are using this loader, please - * note that you can set the path of the textures before loading .my3d files. - * You can do this using SceneManager->getParameters()->setParameter(scene::MY3D_TEXTURE_PATH, - * "path/to/your/textures");
OCT (.oct)The oct file format contains 3D geometry and lightmaps and can be loaded - * directly by Irrlicht. OCT files
- * can be created by FSRad, Paul Nette's radiosity processor or exported from - * Blender using OCTTools which can be found in the exporters/OCTTools directory - * of the SDK. Thanks to Murphy McCauley for creating all this.
OGRE Meshes (.mesh)Ogre .mesh files contain 3D data for the OGRE 3D engine. Irrlicht can read and - * display them directly with this importer. To define materials for the mesh, - * copy a .material file named like the corresponding .mesh file where the .mesh - * file is. (For example ogrehead.material for ogrehead.mesh). Thanks to Christian Stehno - * who wrote and contributed this loader.
Pulsar LMTools (.lmts)LMTools is a set of tools (Windows & Linux) for creating lightmaps. - * Irrlicht can directly read .lmts files thanks to
- * the importer created by Jonas Petersen. If you are using this loader, please - * note that you can set the path of the textures before loading .lmts files. - * You can do this using SceneManager->getParameters()->setParameter(scene::LMTS_TEXTURE_PATH, - * "path/to/your/textures"); Notes for
- * this version of the loader:
- * - It does not recognice/support user data in the *.lmts files.
- * - The TGAs generated by LMTools don't work in Irrlicht for some reason (the - * textures are upside down). Opening and resaving them in a graphics app will - * solve the problem.
Quake 3 levels (.bsp)Quake 3 is a popular game by IDSoftware, and .pk3 files contain .bsp files - * and textures/lightmaps describing huge
- * prelighted levels. Irrlicht can read .pk3 and .bsp files directly and thus - * render Quake 3 levels directly. Written by Nikolaus Gebhardt enhanced by - * Dean P. Macri with the curved surfaces feature.
Quake 2 models (.md2)Quake 2 models are characters with morph target animation. Irrlicht can - * read, display and animate them directly with this importer.
- * - * To load and display a mesh quickly, just do this: - * \code - * SceneManager->addAnimatedMeshSceneNode( - * SceneManager->getMesh("yourmesh.3ds")); - * \endcode - * If you would like to implement and add your own file format loader to Irrlicht, - * see addExternalMeshLoader(). - * \param filename: Filename of the mesh to load. - * \return Returns NULL if failed and the pointer to the mesh if - * successful. - * This pointer should not be dropped. See IReferenceCounted::drop() for more information. - **/ - virtual IAnimatedMesh* getMesh(const c8* filename) = 0; - - //! Returns an interface to the mesh cache which is shared beween all existing scene managers. - /** With this interface, it is possible to manually add new loaded - meshes (if ISceneManager::getMesh() is not sufficient), to remove them and to iterate - through already loaded meshes. */ - virtual IMeshCache* getMeshCache() = 0; - - //! Returns the video driver. - /** \return Returns pointer to the video Driver. - This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ - virtual video::IVideoDriver* getVideoDriver() = 0; - - //! Returns the active GUIEnvironment - /** \return Returns pointer to the GUIEnvironment - This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ - virtual gui::IGUIEnvironment* getGUIEnvironment() = 0; - - //! Adds a test scene node for test purposes to the scene. - /** It is a simple cube of (1,1,1) size. - \param size: Size of the cube. - \param parent: Parent of the scene node. Can be NULL if no parent. - \param id: Id of the node. This id can be used to identify the scene node. - \param position: Position of the space relative to its parent where the - scene node will be placed. - \param rotation: Initital rotation of the scene node. - \param scale: Initial scale of the scene node. - \return Returns pointer to the created test scene node. - This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ - virtual ISceneNode* addCubeSceneNode(f32 size=10.0f, ISceneNode* parent=0, s32 id=-1, - const core::vector3df& position = core::vector3df(0,0,0), - const core::vector3df& rotation = core::vector3df(0,0,0), - const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)) = 0; - - //! Adds a sphere scene node for test purposes to the scene. - /** It is a simple sphere. - \param radius: Radius of the sphere. - \param polyCount: Polycount of the sphere. - \param parent: Parent of the scene node. Can be NULL if no parent. - \param id: Id of the node. This id can be used to identify the scene node. - \param position: Position of the space relative to its parent where the - scene node will be placed. - \param rotation: Initital rotation of the scene node. - \param scale: Initial scale of the scene node. - \return Returns pointer to the created test scene node. - This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ - virtual ISceneNode* addSphereSceneNode(f32 radius=5.0f, s32 polyCount=16, ISceneNode* parent=0, s32 id=-1, - const core::vector3df& position = core::vector3df(0,0,0), - const core::vector3df& rotation = core::vector3df(0,0,0), - const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)) = 0; - - //! Adds a scene node for rendering an animated mesh model. - /** \param mesh: Pointer to the loaded animated mesh to be displayed. - \param parent: Parent of the scene node. Can be NULL if no parent. - \param id: Id of the node. This id can be used to identify the scene node. - \param position: Position of the space relative to its parent where the - scene node will be placed. - \param rotation: Initital rotation of the scene node. - \param scale: Initial scale of the scene node. - \param alsoAddIfMeshPointerZero: Add the scene node even if a 0 pointer is passed. - \return Returns pointer to the created scene node. - This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ - virtual IAnimatedMeshSceneNode* addAnimatedMeshSceneNode(IAnimatedMesh* mesh, ISceneNode* parent=0, s32 id=-1, - const core::vector3df& position = core::vector3df(0,0,0), - const core::vector3df& rotation = core::vector3df(0,0,0), - const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f), - bool alsoAddIfMeshPointerZero=false) = 0; - - //! Adds a scene node for rendering a static mesh. - /** \param mesh: Pointer to the loaded static mesh to be displayed. - \param parent: Parent of the scene node. Can be NULL if no parent. - \param id: Id of the node. This id can be used to identify the scene node. - \param position: Position of the space relative to its parent where the - scene node will be placed. - \param rotation: Initital rotation of the scene node. - \param scale: Initial scale of the scene node. - \param alsoAddIfMeshPointerZero: Add the scene node even if a 0 pointer is passed. - \return Returns pointer to the created scene node. - This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ - virtual IMeshSceneNode* addMeshSceneNode(IMesh* mesh, ISceneNode* parent=0, s32 id=-1, - const core::vector3df& position = core::vector3df(0,0,0), - const core::vector3df& rotation = core::vector3df(0,0,0), - const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f), - bool alsoAddIfMeshPointerZero=false) = 0; - - //! Adds a scene node for rendering a animated water surface mesh. - /** Looks really good when the Material type EMT_TRANSPARENT_REFLECTION - is used. - \param waveHeight: Height of the water waves. - \param waveSpeed: Speed of the water waves. - \param waveLength: Lenght of a water wave. - \param mesh: Pointer to the loaded static mesh to be displayed with water waves on it. - \param parent: Parent of the scene node. Can be NULL if no parent. - \param id: Id of the node. This id can be used to identify the scene node. - \param position: Position of the space relative to its parent where the - scene node will be placed. - \param rotation: Initital rotation of the scene node. - \param scale: Initial scale of the scene node. - \return Returns pointer to the created scene node. - This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ - virtual ISceneNode* addWaterSurfaceSceneNode(IMesh* mesh, - f32 waveHeight=2.0f, f32 waveSpeed=300.0f, f32 waveLength=10.0f, - ISceneNode* parent=0, s32 id=-1, - const core::vector3df& position = core::vector3df(0,0,0), - const core::vector3df& rotation = core::vector3df(0,0,0), - const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)) = 0; - - - //! Adds a scene node for rendering using a octtree to the scene graph. - /** This a good method for rendering - scenes with lots of geometry. The Octree is built on the fly from the mesh. - \param mesh: The mesh containing all geometry from which the octtree will be build. - If this animated mesh has more than one frames in it, the first frame is taken. - \param parent: Parent node of the octtree node. - \param id: id of the node. This id can be used to identify the node. - \param minimalPolysPerNode: Specifies the minimal polygons contained a octree node. - If a node gets less polys than this value it will not be split into - smaller nodes. - \param alsoAddIfMeshPointerZero: Add the scene node even if a 0 pointer is passed. - \return Returns the pointer to the OctTree if successful, otherwise 0. - This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ - virtual ISceneNode* addOctTreeSceneNode(IAnimatedMesh* mesh, ISceneNode* parent=0, - s32 id=-1, s32 minimalPolysPerNode=256, bool alsoAddIfMeshPointerZero=false) = 0; - - //! Adds a scene node for rendering using a octtree to the scene graph. - /** This a good method for rendering - scenes with lots of geometry. The Octree is built on the fly from the mesh, much - faster then a bsp tree. - \param mesh: The mesh containing all geometry from which the octtree will be build. - \param parent: Parent node of the octtree node. - \param id: id of the node. This id can be used to identify the node. - \param minimalPolysPerNode: Specifies the minimal polygons contained a octree node. - If a node gets less polys than this value it will not be split into - smaller nodes. - \param alsoAddIfMeshPointerZero: Add the scene node even if a 0 pointer is passed. - \return Returns the pointer to the octtree if successful, otherwise 0. - This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ - virtual ISceneNode* addOctTreeSceneNode(IMesh* mesh, ISceneNode* parent=0, - s32 id=-1, s32 minimalPolysPerNode=256, bool alsoAddIfMeshPointerZero=false) = 0; - - //! Adds a camera scene node to the scene graph and sets it as active camera. - /** This camera does not react on user input like for example the one created with - addCameraSceneNodeFPS(). If you want to move or animate it, use animators or the - ISceneNode::setPosition(), ICameraSceneNode::setTarget() etc methods. - \param position: Position of the space relative to its parent where the camera will be placed. - \param lookat: Position where the camera will look at. Also known as target. - \param parent: Parent scene node of the camera. Can be null. If the parent moves, - the camera will move too. - \param id: id of the camera. This id can be used to identify the camera. - \return Returns pointer to interface to camera if successful, otherwise 0. - This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ - virtual ICameraSceneNode* addCameraSceneNode(ISceneNode* parent = 0, - const core::vector3df& position = core::vector3df(0,0,0), - const core::vector3df& lookat = core::vector3df(0,0,100), s32 id=-1) = 0; - - //! Adds a maya style user controlled camera scene node to the scene graph. - /** The maya camera is able to be controlled with the mouse similar - like in the 3D Software Maya by Alias Wavefront. - \param parent: Parent scene node of the camera. Can be null. - \param rotateSpeed: Rotation speed of the camera. - \param zoomSpeed: Zoom speed of the camera. - \param translationSpeed: TranslationSpeed of the camera. - \param id: id of the camera. This id can be used to identify the camera. - \return Returns a pointer to the interface of the camera if successful, otherwise 0. - This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ - virtual ICameraSceneNode* addCameraSceneNodeMaya(ISceneNode* parent = 0, - f32 rotateSpeed = -1500.0f, f32 zoomSpeed = 200.0f, f32 translationSpeed = 1500.0f, s32 id=-1) = 0; - - //! Adds a camera scene node which is able to be controlled with the mouse and keys like in most first person shooters (FPS). - /** Look with the mouse, move with cursor keys. If you do not like the default - key layout, you may want to specify your own. For example to make the camera - be controlled by the cursor keys AND the keys W,A,S, and D, do something - like this: - \code - SKeyMap keyMap[8]; - keyMap[0].Action = EKA_MOVE_FORWARD; - keyMap[0].KeyCode = KEY_UP; - keyMap[1].Action = EKA_MOVE_FORWARD; - keyMap[1].KeyCode = KEY_KEY_W; - - keyMap[2].Action = EKA_MOVE_BACKWARD; - keyMap[2].KeyCode = KEY_DOWN; - keyMap[3].Action = EKA_MOVE_BACKWARD; - keyMap[3].KeyCode = KEY_KEY_S; - - keyMap[4].Action = EKA_STRAFE_LEFT; - keyMap[4].KeyCode = KEY_LEFT; - keyMap[5].Action = EKA_STRAFE_LEFT; - keyMap[5].KeyCode = KEY_KEY_A; - - keyMap[6].Action = EKA_STRAFE_RIGHT; - keyMap[6].KeyCode = KEY_RIGHT; - keyMap[7].Action = EKA_STRAFE_RIGHT; - keyMap[7].KeyCode = KEY_KEY_D; - - camera = sceneManager->addCameraSceneNodeFPS(0, 100, 500, -1, keyMap, 8); - \endcode - \param parent: Parent scene node of the camera. Can be null. - \param rotateSpeed: Speed with which the camera is rotated. This can be done - only with the mouse. - \param moveSpeed: Speed with which the camera is moved. Movement is done with - the cursor keys. - \param id: id of the camera. This id can be used to identify the camera. - \param keyMapArray: Optional pointer to an array of a keymap, specifying what - keys should be used to move the camera. If this is null, the default keymap - is used. You can define actions more then one time in the array, to bind - multiple keys to the same action. - \param keyMapSize: Amount of items in the keymap array. - \param noVerticalMovement: Setting this to true makes the camera only move within a - horizontal plane, and disables vertical movement as known from most ego shooters. Default - is 'false', with which it is possible to fly around in space, if no gravity is there. - \param jumpSpeed: Speed with which the camera is moved when jumping. - \return Returns a pointer to the interface of the camera if successful, otherwise 0. - This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ - virtual ICameraSceneNode* addCameraSceneNodeFPS(ISceneNode* parent = 0, - f32 rotateSpeed = 100.0f, f32 moveSpeed = 500.0f, s32 id=-1, - SKeyMap* keyMapArray=0, s32 keyMapSize=0, bool noVerticalMovement=false, - f32 jumpSpeed = 0.f) = 0; - - //! Adds a dynamic light scene node to the scene graph. - /** The light will cast dynamic light on all - other scene nodes in the scene, which have the material flag video::MTF_LIGHTING - turned on. (This is the default setting in most scene nodes). - \param parent: Parent scene node of the light. Can be null. If the parent moves, - the light will move too. - \param position: Position of the space relative to its parent where the light will be placed. - \param color: Diffuse color of the light. Ambient or Specular colors can be set manually with - the ILightSceneNode::getLightData() method. - \param radius: Radius of the light. - \param id: id of the node. This id can be used to identify the node. - \return Returns pointer to the interface of the light if successful, otherwise NULL. - This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ - virtual ILightSceneNode* addLightSceneNode(ISceneNode* parent = 0, - const core::vector3df& position = core::vector3df(0,0,0), - video::SColorf color = video::SColorf(1.0f, 1.0f, 1.0f), - f32 radius=100.0f, s32 id=-1) = 0; - - //! Adds a billboard scene node to the scene graph. - /** A billboard is like a 3d sprite: A 2d element, - which always looks to the camera. It is usually used for things like explosions, fire, - lensflares and things like that. - \param parent: Parent scene node of the billboard. Can be null. If the parent moves, - the billboard will move too. - \param position: Position of the space relative to its parent where the billboard will be placed. - \param size: Size of the billboard. This size is 2 dimensional because a billboard only has - width and height. - \param id: An id of the node. This id can be used to identify the node. - \param shade_top: vertex color top - \param shade_down: vertex color down - \return Returns pointer to the billboard if successful, otherwise NULL. - This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ - virtual IBillboardSceneNode* addBillboardSceneNode(ISceneNode* parent = 0, - const core::dimension2d& size = core::dimension2d(10.0f, 10.0f), - const core::vector3df& position = core::vector3df(0,0,0), s32 id=-1, - video::SColor shade_top = 0xFFFFFFFF, video::SColor shade_down = 0xFFFFFFFF) = 0; - - //! Adds a skybox scene node to the scene graph. - /** A skybox is a big cube with 6 textures on it and - is drawn around the camera position. - \param top: Texture for the top plane of the box. - \param bottom: Texture for the bottom plane of the box. - \param left: Texture for the left plane of the box. - \param right: Texture for the right plane of the box. - \param front: Texture for the front plane of the box. - \param back: Texture for the back plane of the box. - \param parent: Parent scene node of the skybox. A skybox usually has no parent, - so this should be null. Note: If a parent is set to the skybox, the box will not - change how it is drawn. - \param id: An id of the node. This id can be used to identify the node. - \return Returns a pointer to the sky box if successful, otherwise NULL. - This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ - virtual ISceneNode* addSkyBoxSceneNode(video::ITexture* top, video::ITexture* bottom, - video::ITexture* left, video::ITexture* right, video::ITexture* front, - video::ITexture* back, ISceneNode* parent = 0, s32 id=-1) = 0; - - //! Adds a skydome scene node to the scene graph. - /** A skydome is a large (half-) sphere with a panoramic texture - on the inside and is drawn around the camera position. - \param texture: Texture for the dome. - \param horiRes: Number of vertices of a horizontal layer of the sphere. - \param vertRes: Number of vertices of a vertical layer of the sphere. - \param texturePercentage: How much of the height of the texture is used. Should be between 0 and 1. - \param spherePercentage: How much of the sphere is drawn. Value should be between 0 and 2, where 1 is an exact half-sphere and 2 is a full sphere. - \param parent: Parent scene node of the dome. A dome usually has no parent, - so this should be null. Note: If a parent is set, the dome will not - change how it is drawn. - \param id: An id of the node. This id can be used to identify the node. - \return Returns a pointer to the sky dome if successful, otherwise NULL. - This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ - virtual ISceneNode* addSkyDomeSceneNode(video::ITexture* texture, - u32 horiRes, u32 vertRes, f64 texturePercentage, f64 spherePercentage, - ISceneNode* parent = 0, s32 id=-1) = 0; - - //! Adds a particle system scene node to the scene graph. - /** \param withDefaultEmitter: Creates a default working point emitter - which emitts some particles. Set this to true to see a particle system - in action. If set to false, you'll have to set the emitter you want by - calling IParticleSystemSceneNode::setEmitter(). - \param parent: Parent of the scene node. Can be NULL if no parent. - \param id: Id of the node. This id can be used to identify the scene node. - \param position: Position of the space relative to its parent where the - scene node will be placed. - \param rotation: Initital rotation of the scene node. - \param scale: Initial scale of the scene node. - \return Returns pointer to the created scene node. - This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ - virtual IParticleSystemSceneNode* addParticleSystemSceneNode( - bool withDefaultEmitter=true, ISceneNode* parent=0, s32 id=-1, - const core::vector3df& position = core::vector3df(0,0,0), - const core::vector3df& rotation = core::vector3df(0,0,0), - const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)) = 0; - - //! Adds a terrain scene node to the scene graph. - /** This node implements is a simple terrain renderer which uses - a technique known as geo mip mapping - for reducing the detail of triangle blocks which are far away. - The code for the TerrainSceneNode is based on the terrain - renderer by Soconne and the GeoMipMapSceneNode developed by - Spintz. They made their code available for Irrlicht and allowed - it to be distributed under this licence. I only modified some - parts. A lot of thanks go to them. - - This scene node is capable of loading terrains and updating - the indices at runtime to enable viewing very large terrains - very quickly. It uses a CLOD (Continuous Level of Detail) - algorithm which updates the indices for each patch based on - a LOD (Level of Detail) which is determined based on a patch's - distance from the camera. - - The patch size of the terrain must always be a size of ( 2^N+1, i.e. 8+1(9), 16+1(17), etc. ). - The MaxLOD available is directly dependent on the patch size of the terrain. LOD 0 contains all - of the indices to draw all the triangles at the max detail for a patch. As each LOD goes up by 1 - the step taken, in generating indices increases by - 2^LOD, so for LOD 1, the step taken is 2, for - LOD 2, the step taken is 4, LOD 3 - 8, etc. The step can be no larger than the size of the patch, - so having a LOD of 8, with a patch size of 17, is asking the algoritm to generate indices every - 2^8 ( 256 ) vertices, which is not possible with a patch size of 17. The maximum LOD for a patch - size of 17 is 2^4 ( 16 ). So, with a MaxLOD of 5, you'll have LOD 0 ( full detail ), LOD 1 ( every - 2 vertices ), LOD 2 ( every 4 vertices ), LOD 3 ( every 8 vertices ) and LOD 4 ( every 16 vertices ). - \param heightMapFileName: The name of the file on disk, to read vertex data from. This should - be a gray scale bitmap. - \param parent: Parent of the scene node. Can be 0 if no parent. - \param id: Id of the node. This id can be used to identify the scene node. - \param position: The absolute position of this node. - \param rotation: The absolute rotation of this node. ( NOT YET IMPLEMENTED ) - \param scale: The scale factor for the terrain. If you're using a heightmap of size 129x129 and would like - your terrain to be 12900x12900 in game units, then use a scale factor of ( core::vector ( 100.0f, 100.0f, 100.0f ). - If you use a Y scaling factor of 0.0f, then your terrain will be flat. - \param vertexColor: The default color of all the vertices. If no texture is associated - with the scene node, then all vertices will be this color. Defaults to white. - \param maxLOD: The maximum LOD (level of detail) for the node. Only change if you - know what you are doing, this might lead to strange behaviour. - \param patchSize: patch size of the terrain. Only change if you - know what you are doing, this might lead to strange behaviour. - \param smoothFactor: The number of times the vertices are smoothed. - \param addAlsoIfHeightmapEmpty: Add terrain node even with empty heightmap. - \return Returns pointer to the created scene node. Can be null if the - terrain could not be created, for example because the heightmap could not be loaded. - The returned pointer should not be dropped. See IReferenceCounted::drop() for more information. */ - virtual ITerrainSceneNode* addTerrainSceneNode( - const c8* heightMapFileName, - ISceneNode* parent=0, s32 id=-1, - const core::vector3df& position = core::vector3df(0.0f,0.0f,0.0f), - const core::vector3df& rotation = core::vector3df(0.0f,0.0f,0.0f), - const core::vector3df& scale = core::vector3df(1.0f,1.0f,1.0f), - video::SColor vertexColor = video::SColor(255,255,255,255), - s32 maxLOD=5, E_TERRAIN_PATCH_SIZE patchSize=ETPS_17, s32 smoothFactor=0, - bool addAlsoIfHeightmapEmpty = false) = 0; - - //! Adds a terrain scene node to the scene graph. - /** Just like the other addTerrainSceneNode() method, but takes an IReadFile - pointer as parameter for the heightmap. For more informations take a look - at the other function. - \param heightMapFile: The file handle to read vertex data from. This should - be a gray scale bitmap. - \param parent: Parent of the scene node. Can be 0 if no parent. - \param id: Id of the node. This id can be used to identify the scene node. - \param position: The absolute position of this node. - \param rotation: The absolute rotation of this node. ( NOT YET IMPLEMENTED ) - \param scale: The scale factor for the terrain. If you're using a heightmap of size 129x129 and would like - your terrain to be 12900x12900 in game units, then use a scale factor of ( core::vector ( 100.0f, 100.0f, 100.0f ). - If you use a Y scaling factor of 0.0f, then your terrain will be flat. - \param vertexColor: The default color of all the vertices. If no texture is associated - with the scene node, then all vertices will be this color. Defaults to white. - \param maxLOD: The maximum LOD (level of detail) for the node. Only change if you - know what you are doing, this might lead to strange behaviour. - \param patchSize: patch size of the terrain. Only change if you - know what you are doing, this might lead to strange behaviour. - \param smoothFactor: The number of times the vertices are smoothed. - \param addAlsoIfHeightmapEmpty: Add terrain node even with empty heightmap. - \return Returns pointer to the created scene node. Can be null if the - terrain could not be created, for example because the heightmap could not be loaded. - The returned pointer should not be dropped. See IReferenceCounted::drop() for more information. */ - virtual ITerrainSceneNode* addTerrainSceneNode( - io::IReadFile* heightMapFile, - ISceneNode* parent=0, s32 id=-1, - const core::vector3df& position = core::vector3df(0.0f,0.0f,0.0f), - const core::vector3df& rotation = core::vector3df(0.0f,0.0f,0.0f), - const core::vector3df& scale = core::vector3df(1.0f,1.0f,1.0f), - video::SColor vertexColor = video::SColor(255,255,255,255), - s32 maxLOD=5, E_TERRAIN_PATCH_SIZE patchSize=ETPS_17, s32 smoothFactor=0, - bool addAlsoIfHeightmapEmpty = false) = 0; - - //! Adds a quake3 scene node to the scene graph. - /** A Quake3 Scene renders multiple meshes for a specific HighLanguage Shader (Quake3 Style ) - \return Returns a pointer to the quake3 scene node if successful, otherwise NULL. - This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ - virtual ISceneNode* addQuake3SceneNode(IMeshBuffer* meshBuffer, const quake3::SShader * shader, - ISceneNode* parent=0, s32 id=-1 - ) = 0; - - - //! Adds an empty scene node to the scene graph. - /** Can be used for doing advanced transformations - or structuring the scene graph. - \return Returns pointer to the created scene node. - This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ - virtual ISceneNode* addEmptySceneNode(ISceneNode* parent=0, s32 id=-1) = 0; - - //! Adds a dummy transformation scene node to the scene graph. - /** This scene node does not render itself, and does not respond to set/getPosition, - set/getRotation and set/getScale. Its just a simple scene node that takes a - matrix as relative transformation, making it possible to insert any transformation - anywhere into the scene graph. - \return Returns pointer to the created scene node. - This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ - virtual IDummyTransformationSceneNode* addDummyTransformationSceneNode( - ISceneNode* parent=0, s32 id=-1) = 0; - - //! Adds a text scene node, which is able to display 2d text at a position in three dimensional space - virtual ITextSceneNode* addTextSceneNode(gui::IGUIFont* font, const wchar_t* text, - video::SColor color=video::SColor(100,255,255,255), - ISceneNode* parent = 0, const core::vector3df& position = core::vector3df(0,0,0), - s32 id=-1) = 0; - - //! Adds a text scene node, which uses billboards - virtual ITextSceneNode* addBillboardTextSceneNode( gui::IGUIFont* font, const wchar_t* text, - ISceneNode* parent = 0, - const core::dimension2d& size = core::dimension2d(10.0f, 10.0f), - const core::vector3df& position = core::vector3df(0,0,0), s32 id=-1, - video::SColor shade_top = 0xFFFFFFFF, video::SColor shade_down = 0xFFFFFFFF) = 0; - - //! Adds a Hill Plane mesh to the mesh pool. - /** The mesh is generated on the fly - and looks like a plane with some hills on it. It is uses mostly for quick - tests of the engine only. You can specify how many hills there should be - on the plane and how high they should be. Also you must specify a name for - the mesh, because the mesh is added to the mesh pool, and can be retrieved - again using ISceneManager::getMesh() with the name as parameter. - \param name: The name of this mesh which must be specified in order - to be able to retrieve the mesh later with ISceneManager::getMesh(). - \param tileSize: Size of a tile of the mesh. (10.0f, 10.0f) would be a - good value to start, for example. - \param tileCount: Specifies how much tiles there will be. If you specifiy - for example that a tile has the size (10.0f, 10.0f) and the tileCount is - (10,10), than you get a field of 100 tiles which has the dimension 100.0fx100.0f. - \param material: Material of the hill mesh. - \param hillHeight: Height of the hills. If you specify a negative value - you will get holes instead of hills. If the height is 0, no hills will be - created. - \param countHills: Amount of hills on the plane. There will be countHills.X - hills along the X axis and countHills.Y along the Y axis. So in total there - will be countHills.X * countHills.Y hills. - \param textureRepeatCount: Defines how often the texture will be repeated in - x and y direction. - \return Returns null if the creation failed. The reason could be that you - specified some invalid parameters or that a mesh with that name already - exists. If successful, a pointer to the mesh is returned. - This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ - virtual IAnimatedMesh* addHillPlaneMesh(const c8* name, - const core::dimension2d& tileSize, const core::dimension2d& tileCount, - video::SMaterial* material = 0, f32 hillHeight = 0.0f, - const core::dimension2d& countHills = core::dimension2d(0.0f, 0.0f), - const core::dimension2d& textureRepeatCount = core::dimension2d(1.0f, 1.0f)) = 0; - - //! Adds a static terrain mesh to the mesh pool. - /** The mesh is generated on the fly - from a texture file and a height map file. Both files may be huge - (8000x8000 pixels would be no problem) because the generator splits the - files into smaller textures if necessary. - You must specify a name for the mesh, because the mesh is added to the mesh pool, - and can be retrieved again using ISceneManager::getMesh() with the name as parameter. - \param meshname: The name of this mesh which must be specified in order - to be able to retrieve the mesh later with ISceneManager::getMesh(). - \param texture: Texture for the terrain. Please note that this is not a - hardware texture as usual (ITexture), but an IImage software texture. - You can load this texture with IVideoDriver::createImageFromFile(). - \param heightmap: A grayscaled heightmap image. Like the texture, - it can be created with IVideoDriver::createImageFromFile(). The amount - of triangles created depends on the size of this texture, so use a small - heightmap to increase rendering speed. - \param stretchSize: Parameter defining how big a is pixel on the heightmap. - \param maxHeight: Defines how height a white pixel on the heighmap is. - \param defaultVertexBlockSize: Defines the initial dimension between vertices. - \return Returns null if the creation failed. The reason could be that you - specified some invalid parameters, that a mesh with that name already - exists, or that a texture could not be found. If successful, a pointer to the mesh is returned. - This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ - virtual IAnimatedMesh* addTerrainMesh(const c8* meshname, - video::IImage* texture, video::IImage* heightmap, - const core::dimension2d& stretchSize = core::dimension2d(10.0f,10.0f), - f32 maxHeight=200.0f, - const core::dimension2d& defaultVertexBlockSize = core::dimension2d(64,64)) = 0; - - //! add a static arrow mesh to the meshpool - virtual IAnimatedMesh* addArrowMesh(const c8* name, - video::SColor vtxColor0=0xFFFFFFFF, - video::SColor vtxColor1=0xFFFFFFFF, - u32 tesselationCylinder=4, u32 tesselationCone=8, - f32 height=1.f, f32 cylinderHeight=0.6f, - f32 width0=0.05f, f32 width1=0.3f) = 0; - - //! add a static sphere mesh to the meshpool - virtual IAnimatedMesh* addSphereMesh(const c8* name, - f32 radius=5.f, u32 polyCountX = 16, - u32 polyCountY = 16) = 0; - - //! Returns the root scene node. - /** This is the scene node which is parent - of all scene nodes. The root scene node is a special scene node which - only exists to manage all scene nodes. It will not be rendered and cannot - be removed from the scene. - \return Returns a pointer to the root scene node. */ - virtual ISceneNode* getRootSceneNode() = 0; - - //! Returns the first scene node with the specified id. - /** \param id: The id to search for - \param start: Scene node to start from. All children of this scene - node are searched. If null is specified, the root scene node is - taken. - \return Returns pointer to the first scene node with this id, - and null if no scene node could be found. */ - virtual ISceneNode* getSceneNodeFromId(s32 id, ISceneNode* start=0) = 0; - - //! Returns the first scene node with the specified name. - /** \param name: The name to search for - \param start: Scene node to start from. All children of this scene - node are searched. If null is specified, the root scene node is - taken. - \return Returns pointer to the first scene node with this id, - and null if no scene node could be found. */ - virtual ISceneNode* getSceneNodeFromName(const c8* name, ISceneNode* start=0) = 0; - - //! Returns the first scene node with the specified type. - /** \param type: The type to search for - \param start: Scene node to start from. All children of this scene - node are searched. If null is specified, the root scene node is - taken. - \return Returns pointer to the first scene node with this type, - and null if no scene node could be found. */ - virtual ISceneNode* getSceneNodeFromType(scene::ESCENE_NODE_TYPE type, ISceneNode* start=0) = 0; - - //! returns scene nodes by type. - /** \param type: Type of scene node to find. - \param outNodes: array to be filled with results. - \param start: Scene node to start from. All children of this scene - node are searched. If null is specified, the root scene node is - taken. */ - virtual void getSceneNodesFromType(ESCENE_NODE_TYPE type, core::array& outNodes, ISceneNode* start=0) = 0; - - //! Returns the current active camera. - /** \return The active camera is returned. Note that this can be NULL, if there - was no camera created yet. */ - virtual ICameraSceneNode* getActiveCamera() = 0; - - //! Sets the currently active camera. - /** The previous active camera will be deactivated. - \param camera: The new camera which should be active. */ - virtual void setActiveCamera(ICameraSceneNode* camera) = 0; - - //! Sets the color of stencil buffers shadows drawn by the scene manager. - virtual void setShadowColor(video::SColor color = video::SColor(150,0,0,0)) = 0; - - //! Returns the current color of shadows. - virtual video::SColor getShadowColor() const = 0; - - //! Registers a node for rendering it at a specific time. - /** This method should only be used by SceneNodes when they get a - ISceneNode::OnRegisterSceneNode() call. - \param node: Node to register for drawing. Usually scene nodes would set 'this' - as parameter here because they want to be drawn. - \param pass: Specifies when the mode wants to be drawn in relation to the other nodes. - For example, if the node is a shadow, it usually wants to be drawn after all other nodes - and will use ESNRP_SHADOW for this. See E_SCENE_NODE_RENDER_PASS for details. - \return scene will be rendered ( passed culling ) */ - virtual u32 registerNodeForRendering(ISceneNode* node, - E_SCENE_NODE_RENDER_PASS pass = ESNRP_AUTOMATIC) = 0; - - //! Draws all the scene nodes. - /** This can only be invoked between - IVideoDriver::beginScene() and IVideoDriver::endScene(). Please note that - the scene is not only drawn when calling this, but also animated - by existing scene node animators, culling of scene nodes is done, etc. */ - virtual void drawAll() = 0; - - //! Creates a rotation animator, which rotates the attached scene node around itself. - /** \param rotationPerSecond: Specifies the speed of the animation - \return Returns the animator. Attach it to a scene node with ISceneNode::addAnimator() - and the animator will animate it. - If you no longer need the animator, you should call ISceneNodeAnimator::drop(). - See IReferenceCounted::drop() for more information. */ - virtual ISceneNodeAnimator* createRotationAnimator(const core::vector3df& rotationPerSecond) = 0; - - //! Creates a fly circle animator, which lets the attached scene node fly around a center. - /** \param center: Center of the circle. - \param radius: Radius of the circle. - \param speed: Specifies the speed of the flight. - \param direction: Specifies the upvector used for alignment of the mesh. - \return Returns the animator. Attach it to a scene node with ISceneNode::addAnimator() - and the animator will animate it. - If you no longer need the animator, you should call ISceneNodeAnimator::drop(). - See IReferenceCounted::drop() for more information. */ - virtual ISceneNodeAnimator* createFlyCircleAnimator(const core::vector3df& center, - f32 radius, f32 speed=0.001f, const core::vector3df& direction= core::vector3df ( 0.f, 1.f, 0.f ) ) = 0; - - //! Creates a fly straight animator, which lets the attached scene node fly or move along a line between two points. - /** \param startPoint: Start point of the line. - \param endPoint: End point of the line. - \param timeForWay: Time in milli seconds how long the node should need to - move from the start point to the end point. - \param loop: If set to false, the node stops when the end point is reached. - If loop is true, the node begins again at the start. - \return Returns the animator. Attach it to a scene node with ISceneNode::addAnimator() - and the animator will animate it. - If you no longer need the animator, you should call ISceneNodeAnimator::drop(). - See IReferenceCounted::drop() for more information. */ - virtual ISceneNodeAnimator* createFlyStraightAnimator(const core::vector3df& startPoint, - const core::vector3df& endPoint, u32 timeForWay, bool loop=false) = 0; - - //! Creates a texture animator, which switches the textures of the target scene node based on a list of textures. - /** \param textures: List of textures to use. - \param timePerFrame: Time in milliseconds, how long any texture in the list - should be visible. - \param loop: If set to to false, the last texture remains set, and the animation - stops. If set to true, the animation restarts with the first texture. - \return Returns the animator. Attach it to a scene node with ISceneNode::addAnimator() - and the animator will animate it. - If you no longer need the animator, you should call ISceneNodeAnimator::drop(). - See IReferenceCounted::drop() for more information. */ - virtual ISceneNodeAnimator* createTextureAnimator(const core::array& textures, - s32 timePerFrame, bool loop=true) = 0; - - //! Creates a scene node animator, which deletes the scene node after some time automatically. - /** \param timeMs: Time in milliseconds, after when the node will be deleted. - \return Returns the animator. Attach it to a scene node with ISceneNode::addAnimator() - and the animator will animate it. - If you no longer need the animator, you should call ISceneNodeAnimator::drop(). - See IReferenceCounted::drop() for more information. */ - virtual ISceneNodeAnimator* createDeleteAnimator(u32 timeMs) = 0; - - //! Creates a special scene node animator for doing automatic collision detection and response. - /** See ISceneNodeAnimatorCollisionResponse for details. - \param world: Triangle selector holding all triangles of the world with which - the scene node may collide. You can create a triangle selector with - ISceneManager::createTriangleSelector(); - \param sceneNode: SceneNode which should be manipulated. After you added this animator - to the scene node, the scene node will not be able to move through walls and is - affected by gravity. - \param ellipsoidRadius: Radius of the ellipsoid with which collision detection and - response is done. If you have got a scene node, and you are unsure about - how big the radius should be, you could use the following code to determine - it: - \code - const core::aabbox& box = yourSceneNode->getBoundingBox(); - core::vector3df radius = box.MaxEdge - box.getCenter(); - \endcode - \param gravityPerSecond: Sets the gravity of the environment. A good example value would be - core::vector3df(0,-100.0f,0) for letting gravity affect all object to - fall down. For bigger gravity, make increase the length of the vector. - You can disable gravity by setting it to core::vector3df(0,0,0). - \param ellipsoidTranslation: By default, the ellipsoid for collision detection is created around - the center of the scene node, which means that the ellipsoid surrounds - it completely. If this is not what you want, you may specify a translation - for the ellipsoid. - \param slidingValue: DOCUMENTATION NEEDED. - \return Returns the animator. Attach it to a scene node with ISceneNode::addAnimator() - and the animator will cause it to do collision detection and response. - If you no longer need the animator, you should call ISceneNodeAnimator::drop(). - See IReferenceCounted::drop() for more information. */ - virtual ISceneNodeAnimatorCollisionResponse* createCollisionResponseAnimator( - ITriangleSelector* world, ISceneNode* sceneNode, - const core::vector3df& ellipsoidRadius = core::vector3df(30,60,30), - const core::vector3df& gravityPerSecond = core::vector3df(0,-100.0f,0), - const core::vector3df& ellipsoidTranslation = core::vector3df(0,0,0), - f32 slidingValue = 0.0005f) = 0; - - //! Creates a follow spline animator. - /** The animator modifies the position of - the attached scene node to make it follow a hermite spline. - The code of the is based on a scene node - Matthias Gall sent in. Thanks! I adapted the code just a little bit. Matthias - wrote: - Uses a subset of hermite splines: either cardinal splines (tightness != 0.5) or catmull-rom-splines (tightness == 0.5) - but this is just my understanding of this stuff, I'm not a mathematician, so this might be wrong ;) */ - virtual ISceneNodeAnimator* createFollowSplineAnimator(s32 startTime, - const core::array< core::vector3df >& points, - f32 speed = 1.0f, f32 tightness = 0.5f) = 0; - - //! Creates a simple ITriangleSelector, based on a mesh. - /** Triangle selectors - can be used for doing collision detection. Don't use this selector - for a huge amount of triangles like in Quake3 maps. - Instead, use for example ISceneManager::createOctTreeTriangleSelector(). - Please note that the created triangle selector is not automaticly attached - to the scene node. You will have to call ISceneNode::setTriangleSelector() - for this. To create and attach a triangle selector is done like this: - \code - ITriangleSelector* s = sceneManager->createTriangleSelector(yourMesh, - yourSceneNode); - yourSceneNode->setTriangleSelector(s); - s->drop(); - \endcode - \param mesh: Mesh of which the triangles are taken. - \param node: Scene node of which visibility and transformation is used. - \return Returns the selector, or null if not successful. - If you no longer need the selector, you should call ITriangleSelector::drop(). - See IReferenceCounted::drop() for more information. */ - virtual ITriangleSelector* createTriangleSelector(IMesh* mesh, ISceneNode* node) = 0; - - //! Creates a simple dynamic ITriangleSelector, based on a axis aligned bounding box. - /** Triangle selectors - can be used for doing collision detection. Every time when triangles are - queried, the triangle selector gets the bounding box of the scene node, - an creates new triangles. In this way, it works good with animated scene nodes. - \param node: Scene node of which the bounding box, visibility and transformation is used. - \return Returns the selector, or null if not successful. - If you no longer need the selector, you should call ITriangleSelector::drop(). - See IReferenceCounted::drop() for more information. */ - virtual ITriangleSelector* createTriangleSelectorFromBoundingBox(ISceneNode* node) = 0; - - //! Creates a Triangle Selector, optimized by an octtree. - /** Triangle selectors - can be used for doing collision detection. This triangle selector is - optimized for huge amounts of triangle, it organizes them in an octtree. - Please note that the created triangle selector is not automaticly attached - to the scene node. You will have to call ISceneNode::setTriangleSelector() - for this. To create and attach a triangle selector is done like this: - \code - ITriangleSelector* s = sceneManager->createOctTreeTriangleSelector(yourMesh, - yourSceneNode); - yourSceneNode->setTriangleSelector(s); - s->drop(); - \endcode - For more informations and examples on this, take a look at the collision - tutorial in the SDK. - \param mesh: Mesh of which the triangles are taken. - \param node: Scene node of which visibility and transformation is used. - \param minimalPolysPerNode: Specifies the minimal polygons contained a octree node. - If a node gets less polys the this value, it will not be splitted into - smaller nodes. - \return Returns the selector, or null if not successful. - If you no longer need the selector, you should call ITriangleSelector::drop(). - See IReferenceCounted::drop() for more information. */ - virtual ITriangleSelector* createOctTreeTriangleSelector(IMesh* mesh, - ISceneNode* node, s32 minimalPolysPerNode=32) = 0; - - //! Creates a meta triangle selector. - /** A meta triangle selector is nothing more than a - collection of one or more triangle selectors providing together - the interface of one triangle selector. In this way, - collision tests can be done with different triangle soups in one pass. - \return Returns the selector, or null if not successful. - If you no longer need the selector, you should call ITriangleSelector::drop(). - See IReferenceCounted::drop() for more information. */ - virtual IMetaTriangleSelector* createMetaTriangleSelector() = 0; - - //! Creates a triangle selector which can select triangles from a terrain scene node. - /** \param node: Pointer to the created terrain scene node - \param LOD: Level of detail, 0 for highest detail. */ - virtual ITriangleSelector* createTerrainTriangleSelector( - ITerrainSceneNode* node, s32 LOD=0) = 0; - - //! Adds an external mesh loader for extending the engine with new file formats. - /** If you want the engine to be extended with - file formats it currently is not able to load (e.g. .cob), just implement - the IMeshLoader interface in your loading class and add it with this method. - Using this method it is also possible to override built-in mesh loaders with - newer or updated versions without the need of recompiling the engine. - \param externalLoader: Implementation of a new mesh loader. */ - virtual void addExternalMeshLoader(IMeshLoader* externalLoader) = 0; - - //! Returns a pointer to the scene collision manager. - virtual ISceneCollisionManager* getSceneCollisionManager() = 0; - - //! Returns a pointer to the mesh manipulator. - virtual IMeshManipulator* getMeshManipulator() = 0; - - //! Adds a scene node to the deletion queue. - /** The scene node is immediatly - deleted when it's secure. Which means when the scene node does not - execute animators and things like that. This method is for example - used for deleting scene nodes by their scene node animators. In - most other cases, a ISceneNode::remove() call is enough, using this - deletion queue is not necessary. - See ISceneManager::createDeleteAnimator() for details. - \param node: Node to detete. */ - virtual void addToDeletionQueue(ISceneNode* node) = 0; - - //! Posts an input event to the environment. - /** Usually you do not have to - use this method, it is used by the internal engine. */ - virtual bool postEventFromUser(const SEvent& event) = 0; - - //! Clears the whole scene. - /** All scene nodes are removed. */ - virtual void clear() = 0; - - //! Returns interface to the parameters set in this scene. - /** String parameters can be used by plugins and mesh loaders. - For example the CMS and LMTS loader want a parameter named 'CSM_TexturePath' - and 'LMTS_TexturePath' set to the path were attached textures can be found. See - CSM_TEXTURE_PATH, LMTS_TEXTURE_PATH, MY3D_TEXTURE_PATH, - COLLADA_CREATE_SCENE_INSTANCES, DMF_TEXTURE_PATH and DMF_USE_MATERIALS_DIRS*/ - virtual io::IAttributes* getParameters() = 0; - - //! Returns current render pass. - /** All scene nodes are being rendered in a specific order. - First lights, cameras, sky boxes, solid geometry, and then transparent - stuff. During the rendering process, scene nodes may want to know what the scene - manager is rendering currently, because for example they registered for rendering - twice, once for transparent geometry and once for solid. When knowing what rendering - pass currently is active they can render the correct part of their geometry. */ - virtual E_SCENE_NODE_RENDER_PASS getSceneNodeRenderPass() const = 0; - - //! Returns the default scene node factory which can create all built in scene nodes - virtual ISceneNodeFactory* getDefaultSceneNodeFactory() = 0; - - //! Adds a scene node factory to the scene manager. - /** Use this to extend the scene manager with new scene node types which it should be - able to create automaticly, for example when loading data from xml files. */ - virtual void registerSceneNodeFactory(ISceneNodeFactory* factoryToAdd) = 0; - - //! Returns amount of registered scene node factories. - virtual u32 getRegisteredSceneNodeFactoryCount() const = 0; - - //! Returns a scene node factory by index - virtual ISceneNodeFactory* getSceneNodeFactory(u32 index) = 0; - - //! Returns the default scene node animator factory which can create all built-in scene node animators - virtual ISceneNodeAnimatorFactory* getDefaultSceneNodeAnimatorFactory() = 0; - - //! Adds a scene node animator factory to the scene manager. - /** Use this to extend the scene manager with new scene node animator types which it should be - able to create automaticly, for example when loading data from xml files. */ - virtual void registerSceneNodeAnimatorFactory(ISceneNodeAnimatorFactory* factoryToAdd) = 0; - - //! Returns amount of registered scene node animator factories. - virtual u32 getRegisteredSceneNodeAnimatorFactoryCount() const = 0; - - //! Returns a scene node animator factory by index - virtual ISceneNodeAnimatorFactory* getSceneNodeAnimatorFactory(u32 index) = 0; - - //! Returns a typename from a scene node type or null if not found - virtual const c8* getSceneNodeTypeName(ESCENE_NODE_TYPE type) = 0; - - //! Adds a scene node to the scene by name - virtual ISceneNode* addSceneNode(const char* sceneNodeTypeName, ISceneNode* parent) = 0; - - //! Creates a new scene manager. - /** This can be used to easily draw and/or store two independent scenes at the same time. - The mesh cache will be shared between all existing scene managers, which means if you load - a mesh in the original scene manager using for example getMesh(), the mesh will be available - in all other scene managers too, without loading. - The original/main scene manager will still be there and accessible via IrrlichtDevice::getSceneManager(). - If you need input event in this new scene manager, for example for FPS cameras, you'll need - to forward input to this manually: Just implement an IEventReceiver and call - yourNewSceneManager->postEventFromUser(), and return true so that the original scene manager - doesn't get the event. Otherwise, all input will go automaticly to the main scene manager. - If you no longer need the new scene manager, you should call ISceneManager::drop(). - See IReferenceCounted::drop() for more information. */ - virtual ISceneManager* createNewSceneManager(bool cloneContent=false) = 0; - - //! Saves the current scene into a file. - /** Scene nodes with the option isDebugObject set to true are not being saved. - The scene is usually written to an .irr file, an xml based format. .irr files can - Be edited with the Irrlicht Engine Editor, irrEdit (http://irredit.irrlicht3d.org). - To load .irr files again, see ISceneManager::loadScene(). - \param filename: Name of the file. - \param userDataSerializer: If you want to save some user data for every scene node into the - file, implement the ISceneUserDataSerializer interface and provide it as parameter here. - Otherwise, simply specify 0 as this parameter. - \return Returns true if successful. */ - virtual bool saveScene(const c8* filename, ISceneUserDataSerializer* userDataSerializer=0) = 0; - - //! Saves the current scene into a file. - /** Scene nodes with the option isDebugObject set to true are not being saved. - The scene is usually written to an .irr file, an xml based format. .irr files can - Be edited with the Irrlicht Engine Editor, irrEdit (http://irredit.irrlicht3d.org). - To load .irr files again, see ISceneManager::loadScene(). - \param file: File where the scene is saved into. - \param userDataSerializer: If you want to save some user data for every scene node into the - file, implement the ISceneUserDataSerializer interface and provide it as parameter here. - Otherwise, simply specify 0 as this parameter. - \return Returns true if successful. */ - virtual bool saveScene(io::IWriteFile* file, ISceneUserDataSerializer* userDataSerializer=0) = 0; - - //! Loads a scene. Note that the current scene is not cleared before. - /** The scene is usually load from an .irr file, an xml based format. .irr files can - Be edited with the Irrlicht Engine Editor, irrEdit (http://irredit.irrlicht3d.org) or - saved directly by the engine using ISceneManager::saveScene(). - \param filename: Name of the file. - \param userDataSerializer: If you want to load user data possibily saved in that file for - some scene nodes in the file, implement the ISceneUserDataSerializer interface and provide it as parameter here. - Otherwise, simply specify 0 as this parameter. - \return Returns true if successful. */ - virtual bool loadScene(const c8* filename, ISceneUserDataSerializer* userDataSerializer=0) = 0; - - //! Loads a scene. Note that the current scene is not cleared before. - /** The scene is usually load from an .irr file, an xml based format. .irr files can - Be edited with the Irrlicht Engine Editor, irrEdit (http://irredit.irrlicht3d.org) or - saved directly by the engine using ISceneManager::saveScene(). - \param file: File where the scene is going to be saved into. - \param userDataSerializer: If you want to load user data possibily saved in that file for - some scene nodes in the file, implement the ISceneUserDataSerializer interface and provide it as parameter here. - Otherwise, simply specify 0 as this parameter. - \return Returns true if successful. */ - virtual bool loadScene(io::IReadFile* file, ISceneUserDataSerializer* userDataSerializer=0) = 0; - - //! Returns a mesh writer implementation if available - /** Note: You need to drop() the pointer after use again, see IReferenceCounted::drop() - for details. */ - virtual IMeshWriter* createMeshWriter(EMESH_WRITER_TYPE type) = 0; - - //! Sets ambient color of the scene - virtual void setAmbientLight(const video::SColorf &ambientColor) = 0; - - //! Returns ambient color of the scene - virtual const video::SColorf& getAmbientLight() const = 0; - - }; - - -} // end namespace scene -} // end namespace irr - -#endif - +// Copyright (C) 2002-2007 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_SCENE_MANAGER_H_INCLUDED__ +#define __I_SCENE_MANAGER_H_INCLUDED__ + +#include "IReferenceCounted.h" +#include "irrArray.h" +#include "vector3d.h" +#include "dimension2d.h" +#include "SColor.h" +#include "ETerrainElements.h" +#include "ESceneNodeTypes.h" +#include "EMeshWriterEnums.h" +#include "SceneParameters.h" + +namespace irr +{ + struct SKeyMap; + struct SEvent; + +namespace io +{ + class IReadFile; + class IAttributes; + class IWriteFile; +} // end namespace io + +namespace gui +{ + class IGUIFont; + class IGUIEnvironment; +} // end namespace gui + +namespace video +{ + class IVideoDriver; + class SMaterial; + class IImage; + class ITexture; +} // end namespace video + +namespace scene +{ + class IMeshWriter; + + //! Enumeration for render passes. + /** A parameter passed to the registerNodeForRendering() method of the ISceneManager, + specifying when the mode wants to be drawn in relation to the other nodes. */ + enum E_SCENE_NODE_RENDER_PASS + { + //! Camera pass. The active view is set up here. + //! The very first pass. + ESNRP_CAMERA, + + //! In this pass, lights are transformed into camera space and added to the driver + ESNRP_LIGHT, + + //! This is used for sky boxes. + ESNRP_SKY_BOX, + + //! All normal objects can use this for registering themselves. + //! This value will never be returned by ISceneManager::getSceneNodeRenderPass(). + //! The scene manager will determine by itself if an object is + //! transparent or solid and register the object as SNRT_TRANSPARENT or + //! SNRT_SOLD automatically if you call registerNodeForRendering with this + //! value (which is default). Note that it will register the node only as ONE type. + //! If your scene node has both solid and transparent material types register + //! it twice (one time as SNRT_SOLID, the other time as SNRT_TRANSPARENT) and + //! in the render() method call getSceneNodeRenderPass() to find out the current + //! render pass and render only the corresponding parts of the node. + ESNRP_AUTOMATIC, + + //! Solid scene nodes or special scene nodes without materials. + ESNRP_SOLID, + + //! Drawn after the transparent nodes, the time for drawing shadow volumes + ESNRP_SHADOW, + + //! Transparent scene nodes, drawn after shadow nodes. They are sorted from back + //! to front and drawn in that order. + ESNRP_TRANSPARENT, + + //! Never used, value specifing how much parameters there are. + ESNRP_COUNT + }; + + class IMesh; + class IMeshBuffer; + class IAnimatedMesh; + class IMeshCache; + class ISceneNode; + class ICameraSceneNode; + class IAnimatedMeshSceneNode; + class ISceneNodeAnimator; + class ISceneNodeAnimatorCollisionResponse; + class ILightSceneNode; + class IBillboardSceneNode; + class ITerrainSceneNode; + class IMeshSceneNode; + class IMeshLoader; + class ISceneCollisionManager; + class IParticleSystemSceneNode; + class IDummyTransformationSceneNode; + class ITriangleSelector; + class IMetaTriangleSelector; + class IMeshManipulator; + class ITextSceneNode; + class ISceneNodeFactory; + class ISceneNodeAnimatorFactory; + class ISceneUserDataSerializer; + + namespace quake3 + { + class SShader; + } // end namespace quake3 + + //! The Scene Manager manages scene nodes, mesh recources, cameras and all the other stuff. + /** All Scene nodes can be created only here. There is a always growing list of scene + nodes for lots of purposes: Indoor rendering scene nodes like the Octree + (addOctTreeSceneNode()) or the terrain renderer (addTerrainSceneNode()), + different Camera scene nodes (addCameraSceneNode(), addCameraSceneNodeMaya()), + scene nodes for Light (addLightSceneNode()), Billboards (addBillboardSceneNode()) + and so on. + A scene node is a node in the hierachical scene graph. Every scene node may have children, + which are other scene nodes. Children move relative the their parents position. If the parent of a node is not + visible, its children won't be visible, too. In this way, it is for example easily possible + to attach a light to a moving car or to place a walking character on a moving platform + on a moving ship. + The SceneManager is also able to load 3d mesh files of different formats. Take a look + at getMesh() to find out what formats are supported. And if these formats are not enough + use addExternalMeshLoader() to add new formats to the engine. + */ + class ISceneManager : public virtual IReferenceCounted + { + public: + + //! destructor + virtual ~ISceneManager() {} + + //! Returns pointer to an animateable mesh. Loads the file if not loaded already. + /** + * If you want to remove a loaded mesh from the cache again, use removeMesh(). + * Currently there are the following mesh formats supported: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
FormatDescription
3D Studio (.3ds)Loader for 3D-Studio files which lots of 3D packages are able to export. + * Only static meshes are currently supported by this importer.
Bliz Basic B3D (.b3d)Loader for blitz basic files, developed by Mark Sibly, also supports animations.
Cartography shop 4 (.csm)Cartography Shop is a modeling program for creating architecture and calculating + * lighting. Irrlicht can directly import .csm files thanks to the IrrCSM library + * created by Saurav Mohapatra which is now integrated directly in Irrlicht. + * If you are using this loader, please note that you'll have to set the path + * of the textures before loading .csm files. You can do this using SceneManager->getParameters()->setParameter(scene::CSM_TEXTURE_PATH, + * "path/to/your/textures");
COLLADA (.dae, .xml)COLLADA is an open Digital Asset Exchange Schema for the interactive 3D industry. There are + * exporters and importers for this format available for most of the big 3d packages + * at http://collada.org. Irrlicht can import COLLADA files by using the + * ISceneManager::getMesh() method. COLLADA files need not contain only one single mesh + * but multiple meshes and a whole scene setup with lights, cameras and mesh instances, + * this loader can set up a scene as described by the COLLADA file instead of loading + * and returning one single mesh. By default, this loader behaves like the other loaders + * and does not create instances, but it can be switched into this mode by using + * SceneManager->getParameters()->setParameter(COLLADA_CREATE_SCENE_INSTANCES, true); + * Created scene nodes will be named as the names of the nodes in the + * COLLADA file. The returned mesh is just a dummy object in this mode. Meshes included in + * the scene will be added into the scene manager with the following naming scheme: + * path/to/file/file.dea#meshname. The loading of such meshes is logged. + * Currently, this loader is able to create meshes (made of only polygons), lights, + * and cameras. Materials and animations are currently not supported but this will + * change with future releases. + *
Delgine DeleD (.dmf)DeleD (delgine.com) is a 3D editor and level-editor combined into one and is specifically + * designed for 3D game-development. With this loader, it is possible to directly load + * all geometry is as well as textures and lightmaps from .dmf files. To set texture and + * material paths, see scene::DMF_USE_MATERIALS_DIRS and scene::DMF_TEXTURE_PATH. It is also + * possible to flip the alpha texture by setting scene::DMF_FLIP_ALPHA_TEXTURES to true and + * to set the material transparent reference value by setting scene::DMF_ALPHA_CHANNEL_REF to + * a float between 0 and 1. The loader is + * based on Salvatore Russo's .dmf loader, I just changed some parts of it. Thanks to + * Salvatore for his work and for allowing me to use his code in Irrlicht and put it under Irrlicht's + * license. For newer and more enchanced versions of the loader, take a look at delgine.com. + *
DirectX (.x)Platform independent importer (so not D3D-only) for .x files. Most 3D + * packages can export these natively and there are several tools for them + * available. (e.g. the Maya exporter included in the DX SDK) .x files can + * include skeletal animations and Irrlicht is able to play and display them. + * Currently, Irrlicht only supports uncompressed .x files.
Maya (.obj)Most 3D software can create .obj files which contain static geometry without + * material data. The material files .mtl are also supported. This importer + * for Irrlicht can load them directly.
Milkshape (.ms3d).MS3D files contain models and sometimes skeletal animations from the + * Milkshape 3D modeling and animation software. This importer for Irrlicht + * can display and/or animate these files.
My3D (.my3d).my3D is a flexible 3D file format. The My3DTools contains plug-ins to + * export .my3D files from several 3D packages. With this built-in importer, + * Irrlicht can read and display those files directly. This loader was written + * by Zhuck Dimitry who also created the whole My3DTools package. If you are using this loader, please + * note that you can set the path of the textures before loading .my3d files. + * You can do this using SceneManager->getParameters()->setParameter(scene::MY3D_TEXTURE_PATH, + * "path/to/your/textures");
OCT (.oct)The oct file format contains 3D geometry and lightmaps and can be loaded + * directly by Irrlicht. OCT files
+ * can be created by FSRad, Paul Nette's radiosity processor or exported from + * Blender using OCTTools which can be found in the exporters/OCTTools directory + * of the SDK. Thanks to Murphy McCauley for creating all this.
OGRE Meshes (.mesh)Ogre .mesh files contain 3D data for the OGRE 3D engine. Irrlicht can read and + * display them directly with this importer. To define materials for the mesh, + * copy a .material file named like the corresponding .mesh file where the .mesh + * file is. (For example ogrehead.material for ogrehead.mesh). Thanks to Christian Stehno + * who wrote and contributed this loader.
Pulsar LMTools (.lmts)LMTools is a set of tools (Windows & Linux) for creating lightmaps. + * Irrlicht can directly read .lmts files thanks to
+ * the importer created by Jonas Petersen. If you are using this loader, please + * note that you can set the path of the textures before loading .lmts files. + * You can do this using SceneManager->getParameters()->setParameter(scene::LMTS_TEXTURE_PATH, + * "path/to/your/textures"); Notes for
+ * this version of the loader:
+ * - It does not recognice/support user data in the *.lmts files.
+ * - The TGAs generated by LMTools don't work in Irrlicht for some reason (the + * textures are upside down). Opening and resaving them in a graphics app will + * solve the problem.
Quake 3 levels (.bsp)Quake 3 is a popular game by IDSoftware, and .pk3 files contain .bsp files + * and textures/lightmaps describing huge
+ * prelighted levels. Irrlicht can read .pk3 and .bsp files directly and thus + * render Quake 3 levels directly. Written by Nikolaus Gebhardt enhanced by + * Dean P. Macri with the curved surfaces feature.
Quake 2 models (.md2)Quake 2 models are characters with morph target animation. Irrlicht can + * read, display and animate them directly with this importer.
+ * + * To load and display a mesh quickly, just do this: + * \code + * SceneManager->addAnimatedMeshSceneNode( + * SceneManager->getMesh("yourmesh.3ds")); + * \endcode + * If you would like to implement and add your own file format loader to Irrlicht, + * see addExternalMeshLoader(). + * \param filename: Filename of the mesh to load. + * \return Returns NULL if failed and the pointer to the mesh if + * successful. + * This pointer should not be dropped. See IReferenceCounted::drop() for more information. + **/ + virtual IAnimatedMesh* getMesh(const c8* filename) = 0; + + //! Returns an interface to the mesh cache which is shared beween all existing scene managers. + /** With this interface, it is possible to manually add new loaded + meshes (if ISceneManager::getMesh() is not sufficient), to remove them and to iterate + through already loaded meshes. */ + virtual IMeshCache* getMeshCache() = 0; + + //! Returns the video driver. + /** \return Returns pointer to the video Driver. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual video::IVideoDriver* getVideoDriver() = 0; + + //! Returns the active GUIEnvironment + /** \return Returns pointer to the GUIEnvironment + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual gui::IGUIEnvironment* getGUIEnvironment() = 0; + + //! adds Volume Lighting Scene Node. + //! the returned pointer must not be dropped. + // Example Useage: + // scene::ISceneNode * n = smgr->addVolumeLightSceneNode(NULL, -1, + // 32, //Sub Divid U + // 32, //Sub Divid V + // video::SColor(0, 180, 180, 180), //foot colour + // video::SColor(0, 0, 0, 0) //tail colour + // ); + // if (n) { + // n->setScale(core::vector3df(46.0f, 45.0f, 46.0f)); + // n->setPosition(core::vector3df(0,0,0)); + // video::SMaterial& mat = n->getMaterial(0); + // mat.setTexture(0, smgr->getVideoDriver()->getTexture("lightFalloff.png")); + // } + // + virtual ISceneNode* addVolumeLightSceneNode(ISceneNode* parent=0, s32 id=-1, + const s32 subdivU = 32, const s32 subdivV = 32, + const video::SColor foot = video::SColor(51, 0, 230, 180), + const video::SColor tail = video::SColor(0, 0, 0, 0), + const core::vector3df& position = core::vector3df(0,0,0), + const core::vector3df& rotation = core::vector3df(0,0,0), + const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)) = 0; + + + //! Adds a test scene node for test purposes to the scene. + /** It is a simple cube of (1,1,1) size. + \param size: Size of the cube. + \param parent: Parent of the scene node. Can be NULL if no parent. + \param id: Id of the node. This id can be used to identify the scene node. + \param position: Position of the space relative to its parent where the + scene node will be placed. + \param rotation: Initital rotation of the scene node. + \param scale: Initial scale of the scene node. + \return Returns pointer to the created test scene node. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual ISceneNode* addCubeSceneNode(f32 size=10.0f, ISceneNode* parent=0, s32 id=-1, + const core::vector3df& position = core::vector3df(0,0,0), + const core::vector3df& rotation = core::vector3df(0,0,0), + const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)) = 0; + + //! Adds a sphere scene node for test purposes to the scene. + /** It is a simple sphere. + \param radius: Radius of the sphere. + \param polyCount: Polycount of the sphere. + \param parent: Parent of the scene node. Can be NULL if no parent. + \param id: Id of the node. This id can be used to identify the scene node. + \param position: Position of the space relative to its parent where the + scene node will be placed. + \param rotation: Initital rotation of the scene node. + \param scale: Initial scale of the scene node. + \return Returns pointer to the created test scene node. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual ISceneNode* addSphereSceneNode(f32 radius=5.0f, s32 polyCount=16, ISceneNode* parent=0, s32 id=-1, + const core::vector3df& position = core::vector3df(0,0,0), + const core::vector3df& rotation = core::vector3df(0,0,0), + const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)) = 0; + + //! Adds a scene node for rendering an animated mesh model. + /** \param mesh: Pointer to the loaded animated mesh to be displayed. + \param parent: Parent of the scene node. Can be NULL if no parent. + \param id: Id of the node. This id can be used to identify the scene node. + \param position: Position of the space relative to its parent where the + scene node will be placed. + \param rotation: Initital rotation of the scene node. + \param scale: Initial scale of the scene node. + \param alsoAddIfMeshPointerZero: Add the scene node even if a 0 pointer is passed. + \return Returns pointer to the created scene node. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual IAnimatedMeshSceneNode* addAnimatedMeshSceneNode(IAnimatedMesh* mesh, ISceneNode* parent=0, s32 id=-1, + const core::vector3df& position = core::vector3df(0,0,0), + const core::vector3df& rotation = core::vector3df(0,0,0), + const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f), + bool alsoAddIfMeshPointerZero=false) = 0; + + //! Adds a scene node for rendering a static mesh. + /** \param mesh: Pointer to the loaded static mesh to be displayed. + \param parent: Parent of the scene node. Can be NULL if no parent. + \param id: Id of the node. This id can be used to identify the scene node. + \param position: Position of the space relative to its parent where the + scene node will be placed. + \param rotation: Initital rotation of the scene node. + \param scale: Initial scale of the scene node. + \param alsoAddIfMeshPointerZero: Add the scene node even if a 0 pointer is passed. + \return Returns pointer to the created scene node. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual IMeshSceneNode* addMeshSceneNode(IMesh* mesh, ISceneNode* parent=0, s32 id=-1, + const core::vector3df& position = core::vector3df(0,0,0), + const core::vector3df& rotation = core::vector3df(0,0,0), + const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f), + bool alsoAddIfMeshPointerZero=false) = 0; + + //! Adds a scene node for rendering a animated water surface mesh. + /** Looks really good when the Material type EMT_TRANSPARENT_REFLECTION + is used. + \param waveHeight: Height of the water waves. + \param waveSpeed: Speed of the water waves. + \param waveLength: Lenght of a water wave. + \param mesh: Pointer to the loaded static mesh to be displayed with water waves on it. + \param parent: Parent of the scene node. Can be NULL if no parent. + \param id: Id of the node. This id can be used to identify the scene node. + \param position: Position of the space relative to its parent where the + scene node will be placed. + \param rotation: Initital rotation of the scene node. + \param scale: Initial scale of the scene node. + \return Returns pointer to the created scene node. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual ISceneNode* addWaterSurfaceSceneNode(IMesh* mesh, + f32 waveHeight=2.0f, f32 waveSpeed=300.0f, f32 waveLength=10.0f, + ISceneNode* parent=0, s32 id=-1, + const core::vector3df& position = core::vector3df(0,0,0), + const core::vector3df& rotation = core::vector3df(0,0,0), + const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)) = 0; + + + //! Adds a scene node for rendering using a octtree to the scene graph. + /** This a good method for rendering + scenes with lots of geometry. The Octree is built on the fly from the mesh. + \param mesh: The mesh containing all geometry from which the octtree will be build. + If this animated mesh has more than one frames in it, the first frame is taken. + \param parent: Parent node of the octtree node. + \param id: id of the node. This id can be used to identify the node. + \param minimalPolysPerNode: Specifies the minimal polygons contained a octree node. + If a node gets less polys than this value it will not be split into + smaller nodes. + \param alsoAddIfMeshPointerZero: Add the scene node even if a 0 pointer is passed. + \return Returns the pointer to the OctTree if successful, otherwise 0. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual ISceneNode* addOctTreeSceneNode(IAnimatedMesh* mesh, ISceneNode* parent=0, + s32 id=-1, s32 minimalPolysPerNode=256, bool alsoAddIfMeshPointerZero=false) = 0; + + //! Adds a scene node for rendering using a octtree to the scene graph. + /** This a good method for rendering + scenes with lots of geometry. The Octree is built on the fly from the mesh, much + faster then a bsp tree. + \param mesh: The mesh containing all geometry from which the octtree will be build. + \param parent: Parent node of the octtree node. + \param id: id of the node. This id can be used to identify the node. + \param minimalPolysPerNode: Specifies the minimal polygons contained a octree node. + If a node gets less polys than this value it will not be split into + smaller nodes. + \param alsoAddIfMeshPointerZero: Add the scene node even if a 0 pointer is passed. + \return Returns the pointer to the octtree if successful, otherwise 0. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual ISceneNode* addOctTreeSceneNode(IMesh* mesh, ISceneNode* parent=0, + s32 id=-1, s32 minimalPolysPerNode=256, bool alsoAddIfMeshPointerZero=false) = 0; + + //! Adds a camera scene node to the scene graph and sets it as active camera. + /** This camera does not react on user input like for example the one created with + addCameraSceneNodeFPS(). If you want to move or animate it, use animators or the + ISceneNode::setPosition(), ICameraSceneNode::setTarget() etc methods. + \param position: Position of the space relative to its parent where the camera will be placed. + \param lookat: Position where the camera will look at. Also known as target. + \param parent: Parent scene node of the camera. Can be null. If the parent moves, + the camera will move too. + \param id: id of the camera. This id can be used to identify the camera. + \return Returns pointer to interface to camera if successful, otherwise 0. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual ICameraSceneNode* addCameraSceneNode(ISceneNode* parent = 0, + const core::vector3df& position = core::vector3df(0,0,0), + const core::vector3df& lookat = core::vector3df(0,0,100), s32 id=-1) = 0; + + //! Adds a maya style user controlled camera scene node to the scene graph. + /** The maya camera is able to be controlled with the mouse similar + like in the 3D Software Maya by Alias Wavefront. + \param parent: Parent scene node of the camera. Can be null. + \param rotateSpeed: Rotation speed of the camera. + \param zoomSpeed: Zoom speed of the camera. + \param translationSpeed: TranslationSpeed of the camera. + \param id: id of the camera. This id can be used to identify the camera. + \return Returns a pointer to the interface of the camera if successful, otherwise 0. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual ICameraSceneNode* addCameraSceneNodeMaya(ISceneNode* parent = 0, + f32 rotateSpeed = -1500.0f, f32 zoomSpeed = 200.0f, f32 translationSpeed = 1500.0f, s32 id=-1) = 0; + + //! Adds a camera scene node which is able to be controlled with the mouse and keys like in most first person shooters (FPS). + /** Look with the mouse, move with cursor keys. If you do not like the default + key layout, you may want to specify your own. For example to make the camera + be controlled by the cursor keys AND the keys W,A,S, and D, do something + like this: + \code + SKeyMap keyMap[8]; + keyMap[0].Action = EKA_MOVE_FORWARD; + keyMap[0].KeyCode = KEY_UP; + keyMap[1].Action = EKA_MOVE_FORWARD; + keyMap[1].KeyCode = KEY_KEY_W; + + keyMap[2].Action = EKA_MOVE_BACKWARD; + keyMap[2].KeyCode = KEY_DOWN; + keyMap[3].Action = EKA_MOVE_BACKWARD; + keyMap[3].KeyCode = KEY_KEY_S; + + keyMap[4].Action = EKA_STRAFE_LEFT; + keyMap[4].KeyCode = KEY_LEFT; + keyMap[5].Action = EKA_STRAFE_LEFT; + keyMap[5].KeyCode = KEY_KEY_A; + + keyMap[6].Action = EKA_STRAFE_RIGHT; + keyMap[6].KeyCode = KEY_RIGHT; + keyMap[7].Action = EKA_STRAFE_RIGHT; + keyMap[7].KeyCode = KEY_KEY_D; + + camera = sceneManager->addCameraSceneNodeFPS(0, 100, 500, -1, keyMap, 8); + \endcode + \param parent: Parent scene node of the camera. Can be null. + \param rotateSpeed: Speed with which the camera is rotated. This can be done + only with the mouse. + \param moveSpeed: Speed with which the camera is moved. Movement is done with + the cursor keys. + \param id: id of the camera. This id can be used to identify the camera. + \param keyMapArray: Optional pointer to an array of a keymap, specifying what + keys should be used to move the camera. If this is null, the default keymap + is used. You can define actions more then one time in the array, to bind + multiple keys to the same action. + \param keyMapSize: Amount of items in the keymap array. + \param noVerticalMovement: Setting this to true makes the camera only move within a + horizontal plane, and disables vertical movement as known from most ego shooters. Default + is 'false', with which it is possible to fly around in space, if no gravity is there. + \param jumpSpeed: Speed with which the camera is moved when jumping. + \return Returns a pointer to the interface of the camera if successful, otherwise 0. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual ICameraSceneNode* addCameraSceneNodeFPS(ISceneNode* parent = 0, + f32 rotateSpeed = 100.0f, f32 moveSpeed = 500.0f, s32 id=-1, + SKeyMap* keyMapArray=0, s32 keyMapSize=0, bool noVerticalMovement=false, + f32 jumpSpeed = 0.f) = 0; + + //! Adds a dynamic light scene node to the scene graph. + /** The light will cast dynamic light on all + other scene nodes in the scene, which have the material flag video::MTF_LIGHTING + turned on. (This is the default setting in most scene nodes). + \param parent: Parent scene node of the light. Can be null. If the parent moves, + the light will move too. + \param position: Position of the space relative to its parent where the light will be placed. + \param color: Diffuse color of the light. Ambient or Specular colors can be set manually with + the ILightSceneNode::getLightData() method. + \param radius: Radius of the light. + \param id: id of the node. This id can be used to identify the node. + \return Returns pointer to the interface of the light if successful, otherwise NULL. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual ILightSceneNode* addLightSceneNode(ISceneNode* parent = 0, + const core::vector3df& position = core::vector3df(0,0,0), + video::SColorf color = video::SColorf(1.0f, 1.0f, 1.0f), + f32 radius=100.0f, s32 id=-1) = 0; + + //! Adds a billboard scene node to the scene graph. + /** A billboard is like a 3d sprite: A 2d element, + which always looks to the camera. It is usually used for things like explosions, fire, + lensflares and things like that. + \param parent: Parent scene node of the billboard. Can be null. If the parent moves, + the billboard will move too. + \param position: Position of the space relative to its parent where the billboard will be placed. + \param size: Size of the billboard. This size is 2 dimensional because a billboard only has + width and height. + \param id: An id of the node. This id can be used to identify the node. + \param shade_top: vertex color top + \param shade_down: vertex color down + \return Returns pointer to the billboard if successful, otherwise NULL. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual IBillboardSceneNode* addBillboardSceneNode(ISceneNode* parent = 0, + const core::dimension2d& size = core::dimension2d(10.0f, 10.0f), + const core::vector3df& position = core::vector3df(0,0,0), s32 id=-1, + video::SColor shade_top = 0xFFFFFFFF, video::SColor shade_down = 0xFFFFFFFF) = 0; + + //! Adds a skybox scene node to the scene graph. + /** A skybox is a big cube with 6 textures on it and + is drawn around the camera position. + \param top: Texture for the top plane of the box. + \param bottom: Texture for the bottom plane of the box. + \param left: Texture for the left plane of the box. + \param right: Texture for the right plane of the box. + \param front: Texture for the front plane of the box. + \param back: Texture for the back plane of the box. + \param parent: Parent scene node of the skybox. A skybox usually has no parent, + so this should be null. Note: If a parent is set to the skybox, the box will not + change how it is drawn. + \param id: An id of the node. This id can be used to identify the node. + \return Returns a pointer to the sky box if successful, otherwise NULL. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual ISceneNode* addSkyBoxSceneNode(video::ITexture* top, video::ITexture* bottom, + video::ITexture* left, video::ITexture* right, video::ITexture* front, + video::ITexture* back, ISceneNode* parent = 0, s32 id=-1) = 0; + + //! Adds a skydome scene node to the scene graph. + /** A skydome is a large (half-) sphere with a panoramic texture + on the inside and is drawn around the camera position. + \param texture: Texture for the dome. + \param horiRes: Number of vertices of a horizontal layer of the sphere. + \param vertRes: Number of vertices of a vertical layer of the sphere. + \param texturePercentage: How much of the height of the texture is used. Should be between 0 and 1. + \param spherePercentage: How much of the sphere is drawn. Value should be between 0 and 2, where 1 is an exact half-sphere and 2 is a full sphere. + \param parent: Parent scene node of the dome. A dome usually has no parent, + so this should be null. Note: If a parent is set, the dome will not + change how it is drawn. + \param id: An id of the node. This id can be used to identify the node. + \return Returns a pointer to the sky dome if successful, otherwise NULL. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual ISceneNode* addSkyDomeSceneNode(video::ITexture* texture, + u32 horiRes, u32 vertRes, f64 texturePercentage, f64 spherePercentage, + ISceneNode* parent = 0, s32 id=-1) = 0; + + //! Adds a particle system scene node to the scene graph. + /** \param withDefaultEmitter: Creates a default working point emitter + which emitts some particles. Set this to true to see a particle system + in action. If set to false, you'll have to set the emitter you want by + calling IParticleSystemSceneNode::setEmitter(). + \param parent: Parent of the scene node. Can be NULL if no parent. + \param id: Id of the node. This id can be used to identify the scene node. + \param position: Position of the space relative to its parent where the + scene node will be placed. + \param rotation: Initital rotation of the scene node. + \param scale: Initial scale of the scene node. + \return Returns pointer to the created scene node. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual IParticleSystemSceneNode* addParticleSystemSceneNode( + bool withDefaultEmitter=true, ISceneNode* parent=0, s32 id=-1, + const core::vector3df& position = core::vector3df(0,0,0), + const core::vector3df& rotation = core::vector3df(0,0,0), + const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)) = 0; + + //! Adds a terrain scene node to the scene graph. + /** This node implements is a simple terrain renderer which uses + a technique known as geo mip mapping + for reducing the detail of triangle blocks which are far away. + The code for the TerrainSceneNode is based on the terrain + renderer by Soconne and the GeoMipMapSceneNode developed by + Spintz. They made their code available for Irrlicht and allowed + it to be distributed under this licence. I only modified some + parts. A lot of thanks go to them. + + This scene node is capable of loading terrains and updating + the indices at runtime to enable viewing very large terrains + very quickly. It uses a CLOD (Continuous Level of Detail) + algorithm which updates the indices for each patch based on + a LOD (Level of Detail) which is determined based on a patch's + distance from the camera. + + The patch size of the terrain must always be a size of ( 2^N+1, i.e. 8+1(9), 16+1(17), etc. ). + The MaxLOD available is directly dependent on the patch size of the terrain. LOD 0 contains all + of the indices to draw all the triangles at the max detail for a patch. As each LOD goes up by 1 + the step taken, in generating indices increases by - 2^LOD, so for LOD 1, the step taken is 2, for + LOD 2, the step taken is 4, LOD 3 - 8, etc. The step can be no larger than the size of the patch, + so having a LOD of 8, with a patch size of 17, is asking the algoritm to generate indices every + 2^8 ( 256 ) vertices, which is not possible with a patch size of 17. The maximum LOD for a patch + size of 17 is 2^4 ( 16 ). So, with a MaxLOD of 5, you'll have LOD 0 ( full detail ), LOD 1 ( every + 2 vertices ), LOD 2 ( every 4 vertices ), LOD 3 ( every 8 vertices ) and LOD 4 ( every 16 vertices ). + \param heightMapFileName: The name of the file on disk, to read vertex data from. This should + be a gray scale bitmap. + \param parent: Parent of the scene node. Can be 0 if no parent. + \param id: Id of the node. This id can be used to identify the scene node. + \param position: The absolute position of this node. + \param rotation: The absolute rotation of this node. ( NOT YET IMPLEMENTED ) + \param scale: The scale factor for the terrain. If you're using a heightmap of size 129x129 and would like + your terrain to be 12900x12900 in game units, then use a scale factor of ( core::vector ( 100.0f, 100.0f, 100.0f ). + If you use a Y scaling factor of 0.0f, then your terrain will be flat. + \param vertexColor: The default color of all the vertices. If no texture is associated + with the scene node, then all vertices will be this color. Defaults to white. + \param maxLOD: The maximum LOD (level of detail) for the node. Only change if you + know what you are doing, this might lead to strange behaviour. + \param patchSize: patch size of the terrain. Only change if you + know what you are doing, this might lead to strange behaviour. + \param smoothFactor: The number of times the vertices are smoothed. + \param addAlsoIfHeightmapEmpty: Add terrain node even with empty heightmap. + \return Returns pointer to the created scene node. Can be null if the + terrain could not be created, for example because the heightmap could not be loaded. + The returned pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual ITerrainSceneNode* addTerrainSceneNode( + const c8* heightMapFileName, + ISceneNode* parent=0, s32 id=-1, + const core::vector3df& position = core::vector3df(0.0f,0.0f,0.0f), + const core::vector3df& rotation = core::vector3df(0.0f,0.0f,0.0f), + const core::vector3df& scale = core::vector3df(1.0f,1.0f,1.0f), + video::SColor vertexColor = video::SColor(255,255,255,255), + s32 maxLOD=5, E_TERRAIN_PATCH_SIZE patchSize=ETPS_17, s32 smoothFactor=0, + bool addAlsoIfHeightmapEmpty = false) = 0; + + //! Adds a terrain scene node to the scene graph. + /** Just like the other addTerrainSceneNode() method, but takes an IReadFile + pointer as parameter for the heightmap. For more informations take a look + at the other function. + \param heightMapFile: The file handle to read vertex data from. This should + be a gray scale bitmap. + \param parent: Parent of the scene node. Can be 0 if no parent. + \param id: Id of the node. This id can be used to identify the scene node. + \param position: The absolute position of this node. + \param rotation: The absolute rotation of this node. ( NOT YET IMPLEMENTED ) + \param scale: The scale factor for the terrain. If you're using a heightmap of size 129x129 and would like + your terrain to be 12900x12900 in game units, then use a scale factor of ( core::vector ( 100.0f, 100.0f, 100.0f ). + If you use a Y scaling factor of 0.0f, then your terrain will be flat. + \param vertexColor: The default color of all the vertices. If no texture is associated + with the scene node, then all vertices will be this color. Defaults to white. + \param maxLOD: The maximum LOD (level of detail) for the node. Only change if you + know what you are doing, this might lead to strange behaviour. + \param patchSize: patch size of the terrain. Only change if you + know what you are doing, this might lead to strange behaviour. + \param smoothFactor: The number of times the vertices are smoothed. + \param addAlsoIfHeightmapEmpty: Add terrain node even with empty heightmap. + \return Returns pointer to the created scene node. Can be null if the + terrain could not be created, for example because the heightmap could not be loaded. + The returned pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual ITerrainSceneNode* addTerrainSceneNode( + io::IReadFile* heightMapFile, + ISceneNode* parent=0, s32 id=-1, + const core::vector3df& position = core::vector3df(0.0f,0.0f,0.0f), + const core::vector3df& rotation = core::vector3df(0.0f,0.0f,0.0f), + const core::vector3df& scale = core::vector3df(1.0f,1.0f,1.0f), + video::SColor vertexColor = video::SColor(255,255,255,255), + s32 maxLOD=5, E_TERRAIN_PATCH_SIZE patchSize=ETPS_17, s32 smoothFactor=0, + bool addAlsoIfHeightmapEmpty = false) = 0; + + //! Adds a quake3 scene node to the scene graph. + /** A Quake3 Scene renders multiple meshes for a specific HighLanguage Shader (Quake3 Style ) + \return Returns a pointer to the quake3 scene node if successful, otherwise NULL. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual ISceneNode* addQuake3SceneNode(IMeshBuffer* meshBuffer, const quake3::SShader * shader, + ISceneNode* parent=0, s32 id=-1 + ) = 0; + + + //! Adds an empty scene node to the scene graph. + /** Can be used for doing advanced transformations + or structuring the scene graph. + \return Returns pointer to the created scene node. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual ISceneNode* addEmptySceneNode(ISceneNode* parent=0, s32 id=-1) = 0; + + //! Adds a dummy transformation scene node to the scene graph. + /** This scene node does not render itself, and does not respond to set/getPosition, + set/getRotation and set/getScale. Its just a simple scene node that takes a + matrix as relative transformation, making it possible to insert any transformation + anywhere into the scene graph. + \return Returns pointer to the created scene node. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual IDummyTransformationSceneNode* addDummyTransformationSceneNode( + ISceneNode* parent=0, s32 id=-1) = 0; + + //! Adds a text scene node, which is able to display 2d text at a position in three dimensional space + virtual ITextSceneNode* addTextSceneNode(gui::IGUIFont* font, const wchar_t* text, + video::SColor color=video::SColor(100,255,255,255), + ISceneNode* parent = 0, const core::vector3df& position = core::vector3df(0,0,0), + s32 id=-1) = 0; + + //! Adds a text scene node, which uses billboards + virtual ITextSceneNode* addBillboardTextSceneNode( gui::IGUIFont* font, const wchar_t* text, + ISceneNode* parent = 0, + const core::dimension2d& size = core::dimension2d(10.0f, 10.0f), + const core::vector3df& position = core::vector3df(0,0,0), s32 id=-1, + video::SColor shade_top = 0xFFFFFFFF, video::SColor shade_down = 0xFFFFFFFF) = 0; + + //! Adds a Hill Plane mesh to the mesh pool. + /** The mesh is generated on the fly + and looks like a plane with some hills on it. It is uses mostly for quick + tests of the engine only. You can specify how many hills there should be + on the plane and how high they should be. Also you must specify a name for + the mesh, because the mesh is added to the mesh pool, and can be retrieved + again using ISceneManager::getMesh() with the name as parameter. + \param name: The name of this mesh which must be specified in order + to be able to retrieve the mesh later with ISceneManager::getMesh(). + \param tileSize: Size of a tile of the mesh. (10.0f, 10.0f) would be a + good value to start, for example. + \param tileCount: Specifies how much tiles there will be. If you specifiy + for example that a tile has the size (10.0f, 10.0f) and the tileCount is + (10,10), than you get a field of 100 tiles which has the dimension 100.0fx100.0f. + \param material: Material of the hill mesh. + \param hillHeight: Height of the hills. If you specify a negative value + you will get holes instead of hills. If the height is 0, no hills will be + created. + \param countHills: Amount of hills on the plane. There will be countHills.X + hills along the X axis and countHills.Y along the Y axis. So in total there + will be countHills.X * countHills.Y hills. + \param textureRepeatCount: Defines how often the texture will be repeated in + x and y direction. + \return Returns null if the creation failed. The reason could be that you + specified some invalid parameters or that a mesh with that name already + exists. If successful, a pointer to the mesh is returned. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual IAnimatedMesh* addHillPlaneMesh(const c8* name, + const core::dimension2d& tileSize, const core::dimension2d& tileCount, + video::SMaterial* material = 0, f32 hillHeight = 0.0f, + const core::dimension2d& countHills = core::dimension2d(0.0f, 0.0f), + const core::dimension2d& textureRepeatCount = core::dimension2d(1.0f, 1.0f)) = 0; + + //! Adds a static terrain mesh to the mesh pool. + /** The mesh is generated on the fly + from a texture file and a height map file. Both files may be huge + (8000x8000 pixels would be no problem) because the generator splits the + files into smaller textures if necessary. + You must specify a name for the mesh, because the mesh is added to the mesh pool, + and can be retrieved again using ISceneManager::getMesh() with the name as parameter. + \param meshname: The name of this mesh which must be specified in order + to be able to retrieve the mesh later with ISceneManager::getMesh(). + \param texture: Texture for the terrain. Please note that this is not a + hardware texture as usual (ITexture), but an IImage software texture. + You can load this texture with IVideoDriver::createImageFromFile(). + \param heightmap: A grayscaled heightmap image. Like the texture, + it can be created with IVideoDriver::createImageFromFile(). The amount + of triangles created depends on the size of this texture, so use a small + heightmap to increase rendering speed. + \param stretchSize: Parameter defining how big a is pixel on the heightmap. + \param maxHeight: Defines how height a white pixel on the heighmap is. + \param defaultVertexBlockSize: Defines the initial dimension between vertices. + \return Returns null if the creation failed. The reason could be that you + specified some invalid parameters, that a mesh with that name already + exists, or that a texture could not be found. If successful, a pointer to the mesh is returned. + This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ + virtual IAnimatedMesh* addTerrainMesh(const c8* meshname, + video::IImage* texture, video::IImage* heightmap, + const core::dimension2d& stretchSize = core::dimension2d(10.0f,10.0f), + f32 maxHeight=200.0f, + const core::dimension2d& defaultVertexBlockSize = core::dimension2d(64,64)) = 0; + + //! add a static arrow mesh to the meshpool + virtual IAnimatedMesh* addArrowMesh(const c8* name, + video::SColor vtxColor0=0xFFFFFFFF, + video::SColor vtxColor1=0xFFFFFFFF, + u32 tesselationCylinder=4, u32 tesselationCone=8, + f32 height=1.f, f32 cylinderHeight=0.6f, + f32 width0=0.05f, f32 width1=0.3f) = 0; + + //! add a static sphere mesh to the meshpool + virtual IAnimatedMesh* addSphereMesh(const c8* name, + f32 radius=5.f, u32 polyCountX = 16, + u32 polyCountY = 16) = 0; + + //! Returns the root scene node. + /** This is the scene node which is parent + of all scene nodes. The root scene node is a special scene node which + only exists to manage all scene nodes. It will not be rendered and cannot + be removed from the scene. + \return Returns a pointer to the root scene node. */ + virtual ISceneNode* getRootSceneNode() = 0; + + //! Returns the first scene node with the specified id. + /** \param id: The id to search for + \param start: Scene node to start from. All children of this scene + node are searched. If null is specified, the root scene node is + taken. + \return Returns pointer to the first scene node with this id, + and null if no scene node could be found. */ + virtual ISceneNode* getSceneNodeFromId(s32 id, ISceneNode* start=0) = 0; + + //! Returns the first scene node with the specified name. + /** \param name: The name to search for + \param start: Scene node to start from. All children of this scene + node are searched. If null is specified, the root scene node is + taken. + \return Returns pointer to the first scene node with this id, + and null if no scene node could be found. */ + virtual ISceneNode* getSceneNodeFromName(const c8* name, ISceneNode* start=0) = 0; + + //! Returns the first scene node with the specified type. + /** \param type: The type to search for + \param start: Scene node to start from. All children of this scene + node are searched. If null is specified, the root scene node is + taken. + \return Returns pointer to the first scene node with this type, + and null if no scene node could be found. */ + virtual ISceneNode* getSceneNodeFromType(scene::ESCENE_NODE_TYPE type, ISceneNode* start=0) = 0; + + //! returns scene nodes by type. + /** \param type: Type of scene node to find. + \param outNodes: array to be filled with results. + \param start: Scene node to start from. All children of this scene + node are searched. If null is specified, the root scene node is + taken. */ + virtual void getSceneNodesFromType(ESCENE_NODE_TYPE type, core::array& outNodes, ISceneNode* start=0) = 0; + + //! Returns the current active camera. + /** \return The active camera is returned. Note that this can be NULL, if there + was no camera created yet. */ + virtual ICameraSceneNode* getActiveCamera() = 0; + + //! Sets the currently active camera. + /** The previous active camera will be deactivated. + \param camera: The new camera which should be active. */ + virtual void setActiveCamera(ICameraSceneNode* camera) = 0; + + //! Sets the color of stencil buffers shadows drawn by the scene manager. + virtual void setShadowColor(video::SColor color = video::SColor(150,0,0,0)) = 0; + + //! Returns the current color of shadows. + virtual video::SColor getShadowColor() const = 0; + + //! Registers a node for rendering it at a specific time. + /** This method should only be used by SceneNodes when they get a + ISceneNode::OnRegisterSceneNode() call. + \param node: Node to register for drawing. Usually scene nodes would set 'this' + as parameter here because they want to be drawn. + \param pass: Specifies when the mode wants to be drawn in relation to the other nodes. + For example, if the node is a shadow, it usually wants to be drawn after all other nodes + and will use ESNRP_SHADOW for this. See E_SCENE_NODE_RENDER_PASS for details. + \return scene will be rendered ( passed culling ) */ + virtual u32 registerNodeForRendering(ISceneNode* node, + E_SCENE_NODE_RENDER_PASS pass = ESNRP_AUTOMATIC) = 0; + + //! Draws all the scene nodes. + /** This can only be invoked between + IVideoDriver::beginScene() and IVideoDriver::endScene(). Please note that + the scene is not only drawn when calling this, but also animated + by existing scene node animators, culling of scene nodes is done, etc. */ + virtual void drawAll() = 0; + + //! Creates a rotation animator, which rotates the attached scene node around itself. + /** \param rotationPerSecond: Specifies the speed of the animation + \return Returns the animator. Attach it to a scene node with ISceneNode::addAnimator() + and the animator will animate it. + If you no longer need the animator, you should call ISceneNodeAnimator::drop(). + See IReferenceCounted::drop() for more information. */ + virtual ISceneNodeAnimator* createRotationAnimator(const core::vector3df& rotationPerSecond) = 0; + + //! Creates a fly circle animator, which lets the attached scene node fly around a center. + /** \param center: Center of the circle. + \param radius: Radius of the circle. + \param speed: Specifies the speed of the flight. + \param direction: Specifies the upvector used for alignment of the mesh. + \return Returns the animator. Attach it to a scene node with ISceneNode::addAnimator() + and the animator will animate it. + If you no longer need the animator, you should call ISceneNodeAnimator::drop(). + See IReferenceCounted::drop() for more information. */ + virtual ISceneNodeAnimator* createFlyCircleAnimator(const core::vector3df& center, + f32 radius, f32 speed=0.001f, const core::vector3df& direction= core::vector3df ( 0.f, 1.f, 0.f ) ) = 0; + + //! Creates a fly straight animator, which lets the attached scene node fly or move along a line between two points. + /** \param startPoint: Start point of the line. + \param endPoint: End point of the line. + \param timeForWay: Time in milli seconds how long the node should need to + move from the start point to the end point. + \param loop: If set to false, the node stops when the end point is reached. + If loop is true, the node begins again at the start. + \return Returns the animator. Attach it to a scene node with ISceneNode::addAnimator() + and the animator will animate it. + If you no longer need the animator, you should call ISceneNodeAnimator::drop(). + See IReferenceCounted::drop() for more information. */ + virtual ISceneNodeAnimator* createFlyStraightAnimator(const core::vector3df& startPoint, + const core::vector3df& endPoint, u32 timeForWay, bool loop=false) = 0; + + //! Creates a texture animator, which switches the textures of the target scene node based on a list of textures. + /** \param textures: List of textures to use. + \param timePerFrame: Time in milliseconds, how long any texture in the list + should be visible. + \param loop: If set to to false, the last texture remains set, and the animation + stops. If set to true, the animation restarts with the first texture. + \return Returns the animator. Attach it to a scene node with ISceneNode::addAnimator() + and the animator will animate it. + If you no longer need the animator, you should call ISceneNodeAnimator::drop(). + See IReferenceCounted::drop() for more information. */ + virtual ISceneNodeAnimator* createTextureAnimator(const core::array& textures, + s32 timePerFrame, bool loop=true) = 0; + + //! Creates a scene node animator, which deletes the scene node after some time automatically. + /** \param timeMs: Time in milliseconds, after when the node will be deleted. + \return Returns the animator. Attach it to a scene node with ISceneNode::addAnimator() + and the animator will animate it. + If you no longer need the animator, you should call ISceneNodeAnimator::drop(). + See IReferenceCounted::drop() for more information. */ + virtual ISceneNodeAnimator* createDeleteAnimator(u32 timeMs) = 0; + + //! Creates a special scene node animator for doing automatic collision detection and response. + /** See ISceneNodeAnimatorCollisionResponse for details. + \param world: Triangle selector holding all triangles of the world with which + the scene node may collide. You can create a triangle selector with + ISceneManager::createTriangleSelector(); + \param sceneNode: SceneNode which should be manipulated. After you added this animator + to the scene node, the scene node will not be able to move through walls and is + affected by gravity. + \param ellipsoidRadius: Radius of the ellipsoid with which collision detection and + response is done. If you have got a scene node, and you are unsure about + how big the radius should be, you could use the following code to determine + it: + \code + const core::aabbox& box = yourSceneNode->getBoundingBox(); + core::vector3df radius = box.MaxEdge - box.getCenter(); + \endcode + \param gravityPerSecond: Sets the gravity of the environment. A good example value would be + core::vector3df(0,-100.0f,0) for letting gravity affect all object to + fall down. For bigger gravity, make increase the length of the vector. + You can disable gravity by setting it to core::vector3df(0,0,0). + \param ellipsoidTranslation: By default, the ellipsoid for collision detection is created around + the center of the scene node, which means that the ellipsoid surrounds + it completely. If this is not what you want, you may specify a translation + for the ellipsoid. + \param slidingValue: DOCUMENTATION NEEDED. + \return Returns the animator. Attach it to a scene node with ISceneNode::addAnimator() + and the animator will cause it to do collision detection and response. + If you no longer need the animator, you should call ISceneNodeAnimator::drop(). + See IReferenceCounted::drop() for more information. */ + virtual ISceneNodeAnimatorCollisionResponse* createCollisionResponseAnimator( + ITriangleSelector* world, ISceneNode* sceneNode, + const core::vector3df& ellipsoidRadius = core::vector3df(30,60,30), + const core::vector3df& gravityPerSecond = core::vector3df(0,-100.0f,0), + const core::vector3df& ellipsoidTranslation = core::vector3df(0,0,0), + f32 slidingValue = 0.0005f) = 0; + + //! Creates a follow spline animator. + /** The animator modifies the position of + the attached scene node to make it follow a hermite spline. + The code of the is based on a scene node + Matthias Gall sent in. Thanks! I adapted the code just a little bit. Matthias + wrote: + Uses a subset of hermite splines: either cardinal splines (tightness != 0.5) or catmull-rom-splines (tightness == 0.5) + but this is just my understanding of this stuff, I'm not a mathematician, so this might be wrong ;) */ + virtual ISceneNodeAnimator* createFollowSplineAnimator(s32 startTime, + const core::array< core::vector3df >& points, + f32 speed = 1.0f, f32 tightness = 0.5f) = 0; + + //! Creates a simple ITriangleSelector, based on a mesh. + /** Triangle selectors + can be used for doing collision detection. Don't use this selector + for a huge amount of triangles like in Quake3 maps. + Instead, use for example ISceneManager::createOctTreeTriangleSelector(). + Please note that the created triangle selector is not automaticly attached + to the scene node. You will have to call ISceneNode::setTriangleSelector() + for this. To create and attach a triangle selector is done like this: + \code + ITriangleSelector* s = sceneManager->createTriangleSelector(yourMesh, + yourSceneNode); + yourSceneNode->setTriangleSelector(s); + s->drop(); + \endcode + \param mesh: Mesh of which the triangles are taken. + \param node: Scene node of which visibility and transformation is used. + \return Returns the selector, or null if not successful. + If you no longer need the selector, you should call ITriangleSelector::drop(). + See IReferenceCounted::drop() for more information. */ + virtual ITriangleSelector* createTriangleSelector(IMesh* mesh, ISceneNode* node) = 0; + + //! Creates a simple dynamic ITriangleSelector, based on a axis aligned bounding box. + /** Triangle selectors + can be used for doing collision detection. Every time when triangles are + queried, the triangle selector gets the bounding box of the scene node, + an creates new triangles. In this way, it works good with animated scene nodes. + \param node: Scene node of which the bounding box, visibility and transformation is used. + \return Returns the selector, or null if not successful. + If you no longer need the selector, you should call ITriangleSelector::drop(). + See IReferenceCounted::drop() for more information. */ + virtual ITriangleSelector* createTriangleSelectorFromBoundingBox(ISceneNode* node) = 0; + + //! Creates a Triangle Selector, optimized by an octtree. + /** Triangle selectors + can be used for doing collision detection. This triangle selector is + optimized for huge amounts of triangle, it organizes them in an octtree. + Please note that the created triangle selector is not automaticly attached + to the scene node. You will have to call ISceneNode::setTriangleSelector() + for this. To create and attach a triangle selector is done like this: + \code + ITriangleSelector* s = sceneManager->createOctTreeTriangleSelector(yourMesh, + yourSceneNode); + yourSceneNode->setTriangleSelector(s); + s->drop(); + \endcode + For more informations and examples on this, take a look at the collision + tutorial in the SDK. + \param mesh: Mesh of which the triangles are taken. + \param node: Scene node of which visibility and transformation is used. + \param minimalPolysPerNode: Specifies the minimal polygons contained a octree node. + If a node gets less polys the this value, it will not be splitted into + smaller nodes. + \return Returns the selector, or null if not successful. + If you no longer need the selector, you should call ITriangleSelector::drop(). + See IReferenceCounted::drop() for more information. */ + virtual ITriangleSelector* createOctTreeTriangleSelector(IMesh* mesh, + ISceneNode* node, s32 minimalPolysPerNode=32) = 0; + + //! Creates a meta triangle selector. + /** A meta triangle selector is nothing more than a + collection of one or more triangle selectors providing together + the interface of one triangle selector. In this way, + collision tests can be done with different triangle soups in one pass. + \return Returns the selector, or null if not successful. + If you no longer need the selector, you should call ITriangleSelector::drop(). + See IReferenceCounted::drop() for more information. */ + virtual IMetaTriangleSelector* createMetaTriangleSelector() = 0; + + //! Creates a triangle selector which can select triangles from a terrain scene node. + /** \param node: Pointer to the created terrain scene node + \param LOD: Level of detail, 0 for highest detail. */ + virtual ITriangleSelector* createTerrainTriangleSelector( + ITerrainSceneNode* node, s32 LOD=0) = 0; + + //! Adds an external mesh loader for extending the engine with new file formats. + /** If you want the engine to be extended with + file formats it currently is not able to load (e.g. .cob), just implement + the IMeshLoader interface in your loading class and add it with this method. + Using this method it is also possible to override built-in mesh loaders with + newer or updated versions without the need of recompiling the engine. + \param externalLoader: Implementation of a new mesh loader. */ + virtual void addExternalMeshLoader(IMeshLoader* externalLoader) = 0; + + //! Returns a pointer to the scene collision manager. + virtual ISceneCollisionManager* getSceneCollisionManager() = 0; + + //! Returns a pointer to the mesh manipulator. + virtual IMeshManipulator* getMeshManipulator() = 0; + + //! Adds a scene node to the deletion queue. + /** The scene node is immediatly + deleted when it's secure. Which means when the scene node does not + execute animators and things like that. This method is for example + used for deleting scene nodes by their scene node animators. In + most other cases, a ISceneNode::remove() call is enough, using this + deletion queue is not necessary. + See ISceneManager::createDeleteAnimator() for details. + \param node: Node to detete. */ + virtual void addToDeletionQueue(ISceneNode* node) = 0; + + //! Posts an input event to the environment. + /** Usually you do not have to + use this method, it is used by the internal engine. */ + virtual bool postEventFromUser(const SEvent& event) = 0; + + //! Clears the whole scene. + /** All scene nodes are removed. */ + virtual void clear() = 0; + + //! Returns interface to the parameters set in this scene. + /** String parameters can be used by plugins and mesh loaders. + For example the CMS and LMTS loader want a parameter named 'CSM_TexturePath' + and 'LMTS_TexturePath' set to the path were attached textures can be found. See + CSM_TEXTURE_PATH, LMTS_TEXTURE_PATH, MY3D_TEXTURE_PATH, + COLLADA_CREATE_SCENE_INSTANCES, DMF_TEXTURE_PATH and DMF_USE_MATERIALS_DIRS*/ + virtual io::IAttributes* getParameters() = 0; + + //! Returns current render pass. + /** All scene nodes are being rendered in a specific order. + First lights, cameras, sky boxes, solid geometry, and then transparent + stuff. During the rendering process, scene nodes may want to know what the scene + manager is rendering currently, because for example they registered for rendering + twice, once for transparent geometry and once for solid. When knowing what rendering + pass currently is active they can render the correct part of their geometry. */ + virtual E_SCENE_NODE_RENDER_PASS getSceneNodeRenderPass() const = 0; + + //! Returns the default scene node factory which can create all built in scene nodes + virtual ISceneNodeFactory* getDefaultSceneNodeFactory() = 0; + + //! Adds a scene node factory to the scene manager. + /** Use this to extend the scene manager with new scene node types which it should be + able to create automaticly, for example when loading data from xml files. */ + virtual void registerSceneNodeFactory(ISceneNodeFactory* factoryToAdd) = 0; + + //! Returns amount of registered scene node factories. + virtual u32 getRegisteredSceneNodeFactoryCount() const = 0; + + //! Returns a scene node factory by index + virtual ISceneNodeFactory* getSceneNodeFactory(u32 index) = 0; + + //! Returns the default scene node animator factory which can create all built-in scene node animators + virtual ISceneNodeAnimatorFactory* getDefaultSceneNodeAnimatorFactory() = 0; + + //! Adds a scene node animator factory to the scene manager. + /** Use this to extend the scene manager with new scene node animator types which it should be + able to create automaticly, for example when loading data from xml files. */ + virtual void registerSceneNodeAnimatorFactory(ISceneNodeAnimatorFactory* factoryToAdd) = 0; + + //! Returns amount of registered scene node animator factories. + virtual u32 getRegisteredSceneNodeAnimatorFactoryCount() const = 0; + + //! Returns a scene node animator factory by index + virtual ISceneNodeAnimatorFactory* getSceneNodeAnimatorFactory(u32 index) = 0; + + //! Returns a typename from a scene node type or null if not found + virtual const c8* getSceneNodeTypeName(ESCENE_NODE_TYPE type) = 0; + + //! Adds a scene node to the scene by name + virtual ISceneNode* addSceneNode(const char* sceneNodeTypeName, ISceneNode* parent) = 0; + + //! Creates a new scene manager. + /** This can be used to easily draw and/or store two independent scenes at the same time. + The mesh cache will be shared between all existing scene managers, which means if you load + a mesh in the original scene manager using for example getMesh(), the mesh will be available + in all other scene managers too, without loading. + The original/main scene manager will still be there and accessible via IrrlichtDevice::getSceneManager(). + If you need input event in this new scene manager, for example for FPS cameras, you'll need + to forward input to this manually: Just implement an IEventReceiver and call + yourNewSceneManager->postEventFromUser(), and return true so that the original scene manager + doesn't get the event. Otherwise, all input will go automaticly to the main scene manager. + If you no longer need the new scene manager, you should call ISceneManager::drop(). + See IReferenceCounted::drop() for more information. */ + virtual ISceneManager* createNewSceneManager(bool cloneContent=false) = 0; + + //! Saves the current scene into a file. + /** Scene nodes with the option isDebugObject set to true are not being saved. + The scene is usually written to an .irr file, an xml based format. .irr files can + Be edited with the Irrlicht Engine Editor, irrEdit (http://irredit.irrlicht3d.org). + To load .irr files again, see ISceneManager::loadScene(). + \param filename: Name of the file. + \param userDataSerializer: If you want to save some user data for every scene node into the + file, implement the ISceneUserDataSerializer interface and provide it as parameter here. + Otherwise, simply specify 0 as this parameter. + \return Returns true if successful. */ + virtual bool saveScene(const c8* filename, ISceneUserDataSerializer* userDataSerializer=0) = 0; + + //! Saves the current scene into a file. + /** Scene nodes with the option isDebugObject set to true are not being saved. + The scene is usually written to an .irr file, an xml based format. .irr files can + Be edited with the Irrlicht Engine Editor, irrEdit (http://irredit.irrlicht3d.org). + To load .irr files again, see ISceneManager::loadScene(). + \param file: File where the scene is saved into. + \param userDataSerializer: If you want to save some user data for every scene node into the + file, implement the ISceneUserDataSerializer interface and provide it as parameter here. + Otherwise, simply specify 0 as this parameter. + \return Returns true if successful. */ + virtual bool saveScene(io::IWriteFile* file, ISceneUserDataSerializer* userDataSerializer=0) = 0; + + //! Loads a scene. Note that the current scene is not cleared before. + /** The scene is usually load from an .irr file, an xml based format. .irr files can + Be edited with the Irrlicht Engine Editor, irrEdit (http://irredit.irrlicht3d.org) or + saved directly by the engine using ISceneManager::saveScene(). + \param filename: Name of the file. + \param userDataSerializer: If you want to load user data possibily saved in that file for + some scene nodes in the file, implement the ISceneUserDataSerializer interface and provide it as parameter here. + Otherwise, simply specify 0 as this parameter. + \return Returns true if successful. */ + virtual bool loadScene(const c8* filename, ISceneUserDataSerializer* userDataSerializer=0) = 0; + + //! Loads a scene. Note that the current scene is not cleared before. + /** The scene is usually load from an .irr file, an xml based format. .irr files can + Be edited with the Irrlicht Engine Editor, irrEdit (http://irredit.irrlicht3d.org) or + saved directly by the engine using ISceneManager::saveScene(). + \param file: File where the scene is going to be saved into. + \param userDataSerializer: If you want to load user data possibily saved in that file for + some scene nodes in the file, implement the ISceneUserDataSerializer interface and provide it as parameter here. + Otherwise, simply specify 0 as this parameter. + \return Returns true if successful. */ + virtual bool loadScene(io::IReadFile* file, ISceneUserDataSerializer* userDataSerializer=0) = 0; + + //! Returns a mesh writer implementation if available + /** Note: You need to drop() the pointer after use again, see IReferenceCounted::drop() + for details. */ + virtual IMeshWriter* createMeshWriter(EMESH_WRITER_TYPE type) = 0; + + //! Sets ambient color of the scene + virtual void setAmbientLight(const video::SColorf &ambientColor) = 0; + + //! Returns ambient color of the scene + virtual const video::SColorf& getAmbientLight() const = 0; + + }; + + +} // end namespace scene +} // end namespace irr + +#endif + diff --git a/media/lightFalloff.png b/media/lightFalloff.png new file mode 100644 index 00000000..21b2142a Binary files /dev/null and b/media/lightFalloff.png differ diff --git a/source/Irrlicht/CSceneManager.cpp b/source/Irrlicht/CSceneManager.cpp index 91961634..ba646b92 100644 --- a/source/Irrlicht/CSceneManager.cpp +++ b/source/Irrlicht/CSceneManager.cpp @@ -1,2211 +1,2228 @@ -// Copyright (C) 2002-2007 Nikolaus Gebhardt -// This file is part of the "Irrlicht Engine". -// For conditions of distribution and use, see copyright notice in irrlicht.h - -#include "IrrCompileConfig.h" -#include "CSceneManager.h" -#include "IVideoDriver.h" -#include "IFileSystem.h" -#include "SAnimatedMesh.h" -#include "CMeshCache.h" -#include "IWriteFile.h" -#include "IXMLWriter.h" -#include "ISceneUserDataSerializer.h" -#include "IGUIEnvironment.h" -#include "IMaterialRenderer.h" - -#include "os.h" - -#include "CGeometryCreator.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_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_STL_LOADER_ -#include "CSTLMeshFileLoader.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 - -#include "CCubeSceneNode.h" -#include "CSphereSceneNode.h" -#include "CAnimatedMeshSceneNode.h" -#include "COctTreeSceneNode.h" -#include "CCameraSceneNode.h" -#include "CCameraMayaSceneNode.h" -#include "CCameraFPSSceneNode.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 "CDefaultSceneNodeFactory.h" - -#include "CSceneCollisionManager.h" -#include "CMeshManipulator.h" -#include "CTriangleSelector.h" -#include "COctTreeTriangleSelector.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 "CDefaultSceneNodeAnimatorFactory.h" - -#include "CQuake3ShaderSceneNode.h" - -//! Enable debug features -#define SCENEMANAGER_DEBUG - -namespace irr -{ -namespace scene -{ - -//! constructor -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), MeshManipulator(0), - ActiveCamera(0), ShadowColor(150,0,0,0), AmbientLight(0,0,0,0), - MeshCache(cache), CurrentRendertime(ESNRP_COUNT), - 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 - - if (Driver) - Driver->grab(); - - if (FileSystem) - FileSystem->grab(); - - if (CursorControl) - CursorControl->grab(); - - if ( GUIEnvironment ) - GUIEnvironment->grab(); - - // create mesh cache if not there already - if (!MeshCache) - MeshCache = new CMeshCache(); - else - MeshCache->grab(); - - // create collision manager - CollisionManager = new CSceneCollisionManager(this, Driver); - - // create manipulator - MeshManipulator = new CMeshManipulator(); - - // add file format loaders - - #ifdef _IRR_COMPILE_WITH_IRR_MESH_LOADER_ - MeshLoaderList.push_back(new CIrrMeshFileLoader(Driver, this, FileSystem)); - #endif - #ifdef _IRR_COMPILE_WITH_BSP_LOADER_ - MeshLoaderList.push_back(new CBSPMeshFileLoader(FileSystem, Driver, this)); - #endif - #ifdef _IRR_COMPILE_WITH_MD2_LOADER_ - MeshLoaderList.push_back(new CMD2MeshFileLoader()); - #endif - #ifdef _IRR_COMPILE_WITH_MS3D_LOADER_ - MeshLoaderList.push_back(new CMS3DMeshFileLoader(Driver)); - #endif - #ifdef _IRR_COMPILE_WITH_3DS_LOADER_ - MeshLoaderList.push_back(new C3DSMeshFileLoader(MeshManipulator,FileSystem, Driver)); - #endif - #ifdef _IRR_COMPILE_WITH_X_LOADER_ - MeshLoaderList.push_back(new CXMeshFileLoader(this)); - #endif - #ifdef _IRR_COMPILE_WITH_OCT_LOADER_ - MeshLoaderList.push_back(new COCTLoader(Driver)); - #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(FileSystem, Driver, this)); - #endif - #ifdef _IRR_COMPILE_WITH_COLLADA_LOADER_ - MeshLoaderList.push_back(new CColladaFileLoader(Driver, this, FileSystem)); - #endif - #ifdef _IRR_COMPILE_WITH_DMF_LOADER_ - MeshLoaderList.push_back(new CDMFLoader(Driver, this)); - #endif - #ifdef _IRR_COMPILE_WITH_OGRE_LOADER_ - MeshLoaderList.push_back(new COgreMeshFileLoader(MeshManipulator, FileSystem, Driver)); - #endif - #ifdef _IRR_COMPILE_WITH_OBJ_LOADER_ - MeshLoaderList.push_back(new COBJMeshFileLoader(FileSystem, Driver)); - #endif - #ifdef _IRR_COMPILE_WITH_MD3_LOADER_ - MeshLoaderList.push_back(new CMD3MeshFileLoader(FileSystem, Driver)); - #endif - #ifdef _IRR_COMPILE_WITH_B3D_LOADER_ - MeshLoaderList.push_back(new CB3DMeshFileLoader(this)); - #endif - #ifdef _IRR_COMPILE_WITH_STL_LOADER_ - MeshLoaderList.push_back(new CSTLMeshFileLoader()); - #endif - - // factories - ISceneNodeFactory* factory = new CDefaultSceneNodeFactory(this); - registerSceneNodeFactory(factory); - factory->drop(); - - ISceneNodeAnimatorFactory* animatorFactory = new CDefaultSceneNodeAnimatorFactory(this); - registerSceneNodeAnimatorFactory(animatorFactory); - animatorFactory->drop(); -} - - - -//! destructor -CSceneManager::~CSceneManager() -{ - clearDeletionList(); - - if (Driver) - Driver->drop(); - - if (FileSystem) - FileSystem->drop(); - - if (CursorControl) - CursorControl->drop(); - - if (CollisionManager) - CollisionManager->drop(); - - if (MeshManipulator) - MeshManipulator->drop(); - - if ( GUIEnvironment ) - GUIEnvironment->drop (); - - u32 i; - - for (i=0; idrop(); - - if (ActiveCamera) - ActiveCamera->drop(); - - if (MeshCache) - MeshCache->drop(); - - for (i=0; idrop(); - - for (i=0; idrop(); -} - - -//! gets an animateable mesh. loads it if needed. returned pointer must not be dropped. -IAnimatedMesh* CSceneManager::getMesh(const c8* filename) -{ - IAnimatedMesh* msh = MeshCache->getMeshByFilename(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; - } - - core::stringc name = filename; - name.make_lower(); - s32 count = MeshLoaderList.size(); - for (s32 i=count-1; i>=0; --i) - { - if (MeshLoaderList[i]->isALoadableFileExtension(name.c_str())) - { - // reset file to avoid side effects of previous calls to createMesh - 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; -} - - -//! returns the video driver -video::IVideoDriver* CSceneManager::getVideoDriver() -{ - return Driver; -} - -//! returns the GUI Environment -gui::IGUIEnvironment* CSceneManager::getGUIEnvironment () -{ - return GUIEnvironment; -} - - -//! Adds a text scene node, which is able to display -//! 2d text at a position in three dimensional space -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; -} - -//! Adds a text scene node, which uses billboards -ITextSceneNode* CSceneManager::addBillboardTextSceneNode(gui::IGUIFont* font, - const wchar_t* text, ISceneNode* parent, - const core::dimension2d& size, - const core::vector3df& position, s32 id, - video::SColor shade_top, video::SColor shade_down) -{ - if (!font) - return 0; - - if (!parent) - parent = this; - - ITextSceneNode* node = new CBillboardTextSceneNode(parent, this, id, font, text, position, size, - shade_top, shade_down); - node->drop(); - - return node; - -} - - -//! Adds a scene node, which can render a quake3 shader -ISceneNode* CSceneManager::addQuake3SceneNode( IMeshBuffer* meshBuffer, - const quake3::SShader * shader, - ISceneNode* parent, - s32 id - ) - -{ - if ( 0 == shader ) - return 0; - - if (!parent) - parent = this; - - CQuake3ShaderSceneNode* node = new CQuake3ShaderSceneNode ( parent, this, id, FileSystem, meshBuffer, shader ); - node->drop(); - - return node; - -} - - -//! adds a test scene node for test purposes to the scene. It is a simple cube of (1,1,1) size. -//! the returned pointer must not be dropped. -ISceneNode* CSceneManager::addCubeSceneNode(f32 size, ISceneNode* parent, s32 id, - const core::vector3df& position, const core::vector3df& rotation, const core::vector3df& scale) -{ - if (!parent) - parent = this; - - ISceneNode* node = new CCubeSceneNode(size, parent, this, id, position, rotation, scale); - node->drop(); - - return node; -} - -//! Adds a sphere scene node for test purposes to the scene. -ISceneNode* 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; - - ISceneNode* node = new CSphereSceneNode(radius, polyCount, polyCount, parent, this, id, position, rotation, scale); - node->drop(); - - return node; -} - - -//! adds a scene node for rendering a static mesh -//! the returned pointer must not be dropped. -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; -} - - -//! Adds a scene node for rendering a animated water surface mesh. -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 (!mesh) - return 0; - - if (!parent) - parent = this; - - ISceneNode* node = new CWaterSurfaceSceneNode(waveHeight, waveSpeed, waveLength, - mesh, parent, this, id, position, rotation, scale); - - node->drop(); - - return node; -} - - - -//! adds a scene node for rendering an animated mesh model -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; -} - - -//! Adds a scene node for rendering using a octtree to the scene graph. This a good method for rendering -//! scenes with lots of geometry. The Octree is built on the fly from the mesh, much -//! faster then a bsp tree. -ISceneNode* CSceneManager::addOctTreeSceneNode(IAnimatedMesh* mesh, ISceneNode* parent, - s32 id, s32 minimalPolysPerNode, bool alsoAddIfMeshPointerZero) -{ - if (!alsoAddIfMeshPointerZero && (!mesh || !mesh->getFrameCount())) - return 0; - - return addOctTreeSceneNode(mesh ? mesh->getMesh(0) : 0, - parent, id, minimalPolysPerNode, - alsoAddIfMeshPointerZero); -} - - - -//! Adss a scene node for rendering using a octtree. This a good method for rendering -//! scenes with lots of geometry. The Octree is built on the fly from the mesh, much -//! faster then a bsp tree. -ISceneNode* CSceneManager::addOctTreeSceneNode(IMesh* mesh, ISceneNode* parent, - s32 id, s32 minimalPolysPerNode, bool alsoAddIfMeshPointerZero) -{ - if (!alsoAddIfMeshPointerZero && !mesh) - return 0; - - if (!parent) - parent = this; - - COctTreeSceneNode* node = new COctTreeSceneNode(parent, this, id, minimalPolysPerNode); - - if (mesh) - node->createTree(mesh); - - node->drop(); - - return node; -} - - -//! Adds a camera scene node to the tree and sets it as active camera. -//! \param position: Position of the space relative to its parent where the camera will be placed. -//! \param lookat: Position where the camera will look at. Also known as target. -//! \param parent: Parent scene node of the camera. Can be null. If the parent moves, -//! the camera will move too. -//! \return Returns pointer to interface to camera -ICameraSceneNode* CSceneManager::addCameraSceneNode(ISceneNode* parent, - const core::vector3df& position, const core::vector3df& lookat, s32 id) -{ - if (!parent) - parent = this; - - ICameraSceneNode* node = new CCameraSceneNode(parent, this, id, position, lookat); - node->drop(); - - setActiveCamera(node); - - return node; -} - - - -//! Adds a camera scene node which is able to be controlle with the mouse similar -//! like in the 3D Software Maya by Alias Wavefront. -//! The returned pointer must not be dropped. -ICameraSceneNode* CSceneManager::addCameraSceneNodeMaya(ISceneNode* parent, - f32 rotateSpeed, f32 zoomSpeed, f32 translationSpeed, s32 id) -{ - if (!parent) - parent = this; - - ICameraSceneNode* node = new CCameraMayaSceneNode(parent, this, id, rotateSpeed, - zoomSpeed, translationSpeed); - node->drop(); - - setActiveCamera(node); - - return node; -} - - - -//! Adds a camera scene node which is able to be controled with the mouse and keys -//! like in most first person shooters (FPS): -ICameraSceneNode* CSceneManager::addCameraSceneNodeFPS(ISceneNode* parent, - f32 rotateSpeed, f32 moveSpeed, s32 id, - SKeyMap* keyMapArray, s32 keyMapSize, bool noVerticalMovement,f32 jumpSpeed) -{ - if (!parent) - parent = this; - - ICameraSceneNode* node = new CCameraFPSSceneNode(parent, this, CursorControl, - id, rotateSpeed, moveSpeed, jumpSpeed, keyMapArray, keyMapSize, noVerticalMovement); - node->drop(); - - setActiveCamera(node); - - return node; -} - - - -//! Adds a dynamic light scene node. The light will cast dynamic light on all -//! other scene nodes in the scene, which have the material flag video::MTF_LIGHTING -//! turned on. (This is the default setting in most scene nodes). -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; -} - - - -//! Adds a billboard scene node to the scene. A billboard is like a 3d sprite: A 2d element, -//! which always looks to the camera. It is usually used for things like explosions, fire, -//! lensflares and things like that. -IBillboardSceneNode* CSceneManager::addBillboardSceneNode(ISceneNode* parent, - const core::dimension2d& size, const core::vector3df& position, s32 id, - video::SColor shade_top, video::SColor shade_down - ) -{ - if (!parent) - parent = this; - - IBillboardSceneNode* node = new CBillboardSceneNode(parent, this, id, position, size, - shade_top, shade_down); - node->drop(); - - return node; -} - - - -//! Adds a skybox scene node. A skybox is a big cube with 6 textures on it and -//! is drawn around the camera position. -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; -} - - -//! Adds a skydome scene node. A skydome is a large (half-) sphere with a -//! panoramic texture on it and is drawn around the camera position. -ISceneNode* CSceneManager::addSkyDomeSceneNode(video::ITexture* texture, - u32 horiRes, u32 vertRes, f64 texturePercentage, - f64 spherePercentage, ISceneNode* parent, s32 id) -{ - if (!parent) - parent = this; - - ISceneNode* node = new CSkyDomeSceneNode(texture, horiRes, vertRes, - texturePercentage, spherePercentage, parent, this, id); - - node->drop(); - return node; -} - - -//! Adds a particle system scene 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; -} - - -//! Adds a terrain scene node to the scene graph. -ITerrainSceneNode* CSceneManager::addTerrainSceneNode( - const char* 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; -} - -//! Adds a terrain scene node to the scene graph. -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; -} - - -//! Adds an empty scene node. -ISceneNode* CSceneManager::addEmptySceneNode(ISceneNode* parent, s32 id) -{ - if (!parent) - parent = this; - - ISceneNode* node = new CEmptySceneNode(parent, this, id); - node->drop(); - - return node; -} - - -//! Adds a dummy transformation scene node to the scene graph. -IDummyTransformationSceneNode* CSceneManager::addDummyTransformationSceneNode( - ISceneNode* parent, s32 id) -{ - if (!parent) - parent = this; - - IDummyTransformationSceneNode* node = new CDummyTransformationSceneNode( - parent, this, id); - node->drop(); - - return node; -} - -//! Adds a Hill Plane mesh to the mesh pool. The mesh is generated on the fly -//! and looks like a plane with some hills on it. It is uses mostly for quick -//! tests of the engine only. You can specify how many hills there should be -//! on the plane and how high they should be. Also you must specify a name for -//! the mesh, because the mesh is added to the mesh pool, and can be retrieved -//! again using ISceneManager::getMesh with the name as parameter. -IAnimatedMesh* CSceneManager::addHillPlaneMesh(const c8* name, - const core::dimension2d& tileSize, - const core::dimension2d& tileCount, - video::SMaterial* material, f32 hillHeight, - const core::dimension2d& countHills, - const core::dimension2d& textureRepeatCount) -{ - if (!name || MeshCache->isMeshLoaded(name)) - return 0; - - IMesh* mesh = CGeometryCreator::createHillPlaneMesh(tileSize, - tileCount, material, hillHeight, countHills, - textureRepeatCount); - if (!mesh) - return 0; - - SAnimatedMesh* animatedMesh = new SAnimatedMesh(); - if (!animatedMesh) - return 0; - - animatedMesh->addMesh(mesh); - animatedMesh->recalculateBoundingBox(); - mesh->drop(); - - MeshCache->addMesh(name, animatedMesh); - animatedMesh->drop(); - - return animatedMesh; -} - - -//! Adds a terrain mesh to the mesh pool. -IAnimatedMesh* CSceneManager::addTerrainMesh(const c8* name, - video::IImage* texture, video::IImage* heightmap, - const core::dimension2d& stretchSize, - f32 maxHeight, - const core::dimension2d& defaultVertexBlockSize) -{ - if (!name || MeshCache->isMeshLoaded(name)) - return 0; - - IMesh* mesh = CGeometryCreator::createTerrainMesh(texture, heightmap, - stretchSize, maxHeight, getVideoDriver(), - defaultVertexBlockSize); - if (!mesh) - return 0; - - SAnimatedMesh* animatedMesh = new SAnimatedMesh(); - if (!animatedMesh) - return 0; - - animatedMesh->addMesh(mesh); - animatedMesh->recalculateBoundingBox(); - mesh->drop(); - - MeshCache->addMesh(name, animatedMesh); - animatedMesh->drop(); - - return animatedMesh; -} - -//! Adds an arrow mesh to the mesh pool. -IAnimatedMesh* CSceneManager::addArrowMesh(const c8* name, - video::SColor vtxColor0, video::SColor vtxColor1, - u32 tesselationCylinder, u32 tesselationCone, f32 height, - f32 cylinderHeight, f32 width0,f32 width1) -{ - if (!name || MeshCache->isMeshLoaded(name)) - return 0; - - IMesh* mesh = CGeometryCreator::createArrowMesh( tesselationCylinder, - tesselationCone, height, cylinderHeight, width0,width1, - vtxColor0, vtxColor1); - if (!mesh) - return 0; - - SAnimatedMesh* animatedMesh = new SAnimatedMesh(); - if (!animatedMesh) - return 0; - - animatedMesh->addMesh(mesh); - animatedMesh->recalculateBoundingBox(); - mesh->drop(); - - MeshCache->addMesh(name, animatedMesh); - animatedMesh->drop(); - - return animatedMesh; -} - - - -//! Adds a static sphere mesh to the mesh pool. -IAnimatedMesh* CSceneManager::addSphereMesh(const c8* name, - f32 radius, u32 polyCountX, u32 polyCountY) -{ - if (!name || MeshCache->isMeshLoaded(name)) - return 0; - - IMesh* mesh = CGeometryCreator::createSphereMesh( radius, polyCountX, polyCountY); - if (!mesh) - return 0; - - SAnimatedMesh* animatedMesh = new SAnimatedMesh(); - if (!animatedMesh) - return 0; - - animatedMesh->addMesh(mesh); - animatedMesh->recalculateBoundingBox(); - mesh->drop(); - - MeshCache->addMesh(name, animatedMesh); - animatedMesh->drop(); - - return animatedMesh; -} - - - -//! Returns the root scene node. This is the scene node wich is parent -//! of all scene nodes. The root scene node is a special scene node which -//! only exists to manage all scene nodes. It is not rendered and cannot -//! be removed from the scene. -//! \return Returns a pointer to the root scene node. -ISceneNode* CSceneManager::getRootSceneNode() -{ - return this; -} - - - -//! Returns the current active camera. -//! \return The active camera is returned. Note that this can be NULL, if there -//! was no camera created yet. -ICameraSceneNode* CSceneManager::getActiveCamera() -{ - return ActiveCamera; -} - - - -//! Sets the active camera. The previous active camera will be deactivated. -//! \param camera: The new camera which should be active. -void CSceneManager::setActiveCamera(ICameraSceneNode* camera) -{ - if (ActiveCamera) - ActiveCamera->drop(); - - ActiveCamera = camera; - - if (ActiveCamera) - ActiveCamera->grab(); -} - - - - -//! renders the node. -void CSceneManager::render() -{ -} - - -//! returns the axis aligned bounding box of this node -const core::aabbox3d& CSceneManager::getBoundingBox() const -{ - _IRR_DEBUG_BREAK_IF(true) // Bounding Box of Scene Manager wanted. - - // should never be used. - return *((core::aabbox3d*)0); -} - - - -//! returns if node is culled -bool CSceneManager::isCulled(const ISceneNode* node) -{ - const ICameraSceneNode* cam = getActiveCamera(); - if (!cam) - return false; - - switch ( node->getAutomaticCulling() ) - { - // can be seen by a bounding box ? - case scene::EAC_BOX: - { - core::aabbox3d tbox = node->getBoundingBox(); - node->getAbsoluteTransformation().transformBox(tbox); - return !(tbox.intersectsWithBox(cam->getViewFrustum()->getBoundingBox() )); - } - - // can be seen by a bounding sphere - case scene::EAC_FRUSTUM_SPHERE: - { // requires bbox diameter - } - break; - - // can be seen by cam pyramid planes ? - case scene::EAC_FRUSTUM_BOX: - { - SViewFrustum frust = *cam->getViewFrustum(); - - //transform the frustum to the node's current absolute transformation - core::matrix4 invTrans(node->getAbsoluteTransformation()); - invTrans.makeInverse(); - frust.transform(invTrans); - - core::vector3df edges[8]; - node->getBoundingBox().getEdges(edges); - - for (s32 i=0; igetMaterialCount(); - - taken = 0; - for (u32 i=0; igetMaterialRenderer(node->getMaterial(i).MaterialType); - if (rnd && rnd->isTransparent()) - { - // register as transparent node - TransparentNodeEntry e(node, camWorldPos); - TransparentNodeList.push_back(e); - taken = 1; - break; - } - } - - // not transparent, register as solid - if ( 0 == taken ) - { - SolidNodeList.push_back( node ); - taken = 1; - } - } - break; - case ESNRP_SHADOW: - if (!isCulled(node)) - { - ShadowNodeList.push_back(node); - taken = 1; - } - break; - - case ESNRP_COUNT: // ignore this one - break; - } - -#ifdef SCENEMANAGER_DEBUG - s32 index = Parameters.findAttribute ( "calls" ); - Parameters.setAttribute ( index, Parameters.getAttributeAsInt ( index ) + 1 ); - - if ( 0 == taken ) - { - index = Parameters.findAttribute ( "culled" ); - Parameters.setAttribute ( index, Parameters.getAttributeAsInt ( index ) + 1 ); - } -#endif - - return taken; -} - -//! This method is called just before the rendering process of the whole scene. -//! draws all scene nodes -void CSceneManager::drawAll() -{ - if (!Driver) - return; - - // reset attributes - Parameters.setAttribute ( "culled", 0 ); - Parameters.setAttribute ( "calls", 0 ); - Parameters.setAttribute ( "drawn", 0 ); - - // reset all transforms - video::IVideoDriver* driver = getVideoDriver(); - if ( driver ) - { - driver->setTransform ( video::ETS_PROJECTION, core::IdentityMatrix ); - driver->setTransform ( video::ETS_VIEW, core::IdentityMatrix ); - driver->setTransform ( video::ETS_WORLD, core::IdentityMatrix ); - driver->setTransform ( video::ETS_TEXTURE_0, core::IdentityMatrix ); - driver->setTransform ( video::ETS_TEXTURE_1, core::IdentityMatrix ); - driver->setTransform ( video::ETS_TEXTURE_2, core::IdentityMatrix ); - driver->setTransform ( video::ETS_TEXTURE_3, core::IdentityMatrix ); - } - - // do animations and other stuff. - OnAnimate(os::Timer::getTime()); - - /*! - First Scene Node for prerendering should be the active camera - consistent Camera is needed for culling - */ - camWorldPos.set(0,0,0); - if ( ActiveCamera ) - { - ActiveCamera->OnRegisterSceneNode(); - camWorldPos = ActiveCamera->getAbsolutePosition(); - } - - // let all nodes register themselves - OnRegisterSceneNode(); - - u32 i; // new ISO for scoping problem in some compilers - - //render camera scenes - { - CurrentRendertime = ESNRP_CAMERA; - for (i=0; irender(); - - CameraList.set_used(0); - } - - //render lights scenes - { - CurrentRendertime = ESNRP_LIGHT; - - Driver->deleteAllDynamicLights(); - - Driver->setAmbientLight(AmbientLight); - - LightList.sort (); // on distance to camera - - u32 maxLights = core::min_ ( Driver->getMaximalDynamicLightAmount (), LightList.size () ); - for (i=0; i< maxLights; ++i) - LightList[i].node->render(); - - LightList.set_used(0); - } - - // render skyboxes - { - CurrentRendertime = ESNRP_SKY_BOX; - - for (i=0; irender(); - - SkyBoxList.set_used(0); - } - - - // render default objects - { - CurrentRendertime = ESNRP_SOLID; - SolidNodeList.sort(); // sort by textures - - for (i=0; irender(); - - Parameters.setAttribute ( "drawn", (s32) SolidNodeList.size () ); - - SolidNodeList.set_used(0); - } - - // render shadows - { - CurrentRendertime = ESNRP_SHADOW; - for (i=0; irender(); - - if (!ShadowNodeList.empty()) - Driver->drawStencilShadow(true,ShadowColor, ShadowColor, - ShadowColor, ShadowColor); - - ShadowNodeList.set_used(0); - } - - // render transparent objects. - { - CurrentRendertime = ESNRP_TRANSPARENT; - TransparentNodeList.sort(); // sort by distance from camera - - for (i=0; irender(); - - TransparentNodeList.set_used(0); - } - - - clearDeletionList(); - - CurrentRendertime = ESNRP_COUNT; -} - - -//! Sets the color of stencil buffers shadows drawn by the scene manager. -void CSceneManager::setShadowColor(video::SColor color) -{ - ShadowColor = color; -} - - -//! Returns the current color of shadows. -video::SColor CSceneManager::getShadowColor() const -{ - return ShadowColor; -} - - - -//! creates a rotation animator, which rotates the attached scene node around itself. -ISceneNodeAnimator* CSceneManager::createRotationAnimator(const core::vector3df& rotationPerSecond) -{ - ISceneNodeAnimator* anim = new CSceneNodeAnimatorRotation(os::Timer::getTime(), - rotationPerSecond); - - return anim; -} - - - -//! creates a fly circle animator, which lets the attached scene node fly around a center. -ISceneNodeAnimator* CSceneManager::createFlyCircleAnimator( - const core::vector3df& normal, f32 radius, f32 speed, - const core::vector3df& direction) -{ - ISceneNodeAnimator* anim = new CSceneNodeAnimatorFlyCircle(os::Timer::getTime(), normal, - radius, speed, direction); - return anim; -} - - -//! Creates a fly straight animator, which lets the attached scene node -//! fly or move along a line between two points. -ISceneNodeAnimator* CSceneManager::createFlyStraightAnimator(const core::vector3df& startPoint, - const core::vector3df& endPoint, u32 timeForWay, bool loop) -{ - ISceneNodeAnimator* anim = new CSceneNodeAnimatorFlyStraight(startPoint, - endPoint, timeForWay, loop, os::Timer::getTime()); - - return anim; -} - - -//! Creates a texture animator, which switches the textures of the target scene -//! node based on a list of textures. -ISceneNodeAnimator* CSceneManager::createTextureAnimator(const core::array& textures, - s32 timePerFrame, bool loop) -{ - ISceneNodeAnimator* anim = new CSceneNodeAnimatorTexture(textures, - timePerFrame, loop, os::Timer::getTime()); - - return anim; -} - - -//! Creates a scene node animator, which deletes the scene node after -//! some time automaticly. -ISceneNodeAnimator* CSceneManager::createDeleteAnimator(u32 when) -{ - return new CSceneNodeAnimatorDelete(this, os::Timer::getTime() + when); -} - - - - -//! Creates a special scene node animator for doing automatic collision detection -//! and response. -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; -} - - -//! Creates a follow spline animator. -ISceneNodeAnimator* CSceneManager::createFollowSplineAnimator(s32 startTime, - const core::array< core::vector3df >& points, - f32 speed, f32 tightness) -{ - ISceneNodeAnimator* a = new CSceneNodeAnimatorFollowSpline(startTime, points, - speed, tightness); - return a; -} - - - -//! Adds an external mesh loader. -void CSceneManager::addExternalMeshLoader(IMeshLoader* externalLoader) -{ - if (!externalLoader) - return; - - externalLoader->grab(); - MeshLoaderList.push_back(externalLoader); -} - - - -//! Returns a pointer to the scene collision manager. -ISceneCollisionManager* CSceneManager::getSceneCollisionManager() -{ - return CollisionManager; -} - - -//! Returns a pointer to the mesh manipulator. -IMeshManipulator* CSceneManager::getMeshManipulator() -{ - return MeshManipulator; -} - - -//! Creates a simple ITriangleSelector, based on a mesh. -ITriangleSelector* CSceneManager::createTriangleSelector(IMesh* mesh, ISceneNode* node) -{ - if (!mesh || !node) - return 0; - - return new CTriangleSelector(mesh, node); -} - - -//! Creates a simple dynamic ITriangleSelector, based on a axis aligned bounding box. -ITriangleSelector* CSceneManager::createTriangleSelectorFromBoundingBox(ISceneNode* node) -{ - if (!node) - return 0; - - return new CTriangleBBSelector(node); -} - - -//! Creates a simple ITriangleSelector, based on a mesh. -ITriangleSelector* CSceneManager::createOctTreeTriangleSelector(IMesh* mesh, - ISceneNode* node, - s32 minimalPolysPerNode) -{ - if (!mesh || !node) - return 0; - - return new COctTreeTriangleSelector(mesh, node, minimalPolysPerNode); -} - - - -//! Creates a meta triangle selector. -IMetaTriangleSelector* CSceneManager::createMetaTriangleSelector() -{ - return new CMetaTriangleSelector(); -} - - - -//! Creates a triangle selector which can select triangles from a terrain scene node -ITriangleSelector* CSceneManager::createTerrainTriangleSelector( - ITerrainSceneNode* node, s32 LOD) -{ - return new CTerrainTriangleSelector(node, LOD); -} - - - -//! Adds a scene node to the deletion queue. -void CSceneManager::addToDeletionQueue(ISceneNode* node) -{ - if (!node) - return; - - node->grab(); - DeletionList.push_back(node); -} - - -//! clears the deletion list -void CSceneManager::clearDeletionList() -{ - if (DeletionList.empty()) - return; - - for (s32 i=0; i<(s32)DeletionList.size(); ++i) - { - DeletionList[i]->remove(); - DeletionList[i]->drop(); - } - - DeletionList.clear(); -} - - -//! Returns the first scene node with the specified name. -ISceneNode* CSceneManager::getSceneNodeFromName(const char* name, ISceneNode* start) -{ - if (start == 0) - start = getRootSceneNode(); - - if (!strcmp(start->getName(),name)) - return start; - - ISceneNode* node = 0; - - const core::list& list = start->getChildren(); - core::list::ConstIterator it = list.begin(); - for (; it!=list.end(); ++it) - { - node = getSceneNodeFromName(name, *it); - if (node) - return node; - } - - return 0; -} - - -//! Returns the first scene node with the specified id. -ISceneNode* CSceneManager::getSceneNodeFromId(s32 id, ISceneNode* start) -{ - if (start == 0) - start = getRootSceneNode(); - - if (start->getID() == id) - return start; - - ISceneNode* node = 0; - - const core::list& list = start->getChildren(); - core::list::ConstIterator it = list.begin(); - for (; it!=list.end(); ++it) - { - node = getSceneNodeFromId(id, *it); - if (node) - return node; - } - - return 0; -} - - -//! Returns the first scene node with the specified type. -ISceneNode* CSceneManager::getSceneNodeFromType(scene::ESCENE_NODE_TYPE type, ISceneNode* start) -{ - if (start == 0) - start = getRootSceneNode(); - - if (start->getType() == type) - return start; - - ISceneNode* node = 0; - - const core::list& list = start->getChildren(); - core::list::ConstIterator it = list.begin(); - for (; it!=list.end(); ++it) - { - node = getSceneNodeFromType(type, *it); - if (node) - return node; - } - - return 0; -} - -//! returns scene nodes by type. -void CSceneManager::getSceneNodesFromType(ESCENE_NODE_TYPE type, core::array& outNodes, ISceneNode* start) -{ - if (start == 0) - start = getRootSceneNode(); - - if (start->getType() == type) - outNodes.push_back(start); - - const core::list& list = start->getChildren(); - core::list::ConstIterator it = list.begin(); - - for (; it!=list.end(); ++it) - { - getSceneNodesFromType(type, outNodes, *it); - } -} - - -//! Posts an input event to the environment. Usually you do not have to -//! use this method, it is used by the internal engine. -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; -} - - -//! Removes all children of this scene node -void CSceneManager::removeAll() -{ - ISceneNode::removeAll(); - setActiveCamera(0); -} - - -//! Clears the whole scene. All scene nodes are removed. -void CSceneManager::clear() -{ - removeAll(); -} - - -//! Returns interface to the parameters set in this scene. -io::IAttributes* CSceneManager::getParameters() -{ - return &Parameters; -} - - -//! Returns current render pass. -E_SCENE_NODE_RENDER_PASS CSceneManager::getSceneNodeRenderPass() const -{ - return CurrentRendertime; -} - - - -//! Returns an interface to the mesh cache which is shared beween all existing scene managers. -IMeshCache* CSceneManager::getMeshCache() -{ - return MeshCache; -} - - -//! Creates a new scene manager. -ISceneManager* CSceneManager::createNewSceneManager(bool cloneContent) -{ - CSceneManager* manager = new CSceneManager(Driver, FileSystem, CursorControl, MeshCache); - - if (cloneContent) - manager->cloneMembers(this, manager); - - return manager; -} - - -//! Returns the default scene node factory which can create all built in scene nodes -ISceneNodeFactory* CSceneManager::getDefaultSceneNodeFactory() -{ - return getSceneNodeFactory(0); -} - - -//! Adds a scene node factory to the scene manager. -void CSceneManager::registerSceneNodeFactory(ISceneNodeFactory* factoryToAdd) -{ - if (factoryToAdd) - { - factoryToAdd->grab(); - SceneNodeFactoryList.push_back(factoryToAdd); - } -} - - -//! Returns amount of registered scene node factories. -u32 CSceneManager::getRegisteredSceneNodeFactoryCount() const -{ - return SceneNodeFactoryList.size(); -} - - -//! Returns a scene node factory by index -ISceneNodeFactory* CSceneManager::getSceneNodeFactory(u32 index) -{ - if (indexgrab(); - SceneNodeAnimatorFactoryList.push_back(factoryToAdd); - } -} - - -//! Returns amount of registered scene node animator factories. -u32 CSceneManager::getRegisteredSceneNodeAnimatorFactoryCount() const -{ - return SceneNodeAnimatorFactoryList.size(); -} - - -//! Returns a scene node animator factory by index -ISceneNodeAnimatorFactory* CSceneManager::getSceneNodeAnimatorFactory(u32 index) -{ - if (indexcreateAndWriteFile(filename); - if (!file) - return false; - - bool ret = saveScene(file, userDataSerializer); - file->drop(); - return ret; -} - - -//! Saves the current scene into a file. -bool CSceneManager::saveScene(io::IWriteFile* file, ISceneUserDataSerializer* userDataSerializer) -{ - if (!file) - return false; - - io::IXMLWriter* writer = FileSystem->createXMLWriter(file); - if (!writer) - return false; - - writer->writeXMLHeader(); - writeSceneNode(writer, this, userDataSerializer); - writer->drop(); - - return true; -} - - -//! Loads a scene. Note that the current scene is not cleared before. -//! \param filename: Name of the file . -bool CSceneManager::loadScene(const c8* filename, ISceneUserDataSerializer* userDataSerializer) -{ - io::IReadFile* read = FileSystem->createAndOpenFile(filename); - if (!read) - { - os::Printer::log("Unable to open scene file", filename, ELL_ERROR); - return false; - } - - bool ret = loadScene(read, userDataSerializer); - read->drop(); - - return ret; -} - - -//! Loads a scene. Note that the current scene is not cleared before. -bool CSceneManager::loadScene(io::IReadFile* file, ISceneUserDataSerializer* userDataSerializer) -{ - if (!file) - { - os::Printer::log("Unable to open scene file", ELL_ERROR); - return false; - } - - io::IXMLReader* reader = FileSystem->createXMLReader(file); - if (!reader) - { - os::Printer::log("Scene is not a valid XML file", file->getFileName(), ELL_ERROR); - return false; - } - - // for mesh loading, set collada loading attributes - - bool oldColladaSingleMesh = getParameters()->getAttributeAsBool(COLLADA_CREATE_SCENE_INSTANCES); - getParameters()->setAttribute(COLLADA_CREATE_SCENE_INSTANCES, false); - - // read file - - while(reader->read()) - { - readSceneNode(reader, 0, userDataSerializer); - } - - // restore old collada parameters - - getParameters()->setAttribute(COLLADA_CREATE_SCENE_INSTANCES, oldColladaSingleMesh); - - // finish up - - reader->drop(); - return true; - -} - - -//! reads a scene node -void CSceneManager::readSceneNode(io::IXMLReader* reader, ISceneNode* parent, ISceneUserDataSerializer* userDataSerializer) -{ - if (!reader) - return; - - scene::ISceneNode* node = 0; - - if ((!parent && IRR_XML_FORMAT_SCENE==reader->getNodeName()) || - ( parent && IRR_XML_FORMAT_NODE==reader->getNodeName())) - { - if (parent) - { - // find node type and create it - core::stringc attrName = reader->getAttributeValue(IRR_XML_FORMAT_NODE_ATTR_TYPE.c_str()); - - for (int i=(int)SceneNodeFactoryList.size()-1; i>=0 && !node; --i) - node = SceneNodeFactoryList[i]->addSceneNode(attrName.c_str(), parent); - - if (!node) - os::Printer::log("Could not create scene node of unknown type", attrName.c_str()); - } - else - node = this; // root - } - - // read attributes - while(reader->read()) - { - bool endreached = false; - - switch (reader->getNodeType()) - { - case io::EXN_ELEMENT_END: - if ((IRR_XML_FORMAT_NODE==reader->getNodeName()) || - (IRR_XML_FORMAT_SCENE==reader->getNodeName())) - { - endreached = true; - } - break; - case io::EXN_ELEMENT: - if (core::stringw(L"attributes")==reader->getNodeName()) - { - // read attributes - io::IAttributes* attr = FileSystem->createEmptyAttributes(Driver); - attr->read(reader, true); - - if (node) - node->deserializeAttributes(attr); - - attr->drop(); - } - else - if (core::stringw(L"materials")==reader->getNodeName()) - readMaterials(reader, node); - else - if (core::stringw(L"animators")==reader->getNodeName()) - readAnimators(reader, node); - else - if (core::stringw(L"userData")==reader->getNodeName()) - readUserData(reader, node, userDataSerializer); - else - if ((IRR_XML_FORMAT_NODE==reader->getNodeName()) || - (IRR_XML_FORMAT_SCENE==reader->getNodeName())) - { - readSceneNode(reader, node, userDataSerializer); - } - else - { - os::Printer::log("Found unknown element in irrlicht scene file", - core::stringc(reader->getNodeName()).c_str()); - } - break; - default: - break; - } - - if (endreached) - break; - } -} - - -//! reads materials of a node -void CSceneManager::readMaterials(io::IXMLReader* reader, ISceneNode* node) -{ - u32 nr = 0; - - while(reader->read()) - { - const wchar_t* name = reader->getNodeName(); - - switch(reader->getNodeType()) - { - case io::EXN_ELEMENT_END: - if (core::stringw(L"materials")==name) - return; - break; - case io::EXN_ELEMENT: - if (core::stringw(L"attributes")==name) - { - // read materials from attribute list - io::IAttributes* attr = FileSystem->createEmptyAttributes(Driver); - attr->read(reader); - - if (node && node->getMaterialCount() > nr) - { - getVideoDriver()->fillMaterialStructureFromAttributes( - node->getMaterial(nr), attr); - } - - attr->drop(); - ++nr; - } - break; - default: - break; - } - } -} - - -//! reads animators of a node -void CSceneManager::readAnimators(io::IXMLReader* reader, ISceneNode* node) -{ - while(reader->read()) - { - const wchar_t* name = reader->getNodeName(); - - switch(reader->getNodeType()) - { - case io::EXN_ELEMENT_END: - if (core::stringw(L"animators")==name) - return; - break; - case io::EXN_ELEMENT: - if (core::stringw(L"attributes")==name) - { - // read animator data from attribute list - io::IAttributes* attr = FileSystem->createEmptyAttributes(Driver); - attr->read(reader); - - if (node) - { - core::stringc typeName = attr->getAttributeAsString("Type"); - ISceneNodeAnimator* anim = 0; - - for (int i=0; i<(int)SceneNodeAnimatorFactoryList.size() && !anim; ++i) - anim = SceneNodeAnimatorFactoryList[i]->createSceneNodeAnimator(typeName.c_str(), node); - - if (anim) - { - anim->deserializeAttributes(attr); - anim->drop(); - } - } - - attr->drop(); - } - break; - default: - break; - } - } -} - - -//! reads user data of a node -void CSceneManager::readUserData(io::IXMLReader* reader, ISceneNode* node, ISceneUserDataSerializer* userDataSerializer) -{ - while(reader->read()) - { - const wchar_t* name = reader->getNodeName(); - - switch(reader->getNodeType()) - { - case io::EXN_ELEMENT_END: - if (core::stringw(L"userData")==name) - return; - break; - case io::EXN_ELEMENT: - if (core::stringw(L"attributes")==name) - { - // read user data from attribute list - io::IAttributes* attr = FileSystem->createEmptyAttributes(Driver); - attr->read(reader); - - if (node && userDataSerializer) - { - userDataSerializer->OnReadUserData(node, attr); - } - - attr->drop(); - } - break; - default: - break; - } - } -} - - -//! writes a scene node -void CSceneManager::writeSceneNode(io::IXMLWriter* writer, ISceneNode* node, ISceneUserDataSerializer* userDataSerializer) -{ - if (!writer || !node || node->isDebugObject()) - return; - - const wchar_t* name; - - if (node == this) - { - name = IRR_XML_FORMAT_SCENE.c_str(); - writer->writeElement(name, false); - } - 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(); - writer->writeLineBreak(); - - // write properties - - io::IAttributes* attr = FileSystem->createEmptyAttributes(Driver); - node->serializeAttributes(attr); - - if (attr->getAttributeCount() != 0) - { - attr->write(writer); - writer->writeLineBreak(); - } - - // write materials - - 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(); - } - - // write animators - - if (!node->getAnimators().empty()) - { - const wchar_t* animatorElement = L"animators"; - writer->writeElement(animatorElement); - writer->writeLineBreak(); - - core::list::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(); - } - - // write possible user data - - 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(); - } - } - - // write children - - core::list::ConstIterator it = node->getChildren().begin(); - for (; it != node->getChildren().end(); ++it) - writeSceneNode(writer, (*it), userDataSerializer); - - attr->drop(); - - writer->writeClosingTag(name); - writer->writeLineBreak(); - writer->writeLineBreak(); -} - - -//! Returns a typename from a scene node type or null if not found -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; -} - -//! Adds a scene node to the scene by 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; -} - - -//! Returns a typename from a scene node animator type or null if not found -const c8* CSceneManager::getAnimatorTypeName(ESCENE_NODE_ANIMATOR_TYPE type) const -{ - const char* name = 0; - - for (u32 i=0; !name && igetCreateableSceneNodeAnimatorTypeName(type); - - return name; -} - - -//! Writes attributes of the scene node. -void CSceneManager::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const -{ - out->addString ("Name", Name.c_str()); - out->addInt ("Id", ID ); - out->addColorf ("AmbientLight", AmbientLight); -} - -//! Reads attributes of the scene node. -void CSceneManager::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) -{ - Name = in->getAttributeAsString("Name"); - ID = in->getAttributeAsInt("Id"); - AmbientLight = in->getAttributeAsColorf("AmbientLight"); - - 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(); -} - - -//! Sets ambient color of the scene -void CSceneManager::setAmbientLight(const video::SColorf &ambientColor) -{ - AmbientLight = ambientColor; -} - - -//! Returns ambient color of the scene -const video::SColorf& CSceneManager::getAmbientLight() const -{ - return AmbientLight; -} - - -//! Returns a mesh writer implementation if available -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 - } - - return 0; -} - - -// creates a scenemanager -ISceneManager* createSceneManager(video::IVideoDriver* driver, - io::IFileSystem* fs, gui::ICursorControl* cursorcontrol, - gui::IGUIEnvironment *guiEnvironment) -{ - return new CSceneManager(driver, fs, cursorcontrol, 0, guiEnvironment ); -} - - -} // end namespace scene -} // end namespace irr - +// Copyright (C) 2002-2007 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#include "IrrCompileConfig.h" +#include "CSceneManager.h" +#include "IVideoDriver.h" +#include "IFileSystem.h" +#include "SAnimatedMesh.h" +#include "CMeshCache.h" +#include "IWriteFile.h" +#include "IXMLWriter.h" +#include "ISceneUserDataSerializer.h" +#include "IGUIEnvironment.h" +#include "IMaterialRenderer.h" + +#include "os.h" + +#include "CGeometryCreator.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_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_STL_LOADER_ +#include "CSTLMeshFileLoader.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 + +#include "CCubeSceneNode.h" +#include "CSphereSceneNode.h" +#include "CAnimatedMeshSceneNode.h" +#include "COctTreeSceneNode.h" +#include "CCameraSceneNode.h" +#include "CCameraMayaSceneNode.h" +#include "CCameraFPSSceneNode.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 "CDefaultSceneNodeFactory.h" + +#include "CSceneCollisionManager.h" +#include "CMeshManipulator.h" +#include "CTriangleSelector.h" +#include "COctTreeTriangleSelector.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 "CDefaultSceneNodeAnimatorFactory.h" + +#include "CQuake3ShaderSceneNode.h" +#include "CVolumeLightSceneNode.h" + +//! Enable debug features +#define SCENEMANAGER_DEBUG + +namespace irr +{ +namespace scene +{ + +//! constructor +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), MeshManipulator(0), + ActiveCamera(0), ShadowColor(150,0,0,0), AmbientLight(0,0,0,0), + MeshCache(cache), CurrentRendertime(ESNRP_COUNT), + 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 + + if (Driver) + Driver->grab(); + + if (FileSystem) + FileSystem->grab(); + + if (CursorControl) + CursorControl->grab(); + + if ( GUIEnvironment ) + GUIEnvironment->grab(); + + // create mesh cache if not there already + if (!MeshCache) + MeshCache = new CMeshCache(); + else + MeshCache->grab(); + + // create collision manager + CollisionManager = new CSceneCollisionManager(this, Driver); + + // create manipulator + MeshManipulator = new CMeshManipulator(); + + // add file format loaders + + #ifdef _IRR_COMPILE_WITH_IRR_MESH_LOADER_ + MeshLoaderList.push_back(new CIrrMeshFileLoader(Driver, this, FileSystem)); + #endif + #ifdef _IRR_COMPILE_WITH_BSP_LOADER_ + MeshLoaderList.push_back(new CBSPMeshFileLoader(FileSystem, Driver, this)); + #endif + #ifdef _IRR_COMPILE_WITH_MD2_LOADER_ + MeshLoaderList.push_back(new CMD2MeshFileLoader()); + #endif + #ifdef _IRR_COMPILE_WITH_MS3D_LOADER_ + MeshLoaderList.push_back(new CMS3DMeshFileLoader(Driver)); + #endif + #ifdef _IRR_COMPILE_WITH_3DS_LOADER_ + MeshLoaderList.push_back(new C3DSMeshFileLoader(MeshManipulator,FileSystem, Driver)); + #endif + #ifdef _IRR_COMPILE_WITH_X_LOADER_ + MeshLoaderList.push_back(new CXMeshFileLoader(this)); + #endif + #ifdef _IRR_COMPILE_WITH_OCT_LOADER_ + MeshLoaderList.push_back(new COCTLoader(Driver)); + #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(FileSystem, Driver, this)); + #endif + #ifdef _IRR_COMPILE_WITH_COLLADA_LOADER_ + MeshLoaderList.push_back(new CColladaFileLoader(Driver, this, FileSystem)); + #endif + #ifdef _IRR_COMPILE_WITH_DMF_LOADER_ + MeshLoaderList.push_back(new CDMFLoader(Driver, this)); + #endif + #ifdef _IRR_COMPILE_WITH_OGRE_LOADER_ + MeshLoaderList.push_back(new COgreMeshFileLoader(MeshManipulator, FileSystem, Driver)); + #endif + #ifdef _IRR_COMPILE_WITH_OBJ_LOADER_ + MeshLoaderList.push_back(new COBJMeshFileLoader(FileSystem, Driver)); + #endif + #ifdef _IRR_COMPILE_WITH_MD3_LOADER_ + MeshLoaderList.push_back(new CMD3MeshFileLoader(FileSystem, Driver)); + #endif + #ifdef _IRR_COMPILE_WITH_B3D_LOADER_ + MeshLoaderList.push_back(new CB3DMeshFileLoader(this)); + #endif + #ifdef _IRR_COMPILE_WITH_STL_LOADER_ + MeshLoaderList.push_back(new CSTLMeshFileLoader()); + #endif + + // factories + ISceneNodeFactory* factory = new CDefaultSceneNodeFactory(this); + registerSceneNodeFactory(factory); + factory->drop(); + + ISceneNodeAnimatorFactory* animatorFactory = new CDefaultSceneNodeAnimatorFactory(this); + registerSceneNodeAnimatorFactory(animatorFactory); + animatorFactory->drop(); +} + + + +//! destructor +CSceneManager::~CSceneManager() +{ + clearDeletionList(); + + if (Driver) + Driver->drop(); + + if (FileSystem) + FileSystem->drop(); + + if (CursorControl) + CursorControl->drop(); + + if (CollisionManager) + CollisionManager->drop(); + + if (MeshManipulator) + MeshManipulator->drop(); + + if ( GUIEnvironment ) + GUIEnvironment->drop (); + + u32 i; + + for (i=0; idrop(); + + if (ActiveCamera) + ActiveCamera->drop(); + + if (MeshCache) + MeshCache->drop(); + + for (i=0; idrop(); + + for (i=0; idrop(); +} + + +//! gets an animateable mesh. loads it if needed. returned pointer must not be dropped. +IAnimatedMesh* CSceneManager::getMesh(const c8* filename) +{ + IAnimatedMesh* msh = MeshCache->getMeshByFilename(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; + } + + core::stringc name = filename; + name.make_lower(); + s32 count = MeshLoaderList.size(); + for (s32 i=count-1; i>=0; --i) + { + if (MeshLoaderList[i]->isALoadableFileExtension(name.c_str())) + { + // reset file to avoid side effects of previous calls to createMesh + 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; +} + + +//! returns the video driver +video::IVideoDriver* CSceneManager::getVideoDriver() +{ + return Driver; +} + +//! returns the GUI Environment +gui::IGUIEnvironment* CSceneManager::getGUIEnvironment () +{ + return GUIEnvironment; +} + + +//! Adds a text scene node, which is able to display +//! 2d text at a position in three dimensional space +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; +} + +//! Adds a text scene node, which uses billboards +ITextSceneNode* CSceneManager::addBillboardTextSceneNode(gui::IGUIFont* font, + const wchar_t* text, ISceneNode* parent, + const core::dimension2d& size, + const core::vector3df& position, s32 id, + video::SColor shade_top, video::SColor shade_down) +{ + if (!font) + return 0; + + if (!parent) + parent = this; + + ITextSceneNode* node = new CBillboardTextSceneNode(parent, this, id, font, text, position, size, + shade_top, shade_down); + node->drop(); + + return node; + +} + + +//! Adds a scene node, which can render a quake3 shader +ISceneNode* CSceneManager::addQuake3SceneNode( IMeshBuffer* meshBuffer, + const quake3::SShader * shader, + ISceneNode* parent, + s32 id + ) + +{ + if ( 0 == shader ) + return 0; + + if (!parent) + parent = this; + + CQuake3ShaderSceneNode* node = new CQuake3ShaderSceneNode ( parent, this, id, FileSystem, meshBuffer, shader ); + node->drop(); + + return node; + +} + +//! adds Volume Lighting Scene Node. +//! the returned pointer must not be dropped. +ISceneNode* CSceneManager::addVolumeLightSceneNode(ISceneNode* parent, s32 id, + const s32 subdivU, const s32 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; + + ISceneNode* node = new CVolumeLightSceneNode(parent, this, id, subdivU, subdivV, foot, tail, position, rotation, scale); + node->drop(); + + return node; +} + +//! adds a test scene node for test purposes to the scene. It is a simple cube of (1,1,1) size. +//! the returned pointer must not be dropped. +ISceneNode* CSceneManager::addCubeSceneNode(f32 size, ISceneNode* parent, s32 id, + const core::vector3df& position, const core::vector3df& rotation, const core::vector3df& scale) +{ + if (!parent) + parent = this; + + ISceneNode* node = new CCubeSceneNode(size, parent, this, id, position, rotation, scale); + node->drop(); + + return node; +} + +//! Adds a sphere scene node for test purposes to the scene. +ISceneNode* 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; + + ISceneNode* node = new CSphereSceneNode(radius, polyCount, polyCount, parent, this, id, position, rotation, scale); + node->drop(); + + return node; +} + + +//! adds a scene node for rendering a static mesh +//! the returned pointer must not be dropped. +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; +} + + +//! Adds a scene node for rendering a animated water surface mesh. +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 (!mesh) + return 0; + + if (!parent) + parent = this; + + ISceneNode* node = new CWaterSurfaceSceneNode(waveHeight, waveSpeed, waveLength, + mesh, parent, this, id, position, rotation, scale); + + node->drop(); + + return node; +} + + + +//! adds a scene node for rendering an animated mesh model +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; +} + + +//! Adds a scene node for rendering using a octtree to the scene graph. This a good method for rendering +//! scenes with lots of geometry. The Octree is built on the fly from the mesh, much +//! faster then a bsp tree. +ISceneNode* CSceneManager::addOctTreeSceneNode(IAnimatedMesh* mesh, ISceneNode* parent, + s32 id, s32 minimalPolysPerNode, bool alsoAddIfMeshPointerZero) +{ + if (!alsoAddIfMeshPointerZero && (!mesh || !mesh->getFrameCount())) + return 0; + + return addOctTreeSceneNode(mesh ? mesh->getMesh(0) : 0, + parent, id, minimalPolysPerNode, + alsoAddIfMeshPointerZero); +} + + + +//! Adss a scene node for rendering using a octtree. This a good method for rendering +//! scenes with lots of geometry. The Octree is built on the fly from the mesh, much +//! faster then a bsp tree. +ISceneNode* CSceneManager::addOctTreeSceneNode(IMesh* mesh, ISceneNode* parent, + s32 id, s32 minimalPolysPerNode, bool alsoAddIfMeshPointerZero) +{ + if (!alsoAddIfMeshPointerZero && !mesh) + return 0; + + if (!parent) + parent = this; + + COctTreeSceneNode* node = new COctTreeSceneNode(parent, this, id, minimalPolysPerNode); + + if (mesh) + node->createTree(mesh); + + node->drop(); + + return node; +} + + +//! Adds a camera scene node to the tree and sets it as active camera. +//! \param position: Position of the space relative to its parent where the camera will be placed. +//! \param lookat: Position where the camera will look at. Also known as target. +//! \param parent: Parent scene node of the camera. Can be null. If the parent moves, +//! the camera will move too. +//! \return Returns pointer to interface to camera +ICameraSceneNode* CSceneManager::addCameraSceneNode(ISceneNode* parent, + const core::vector3df& position, const core::vector3df& lookat, s32 id) +{ + if (!parent) + parent = this; + + ICameraSceneNode* node = new CCameraSceneNode(parent, this, id, position, lookat); + node->drop(); + + setActiveCamera(node); + + return node; +} + + + +//! Adds a camera scene node which is able to be controlle with the mouse similar +//! like in the 3D Software Maya by Alias Wavefront. +//! The returned pointer must not be dropped. +ICameraSceneNode* CSceneManager::addCameraSceneNodeMaya(ISceneNode* parent, + f32 rotateSpeed, f32 zoomSpeed, f32 translationSpeed, s32 id) +{ + if (!parent) + parent = this; + + ICameraSceneNode* node = new CCameraMayaSceneNode(parent, this, id, rotateSpeed, + zoomSpeed, translationSpeed); + node->drop(); + + setActiveCamera(node); + + return node; +} + + + +//! Adds a camera scene node which is able to be controled with the mouse and keys +//! like in most first person shooters (FPS): +ICameraSceneNode* CSceneManager::addCameraSceneNodeFPS(ISceneNode* parent, + f32 rotateSpeed, f32 moveSpeed, s32 id, + SKeyMap* keyMapArray, s32 keyMapSize, bool noVerticalMovement,f32 jumpSpeed) +{ + if (!parent) + parent = this; + + ICameraSceneNode* node = new CCameraFPSSceneNode(parent, this, CursorControl, + id, rotateSpeed, moveSpeed, jumpSpeed, keyMapArray, keyMapSize, noVerticalMovement); + node->drop(); + + setActiveCamera(node); + + return node; +} + + + +//! Adds a dynamic light scene node. The light will cast dynamic light on all +//! other scene nodes in the scene, which have the material flag video::MTF_LIGHTING +//! turned on. (This is the default setting in most scene nodes). +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; +} + + + +//! Adds a billboard scene node to the scene. A billboard is like a 3d sprite: A 2d element, +//! which always looks to the camera. It is usually used for things like explosions, fire, +//! lensflares and things like that. +IBillboardSceneNode* CSceneManager::addBillboardSceneNode(ISceneNode* parent, + const core::dimension2d& size, const core::vector3df& position, s32 id, + video::SColor shade_top, video::SColor shade_down + ) +{ + if (!parent) + parent = this; + + IBillboardSceneNode* node = new CBillboardSceneNode(parent, this, id, position, size, + shade_top, shade_down); + node->drop(); + + return node; +} + + + +//! Adds a skybox scene node. A skybox is a big cube with 6 textures on it and +//! is drawn around the camera position. +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; +} + + +//! Adds a skydome scene node. A skydome is a large (half-) sphere with a +//! panoramic texture on it and is drawn around the camera position. +ISceneNode* CSceneManager::addSkyDomeSceneNode(video::ITexture* texture, + u32 horiRes, u32 vertRes, f64 texturePercentage, + f64 spherePercentage, ISceneNode* parent, s32 id) +{ + if (!parent) + parent = this; + + ISceneNode* node = new CSkyDomeSceneNode(texture, horiRes, vertRes, + texturePercentage, spherePercentage, parent, this, id); + + node->drop(); + return node; +} + + +//! Adds a particle system scene 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; +} + + +//! Adds a terrain scene node to the scene graph. +ITerrainSceneNode* CSceneManager::addTerrainSceneNode( + const char* 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; +} + +//! Adds a terrain scene node to the scene graph. +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; +} + + +//! Adds an empty scene node. +ISceneNode* CSceneManager::addEmptySceneNode(ISceneNode* parent, s32 id) +{ + if (!parent) + parent = this; + + ISceneNode* node = new CEmptySceneNode(parent, this, id); + node->drop(); + + return node; +} + + +//! Adds a dummy transformation scene node to the scene graph. +IDummyTransformationSceneNode* CSceneManager::addDummyTransformationSceneNode( + ISceneNode* parent, s32 id) +{ + if (!parent) + parent = this; + + IDummyTransformationSceneNode* node = new CDummyTransformationSceneNode( + parent, this, id); + node->drop(); + + return node; +} + +//! Adds a Hill Plane mesh to the mesh pool. The mesh is generated on the fly +//! and looks like a plane with some hills on it. It is uses mostly for quick +//! tests of the engine only. You can specify how many hills there should be +//! on the plane and how high they should be. Also you must specify a name for +//! the mesh, because the mesh is added to the mesh pool, and can be retrieved +//! again using ISceneManager::getMesh with the name as parameter. +IAnimatedMesh* CSceneManager::addHillPlaneMesh(const c8* name, + const core::dimension2d& tileSize, + const core::dimension2d& tileCount, + video::SMaterial* material, f32 hillHeight, + const core::dimension2d& countHills, + const core::dimension2d& textureRepeatCount) +{ + if (!name || MeshCache->isMeshLoaded(name)) + return 0; + + IMesh* mesh = CGeometryCreator::createHillPlaneMesh(tileSize, + tileCount, material, hillHeight, countHills, + textureRepeatCount); + if (!mesh) + return 0; + + SAnimatedMesh* animatedMesh = new SAnimatedMesh(); + if (!animatedMesh) + return 0; + + animatedMesh->addMesh(mesh); + animatedMesh->recalculateBoundingBox(); + mesh->drop(); + + MeshCache->addMesh(name, animatedMesh); + animatedMesh->drop(); + + return animatedMesh; +} + + +//! Adds a terrain mesh to the mesh pool. +IAnimatedMesh* CSceneManager::addTerrainMesh(const c8* name, + video::IImage* texture, video::IImage* heightmap, + const core::dimension2d& stretchSize, + f32 maxHeight, + const core::dimension2d& defaultVertexBlockSize) +{ + if (!name || MeshCache->isMeshLoaded(name)) + return 0; + + IMesh* mesh = CGeometryCreator::createTerrainMesh(texture, heightmap, + stretchSize, maxHeight, getVideoDriver(), + defaultVertexBlockSize); + if (!mesh) + return 0; + + SAnimatedMesh* animatedMesh = new SAnimatedMesh(); + if (!animatedMesh) + return 0; + + animatedMesh->addMesh(mesh); + animatedMesh->recalculateBoundingBox(); + mesh->drop(); + + MeshCache->addMesh(name, animatedMesh); + animatedMesh->drop(); + + return animatedMesh; +} + +//! Adds an arrow mesh to the mesh pool. +IAnimatedMesh* CSceneManager::addArrowMesh(const c8* name, + video::SColor vtxColor0, video::SColor vtxColor1, + u32 tesselationCylinder, u32 tesselationCone, f32 height, + f32 cylinderHeight, f32 width0,f32 width1) +{ + if (!name || MeshCache->isMeshLoaded(name)) + return 0; + + IMesh* mesh = CGeometryCreator::createArrowMesh( tesselationCylinder, + tesselationCone, height, cylinderHeight, width0,width1, + vtxColor0, vtxColor1); + if (!mesh) + return 0; + + SAnimatedMesh* animatedMesh = new SAnimatedMesh(); + if (!animatedMesh) + return 0; + + animatedMesh->addMesh(mesh); + animatedMesh->recalculateBoundingBox(); + mesh->drop(); + + MeshCache->addMesh(name, animatedMesh); + animatedMesh->drop(); + + return animatedMesh; +} + + + +//! Adds a static sphere mesh to the mesh pool. +IAnimatedMesh* CSceneManager::addSphereMesh(const c8* name, + f32 radius, u32 polyCountX, u32 polyCountY) +{ + if (!name || MeshCache->isMeshLoaded(name)) + return 0; + + IMesh* mesh = CGeometryCreator::createSphereMesh( radius, polyCountX, polyCountY); + if (!mesh) + return 0; + + SAnimatedMesh* animatedMesh = new SAnimatedMesh(); + if (!animatedMesh) + return 0; + + animatedMesh->addMesh(mesh); + animatedMesh->recalculateBoundingBox(); + mesh->drop(); + + MeshCache->addMesh(name, animatedMesh); + animatedMesh->drop(); + + return animatedMesh; +} + + + +//! Returns the root scene node. This is the scene node wich is parent +//! of all scene nodes. The root scene node is a special scene node which +//! only exists to manage all scene nodes. It is not rendered and cannot +//! be removed from the scene. +//! \return Returns a pointer to the root scene node. +ISceneNode* CSceneManager::getRootSceneNode() +{ + return this; +} + + + +//! Returns the current active camera. +//! \return The active camera is returned. Note that this can be NULL, if there +//! was no camera created yet. +ICameraSceneNode* CSceneManager::getActiveCamera() +{ + return ActiveCamera; +} + + + +//! Sets the active camera. The previous active camera will be deactivated. +//! \param camera: The new camera which should be active. +void CSceneManager::setActiveCamera(ICameraSceneNode* camera) +{ + if (ActiveCamera) + ActiveCamera->drop(); + + ActiveCamera = camera; + + if (ActiveCamera) + ActiveCamera->grab(); +} + + + + +//! renders the node. +void CSceneManager::render() +{ +} + + +//! returns the axis aligned bounding box of this node +const core::aabbox3d& CSceneManager::getBoundingBox() const +{ + _IRR_DEBUG_BREAK_IF(true) // Bounding Box of Scene Manager wanted. + + // should never be used. + return *((core::aabbox3d*)0); +} + + + +//! returns if node is culled +bool CSceneManager::isCulled(const ISceneNode* node) +{ + const ICameraSceneNode* cam = getActiveCamera(); + if (!cam) + return false; + + switch ( node->getAutomaticCulling() ) + { + // can be seen by a bounding box ? + case scene::EAC_BOX: + { + core::aabbox3d tbox = node->getBoundingBox(); + node->getAbsoluteTransformation().transformBox(tbox); + return !(tbox.intersectsWithBox(cam->getViewFrustum()->getBoundingBox() )); + } + + // can be seen by a bounding sphere + case scene::EAC_FRUSTUM_SPHERE: + { // requires bbox diameter + } + break; + + // can be seen by cam pyramid planes ? + case scene::EAC_FRUSTUM_BOX: + { + SViewFrustum frust = *cam->getViewFrustum(); + + //transform the frustum to the node's current absolute transformation + core::matrix4 invTrans(node->getAbsoluteTransformation()); + invTrans.makeInverse(); + frust.transform(invTrans); + + core::vector3df edges[8]; + node->getBoundingBox().getEdges(edges); + + for (s32 i=0; igetMaterialCount(); + + taken = 0; + for (u32 i=0; igetMaterialRenderer(node->getMaterial(i).MaterialType); + if (rnd && rnd->isTransparent()) + { + // register as transparent node + TransparentNodeEntry e(node, camWorldPos); + TransparentNodeList.push_back(e); + taken = 1; + break; + } + } + + // not transparent, register as solid + if ( 0 == taken ) + { + SolidNodeList.push_back( node ); + taken = 1; + } + } + break; + case ESNRP_SHADOW: + if (!isCulled(node)) + { + ShadowNodeList.push_back(node); + taken = 1; + } + break; + + case ESNRP_COUNT: // ignore this one + break; + } + +#ifdef SCENEMANAGER_DEBUG + s32 index = Parameters.findAttribute ( "calls" ); + Parameters.setAttribute ( index, Parameters.getAttributeAsInt ( index ) + 1 ); + + if ( 0 == taken ) + { + index = Parameters.findAttribute ( "culled" ); + Parameters.setAttribute ( index, Parameters.getAttributeAsInt ( index ) + 1 ); + } +#endif + + return taken; +} + +//! This method is called just before the rendering process of the whole scene. +//! draws all scene nodes +void CSceneManager::drawAll() +{ + if (!Driver) + return; + + // reset attributes + Parameters.setAttribute ( "culled", 0 ); + Parameters.setAttribute ( "calls", 0 ); + Parameters.setAttribute ( "drawn", 0 ); + + // reset all transforms + video::IVideoDriver* driver = getVideoDriver(); + if ( driver ) + { + driver->setTransform ( video::ETS_PROJECTION, core::IdentityMatrix ); + driver->setTransform ( video::ETS_VIEW, core::IdentityMatrix ); + driver->setTransform ( video::ETS_WORLD, core::IdentityMatrix ); + driver->setTransform ( video::ETS_TEXTURE_0, core::IdentityMatrix ); + driver->setTransform ( video::ETS_TEXTURE_1, core::IdentityMatrix ); + driver->setTransform ( video::ETS_TEXTURE_2, core::IdentityMatrix ); + driver->setTransform ( video::ETS_TEXTURE_3, core::IdentityMatrix ); + } + + // do animations and other stuff. + OnAnimate(os::Timer::getTime()); + + /*! + First Scene Node for prerendering should be the active camera + consistent Camera is needed for culling + */ + camWorldPos.set(0,0,0); + if ( ActiveCamera ) + { + ActiveCamera->OnRegisterSceneNode(); + camWorldPos = ActiveCamera->getAbsolutePosition(); + } + + // let all nodes register themselves + OnRegisterSceneNode(); + + u32 i; // new ISO for scoping problem in some compilers + + //render camera scenes + { + CurrentRendertime = ESNRP_CAMERA; + for (i=0; irender(); + + CameraList.set_used(0); + } + + //render lights scenes + { + CurrentRendertime = ESNRP_LIGHT; + + Driver->deleteAllDynamicLights(); + + Driver->setAmbientLight(AmbientLight); + + LightList.sort (); // on distance to camera + + u32 maxLights = core::min_ ( Driver->getMaximalDynamicLightAmount (), LightList.size () ); + for (i=0; i< maxLights; ++i) + LightList[i].node->render(); + + LightList.set_used(0); + } + + // render skyboxes + { + CurrentRendertime = ESNRP_SKY_BOX; + + for (i=0; irender(); + + SkyBoxList.set_used(0); + } + + + // render default objects + { + CurrentRendertime = ESNRP_SOLID; + SolidNodeList.sort(); // sort by textures + + for (i=0; irender(); + + Parameters.setAttribute ( "drawn", (s32) SolidNodeList.size () ); + + SolidNodeList.set_used(0); + } + + // render shadows + { + CurrentRendertime = ESNRP_SHADOW; + for (i=0; irender(); + + if (!ShadowNodeList.empty()) + Driver->drawStencilShadow(true,ShadowColor, ShadowColor, + ShadowColor, ShadowColor); + + ShadowNodeList.set_used(0); + } + + // render transparent objects. + { + CurrentRendertime = ESNRP_TRANSPARENT; + TransparentNodeList.sort(); // sort by distance from camera + + for (i=0; irender(); + + TransparentNodeList.set_used(0); + } + + + clearDeletionList(); + + CurrentRendertime = ESNRP_COUNT; +} + + +//! Sets the color of stencil buffers shadows drawn by the scene manager. +void CSceneManager::setShadowColor(video::SColor color) +{ + ShadowColor = color; +} + + +//! Returns the current color of shadows. +video::SColor CSceneManager::getShadowColor() const +{ + return ShadowColor; +} + + + +//! creates a rotation animator, which rotates the attached scene node around itself. +ISceneNodeAnimator* CSceneManager::createRotationAnimator(const core::vector3df& rotationPerSecond) +{ + ISceneNodeAnimator* anim = new CSceneNodeAnimatorRotation(os::Timer::getTime(), + rotationPerSecond); + + return anim; +} + + + +//! creates a fly circle animator, which lets the attached scene node fly around a center. +ISceneNodeAnimator* CSceneManager::createFlyCircleAnimator( + const core::vector3df& normal, f32 radius, f32 speed, + const core::vector3df& direction) +{ + ISceneNodeAnimator* anim = new CSceneNodeAnimatorFlyCircle(os::Timer::getTime(), normal, + radius, speed, direction); + return anim; +} + + +//! Creates a fly straight animator, which lets the attached scene node +//! fly or move along a line between two points. +ISceneNodeAnimator* CSceneManager::createFlyStraightAnimator(const core::vector3df& startPoint, + const core::vector3df& endPoint, u32 timeForWay, bool loop) +{ + ISceneNodeAnimator* anim = new CSceneNodeAnimatorFlyStraight(startPoint, + endPoint, timeForWay, loop, os::Timer::getTime()); + + return anim; +} + + +//! Creates a texture animator, which switches the textures of the target scene +//! node based on a list of textures. +ISceneNodeAnimator* CSceneManager::createTextureAnimator(const core::array& textures, + s32 timePerFrame, bool loop) +{ + ISceneNodeAnimator* anim = new CSceneNodeAnimatorTexture(textures, + timePerFrame, loop, os::Timer::getTime()); + + return anim; +} + + +//! Creates a scene node animator, which deletes the scene node after +//! some time automaticly. +ISceneNodeAnimator* CSceneManager::createDeleteAnimator(u32 when) +{ + return new CSceneNodeAnimatorDelete(this, os::Timer::getTime() + when); +} + + + + +//! Creates a special scene node animator for doing automatic collision detection +//! and response. +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; +} + + +//! Creates a follow spline animator. +ISceneNodeAnimator* CSceneManager::createFollowSplineAnimator(s32 startTime, + const core::array< core::vector3df >& points, + f32 speed, f32 tightness) +{ + ISceneNodeAnimator* a = new CSceneNodeAnimatorFollowSpline(startTime, points, + speed, tightness); + return a; +} + + + +//! Adds an external mesh loader. +void CSceneManager::addExternalMeshLoader(IMeshLoader* externalLoader) +{ + if (!externalLoader) + return; + + externalLoader->grab(); + MeshLoaderList.push_back(externalLoader); +} + + + +//! Returns a pointer to the scene collision manager. +ISceneCollisionManager* CSceneManager::getSceneCollisionManager() +{ + return CollisionManager; +} + + +//! Returns a pointer to the mesh manipulator. +IMeshManipulator* CSceneManager::getMeshManipulator() +{ + return MeshManipulator; +} + + +//! Creates a simple ITriangleSelector, based on a mesh. +ITriangleSelector* CSceneManager::createTriangleSelector(IMesh* mesh, ISceneNode* node) +{ + if (!mesh || !node) + return 0; + + return new CTriangleSelector(mesh, node); +} + + +//! Creates a simple dynamic ITriangleSelector, based on a axis aligned bounding box. +ITriangleSelector* CSceneManager::createTriangleSelectorFromBoundingBox(ISceneNode* node) +{ + if (!node) + return 0; + + return new CTriangleBBSelector(node); +} + + +//! Creates a simple ITriangleSelector, based on a mesh. +ITriangleSelector* CSceneManager::createOctTreeTriangleSelector(IMesh* mesh, + ISceneNode* node, + s32 minimalPolysPerNode) +{ + if (!mesh || !node) + return 0; + + return new COctTreeTriangleSelector(mesh, node, minimalPolysPerNode); +} + + + +//! Creates a meta triangle selector. +IMetaTriangleSelector* CSceneManager::createMetaTriangleSelector() +{ + return new CMetaTriangleSelector(); +} + + + +//! Creates a triangle selector which can select triangles from a terrain scene node +ITriangleSelector* CSceneManager::createTerrainTriangleSelector( + ITerrainSceneNode* node, s32 LOD) +{ + return new CTerrainTriangleSelector(node, LOD); +} + + + +//! Adds a scene node to the deletion queue. +void CSceneManager::addToDeletionQueue(ISceneNode* node) +{ + if (!node) + return; + + node->grab(); + DeletionList.push_back(node); +} + + +//! clears the deletion list +void CSceneManager::clearDeletionList() +{ + if (DeletionList.empty()) + return; + + for (s32 i=0; i<(s32)DeletionList.size(); ++i) + { + DeletionList[i]->remove(); + DeletionList[i]->drop(); + } + + DeletionList.clear(); +} + + +//! Returns the first scene node with the specified name. +ISceneNode* CSceneManager::getSceneNodeFromName(const char* name, ISceneNode* start) +{ + if (start == 0) + start = getRootSceneNode(); + + if (!strcmp(start->getName(),name)) + return start; + + ISceneNode* node = 0; + + const core::list& list = start->getChildren(); + core::list::ConstIterator it = list.begin(); + for (; it!=list.end(); ++it) + { + node = getSceneNodeFromName(name, *it); + if (node) + return node; + } + + return 0; +} + + +//! Returns the first scene node with the specified id. +ISceneNode* CSceneManager::getSceneNodeFromId(s32 id, ISceneNode* start) +{ + if (start == 0) + start = getRootSceneNode(); + + if (start->getID() == id) + return start; + + ISceneNode* node = 0; + + const core::list& list = start->getChildren(); + core::list::ConstIterator it = list.begin(); + for (; it!=list.end(); ++it) + { + node = getSceneNodeFromId(id, *it); + if (node) + return node; + } + + return 0; +} + + +//! Returns the first scene node with the specified type. +ISceneNode* CSceneManager::getSceneNodeFromType(scene::ESCENE_NODE_TYPE type, ISceneNode* start) +{ + if (start == 0) + start = getRootSceneNode(); + + if (start->getType() == type) + return start; + + ISceneNode* node = 0; + + const core::list& list = start->getChildren(); + core::list::ConstIterator it = list.begin(); + for (; it!=list.end(); ++it) + { + node = getSceneNodeFromType(type, *it); + if (node) + return node; + } + + return 0; +} + +//! returns scene nodes by type. +void CSceneManager::getSceneNodesFromType(ESCENE_NODE_TYPE type, core::array& outNodes, ISceneNode* start) +{ + if (start == 0) + start = getRootSceneNode(); + + if (start->getType() == type) + outNodes.push_back(start); + + const core::list& list = start->getChildren(); + core::list::ConstIterator it = list.begin(); + + for (; it!=list.end(); ++it) + { + getSceneNodesFromType(type, outNodes, *it); + } +} + + +//! Posts an input event to the environment. Usually you do not have to +//! use this method, it is used by the internal engine. +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; +} + + +//! Removes all children of this scene node +void CSceneManager::removeAll() +{ + ISceneNode::removeAll(); + setActiveCamera(0); +} + + +//! Clears the whole scene. All scene nodes are removed. +void CSceneManager::clear() +{ + removeAll(); +} + + +//! Returns interface to the parameters set in this scene. +io::IAttributes* CSceneManager::getParameters() +{ + return &Parameters; +} + + +//! Returns current render pass. +E_SCENE_NODE_RENDER_PASS CSceneManager::getSceneNodeRenderPass() const +{ + return CurrentRendertime; +} + + + +//! Returns an interface to the mesh cache which is shared beween all existing scene managers. +IMeshCache* CSceneManager::getMeshCache() +{ + return MeshCache; +} + + +//! Creates a new scene manager. +ISceneManager* CSceneManager::createNewSceneManager(bool cloneContent) +{ + CSceneManager* manager = new CSceneManager(Driver, FileSystem, CursorControl, MeshCache); + + if (cloneContent) + manager->cloneMembers(this, manager); + + return manager; +} + + +//! Returns the default scene node factory which can create all built in scene nodes +ISceneNodeFactory* CSceneManager::getDefaultSceneNodeFactory() +{ + return getSceneNodeFactory(0); +} + + +//! Adds a scene node factory to the scene manager. +void CSceneManager::registerSceneNodeFactory(ISceneNodeFactory* factoryToAdd) +{ + if (factoryToAdd) + { + factoryToAdd->grab(); + SceneNodeFactoryList.push_back(factoryToAdd); + } +} + + +//! Returns amount of registered scene node factories. +u32 CSceneManager::getRegisteredSceneNodeFactoryCount() const +{ + return SceneNodeFactoryList.size(); +} + + +//! Returns a scene node factory by index +ISceneNodeFactory* CSceneManager::getSceneNodeFactory(u32 index) +{ + if (indexgrab(); + SceneNodeAnimatorFactoryList.push_back(factoryToAdd); + } +} + + +//! Returns amount of registered scene node animator factories. +u32 CSceneManager::getRegisteredSceneNodeAnimatorFactoryCount() const +{ + return SceneNodeAnimatorFactoryList.size(); +} + + +//! Returns a scene node animator factory by index +ISceneNodeAnimatorFactory* CSceneManager::getSceneNodeAnimatorFactory(u32 index) +{ + if (indexcreateAndWriteFile(filename); + if (!file) + return false; + + bool ret = saveScene(file, userDataSerializer); + file->drop(); + return ret; +} + + +//! Saves the current scene into a file. +bool CSceneManager::saveScene(io::IWriteFile* file, ISceneUserDataSerializer* userDataSerializer) +{ + if (!file) + return false; + + io::IXMLWriter* writer = FileSystem->createXMLWriter(file); + if (!writer) + return false; + + writer->writeXMLHeader(); + writeSceneNode(writer, this, userDataSerializer); + writer->drop(); + + return true; +} + + +//! Loads a scene. Note that the current scene is not cleared before. +//! \param filename: Name of the file . +bool CSceneManager::loadScene(const c8* filename, ISceneUserDataSerializer* userDataSerializer) +{ + io::IReadFile* read = FileSystem->createAndOpenFile(filename); + if (!read) + { + os::Printer::log("Unable to open scene file", filename, ELL_ERROR); + return false; + } + + bool ret = loadScene(read, userDataSerializer); + read->drop(); + + return ret; +} + + +//! Loads a scene. Note that the current scene is not cleared before. +bool CSceneManager::loadScene(io::IReadFile* file, ISceneUserDataSerializer* userDataSerializer) +{ + if (!file) + { + os::Printer::log("Unable to open scene file", ELL_ERROR); + return false; + } + + io::IXMLReader* reader = FileSystem->createXMLReader(file); + if (!reader) + { + os::Printer::log("Scene is not a valid XML file", file->getFileName(), ELL_ERROR); + return false; + } + + // for mesh loading, set collada loading attributes + + bool oldColladaSingleMesh = getParameters()->getAttributeAsBool(COLLADA_CREATE_SCENE_INSTANCES); + getParameters()->setAttribute(COLLADA_CREATE_SCENE_INSTANCES, false); + + // read file + + while(reader->read()) + { + readSceneNode(reader, 0, userDataSerializer); + } + + // restore old collada parameters + + getParameters()->setAttribute(COLLADA_CREATE_SCENE_INSTANCES, oldColladaSingleMesh); + + // finish up + + reader->drop(); + return true; + +} + + +//! reads a scene node +void CSceneManager::readSceneNode(io::IXMLReader* reader, ISceneNode* parent, ISceneUserDataSerializer* userDataSerializer) +{ + if (!reader) + return; + + scene::ISceneNode* node = 0; + + if ((!parent && IRR_XML_FORMAT_SCENE==reader->getNodeName()) || + ( parent && IRR_XML_FORMAT_NODE==reader->getNodeName())) + { + if (parent) + { + // find node type and create it + core::stringc attrName = reader->getAttributeValue(IRR_XML_FORMAT_NODE_ATTR_TYPE.c_str()); + + for (int i=(int)SceneNodeFactoryList.size()-1; i>=0 && !node; --i) + node = SceneNodeFactoryList[i]->addSceneNode(attrName.c_str(), parent); + + if (!node) + os::Printer::log("Could not create scene node of unknown type", attrName.c_str()); + } + else + node = this; // root + } + + // read attributes + while(reader->read()) + { + bool endreached = false; + + switch (reader->getNodeType()) + { + case io::EXN_ELEMENT_END: + if ((IRR_XML_FORMAT_NODE==reader->getNodeName()) || + (IRR_XML_FORMAT_SCENE==reader->getNodeName())) + { + endreached = true; + } + break; + case io::EXN_ELEMENT: + if (core::stringw(L"attributes")==reader->getNodeName()) + { + // read attributes + io::IAttributes* attr = FileSystem->createEmptyAttributes(Driver); + attr->read(reader, true); + + if (node) + node->deserializeAttributes(attr); + + attr->drop(); + } + else + if (core::stringw(L"materials")==reader->getNodeName()) + readMaterials(reader, node); + else + if (core::stringw(L"animators")==reader->getNodeName()) + readAnimators(reader, node); + else + if (core::stringw(L"userData")==reader->getNodeName()) + readUserData(reader, node, userDataSerializer); + else + if ((IRR_XML_FORMAT_NODE==reader->getNodeName()) || + (IRR_XML_FORMAT_SCENE==reader->getNodeName())) + { + readSceneNode(reader, node, userDataSerializer); + } + else + { + os::Printer::log("Found unknown element in irrlicht scene file", + core::stringc(reader->getNodeName()).c_str()); + } + break; + default: + break; + } + + if (endreached) + break; + } +} + + +//! reads materials of a node +void CSceneManager::readMaterials(io::IXMLReader* reader, ISceneNode* node) +{ + u32 nr = 0; + + while(reader->read()) + { + const wchar_t* name = reader->getNodeName(); + + switch(reader->getNodeType()) + { + case io::EXN_ELEMENT_END: + if (core::stringw(L"materials")==name) + return; + break; + case io::EXN_ELEMENT: + if (core::stringw(L"attributes")==name) + { + // read materials from attribute list + io::IAttributes* attr = FileSystem->createEmptyAttributes(Driver); + attr->read(reader); + + if (node && node->getMaterialCount() > nr) + { + getVideoDriver()->fillMaterialStructureFromAttributes( + node->getMaterial(nr), attr); + } + + attr->drop(); + ++nr; + } + break; + default: + break; + } + } +} + + +//! reads animators of a node +void CSceneManager::readAnimators(io::IXMLReader* reader, ISceneNode* node) +{ + while(reader->read()) + { + const wchar_t* name = reader->getNodeName(); + + switch(reader->getNodeType()) + { + case io::EXN_ELEMENT_END: + if (core::stringw(L"animators")==name) + return; + break; + case io::EXN_ELEMENT: + if (core::stringw(L"attributes")==name) + { + // read animator data from attribute list + io::IAttributes* attr = FileSystem->createEmptyAttributes(Driver); + attr->read(reader); + + if (node) + { + core::stringc typeName = attr->getAttributeAsString("Type"); + ISceneNodeAnimator* anim = 0; + + for (int i=0; i<(int)SceneNodeAnimatorFactoryList.size() && !anim; ++i) + anim = SceneNodeAnimatorFactoryList[i]->createSceneNodeAnimator(typeName.c_str(), node); + + if (anim) + { + anim->deserializeAttributes(attr); + anim->drop(); + } + } + + attr->drop(); + } + break; + default: + break; + } + } +} + + +//! reads user data of a node +void CSceneManager::readUserData(io::IXMLReader* reader, ISceneNode* node, ISceneUserDataSerializer* userDataSerializer) +{ + while(reader->read()) + { + const wchar_t* name = reader->getNodeName(); + + switch(reader->getNodeType()) + { + case io::EXN_ELEMENT_END: + if (core::stringw(L"userData")==name) + return; + break; + case io::EXN_ELEMENT: + if (core::stringw(L"attributes")==name) + { + // read user data from attribute list + io::IAttributes* attr = FileSystem->createEmptyAttributes(Driver); + attr->read(reader); + + if (node && userDataSerializer) + { + userDataSerializer->OnReadUserData(node, attr); + } + + attr->drop(); + } + break; + default: + break; + } + } +} + + +//! writes a scene node +void CSceneManager::writeSceneNode(io::IXMLWriter* writer, ISceneNode* node, ISceneUserDataSerializer* userDataSerializer) +{ + if (!writer || !node || node->isDebugObject()) + return; + + const wchar_t* name; + + if (node == this) + { + name = IRR_XML_FORMAT_SCENE.c_str(); + writer->writeElement(name, false); + } + 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(); + writer->writeLineBreak(); + + // write properties + + io::IAttributes* attr = FileSystem->createEmptyAttributes(Driver); + node->serializeAttributes(attr); + + if (attr->getAttributeCount() != 0) + { + attr->write(writer); + writer->writeLineBreak(); + } + + // write materials + + 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(); + } + + // write animators + + if (!node->getAnimators().empty()) + { + const wchar_t* animatorElement = L"animators"; + writer->writeElement(animatorElement); + writer->writeLineBreak(); + + core::list::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(); + } + + // write possible user data + + 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(); + } + } + + // write children + + core::list::ConstIterator it = node->getChildren().begin(); + for (; it != node->getChildren().end(); ++it) + writeSceneNode(writer, (*it), userDataSerializer); + + attr->drop(); + + writer->writeClosingTag(name); + writer->writeLineBreak(); + writer->writeLineBreak(); +} + + +//! Returns a typename from a scene node type or null if not found +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; +} + +//! Adds a scene node to the scene by 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; +} + + +//! Returns a typename from a scene node animator type or null if not found +const c8* CSceneManager::getAnimatorTypeName(ESCENE_NODE_ANIMATOR_TYPE type) const +{ + const char* name = 0; + + for (u32 i=0; !name && igetCreateableSceneNodeAnimatorTypeName(type); + + return name; +} + + +//! Writes attributes of the scene node. +void CSceneManager::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const +{ + out->addString ("Name", Name.c_str()); + out->addInt ("Id", ID ); + out->addColorf ("AmbientLight", AmbientLight); +} + +//! Reads attributes of the scene node. +void CSceneManager::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) +{ + Name = in->getAttributeAsString("Name"); + ID = in->getAttributeAsInt("Id"); + AmbientLight = in->getAttributeAsColorf("AmbientLight"); + + 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(); +} + + +//! Sets ambient color of the scene +void CSceneManager::setAmbientLight(const video::SColorf &ambientColor) +{ + AmbientLight = ambientColor; +} + + +//! Returns ambient color of the scene +const video::SColorf& CSceneManager::getAmbientLight() const +{ + return AmbientLight; +} + + +//! Returns a mesh writer implementation if available +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 + } + + return 0; +} + + +// creates a scenemanager +ISceneManager* createSceneManager(video::IVideoDriver* driver, + io::IFileSystem* fs, gui::ICursorControl* cursorcontrol, + gui::IGUIEnvironment *guiEnvironment) +{ + return new CSceneManager(driver, fs, cursorcontrol, 0, guiEnvironment ); +} + + +} // end namespace scene +} // end namespace irr + diff --git a/source/Irrlicht/CSceneManager.h b/source/Irrlicht/CSceneManager.h index 3449e91d..79741072 100644 --- a/source/Irrlicht/CSceneManager.h +++ b/source/Irrlicht/CSceneManager.h @@ -50,6 +50,14 @@ namespace scene virtual gui::IGUIEnvironment* getGUIEnvironment(); + //! adds Volume Lighting Scene Node. + //! the returned pointer must not be dropped. + virtual ISceneNode* addVolumeLightSceneNode(ISceneNode* parent=0, s32 id=-1, + const s32 subdivU = 32, const s32 subdivV = 32, + const video::SColor foot = video::SColor(51, 0, 230, 180), + const video::SColor tail = video::SColor(0, 0, 0, 0), + const core::vector3df& position = core::vector3df(0,0,0), const core::vector3df& rotation = core::vector3df(0,0,0), const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)); + //! adds a cube scene node to the scene. It is a simple cube of (1,1,1) size. //! the returned pointer must not be dropped. virtual ISceneNode* addCubeSceneNode(f32 size=10.0f, ISceneNode* parent=0, s32 id=-1, diff --git a/source/Irrlicht/CVolumeLightSceneNode.cpp b/source/Irrlicht/CVolumeLightSceneNode.cpp new file mode 100644 index 00000000..2dc7a29d --- /dev/null +++ b/source/Irrlicht/CVolumeLightSceneNode.cpp @@ -0,0 +1,301 @@ +// Copyright (C) 2002-2007 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h +// +// created by Dean Wadsworth aka Varmint Dec 31 2007 + +#include "CVolumeLightSceneNode.h" +#include "IVideoDriver.h" +#include "ISceneManager.h" +#include "S3DVertex.h" +#include "os.h" + +namespace irr +{ +namespace scene +{ + +//! constructor +CVolumeLightSceneNode::CVolumeLightSceneNode(ISceneNode* parent, ISceneManager* mgr, + s32 id, const s32 subdivU, const s32 subdivV, + const video::SColor foot, + const video::SColor tail, + const core::vector3df& position, + const core::vector3df& rotation, const core::vector3df& scale) + : ISceneNode(parent, mgr, id, position, rotation, scale) +{ + #ifdef _DEBUG + setDebugName("CVolumeLightSceneNode"); + #endif + + video::IVideoDriver* driver = SceneManager->getVideoDriver(); + + lightDimensions = core::vector3df(1.0f, 1.2f, 1.0f); + + mlpDistance = 8.0f; + + mSubdivideU = subdivU; + mSubdivideV = subdivV; + + //test light + mfootColour = foot; + mtailColour = tail; + + Buffer = NULL; + + constructLight(); +} + + +//! destructor +CVolumeLightSceneNode::~CVolumeLightSceneNode() +{ + if (Buffer) + Buffer->drop(); +} + +void CVolumeLightSceneNode::addToBuffer(video::S3DVertex v) +{ + s32 tnidx = Buffer->Vertices.linear_reverse_search(v); + bool alreadyIn = (tnidx != -1); + u16 nidx = (u16)tnidx; + if (!alreadyIn) { + nidx = Buffer->Vertices.size(); + Buffer->Indices.push_back(nidx); + Buffer->Vertices.push_back(v); + } else + Buffer->Indices.push_back(nidx); + +} + +void CVolumeLightSceneNode::constructLight() +{ + core::vector3df lightPoint = core::vector3df(0, -(mlpDistance*lightDimensions.Y), 0); + f32 ax = lightDimensions.X / 2.0f; // X Axis + f32 az = lightDimensions.Z / 2.0f; // Z Axis + + if (Buffer) + Buffer->drop(); + Buffer = new SMeshBuffer(); + + //draw the bottom foot.. the glowing region + addToBuffer(video::S3DVertex(-ax, 0, az, 0,0,0, mfootColour, 0, 1)); + addToBuffer(video::S3DVertex(ax , 0, az, 0,0,0, mfootColour, 1, 1)); + addToBuffer(video::S3DVertex(ax , 0,-az, 0,0,0, mfootColour, 1, 0)); + + addToBuffer(video::S3DVertex(ax , 0,-az, 0,0,0, mfootColour, 1, 0)); + addToBuffer(video::S3DVertex(-ax, 0,-az, 0,0,0, mfootColour, 0, 0)); + addToBuffer(video::S3DVertex(-ax, 0, az, 0,0,0, mfootColour, 0, 1)); + + // Slices in X/U space + for(s32 i = 0; i <= mSubdivideU; i++) { + f32 k = ((f32)i) / mSubdivideU; // use for the texture coord + f32 bx = ((lightDimensions.X / (f32)mSubdivideU) * i) - ax; + //printf("bx: %f\n", bx); + + // These are the two endpoints for a slice at the foot + core::vector3df end1(bx, 0.0f, -az); + core::vector3df end2(bx, 0.0f, az); + + end1 -= lightPoint; // get a vector from point to lightsource + end1.normalize(); // normalize vector + end1 *= lightDimensions.Y; // multiply it out by shootlength + + end1.X += bx; // Add the original point location to the vector + end1.Z -= az; + + // Do it again for the other point. + end2 -= lightPoint; + end2.normalize(); + end2 *= lightDimensions.Y; + + end2.X += bx; + end2.Z += az; + + + addToBuffer(video::S3DVertex(bx , 0, az, 0,0,0, mfootColour, k, 1)); + addToBuffer(video::S3DVertex(bx , 0, -az, 0,0,0, mfootColour, k, 0)); + addToBuffer(video::S3DVertex(end2.X , end2.Y, end2.Z, 0,0,0, mtailColour, k, 1)); + + addToBuffer(video::S3DVertex(bx , 0, -az, 0,0,0, mfootColour, k, 0)); + addToBuffer(video::S3DVertex(end1.X , end1.Y, end1.Z, 0,0,0, mtailColour, k, 0)); + addToBuffer(video::S3DVertex(end2.X , end2.Y, end2.Z, 0,0,0, mtailColour, k, 1)); + + //back side + addToBuffer(video::S3DVertex(-end2.X , end2.Y, -end2.Z, 0,0,0, mtailColour, k, 1)); + addToBuffer(video::S3DVertex(-bx , 0, -az, 0,0,0, mfootColour, k, 1)); + addToBuffer(video::S3DVertex(-bx , 0, az, 0,0,0, mfootColour, k, 0)); + + addToBuffer(video::S3DVertex(-bx , 0, az, 0,0,0, mfootColour, k, 0)); + addToBuffer(video::S3DVertex(-end1.X , end1.Y, -end1.Z, 0,0,0, mtailColour, k, 0)); + addToBuffer(video::S3DVertex(-end2.X , end2.Y, -end2.Z, 0,0,0, mtailColour, k, 1)); + + } + + // Slices in Z/V space + for(s32 i = 0; i <= mSubdivideV; i++) { + f32 k = ((f32)i) / mSubdivideV; // use for the texture coord + f32 bz = ((lightDimensions.Z / (f32)mSubdivideV) * i) - az; + + // These are the two endpoints for a slice at the foot + core::vector3df end1(-ax, 0.0f, bz); + core::vector3df end2(ax, 0.0f, bz); + + end1 -= lightPoint; // get a vector from point to lightsource + end1.normalize(); // normalize vector + end1 *= lightDimensions.Y; // multiply it out by shootlength + + end1.X -= ax; // Add the original point location to the vector + end1.Z += bz; + + // Do it again for the other point. + end2 -= lightPoint; + end2.normalize(); + end2 *= lightDimensions.Y; + + end2.X += ax; + end2.Z += bz; + + addToBuffer(video::S3DVertex(-ax , 0, bz, 0,0,0, mfootColour, 0, k)); + addToBuffer(video::S3DVertex(ax , 0, bz, 0,0,0, mfootColour, 1, k)); + addToBuffer(video::S3DVertex(end2.X , end2.Y, end2.Z, 0,0,0, mtailColour, 1, k)); + + addToBuffer(video::S3DVertex(end2.X , end2.Y, end2.Z, 0,0,0, mtailColour, 1, k)); + addToBuffer(video::S3DVertex(end1.X , end1.Y, end1.Z, 0,0,0, mtailColour, 0, k)); + addToBuffer(video::S3DVertex(-ax , 0, bz, 0,0,0, mfootColour, 0, k)); + + //back side + addToBuffer(video::S3DVertex(ax , 0, -bz, 0,0,0, mfootColour, 0, k)); + addToBuffer(video::S3DVertex(-ax , 0, -bz, 0,0,0, mfootColour, 1, k)); + addToBuffer(video::S3DVertex(-end2.X , end2.Y, -end2.Z, 0,0,0, mtailColour, 1, k)); + + addToBuffer(video::S3DVertex(-end2.X , end2.Y, -end2.Z, 0,0,0, mtailColour, 1, k)); + addToBuffer(video::S3DVertex(-end1.X , end1.Y, -end1.Z, 0,0,0, mtailColour, 0, k)); + addToBuffer(video::S3DVertex(ax , 0, -bz, 0,0,0, mfootColour, 0, k)); + + } + + Buffer->BoundingBox.reset(0,0,0); + + Buffer->recalculateBoundingBox(); + + Buffer->Material.MaterialType = video::EMT_ONETEXTURE_BLEND; + Buffer->Material.MaterialTypeParam = pack_texureBlendFunc( video::EBF_SRC_COLOR, video::EBF_SRC_ALPHA, video::EMFN_MODULATE_1X ); + + Buffer->Material.Lighting = false; + Buffer->Material.ZWriteEnable = false; +} + +//! renders the node. +void CVolumeLightSceneNode::render() +{ + video::IVideoDriver* driver = SceneManager->getVideoDriver(); + driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); + + driver->setMaterial(Buffer->Material); + driver->drawVertexPrimitiveList( + Buffer->getVertices(), Buffer->getVertexCount(), + Buffer->getIndices(), Buffer->getIndexCount() / 3 , + Buffer->getVertexType(), EPT_TRIANGLES); +} + + +//! returns the axis aligned bounding box of this node +const core::aabbox3d& CVolumeLightSceneNode::getBoundingBox() const +{ + return Buffer->BoundingBox; +} + + +void CVolumeLightSceneNode::OnRegisterSceneNode() +{ + if (IsVisible) { + //lie to sceneManager + Buffer->Material.MaterialType = video::EMT_TRANSPARENT_ADD_COLOR; + Buffer->Material.MaterialTypeParam = 0.01f; + SceneManager->registerNodeForRendering(this, ESNRP_AUTOMATIC); + + //restore state + Buffer->Material.MaterialType = video::EMT_ONETEXTURE_BLEND; + Buffer->Material.MaterialTypeParam = pack_texureBlendFunc( video::EBF_SRC_COLOR, video::EBF_SRC_ALPHA, video::EMFN_MODULATE_1X ); + } + ISceneNode::OnRegisterSceneNode(); +} + + +//! returns the material based on the zero based index i. To get the amount +//! of materials used by this scene node, use getMaterialCount(). +//! This function is needed for inserting the node into the scene hirachy on a +//! optimal position for minimizing renderstate changes, but can also be used +//! to directly modify the material of a scene node. +video::SMaterial& CVolumeLightSceneNode::getMaterial(u32 i) +{ + return Buffer->Material; +} + + +//! returns amount of materials used by this scene node. +u32 CVolumeLightSceneNode::getMaterialCount() const +{ + return 1; +} + + +//! Writes attributes of the scene node. +void CVolumeLightSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const +{ + ISceneNode::serializeAttributes(out, options); + + out->addFloat("lpDistance", mlpDistance); + out->addInt("subDivideU", mSubdivideU); + out->addInt("subDivideV", mSubdivideV); + + out->addColor("footColour", mfootColour); + out->addColor("tailColour", mtailColour); + + out->addVector3d("lightDimension", lightDimensions); +} + + +//! Reads attributes of the scene node. +void CVolumeLightSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) +{ + mlpDistance = in->getAttributeAsFloat("lpDistance"); + mlpDistance = core::max_(mlpDistance, 8.0f); + + mSubdivideU = in->getAttributeAsInt("subDivideU"); + mSubdivideU = core::max_(mSubdivideU, 1); + + mSubdivideV = in->getAttributeAsInt("subDivideV"); + mSubdivideV = core::max_(mSubdivideV, 1); + + mfootColour = in->getAttributeAsColor("footColour"); + mtailColour = in->getAttributeAsColor("tailColour"); + + lightDimensions = in->getAttributeAsVector3d("lightDimension"); + + constructLight(); + + ISceneNode::deserializeAttributes(in, options); +} + + +//! Creates a clone of this scene node and its children. +ISceneNode* CVolumeLightSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager) +{ + if (!newParent) newParent = Parent; + if (!newManager) newManager = SceneManager; + + CVolumeLightSceneNode* nb = new CVolumeLightSceneNode(newParent, + newManager, ID, mSubdivideU, mSubdivideV, mfootColour, mtailColour, RelativeTranslation); + + nb->cloneMembers(this, newManager); + nb->Buffer->Material = Buffer->Material; + + nb->drop(); + return nb; +} + + +} // end namespace scene +} // end namespace irr diff --git a/source/Irrlicht/CVolumeLightSceneNode.h b/source/Irrlicht/CVolumeLightSceneNode.h new file mode 100644 index 00000000..e8da5d0b --- /dev/null +++ b/source/Irrlicht/CVolumeLightSceneNode.h @@ -0,0 +1,98 @@ +// Copyright (C) 2002-2007 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h +// +// created by Dean Wadsworth aka Varmint Dec 31 2007 + +#ifndef __VOLUME_LIGHT_SCENE_NODE_H_INCLUDED__ +#define __VOLUME_LIGHT_SCENE_NODE_H_INCLUDED__ + +#include "ISceneNode.h" +#include "SMeshBuffer.h" + +namespace irr +{ +namespace scene +{ + class CVolumeLightSceneNode : public ISceneNode + { + public: + + //! constructor + CVolumeLightSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, + const s32 subdivU = 32, const s32 subdivV = 32, + const video::SColor foot = video::SColor(51, 0, 230, 180), + const video::SColor tail = video::SColor(0, 0, 0, 0), + const core::vector3df& position = core::vector3df(0,0,0), + const core::vector3df& rotation = core::vector3df(0,0,0), + const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)); + + //! destructor + virtual ~CVolumeLightSceneNode(); + + virtual void OnRegisterSceneNode(); + + //! renders the node. + virtual void render(); + + //! returns the axis aligned bounding box of this node + virtual const core::aabbox3d& getBoundingBox() const; + + //! returns the material based on the zero based index i. To get the amount + //! of materials used by this scene node, use getMaterialCount(). + //! This function is needed for inserting the node into the scene hirachy on a + //! optimal position for minimizing renderstate changes, but can also be used + //! to directly modify the material of a scene node. + virtual video::SMaterial& getMaterial(u32 i); + + //! returns amount of materials used by this scene node. + virtual u32 getMaterialCount() const; + + //! Returns type of the scene node + virtual ESCENE_NODE_TYPE getType() const { return ESNT_CUBE; } + + //! Writes attributes of the scene node. + virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const; + + //! Reads attributes of the scene node. + virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0); + + //! Creates a clone of this scene node and its children. + virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0); + + void setSubDivideU (const s32 inU) { mSubdivideU = inU; } + void setSubDivideV (const s32 inV) { mSubdivideV = inV; } + + s32 getSubDivideU () const { return mSubdivideU; } + s32 getSubDivideV () const { return mSubdivideV; } + + void setFootColour(const video::SColor inColouf) { mfootColour = inColouf; } + void setTailColour(const video::SColor inColouf) { mtailColour = inColouf; } + + video::SColor getFootColour () const { return mfootColour; } + video::SColor getTailColour () const { return mtailColour; } + + private: + void addToBuffer(video::S3DVertex v); + void constructLight(); + + SMeshBuffer * Buffer; + + f32 mlpDistance; // Distance to hypothetical lightsource point -- affects fov angle + + s32 mSubdivideU; // Number of subdivisions in U and V space. + s32 mSubdivideV; // Controls the number of "slices" in the volume. + // NOTE : Total number of polygons = 2 + ((mSubdiveU + 1) + (mSubdivideV + 1)) * 2 + // Each slice being a quad plus the rectangular plane at the bottom. + + video::SColor mfootColour; // Color at the source + video::SColor mtailColour; // Color at the end. + + core::vector3df lightDimensions; // lightDimensions.Y Distance of shooting -- Length of beams + // lightDimensions.X and lightDimensions.Z determine the size/dimension of the plane + }; + +} // end namespace scene +} // end namespace irr + +#endif diff --git a/source/Irrlicht/MacOSX/MacOSX.xcodeproj/project.pbxproj b/source/Irrlicht/MacOSX/MacOSX.xcodeproj/project.pbxproj index 545b3eb0..a319dcb3 100644 --- a/source/Irrlicht/MacOSX/MacOSX.xcodeproj/project.pbxproj +++ b/source/Irrlicht/MacOSX/MacOSX.xcodeproj/project.pbxproj @@ -36,6 +36,8 @@ /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ + 090FBC820D31085E0076D847 /* CVolumeLightSceneNode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 090FBC800D31085E0076D847 /* CVolumeLightSceneNode.cpp */; }; + 090FBC830D31085E0076D847 /* CVolumeLightSceneNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 090FBC810D31085E0076D847 /* CVolumeLightSceneNode.h */; }; 0910B9DE0D1F5D4100D46B04 /* CBurningShader_Raster_Reference.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0910B9D90D1F5D4100D46B04 /* CBurningShader_Raster_Reference.cpp */; }; 0910B9DF0D1F5D4100D46B04 /* CGUITable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0910B9DA0D1F5D4100D46B04 /* CGUITable.cpp */; }; 0910B9E00D1F5D4100D46B04 /* CGUITable.h in Headers */ = {isa = PBXBuildFile; fileRef = 0910B9DB0D1F5D4100D46B04 /* CGUITable.h */; }; @@ -721,6 +723,8 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 090FBC800D31085E0076D847 /* CVolumeLightSceneNode.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CVolumeLightSceneNode.cpp; sourceTree = ""; }; + 090FBC810D31085E0076D847 /* CVolumeLightSceneNode.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CVolumeLightSceneNode.h; sourceTree = ""; }; 0910B9D90D1F5D4100D46B04 /* CBurningShader_Raster_Reference.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CBurningShader_Raster_Reference.cpp; sourceTree = ""; }; 0910B9DA0D1F5D4100D46B04 /* CGUITable.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CGUITable.cpp; sourceTree = ""; }; 0910B9DB0D1F5D4100D46B04 /* CGUITable.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CGUITable.h; sourceTree = ""; }; @@ -1155,7 +1159,7 @@ 4C53E18D0A484C2C0014E966 /* uncompr.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = uncompr.c; sourceTree = ""; }; 4C53E1920A484C2C0014E966 /* zutil.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = zutil.c; sourceTree = ""; }; 4C53E24D0A4850120014E966 /* libIrrlicht.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libIrrlicht.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 4C53E2520A4850550014E966 /* Quake3Map_dbg.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Quake3Map_dbg.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 4C53E2520A4850550014E966 /* Quake3Map.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Quake3Map.app; sourceTree = BUILT_PRODUCTS_DIR; }; 4C53E26D0A4850D60014E966 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = ""; }; 4C53E26E0A4850D60014E966 /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = /System/Library/Frameworks/OpenGL.framework; sourceTree = ""; }; 4C53E38E0A4855BA0014E966 /* DemoApp-Info.plist */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.xml; path = "DemoApp-Info.plist"; sourceTree = ""; }; @@ -1219,18 +1223,18 @@ 4C53E76F0A485CD90014E966 /* wrrle.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = wrrle.c; sourceTree = ""; }; 4C53E7700A485CD90014E966 /* wrtarga.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = wrtarga.c; sourceTree = ""; }; 4C6DC9B60A48715A0017A6E5 /* inflate.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = inflate.c; sourceTree = ""; }; - 4CA25B980A485D9800B4E469 /* CustomSceneNode_dbg.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CustomSceneNode_dbg.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 4CA25B9A0A485D9800B4E469 /* MeshViewer_dbg.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MeshViewer_dbg.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 4CA25B9C0A485D9800B4E469 /* RenderToTexture_dbg.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RenderToTexture_dbg.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 4CA25B9E0A485D9800B4E469 /* UserInterface_dbg.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = UserInterface_dbg.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 4CA25BA00A485D9800B4E469 /* PerPixelLighting_dbg.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = PerPixelLighting_dbg.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 4CA25BA20A485D9800B4E469 /* Demo_dbg.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Demo_dbg.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 4CA25BA40A485D9800B4E469 /* Movement_dbg.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Movement_dbg.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 4CA25BA60A485D9800B4E469 /* Shaders_dbg.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = Shaders_dbg.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 4CA25BA80A485D9800B4E469 /* SpecialFx_dbg.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SpecialFx_dbg.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 4CA25BAA0A485D9800B4E469 /* TerrainRendering_dbg.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TerrainRendering_dbg.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 4CA25BAC0A485D9800B4E469 /* 2DGraphics_dbg.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = 2DGraphics_dbg.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 4CA25BAE0A485D9800B4E469 /* Collision_dbg.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Collision_dbg.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 4CA25B980A485D9800B4E469 /* CustomSceneNode.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CustomSceneNode.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 4CA25B9A0A485D9800B4E469 /* MeshViewer.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MeshViewer.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 4CA25B9C0A485D9800B4E469 /* RenderToTexture.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RenderToTexture.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 4CA25B9E0A485D9800B4E469 /* UserInterface.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = UserInterface.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 4CA25BA00A485D9800B4E469 /* PerPixelLighting.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PerPixelLighting.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 4CA25BA20A485D9800B4E469 /* Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Demo.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 4CA25BA40A485D9800B4E469 /* Movement.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Movement.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 4CA25BA60A485D9800B4E469 /* Shaders.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Shaders.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 4CA25BA80A485D9800B4E469 /* SpecialFx.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SpecialFx.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 4CA25BAA0A485D9800B4E469 /* TerrainRendering.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TerrainRendering.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 4CA25BAC0A485D9800B4E469 /* 2DGraphics.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = 2DGraphics.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 4CA25BAE0A485D9800B4E469 /* Collision.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Collision.app; sourceTree = BUILT_PRODUCTS_DIR; }; 4CC36B0D0A6B61DB0076C4B2 /* CSphereSceneNode.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CSphereSceneNode.cpp; sourceTree = ""; }; 4CC36B0E0A6B61DB0076C4B2 /* CSphereSceneNode.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CSphereSceneNode.h; sourceTree = ""; }; 4CFA7BDC0A88735900B03626 /* CImageLoaderBMP.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 2; path = CImageLoaderBMP.cpp; sourceTree = ""; }; @@ -2042,6 +2046,8 @@ 4C53DFCB0A484C240014E966 /* CTerrainSceneNode.h */, 4C53DFCE0A484C240014E966 /* CTextSceneNode.cpp */, 4C53DFCF0A484C240014E966 /* CTextSceneNode.h */, + 090FBC800D31085E0076D847 /* CVolumeLightSceneNode.cpp */, + 090FBC810D31085E0076D847 /* CVolumeLightSceneNode.h */, 4C53DFF00A484C250014E966 /* CWaterSurfaceSceneNode.cpp */, 4C53DFF10A484C250014E966 /* CWaterSurfaceSceneNode.h */, ); @@ -2588,19 +2594,19 @@ isa = PBXGroup; children = ( 4C53E24D0A4850120014E966 /* libIrrlicht.a */, - 4C53E2520A4850550014E966 /* Quake3Map_dbg.app */, - 4CA25B980A485D9800B4E469 /* CustomSceneNode_dbg.app */, - 4CA25BA40A485D9800B4E469 /* Movement_dbg.app */, - 4CA25B9E0A485D9800B4E469 /* UserInterface_dbg.app */, - 4CA25BAC0A485D9800B4E469 /* 2DGraphics_dbg.app */, - 4CA25BAE0A485D9800B4E469 /* Collision_dbg.app */, - 4CA25BA80A485D9800B4E469 /* SpecialFx_dbg.app */, - 4CA25B9A0A485D9800B4E469 /* MeshViewer_dbg.app */, - 4CA25BA60A485D9800B4E469 /* Shaders_dbg.app */, - 4CA25BA00A485D9800B4E469 /* PerPixelLighting_dbg.app */, - 4CA25B9C0A485D9800B4E469 /* RenderToTexture_dbg.app */, - 4CA25BAA0A485D9800B4E469 /* TerrainRendering_dbg.app */, - 4CA25BA20A485D9800B4E469 /* Demo_dbg.app */, + 4C53E2520A4850550014E966 /* Quake3Map.app */, + 4CA25B980A485D9800B4E469 /* CustomSceneNode.app */, + 4CA25BA40A485D9800B4E469 /* Movement.app */, + 4CA25B9E0A485D9800B4E469 /* UserInterface.app */, + 4CA25BAC0A485D9800B4E469 /* 2DGraphics.app */, + 4CA25BAE0A485D9800B4E469 /* Collision.app */, + 4CA25BA80A485D9800B4E469 /* SpecialFx.app */, + 4CA25B9A0A485D9800B4E469 /* MeshViewer.app */, + 4CA25BA60A485D9800B4E469 /* Shaders.app */, + 4CA25BA00A485D9800B4E469 /* PerPixelLighting.app */, + 4CA25B9C0A485D9800B4E469 /* RenderToTexture.app */, + 4CA25BAA0A485D9800B4E469 /* TerrainRendering.app */, + 4CA25BA20A485D9800B4E469 /* Demo.app */, 09F6493E0D2CE03E001E0599 /* LoadIrrFile.app */, 09F649650D2CE206001E0599 /* Quake3Shader.app */, 09F649030D2CDED9001E0599 /* HelloWorld.app */, @@ -2753,6 +2759,7 @@ 0910BA480D1F64B300D46B04 /* SSharedMeshBuffer.h in Headers */, 0910BA490D1F64B300D46B04 /* SSkinMeshBuffer.h in Headers */, 0910BA4A0D1F64B300D46B04 /* SViewFrustum.h in Headers */, + 090FBC830D31085E0076D847 /* CVolumeLightSceneNode.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2828,7 +2835,7 @@ ); name = 2DGraphics; productName = DemoApp; - productReference = 4CA25BAC0A485D9800B4E469 /* 2DGraphics_dbg.app */; + productReference = 4CA25BAC0A485D9800B4E469 /* 2DGraphics.app */; productType = "com.apple.product-type.application"; }; B81CFE82097FDDE20057C06F /* Collision */ = { @@ -2846,7 +2853,7 @@ ); name = Collision; productName = DemoApp; - productReference = 4CA25BAE0A485D9800B4E469 /* Collision_dbg.app */; + productReference = 4CA25BAE0A485D9800B4E469 /* Collision.app */; productType = "com.apple.product-type.application"; }; B81CFEA4097FDE900057C06F /* PerPixelLightning */ = { @@ -2864,7 +2871,7 @@ ); name = PerPixelLightning; productName = DemoApp; - productReference = 4CA25BA00A485D9800B4E469 /* PerPixelLighting_dbg.app */; + productReference = 4CA25BA00A485D9800B4E469 /* PerPixelLighting.app */; productType = "com.apple.product-type.application"; }; B81CFEC2097FDF020057C06F /* TerrainRendering */ = { @@ -2882,7 +2889,7 @@ ); name = TerrainRendering; productName = DemoApp; - productReference = 4CA25BAA0A485D9800B4E469 /* TerrainRendering_dbg.app */; + productReference = 4CA25BAA0A485D9800B4E469 /* TerrainRendering.app */; productType = "com.apple.product-type.application"; }; B81CFEE8097FE05F0057C06F /* SpecialFx */ = { @@ -2900,7 +2907,7 @@ ); name = SpecialFx; productName = DemoApp; - productReference = 4CA25BA80A485D9800B4E469 /* SpecialFx_dbg.app */; + productReference = 4CA25BA80A485D9800B4E469 /* SpecialFx.app */; productType = "com.apple.product-type.application"; }; B81CFF07097FE13E0057C06F /* UserInterface */ = { @@ -2918,7 +2925,7 @@ ); name = UserInterface; productName = DemoApp; - productReference = 4CA25B9E0A485D9800B4E469 /* UserInterface_dbg.app */; + productReference = 4CA25B9E0A485D9800B4E469 /* UserInterface.app */; productType = "com.apple.product-type.application"; }; B81CFF1E097FE1E00057C06F /* CustomSceneNode */ = { @@ -2936,7 +2943,7 @@ ); name = CustomSceneNode; productName = DemoApp; - productReference = 4CA25B980A485D9800B4E469 /* CustomSceneNode_dbg.app */; + productReference = 4CA25B980A485D9800B4E469 /* CustomSceneNode.app */; productType = "com.apple.product-type.application"; }; B81CFF33097FE25F0057C06F /* Quake3Map */ = { @@ -2954,7 +2961,7 @@ ); name = Quake3Map; productName = DemoApp; - productReference = 4C53E2520A4850550014E966 /* Quake3Map_dbg.app */; + productReference = 4C53E2520A4850550014E966 /* Quake3Map.app */; productType = "com.apple.product-type.application"; }; B81CFF4A097FE3050057C06F /* Shaders */ = { @@ -2972,7 +2979,7 @@ ); name = Shaders; productName = DemoApp; - productReference = 4CA25BA60A485D9800B4E469 /* Shaders_dbg.app */; + productReference = 4CA25BA60A485D9800B4E469 /* Shaders.app */; productType = "com.apple.product-type.application"; }; B81CFF78097FE3DC0057C06F /* Movement */ = { @@ -2990,7 +2997,7 @@ ); name = Movement; productName = DemoApp; - productReference = 4CA25BA40A485D9800B4E469 /* Movement_dbg.app */; + productReference = 4CA25BA40A485D9800B4E469 /* Movement.app */; productType = "com.apple.product-type.application"; }; B81CFF91097FE45E0057C06F /* MeshViewer */ = { @@ -3008,7 +3015,7 @@ ); name = MeshViewer; productName = DemoApp; - productReference = 4CA25B9A0A485D9800B4E469 /* MeshViewer_dbg.app */; + productReference = 4CA25B9A0A485D9800B4E469 /* MeshViewer.app */; productType = "com.apple.product-type.application"; }; B81CFFAF097FE5F80057C06F /* RenderToTexture */ = { @@ -3026,7 +3033,7 @@ ); name = RenderToTexture; productName = DemoApp; - productReference = 4CA25B9C0A485D9800B4E469 /* RenderToTexture_dbg.app */; + productReference = 4CA25B9C0A485D9800B4E469 /* RenderToTexture.app */; productType = "com.apple.product-type.application"; }; B8DEF35C0950229200FDEA7E /* Demo */ = { @@ -3044,7 +3051,7 @@ ); name = Demo; productName = DemoApp; - productReference = 4CA25BA20A485D9800B4E469 /* Demo_dbg.app */; + productReference = 4CA25BA20A485D9800B4E469 /* Demo.app */; productType = "com.apple.product-type.application"; }; D2AAC07D0554694100DB518D /* libIrrlicht.a */ = { @@ -3663,6 +3670,7 @@ 0910B9DE0D1F5D4100D46B04 /* CBurningShader_Raster_Reference.cpp in Sources */, 0910B9DF0D1F5D4100D46B04 /* CGUITable.cpp in Sources */, 0910B9E10D1F5D4100D46B04 /* CImageLoaderWAL.cpp in Sources */, + 090FBC820D31085E0076D847 /* CVolumeLightSceneNode.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; };