Browse Source

Refactoring scene and events. Won't compile

Panagiotis Christopoulos Charitos 12 years ago
parent
commit
759724573a

+ 13 - 11
bench/Main.cpp

@@ -163,7 +163,7 @@ void initScene()
 
 
 	PerspectiveCamera* cam = nullptr;
 	PerspectiveCamera* cam = nullptr;
 	scene.newSceneNode(
 	scene.newSceneNode(
-		cam, "main_camera", &scene, nullptr, (U32)Movable::MF_NONE);
+		cam, "main_camera", nullptr, (U32)Movable::MF_NONE);
 
 
 	const F32 ang = 45.0;
 	const F32 ang = 45.0;
 	cam->setAll(
 	cam->setAll(
@@ -184,9 +184,9 @@ void initScene()
 	{
 	{
 		Vec3 lightPos = vaseLightPos[i];
 		Vec3 lightPos = vaseLightPos[i];
 
 
-		PointLight* point =
-			new PointLight(("vase_plight" + std::to_string(i)).c_str(),
-			&scene, nullptr, Movable::MF_NONE, 
+		PointLight* point;
+		scene.newSceneNode(point, ("vase_plight" + std::to_string(i)).c_str(),
+			nullptr, Movable::MF_NONE, 
 			(i != 100) ? "textures/lens_flare/flares0.ankitex" : nullptr);
 			(i != 100) ? "textures/lens_flare/flares0.ankitex" : nullptr);
 		point->setRadius(2.0);
 		point->setRadius(2.0);
 		point->setLocalOrigin(lightPos);
 		point->setLocalOrigin(lightPos);
@@ -210,13 +210,14 @@ void initScene()
 		auto mevent = scene.getEventManager().newMovableEvent(0.0, 2.0, moveData);
 		auto mevent = scene.getEventManager().newMovableEvent(0.0, 2.0, moveData);
 		mevent->enableBits(Event::EF_REANIMATE);
 		mevent->enableBits(Event::EF_REANIMATE);
 
 
-		ParticleEmitter* pe = new ParticleEmitter(
-			("pe" + std::to_string(i)).c_str(), &scene, nullptr,
+		ParticleEmitter* pe;
+		scene.newSceneNode(pe,
+			("pe" + std::to_string(i)).c_str(), nullptr,
 			Movable::MF_NONE, "particles/smoke.ankipart");
 			Movable::MF_NONE, "particles/smoke.ankipart");
 		pe->setLocalOrigin(lightPos);
 		pe->setLocalOrigin(lightPos);
 
 
-		pe = new ParticleEmitter(
-			("pef" + std::to_string(i)).c_str(), &scene, nullptr,
+		scene.newSceneNode(pe,
+			("pef" + std::to_string(i)).c_str(), nullptr,
 			Movable::MF_NONE, "particles/fire.ankipart");
 			Movable::MF_NONE, "particles/fire.ankipart");
 		pe->setLocalOrigin(lightPos);
 		pe->setLocalOrigin(lightPos);
 	}
 	}
@@ -224,19 +225,20 @@ void initScene()
 
 
 	scene.load("maps/sponza/master.ankiscene");
 	scene.load("maps/sponza/master.ankiscene");
 
 
-	PointLight* pl = new PointLight("pl0", &scene, nullptr, Movable::MF_NONE);
+	PointLight* pl;
+	scene.newSceneNode(pl, "pl0", nullptr, Movable::MF_NONE);
 	pl->setRadius(12.5);
 	pl->setRadius(12.5);
 	pl->setDiffuseColor(Vec4(0.5, 0.3, 0.2, 1.0));
 	pl->setDiffuseColor(Vec4(0.5, 0.3, 0.2, 1.0));
 	pl->setSpecularColor(Vec4(0.1, 0.0, 0.0, 1.0));
 	pl->setSpecularColor(Vec4(0.1, 0.0, 0.0, 1.0));
 	pl->setLocalOrigin(Vec3(10, 2.0, -0.8));
 	pl->setLocalOrigin(Vec3(10, 2.0, -0.8));
 
 
-	pl = new PointLight("pl1", &scene, nullptr, Movable::MF_NONE);
+	scene.newSceneNode(pl, "pl1", nullptr, Movable::MF_NONE);
 	pl->setRadius(12.5);
 	pl->setRadius(12.5);
 	pl->setDiffuseColor(Vec4(0.5, 0.3, 0.2, 1.0));
 	pl->setDiffuseColor(Vec4(0.5, 0.3, 0.2, 1.0));
 	pl->setSpecularColor(Vec4(0.1, 0.0, 0.0, 1.0));
 	pl->setSpecularColor(Vec4(0.1, 0.0, 0.0, 1.0));
 	pl->setLocalOrigin(Vec3(0, 2.0, -0.8));
 	pl->setLocalOrigin(Vec3(0, 2.0, -0.8));
 
 
-	pl = new PointLight("pl2", &scene, nullptr, Movable::MF_NONE);
+	scene.newSceneNode(pl, "pl2", nullptr, Movable::MF_NONE);
 	pl->setRadius(12.5);
 	pl->setRadius(12.5);
 	pl->setDiffuseColor(Vec4(0.5, 0.3, 0.2, 1.0));
 	pl->setDiffuseColor(Vec4(0.5, 0.3, 0.2, 1.0));
 	pl->setSpecularColor(Vec4(0.1, 0.0, 0.0, 1.0));
 	pl->setSpecularColor(Vec4(0.1, 0.0, 0.0, 1.0));

+ 1 - 1
include/anki/Util.h

@@ -6,7 +6,7 @@
 #include "anki/util/Assert.h"
 #include "anki/util/Assert.h"
 #include "anki/util/Barrier.h"
 #include "anki/util/Barrier.h"
 #include "anki/util/Bitset.h"
 #include "anki/util/Bitset.h"
-#include "anki/util/ConstCharPtrHashMap.h"
+#include "anki/util/Dictionary.h"
 #include "anki/util/DynamicArray.h"
 #include "anki/util/DynamicArray.h"
 #include "anki/util/Exception.h"
 #include "anki/util/Exception.h"
 #include "anki/util/File.h"
 #include "anki/util/File.h"

+ 2 - 2
include/anki/event/AnimationEvent.h

@@ -3,14 +3,14 @@
 
 
 namespace anki {
 namespace anki {
 
 
-/// @addtogroup Event
+/// @addtogroup Events
 /// @{
 /// @{
 
 
 /// Event controled by animation resource
 /// Event controled by animation resource
 class AnimationEvent: public Event
 class AnimationEvent: public Event
 {
 {
 public:
 public:
-	AnimationEvent(const AnimationResourcePointer& anim, 
+	AnimationEvent(EventManager* manager, const AnimationResourcePointer& anim, 
 		SceneNode* movableSceneNode);
 		SceneNode* movableSceneNode);
 
 
 	/// Implements Event::update
 	/// Implements Event::update

+ 45 - 7
include/anki/event/Event.h

@@ -9,8 +9,12 @@ namespace anki {
 
 
 // Forward
 // Forward
 class EventManager;
 class EventManager;
+class SceneNode;
 
 
-/// Abstract class for all events
+/// @addtogroup Events
+/// @{
+
+/// The base class for all events
 class Event: public Bitset<U8>
 class Event: public Bitset<U8>
 {
 {
 	friend class EventManager;
 	friend class EventManager;
@@ -27,8 +31,8 @@ public:
 	/// @{
 	/// @{
 
 
 	/// Constructor
 	/// Constructor
-	Event(F32 startTime, F32 duration, EventManager* manager, 
-		U8 flags = EF_NONE);
+	Event(EventManager* manager, F32 startTime, F32 duration,  
+		SceneNode* snode = nullptr, U8 flags = EF_NONE);
 
 
 	virtual ~Event();
 	virtual ~Event();
 	/// @}
 	/// @}
@@ -52,6 +56,24 @@ public:
 
 
 	SceneAllocator<U8> getSceneAllocator() const;
 	SceneAllocator<U8> getSceneAllocator() const;
 	SceneAllocator<U8> getSceneFrameAllocator() const;
 	SceneAllocator<U8> getSceneFrameAllocator() const;
+
+	EventManager& getEventManager()
+	{
+		return *manager;
+	}
+	const EventManager& getEventManager() const
+	{
+		return *manager;
+	}
+
+	SceneNode* getSceneNode()
+	{
+		return snode;
+	}
+	const SceneNode* getSceneNode() const
+	{
+		return snode;
+	}
 	/// @}
 	/// @}
 
 
 	/// This method should be implemented by the derived classes
 	/// This method should be implemented by the derived classes
@@ -70,7 +92,24 @@ public:
 		return true;
 		return true;
 	}
 	}
 
 
+	/// Mark event for deletion
+	void markForDeletion()
+	{
+		markedForDeletion = true;
+	}
+
+	/// Ask if event is marked for deletion
+	Bool isMarkedForDeletion() const
+	{
+		return markedForDeletion;
+	}
+
 protected:
 protected:
+	/// The time the event will start. Eg 23:00. If it's < 0 then start the 
+	/// event now
+	F32 startTime;
+	F32 duration; ///< The duration of the event
+
 	/// Linear interpolation between values
 	/// Linear interpolation between values
 	/// @param[in] from Starting value
 	/// @param[in] from Starting value
 	/// @param[in] to Ending value
 	/// @param[in] to Ending value
@@ -109,12 +148,11 @@ protected:
 	F32 getDelta(F32 crntTime) const;
 	F32 getDelta(F32 crntTime) const;
 
 
 private:
 private:
-	/// The time the event will start. Eg 23:00. If it's < 0 then start the 
-	/// event now
-	F32 startTime;
-	F32 duration; ///< The duration of the event
 	EventManager* manager = nullptr; ///< Keep it here to access allocators etc
 	EventManager* manager = nullptr; ///< Keep it here to access allocators etc
+	SceneNode* node = nullptr; ///< Optional scene node
+	Bool8 markedForDeletion = false;
 };
 };
+/// @}
 
 
 } // end namespace anki
 } // end namespace anki
 
 

+ 35 - 19
include/anki/event/EventManager.h

@@ -21,11 +21,14 @@ class MovableEvent;
 class MovableEventData;
 class MovableEventData;
 class FollowPathEvent;
 class FollowPathEvent;
 
 
+/// @addtogroup Events
+/// @{
+
 /// This manager creates the events ands keeps tracks of them
 /// This manager creates the events ands keeps tracks of them
 class EventManager
 class EventManager
 {
 {
 public:
 public:
-	typedef SceneVector<std::shared_ptr<Event>> EventsContainer;
+	typedef SceneVector<Event> EventsContainer;
 
 
 	EventManager(SceneGraph* scene);
 	EventManager(SceneGraph* scene);
 	~EventManager();
 	~EventManager();
@@ -34,39 +37,52 @@ public:
 	/// @{
 	/// @{
 	SceneAllocator<U8> getSceneAllocator() const;
 	SceneAllocator<U8> getSceneAllocator() const;
 	SceneAllocator<U8> getSceneFrameAllocator() const;
 	SceneAllocator<U8> getSceneFrameAllocator() const;
-	/// @}
-
-	/// @name Creators
-	/// @{
 
 
-	std::shared_ptr<Event> newSceneAmbientColorEvent(
-		F32 startTime, F32 duration, const Vec4& finalColor);
+	SceneGraph& getScene()
+	{
+		return *scene;
+	}
+	const SceneGraph& getScene() const
+	{
+		return *scene;
+	}
+	/// @}
 
 
-	std::shared_ptr<Event> newLightEvent(
-		F32 startTime, F32 duration, const LightEventData& data);
+	/// Create a new event
+	template<typename T, typename... Args>
+	void newEvent(T*& event, Args&&.. args)
+	{
+		SceneAllocator<T> al = getSceneAllocator();
+		event = al.allocate(1);
+		al.construct(event, this, std::forward<Args>(args)...);
 
 
-	std::shared_ptr<Event> newMovableEvent(
-		F32 startTime, F32 duration, const MovableEventData& data);
+		registerEvent(event);
+	}
 
 
-	std::shared_ptr<Event> newFollowPathEvent(
-		F32 startTime, F32 duration,
-		SceneNode* movableSceneNode, Path* path, F32 distPerTime);
-	/// @}
+	/// Delete an event. It actualy marks it for deletion
+	void deleteEvent(Event* event)
+	{
+		event->markForDeletion();
+		++eventsMarkedForDeletionCount;
+	}
 
 
 	/// Update
 	/// Update
 	void updateAllEvents(F32 prevUpdateTime, F32 crntTime);
 	void updateAllEvents(F32 prevUpdateTime, F32 crntTime);
 
 
-	/// Remove an event from the container
-	void unregisterEvent(Event* event);
-
 private:
 private:
 	SceneGraph* scene = nullptr;
 	SceneGraph* scene = nullptr;
 	EventsContainer events;
 	EventsContainer events;
 	F32 prevUpdateTime;
 	F32 prevUpdateTime;
 	F32 crntTime;
 	F32 crntTime;
+	U32 eventsMarkedForDeletionCount = 0;
 
 
-	std::shared_ptr<Event> registerEvent(Event* event);
+	/// Add an event to the local container
+	void registerEvent(Event* event);
+
+	/// Remove an event from the container
+	void unregisterEvent(Event* event);
 };
 };
+/// @}
 
 
 } // end namespace anki
 } // end namespace anki
 
 

+ 1 - 1
include/anki/event/FollowPathEvent.h

@@ -14,7 +14,7 @@ public:
 
 
 	/// Constructor
 	/// Constructor
 	FollowPathEvent(
 	FollowPathEvent(
-		F32 startTime, F32 duration, EventManager* manager, U8 flags, // Event
+		EventManager* manager, F32 startTime, F32 duration, U8 flags, // Event
 		SceneNode* movableSceneNode, Path* path, F32 distPerTime);
 		SceneNode* movableSceneNode, Path* path, F32 distPerTime);
 	/// @}
 	/// @}
 
 

+ 7 - 3
include/anki/event/LightEvent.h

@@ -9,10 +9,12 @@ namespace anki {
 // Forward
 // Forward
 class Light;
 class Light;
 
 
+/// @addtogroup Events
+/// @{
+
 /// Helper class
 /// Helper class
 struct LightEventData
 struct LightEventData
 {
 {
-	Light* light = nullptr;
 	F32 radiusMultiplier = 0.0;
 	F32 radiusMultiplier = 0.0;
 	Vec4 intensityMultiplier = Vec4(0.0);
 	Vec4 intensityMultiplier = Vec4(0.0);
 	Vec4 specularIntensityMultiplier = Vec4(0.0);
 	Vec4 specularIntensityMultiplier = Vec4(0.0);
@@ -26,18 +28,20 @@ public:
 	/// @{
 	/// @{
 
 
 	/// Constructor
 	/// Constructor
-	LightEvent(F32 startTime, F32 duration, EventManager* manager,
-		U8 flags, const LightEventData& data);
+	LightEvent(EventManager* manager, F32 startTime, F32 duration,
+		U8 flags, Light* light, const LightEventData& data);
 	/// @}
 	/// @}
 
 
 	/// Implements Event::update
 	/// Implements Event::update
 	void update(F32 prevUpdateTime, F32 crntTime);
 	void update(F32 prevUpdateTime, F32 crntTime);
 
 
 private:
 private:
+	Light* light;
 	F32 originalRadius;
 	F32 originalRadius;
 	Vec4 originalDiffColor;
 	Vec4 originalDiffColor;
 	Vec4 originalSpecColor;
 	Vec4 originalSpecColor;
 };
 };
+/// @}
 
 
 } // end namespace anki
 } // end namespace anki
 
 

