Selaa lähdekoodia

Scene refactoring is done. IT COMPILES

Panagiotis Christopoulos Charitos 12 vuotta sitten
vanhempi
sitoutus
f589d7cea3
51 muutettua tiedostoa jossa 389 lisäystä ja 424 poistoa
  1. 1 1
      CMakeLists.txt
  2. 6 6
      include/anki/event/MoveEvent.h
  3. 9 9
      include/anki/physics/Character.h
  4. 3 3
      include/anki/physics/MotionState.h
  5. 3 3
      include/anki/physics/RigidBody.h
  6. 2 8
      include/anki/renderer/DebugDrawer.h
  7. 4 4
      include/anki/renderer/Drawer.h
  8. 4 8
      include/anki/resource/Path.h
  9. 1 1
      include/anki/scene/Camera.h
  10. 3 3
      include/anki/scene/Light.h
  11. 6 3
      include/anki/scene/ModelNode.h
  12. 22 25
      include/anki/scene/ParticleEmitter.h
  13. 3 4
      include/anki/scene/Path.h
  14. 2 2
      include/anki/scene/RenderComponent.h
  15. 22 0
      include/anki/scene/SceneNode.h
  16. 4 9
      include/anki/scene/Sector.h
  17. 15 15
      include/anki/scene/SkinNode.h
  18. 10 8
      include/anki/scene/StaticGeometryNode.h
  19. 4 4
      include/anki/scene/Visibility.h
  20. 1 1
      include/anki/util/Allocator.h
  21. 3 3
      src/event/AnimationEvent.cpp
  22. 0 5
      src/event/EventManager.cpp
  23. 1 1
      src/event/FollowPathEvent.cpp
  24. 0 41
      src/event/MovableEvent.cpp
  25. 41 0
      src/event/MoveEvent.cpp
  26. 1 1
      src/physics/MotionState.cpp
  27. 1 1
      src/physics/RigidBody.cpp
  28. 2 1
      src/renderer/Bs.cpp
  29. 1 6
      src/renderer/Dbg.cpp
  30. 5 40
      src/renderer/DebugDrawer.cpp
  31. 23 22
      src/renderer/Drawer.cpp
  32. 1 1
      src/renderer/Ez.cpp
  33. 3 1
      src/renderer/Is.cpp
  34. 2 2
      src/renderer/Lf.cpp
  35. 3 2
      src/renderer/MainRenderer.cpp
  36. 1 1
      src/renderer/Ms.cpp
  37. 2 1
      src/renderer/Renderer.cpp
  38. 10 10
      src/renderer/Sm.cpp
  39. 2 1
      src/renderer/Ssao.cpp
  40. 2 1
      src/renderer/Tiler.cpp
  41. 15 22
      src/scene/ModelNode.cpp
  42. 2 2
      src/scene/Octree.cpp
  43. 38 47
      src/scene/ParticleEmitter.cpp
  44. 5 6
      src/scene/Path.cpp
  45. 9 6
      src/scene/RenderComponent.cpp
  46. 8 15
      src/scene/SceneGraph.cpp
  47. 22 8
      src/scene/Sector.cpp
  48. 14 15
      src/scene/StaticGeometryNode.cpp
  49. 15 15
      src/scene/Visibility.cpp
  50. 3 1
      src/util/Memory.cpp
  51. 29 29
      testapp/Main.cpp

+ 1 - 1
CMakeLists.txt

@@ -71,7 +71,7 @@ endif()
 if(LINUX)
 	#set(_WIN_BACKEND "GLXX11")
 	set(_WIN_BACKEND "SDL")
-else(WINDOWS)
+elseif(WINDOWS)
 	set(_WIN_BACKEND "SDL")
 elseif(ANDROID)
 	set(_WIN_BACKEND "ANDROID")

+ 6 - 6
include/anki/event/MovableEvent.h → include/anki/event/MoveEvent.h

@@ -1,5 +1,5 @@
-#ifndef ANKI_EVENT_MOVABLE_EVENT_H
-#define ANKI_EVENT_MOVABLE_EVENT_H
+#ifndef ANKI_EVENT_MOVE_EVENT_H
+#define ANKI_EVENT_MOVE_EVENT_H
 
 #include "anki/event/Event.h"
 #include "anki/Math.h"
@@ -13,22 +13,22 @@ class SceneNode;
 /// @{
 
 /// Helper class
-struct MovableEventData
+struct MoveEventData
 {
 	Vec3 posMin;
 	Vec3 posMax;
 };
 
 /// An event for simple movable animations
-class MovableEvent: public Event, private MovableEventData
+class MoveEvent: public Event, private MoveEventData
 {
 public:
 	/// @name Constructors/Destructor
 	/// @{
 
 	/// Constructor
-	MovableEvent(EventManager* manager, F32 startTime, F32 duration,
-		SceneNode* movableSceneNode, const MovableEventData& data);
+	MoveEvent(EventManager* manager, F32 startTime, F32 duration,
+		SceneNode* movableSceneNode, const MoveEventData& data);
 	/// @}
 
 	/// Implements Event::update

+ 9 - 9
include/anki/physics/Character.h

@@ -11,7 +11,7 @@ class btGhostPairCallback;
 
 namespace anki {
 
-class Movable;
+class MoveComponent;
 class PhysWorld;
 class MotionState;
 
@@ -24,12 +24,12 @@ public:
 	/// Initializer class
 	struct Initializer
 	{
-		float characterHeight;
-		float characterWidth;
-		float stepHeight;
-		float jumpSpeed;
-		float maxJumpHeight;
-		Movable* movable; ///< For the MotionState
+		F32 characterHeight;
+		F32 characterWidth;
+		F32 stepHeight;
+		F32 jumpSpeed;
+		F32 maxJumpHeight;
+		MoveComponent* movable; ///< For the MotionState
 		Transform startTrf;
 
 		Initializer();
@@ -37,8 +37,8 @@ public:
 
 	Character(PhysWorld* masterContainer, const Initializer& init);
 	~Character();
-	void rotate(float angle);
-	void moveForward(float distance);
+	void rotate(F32 angle);
+	void moveForward(F32 distance);
 	void jump();
 
 private:

+ 3 - 3
include/anki/physics/MotionState.h

@@ -1,7 +1,7 @@
 #ifndef ANKI_PHYSICS_MOTION_STATE_H
 #define ANKI_PHYSICS_MOTION_STATE_H
 
-#include "anki/scene/Movable.h"
+#include "anki/scene/MoveComponent.h"
 #include <LinearMath/btMotionState.h>
 
 namespace anki {
@@ -11,7 +11,7 @@ class MotionState: public btMotionState
 {
 public:
 	MotionState();
-	MotionState(const Transform& initialTransform, Movable* node);
+	MotionState(const Transform& initialTransform, MoveComponent* node);
 
 	~MotionState()
 	{}
@@ -30,7 +30,7 @@ public:
 
 private:
 	btTransform worldTransform;
-	Movable* node; ///< Pointer cause it may be NULL
+	MoveComponent* node; ///< Pointer cause it may be NULL
 };
 
 } // end namespace anki

+ 3 - 3
include/anki/physics/RigidBody.h

@@ -8,7 +8,7 @@
 
 namespace anki {
 
-class Movable;
+class MoveComponent;
 class PhysWorld;
 
 /// Wrapper for rigid body
@@ -21,14 +21,14 @@ public:
 		F32 mass = 0.0;
 		Transform startTrf = Transform::getIdentity();
 		btCollisionShape* shape = nullptr;
-		Movable* movable = nullptr;
+		MoveComponent* movable = nullptr;
 		I32 group = -1;
 		I32 mask = -1;
 	};
 
 	/// Init and register
 	RigidBody(PhysWorld* masterContainer, const Initializer& init, 
-		Movable* movable = nullptr);
+		MoveComponent* movable = nullptr);
 
 	/// Unregister
 	~RigidBody();

+ 2 - 8
include/anki/renderer/DebugDrawer.h

@@ -149,11 +149,10 @@ private:
 };
 
 // Forward
-class Octree;
-class OctreeNode;
 class Renderer;
 class Camera;
 class Sector;
+class Path;
 
 /// This is a drawer for some scene nodes that need debug
 class SceneDebugDrawer
@@ -168,8 +167,6 @@ public:
 
 	void draw(SceneNode& node);
 
-	void draw(const Octree& octree) const;
-
 	void draw(const Sector& sector);
 
 	void setViewProjectionMatrix(const Mat4& m)
@@ -180,13 +177,10 @@ public:
 private:
 	DebugDrawer* dbg;
 
-	void draw(Frustumable& fr) const;
+	void draw(FrustumComponent& fr) const;
 
 	void draw(SpatialComponent& sp) const;
 
-	void draw(const OctreeNode& octnode,
-		U32 depth, const Octree& octree) const;
-
 	void drawPath(const Path& path) const;
 };
 

+ 4 - 4
include/anki/renderer/Drawer.h

@@ -8,10 +8,10 @@ namespace anki {
 
 class PassLevelKey;
 class Renderer;
-class Frustumable;
+class FrustumComponent;
 class SceneNode;
 class ShaderProgram;
-class Renderable;
+class RenderComponent;
 
 /// It includes all the functions to render a Renderable
 class RenderableDrawer
@@ -44,9 +44,9 @@ private:
 
 	void setupShaderProg(
 		const PassLevelKey& key,
-		const Frustumable& fr,
+		const FrustumComponent& fr,
 		const ShaderProgram& prog,
-		Renderable& renderable,
+		RenderComponent& renderable,
 		U32* subSpatialIndices,
 		U subSpatialIndicesCount);
 };

+ 4 - 8
include/anki/resource/Path.h

@@ -3,26 +3,22 @@
 
 #include "anki/Math.h"
 
-
 namespace anki {
 
-
 /// Path @ref Resource resource
 class Path
 {
 	public:
 		Vector<Vec3> positions; ///< AKA translations
-		Vector<Mat3> rotations;
-		Vector<float>  scales;
-		float         step;
+		Vector<Quat> rotations;
+		Vector<F32> scales;
+		F32 step;
 
 		Path() {}
 		~Path() {}
 		bool load(const char* filename);
 };
 
-
-} // end namespace
-
+} // end namespace anki
 
 #endif

+ 1 - 1
include/anki/scene/Camera.h

@@ -234,7 +234,7 @@ public:
 	/// @li Update view matrix
 	/// @li Update view-projection matrix
 	/// @li Update frustum
-	void movableUpdate()
+	void moveUpdate()
 	{
 		ANKI_ASSERT(0 && "TODO");
 	}

+ 3 - 3
include/anki/scene/Light.h

@@ -223,7 +223,7 @@ public:
 
 	/// Overrides MoveComponent::moveUpdate(). This does:
 	/// - Update the collision shape
-	void movableUpdate()
+	void moveUpdate()
 	{
 		sphereW.setCenter(getWorldTransform().getOrigin());
 		SpatialComponent::markForUpdate();
@@ -314,8 +314,8 @@ public:
 	/// @name FrustumComponent virtuals
 	/// @{
 
-	/// Override FrustumComponent::getFrustumComponentOrigin()
-	const Vec3& getFrustumComponentOrigin() const
+	/// Override FrustumComponent::getFrustumOrigin()
+	const Vec3& getFrustumOrigin() const
 	{
 		return getWorldTransform().getOrigin();
 	}

+ 6 - 3
include/anki/scene/ModelNode.h

@@ -11,6 +11,9 @@
 
 namespace anki {
 
+// Forward
+class ModelPatchNode;
+
 /// @addtogroup Scene
 /// @{
 
@@ -24,7 +27,7 @@ class ModelPatchNodeInstance: public SceneNode, public MoveComponent,
 public:
 	ModelPatchNodeInstance(
 		const char* name, SceneGraph* scene, // SceneNode
-		const ModelPatchBase* modelPatchResource); // Self
+		ModelPatchNode* modelPatchNode); // Self
 
 	/// @name MoveComponent virtuals
 	/// @{
@@ -37,7 +40,7 @@ public:
 
 private:
 	Obb obb; ///< In world space
-	const ModelPatchBase* modelPatch; ///< Keep the resource for the OBB
+	ModelPatchNode* modelPatchNode; ///< Keep the father here
 };
 
 /// A fragment of the ModelNode