+ 6 - 3
include/anki/event/MovableEvent.h

@@ -9,10 +9,12 @@ namespace anki {
 // Forward
 // Forward
 class SceneNode;
 class SceneNode;
 
 
+/// @addtogroup Events
+/// @{
+
 /// Helper class
 /// Helper class
 struct MovableEventData
 struct MovableEventData
 {
 {
-	SceneNode* movableSceneNode = nullptr;
 	Vec3 posMin;
 	Vec3 posMin;
 	Vec3 posMax;
 	Vec3 posMax;
 };
 };
@@ -25,8 +27,8 @@ public:
 	/// @{
 	/// @{
 
 
 	/// Constructor
 	/// Constructor
-	MovableEvent(F32 startTime, F32 duration, EventManager* manager,
-		U8 flags, const MovableEventData& data);
+	MovableEvent(EventManager* manager, F32 startTime, F32 duration,
+		U8 flags, SceneNode* movableSceneNode, const MovableEventData& data);
 	/// @}
 	/// @}
 
 
 	/// Implements Event::update
 	/// Implements Event::update
@@ -36,6 +38,7 @@ private:
 	Vec3 originalPos;
 	Vec3 originalPos;
 	Vec3 newPos;
 	Vec3 newPos;
 };
 };
+/// @}
 
 
 } // end namespace anki
 } // end namespace anki
 
 

+ 5 - 5
include/anki/event/SceneAmbientColorEvent.h

@@ -6,16 +6,16 @@
 
 
 namespace anki {
 namespace anki {
 
 
-// Forward
-class SceneGraph;
+/// @addtogroup Events
+/// @{
 
 
 /// Change the scene color
 /// Change the scene color
 class SceneAmbientColorEvent: public Event
 class SceneAmbientColorEvent: public Event
 {
 {
 public:
 public:
 	/// Constructor
 	/// Constructor
-	SceneAmbientColorEvent(F32 startTime, F32 duration, EventManager* manager,
-		const Vec4& finalColor, SceneGraph* scene);
+	SceneAmbientColorEvent(EventManager* manager, F32 startTime, F32 duration,
+		const Vec4& finalColor);
 
 
 	/// Implements Event::update
 	/// Implements Event::update
 	void update(F32 prevUpdateTime, F32 crntTime);
 	void update(F32 prevUpdateTime, F32 crntTime);
@@ -23,8 +23,8 @@ public:
 private:
 private:
 	Vec4 originalColor; ///< Original scene color. The constructor sets it
 	Vec4 originalColor; ///< Original scene color. The constructor sets it
 	Vec4 finalColor;
 	Vec4 finalColor;
-	SceneGraph* scene = nullptr;
 };
 };
+/// @}
 
 
 } // end namespace anki
 } // end namespace anki
 
 

+ 4 - 4
include/anki/gl/ShaderProgram.h

@@ -2,7 +2,7 @@
 #define ANKI_GL_SHADER_PROGRAM_H
 #define ANKI_GL_SHADER_PROGRAM_H
 
 
 #include "anki/gl/GlObject.h"
 #include "anki/gl/GlObject.h"
-#include "anki/util/ConstCharPtrHashMap.h"
+#include "anki/util/Dictionary.h"
 #include "anki/Math.h"
 #include "anki/Math.h"
 #include "anki/util/Vector.h"
 #include "anki/util/Vector.h"
 #include <string>
 #include <string>
@@ -397,13 +397,13 @@ public:
 		const ShaderProgram& x);
 		const ShaderProgram& x);
 
 
 private:
 private:
-	typedef ConstCharPtrHashMap<ShaderProgramUniformVariable*>::Type
+	typedef Dictionary<ShaderProgramUniformVariable*>
 		NameToUniVarHashMap;
 		NameToUniVarHashMap;
 
 
-	typedef ConstCharPtrHashMap<ShaderProgramAttributeVariable*>::Type
+	typedef Dictionary<ShaderProgramAttributeVariable*>
 		NameToAttribVarHashMap;
 		NameToAttribVarHashMap;
 
 
-	typedef ConstCharPtrHashMap<ShaderProgramUniformBlock*>::Type
+	typedef Dictionary<ShaderProgramUniformBlock*>
 		NameToUniformBlockHashMap;
 		NameToUniformBlockHashMap;
 
 
 	static thread_local const ShaderProgram* current;
 	static thread_local const ShaderProgram* current;

+ 2 - 3
include/anki/resource/Material.h

@@ -3,7 +3,7 @@
 
 
 #include "anki/resource/MaterialCommon.h"
 #include "anki/resource/MaterialCommon.h"
 #include "anki/resource/Resource.h"
 #include "anki/resource/Resource.h"
-#include "anki/util/ConstCharPtrHashMap.h"
+#include "anki/util/Dictionary.h"
 #include "anki/util/StringList.h"
 #include "anki/util/StringList.h"
 #include "anki/Math.h"
 #include "anki/Math.h"
 #include "anki/util/Visitor.h"
 #include "anki/util/Visitor.h"
@@ -365,8 +365,7 @@ public:
 	}
 	}
 
 
 private:
 private:
-	typedef ConstCharPtrHashMap<MaterialVariable*>::Type
-		NameToVariableHashMap;
+	typedef Dictionary<MaterialVariable*> NameToVariableHashMap;
 
 
 	std::string fname; ///< filename
 	std::string fname; ///< filename
 
 

+ 12 - 1
include/anki/scene/Common.h

@@ -4,6 +4,8 @@
 #include "anki/util/Allocator.h"
 #include "anki/util/Allocator.h"
 #include "anki/util/Vector.h"
 #include "anki/util/Vector.h"
 #include "anki/util/StdTypes.h"
 #include "anki/util/StdTypes.h"
+#include "anki/util/Dictionary.h"
+#include <memory>
 
 
 namespace anki {
 namespace anki {
 
 
@@ -30,6 +32,11 @@ using SceneVector = Vector<T, SceneAllocator<T>>;
 template<typename T>
 template<typename T>
 using SceneFrameVector = Vector<T, SceneFrameAllocator<T>>;
 using SceneFrameVector = Vector<T, SceneFrameAllocator<T>>;
 
 
+/// Scene dictionary
+template<typename T>
+using SceneDictionary = 
+	Dictionary<T, SceneAllocator<std::pair<const char*, T>>>;
+
 /// Deleter for shared pointers
 /// Deleter for shared pointers
 template<typename T>
 template<typename T>
 struct SceneSharedPtrDeleter
 struct SceneSharedPtrDeleter
@@ -38,10 +45,14 @@ struct SceneSharedPtrDeleter
 	{
 	{
 		ANKI_ASSERT(x);
 		ANKI_ASSERT(x);
 		SceneAllocator<U8> alloc = x->getSceneAllocator();
 		SceneAllocator<U8> alloc = x->getSceneAllocator();
-		//ANKI_DELETE(x, alloc);
+		deleteObject(alloc, x);
 	}
 	}
 };
 };
 
 