@@ -97,7 +100,7 @@ private:
 	SceneVector<ModelPatchNodeInstance*> instances;
 	SceneVector<Transform> transforms;
 
-	/// This is called by the last of the instances on it's movableUpdate()
+	/// This is called by the last of the instances on it's moveUpdate()
 	void updateSpatialCs();
 };
 

+ 22 - 25
include/anki/scene/ParticleEmitter.h

@@ -2,9 +2,9 @@
 #define ANKI_SCENE_PARTICLE_EMITTER_H
 
 #include "anki/scene/SceneNode.h"
-#include "anki/scene/Movable.h"
+#include "anki/scene/MoveComponent.h"
 #include "anki/scene/SpatialComponent.h"
-#include "anki/scene/Renderable.h"
+#include "anki/scene/RenderComponent.h"
 #include "anki/physics/RigidBody.h"
 #include "anki/resource/ParticleEmitterResource.h"
 
@@ -14,7 +14,7 @@ class ParticleEmitter;
 
 /// Particle base
 /// XXX Remove SceneNode
-class ParticleBase: public SceneNode, public Movable
+class ParticleBase: public SceneNode, public MoveComponent
 {
 	friend class ParticleEmitter;
 
@@ -26,8 +26,7 @@ public:
 	};
 
 	ParticleBase(
-		const char* name, SceneGraph* scene, SceneNode* parent, // SceneNode
-		U32 movableFlags, // Movable
+		const char* name, SceneGraph* scene, // SceneNode
 		ParticleType type); // Self
 
 	virtual ~ParticleBase();
@@ -101,8 +100,7 @@ class ParticleSimple: public ParticleBase
 {
 public:
 	ParticleSimple(
-		const char* name, SceneGraph* scene, SceneNode* parent, // SceneNode
-		U32 movableFlags); // Movable
+		const char* name, SceneGraph* scene); // SceneNode
 
 	void revive(const ParticleEmitter& pe,
 		F32 prevUpdateTime, F32 crntTime);
@@ -120,8 +118,7 @@ class Particle: public ParticleBase, public RigidBody
 {
 public:
 	Particle(
-		const char* name, SceneGraph* scene, SceneNode* parent, // SceneNode
-		U32 movableFlags, // Movable
+		const char* name, SceneGraph* scene, // SceneNode
 		// RigidBody
 		PhysWorld* masterContainer, const RigidBody::Initializer& init); 
 
@@ -139,7 +136,8 @@ public:
 
 /// The particle emitter scene node. This scene node emitts
 class ParticleEmitter: public SceneNode, public SpatialComponent, 
-	public Movable, public Renderable, private ParticleEmitterProperties
+	public MoveComponent, public RenderComponent, 
+	private ParticleEmitterProperties
 {
 	friend class ParticleBase;
 	friend class Particle;
@@ -147,8 +145,7 @@ class ParticleEmitter: public SceneNode, public SpatialComponent,
 
 public:
 	ParticleEmitter(
-		const char* name, SceneGraph* scene, SceneNode* parent, // SceneNode
-		U32 movableFlags, // Movable
+		const char* name, SceneGraph* scene, // SceneNode
 		const char* filename); // Self
 
 	~ParticleEmitter();
@@ -160,33 +157,33 @@ public:
 	void frameUpdate(F32 prevUpdateTime, F32 crntTime, I frame);
 	/// @}
 
-	/// @name Renderable virtuals
+	/// @name RenderComponent virtuals
 	/// @{
 
-	/// Implements Renderable::getModelPatchBase
-	const ModelPatchBase& getRenderableModelPatchBase();
+	/// Implements RenderComponent::getModelPatchBase
+	const ModelPatchBase& getModelPatchBase();
 
-	/// Implements  Renderable::getMaterial
-	const Material& getRenderableMaterial();
+	/// Implements  RenderComponent::getMaterial
+	const Material& getMaterial();
 
-	/// Overrides Renderable::getRenderableWorldTransforms
-	const Transform* getRenderableWorldTransforms()
+	/// Overrides RenderComponent::getRenderWorldTransforms
+	const Transform* getRenderWorldTransforms()
 	{
 		return &(*instancingTransformations)[0];
 	}
 
-	/// Overrides Renderable::getRenderableInstancesCount
-	U32 getRenderableInstancesCount()
+	/// Overrides RenderComponent::getRenderInstancesCount
+	U32 getRenderInstancesCount()
 	{
 		return instancesCount;
 	}
 	/// @}
 
-	/// @name Movable virtuals
+	/// @name MoveComponent virtuals
 	/// @{
 
-	/// Overrides Movable::movableUpdate. Calculates an optimization
-	void movableUpdate();
+	/// Overrides MoveComponent::moveUpdate. Calculates an optimization
+	void moveUpdate();
 	/// @}
 
 private:
@@ -207,7 +204,7 @@ private:
 	/// rendering.
 	SceneFrameVector<Transform>* instancingTransformations;
 
-	RenderableVariable* alphaRenderableVar = nullptr;
+	RenderComponentVariable* alphaRenderComponentVar = nullptr;
 
 	void createParticlesSimulation(SceneGraph* scene);
 	void createParticlesSimpleSimulation(SceneGraph* scene);

+ 3 - 4
include/anki/scene/Path.h

@@ -3,7 +3,7 @@
 
 #include "anki/scene/Common.h"
 #include "anki/scene/SceneNode.h"
-#include "anki/scene/Movable.h"
+#include "anki/scene/MoveComponent.h"
 
 namespace anki {
 
@@ -44,12 +44,11 @@ private:
 };
 
 /// XXX
-class Path: public SceneNode, public Movable
+class Path: public SceneNode, public MoveComponent
 {
 public:
 	Path(
-		const char* name, SceneGraph* scene, SceneNode* parent, // SceneNode
-		U32 movableFlags, // Movable
+		const char* name, SceneGraph* scene, // SceneNode
 		const char* filename); // Self
 
 	const SceneVector<PathPoint>& getPoints() const

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

@@ -78,13 +78,13 @@ public:
 
 	/// This will trigger copy on write
 	template<typename T>
-	void setValues(const T* values, U32 size)
+	void setValues(const T* values, U32 size, SceneAllocator<U8> alloc)
 	{
 		ANKI_ASSERT(
 			Base::getVariadicTypeId<RenderComponentVariableTemplate<T>>()
 			== Base::getVisitableTypeId());
 		static_cast<RenderComponentVariableTemplate<T>*>(this)->set(
-			values, size);
+			values, size, alloc);
 	}
 
 	U32 getArraySize() const

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

@@ -15,6 +15,8 @@ class RenderComponent;
 class FrustumComponent;
 class SpatialComponent;
 class Light;
+class RigidBody;
+class Path;
 
 /// @addtogroup Scene
 /// @{
@@ -104,6 +106,24 @@ public:
 	{
 		return sceneNodeProtected.lightC;
 	}
+
+	RigidBody* getRigidBody()
+	{
+		return sceneNodeProtected.rigidBodyC;
+	}
+	const RigidBody* getRigidBody() const 
+	{
+		return sceneNodeProtected.rigidBodyC;
+	}
+
+	Path* getPath()
+	{
+		return sceneNodeProtected.pathC;
+	}
+	const Path* getPath() const 
+	{
+		return sceneNodeProtected.pathC;
+	}
 	/// @}
 
 	/// This is called by the scene every frame after logic and before
@@ -139,6 +159,8 @@ protected:
 		FrustumComponent* frustumC = nullptr;
 		SpatialComponent* spatialC = nullptr;
 		Light* lightC = nullptr;
+		RigidBody* rigidBodyC = nullptr;
+		Path* pathC = nullptr;
 	} sceneNodeProtected;
 
 private:

+ 4 - 9
include/anki/scene/Sector.h

@@ -1,7 +1,8 @@
 #ifndef ANKI_SCENE_SECTOR_H
 #define ANKI_SCENE_SECTOR_H
 
-#include "anki/scene/Octree.h"
+#include "anki/scene/Common.h"
+#include "anki/scene/Visibility.h"
 #include "anki/Collision.h"
 
 namespace anki {
@@ -40,7 +41,7 @@ public:
 
 	const Aabb& getAabb() const
 	{
-		return octree.getRoot().getAabb();
+		return aabb;
 	}
 
 	const SectorGroup& getSectorGroup() const
@@ -52,11 +53,6 @@ public:
 		return *group;
 	}
 
-	const Octree& getOctree() const
-	{
-		return octree;
-	}
-
 	U8 getVisibleByMask() const
 	{
 		return visibleBy;
@@ -67,9 +63,9 @@ public:
 
 private:
 	SectorGroup* group; ///< Know your father
-	Octree octree;
 	SceneVector<Portal*> portals;
 	U8 visibleBy;
+	Aabb aabb;
 
 	/// Sector does not take ownership of the portal
 	void addNewPortal(Portal* portal);
@@ -131,7 +127,6 @@ private:
 	void doVisibilityTestsInternal(SceneNode& fr, VisibilityTest test,
 		Renderer* r, VisibleBy visibleBy);
 };
-
 /// @}
 
 } // end namespace anki

+ 15 - 15
include/anki/scene/SkinNode.h

@@ -2,8 +2,8 @@
 #define ANKI_SCENE_SKIN_NODE_H
 
 #include "anki/scene/SceneNode.h"
-#include "anki/scene/Renderable.h"
-#include "anki/scene/Movable.h"
+#include "anki/scene/RenderComponent.h"
+#include "anki/scene/MoveComponent.h"
 #include "anki/scene/SpatialComponent.h"
 #include "anki/resource/Model.h"
 #include "anki/Math.h"
@@ -130,7 +130,7 @@ private:
 };
 
 /// A fragment of the SkinNode
-class SkinPatchNode: public SceneNode, public Movable, public Renderable,
+class SkinPatchNode: public SceneNode, public MoveComponent, public RenderComponent,
 	public SpatialComponent
 {
 public:
@@ -138,7 +138,7 @@ public:
 	/// @{
 	SkinPatchNode(const ModelPatchBase* modelPatch_,
 		const char* name, SceneGraph* scene, // Scene
-		U32 movableFlags, Movable* movParent, // Movable
+		U32 movableFlags, MoveComponent* movParent, // MoveComponent
 		CollisionShape* spatialCs); // SpatialComponent
 	/// @}
 
@@ -154,23 +154,23 @@ public:
 	}
 	/// @}
 
-	/// @name Renderable virtuals
+	/// @name RenderComponent virtuals
 	/// @{
 
-	/// Implements Renderable::getModelPatchBase
-	const ModelPatchBase& getRenderableModelPatchBase() const
+	/// Implements RenderComponent::getModelPatchBase
+	const ModelPatchBase& getRenderComponentModelPatchBase() const
 	{
 		return *skinModelPatch;
 	}
 
-	/// Implements Renderable::getMaterial
-	const Material& getRenderableMaterial() const
+	/// Implements RenderComponent::getMaterial
+	const Material& getRenderComponentMaterial() const
 	{
 		return skinModelPatch->getMaterial();
 	}
 
-	/// Overrides Renderable::getRenderableWorldTransforms
-	const Transform* getRenderableWorldTransforms() const
+	/// Overrides RenderComponent::getRenderComponentWorldTransforms
+	const Transform* getRenderComponentWorldTransforms() const
 	{
 		return &getWorldTransform();
 	}
@@ -181,14 +181,14 @@ private:
 };
 
 /// A skin scene node
-class SkinNode: public SceneNode, public Movable
+class SkinNode: public SceneNode, public MoveComponent
 {
 public:
 	/// @name Constructors/Destructor
 	/// @{
 	SkinNode(const char* skinFname,
 		const char* name, SceneGraph* scene, // SceneNode
-		U32 movableFlags, Movable* movParent); // Movable
+		U32 movableFlags, MoveComponent* movParent); // MoveComponent
 
 	~SkinNode();
 	/// @}
@@ -200,12 +200,12 @@ public:
 	void frameUpdate(F32 prevUpdateTime, F32 crntTime, int frame);
 	/// @}
 
-	/// @name Movable virtuals
+	/// @name MoveComponent virtuals
 	/// @{
 
 	/// Update boundingShapeWSpace from bone tails (not heads as well
 	/// cause its faster that way). The tails come from the previous frame
-	void movableUpdate();
+	void moveUpdate();
 	/// @}
 
 	/// @name Accessors

+ 10 - 8
include/anki/scene/StaticGeometryNode.h

@@ -4,7 +4,7 @@
 #include "anki/scene/Common.h"
 #include "anki/scene/SceneNode.h"
 #include "anki/scene/SpatialComponent.h"
-#include "anki/scene/Renderable.h"
+#include "anki/scene/RenderComponent.h"
 
 namespace anki {
 
@@ -17,13 +17,15 @@ class StaticGeometrySpatial: public SpatialComponent
 public:
 	/// @name Constructors/Destructor
 	/// @{
-	StaticGeometrySpatial(const Obb* obb, const SceneAllocator<U8>& alloc);
+
+	/// @note The node is only to steal the allocator
+	StaticGeometrySpatial(const Obb* obb, SceneNode& node);
 	/// @}
 };
 
 /// Static geometry scene node patch
 class StaticGeometryPatchNode: public SceneNode, public SpatialComponent,
-	public Renderable
+	public RenderComponent
 {
 public:
 	/// @name Constructors/Destructor
@@ -35,17 +37,17 @@ public:
 	~StaticGeometryPatchNode();
 	/// @}
 
-	/// @name Renderable virtuals
+	/// @name RenderComponent virtuals
 	/// @{
 
-	/// Implements Renderable::getModelPatchBase
-	const ModelPatchBase& getRenderableModelPatchBase()
+	/// Implements RenderComponent::getModelPatchBase
+	const ModelPatchBase& getModelPatchBase()
 	{
 		return *modelPatch;
 	}
 
-	/// Implements  Renderable::getMaterial
-	const Material& getRenderableMaterial()
+	/// Implements  RenderComponent::getMaterial
+	const Material& getMaterial()
 	{
 		return modelPatch->getMaterial();
 	}

+ 4 - 4
include/anki/scene/Visibility.h

@@ -131,11 +131,11 @@ struct MaterialSortFunctor
 	{
 		ANKI_ASSERT(a.node && b.node);
 
-		ANKI_ASSERT(a.node->getRenderable() != nullptr 
-			&& b.node->getRenderable() != nullptr);
+		ANKI_ASSERT(a.node->getRenderComponent() != nullptr 
+			&& b.node->getRenderComponent() != nullptr);
 
-		return a.node->getRenderComponent()->getRenderableMaterial()
-			< b.node->getRenderComponent()->getRenderableMaterial();
+		return a.node->getRenderComponent()->getMaterial()
+			< b.node->getRenderComponent()->getMaterial();
 	}
 };
 

+ 1 - 1
include/anki/util/Allocator.h

@@ -97,7 +97,7 @@ public:
 		// operator new doesn't respect alignment (in GCC at least) so use 
 		// custom mem allocation function
 		PtrSize size = n * sizeof(T);
-		allocatedSize += n * sizeof(T);
+		allocatedSize += size;
 		return (T*)mallocAligned(size, alignof(T));
 	}
 

+ 3 - 3
src/event/AnimationEvent.cpp

@@ -1,7 +1,7 @@
 #include "anki/event/AnimationEvent.h"
 #include "anki/resource/Animation.h"
 #include "anki/scene/SceneNode.h"