+/// Shared pointer in scene
+template<typename T>
+using SceneSharedPointer = std::shared_ptr<T>;
+
 /// @}
 /// @}
 
 
 } // end namespace anki
 } // end namespace anki

+ 2 - 2
include/anki/scene/Property.h

@@ -10,7 +10,7 @@
 #include "anki/resource/Resource.h"
 #include "anki/resource/Resource.h"
 #include "anki/resource/TextureResource.h"
 #include "anki/resource/TextureResource.h"
 #include "anki/Collision.h"
 #include "anki/Collision.h"
-#include "anki/util/ConstCharPtrHashMap.h"
+#include "anki/util/Dictionary.h"
 
 
 namespace anki {
 namespace anki {
 
 
@@ -316,7 +316,7 @@ class PropertyMap
 {
 {
 public:
 public:
 	typedef Vector<PropertyBase*> Container;
 	typedef Vector<PropertyBase*> Container;
-	typedef ConstCharPtrHashMap<PropertyBase*>::Type NameToPropertyMap;
+	typedef Dictionary<PropertyBase*> NameToPropertyMap;
 
 
 	/// Add new property to the map. The map gets the ownership of this
 	/// Add new property to the map. The map gets the ownership of this
 	/// property
 	/// property

+ 18 - 65
include/anki/scene/SceneGraph.h

@@ -28,16 +28,6 @@ class SceneGraph
 	friend class SceneNode;
 	friend class SceneNode;
 
 
 public:
 public:
-	template<typename T>
-	struct Types
-	{
-		typedef SceneVector<T*> Container;
-		typedef typename Container::iterator Iterator;
-		typedef typename Container::const_iterator ConstIterator;
-		// XXX Change the map with map with allocator
-		typedef typename ConstCharPtrHashMap<T*>::Type NameToItemMap;
-	};
-
 	/// @name Constructors/Destructor
 	/// @name Constructors/Destructor
 	/// @{
 	/// @{
 	SceneGraph();
 	SceneGraph();
@@ -142,7 +132,7 @@ public:
 		}
 		}
 	}
 	}
 
 
-	/// Iterate the scene nodes using a lambda
+	/// Iterate a range of scene nodes using a lambda
 	template<typename Func>
 	template<typename Func>
 	void iterateSceneNodes(PtrSize begin, PtrSize count, Func func)
 	void iterateSceneNodes(PtrSize begin, PtrSize count, Func func)
 	{
 	{
@@ -155,19 +145,28 @@ public:
 
 
 	/// Create a new SceneNode
 	/// Create a new SceneNode
 	template<typename Node, typename... Args>
 	template<typename Node, typename... Args>
-	void newSceneNode(Node*& node, Args&&... args)
+	void newSceneNode(Node*& node, const char* name, Args&&... args)
 	{
 	{
 		SceneAllocator<Node> al = alloc;
 		SceneAllocator<Node> al = alloc;
 		node = al.allocate(1);
 		node = al.allocate(1);
-		al.construct(node, std::forward<Args>(args)...);
+		al.construct(node, name, this, std::forward<Args>(args)...);
+
+		registerNode(node);
+	}
+
+	/// Delete a scene node. It actualy marks it for deletion
+	void deleteSceneNode(SceneNode* node)
+	{
+		node->markForDeletion();
+		++nodesMarkedForDeletionCount;
 	}
 	}
 
 
 private:
 private:
 	SceneAllocator<U8> alloc;
 	SceneAllocator<U8> alloc;
 	SceneAllocator<U8> frameAlloc;
 	SceneAllocator<U8> frameAlloc;
 
 
-	Types<SceneNode>::Container nodes;
-	Types<SceneNode>::NameToItemMap nameToNode;
+	SceneVector<SceneNode*> nodes;
+	SceneDictionary<SceneNode*> dict;
 
 
 	Vec3 ambientCol = Vec3(1.0); ///< The global ambient color
 	Vec3 ambientCol = Vec3(1.0); ///< The global ambient color
 	Timestamp ambiendColorUpdateTimestamp = getGlobTimestamp();
 	Timestamp ambiendColorUpdateTimestamp = getGlobTimestamp();
@@ -180,60 +179,14 @@ private:
 
 
 	EventManager events;
 	EventManager events;
 
 
+	U32 nodesMarkedForDeletionCount = 0;
+
 	/// Put a node in the appropriate containers
 	/// Put a node in the appropriate containers
 	void registerNode(SceneNode* node);
 	void registerNode(SceneNode* node);
 	void unregisterNode(SceneNode* node);
 	void unregisterNode(SceneNode* node);
 
 
-	/// Add to a container
-	template<typename T>
-	void addC(typename Types<T>::Container& c, T* ptr)
-	{
-		ANKI_ASSERT(std::find(c.begin(), c.end(), ptr) == c.end());
-		c.push_back(ptr);
-	}
-
-	/// Add to a dictionary
-	template<typename T>
-	void addDict(typename Types<T>::NameToItemMap& d, T* ptr)
-	{
-		ANKI_ASSERT(ptr && ptr->getName());
-
-		if(d.find(ptr->getName()) != d.end())
-		{
-			throw ANKI_EXCEPTION("Node with the same name already exists: "
-				+ ptr->getName());
-		}
-
-		d[ptr->getName()] = ptr;
-	}
-
-	/// Remove from a container
-	template<typename T>
-	void removeC(typename Types<T>::Container& c, T* ptr)
-	{
-		typename Types<T>::Iterator it = c.begin();
-		for(; it != c.end(); ++it)
-		{
-			if(*it == ptr)
-			{
-				break;
-			}
-		}
-
-		ANKI_ASSERT(it != c.end());
-		c.erase(it);
-	}
-
-	/// Remove from a dictionary
-	template<typename T>
-	void removeDict(typename Types<T>::NameToItemMap& d, T* ptr)
-	{
-		typename Types<T>::NameToItemMap::iterator it =
-			d.find(ptr->getName());
-
-		ANKI_ASSERT(it != d.end());
-		d.erase(it);
-	}
+	/// Delete the nodes that are marked for deletion
+	void deleteNodesMarkedForDeletion();
 };
 };
 
 
 typedef Singleton<SceneGraph> SceneGraphSingleton;
 typedef Singleton<SceneGraph> SceneGraphSingleton;

+ 11 - 0
include/anki/scene/SceneNode.h

@@ -146,6 +146,16 @@ public:
 	/// Return the last frame the node was updated. It checks all components
 	/// Return the last frame the node was updated. It checks all components
 	U32 getLastUpdateFrame() const;
 	U32 getLastUpdateFrame() const;
 
 