-#include "anki/scene/Movable.h"
+#include "anki/scene/MoveComponent.h"
 
 namespace anki {
 
@@ -11,7 +11,7 @@ AnimationEvent::AnimationEvent(EventManager* manager,
 	:	Event(manager, 0.0, 0.0, movableSceneNode),
 		anim(anim_)
 {
-	ANKI_ASSERT(movableSceneNode && movableSceneNode->getMovable());
+	ANKI_ASSERT(movableSceneNode && movableSceneNode->getMoveComponent());
 
 	startTime = anim->getStartingTime();
 	duration = anim->getDuration();
@@ -21,7 +21,7 @@ AnimationEvent::AnimationEvent(EventManager* manager,
 void AnimationEvent::update(F32 prevUpdateTime, F32 crntTime)
 {
 	ANKI_ASSERT(getSceneNode());
-	Movable* mov = getSceneNode()->getMovable();
+	MoveComponent* mov = getSceneNode()->getMoveComponent();
 	ANKI_ASSERT(mov);
 
 	Vec3 pos;

+ 0 - 5
src/event/EventManager.cpp

@@ -1,11 +1,6 @@
 #include "anki/event/EventManager.h"
 #include "anki/scene/SceneGraph.h"
 
-#include "anki/event/SceneAmbientColorEvent.h"
-#include "anki/event/LightEvent.h"
-#include "anki/event/MovableEvent.h"
-#include "anki/event/FollowPathEvent.h"
-
 namespace anki {
 
 //==============================================================================

+ 1 - 1
src/event/FollowPathEvent.cpp

@@ -18,7 +18,7 @@ FollowPathEvent::FollowPathEvent(
 //==============================================================================
 void FollowPathEvent::update(F32 prevUpdateTime, F32 crntTime)
 {
-	Movable* mov = movableSceneNode->getMovable();
+	MoveComponent* mov = movableSceneNode->getMoveComponent();
 	ANKI_ASSERT(mov);
 
 	I pointA = 0;

+ 0 - 41
src/event/MovableEvent.cpp

@@ -1,41 +0,0 @@
-#include "anki/event/MovableEvent.h"
-#include "anki/scene/SceneNode.h"
-#include "anki/scene/Movable.h"
-#include "anki/util/Functions.h"
-
-namespace anki {
-
-//==============================================================================
-MovableEvent::MovableEvent(EventManager* manager, F32 startTime, F32 duration,
-	SceneNode* movableSceneNode, const MovableEventData& data)
-	: Event(manager, startTime, duration, movableSceneNode, EF_NONE)
-{
-	ANKI_ASSERT(movableSceneNode);
-	*static_cast<MovableEventData*>(this) = data;
-
-	originalPos =
-		movableSceneNode->getMovable()->getLocalTransform().getOrigin();
-
-	for(U i = 0; i < 3; i++)
-	{
-		newPos[i] = randRange(posMin[i], posMax[i]);
-	}
-	newPos += movableSceneNode->getMovable()->getLocalTransform().getOrigin();
-}
-
-//==============================================================================
-void MovableEvent::update(F32 prevUpdateTime, F32 crntTime)
-{
-	SceneNode* movableSceneNode = getSceneNode();
-	ANKI_ASSERT(movableSceneNode);
-
-	Transform trf = movableSceneNode->getMovable()->getLocalTransform();
-
-	F32 factor = sin(getDelta(crntTime) * getPi<F32>());
-
-	trf.getOrigin() = interpolate(originalPos, newPos, factor);
-
-	movableSceneNode->getMovable()->setLocalTransform(trf);
-}
-
-} // end namespace anki

+ 41 - 0
src/event/MoveEvent.cpp

@@ -0,0 +1,41 @@
+#include "anki/event/MoveEvent.h"
+#include "anki/scene/SceneNode.h"
+#include "anki/scene/MoveComponent.h"
+#include "anki/util/Functions.h"
+
+namespace anki {
+
+//==============================================================================
+MoveEvent::MoveEvent(EventManager* manager, F32 startTime, F32 duration,
+	SceneNode* node, const MoveEventData& data)
+	: Event(manager, startTime, duration, node, EF_NONE)
+{
+	ANKI_ASSERT(node);
+	*static_cast<MoveEventData*>(this) = data;
+
+	originalPos =
+		node->getMoveComponent()->getLocalTransform().getOrigin();
+
+	for(U i = 0; i < 3; i++)
+	{
+		newPos[i] = randRange(posMin[i], posMax[i]);
+	}
+	newPos += node->getMoveComponent()->getLocalTransform().getOrigin();
+}
+
+//==============================================================================
+void MoveEvent::update(F32 prevUpdateTime, F32 crntTime)
+{
+	SceneNode* node = getSceneNode();
+	ANKI_ASSERT(node);
+
+	Transform trf = node->getMoveComponent()->getLocalTransform();
+
+	F32 factor = sin(getDelta(crntTime) * getPi<F32>());
+
+	trf.getOrigin() = interpolate(originalPos, newPos, factor);
+
+	node->getMoveComponent()->setLocalTransform(trf);
+}
+
+} // end namespace anki

+ 1 - 1
src/physics/MotionState.cpp

@@ -11,7 +11,7 @@ MotionState::MotionState()
 }
 
 //==============================================================================
-MotionState::MotionState(const Transform& initialTransform, Movable* node_)
+MotionState::MotionState(const Transform& initialTransform, MoveComponent* node_)
 	: worldTransform(toBt(initialTransform)), node(node_)
 {}
 

+ 1 - 1
src/physics/RigidBody.cpp

@@ -7,7 +7,7 @@ namespace anki {
 
 //==============================================================================
 RigidBody::RigidBody(PhysWorld* masterContainer_, const Initializer& init,
-	Movable* movable)
+	MoveComponent* movable)
 	: btRigidBody(btRigidBody::btRigidBodyConstructionInfo(0.0, nullptr, 
 		nullptr, btVector3(0.0, 0.0, 0.0))), // dummy init
 		masterContainer(masterContainer_)

+ 2 - 1
src/renderer/Bs.cpp

@@ -25,7 +25,8 @@ void Bs::run()
 	drawer.prepareDraw();
 	SceneGraph& scene = r->getSceneGraph();
 	VisibilityTestResults& vi =
-		*scene.getActiveCamera().getFrustumable()->getVisibilityTestResults();
+		scene.getActiveCamera().getFrustumComponent()->
+		getVisibilityTestResults();
 
 	for(auto it = vi.getRenderablesBegin(); it != vi.getRenderablesEnd();
 		++it)

+ 1 - 6
src/renderer/Dbg.cpp

@@ -66,7 +66,7 @@ void Dbg::run()
 
 	scene.iterateSceneNodes([&](SceneNode& node)
 	{
-		SpatialComponent* sp = node.getSpatial();
+		SpatialComponent* sp = node.getSpatialComponent();
 		if(bitsEnabled(DF_SPATIAL) && sp)
 		{
 			sceneDrawer->draw(node);
@@ -82,11 +82,6 @@ void Dbg::run()
 			{
 				sceneDrawer->draw(*sector);
 			}
-
-			if(bitsEnabled(DF_OCTREE))
-			{
-				sceneDrawer->draw(sector->getOctree());
-			}
 		}
 	}
 

+ 5 - 40
src/renderer/DebugDrawer.cpp

@@ -467,7 +467,7 @@ void PhysicsDebugDrawer::draw3dText(const btVector3& /*location*/,
 //==============================================================================
 void SceneDebugDrawer::draw(SceneNode& node)
 {
-	Movable* mv = node.getMovable();
+	MoveComponent* mv = node.getMoveComponent();
 	if(mv)
 	{
 		dbg->setModelMatrix(Mat4(mv->getWorldTransform()));
@@ -477,14 +477,14 @@ void SceneDebugDrawer::draw(SceneNode& node)
 		dbg->setModelMatrix(Mat4::getIdentity());
 	}
 
-	Frustumable* fr;
-	if((fr = node.getFrustumable()))
+	FrustumComponent* fr;
+	if((fr = node.getFrustumComponent()))
 	{
 		draw(*fr);
 	}
 
 	SpatialComponent* sp;
-	if((sp = node.getSpatial())
+	if((sp = node.getSpatialComponent())
 		&& sp->bitsEnabled(SpatialComponent::SF_VISIBLE_CAMERA))
 	{
 		draw(*sp);
@@ -498,7 +498,7 @@ void SceneDebugDrawer::draw(SceneNode& node)
 }
 
 //==============================================================================
-void SceneDebugDrawer::draw(Frustumable& fr) const
+void SceneDebugDrawer::draw(FrustumComponent& fr) const
 {
 	const Frustum& fs = fr.getFrustum();
 
@@ -524,41 +524,6 @@ void SceneDebugDrawer::draw(SpatialComponent& x) const
 	});
 }
 
-//==============================================================================
-void SceneDebugDrawer::draw(const Octree& octree) const
-{
-	dbg->setColor(Vec3(1.0));
-	draw(octree.getRoot(), 0, octree);
-}
-
-//==============================================================================
-void SceneDebugDrawer::draw(const OctreeNode& octnode, U32 depth,
-	const Octree& octree) const
-{
-	PtrSize nodesCount =
-		octnode.getSceneNodesEnd() - octnode.getSceneNodesBegin();
-
-	// Draw if it has spatials
-	if(nodesCount != 0)
-	{
-		//Vec3 color = Vec3(1.0 - F32(depth) / F32(octree.getMaxDepth()));
-		Vec3 color(1.0);
-		dbg->setColor(color);
-
-		CollisionDebugDrawer v(dbg);
-		octnode.getAabb().accept(v);
-	}
-
-	// Children
-	for(U32 i = 0; i < 8; ++i)
-	{
-		if(octnode.getChild(i) != nullptr)
-		{
-			draw(*octnode.getChild(i), depth + 1, octree);
-		}
-	}
-}
-
 //==============================================================================
 void SceneDebugDrawer::draw(const Sector& sector)
 {

+ 23 - 22
src/renderer/Drawer.cpp

@@ -1,8 +1,8 @@
 #include "anki/renderer/Drawer.h"
 #include "anki/resource/ShaderProgramResource.h"
-#include "anki/scene/Frustumable.h"
+#include "anki/scene/FrustumComponent.h"
 #include "anki/resource/Material.h"
-#include "anki/scene/Renderable.h"
+#include "anki/scene/RenderComponent.h"
 #include "anki/scene/Camera.h"
 #include "anki/scene/ModelNode.h"
 #include "anki/resource/TextureResource.h"
@@ -33,10 +33,10 @@ static U64 countVerts(U32* indicesCount, I primCount)
 ANKI_ATTRIBUTE_ALIGNED(struct, 16) SetupRenderableVariableVisitor
 {
 	Array<U8, UNIFORM_BLOCK_MAX_SIZE> clientBlock;
-	const Frustumable* fr = nullptr;
+	const FrustumComponent* fr = nullptr;
 	Renderer* r = nullptr;
-	Renderable* renderable = nullptr;
-	RenderableVariable* rvar = nullptr;
+	RenderComponent* renderable = nullptr;
+	RenderComponentVariable* rvar = nullptr;
 	const ShaderProgramUniformVariable* uni;
 
 	// Used for 
@@ -54,13 +54,13 @@ ANKI_ATTRIBUTE_ALIGNED(struct, 16) SetupRenderableVariableVisitor
 	template<typename TRenderableVariableTemplate>
 	void visit(TRenderableVariableTemplate& x)
 	{
-		const U32 instancesCount = renderable->getRenderableInstancesCount();
+		const U32 instancesCount = renderable->getRenderInstancesCount();
 		const U32 uniArrSize = uni->getSize();
 		U32 size = std::min(instancesCount, uniArrSize);
 
 		// Set uniform
 		//
-		const Transform* trfs = renderable->getRenderableWorldTransforms();
+		const Transform* trfs = renderable->getRenderWorldTransforms();
 		const Mat4& vp = fr->getViewProjectionMatrix();
 		const Mat4& v = fr->getViewMatrix();
 
@@ -237,8 +237,8 @@ void SetupRenderableVariableVisitor::uniSet<TextureResourcePointer>(
 
 //==============================================================================
 void RenderableDrawer::setupShaderProg(const PassLevelKey& key_,
-	const Frustumable& fr, const ShaderProgram &prog,
-	Renderable& renderable, 
+	const FrustumComponent& fr, const ShaderProgram &prog,
+	RenderComponent& renderable, 
 	U32* subSpatialIndices, U subSpatialIndicesCount)
 {
 	prog.bind();
@@ -253,13 +253,13 @@ void RenderableDrawer::setupShaderProg(const PassLevelKey& key_,
 
 	PassLevelKey key(key_.pass,
 		std::min(key_.level,
-		U8(renderable.getRenderableMaterial().getLevelsOfDetail() - 1)));
+		U8(renderable.getMaterial().getLevelsOfDetail() - 1)));
 
 	// Set the uniforms
 	for(auto it = renderable.getVariablesBegin();
 		it != renderable.getVariablesEnd(); ++it)
 	{
-		RenderableVariable* rvar = *it;
+		RenderComponentVariable* rvar = *it;
 
 		const ShaderProgramUniformVariable* uni =
 			rvar->tryFindShaderProgramUniformVariable(key);
@@ -273,15 +273,15 @@ void RenderableDrawer::setupShaderProg(const PassLevelKey& key_,
 	}
 
 	// Write the block
-	const ShaderProgramUniformBlock* block =
-		renderable.getRenderableMaterial().getCommonUniformBlock();
+	/*const ShaderProgramUniformBlock* block =
+		renderable.getMaterial().getCommonUniformBlock();
 	if(block)
 	{
 		ANKI_ASSERT(block->getSize() <= UNIFORM_BLOCK_MAX_SIZE);
 		ANKI_ASSERT(block->getBinding() == 0);
 		renderable.getUbo().write(&vis.clientBlock[0]);
 		renderable.getUbo().setBinding(0);
-	}
+	}*/
 }
 
 //==============================================================================
@@ -289,13 +289,13 @@ void RenderableDrawer::render(SceneNode& frsn, RenderingStage stage,
 	Pass pass, SceneNode& rsn, U32* subSpatialIndices,
 	U subSpatialIndicesCount)
 {
-	ANKI_ASSERT(frsn.getFrustumable());
-	Frustumable& fr = *frsn.getFrustumable();
-	Renderable* renderable = rsn.getRenderable();
+	ANKI_ASSERT(frsn.getFrustumComponent());
+	FrustumComponent& fr = *frsn.getFrustumComponent();
+	RenderComponent* renderable = rsn.getRenderComponent();
 	ANKI_ASSERT(renderable);
 
 	/* Instancing */
-	U32 instancesCount = renderable->getRenderableInstancesCount();
+	U32 instancesCount = renderable->getRenderInstancesCount();
 
 	if(ANKI_UNLIKELY(instancesCount < 1))
 	{
@@ -303,7 +303,7 @@ void RenderableDrawer::render(SceneNode& frsn, RenderingStage stage,
 	}
 
 	/* Blending */
-	const Material& mtl = renderable->getRenderableMaterial();
+	const Material& mtl = renderable->getMaterial();
 
 	Bool blending = mtl.isBlendingEnabled();
 
@@ -328,9 +328,10 @@ void RenderableDrawer::render(SceneNode& frsn, RenderingStage stage,
 	GlStateSingleton::get().enable(GL_BLEND, blending);
 
 	// Calculate the LOD
-	Vec3 camPos = fr.getFrustumableOrigin();
+	Vec3 camPos = fr.getFrustumOrigin();
 
-	F32 dist = (rsn.getSpatial()->getSpatialOrigin() - camPos).getLength();
+	F32 dist = 
+		(rsn.getSpatialComponent()->getSpatialOrigin() - camPos).getLength();
 	U8 lod = r->calculateLod(dist);
 
 	PassLevelKey key(pass, lod);
@@ -347,7 +348,7 @@ void RenderableDrawer::render(SceneNode& frsn, RenderingStage stage,
 
 	U32 primCount = 1;
 
-	const ModelPatchBase& resource = renderable->getRenderableModelPatchBase();
+	const ModelPatchBase& resource = renderable->getModelPatchBase();
 	if(subSpatialIndicesCount == 0 || resource.getSubMeshesCount() == 0)
 	{
 		// No multimesh

+ 1 - 1
src/renderer/Ez.cpp

@@ -22,7 +22,7 @@ void Ez::run()
 	Camera& cam = scene.getActiveCamera();
 
 	VisibilityTestResults& vi = 
-		*cam.getFrustumable()->getVisibilityTestResults();
+		cam.getFrustumComponent()->getVisibilityTestResults();
 
 	U count = 0;
 	for(auto it = vi.getRenderablesBegin();

+ 3 - 1
src/renderer/Is.cpp

@@ -5,6 +5,8 @@
 #include "anki/scene/Light.h"
 #include "anki/core/ThreadPool.h"
 #include "anki/core/Counters.h"
+#include "anki/core/Logger.h"
+#include <sstream>
 
 namespace anki {
 
@@ -621,7 +623,7 @@ void Is::lightPass()
 {
 	ThreadPool& threadPool = ThreadPoolSingleton::get();
 	VisibilityTestResults& vi = 
-		*cam->getFrustumable()->getVisibilityTestResults();
+		cam->getFrustumComponent()->getVisibilityTestResults();
 
 	//
 	// Quickly get the lights

+ 2 - 2
src/renderer/Lf.cpp

@@ -1,7 +1,7 @@
 #include "anki/renderer/Lf.h"
 #include "anki/renderer/Renderer.h"
 #include "anki/scene/SceneGraph.h"
-#include "anki/scene/Movable.h"
+#include "anki/scene/MoveComponent.h"
 #include "anki/scene/Camera.h"
 #include "anki/scene/Light.h"
 
@@ -147,7 +147,7 @@ void Lf::run()
 	// Retrieve some things
 	SceneGraph& scene = r->getSceneGraph();
 	Camera& cam = scene.getActiveCamera();
-	VisibilityTestResults& vi = *cam.getVisibilityTestResults();
+	VisibilityTestResults& vi = cam.getVisibilityTestResults();
 
 	// Iterate the visible light and get those that have lens flare
 	Array<Light*, ANKI_MAX_LIGHTS_WITH_FLARE> lights;

+ 3 - 2
src/renderer/MainRenderer.cpp

@@ -41,9 +41,10 @@ void MainRenderer::render(SceneGraph& scene)
 	ANKI_COUNTER_START_TIMER(C_MAIN_RENDERER_TIME);
 	Renderer::render(scene);
 
-	Bool alreadyDrawn = getRenderingQuality() == 1.0;
+	Bool notDrawnToDefault = 
+		getRenderingQuality() != 1.0 || getDbg().getEnabled();
 
-	if(!alreadyDrawn)
+	if(notDrawnToDefault)
 	{
 		Fbo::bindDefault(Fbo::FT_ALL, true); // Bind the window framebuffer
 

+ 1 - 1
src/renderer/Ms.cpp

@@ -111,7 +111,7 @@ void Ms::run()
 	// render all
 	r->getSceneDrawer().prepareDraw();
 	VisibilityTestResults& vi =
-		*r->getSceneGraph().getActiveCamera().getVisibilityTestResults();
+		r->getSceneGraph().getActiveCamera().getVisibilityTestResults();
 
 	for(auto it = vi.getRenderablesBegin(); it != vi.getRenderablesEnd(); ++it)
 	{

+ 2 - 1
src/renderer/Renderer.cpp

@@ -3,6 +3,7 @@
 #include "anki/scene/Camera.h"
 #include "anki/scene/SceneGraph.h"
 #include "anki/core/Counters.h"
+#include <sstream>
 
 namespace anki {
 
@@ -157,7 +158,7 @@ void Renderer::render(SceneGraph& scene_)
 
 	// Calc a few vars
 	//
-	U32 camUpdateTimestamp = cam.getFrustumable()->getFrustumableTimestamp();
+	U32 camUpdateTimestamp = cam.getFrustumComponent()->getTimestamp();
 	if(planesUpdateTimestamp < scene->getActiveCameraChangeTimestamp()
 		|| planesUpdateTimestamp < camUpdateTimestamp
 		|| planesUpdateTimestamp == 1)

+ 10 - 10
src/renderer/Sm.cpp

@@ -153,36 +153,36 @@ Sm::Shadowmap* Sm::doLight(Light& light)
 {
 	Shadowmap& sm = bestCandidate(light);
 
-	Frustumable* fr = light.getFrustumable();
+	FrustumComponent* fr = light.getFrustumComponent();
 	ANKI_ASSERT(fr != nullptr);
-	VisibilityTestResults& vi = *fr->getVisibilityTestResults();
+	VisibilityTestResults& vi = fr->getVisibilityTestResults();
 
 	//
 	// Find last update
 	//
-	U32 lastUpdate = light.getMovableTimestamp();
-	lastUpdate = std::max(lastUpdate, fr->getFrustumableTimestamp());
+	U32 lastUpdate = light.MoveComponent::getTimestamp();
+	lastUpdate = std::max(lastUpdate, fr->getTimestamp());
 
 	for(auto it = vi.getRenderablesBegin(); it != vi.getRenderablesEnd(); ++it)
 	{
 		SceneNode* node = (*it).node;
-		Frustumable* bfr = node->getFrustumable();
-		Movable* bmov = node->getMovable();
-		SpatialComponent* sp = node->getSpatial();
+		FrustumComponent* bfr = node->getFrustumComponent();
+		MoveComponent* bmov = node->getMoveComponent();
+		SpatialComponent* sp = node->getSpatialComponent();
 
 		if(bfr)
 		{
-			lastUpdate = std::max(lastUpdate, bfr->getFrustumableTimestamp());
+			lastUpdate = std::max(lastUpdate, bfr->getTimestamp());
 		}
 
 		if(bmov)
 		{
-			lastUpdate = std::max(lastUpdate, bmov->getMovableTimestamp());
+			lastUpdate = std::max(lastUpdate, bmov->getTimestamp());
 		}
 
 		if(sp)
 		{
-			lastUpdate = std::max(lastUpdate, sp->getSpatialTimestamp());
+			lastUpdate = std::max(lastUpdate, sp->getTimestamp());
 		}
 	}
 

+ 2 - 1
src/renderer/Ssao.cpp

@@ -3,6 +3,7 @@
 #include "anki/scene/Camera.h"
 #include "anki/scene/SceneGraph.h"
 #include "anki/util/Functions.h"
+#include <sstream>
 
 namespace anki {
 
@@ -218,7 +219,7 @@ void Ssao::run()
 
 	// Write common block
 	if(commonUboUpdateTimestamp < r->getPlanesUpdateTimestamp()
-		|| commonUboUpdateTimestamp < cam.getFrustumableTimestamp()
+		|| commonUboUpdateTimestamp < cam.FrustumComponent::getTimestamp()
 		|| commonUboUpdateTimestamp == 1)
 	{
 		ShaderCommonUniforms blk;

+ 2 - 1
src/renderer/Tiler.cpp

@@ -3,6 +3,7 @@
 #include "anki/resource/ShaderProgramResource.h"
 #include "anki/core/ThreadPool.h"
 #include "anki/scene/Camera.h"
+#include <sstream>
 
 // Default should be 0
 #define ANKI_TILER_ENABLE_GPU 0
@@ -302,7 +303,7 @@ void Tiler::updateTiles(Camera& cam)
 	// Issue parallel jobs
 	//
 	Array<UpdatePlanesPerspectiveCameraJob, ThreadPool::MAX_THREADS> jobs;
-	U32 camTimestamp = cam.getFrustumable()->getFrustumableTimestamp();
+	U32 camTimestamp = cam.FrustumComponent::getTimestamp();
 
 	// Do a job that transforms only the planes when:
 	// - it is the same camera as before and

+ 15 - 22
src/scene/ModelNode.cpp

@@ -12,11 +12,11 @@ namespace anki {
 //==============================================================================
 ModelPatchNodeInstance::ModelPatchNodeInstance(
 	const char* name, SceneGraph* scene, // Scene
-	const ModelPatchBase* modelPatchResource) // Self
+	ModelPatchNode* modelPatchNode_) // Self
 	:	SceneNode(name, scene),
 		MoveComponent(this),
 		SpatialComponent(this, &obb),
-		modelPatch(modelPatchResource)
+		modelPatchNode(modelPatchNode_)
 {
 	sceneNodeProtected.moveC = this;
 
@@ -24,31 +24,20 @@ ModelPatchNodeInstance::ModelPatchNodeInstance(
 	// be updated by the scene
 	sceneNodeProtected.spatialC = nullptr;
 
-	ANKI_ASSERT(modelPatch);
+	ANKI_ASSERT(modelPatchNode);
 }
 
 //==============================================================================
 void ModelPatchNodeInstance::moveUpdate()
 {
-	ANKI_ASSERT(modelPatch);
+	ANKI_ASSERT(modelPatchNode);
 
 	// Update the obb of self
-	obb = modelPatch->getBoundingShape().getTransformed(
+	obb = modelPatchNode->getModelPatchBase().getBoundingShape().getTransformed(
 		getWorldTransform());
-	spatialMarkForUpdate();
+	SpatialComponent::markForUpdate();
 
 	// If this instance is the last update the parent's collision shape
-	MoveComponent* parentM = MoveComponent::getParent();
-	ANKI_ASSERT(parentM);
-
-	ModelPatchNode* modelPatchNode = 
-#if ANKI_DEBUG
-		dynamic_cast<ModelPatchNode*>(parentM);
-#else
-		static_cast<ModelPatchNode*>(parentM);
-#endif
-	ANKI_ASSERT(modelPatchNode);
-
 	ANKI_ASSERT(modelPatchNode->instances.size() > 0);
 	if(this == modelPatchNode->instances.back())
 	{
@@ -76,7 +65,7 @@ ModelPatchNode::ModelPatchNode(
 	sceneNodeProtected.renderC = this;
 	sceneNodeProtected.spatialC = this;
 
-	RenderComponent::init(*this);
+	RenderComponent::init();
 
 	// Create the instances as ModelPatchNodeInstance
 	if(instancesCount > 1)
@@ -89,7 +78,9 @@ ModelPatchNode::ModelPatchNode(
 		for(U i = 0; i < instancesCount; i++)
 		{
 			ModelPatchNodeInstance* instance;
-			getSceneGraph().newSceneNode(instance, nullptr, modelPatch);
+			getSceneGraph().newSceneNode(instance, nullptr, this);
+
+			//MoveComponent::addChild(instance);
 
 			instance->setLocalOrigin(pos);
 			pos.x() += 2.0;
@@ -143,7 +134,7 @@ void ModelPatchNode::moveUpdate()
 		obb = modelPatch->getBoundingShape().getTransformed(
 			getWorldTransform());
 
-		spatialMarkForUpdate();
+		SpatialComponent::markForUpdate();
 	}
 	else
 	{
@@ -169,7 +160,7 @@ void ModelPatchNode::updateSpatialCs()
 		obb = obb.getCompoundShape(instances[i]->obb);
 	}
 
-	spatialMarkForUpdate();
+	SpatialComponent::markForUpdate();
 }
 
 //==============================================================================
@@ -194,7 +185,9 @@ ModelNode::ModelNode(
 	for(const ModelPatchBase* patch : model->getModelPatches())
 	{
 		ModelPatchNode* mpn;
-		getSceneGraph().newSceneNode(mpn, nullptr, this, patch, instances);
+		getSceneGraph().newSceneNode(mpn, nullptr, patch, instances);
+
+		MoveComponent::addChild(mpn);
 
 		patches.push_back(mpn);
 		++i;

+ 2 - 2
src/scene/Octree.cpp

@@ -1,12 +1,12 @@
 #include "anki/scene/Octree.h"
 #include "anki/scene/SpatialComponent.h"
-#include "anki/scene/Frustumable.h"
+#include "anki/scene/FrustumComponent.h"
 #include "anki/scene/Light.h"
 #include "anki/scene/Sector.h"
 #include "anki/scene/SceneGraph.h"
 #include "anki/util/Exception.h"
 #include "anki/core/Logger.h"
-#include "anki/scene/Renderable.h"
+#include "anki/scene/RenderComponent.h"
 
 namespace anki {
 

+ 38 - 47
src/scene/ParticleEmitter.cpp

@@ -42,14 +42,13 @@ Vec3 getRandom(const Vec3& initial, const Vec3& deviation)
 
 //==============================================================================
 ParticleBase::ParticleBase(
-	const char* name, SceneGraph* scene, SceneNode* parent, // SceneNode
-	U32 movableFlags, // Movable
+	const char* name, SceneGraph* scene, // SceneNode
 	ParticleType type_)
-	:	SceneNode(name, scene, parent),
-		Movable(movableFlags, this),
+	:	SceneNode(name, scene),
+		MoveComponent(this),
 		type(type_)
 {
-	sceneNodeProtected.movable = this;
+	sceneNodeProtected.moveC = this;
 }
 
 //==============================================================================
@@ -75,9 +74,8 @@ void ParticleBase::revive(const ParticleEmitter& pe,
 
 //==============================================================================
 ParticleSimple::ParticleSimple(
-	const char* name, SceneGraph* scene, SceneNode* parent, // SceneNode
-	U32 movableFlags) // Movable
-	: ParticleBase(name, scene, parent, movableFlags, PT_SIMPLE)
+	const char* name, SceneGraph* scene)
+	: ParticleBase(name, scene, PT_SIMPLE)
 {}
 
 //==============================================================================
@@ -131,14 +129,13 @@ void ParticleSimple::revive(const ParticleEmitter& pe,
 
 //==============================================================================
 Particle::Particle(
-	const char* name, SceneGraph* scene, SceneNode* parent, // SceneNode
-	U32 movableFlags, // Movable
+	const char* name, SceneGraph* scene, // SceneNode
 	// RigidBody
 	PhysWorld* masterContainer, const Initializer& init)
-	:	ParticleBase(name, scene, parent, movableFlags, PT_PHYSICS),
+	:	ParticleBase(name, scene, PT_PHYSICS),
 		RigidBody(masterContainer, init, this)
 {
-	sceneNodeProtected.rigidBody = this;
+	sceneNodeProtected.rigidBodyC = this;
 }
 
 //==============================================================================
@@ -216,19 +213,17 @@ void Particle::revive(const ParticleEmitter& pe,
 
 //==============================================================================
 ParticleEmitter::ParticleEmitter(
-	const char* name, SceneGraph* scene, SceneNode* parent,
-	U32 movableFlags,
+	const char* name, SceneGraph* scene,
 	const char* filename)
-	:	SceneNode(name, scene, parent),
-		SpatialComponent(&aabb, getSceneAllocator()),
-		Movable(movableFlags, this),
-		Renderable(getSceneAllocator()),
+	:	SceneNode(name, scene),
+		SpatialComponent(this, &aabb),
+		MoveComponent(this),
+		RenderComponent(this),
 		particles(getSceneAllocator())
 {
-	sceneNodeProtected.spatial = this;
-	sceneNodeProtected.movable = this;
-	sceneNodeProtected.renderable = this;
-	sceneNodeProtected.renderable = this;
+	sceneNodeProtected.spatialC = this;
+	sceneNodeProtected.moveC = this;
+	sceneNodeProtected.renderC = this;
 
 	// Load resource
 	particleEmitterResource.load(filename);
@@ -250,15 +245,15 @@ ParticleEmitter::ParticleEmitter(
 
 	timeLeftForNextEmission = 0.0;
 	instancesCount = particles.size();
-	Renderable::init(*this);
+	RenderComponent::init();
 
 	// Find the "alpha" material variable
-	for(auto it = Renderable::getVariablesBegin();
-		it != Renderable::getVariablesEnd(); ++it)
+	for(auto it = RenderComponent::getVariablesBegin();
+		it != RenderComponent::getVariablesEnd(); ++it)
 	{
 		if((*it)->getName() == "alpha")
 		{
-			alphaRenderableVar = *it;
+			alphaRenderComponentVar = *it;
 		}
 	}
 }
@@ -271,24 +266,24 @@ ParticleEmitter::~ParticleEmitter()
 		getSceneGraph().deleteSceneNode(part);
 	}
 
-	ANKI_DELETE(collShape, getSceneAllocator());
+	getSceneAllocator().deleteInstance(collShape);
 }
 
 //==============================================================================
-const ModelPatchBase& ParticleEmitter::getRenderableModelPatchBase()
+const ModelPatchBase& ParticleEmitter::getModelPatchBase()
 {
 	return *particleEmitterResource->getModel().getModelPatches()[0];
 }
 
 //==============================================================================
-const Material& ParticleEmitter::getRenderableMaterial()
+const Material& ParticleEmitter::getMaterial()
 {
 	return
 		particleEmitterResource->getModel().getModelPatches()[0]->getMaterial();
 }
 
 //==============================================================================
-void ParticleEmitter::movableUpdate()
+void ParticleEmitter::moveUpdate()
 {
 	identityRotation =
 		getWorldTransform().getRotation() == Mat3::getIdentity();
@@ -297,7 +292,7 @@ void ParticleEmitter::movableUpdate()
 //==============================================================================
 void ParticleEmitter::createParticlesSimulation(SceneGraph* scene)
 {
-	collShape = ANKI_NEW(btSphereShape, getSceneAllocator(), particle.size);
+	collShape = getSceneAllocator().newInstance<btSphereShape>(particle.size);
 
 	RigidBody::Initializer binit;
 	binit.shape = collShape;
@@ -312,9 +307,7 @@ void ParticleEmitter::createParticlesSimulation(SceneGraph* scene)
 
 		Particle* part;
 		getSceneGraph().newSceneNode(part,
-			(getName() + std::to_string(i)).c_str(), nullptr,
-			Movable::MF_NONE,
-			&scene->getPhysics(), binit);
+			nullptr, &scene->getPhysics(), binit);
 
 		part->size = getRandom(particle.size, particle.sizeDeviation);
 		part->alpha = getRandom(particle.alpha, particle.alphaDeviation);
@@ -331,9 +324,7 @@ void ParticleEmitter::createParticlesSimpleSimulation(SceneGraph* scene)
 	{
 		ParticleSimple* part;
 		
-		getSceneGraph().newSceneNode(part,
-			(getName() + std::to_string(i)).c_str(), nullptr,
-			Movable::MF_NONE);
+		getSceneGraph().newSceneNode(part, nullptr);
 
 		part->size = getRandom(particle.size, particle.sizeDeviation);
 		part->alpha = getRandom(particle.alpha, particle.alphaDeviation);
@@ -345,8 +336,6 @@ void ParticleEmitter::createParticlesSimpleSimulation(SceneGraph* scene)
 //==============================================================================
 void ParticleEmitter::frameUpdate(F32 prevUpdateTime, F32 crntTime, I frame)
 {
-	SceneNode::frameUpdate(prevUpdateTime, crntTime, frame);
-
 	// - Deactivate the dead particles
 	// - Calc the AABB
 	// - Calc the instancing stuff
@@ -355,8 +344,8 @@ void ParticleEmitter::frameUpdate(F32 prevUpdateTime, F32 crntTime, I frame)
 	Vec3 aabbmax(-std::numeric_limits<F32>::max());
 
 	// Create the transformations vector
-	instancingTransformations = ANKI_NEW(SceneFrameVector<Transform>,
-		getSceneFrameAllocator(), getSceneFrameAllocator());
+	instancingTransformations = getSceneFrameAllocator().
+		newInstance<SceneFrameVector<Transform>>(getSceneFrameAllocator());
 
 	instancingTransformations->reserve(particles.size());
 
@@ -383,7 +372,8 @@ void ParticleEmitter::frameUpdate(F32 prevUpdateTime, F32 crntTime, I frame)
 			p->simulate(*this, prevUpdateTime, crntTime);
 
 			// An alive
-			const Vec3& origin = p->Movable::getWorldTransform().getOrigin();
+			const Vec3& origin = 
+				p->MoveComponent::getWorldTransform().getOrigin();
 
 			for(U i = 0; i < 3; i++)
 			{
@@ -394,7 +384,7 @@ void ParticleEmitter::frameUpdate(F32 prevUpdateTime, F32 crntTime, I frame)
 			F32 lifePercent = (crntTime - p->getTimeOfBirth())
 				/ (p->getTimeOfDeath() - p->getTimeOfBirth());
 
-			Transform trf = p->Movable::getWorldTransform();
+			Transform trf = p->MoveComponent::getWorldTransform();
 			// XXX set a flag for scale
 			trf.setScale(
 				p->size + (lifePercent * particle.sizeAnimation));
@@ -402,7 +392,7 @@ void ParticleEmitter::frameUpdate(F32 prevUpdateTime, F32 crntTime, I frame)
 			instancingTransformations->push_back(trf);
 
 			// Set alpha
-			if(alphaRenderableVar)
+			if(alphaRenderComponentVar)
 			{
 				alpha.push_back(
 					sin((lifePercent) * getPi<F32>())
@@ -420,11 +410,12 @@ void ParticleEmitter::frameUpdate(F32 prevUpdateTime, F32 crntTime, I frame)
 	{
 		aabb = Aabb(Vec3(0.0), Vec3(0.01));
 	}
-	spatialMarkForUpdate();
+	SpatialComponent::markForUpdate();
 
-	if(alphaRenderableVar)
+	if(alphaRenderComponentVar)
 	{
-		alphaRenderableVar->setValues(&alpha[0], alpha.size());
+		alphaRenderComponentVar->setValues(
+			&alpha[0], alpha.size(), getSceneAllocator());
 	}
 
 	//

+ 5 - 6
src/scene/Path.cpp

@@ -4,16 +4,15 @@ namespace anki {
 
 //==============================================================================
 Path::Path(
-	const char* name, SceneGraph* scene, SceneNode* parent,
-	U32 movableFlags,
+	const char* name, SceneGraph* scene, 
 	const char* filename)
-	:	SceneNode(name, scene, parent), 
-		Movable(movableFlags, this),
+	:	SceneNode(name, scene), 
+		MoveComponent(this),
 		points(getSceneAllocator())
 {
 	// Set scene node related flags
-	sceneNodeProtected.movable = this;
-	sceneNodeProtected.path = this;
+	sceneNodeProtected.moveC = this;
+	sceneNodeProtected.pathC = this;
 
 	// XXX Fix the dummy load 
 	Vector<std::pair<Vec3, Quat>> tmp = {

+ 9 - 6
src/scene/RenderComponent.cpp

@@ -116,14 +116,17 @@ void RenderComponent::init()
 
 	// Instancing sanity checks
 	U32 instancesCount = getRenderInstancesCount();
-	iterateVariables([&](RenderComponentVariable& var)
+	if(instancesCount > 1)
 	{
-		if(var.getArraySize() < instancesCount)
+		iterateVariables([&](RenderComponentVariable& var)
 		{
-			throw ANKI_EXCEPTION("The renderable needs more instances that "
-				"the shader program can handle");
-		}
-	});
+			if(var.getArraySize() > 1 && instancesCount > var.getArraySize())
+			{
+				throw ANKI_EXCEPTION("The renderable needs more instances "
+					"that the shader program can handle");
+			}
+		});
+	}
 }
 
 }  // end namespace anki

+ 8 - 15
src/scene/SceneGraph.cpp

@@ -14,10 +14,9 @@ namespace anki {
 //==============================================================================
 
 //==============================================================================
-struct UpdateMovablesJob: ThreadJob
+struct UpdateMoveComponentsJob: ThreadJob
 {
 	SceneGraph* scene = nullptr;
-	U32 movablesCount;
 
 	void operator()(U threadId, U threadsCount)
 	{
@@ -28,7 +27,7 @@ struct UpdateMovablesJob: ThreadJob
 
 		scene->iterateSceneNodes(start, end, [](SceneNode& sn)
 		{
-			Movable* m = sn.getMovable();
+			MoveComponent* m = sn.getMoveComponent();
 			if(m)
 			{
 				m->update();
@@ -44,26 +43,21 @@ static void updateSceneNode(SceneNode& sn, F32 prevUpdateTime,
 	sn.frameUpdate(prevUpdateTime, crntTime, getGlobTimestamp());
 
 	// Do some spatial stuff
-	SpatialComponent* sp = sn.getSpatial();
+	SpatialComponent* sp = sn.getSpatialComponent();
 	if(sp)
 	{
-		if(sp->getSpatialTimestamp() >= getGlobTimestamp())
-		{
-			sp->update();
-			//sectorGroup.placeSceneNode(&sn);
-		}
 		sp->resetFrame();
 	}
 
 	// Do some frustumable stuff
-	Frustumable* fr = sn.getFrustumable();
+	FrustumComponent* fr = sn.getFrustumComponent();
 	if(fr)
 	{
 		fr->resetFrame();
 	}
 
 	// Do some renderable stuff
-	Renderable* r = sn.getRenderable();
+	RenderComponent* r = sn.getRenderComponent();
 	if(r)
 	{
 		r->resetFrame();
@@ -249,7 +243,7 @@ void SceneGraph::update(F32 prevUpdateTime, F32 crntTime, Renderer& renderer)
 	// First do the movable updates
 	for(SceneNode* n : nodes)
 	{
-		Movable* m = n->getMovable();
+		MoveComponent* m = n->getMoveComponent();
 
 		if(m)
 		{
@@ -257,7 +251,7 @@ void SceneGraph::update(F32 prevUpdateTime, F32 crntTime, Renderer& renderer)
 		}
 	}
 #else
-	UpdateMovablesJob jobs[ThreadPool::MAX_THREADS];
+	UpdateMoveComponentsJob jobs[ThreadPool::MAX_THREADS];
 
 	for(U i = 0; i < threadPool.getThreadsCount(); i++)
 	{
@@ -336,8 +330,7 @@ void SceneGraph::load(const char* filename)
 			}
 
 			ModelNode* node;
-			newSceneNode(node, name.c_str(), nullptr,
-				Movable::MF_NONE, el.getText(), instancesCount);
+			newSceneNode(node, name.c_str(), el.getText(), instancesCount);
 
 			// <transform>
 			el = mdlNodeEl.getChildElement("transform");

+ 22 - 8
src/scene/Sector.cpp

@@ -1,10 +1,10 @@
 #include "anki/scene/Sector.h"
 #include "anki/scene/SpatialComponent.h"
 #include "anki/scene/SceneNode.h"
-#include "anki/scene/Renderable.h"
+#include "anki/scene/RenderComponent.h"
 #include "anki/scene/Light.h"
 #include "anki/scene/Visibility.h"
-#include "anki/scene/Frustumable.h"
+#include "anki/scene/FrustumComponent.h"
 #include "anki/scene/SceneGraph.h"
 #include "anki/core/Logger.h"
 #include "anki/renderer/Renderer.h"
@@ -12,8 +12,6 @@
 
 namespace anki {
 
-#if 0
-
 //==============================================================================
 // Portal                                                                      =
 //==============================================================================
@@ -31,7 +29,7 @@ Portal::Portal()
 
 //==============================================================================
 Sector::Sector(SectorGroup* group_, const Aabb& box)
-	: group(group_), octree(this, box, 3),
+	:	group(group_),
 		portals(group->getSceneGraph().getAllocator())
 {
 	// Reserve some space for portals
@@ -41,14 +39,18 @@ Sector::Sector(SectorGroup* group_, const Aabb& box)
 //==============================================================================
 Bool Sector::placeSceneNode(SceneNode* sn)
 {
+#if 0
 	// XXX Optimize
 
-	if(!sn->getSpatial()->getAabb().collide(octree.getRoot().getAabb()))
+	SpatialComponent* sp = sn->getSpatialComponent();
+	ANKI_ASSERT(sp);
+	if(!sp->getAabb().collide(octree.getRoot().getAabb()))
 	{
 		return false;
 	}
 
 	octree.placeSceneNode(sn);
+#endif
 	return true;
 }
 
@@ -90,6 +92,7 @@ SectorGroup::SectorGroup(SceneGraph* scene_)
 //==============================================================================
 SectorGroup::~SectorGroup()
 {
+#if 0
 	for(Sector* sector : sectors)
 	{
 		ANKI_DELETE(sector, scene->getAllocator());
@@ -99,20 +102,25 @@ SectorGroup::~SectorGroup()
 	{
 		ANKI_DELETE(portal, scene->getAllocator());
 	}
+#endif
 }
 
 //==============================================================================
 Sector* SectorGroup::createNewSector(const Aabb& aabb)
 {
+#if 0
 	Sector* out = ANKI_NEW(Sector, scene->getAllocator(), this, aabb);
 	sectors.push_back(out);
 	return out;
+#endif
+	return nullptr;
 }
 
 //==============================================================================
 Portal* SectorGroup::createNewPortal(Sector* a, Sector* b, 
 	const Obb& collisionShape)
 {
+#if 0
 	ANKI_ASSERT(a && b);
 	Portal* out = ANKI_NEW_0(Portal, scene->getAllocator());
 
@@ -126,11 +134,14 @@ Portal* SectorGroup::createNewPortal(Sector* a, Sector* b,
 	b->addNewPortal(out);
 
 	return out;
+#endif
+	return nullptr;
 }
 
 //==============================================================================
 void SectorGroup::placeSceneNode(SceneNode* sn)
 {
+#if 0
 	ANKI_ASSERT(sn != nullptr);
 	SpatialComponent* sp = sn->getSpatial();
 	ANKI_ASSERT(sp);
@@ -189,12 +200,14 @@ void SectorGroup::placeSceneNode(SceneNode* sn)
 	{
 		ANKI_LOGW("Spatial outside all sectors");
 	}
+#endif
 }
 
 //==============================================================================
 void SectorGroup::doVisibilityTests(SceneNode& sn, VisibilityTest test,
 	Renderer* r)
 {
+#if 0
 	// Set all sectors to not visible
 	for(Sector* sector : sectors)
 	{
@@ -202,12 +215,14 @@ void SectorGroup::doVisibilityTests(SceneNode& sn, VisibilityTest test,
 	}
 
 	doVisibilityTestsInternal(sn, test, r, VB_CAMERA);
+#endif
 }
 
 //==============================================================================
 void SectorGroup::doVisibilityTestsInternal(SceneNode& sn, VisibilityTest test,
 	Renderer* r, VisibleBy visibleBy)
 {
+#if 0
 	Frustumable* fr = sn.getFrustumable();
 	ANKI_ASSERT(fr != nullptr && "sn should be frustumable");
 	fr->visible = nullptr;
@@ -403,8 +418,7 @@ void SectorGroup::doVisibilityTestsInternal(SceneNode& sn, VisibilityTest test,
 				nullptr, VB_LIGHT);
 		}
 	}
-}
-
 #endif
+}
 
 } // end namespace anki

+ 14 - 15
src/scene/StaticGeometryNode.cpp

@@ -9,8 +9,8 @@ namespace anki {
 
 //==============================================================================
 StaticGeometrySpatial::StaticGeometrySpatial(const Obb* obb,
-	const SceneAllocator<U8>& alloc)
-	: SpatialComponent(obb, alloc)
+	SceneNode& node)
+	: SpatialComponent(&node, obb)
 {}
 
 //==============================================================================
@@ -20,16 +20,16 @@ StaticGeometrySpatial::StaticGeometrySpatial(const Obb* obb,
 //==============================================================================
 StaticGeometryPatchNode::StaticGeometryPatchNode(
 	const char* name, SceneGraph* scene, const ModelPatchBase* modelPatch_)
-	:	SceneNode(name, scene, nullptr),
-		SpatialComponent(&modelPatch_->getBoundingShape(), getSceneAllocator()),
-		Renderable(getSceneAllocator()),
+	:	SceneNode(name, scene),
+		SpatialComponent(this, &modelPatch_->getBoundingShape()),
+		RenderComponent(this),
 		modelPatch(modelPatch_)
 {
-	sceneNodeProtected.spatial = this;
-	sceneNodeProtected.renderable = this;
+	sceneNodeProtected.spatialC = this;
+	sceneNodeProtected.renderC = this;
 
 	ANKI_ASSERT(modelPatch);
-	Renderable::init(*this);
+	RenderComponent::init();
 
 	// For all submeshes create a StaticGeometrySp[atial
 	if(modelPatch->getSubMeshesCount() > 1)
@@ -37,8 +37,8 @@ StaticGeometryPatchNode::StaticGeometryPatchNode(
 		for(U i = 0; i < modelPatch->getSubMeshesCount(); i++)
 		{
 			StaticGeometrySpatial* spatial =
-				ANKI_NEW(StaticGeometrySpatial, getSceneAllocator(),
-				&modelPatch->getBoundingShapeSub(i), getSceneAllocator());
+				getSceneAllocator().newInstance<StaticGeometrySpatial>(
+				&modelPatch->getBoundingShapeSub(i), *this);
 
 			SpatialComponent::addChild(spatial);
 		}
@@ -48,11 +48,10 @@ StaticGeometryPatchNode::StaticGeometryPatchNode(
 //==============================================================================
 StaticGeometryPatchNode::~StaticGeometryPatchNode()
 {
-	/*for(SpatialComponent* spatial : spatialProtected.subSpatials)
+	visitSubSpatials([&](SpatialComponent& spatial)
 	{
-		ANKI_DELETE(spatial, getSceneAllocator());
-	}*/
-	// XXX
+		getSceneAllocator().deleteInstance(&spatial);
+	});
 }
 
 //==============================================================================
@@ -62,7 +61,7 @@ StaticGeometryPatchNode::~StaticGeometryPatchNode()
 //==============================================================================
 StaticGeometryNode::StaticGeometryNode(
 	const char* name, SceneGraph* scene, const char* filename)
-	: SceneNode(name, scene, nullptr), patches(getSceneAllocator())
+	: SceneNode(name, scene), patches(getSceneAllocator())
 {
 	model.load(filename);
 

+ 15 - 15
src/scene/Visibility.cpp

@@ -1,6 +1,6 @@
 #include "anki/scene/Visibility.h"
 #include "anki/scene/SceneGraph.h"
-#include "anki/scene/Frustumable.h"
+#include "anki/scene/FrustumComponent.h"
 #include "anki/scene/Light.h"
 #include "anki/renderer/Renderer.h"
 #include "anki/core/Logger.h"
@@ -45,7 +45,7 @@ struct VisibilityTestJob: ThreadJob
 
 	/// Handle sub spatials
 	Bool handleSubspatials(
-		const Frustumable& fr,
+		const FrustumComponent& fr,
 		SpatialComponent& sp,
 		U32*& subSpatialIndices,
 		U32& subSpatialIndicesCount)
@@ -74,7 +74,7 @@ struct VisibilityTestJob: ThreadJob
 
 			// Sort them
 			SortSubspatialsFunctor functor;
-			functor.origin = fr.getFrustumableOrigin();
+			functor.origin = fr.getFrustumOrigin();
 			functor.sp = &sp;
 			std::sort(subSpatialIndices, 
 				subSpatialIndices + subSpatialIndicesCount,
@@ -96,12 +96,12 @@ struct VisibilityTestJob: ThreadJob
 
 		visible = frameAlloc.newInstance<VisibilityTestResults>(frameAlloc);
 
-		Frustumable* frustumable = frustumableSn->getFrustumable();
+		FrustumComponent* frustumable = frustumableSn->getFrustumComponent();
 		ANKI_ASSERT(frustumable);
 
 		scene->iterateSceneNodes(start, end, [&](SceneNode& node)
 		{
-			Frustumable* fr = node.getFrustumable();
+			FrustumComponent* fr = node.getFrustumComponent();
 
 			// Skip if it is the same
 			if(ANKI_UNLIKELY(frustumable == fr))
@@ -109,7 +109,7 @@ struct VisibilityTestJob: ThreadJob
 				return;
 			}
 
-			SpatialComponent* sp = node.getSpatial();
+			SpatialComponent* sp = node.getSpatialComponent();
 			if(!sp)
 			{
 				return;
@@ -130,7 +130,7 @@ struct VisibilityTestJob: ThreadJob
 			}
 
 			// renderable
-			Renderable* r = node.getRenderable();
+			RenderComponent* r = node.getRenderComponent();
 			if(r)
 			{
 				visible->renderables.push_back(VisibleNode(
@@ -161,8 +161,8 @@ struct VisibilityTestJob: ThreadJob
 	/// Test an individual light
 	void testLight(SceneNode& lightSn)
 	{
-		ANKI_ASSERT(lightSn.getFrustumable() != nullptr);
-		Frustumable& ref = *lightSn.getFrustumable();
+		ANKI_ASSERT(lightSn.getFrustumComponent() != nullptr);
+		FrustumComponent& ref = *lightSn.getFrustumComponent();
 
 		// Allocate new visibles
 		VisibilityTestResults* lvisible = 
@@ -172,14 +172,14 @@ struct VisibilityTestJob: ThreadJob
 
 		scene->iterateSceneNodes([&](SceneNode& node)
 		{
-			Frustumable* fr = node.getFrustumable();
+			FrustumComponent* fr = node.getFrustumComponent();
 			// Wont check the same
 			if(ANKI_UNLIKELY(&ref == fr))
 			{
 				return;
 			}
 
-			SpatialComponent* sp = node.getSpatial();
+			SpatialComponent* sp = node.getSpatialComponent();
 			if(!sp)
 			{
 				return;
@@ -201,7 +201,7 @@ struct VisibilityTestJob: ThreadJob
 
 			sp->enableBits(SpatialComponent::SF_VISIBLE_LIGHT);
 
-			Renderable* r = node.getRenderable();
+			RenderComponent* r = node.getRenderComponent();
 			if(r)
 			{
 				lvisible->renderables.push_back(VisibleNode(
@@ -215,7 +215,7 @@ struct VisibilityTestJob: ThreadJob
 void doVisibilityTests(SceneNode& fsn, SceneGraph& scene, 
 	Renderer& r)
 {
-	Frustumable* fr = fsn.getFrustumable();
+	FrustumComponent* fr = fsn.getFrustumComponent();
 	ANKI_ASSERT(fr);
 
 	//
@@ -291,7 +291,7 @@ void doVisibilityTests(SceneNode& fsn, SceneGraph& scene,
 	DistanceSortJob dsjob;
 	dsjob.nodes = visible->lights.begin();
 	dsjob.nodesCount = visible->lights.size();
-	dsjob.origin = fr->getFrustumableOrigin();
+	dsjob.origin = fr->getFrustumOrigin();
 	threadPool.assignNewJob(0, &dsjob);
 
 	// The rest of the jobs are dummy
@@ -303,7 +303,7 @@ void doVisibilityTests(SceneNode& fsn, SceneGraph& scene,
 
 	// Sort the renderables in the main thread
 	DistanceSortFunctor dsfunc;
-	dsfunc.origin = fr->getFrustumableOrigin();
+	dsfunc.origin = fr->getFrustumOrigin();
 	std::sort(visible->renderables.begin(), visible->renderables.end(), dsfunc);
 
 	threadPool.waitForAllJobsToFinish();

+ 3 - 1
src/util/Memory.cpp

@@ -167,7 +167,8 @@ void* mallocAligned(PtrSize size, PtrSize alignmentBytes)
 {
 #if ANKI_POSIX
 	void* out;
-	int err = posix_memalign(&out, alignmentBytes, size);
+	int err = posix_memalign(
+		&out, getAlignedRoundUp(alignmentBytes, sizeof(void*)), size);
 
 	if(!err)
 	{
@@ -177,6 +178,7 @@ void* mallocAligned(PtrSize size, PtrSize alignmentBytes)
 	}
 	else
 	{
+		throw ANKI_EXCEPTION("mallocAligned() failed");
 		return nullptr;
 	}
 #else

+ 29 - 29
testapp/Main.cpp

@@ -29,7 +29,7 @@
 #include "anki/core/NativeWindow.h"
 #include "anki/Scene.h"
 #include "anki/event/LightEvent.h"
-#include "anki/event/MovableEvent.h"
+#include "anki/event/MoveEvent.h"
 #include "anki/core/Counters.h"
 
 using namespace anki;
@@ -63,7 +63,7 @@ void initPhysics()
 
 	new RigidBody(&SceneGraphSingleton::get().getPhysics(), init);
 
-#if 1
+#if 0
 	btCollisionShape* colShape = new btBoxShape(
 	    btVector3(1, 1, 1));
 
@@ -95,7 +95,7 @@ void initPhysics()
 
 				ModelNode* mnode = new ModelNode(
 					name.c_str(), &SceneGraphSingleton::get(), nullptr,
-					Movable::MF_NONE, "models/crate0/crate0.mdl");
+					MoveComponent::MF_NONE, "models/crate0/crate0.mdl");
 
 				init.movable = mnode;
 				ANKI_ASSERT(init.movable);
@@ -128,8 +128,7 @@ void init()
 #endif
 
 	// camera
-	scene.newSceneNode(cam, "main-camera", nullptr,
-		Movable::MF_NONE);
+	scene.newSceneNode(cam, "main-camera");
 	const F32 ang = 45.0;
 	cam->setAll(
 		MainRendererSingleton::get().getAspectRatio() * toRad(ang),
@@ -149,8 +148,7 @@ void init()
 			std::string name = "plight" + std::to_string(i) + std::to_string(j);
 
 			PointLight* point;
-			scene.newSceneNode(point, name.c_str(), nullptr,
-				Movable::MF_NONE);
+			scene.newSceneNode(point, name.c_str());
 			point->setRadius(0.5);
 			point->setDiffuseColor(Vec4(randFloat(6.0) - 2.0, 
 				randFloat(6.0) - 2.0, randFloat(6.0) - 2.0, 0.0));
@@ -168,7 +166,7 @@ void init()
 
 #if 1
 	SpotLight* spot;
-	scene.newSceneNode(spot, "spot0", nullptr, Movable::MF_NONE);
+	scene.newSceneNode(spot, "spot0");
 	spot->setOuterAngle(toRad(45.0));
 	spot->setInnerAngle(toRad(15.0));
 	spot->setLocalTransform(Transform(Vec3(8.27936, 5.86285, 1.85526),
@@ -179,7 +177,7 @@ void init()
 	spot->setShadowEnabled(true);
 
 
-	scene.newSceneNode(spot, "spot1", nullptr, Movable::MF_NONE);
+	scene.newSceneNode(spot, "spot1");
 	spot->setOuterAngle(toRad(45.0));
 	spot->setInnerAngle(toRad(15.0));
 	spot->setLocalTransform(Transform(Vec3(5.3, 4.3, 3.0),
@@ -202,9 +200,10 @@ void init()
 		Vec3 lightPos = vaseLightPos[i];
 
 		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);
+		scene.newSceneNode(point, ("vase_plight" + std::to_string(i)).c_str());
+
+		point->loadLensFlare("textures/lens_flare/flares0.ankitex");
+
 		point->setRadius(2.0);
 		point->setLocalOrigin(lightPos);
 		point->setDiffuseColor(Vec4(3.0, 0.2, 0.0, 0.0));
@@ -220,35 +219,34 @@ void init()
 		scene.getEventManager().newEvent(event, 0.0, 0.8, point, eventData);
 		event->enableBits(Event::EF_REANIMATE);
 
-		MovableEventData moveData;
+		MoveEventData moveData;
 		moveData.posMin = Vec3(-0.5, 0.0, -0.5);
 		moveData.posMax = Vec3(0.5, 0.0, 0.5);
-		MovableEvent* mevent;
+		MoveEvent* mevent;
 		scene.getEventManager().newEvent(mevent, 0.0, 2.0, point, moveData);
 		mevent->enableBits(Event::EF_REANIMATE);
 
 		ParticleEmitter* pe;
 		scene.newSceneNode(pe,
-			("pe" + std::to_string(i)).c_str(), nullptr,
-			Movable::MF_NONE, "particles/smoke.ankipart");
+			("pe" + std::to_string(i)).c_str(),
+			"particles/smoke.ankipart");
 		pe->setLocalOrigin(lightPos);
 
-		scene.newSceneNode(pe, ("pef" + std::to_string(i)).c_str(), nullptr,
-			Movable::MF_NONE, "particles/fire.ankipart");
+		scene.newSceneNode(pe, ("pef" + std::to_string(i)).c_str(), 
+			"particles/fire.ankipart");
 		pe->setLocalOrigin(lightPos);
 	}
 #endif
 
 #if 1
 	// horse
-	scene.newSceneNode(horse, "horse", nullptr,
-		Movable::MF_NONE, "models/horse/horse.ankimdl");
+	scene.newSceneNode(horse, "horse", "models/horse/horse.ankimdl");
 	horse->setLocalTransform(Transform(Vec3(-2, 0, 0), Mat3::getIdentity(),
 		0.7));
 
 	// barrel
 	/*ModelNode* redBarrel = new ModelNode(
-		"red_barrel", &scene, nullptr, Movable::MF_NONE, 
+		"red_barrel", &scene, nullptr, MoveComponent::MF_NONE, 
 		"models/red_barrel/red_barrel.mdl");
 	redBarrel->setLocalTransform(Transform(Vec3(+2, 0, 0), Mat3::getIdentity(),
 		0.7));*/
@@ -267,6 +265,7 @@ void init()
 	//initPhysics();
 
 	// Sectors
+#if 0
 	SectorGroup& sgroup = scene.getSectorGroup();
 
 	Sector* sectorA = sgroup.createNewSector(
@@ -281,9 +280,10 @@ void init()
 
 	sgroup.createNewPortal(sectorA, sectorC, Obb(Vec3(-1.1, 2.0, -11.0),
 		Mat3::getIdentity(), Vec3(1.3, 1.8, 0.5)));
+#endif
 
 	// Path
-	/*Path* path = new Path("todo", "path", &scene, Movable::MF_NONE, nullptr);
+	/*Path* path = new Path("todo", "path", &scene, MoveComponent::MF_NONE, nullptr);
 	(void)path;
 
 	const F32 distPerSec = 2.0;
@@ -326,7 +326,7 @@ void mainLoopExtra()
 	F32 mouseSensivity = 9.0;
 
 	// move the camera
-	static Movable* mover = SceneGraphSingleton::get().getActiveCamera().getMovable();
+	static MoveComponent* mover = SceneGraphSingleton::get().getActiveCamera().getMoveComponent();
 	Input& in = InputSingleton::get();
 
 	if(in.getKey(KC_1))
@@ -335,27 +335,27 @@ void mainLoopExtra()
 	}
 	if(in.getKey(KC_2))
 	{
-		mover = SceneGraphSingleton::get().findSceneNode("horse").getMovable();
+		mover = SceneGraphSingleton::get().findSceneNode("horse").getMoveComponent();
 	}
 	if(in.getKey(KC_3))
 	{
-		mover = SceneGraphSingleton::get().findSceneNode("spot0").getMovable();
+		mover = SceneGraphSingleton::get().findSceneNode("spot0").getMoveComponent();
 	}
 	if(in.getKey(KC_4))
 	{
-		mover = SceneGraphSingleton::get().findSceneNode("spot1").getMovable();
+		mover = SceneGraphSingleton::get().findSceneNode("spot1").getMoveComponent();
 	}
 	if(in.getKey(KC_5))
 	{
-		mover = SceneGraphSingleton::get().findSceneNode("pe").getMovable();
+		mover = SceneGraphSingleton::get().findSceneNode("pe").getMoveComponent();
 	}
 	if(in.getKey(KC_6))
 	{
-		mover = SceneGraphSingleton::get().findSceneNode("vase_plight0").getMovable();
+		mover = SceneGraphSingleton::get().findSceneNode("vase_plight0").getMoveComponent();
 	}
 	if(in.getKey(KC_7))
 	{
-		mover = SceneGraphSingleton::get().findSceneNode("red_barrel").getMovable();
+		mover = SceneGraphSingleton::get().findSceneNode("red_barrel").getMoveComponent();
 	}
 
 	if(in.getKey(KC_L) == 1)