+	/// Mark a node for deletion
+	void markForDeletion()
+	{
+		markedForDeletion = true;
+	}
+	Bool isMarkedForDeletion()
+	{
+		return markedForDeletion;
+	}
+
 protected:
 protected:
 	struct
 	struct
 	{
 	{
@@ -161,6 +171,7 @@ protected:
 private:
 private:
 	SceneGraph* scene = nullptr;
 	SceneGraph* scene = nullptr;
 	SceneString name; ///< A unique name
 	SceneString name; ///< A unique name
+	Bool8 markedForDeletion;
 };
 };
 /// @}
 /// @}
 
 

+ 11 - 14
include/anki/util/ConstCharPtrHashMap.h → include/anki/util/Dictionary.h

@@ -1,5 +1,5 @@
-#ifndef ANKI_UTIL_CONST_CHAR_PTR_HASH_MAP_H
-#define ANKI_UTIL_CONST_CHAR_PTR_HASH_MAP_H
+#ifndef ANKI_UTIL_DICTIONARY_H
+#define ANKI_UTIL_DICTIONARY_H
 
 
 #include "anki/util/Allocator.h"
 #include "anki/util/Allocator.h"
 #include <unordered_map>
 #include <unordered_map>
@@ -13,7 +13,7 @@ namespace anki {
 /// @{
 /// @{
 
 
 /// The hash function
 /// The hash function
-struct CreateCharPtrHashMapKey
+struct DictionaryHasher
 {
 {
 	size_t operator()(const char* str) const
 	size_t operator()(const char* str) const
 	{
 	{
@@ -27,7 +27,7 @@ struct CreateCharPtrHashMapKey
 };
 };
 
 
 /// The collision evaluation function
 /// The collision evaluation function
-struct CompareCharPtrHashMapKeys
+struct DictionaryEqual
 {
 {
 	bool operator()(const char* a, const char* b) const
 	bool operator()(const char* a, const char* b) const
 	{
 	{
@@ -38,18 +38,15 @@ struct CompareCharPtrHashMapKeys
 /// The hash map that has as key an old school C string. When inserting the
 /// The hash map that has as key an old school C string. When inserting the
 /// char MUST NOT point to a temporary or the evaluation function will fail.
 /// char MUST NOT point to a temporary or the evaluation function will fail.
 /// Its template struct because C++ does not offer template typedefs
 /// Its template struct because C++ does not offer template typedefs
-template<
-	typename T,
-	typename Alloc = Allocator<std::pair<const char*, T>>>
-struct ConstCharPtrHashMap
-{
-	typedef std::unordered_map<
+template<typename T, typename Alloc = Allocator<std::pair<const char*, T>>>
+using Dictionary = 
+	std::unordered_map<
 		const char*,
 		const char*,
 		T,
 		T,
-		CreateCharPtrHashMapKey,
-		CompareCharPtrHashMapKeys,
-		Alloc> Type;
-};
+		DictionaryHasher,
+		DictionaryEqual,
+		Alloc>;
+
 /// @}
 /// @}
 /// @}
 /// @}
 
 

+ 4 - 2
src/event/Event.cpp

@@ -5,11 +5,13 @@
 namespace anki {
 namespace anki {
 
 
 //==============================================================================
 //==============================================================================
-Event::Event(F32 startTime_, F32 duration_, EventManager* manager_, U8 flags)
+Event::Event(EventManager* manager_, F32 startTime_, F32 duration_, 
+	SceneNode* snode_, U8 flags)
 	:	Bitset<U8>(flags), 
 	:	Bitset<U8>(flags), 
 		startTime(startTime_),
 		startTime(startTime_),
 		duration(duration_),
 		duration(duration_),
-		manager(manager_)
+		manager(manager_),
+		snode(snode_)
 {
 {
 	ANKI_ASSERT(manager);
 	ANKI_ASSERT(manager);
 }
 }

+ 6 - 41
src/event/EventManager.cpp

@@ -30,13 +30,11 @@ SceneAllocator<U8> EventManager::getSceneFrameAllocator() const
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-std::shared_ptr<Event> EventManager::registerEvent(Event* event)
+void EventManager::registerEvent(Event* event)
 {
 {
 	ANKI_ASSERT(event);
 	ANKI_ASSERT(event);
-	SceneSharedPtrDeleter<Event> deleter;
-	std::shared_ptr<Event> ptr(event, deleter, getSceneAllocator());
-	events.push_back(ptr);
-	return ptr;
+	ANKI_ASSERT(std::find(events.begin(), events.end(), event) == events.end());
+	events.push_back(event);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
@@ -64,14 +62,14 @@ void EventManager::updateAllEvents(F32 prevUpdateTime_, F32 crntTime_)
 	crntTime = crntTime_;
 	crntTime = crntTime_;
 
 
 	// Container to gather dead events
 	// Container to gather dead events
-	SceneFrameVector<EventsContainer::iterator> forDeletion(
-		getSceneFrameAllocator());
+	SceneFrameVector<EventsContainer::iterator> 
+		forDeletion(getSceneFrameAllocator());
 	// XXX reserve on vector
 	// XXX reserve on vector
 
 
 	EventsContainer::iterator it = events.begin();
 	EventsContainer::iterator it = events.begin();
 	for(; it != events.end(); it++)
 	for(; it != events.end(); it++)
 	{
 	{
-		std::shared_ptr<Event>& pevent = *it;
+		Event* pevent = *it;
 
 
 		// Audjust starting time
 		// Audjust starting time
 		if(pevent->startTime < 0.0)
 		if(pevent->startTime < 0.0)
@@ -111,37 +109,4 @@ void EventManager::updateAllEvents(F32 prevUpdateTime_, F32 crntTime_)
 	}
 	}
 }
 }
 
 
-//==============================================================================
-std::shared_ptr<Event> EventManager::newSceneAmbientColorEvent(
-	F32 startTime, F32 duration, const Vec4& finalColor)
-{
-	return registerEvent(new SceneAmbientColorEvent(startTime, duration, this, 
-		finalColor, scene));
-}
-
-//==============================================================================
-std::shared_ptr<Event> EventManager::newLightEvent(
-	F32 startTime, F32 duration, const LightEventData& data)
-{
-	return registerEvent(new LightEvent(startTime, duration, this,
-		Event::EF_NONE, data));
-}
-
-//==============================================================================
-std::shared_ptr<Event> EventManager::newMovableEvent(
-	F32 startTime, F32 duration, const MovableEventData& data)
-{
-	return registerEvent(new MovableEvent(startTime, duration, this,
-		Event::EF_NONE, data));
-}
-
-//==============================================================================
-std::shared_ptr<Event> EventManager::newFollowPathEvent(
-	F32 startTime, F32 duration,
-	SceneNode* movableSceneNode, Path* path, F32 distPerTime)
-{
-	return registerEvent(new FollowPathEvent(startTime, duration, this,
-		Event::EF_NONE, movableSceneNode, path, distPerTime));
-}
-
 } // end namespace anki
 } // end namespace anki

+ 1 - 1
src/event/FollowPathEvent.cpp

@@ -7,7 +7,7 @@ namespace anki {
 FollowPathEvent::FollowPathEvent(
 FollowPathEvent::FollowPathEvent(
 	F32 startTime, F32 duration, EventManager* manager, U8 flags,
 	F32 startTime, F32 duration, EventManager* manager, U8 flags,
 	SceneNode* movableSceneNode_, Path* path_, F32 distPerTime_)
 	SceneNode* movableSceneNode_, Path* path_, F32 distPerTime_)
-	:	Event(startTime, duration, manager, flags),
+	:	Event(manager, startTime, duration, nullptr, flags),
 		distPerTime(distPerTime_),
 		distPerTime(distPerTime_),
 		movableSceneNode(movableSceneNode_),
 		movableSceneNode(movableSceneNode_),
 		path(path_)
 		path(path_)

+ 3 - 3
src/event/LightEvent.cpp

@@ -4,9 +4,9 @@
 namespace anki {
 namespace anki {
 
 
 //==============================================================================
 //==============================================================================
-LightEvent::LightEvent(F32 startTime, F32 duration, EventManager* manager,
-	U8 flags, const LightEventData& data)
-	: Event(startTime, duration, manager, flags)
+LightEvent::LightEvent(EventManager* manager, F32 startTime, F32 duration,
+	U8 flags, Light* light, const LightEventData& data)
+	: Event(manager, startTime, duration, light, flags)
 {
 {
 	*static_cast<LightEventData*>(this) = data;
 	*static_cast<LightEventData*>(this) = data;
 
 

+ 6 - 3
src/event/MovableEvent.cpp

@@ -6,9 +6,9 @@
 namespace anki {
 namespace anki {
 
 
 //==============================================================================
 //==============================================================================
-MovableEvent::MovableEvent(F32 startTime, F32 duration, EventManager* manager,
-	U8 flags, const MovableEventData& data)
-	: Event(startTime, duration, manager, flags)
+MovableEvent::MovableEvent(EventManager* manager, F32 startTime, F32 duration,
+	U8 flags, SceneNode* movableSceneNode, const MovableEventData& data)
+	: Event(manager, startTime, duration, movableSceneNode, flags)
 {
 {
 	ANKI_ASSERT(data.movableSceneNode->getMovable());
 	ANKI_ASSERT(data.movableSceneNode->getMovable());
 
 
@@ -27,6 +27,9 @@ MovableEvent::MovableEvent(F32 startTime, F32 duration, EventManager* manager,
 //==============================================================================
 //==============================================================================
 void MovableEvent::update(F32 prevUpdateTime, F32 crntTime)
 void MovableEvent::update(F32 prevUpdateTime, F32 crntTime)
 {
 {
+	SceneNode* movableSceneNode = getSceneNode();
+	ANKI_ASSERT(movableSceneNode);
+
 	Transform trf = movableSceneNode->getMovable()->getLocalTransform();
 	Transform trf = movableSceneNode->getMovable()->getLocalTransform();
 
 
 	F32 factor = sin(getDelta(crntTime) * getPi<F32>());
 	F32 factor = sin(getDelta(crntTime) * getPi<F32>());

+ 5 - 6
src/event/SceneAmbientColorEvent.cpp

@@ -5,11 +5,10 @@
 namespace anki {
 namespace anki {
 
 
 //==============================================================================
 //==============================================================================
-SceneAmbientColorEvent::SceneAmbientColorEvent(F32 startTime, F32 duration, 
-	EventManager* manager, const Vec4& finalColor_, SceneGraph* scene_)
-	:	Event(startTime, duration, manager), 
-		finalColor(finalColor_), 
-		scene(scene_)
+SceneAmbientColorEvent::SceneAmbientColorEvent(EventManager* manager,
+	F32 startTime, F32 duration, const Vec4& finalColor_)
+	:	Event(manager, startTime, duration), 
+		finalColor(finalColor_)
 {
 {
 	ANKI_ASSERT(scene);
 	ANKI_ASSERT(scene);
 	originalColor = scene->getAmbientColor();
 	originalColor = scene->getAmbientColor();
@@ -18,7 +17,7 @@ SceneAmbientColorEvent::SceneAmbientColorEvent(F32 startTime, F32 duration,
 //==============================================================================
 //==============================================================================
 void SceneAmbientColorEvent::update(F32 /*prevUpdateTime*/, F32 crntTime)
 void SceneAmbientColorEvent::update(F32 /*prevUpdateTime*/, F32 crntTime)
 {
 {
-	scene->setAmbientColor(
+	getEventManager().getScene().setAmbientColor(
 		interpolate(originalColor, finalColor, getDelta(crntTime)));
 		interpolate(originalColor, finalColor, getDelta(crntTime)));
 }
 }
 
 

+ 8 - 8
src/scene/ModelNode.cpp

@@ -1,4 +1,5 @@
 #include "anki/scene/ModelNode.h"
 #include "anki/scene/ModelNode.h"
+#include "anki/scene/SceneGraph.h"
 #include "anki/resource/Model.h"
 #include "anki/resource/Model.h"
 #include "anki/resource/Skeleton.h"
 #include "anki/resource/Skeleton.h"
 
 
@@ -90,10 +91,9 @@ ModelPatchNode::ModelPatchNode(
 
 
 		for(U i = 0; i < instancesCount; i++)
 		for(U i = 0; i < instancesCount; i++)
 		{
 		{
-			ModelPatchNodeInstance* instance = ANKI_NEW(
-				ModelPatchNodeInstance, getSceneAllocator(), 
-				nullptr, scene, this, Movable::MF_IGNORE_PARENT,
-				modelPatch);
+			ModelPatchNodeInstance* instance;
+			getSceneGraph().newSceneNode(instance, nullptr, this, 
+				Movable::MF_IGNORE_PARENT, modelPatch);
 
 
 			instance->setLocalOrigin(pos);
 			instance->setLocalOrigin(pos);
 			pos.x() += 2.0;
 			pos.x() += 2.0;
@@ -109,7 +109,7 @@ ModelPatchNode::~ModelPatchNode()
 {
 {
 	for(ModelPatchNodeInstance* instance : instances)
 	for(ModelPatchNodeInstance* instance : instances)
 	{
 	{
-		ANKI_DELETE(instance, getSceneAllocator());
+		getSceneGraph().deleteSceneNode(instance);
 	}
 	}
 }
 }
 
 
@@ -200,8 +200,8 @@ ModelNode::ModelNode(
 	U i = 0;
 	U i = 0;
 	for(const ModelPatchBase* patch : model->getModelPatches())
 	for(const ModelPatchBase* patch : model->getModelPatches())
 	{
 	{
-		ModelPatchNode* mpn = ANKI_NEW(ModelPatchNode, getSceneAllocator(),
-			nullptr, scene, this,
+		ModelPatchNode* mpn;
+		getSceneGraph().newSceneNode(mpn, nullptr, this,
 			Movable::MF_IGNORE_LOCAL_TRANSFORM, patch, instances);
 			Movable::MF_IGNORE_LOCAL_TRANSFORM, patch, instances);
 
 
 		patches.push_back(mpn);
 		patches.push_back(mpn);
@@ -214,7 +214,7 @@ ModelNode::~ModelNode()
 {
 {
 	for(ModelPatchNode* patch : patches)
 	for(ModelPatchNode* patch : patches)
 	{
 	{
-		ANKI_DELETE(patch, getSceneAllocator());
+		getSceneGraph().deleteSceneNode(patch);
 	}
 	}
 }
 }
 
 

+ 8 - 5
src/scene/ParticleEmitter.cpp

@@ -268,7 +268,7 @@ ParticleEmitter::~ParticleEmitter()
 {
 {
 	for(ParticleBase* part : particles)
 	for(ParticleBase* part : particles)
 	{
 	{
-		ANKI_DELETE(part, getSceneAllocator());
+		getSceneGraph().deleteSceneNode(part);
 	}
 	}
 
 
 	ANKI_DELETE(collShape, getSceneAllocator());
 	ANKI_DELETE(collShape, getSceneAllocator());
@@ -310,8 +310,9 @@ void ParticleEmitter::createParticlesSimulation(SceneGraph* scene)
 	{
 	{
 		binit.mass = getRandom(particle.mass, particle.massDeviation);
 		binit.mass = getRandom(particle.mass, particle.massDeviation);
 
 
-		Particle* part = ANKI_NEW(Particle, getSceneAllocator(),
-			(getName() + std::to_string(i)).c_str(), scene, nullptr,
+		Particle* part;
+		getSceneGraph().newSceneNode(part,
+			(getName() + std::to_string(i)).c_str(), nullptr,
 			Movable::MF_NONE,
 			Movable::MF_NONE,
 			&scene->getPhysics(), binit);
 			&scene->getPhysics(), binit);
 
 
@@ -328,8 +329,10 @@ void ParticleEmitter::createParticlesSimpleSimulation(SceneGraph* scene)
 {
 {
 	for(U i = 0; i < maxNumOfParticles; i++)
 	for(U i = 0; i < maxNumOfParticles; i++)
 	{
 	{
-		ParticleSimple* part = ANKI_NEW(ParticleSimple, getSceneAllocator(),
-			(getName() + std::to_string(i)).c_str(), scene, nullptr,
+		ParticleSimple* part;
+		
+		getSceneGraph().newSceneNode(part,
+			(getName() + std::to_string(i)).c_str(), nullptr,
 			Movable::MF_NONE);
 			Movable::MF_NONE);
 
 
 		part->size = getRandom(particle.size, particle.sizeDeviation);
 		part->size = getRandom(particle.size, particle.sizeDeviation);

+ 94 - 38
src/scene/SceneGraph.cpp

@@ -16,23 +16,24 @@ namespace anki {
 //==============================================================================
 //==============================================================================
 struct UpdateMovablesJob: ThreadJob
 struct UpdateMovablesJob: ThreadJob
 {
 {
-	SceneGraph::Types<SceneNode>::Iterator movablesBegin;
+	SceneGraph* scene = nullptr;
 	U32 movablesCount;
 	U32 movablesCount;
 
 
 	void operator()(U threadId, U threadsCount)
 	void operator()(U threadId, U threadsCount)
 	{
 	{
 		U64 start, end;
 		U64 start, end;
-		choseStartEnd(threadId, threadsCount, movablesCount, start, end);
+		ANKI_ASSERT(scene);
+		choseStartEnd(
+			threadId, threadsCount, scene->getSceneNodesCount(), start, end);
 
 
-		for(U64 i = start; i < end; i++)
+		scene->iterateSceneNodes(start, end, [](SceneNode& sn)
 		{
 		{
-			SceneNode* sn = *(movablesBegin + i);
-			Movable* m = sn->getMovable();
+			Movable* m = sn.getMovable();
 			if(m)
 			if(m)
 			{
 			{
 				m->update();
 				m->update();
 			}
 			}
-		}
+		});
 	}
 	}
 };
 };
 
 
@@ -72,22 +73,22 @@ static void updateSceneNode(SceneNode& sn, F32 prevUpdateTime,
 //==============================================================================
 //==============================================================================
 struct UpdateSceneNodesJob: ThreadJob
 struct UpdateSceneNodesJob: ThreadJob
 {
 {
-	SceneGraph::Types<SceneNode>::Iterator sceneNodesBegin;
-	U32 sceneNodesCount;
+	SceneGraph* scene = nullptr;
 	F32 prevUpdateTime;
 	F32 prevUpdateTime;
 	F32 crntTime;
 	F32 crntTime;
 	SectorGroup* sectorGroup;
 	SectorGroup* sectorGroup;
 
 
 	void operator()(U threadId, U threadsCount)
 	void operator()(U threadId, U threadsCount)
 	{
 	{
+		ANKI_ASSERT(scene);
 		U64 start, end;
 		U64 start, end;
-		choseStartEnd(threadId, threadsCount, sceneNodesCount, start, end);
+		choseStartEnd(
+			threadId, threadsCount, scene->getSceneNodesCount(), start, end);
 
 
-		for(U64 i = start; i < end; i++)
+		scene->iterateSceneNodes(start, end, [&](SceneNode& sn)
 		{
 		{
-			SceneNode* n = *(sceneNodesBegin + i);
-			updateSceneNode(*n, prevUpdateTime, crntTime, *sectorGroup);
-		}
+			updateSceneNode(sn, prevUpdateTime, crntTime, *sectorGroup);	
+		});
 	}
 	}
 };
 };
 
 
@@ -100,6 +101,7 @@ SceneGraph::SceneGraph()
 	:	alloc(ANKI_SCENE_ALLOCATOR_SIZE),
 	:	alloc(ANKI_SCENE_ALLOCATOR_SIZE),
 		frameAlloc(ANKI_SCENE_FRAME_ALLOCATOR_SIZE),
 		frameAlloc(ANKI_SCENE_FRAME_ALLOCATOR_SIZE),
 		nodes(alloc),
 		nodes(alloc),
+		dict(10, DictionaryHasher(), DictionaryEqual(), alloc),
 		sectorGroup(this),
 		sectorGroup(this),
 		events(this)
 		events(this)
 {
 {
@@ -115,24 +117,92 @@ SceneGraph::~SceneGraph()
 //==============================================================================
 //==============================================================================
 void SceneGraph::registerNode(SceneNode* node)
 void SceneGraph::registerNode(SceneNode* node)
 {
 {
-	addC(nodes, node);
+	ANKI_ASSERT(node);
 
 
 	// Add to dict if it has name
 	// Add to dict if it has name
 	if(node->getName())
 	if(node->getName())
 	{
 	{
-		addDict(nameToNode, node);
+		if(dict.find(node->getName()) != dict.end())
+		{
+			throw ANKI_EXCEPTION("Node with the same name already exists: "
+				+ node->getName());
+		}
+
+		dict[node->getName()] = node;
 	}
 	}
+
+	// Add to vector
+	nodes.push_back(node);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
 void SceneGraph::unregisterNode(SceneNode* node)
 void SceneGraph::unregisterNode(SceneNode* node)
 {
 {
-	removeC(nodes, node);
+	// Remove from vector
+	auto it = nodes.begin();
+	for(; it != nodes.end(); it++)
+	{
+		if((*it) == node)
+		{
+			break;
+		}
+	}
+	
+	ANKI_ASSERT(it != nodes.end());
+	nodes.erase(it);
 
 
-	// Remove from dict if it has name
+	// Remove from dict
 	if(node->getName())
 	if(node->getName())
 	{
 	{
-		removeDict(nameToNode, node);
+		auto it = dict.find(node->getName());
+
+		ANKI_ASSERT(it != dict.end());
+		dict.erase(it);
+	}
+}
+
+//==============================================================================
+SceneNode& SceneGraph::findSceneNode(const char* name)
+{
+	ANKI_ASSERT(dict.find(name) != dict.end());
+	return *(dict.find(name))->second;
+}
+
+//==============================================================================
+SceneNode* SceneGraph::tryFindSceneNode(const char* name)
+{
+	auto it = dict.find(name);
+	return (it == dict.end()) ? nullptr : it->second;
+}
+
+//==============================================================================
+void SceneGraph::deleteNodesMarkedForDeletion()
+{
+	/// Delete all nodes pending deletion. At this point all scene threads 
+	/// should have finished their tasks
+	while(nodesMarkedForDeletionCount > 0)
+	{
+		// First gather the nodes that will be de
+		SceneFrameVector<decltype(nodes)::iterator> forDeletion;
+		for(auto it = nodes.begin(); it != nodes.end(); it++)
+		{
+			if((*it)->isMarkedForDeletion())
+			{
+				forDeletion.push_back(it);
+			}
+		}
+
+		// Now delete
+		for(auto& it : forDeletion)
+		{
+			unregisterNode(*it);
+
+			SceneAllocator<SceneNode> al = alloc;
+			alloc.destroy(*it);
+			alloc.deallocate(*it, 1);
+
+			++nodesMarkedForDeletionCount;
+		}
 	}
 	}
 }
 }
 
 
@@ -143,6 +213,8 @@ void SceneGraph::update(F32 prevUpdateTime, F32 crntTime, Renderer& renderer)
 
 
 	ANKI_COUNTER_START_TIMER(C_SCENE_UPDATE_TIME);
 	ANKI_COUNTER_START_TIMER(C_SCENE_UPDATE_TIME);
 
 
+	deleteNodesMarkedForDeletion();
+
 	ThreadPool& threadPool = ThreadPoolSingleton::get();
 	ThreadPool& threadPool = ThreadPoolSingleton::get();
 	(void)threadPool;
 	(void)threadPool;
 	frameAlloc.reset();
 	frameAlloc.reset();
@@ -168,8 +240,7 @@ void SceneGraph::update(F32 prevUpdateTime, F32 crntTime, Renderer& renderer)
 
 
 	for(U i = 0; i < threadPool.getThreadsCount(); i++)
 	for(U i = 0; i < threadPool.getThreadsCount(); i++)
 	{
 	{
-		jobs[i].movablesBegin = nodes.begin();
-		jobs[i].movablesCount = nodes.size();
+		jobs[i].scene = this;
 
 
 		threadPool.assignNewJob(i, &jobs[i]);
 		threadPool.assignNewJob(i, &jobs[i]);
 	}
 	}
@@ -190,8 +261,7 @@ void SceneGraph::update(F32 prevUpdateTime, F32 crntTime, Renderer& renderer)
 	{
 	{
 		UpdateSceneNodesJob& job = jobs2[i];
 		UpdateSceneNodesJob& job = jobs2[i];
 
 
-		job.sceneNodesBegin = nodes.begin();
-		job.sceneNodesCount = nodes.size();
+		job.scene = this;
 		job.prevUpdateTime = prevUpdateTime;
 		job.prevUpdateTime = prevUpdateTime;
 		job.crntTime = crntTime;
 		job.crntTime = crntTime;
 		job.sectorGroup = &sectorGroup;
 		job.sectorGroup = &sectorGroup;
@@ -210,20 +280,6 @@ void SceneGraph::update(F32 prevUpdateTime, F32 crntTime, Renderer& renderer)
 	ANKI_COUNTER_STOP_TIMER_INC(C_SCENE_UPDATE_TIME);
 	ANKI_COUNTER_STOP_TIMER_INC(C_SCENE_UPDATE_TIME);
 }
 }
 
 
-//==============================================================================
-SceneNode& SceneGraph::findSceneNode(const char* name)
-{
-	ANKI_ASSERT(nameToNode.find(name) != nameToNode.end());
-	return *(nameToNode.find(name)->second);
-}
-
-//==============================================================================
-SceneNode* SceneGraph::tryFindSceneNode(const char* name)
-{
-	Types<SceneNode>::NameToItemMap::iterator it = nameToNode.find(name);
-	return (it == nameToNode.end()) ? nullptr : it->second;
-}
-
 //==============================================================================
 //==============================================================================
 void SceneGraph::load(const char* filename)
 void SceneGraph::load(const char* filename)
 {
 {
@@ -258,8 +314,8 @@ void SceneGraph::load(const char* filename)
 				throw ANKI_EXCEPTION("Too many instances");
 				throw ANKI_EXCEPTION("Too many instances");
 			}
 			}
 
 
-			ModelNode* node = ANKI_NEW(ModelNode, alloc,
-				name.c_str(), this, nullptr,
+			ModelNode* node;
+			newSceneNode(node, name.c_str(), nullptr,
 				Movable::MF_NONE, el.getText(), instancesCount);
 				Movable::MF_NONE, el.getText(), instancesCount);
 
 
 			// <transform>
 			// <transform>

+ 3 - 14
src/scene/SceneNode.cpp

@@ -10,7 +10,8 @@ namespace anki {
 SceneNode::SceneNode(const char* name_, SceneGraph* scene_, SceneNode* parent)
 SceneNode::SceneNode(const char* name_, SceneGraph* scene_, SceneNode* parent)
 	:	Base(parent, scene_->getAllocator()),
 	:	Base(parent, scene_->getAllocator()),
 		scene(scene_),
 		scene(scene_),
-		name(getSceneAllocator())
+		name(getSceneAllocator()),
+		markedForDeletion(false)
 {
 {
 	ANKI_ASSERT(scene);
 	ANKI_ASSERT(scene);
 
 
@@ -19,25 +20,13 @@ SceneNode::SceneNode(const char* name_, SceneGraph* scene_, SceneNode* parent)
 		name = SceneString(name_, scene->getAllocator());
 		name = SceneString(name_, scene->getAllocator());
 	}
 	}
 	
 	
-	scene->registerNode(this);
-
 	/// Add the first property
 	/// Add the first property
 	//addNewProperty(new ReadPointerProperty<std::string>("name", &name));
 	//addNewProperty(new ReadPointerProperty<std::string>("name", &name));
 }
 }
 
 
 //==============================================================================
 //==============================================================================
 SceneNode::~SceneNode()
 SceneNode::~SceneNode()
-{
-	if(scene)
-	{
-		scene->unregisterNode(this);
-
-		if(getSpatial() && getSpatial()->octreeNode)
-		{
-			getSpatial()->octreeNode->removeSceneNode(this);
-		}
-	}
-}
+{}
 
 
 //==============================================================================
 //==============================================================================
 SceneAllocator<U8> SceneNode::getSceneAllocator() const
 SceneAllocator<U8> SceneNode::getSceneAllocator() const

+ 3 - 4
src/scene/StaticGeometryNode.cpp

@@ -74,9 +74,8 @@ StaticGeometryNode::StaticGeometryNode(
 	{
 	{
 		std::string name_ = name + std::to_string(i);
 		std::string name_ = name + std::to_string(i);
 
 
-		StaticGeometryPatchNode* node = ANKI_NEW(
-			StaticGeometryPatchNode, getSceneAllocator(),
-			name_.c_str(), scene, patch);
+		StaticGeometryPatchNode* node;
+		getSceneGraph().newSceneNode(node, name_.c_str(), patch);
 
 
 		patches.push_back(node);
 		patches.push_back(node);
 		++i;
 		++i;
@@ -88,7 +87,7 @@ StaticGeometryNode::~StaticGeometryNode()
 {
 {
 	for(StaticGeometryPatchNode* patch : patches)
 	for(StaticGeometryPatchNode* patch : patches)
 	{
 	{
-		ANKI_DELETE(patch, getSceneAllocator());
+		getSceneGraph().deleteSceneNode(patch);
 	}
 	}
 }
 }