Browse Source

Fixing a problem with order of updates in scene and made a refactoring along the way

Panagiotis Christopoulos Charitos 11 years ago
parent
commit
21ea42fa4d

+ 3 - 18
include/anki/scene/Camera.h

@@ -29,17 +29,12 @@ public:
 		COUNT
 		COUNT
 	};
 	};
 
 
-	/// @name Constructors/Destructor
-	/// @{
 	Camera(
 	Camera(
 		const CString& name, SceneGraph* scene, // SceneNode
 		const CString& name, SceneGraph* scene, // SceneNode
 		Type type, Frustum* frustum); // Self
 		Type type, Frustum* frustum); // Self
 
 
 	virtual ~Camera();
 	virtual ~Camera();
-	/// @}
 
 
-	/// @name Accessors
-	/// @{
 	Type getCameraType() const
 	Type getCameraType() const
 	{
 	{
 		return m_type;
 		return m_type;
@@ -56,18 +51,11 @@ public:
 	{
 	{
 		return getFrustum().getFar();
 		return getFrustum().getFar();
 	}
 	}
-	/// @}
 
 
-	/// @name SceneNode virtuals
+	/// @name MoveComponent virtuals
 	/// @{
 	/// @{
-	void componentUpdated(SceneComponent& comp, 
-		SceneComponent::UpdateType) override
-	{
-		if(comp.getType() == MoveComponent::getClassType())
-		{
-			moveUpdate(comp.downCast<MoveComponent>());
-		}
-	}
+	void onMoveComponentUpdate(
+		SceneNode& node, F32 prevTime, F32 crntTime) override;
 	/// @}
 	/// @}
 
 
 	/// @name SpatialComponent virtuals
 	/// @name SpatialComponent virtuals
@@ -84,9 +72,6 @@ protected:
 	/// Called when something changes in the frustum
 	/// Called when something changes in the frustum
 	void frustumUpdate();
 	void frustumUpdate();
 
 
-	/// Called when the world transform got updated
-	void moveUpdate(MoveComponent& move);
-
 private:
 private:
 	Type m_type;
 	Type m_type;
 };
 };

+ 29 - 23
include/anki/scene/FrustumComponent.h

@@ -16,7 +16,7 @@ namespace anki {
 // Forward
 // Forward
 class VisibilityTestResults;
 class VisibilityTestResults;
 
 
-/// @addtogroup Scene
+/// @addtogroup scene
 /// @{
 /// @{
 
 
 /// Frustum component interface for scene nodes. Useful for nodes that are 
 /// Frustum component interface for scene nodes. Useful for nodes that are 
@@ -24,25 +24,21 @@ class VisibilityTestResults;
 class FrustumComponent: public SceneComponent
 class FrustumComponent: public SceneComponent
 {
 {
 public:
 public:
-	/// @name Constructors
-	/// @{
-
 	/// Pass the frustum here so we can avoid the virtuals
 	/// Pass the frustum here so we can avoid the virtuals
 	FrustumComponent(SceneNode* node, Frustum* frustum)
 	FrustumComponent(SceneNode* node, Frustum* frustum)
-		: SceneComponent(FRUSTUM_COMPONENT, node), m_frustum(frustum)
+	:	SceneComponent(Type::FRUSTUM, node), 
+		m_frustum(frustum)
 	{
 	{
 		// WARNING: Never touch m_frustum in constructor
 		// WARNING: Never touch m_frustum in constructor
 		ANKI_ASSERT(frustum);
 		ANKI_ASSERT(frustum);
 		markForUpdate();
 		markForUpdate();
 	}
 	}
-	/// @}
 
 
-	/// @name Accessors
-	/// @{
 	Frustum& getFrustum()
 	Frustum& getFrustum()
 	{
 	{
 		return *m_frustum;
 		return *m_frustum;
 	}
 	}
+
 	const Frustum& getFrustum() const
 	const Frustum& getFrustum() const
 	{
 	{
 		return *m_frustum;
 		return *m_frustum;
@@ -52,27 +48,33 @@ public:
 	{
 	{
 		return m_pm;
 		return m_pm;
 	}
 	}
+
 	void setProjectionMatrix(const Mat4& m)
 	void setProjectionMatrix(const Mat4& m)
 	{
 	{
 		m_pm = m;
 		m_pm = m;
+		markForUpdate();
 	}
 	}
 
 
 	const Mat4& getViewMatrix() const
 	const Mat4& getViewMatrix() const
 	{
 	{
 		return m_vm;
 		return m_vm;
 	}
 	}
+
 	void setViewMatrix(const Mat4& m)
 	void setViewMatrix(const Mat4& m)
 	{
 	{
 		m_vm = m;
 		m_vm = m;
+		markForUpdate();
 	}
 	}
 
 
 	const Mat4& getViewProjectionMatrix() const
 	const Mat4& getViewProjectionMatrix() const
 	{
 	{
 		return m_vpm;
 		return m_vpm;
 	}
 	}
+
 	void setViewProjectionMatrix(const Mat4& m)
 	void setViewProjectionMatrix(const Mat4& m)
 	{
 	{
 		m_vpm = m;
 		m_vpm = m;
+		markForUpdate();
 	}
 	}
 
 
 	/// Get the origin for sorting and visibility tests
 	/// Get the origin for sorting and visibility tests
@@ -92,7 +94,6 @@ public:
 		ANKI_ASSERT(m_visible != nullptr);
 		ANKI_ASSERT(m_visible != nullptr);
 		return *m_visible;
 		return *m_visible;
 	}
 	}
-	/// @}
 
 
 	void markForUpdate()
 	void markForUpdate()
 	{
 	{
@@ -111,30 +112,35 @@ public:
 		return getFrustum().insideFrustum(cs);
 		return getFrustum().insideFrustum(cs);
 	}
 	}
 
 
-	/// Override SceneComponent::update
-	Bool update(SceneNode&, F32, F32, UpdateType updateType) override
+	/// Called when the component gets updated. It should be overriden, by 
+	/// default it does nothing.
+	virtual void onFrustumComponentUpdate(
+		SceneNode& node, F32 prevTime, F32 crntTime)
+	{}
+
+	/// @name SceneComponent overrides
+	/// @{
+	Bool update(SceneNode&, F32, F32) override
 	{
 	{
-		if(updateType == ASYNC_UPDATE)
-		{
-			Bool out = m_markedForUpdate;
-			m_markedForUpdate = false;
-			return out;
-		}
-		else
-		{
-			return false;
-		}
+		Bool out = m_markedForUpdate;
+		m_markedForUpdate = false;
+		return out;
+	}
+
+	void onUpdate(SceneNode& node, F32 prevTime, F32 crntTime) final
+	{
+		onFrustumComponentUpdate(node, prevTime, crntTime);
 	}
 	}
 
 
-	/// Override SceneComponent::reset
 	void reset() override
 	void reset() override
 	{
 	{
 		m_visible = nullptr;
 		m_visible = nullptr;
 	}
 	}
+	/// @}
 
 
 	static constexpr Type getClassType()
 	static constexpr Type getClassType()
 	{
 	{
-		return FRUSTUM_COMPONENT;
+		return Type::FRUSTUM;
 	}
 	}
 
 
 private:
 private:

+ 8 - 8
include/anki/scene/InstanceNode.h

@@ -10,7 +10,7 @@
 
 
 namespace anki {
 namespace anki {
 
 
-/// @addtogroup Scene
+/// @addtogroup scene
 /// @{
 /// @{
 
 
 /// Instance component. Dummy used only for idendification
 /// Instance component. Dummy used only for idendification
@@ -18,27 +18,27 @@ class InstanceComponent: public SceneComponent
 {
 {
 public:
 public:
 	InstanceComponent(SceneNode* node)
 	InstanceComponent(SceneNode* node)
-	:	SceneComponent(INSTANCE_COMPONENT, node)
+	:	SceneComponent(Type::INSTANCE, node)
 	{}
 	{}
 
 
 	static constexpr Type getClassType()
 	static constexpr Type getClassType()
 	{
 	{
-		return INSTANCE_COMPONENT;
+		return Type::INSTANCE;
 	}
 	}
 };
 };
 
 
 /// Instance scene node
 /// Instance scene node
-class InstanceNode: public SceneNode, public InstanceComponent, 
-	public MoveComponent
+class InstanceNode: public SceneNode,  public MoveComponent, 
+	public InstanceComponent
 {
 {
 public:
 public:
 	InstanceNode(const CString& name, SceneGraph* scene)
 	InstanceNode(const CString& name, SceneGraph* scene)
 	:	SceneNode(name, scene), 
 	:	SceneNode(name, scene), 
-		InstanceComponent(this), 
-		MoveComponent(this)
+		MoveComponent(this, MoveComponent::Flag::IGNORE_PARENT_TRANSFORM),
+		InstanceComponent(this)
 	{
 	{
-		addComponent(static_cast<InstanceComponent*>(this));
 		addComponent(static_cast<MoveComponent*>(this));
 		addComponent(static_cast<MoveComponent*>(this));
+		addComponent(static_cast<InstanceComponent*>(this));
 	}
 	}
 };
 };
 
 

+ 67 - 65
include/anki/scene/Light.h

@@ -16,6 +16,9 @@
 
 
 namespace anki {
 namespace anki {
 
 
+/// @addtogroup scene
+/// @{
+
 /// Light component. It's a dummy component used to identify lights
 /// Light component. It's a dummy component used to identify lights
 class LightComponent: public SceneComponent
 class LightComponent: public SceneComponent
 {
 {
@@ -24,7 +27,7 @@ public:
 
 
 	static constexpr Type getClassType()
 	static constexpr Type getClassType()
 	{
 	{
-		return LIGHT_COMPONENT;
+		return Type::LIGHT;
 	}
 	}
 };
 };
 
 
@@ -72,109 +75,115 @@ class Light: public SceneNode, public LightComponent, public MoveComponent,
 	public SpatialComponent
 	public SpatialComponent
 {
 {
 public:
 public:
-	enum LightType
+	enum class Type: U8
 	{
 	{
-		LT_POINT,
-		LT_SPOT,
-		LT_NUM
+		POINT,
+		SPOT,
+		COUNT
 	};
 	};
 
 
-	/// @name Constructors
-	/// @{
 	Light(
 	Light(
 		const CString& name, SceneGraph* scene, // SceneNode
 		const CString& name, SceneGraph* scene, // SceneNode
-		LightType t); // Self
-	/// @}
+		Type t); // Self
 
 
 	virtual ~Light();
 	virtual ~Light();
 
 
-	/// @name Accessors
-	/// @{
-	LightType getLightType() const
+	Type getLightType() const
 	{
 	{
-		return type;
+		return m_type;
 	}
 	}
 
 
 	const Vec4& getDiffuseColor() const
 	const Vec4& getDiffuseColor() const
 	{
 	{
-		return color;
+		return m_color;
 	}
 	}
+
 	Vec4& getDiffuseColor()
 	Vec4& getDiffuseColor()
 	{
 	{
-		return color;
+		return m_color;
 	}
 	}
+
 	void setDiffuseColor(const Vec4& x)
 	void setDiffuseColor(const Vec4& x)
 	{
 	{
-		color = x;
+		m_color = x;
 	}
 	}
 
 
 	const Vec4& getSpecularColor() const
 	const Vec4& getSpecularColor() const
 	{
 	{
-		return specColor;
+		return m_specColor;
 	}
 	}
+
 	Vec4& getSpecularColor()
 	Vec4& getSpecularColor()
 	{
 	{
-		return specColor;
+		return m_specColor;
 	}
 	}
+
 	void setSpecularColor(const Vec4& x)
 	void setSpecularColor(const Vec4& x)
 	{
 	{
-		specColor = x;
+		m_specColor = x;
 	}
 	}
 
 
 	Bool getShadowEnabled() const
 	Bool getShadowEnabled() const
 	{
 	{
-		return shadow;
+		return m_shadow;
 	}
 	}
+
 	void setShadowEnabled(const Bool x)
 	void setShadowEnabled(const Bool x)
 	{
 	{
-		shadow = x;
+		m_shadow = x;
 	}
 	}
 
 
 	U getShadowMapIndex() const
 	U getShadowMapIndex() const
 	{
 	{
-		return (U)shadowMapIndex;
+		return static_cast<U>(m_shadowMapIndex);
 	}
 	}
+
 	void setShadowMapIndex(const U i)
 	void setShadowMapIndex(const U i)
 	{
 	{
 		ANKI_ASSERT(i < 0xFF);
 		ANKI_ASSERT(i < 0xFF);
-		shadowMapIndex = (U8)i;
+		m_shadowMapIndex = static_cast<U8>(i);
 	}
 	}
 
 
 	Bool hasLensFlare() const
 	Bool hasLensFlare() const
 	{
 	{
-		return flaresTex.isLoaded();
+		return m_flaresTex.isLoaded();
 	}
 	}
 
 
 	const GlTextureHandle& getLensFlareTexture() const
 	const GlTextureHandle& getLensFlareTexture() const
 	{
 	{
 		ANKI_ASSERT(hasLensFlare());
 		ANKI_ASSERT(hasLensFlare());
-		return flaresTex->getGlTexture();
+		return m_flaresTex->getGlTexture();
 	}
 	}
+
 	const Vec2& getLensFlaresSize() const
 	const Vec2& getLensFlaresSize() const
 	{
 	{
-		return flaresSize;
+		return m_flaresSize;
 	}
 	}
+
 	void setLensFlaresSize(const Vec2& val)
 	void setLensFlaresSize(const Vec2& val)
 	{
 	{
-		flaresSize = val;
+		m_flaresSize = val;
 	}
 	}
+
 	const Vec2& getLensFlaresStretchMultiplier() const
 	const Vec2& getLensFlaresStretchMultiplier() const
 	{
 	{
-		return flaresStretchMultiplier;
+		return m_flaresStretchMultiplier;
 	}
 	}
+
 	void setLensFlaresStretchMultiplier(const Vec2& val)
 	void setLensFlaresStretchMultiplier(const Vec2& val)
 	{
 	{
-		flaresStretchMultiplier = val;
+		m_flaresStretchMultiplier = val;
 	}
 	}
+
 	F32 getLensFlaresAlpha() const
 	F32 getLensFlaresAlpha() const
 	{
 	{
-		return flaresAlpha;
+		return m_flaresAlpha;
 	}
 	}
+
 	void setLensFlaresAlpha(F32 val)
 	void setLensFlaresAlpha(F32 val)
 	{
 	{
-		flaresAlpha = val;
+		m_flaresAlpha = val;
 	}
 	}
-	/// @}
 
 
 	void loadLensFlare(const CString& filename);
 	void loadLensFlare(const CString& filename);
 
 
@@ -191,85 +200,75 @@ protected:
 	void frustumUpdate();
 	void frustumUpdate();
 
 
 	/// Called when moved
 	/// Called when moved
-	void moveUpdate(MoveComponent& move);
+	void onMoveComponentUpdateCommon();
 
 
 private:
 private:
-	LightType type;
-	Vec4 color = Vec4(1.0);
-	Vec4 specColor = Vec4(1.0);
+	Type m_type;
+	Vec4 m_color = Vec4(1.0);
+	Vec4 m_specColor = Vec4(1.0);
 
 
 	/// @name Flare struff
 	/// @name Flare struff
 	/// @{
 	/// @{
-	TextureResourcePointer flaresTex;
-	Vec2 flaresSize = Vec2(0.2);
-	Vec2 flaresStretchMultiplier = Vec2(1.0);
-	F32 flaresAlpha = 1.0;
+	TextureResourcePointer m_flaresTex;
+	Vec2 m_flaresSize = Vec2(0.2);
+	Vec2 m_flaresStretchMultiplier = Vec2(1.0);
+	F32 m_flaresAlpha = 1.0;
 	/// @}
 	/// @}
 
 
-	Bool8 shadow = false;
-	U8 shadowMapIndex = 0xFF; ///< Used by the renderer
+	Bool8 m_shadow = false;
+	U8 m_shadowMapIndex = 0xFF; ///< Used by the renderer
 };
 };
 
 
 /// Point light
 /// Point light
 class PointLight: public Light
 class PointLight: public Light
 {
 {
 public:
 public:
-	/// @name Constructors/Destructor
-	/// @{
 	PointLight(const CString& name, SceneGraph* scene);
 	PointLight(const CString& name, SceneGraph* scene);
-	/// @}
 
 
-	/// @name Accessors
-	/// @{
 	F32 getRadius() const
 	F32 getRadius() const
 	{
 	{
-		return sphereW.getRadius();
+		return m_sphereW.getRadius();
 	}
 	}
+
 	void setRadius(const F32 x)
 	void setRadius(const F32 x)
 	{
 	{
-		sphereW.setRadius(x);
+		m_sphereW.setRadius(x);
 		frustumUpdate();
 		frustumUpdate();
 	}
 	}
 
 
 	const Sphere& getSphere() const
 	const Sphere& getSphere() const
 	{
 	{
-		return sphereW;
+		return m_sphereW;
 	}
 	}
-	/// @}
 
 
-	/// @name SceneNode virtuals
+	/// @name MoveComponent virtuals
 	/// @{
 	/// @{
-	void componentUpdated(SceneComponent& comp, 
-		SceneComponent::UpdateType uptype) override;
+	void onMoveComponentUpdate(SceneNode&, F32, F32) override;
 	/// @}
 	/// @}
 
 
 	/// @name SpatialComponent virtuals
 	/// @name SpatialComponent virtuals
 	/// @{
 	/// @{
 	const CollisionShape& getSpatialCollisionShape()
 	const CollisionShape& getSpatialCollisionShape()
 	{
 	{
-		return sphereW;
+		return m_sphereW;
 	}
 	}
 	/// @}
 	/// @}
 
 
 public:
 public:
-	Sphere sphereW = Sphere(Vec4(0.0), 1.0);
+	Sphere m_sphereW = Sphere(Vec4(0.0), 1.0);
 };
 };
 
 
 /// Spot light
 /// Spot light
 class SpotLight: public Light, public FrustumComponent
 class SpotLight: public Light, public FrustumComponent
 {
 {
 public:
 public:
-	/// @name Constructors/Destructor
-	/// @{
 	SpotLight(const CString& name, SceneGraph* scene);
 	SpotLight(const CString& name, SceneGraph* scene);
-	/// @}
 
 
-	/// @name Accessors
-	/// @{
 	GlTextureHandle& getTexture()
 	GlTextureHandle& getTexture()
 	{
 	{
 		return m_tex->getGlTexture();
 		return m_tex->getGlTexture();
 	}
 	}
+
 	const GlTextureHandle& getTexture() const
 	const GlTextureHandle& getTexture() const
 	{
 	{
 		return m_tex->getGlTexture();
 		return m_tex->getGlTexture();
@@ -279,6 +278,7 @@ public:
 	{
 	{
 		return m_frustum.getFovX();
 		return m_frustum.getFovX();
 	}
 	}
+
 	void setOuterAngle(F32 x)
 	void setOuterAngle(F32 x)
 	{
 	{
 		m_frustum.setFovX(x);
 		m_frustum.setFovX(x);
@@ -296,6 +296,7 @@ public:
 	{
 	{
 		m_cosInnerAngle = cos(ang / 2.0);
 		m_cosInnerAngle = cos(ang / 2.0);
 	}
 	}
+
 	F32 getInnerAngleCos() const
 	F32 getInnerAngleCos() const
 	{
 	{
 		return m_cosInnerAngle;
 		return m_cosInnerAngle;
@@ -305,6 +306,7 @@ public:
 	{
 	{
 		return m_frustum.getFar();
 		return m_frustum.getFar();
 	}
 	}
+
 	void setDistance(F32 f)
 	void setDistance(F32 f)
 	{
 	{
 		m_frustum.setFar(f);
 		m_frustum.setFar(f);
@@ -315,12 +317,10 @@ public:
 	{
 	{
 		return m_frustum;
 		return m_frustum;
 	}
 	}
-	/// @}
 
 
-	/// @name SceneNode virtuals
+	/// @name MoveComponent virtuals
 	/// @{
 	/// @{
-	void componentUpdated(SceneComponent& comp,
-		SceneComponent::UpdateType uptype) override;
+	void onMoveComponentUpdate(SceneNode&, F32, F32) override;
 	/// @}
 	/// @}
 
 
 	/// @name SpatialComponent virtuals
 	/// @name SpatialComponent virtuals
@@ -340,6 +340,8 @@ private:
 	F32 m_cosInnerAngle;
 	F32 m_cosInnerAngle;
 };
 };
 
 
+/// @}
+
 } // end namespace anki
 } // end namespace anki
 
 
 #endif
 #endif

+ 11 - 5
include/anki/scene/Misc.h

@@ -10,29 +10,35 @@
 
 
 namespace anki {
 namespace anki {
 
 
+/// @addtogroup scene
+/// @{
+
 /// A class that holds spatial information and implements the SpatialComponent
 /// A class that holds spatial information and implements the SpatialComponent
 /// virtuals. You just need to update the OBB manually
 /// virtuals. You just need to update the OBB manually
-struct ObbSpatialComponent: public SpatialComponent
+class ObbSpatialComponent: public SpatialComponent
 {
 {
-	Obb obb;
+public:
+	Obb m_obb;
 
 
 	ObbSpatialComponent(SceneNode* node)
 	ObbSpatialComponent(SceneNode* node)
-		: SpatialComponent(node)
+	:	SpatialComponent(node)
 	{}
 	{}
 
 
 	/// Implement SpatialComponent::getSpatialCollisionShape
 	/// Implement SpatialComponent::getSpatialCollisionShape
 	const CollisionShape& getSpatialCollisionShape()
 	const CollisionShape& getSpatialCollisionShape()
 	{
 	{
-		return obb;
+		return m_obb;
 	}
 	}
 
 
 	/// Implement SpatialComponent::getSpatialOrigin
 	/// Implement SpatialComponent::getSpatialOrigin
 	Vec4 getSpatialOrigin()
 	Vec4 getSpatialOrigin()
 	{
 	{
-		return obb.getCenter();
+		return m_obb.getCenter();
 	}
 	}
 };
 };
 
 
+/// @}
+
 } // end namespace anki
 } // end namespace anki
 
 
 #endif
 #endif

+ 16 - 14
include/anki/scene/ModelNode.h

@@ -16,22 +16,24 @@
 
 
 namespace anki {
 namespace anki {
 
 
-/// @addtogroup Scene
+// Forward
+class ObbSpatialComponent;
+
+/// @addtogroup scene
 /// @{
 /// @{
 
 
 /// A fragment of the ModelNode
 /// A fragment of the ModelNode
 class ModelPatchNode: public SceneNode, 
 class ModelPatchNode: public SceneNode, 
 	public RenderComponent, public SpatialComponent
 	public RenderComponent, public SpatialComponent
 {
 {
+	friend class ModelNode;
+
 public:
 public:
-	/// @name Constructors/Destructor
-	/// @{
 	ModelPatchNode(
 	ModelPatchNode(
 		const CString& name, SceneGraph* scene, // Scene
 		const CString& name, SceneGraph* scene, // Scene
 		const ModelPatchBase* modelPatch); // Self
 		const ModelPatchBase* modelPatch); // Self
 
 
 	~ModelPatchNode();
 	~ModelPatchNode();
-	/// @}
 
 
 	/// @name RenderComponent virtuals
 	/// @name RenderComponent virtuals
 	/// @{
 	/// @{
@@ -54,9 +56,6 @@ public:
 	}
 	}
 	/// @}
 	/// @}
 
 
-	/// Override SceneNode::frameUpdate
-	void frameUpdate(F32, F32, SceneNode::UpdateType uptype) override;
-
 	/// Implement SpatialComponent::getSpatialCollisionShape
 	/// Implement SpatialComponent::getSpatialCollisionShape
 	const CollisionShape& getSpatialCollisionShape()
 	const CollisionShape& getSpatialCollisionShape()
 	{
 	{
@@ -72,6 +71,10 @@ public:
 private:
 private:
 	Obb m_obb; ///< In world space
 	Obb m_obb; ///< In world space
 	const ModelPatchBase* m_modelPatch; ///< The resource
 	const ModelPatchBase* m_modelPatch; ///< The resource
+	SceneVector<ObbSpatialComponent*> m_spatials;
+
+	void updateInstanceSpatials(
+		const SceneFrameVector<MoveComponent*>& instanceMoves);
 };
 };
 
 
 /// The model scene node
 /// The model scene node
@@ -80,28 +83,27 @@ class ModelNode: public SceneNode, public MoveComponent
 	friend class ModelPatchNode;
 	friend class ModelPatchNode;
 
 
 public:
 public:
-	/// @name Constructors/Destructor
-	/// @{
 	ModelNode(
 	ModelNode(
 		const CString& name, SceneGraph* scene, // SceneNode
 		const CString& name, SceneGraph* scene, // SceneNode
 		const CString& modelFname); // Self
 		const CString& modelFname); // Self
 
 
 	virtual ~ModelNode();
 	virtual ~ModelNode();
-	/// @}
 
 
-	/// @name Accessors
-	/// @{
 	const Model& getModel() const
 	const Model& getModel() const
 	{
 	{
 		return *m_model;
 		return *m_model;
 	}
 	}
-	/// @}
 
 
 	/// Override SceneNode::frameUpdate
 	/// Override SceneNode::frameUpdate
-	void frameUpdate(F32, F32, SceneNode::UpdateType uptype) override;
+	void frameUpdate(F32, F32) override;
+
+	/// Override MoveComponent::onMoveComponentUpdate
+	void onMoveComponentUpdate(
+		SceneNode& node, F32 prevTime, F32 crntTime) override;
 
 
 private:
 private:
 	ModelResourcePointer m_model; ///< The resource
 	ModelResourcePointer m_model; ///< The resource
+	SceneVector<ModelPatchNode*> m_modelPatches;
 	SceneVector<Transform> m_transforms; ///< Cache the transforms of instances
 	SceneVector<Transform> m_transforms; ///< Cache the transforms of instances
 	Timestamp m_transformsTimestamp;
 	Timestamp m_transformsTimestamp;
 };
 };

+ 40 - 27
include/anki/scene/MoveComponent.h

@@ -9,78 +9,82 @@
 #include "anki/scene/Common.h"
 #include "anki/scene/Common.h"
 #include "anki/scene/SceneComponent.h"
 #include "anki/scene/SceneComponent.h"
 #include "anki/util/Bitset.h"
 #include "anki/util/Bitset.h"
+#include "anki/util/Enum.h"
 #include "anki/Math.h"
 #include "anki/Math.h"
 
 
 namespace anki {
 namespace anki {
 
 
-/// @addtogroup Scene
+/// @addtogroup scene
 /// @{
 /// @{
 
 
-/// Interface for movable scene nodes
-class MoveComponent: 
-	public SceneComponent,
-	public SceneHierarchicalObject<MoveComponent>, 
-	public Bitset<U8>
+enum class MoveComponentFlag: U8
 {
 {
-public:
-	typedef SceneHierarchicalObject<MoveComponent> Base;
+	NONE = 0,
 
 
-	enum MoveComponentFlag
-	{
-		MF_NONE = 0,
+	/// Get the parent's world transform
+	IGNORE_LOCAL_TRANSFORM = 1 << 1,
 
 
-		/// Get the parent's world transform
-		MF_IGNORE_LOCAL_TRANSFORM = 1 << 1,
+	/// Ignore parent's transform
+	IGNORE_PARENT_TRANSFORM = 1 << 2,
 
 
-		/// If dirty then is marked for update
-		MF_MARKED_FOR_UPDATE = 1 << 3,
-	};
+	/// If dirty then is marked for update
+	MARKED_FOR_UPDATE = 1 << 3,
+};
+ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(MoveComponentFlag, inline)
 
 
-	/// @name Constructors & destructor
-	/// @{
+/// Interface for movable scene nodes
+class MoveComponent: public SceneComponent, public Bitset<MoveComponentFlag>
+{
+public:
+	using Base = SceneHierarchicalObject<MoveComponent>;
+	using Flag = MoveComponentFlag;
 
 
 	/// The one and only constructor
 	/// The one and only constructor
 	/// @param node The scene node to steal it's allocators
 	/// @param node The scene node to steal it's allocators
 	/// @param flags The flags
 	/// @param flags The flags
-	MoveComponent(SceneNode* node, U32 flags = MF_NONE);
+	MoveComponent(SceneNode* node, Flag flags = Flag::NONE);
 
 
 	~MoveComponent();
 	~MoveComponent();
-	/// @}
 
 
-	/// @name Accessors
-	/// @{
 	const Transform& getLocalTransform() const
 	const Transform& getLocalTransform() const
 	{
 	{
 		return m_ltrf;
 		return m_ltrf;
 	}
 	}
+
 	void setLocalTransform(const Transform& x)
 	void setLocalTransform(const Transform& x)
 	{
 	{
 		m_ltrf = x;
 		m_ltrf = x;
 		markForUpdate();
 		markForUpdate();
 	}
 	}
+
 	void setLocalOrigin(const Vec4& x)
 	void setLocalOrigin(const Vec4& x)
 	{
 	{
 		m_ltrf.setOrigin(x);
 		m_ltrf.setOrigin(x);
 		markForUpdate();
 		markForUpdate();
 	}
 	}
+
 	const Vec4& getLocalOrigin() const
 	const Vec4& getLocalOrigin() const
 	{
 	{
 		return m_ltrf.getOrigin();
 		return m_ltrf.getOrigin();
 	}
 	}
+
 	void setLocalRotation(const Mat3x4& x)
 	void setLocalRotation(const Mat3x4& x)
 	{
 	{
 		m_ltrf.setRotation(x);
 		m_ltrf.setRotation(x);
 		markForUpdate();
 		markForUpdate();
 	}
 	}
+
 	const Mat3x4& getLocalRotation() const
 	const Mat3x4& getLocalRotation() const
 	{
 	{
 		return m_ltrf.getRotation();
 		return m_ltrf.getRotation();
 	}
 	}
+
 	void setLocalScale(F32 x)
 	void setLocalScale(F32 x)
 	{
 	{
 		m_ltrf.setScale(x);
 		m_ltrf.setScale(x);
 		markForUpdate();
 		markForUpdate();
 	}
 	}
+
 	F32 getLocalScale() const
 	F32 getLocalScale() const
 	{
 	{
 		return m_ltrf.getScale();
 		return m_ltrf.getScale();
@@ -95,7 +99,11 @@ public:
 	{
 	{
 		return m_prevWTrf;
 		return m_prevWTrf;
 	}
 	}
-	/// @}
+
+	/// Called when there is an update in the world transformation.
+	virtual void onMoveComponentUpdate(
+		SceneNode& node, F32 prevTime, F32 crntTime)
+	{}
 
 
 	/// @name SceneComponent overrides
 	/// @name SceneComponent overrides
 	/// @{
 	/// @{
@@ -105,7 +113,12 @@ public:
 	/// @note Don't update if child because we start from roots and go to
 	/// @note Don't update if child because we start from roots and go to
 	///       children and we don't want a child to be updated before the
 	///       children and we don't want a child to be updated before the
 	///       parent
 	///       parent
-	Bool update(SceneNode&, F32, F32, UpdateType uptype) override;
+	Bool update(SceneNode&, F32, F32) override;
+
+	void onUpdate(SceneNode& node, F32 prevTime, F32 crntTime) final
+	{
+		onMoveComponentUpdate(node, prevTime, crntTime);
+	}
 	/// @}
 	/// @}
 
 
 	/// @name Mess with the local transform
 	/// @name Mess with the local transform
@@ -152,7 +165,7 @@ public:
 
 
 	static constexpr Type getClassType()
 	static constexpr Type getClassType()
 	{
 	{
-		return MOVE_COMPONENT;
+		return Type::MOVE;
 	}
 	}
 
 
 private:
 private:
@@ -170,12 +183,12 @@ private:
 
 
 	void markForUpdate()
 	void markForUpdate()
 	{
 	{
-		enableBits(MF_MARKED_FOR_UPDATE);
+		enableBits(Flag::MARKED_FOR_UPDATE);
 	}
 	}
 
 
 	/// Called every frame. It updates the @a m_wtrf if @a shouldUpdateWTrf
 	/// Called every frame. It updates the @a m_wtrf if @a shouldUpdateWTrf
 	/// is true. Then it moves to the children.
 	/// is true. Then it moves to the children.
-	void updateWorldTransform();
+	Bool updateWorldTransform(SceneNode& node);
 };
 };
 /// @}
 /// @}
 
 

+ 6 - 6
include/anki/scene/ParticleEmitter.h

@@ -164,12 +164,13 @@ public:
 
 
 	/// @name SceneNode virtuals
 	/// @name SceneNode virtuals
 	/// @{
 	/// @{
+	void frameUpdate(F32 prevUpdateTime, F32 crntTime) override;
+	/// @}
 
 
-	void frameUpdate(F32 prevUpdateTime, F32 crntTime, 
-		SceneNode::UpdateType uptype) override;
-
-	void componentUpdated(SceneComponent& comp, 
-		SceneComponent::UpdateType) override;
+	/// @name MoveComponent virtuals
+	/// @{
+	void onMoveComponentUpdate(
+		SceneNode& node, F32 prevTime, F32 crntTime) override;
 	/// @}
 	/// @}
 
 
 	/// @name SpatialComponent virtuals
 	/// @name SpatialComponent virtuals
@@ -187,7 +188,6 @@ public:
 
 
 	/// @name RenderComponent virtuals
 	/// @name RenderComponent virtuals
 	/// @{
 	/// @{
-
 	void buildRendering(RenderingBuildData& data);
 	void buildRendering(RenderingBuildData& data);
 
 
 	const Material& getMaterial();
 	const Material& getMaterial();

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

@@ -59,8 +59,6 @@ public:
 	RenderComponentVariable(const MaterialVariable* mvar);
 	RenderComponentVariable(const MaterialVariable* mvar);
 	virtual ~RenderComponentVariable();
 	virtual ~RenderComponentVariable();
 
 
-	/// @name Accessors
-	/// @{
 	BuildinMaterialVariableId getBuildinId() const
 	BuildinMaterialVariableId getBuildinId() const
 	{
 	{
 		return m_buildinId;
 		return m_buildinId;
@@ -121,7 +119,6 @@ public:
 	{
 	{
 		return m_mvar->isInstanced();
 		return m_mvar->isInstanced();
 	}
 	}
-	/// @}
 
 
 	/// A custom cleanup method
 	/// A custom cleanup method
 	virtual void cleanup(SceneAllocator<U8> alloc) = 0;
 	virtual void cleanup(SceneAllocator<U8> alloc) = 0;
@@ -142,7 +139,7 @@ public:
 	typedef T Type;
 	typedef T Type;
 
 
 	RenderComponentVariableTemplate(const MaterialVariable* mvar)
 	RenderComponentVariableTemplate(const MaterialVariable* mvar)
-		: RenderComponentVariable(mvar)
+	:	RenderComponentVariable(mvar)
 	{
 	{
 		setupVisitable(this);
 		setupVisitable(this);
 	}
 	}
@@ -233,8 +230,6 @@ public:
 
 
 	~RenderComponent();
 	~RenderComponent();
 
 
-	/// @name Accessors
-	/// @{
 	Variables::iterator getVariablesBegin()
 	Variables::iterator getVariablesBegin()
 	{
 	{
 		return m_vars.begin();
 		return m_vars.begin();
@@ -243,7 +238,6 @@ public:
 	{
 	{
 		return m_vars.end();
 		return m_vars.end();
 	}
 	}
-	/// @}
 
 
 	/// Build up the rendering.
 	/// Build up the rendering.
 	/// Given an array of submeshes that are visible append jobs to the GL
 	/// Given an array of submeshes that are visible append jobs to the GL
@@ -287,7 +281,7 @@ public:
 
 
 	static constexpr Type getClassType()
 	static constexpr Type getClassType()
 	{
 	{
-		return RENDER_COMPONENT;
+		return Type::RENDER;
 	}
 	}
 
 
 protected:
 protected:

+ 19 - 33
include/anki/scene/SceneComponent.h

@@ -17,43 +17,32 @@ class SceneComponent
 {
 {
 public:
 public:
 	// The type of the components
 	// The type of the components
-	enum Type
+	enum class Type: U16
 	{
 	{
-		COMPONENT_NONE,
-		FRUSTUM_COMPONENT,
-		MOVE_COMPONENT,
-		RENDER_COMPONENT,
-		SPATIAL_COMPONENT,
-		LIGHT_COMPONENT,
-		INSTANCE_COMPONENT,
+		NONE,
+		FRUSTUM,
+		MOVE,
+		RENDER,
+		SPATIAL,
+		LIGHT,
+		INSTANCE,
 		RIGID_BODY,
 		RIGID_BODY,
 		LAST_COMPONENT_ID = RIGID_BODY
 		LAST_COMPONENT_ID = RIGID_BODY
 	};
 	};
 
 
-	/// The update type
-	enum UpdateType
-	{
-		/// The update happens in the thread safe sync section
-		SYNC_UPDATE, 
-		
-		/// The update happens in a thread. This should not touch data that 
-		/// belong to other nodes
-		ASYNC_UPDATE 
-	};
-
-	/// Construct the scene component. The x is bogus
-	SceneComponent(Type type_, SceneNode* node)
-		: type(type_)
+	/// Construct the scene component.
+	SceneComponent(Type type, SceneNode* node)
+	:	m_type(type)
 	{}
 	{}
 
 
 	Type getType() const
 	Type getType() const
 	{
 	{
-		return (Type)type;
+		return m_type;
 	}
 	}
 
 
 	Timestamp getTimestamp() const
 	Timestamp getTimestamp() const
 	{
 	{
-		return timestamp;
+		return m_timestamp;
 	}
 	}
 
 
 	/// Do some reseting before frame starts
 	/// Do some reseting before frame starts
@@ -62,20 +51,17 @@ public:
 
 
 	/// Do some updating
 	/// Do some updating
 	/// @return true if an update happened
 	/// @return true if an update happened
-	virtual Bool update(SceneNode& node, F32 prevTime, F32 crntTime, 
-		UpdateType updateType)
+	virtual Bool update(SceneNode& node, F32 prevTime, F32 crntTime)
 	{
 	{
 		return false;
 		return false;
 	}
 	}
 
 
-	/// Method called when the component got updated
-	virtual void updated(SceneNode& node, F32 prevTime, F32 crntTime, 
-		UpdateType updateType)
+	/// Called if SceneComponent::update returned true.
+	virtual void onUpdate(SceneNode& node, F32 prevTime, F32 crntTime)
 	{}
 	{}
 
 
 	/// Called only by the SceneGraph
 	/// Called only by the SceneGraph
-	Bool updateReal(SceneNode& node, F32 prevTime, F32 crntTime,
-		UpdateType updateType);
+	Bool updateReal(SceneNode& node, F32 prevTime, F32 crntTime);
 
 
 	template<typename TComponent>
 	template<typename TComponent>
 	TComponent& downCast()
 	TComponent& downCast()
@@ -86,10 +72,10 @@ public:
 	}
 	}
 
 
 protected:
 protected:
-	Timestamp timestamp; ///< Indicates when an update happened
+	Timestamp m_timestamp; ///< Indicates when an update happened
 
 
 private:
 private:
-	U8 type;
+	Type m_type;
 };
 };
 
 
 } // end namespace anki
 } // end namespace anki

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

@@ -22,13 +22,6 @@ class ResourceManager;
 class SceneNode: public SceneObject
 class SceneNode: public SceneObject
 {
 {
 public:
 public:
-	/// Scene node update type
-	enum UpdateType
-	{
-		SYNC_UPDATE,
-		ASYNC_UPDATE
-	};
-
 	/// The one and only constructor
 	/// The one and only constructor
 	/// @param name The unique name of the node. If it's nullptr the the node
 	/// @param name The unique name of the node. If it's nullptr the the node
 	///             is not searchable
 	///             is not searchable
@@ -40,8 +33,7 @@ public:
 	/// Unregister node
 	/// Unregister node
 	virtual ~SceneNode();
 	virtual ~SceneNode();
 
 
-	/// Return the name. It may be nullptr for nodes that we don't want to 
-	/// track
+	/// Return the name. It may be empty for nodes that we don't want to track
 	CString getName() const
 	CString getName() const
 	{
 	{
 		return (!m_name.isEmpty()) ? m_name.toCString() : CString();
 		return (!m_name.isEmpty()) ? m_name.toCString() : CString();
@@ -51,21 +43,10 @@ public:
 	/// rendering. By default it does nothing
 	/// rendering. By default it does nothing
 	/// @param prevUpdateTime Timestamp of the previous update
 	/// @param prevUpdateTime Timestamp of the previous update
 	/// @param crntTime Timestamp of this update
 	/// @param crntTime Timestamp of this update
-	/// @param uptype The type of this update
-	virtual void frameUpdate(F32 prevUpdateTime, F32 crntTime, 
-		UpdateType uptype)
+	virtual void frameUpdate(F32 prevUpdateTime, F32 crntTime)
 	{
 	{
 		(void)prevUpdateTime;
 		(void)prevUpdateTime;
 		(void)crntTime;
 		(void)crntTime;
-		(void)uptype;
-	}
-
-	/// Called when a component got updated
-	virtual void componentUpdated(SceneComponent& component, 
-		SceneComponent::UpdateType uptype)
-	{
-		(void)component;
-		(void)uptype;
 	}
 	}
 
 
 	/// Return the last frame the node was updated. It checks all components
 	/// Return the last frame the node was updated. It checks all components
@@ -155,7 +136,7 @@ public:
 
 
 	static constexpr SceneObject::Type getClassType()
 	static constexpr SceneObject::Type getClassType()
 	{
 	{
-		return SCENE_NODE_TYPE;
+		return SceneObject::Type::SCENE_NODE;
 	}
 	}
 
 
 protected:
 protected:

+ 29 - 52
include/anki/scene/SceneObject.h

@@ -9,6 +9,7 @@
 #include "anki/scene/Common.h"
 #include "anki/scene/Common.h"
 #include "anki/util/Object.h"
 #include "anki/util/Object.h"
 #include "anki/util/Functions.h"
 #include "anki/util/Functions.h"
+#include "anki/util/Enum.h"
 
 
 namespace anki {
 namespace anki {
 
 
@@ -39,14 +40,16 @@ class SceneObject:
 	SceneObjectCallbackCollection>
 	SceneObjectCallbackCollection>
 {
 {
 public:
 public:
-	enum Type
+	enum class Type: U8
 	{
 	{
-		SCENE_NODE_TYPE = 0,
-		EVENT_TYPE = 1 << 0
+		SCENE_NODE = 1 << 0,
+		EVENT = 1 << 1,
+		_TYPE_MASK = SCENE_NODE | EVENT
 	};
 	};
+	ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(Type, friend)
 
 
-	typedef Object<SceneObject, SceneAllocator<SceneObject>,
-		SceneObjectCallbackCollection> Base;
+	using Base = Object<SceneObject, SceneAllocator<SceneObject>,
+		SceneObjectCallbackCollection>;
 
 
 	SceneObject(Type type, SceneObject* parent, SceneGraph* scene);
 	SceneObject(Type type, SceneObject* parent, SceneGraph* scene);
 
 
@@ -54,7 +57,7 @@ public:
 
 
 	Type getType() const
 	Type getType() const
 	{
 	{
-		return (Type)(flags & EVENT_TYPE);
+		return m_bits & Type::_TYPE_MASK;
 	}
 	}
 
 
 	SceneAllocator<U8> getSceneAllocator() const;
 	SceneAllocator<U8> getSceneAllocator() const;
@@ -63,75 +66,49 @@ public:
 
 
 	SceneGraph& getSceneGraph()
 	SceneGraph& getSceneGraph()
 	{
 	{
-		return *scene;
+		return *m_scene;
 	}
 	}
+
 	const SceneGraph& getSceneGraph() const
 	const SceneGraph& getSceneGraph() const
 	{
 	{
-		return *scene;
+		return *m_scene;
 	}
 	}
 
 
 	Bool isMarkedForDeletion() const
 	Bool isMarkedForDeletion() const
 	{
 	{
-		return (flags & MARKED_FOR_DELETION) != 0;
-	}
-	void markForDeletion();
-
-	/// Visit this and the children of a specific SceneObject type
-	template<typename ScObj, typename Func>
-	void visitThisAndChildren(Func func)
-	{
-		Base::visitThisAndChildren([&](SceneObject& so)
-		{
-			const Type type = ScObj::getClassType();
-
-			if(so.getType() == type)
-			{
-				func(so.downCast<ScObj>());
-			}
-		});
+		return (m_bits & Flag::MARKED_FOR_DELETION) != Flag::NONE;
 	}
 	}
 
 
-	/// Visit this and the children of a specific SceneObject type
-	template<typename ScObj, typename Func>
-	void visitThisAndChildren(Func func) const
-	{
-		Base::visitThisAndChildren([&](const SceneObject& so)
-		{
-			const Type type = ScObj::getClassType();
-
-			if(so.getType() == type)
-			{
-				func(so.downCast<ScObj>());
-			}
-		});
-	}
+	void markForDeletion();
 
 
 	/// Downcast the class
 	/// Downcast the class
-	template<typename ScObj>
-	ScObj& downCast()
+	template<typename TScObj>
+	TScObj& downCast()
 	{
 	{
-		ANKI_ASSERT(ScObj::getClassType() == getType());
-		ScObj* out = staticCastPtr<ScObj*>(this);
+		ANKI_ASSERT(TScObj::getClassType() == getType());
+		TScObj* out = staticCastPtr<TScObj*>(this);
 		return *out;
 		return *out;
 	}
 	}
 
 
 	/// Downcast the class
 	/// Downcast the class
-	template<typename ScObj>
-	const ScObj& downCast() const
+	template<typename TScObj>
+	const TScObj& downCast() const
 	{
 	{
-		ANKI_ASSERT(ScObj::getClassType() == getType());
-		const ScObj* out = staticCastPtr<const ScObj*>(this);
+		ANKI_ASSERT(TScObj::getClassType() == getType());
+		const TScObj* out = staticCastPtr<const TScObj*>(this);
 		return *out;
 		return *out;
 	}
 	}
 
 
-public:
-	enum
+private:
+	enum class Flag: U8
 	{
 	{
-		MARKED_FOR_DELETION = 1 << 1
+		NONE = 0,
+		MARKED_FOR_DELETION = 1 << 2
 	};
 	};
+	ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(Flag, friend)
 
 
-	SceneGraph* scene;
-	U8 flags; ///< Contains the type and the marked for deletion
+	SceneGraph* m_scene;
+	U8 m_bits; ///< Contains the type and the marked for deletion
 };
 };
 
 
 inline void SceneObjectCallbackCollection::onChildRemoved(
 inline void SceneObjectCallbackCollection::onChildRemoved(

+ 44 - 30
include/anki/scene/SpatialComponent.h

@@ -10,51 +10,54 @@
 #include "anki/scene/SceneComponent.h"
 #include "anki/scene/SceneComponent.h"
 #include "anki/Collision.h"
 #include "anki/Collision.h"
 #include "anki/util/Bitset.h"
 #include "anki/util/Bitset.h"
+#include "anki/util/Enum.h"
 
 
 namespace anki {
 namespace anki {
 
 
-/// @addtogroup Scene
+/// @addtogroup scene
 /// @{
 /// @{
 
 
-/// Spatial component for scene nodes. It indicates scene nodes that need to 
-/// be placed in the a sector and they participate in the visibility tests
-class SpatialComponent: public SceneComponent, public Bitset<U8>
+/// Spatial flags
+enum class SpatialComponentFlag: U8
 {
 {
-public:
-	/// Spatial flags
-	enum SpatialFlag
-	{
-		SF_NONE = 0,
-		SF_VISIBLE_CAMERA = 1 << 1,
-		SF_VISIBLE_LIGHT = 1 << 2,
+	NONE = 0,
+	VISIBLE_CAMERA = 1 << 1,
+	VISIBLE_LIGHT = 1 << 2,
 
 
-		/// Visible or not. The visibility tester sets it
-		SF_VISIBLE_ANY = SF_VISIBLE_CAMERA | SF_VISIBLE_LIGHT,
+	/// Visible or not. The visibility tester sets it
+	VISIBLE_ANY = VISIBLE_CAMERA | VISIBLE_LIGHT,
 
 
-		/// This is used for example in lights. If the light does not collide 
-		/// with any surface then it shouldn't be visible and be processed 
-		/// further. This flag is being used to check if we should test agains
-		/// near plane when using the tiler for visibility tests.
-		SF_FULLY_TRANSPARENT = 1 << 3,
+	/// This is used for example in lights. If the light does not collide 
+	/// with any surface then it shouldn't be visible and be processed 
+	/// further. This flag is being used to check if we should test agains
+	/// near plane when using the tiler for visibility tests.
+	FULLY_TRANSPARENT = 1 << 3,
 
 
-		SF_MARKED_FOR_UPDATE = 1 << 4
-	};
+	MARKED_FOR_UPDATE = 1 << 4
+};
+ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(SpatialComponentFlag, inline)
+
+/// Spatial component for scene nodes. It indicates scene nodes that need to 
+/// be placed in the a sector and they participate in the visibility tests
+class SpatialComponent: public SceneComponent, 
+	public Bitset<SpatialComponentFlag>
+{
+public:
+	using Flag = SpatialComponentFlag;
 
 
 	/// Pass the collision shape here so we can avoid the virtuals
 	/// Pass the collision shape here so we can avoid the virtuals
 	/// @param node The scene node. Used only to steal it's allocators
 	/// @param node The scene node. Used only to steal it's allocators
 	/// @param flags A mask of SpatialFlag
 	/// @param flags A mask of SpatialFlag
-	SpatialComponent(SceneNode* node, U32 flags = SF_NONE);
+	SpatialComponent(SceneNode* node, Flag flags = Flag::NONE);
 
 
 	// Remove from current OctreeNode
 	// Remove from current OctreeNode
 	~SpatialComponent();
 	~SpatialComponent();
 
 
-	/// @name Accessors
-	/// @{
 	virtual const CollisionShape& getSpatialCollisionShape() = 0;
 	virtual const CollisionShape& getSpatialCollisionShape() = 0;
 
 
 	const Aabb& getAabb() const
 	const Aabb& getAabb() const
 	{
 	{
-		return aabb;
+		return m_aabb;
 	}
 	}
 
 
 	/// Get optimal collision shape for visibility tests
 	/// Get optimal collision shape for visibility tests
@@ -67,25 +70,35 @@ public:
 		}
 		}
 		else
 		else
 		{
 		{
-			return aabb;
+			return m_aabb;
 		}
 		}
 	}
 	}
 
 
 	/// Used for sorting spatials. In most object the origin is the center of
 	/// Used for sorting spatials. In most object the origin is the center of
 	/// mess but for cameras the origin is the eye point
 	/// mess but for cameras the origin is the eye point
 	virtual Vec4 getSpatialOrigin() = 0;
 	virtual Vec4 getSpatialOrigin() = 0;
-	/// @}
 
 
 	/// The derived class has to manually call this method when the collision 
 	/// The derived class has to manually call this method when the collision 
 	/// shape got updated
 	/// shape got updated
 	void markForUpdate()
 	void markForUpdate()
 	{
 	{
-		enableBits(SF_MARKED_FOR_UPDATE);
+		enableBits(Flag::MARKED_FOR_UPDATE);
 	}
 	}
 
 
+	/// Called when the component gets updated. It should be overriden, by 
+	/// default it does nothing.
+	virtual void onSpatialComponentUpdate(
+		SceneNode& node, F32 prevTime, F32 crntTime)
+	{}
+
 	/// @name SceneComponent overrides
 	/// @name SceneComponent overrides
 	/// @{
 	/// @{
-	Bool update(SceneNode&, F32, F32, UpdateType) override;
+	Bool update(SceneNode&, F32, F32) override;
+
+	void onUpdate(SceneNode& node, F32 prevTime, F32 crntTime) final
+	{
+		onSpatialComponentUpdate(node, prevTime, crntTime);
+	}
 
 
 	/// Disable some flags
 	/// Disable some flags
 	void reset() override;
 	void reset() override;
@@ -93,12 +106,13 @@ public:
 
 
 	static constexpr Type getClassType()
 	static constexpr Type getClassType()
 	{
 	{
-		return SPATIAL_COMPONENT;
+		return Type::SPATIAL;
 	}
 	}
 
 
 private:
 private:
-	Aabb aabb; ///< A faster shape
+	Aabb m_aabb; ///< A faster shape
 };
 };
+
 /// @}
 /// @}
 
 
 } // end namespace anki
 } // end namespace anki

+ 0 - 6
include/anki/scene/StaticGeometryNode.h

@@ -41,14 +41,11 @@ class StaticGeometryPatchNode: public SceneNode, public SpatialComponent,
 	public RenderComponent
 	public RenderComponent
 {
 {
 public:
 public:
-	/// @name Constructors/Destructor
-	/// @{
 	StaticGeometryPatchNode(
 	StaticGeometryPatchNode(
 		const CString& name, SceneGraph* scene, // Scene
 		const CString& name, SceneGraph* scene, // Scene
 		const ModelPatchBase* modelPatch); // Self
 		const ModelPatchBase* modelPatch); // Self
 
 
 	~StaticGeometryPatchNode();
 	~StaticGeometryPatchNode();
-	/// @}
 
 
 	/// @name SpatialComponent virtuals
 	/// @name SpatialComponent virtuals
 	/// @{
 	/// @{
@@ -65,11 +62,8 @@ public:
 
 
 	/// @name RenderComponent virtuals
 	/// @name RenderComponent virtuals
 	/// @{
 	/// @{
-
-	/// Implements RenderComponent::buildRendering
 	void buildRendering(RenderingBuildData& data);
 	void buildRendering(RenderingBuildData& data);
 
 
-	/// Implements  RenderComponent::getMaterial
 	const Material& getMaterial()
 	const Material& getMaterial()
 	{
 	{
 		return m_modelPatch->getMaterial();
 		return m_modelPatch->getMaterial();

+ 5 - 2
include/anki/scene/Visibility.h

@@ -48,7 +48,9 @@ public:
 	U8 m_spatialsCount;
 	U8 m_spatialsCount;
 
 
 	VisibleNode()
 	VisibleNode()
-		: m_node(nullptr), m_spatialIndices(nullptr), m_spatialsCount(0)
+	:	m_node(nullptr), 
+		m_spatialIndices(nullptr), 
+		m_spatialsCount(0)
 	{}
 	{}
 
 
 	VisibleNode(VisibleNode&& other)
 	VisibleNode(VisibleNode&& other)
@@ -90,7 +92,8 @@ public:
 			ANKI_FRUSTUMABLE_AVERAGE_VISIBLE_RENDERABLES_COUNT,
 			ANKI_FRUSTUMABLE_AVERAGE_VISIBLE_RENDERABLES_COUNT,
 		U32 lightsReservedSize =
 		U32 lightsReservedSize =
 			ANKI_FRUSTUMABLE_AVERAGE_VISIBLE_LIGHTS_COUNT)
 			ANKI_FRUSTUMABLE_AVERAGE_VISIBLE_LIGHTS_COUNT)
-		: m_renderables(frameAlloc), m_lights(frameAlloc)
+	:	m_renderables(frameAlloc), 
+		m_lights(frameAlloc)
 	{
 	{
 		m_renderables.reserve(renderablesReservedSize);
 		m_renderables.reserve(renderablesReservedSize);
 		m_lights.reserve(lightsReservedSize);
 		m_lights.reserve(lightsReservedSize);

+ 7 - 0
include/anki/util/Enum.h

@@ -19,6 +19,13 @@ struct EnumUnderlyingType
 	using Type = __underlying_type(TEnum);
 	using Type = __underlying_type(TEnum);
 };
 };
 
 
+/// Convert an enum to it's integer type.
+template<typename TEnum>
+inline typename EnumUnderlyingType<TEnum>::Type enumToType(TEnum e)
+{
+	return static_cast<typename EnumUnderlyingType<TEnum>::Type>(e);
+}
+
 #define _ANKI_ENUM_OPERATOR(enum_, qualifier_, operator_, selfOperator_) \
 #define _ANKI_ENUM_OPERATOR(enum_, qualifier_, operator_, selfOperator_) \
 	qualifier_ enum_ operator operator_ (enum_ a, enum_ b) \
 	qualifier_ enum_ operator operator_ (enum_ a, enum_ b) \
 	{ \
 	{ \

+ 25 - 10
include/anki/util/Object.h

@@ -43,22 +43,22 @@ template<typename T, typename Alloc = HeapAllocator<T>,
 class Object: public NonCopyable
 class Object: public NonCopyable
 {
 {
 public:
 public:
-	typedef T Value;
-	typedef Vector<Value*, Alloc> Container;
-	typedef TCallbackCollection CallbackCollection;
+	using Value = T;
+	using Container = Vector<Value*, Alloc>;
+	using CallbackCollection = TCallbackCollection;
 
 
 	/// Calls addChild if parent is not nullptr
 	/// Calls addChild if parent is not nullptr
 	///
 	///
-	/// @param parent_ The parent. Can be nullptr
+	/// @param parent The parent. Can be nullptr
 	/// @param alloc The allocator to use on internal allocations
 	/// @param alloc The allocator to use on internal allocations
 	/// @param callbacks A set of callbacks
 	/// @param callbacks A set of callbacks
 	Object(
 	Object(
 		Value* parent, 
 		Value* parent, 
 		const Alloc& alloc = Alloc(),
 		const Alloc& alloc = Alloc(),
 		const CallbackCollection& callbacks = CallbackCollection())
 		const CallbackCollection& callbacks = CallbackCollection())
-		:	m_parent(nullptr), // Set to nullptr or prepare for assertion
-			m_children(alloc), 
-			m_callbacks(callbacks)
+	:	m_parent(nullptr), // Set to nullptr or prepare for an assertion
+		m_children(alloc), 
+		m_callbacks(callbacks)
 	{
 	{
 		if(parent != nullptr)
 		if(parent != nullptr)
 		{
 		{
@@ -85,8 +85,6 @@ public:
 		}
 		}
 	}
 	}
 
 
-	/// @name Accessors
-	/// @{
 	const Value* getParent() const
 	const Value* getParent() const
 	{
 	{
 		return m_parent;
 		return m_parent;
@@ -116,7 +114,6 @@ public:
 	{
 	{
 		return m_children.get_allocator();
 		return m_children.get_allocator();
 	}
 	}
-	/// @}
 
 
 	/// Add a new child
 	/// Add a new child
 	void addChild(Value* child)
 	void addChild(Value* child)
@@ -184,6 +181,24 @@ public:
 		root->visitThisAndChildren(vis);
 		root->visitThisAndChildren(vis);
 	}
 	}
 
 
+	/// Visit the children and limit the depth. Use it with lambda.
+	template<typename VisitorFunc>
+	void visitChildrenMaxDepth(I maxDepth, VisitorFunc vis)
+	{
+		ANKI_ASSERT(maxDepth >= 0);
+		--maxDepth;
+
+		for(Value* c : m_children)
+		{
+			vis(*c);
+
+			if(maxDepth >= 0)
+			{
+				c->visitChildrenMaxDepth(maxDepth, vis);
+			}
+		}
+	}
+
 private:
 private:
 	Value* m_parent; ///< May be nullptr
 	Value* m_parent; ///< May be nullptr
 	Container m_children;
 	Container m_children;

+ 4 - 3
src/core/App.cpp

@@ -153,7 +153,7 @@ void App::init(const ConfigSet& config_)
 	nwinit.m_depthBits = 0;
 	nwinit.m_depthBits = 0;
 	nwinit.m_stencilBits = 0;
 	nwinit.m_stencilBits = 0;
 	nwinit.m_fullscreenDesktopRez = config.get("fullscreenDesktopResolution");
 	nwinit.m_fullscreenDesktopRez = config.get("fullscreenDesktopResolution");
-	nwinit.m_debugContext = ANKI_DEBUG;
+	nwinit.m_debugContext = config.get("debugContext");
 	m_window = m_heapAlloc.newInstance<NativeWindow>(nwinit, m_heapAlloc);	
 	m_window = m_heapAlloc.newInstance<NativeWindow>(nwinit, m_heapAlloc);	
 	m_ctx = m_window->getCurrentContext();
 	m_ctx = m_window->getCurrentContext();
 	m_window->contextMakeCurrent(nullptr);
 	m_window->contextMakeCurrent(nullptr);
@@ -288,12 +288,13 @@ void App::mainLoop(UserMainLoopCallback callback, void* userData)
 
 
 		// Update
 		// Update
 		m_input->handleEvents();
 		m_input->handleEvents();
-		m_scene->update(prevUpdateTime, crntTime, *m_renderer);
-		m_renderer->render(*m_scene);
 
 
 		// User update
 		// User update
 		userRetCode = callback(*this, userData);
 		userRetCode = callback(*this, userData);
 
 
+		m_scene->update(prevUpdateTime, crntTime, *m_renderer);
+		m_renderer->render(*m_scene);
+
 		m_gl->swapBuffers();
 		m_gl->swapBuffers();
 		ANKI_COUNTERS_RESOLVE_FRAME();
 		ANKI_COUNTERS_RESOLVE_FRAME();
 
 

+ 7 - 0
src/core/Config.cpp

@@ -89,6 +89,13 @@ Config::Config()
 	newOption("glminor", 4);
 	newOption("glminor", 4);
 	newOption("glmajor", 4);
 	newOption("glmajor", 4);
 	newOption("fullscreenDesktopResolution", false);
 	newOption("fullscreenDesktopResolution", false);
+	newOption("debugContext", 
+#if ANKI_DEBUG == 1
+		true
+#else
+		false
+#endif
+		);
 }
 }
 
 
 //==============================================================================
 //==============================================================================

+ 4 - 4
src/event/Event.cpp

@@ -13,10 +13,10 @@ namespace anki {
 //==============================================================================
 //==============================================================================
 Event::Event(EventManager* manager, F32 startTime_, F32 duration_, 
 Event::Event(EventManager* manager, F32 startTime_, F32 duration_, 
 	SceneNode* node, U8 flags)
 	SceneNode* node, U8 flags)
-	:	SceneObject(EVENT_TYPE, node, &manager->getSceneGraph()),
-		Bitset<U8>(flags), 
-		startTime(startTime_),
-		duration(duration_)
+:	SceneObject(Type::EVENT, node, &manager->getSceneGraph()),
+	Bitset<U8>(flags), 
+	startTime(startTime_),
+	duration(duration_)
 {}
 {}
 
 
 //==============================================================================
 //==============================================================================

+ 5 - 5
src/event/LightEvent.cpp

@@ -11,19 +11,19 @@ namespace anki {
 //==============================================================================
 //==============================================================================
 LightEvent::LightEvent(EventManager* manager, F32 startTime, F32 duration,
 LightEvent::LightEvent(EventManager* manager, F32 startTime, F32 duration,
 	Light* light, const LightEventData& data)
 	Light* light, const LightEventData& data)
-	: Event(manager, startTime, duration, light, EF_NONE)
+:	Event(manager, startTime, duration, light, EF_NONE)
 {
 {
 	*static_cast<LightEventData*>(this) = data;
 	*static_cast<LightEventData*>(this) = data;
 
 
 	switch(light->getLightType())
 	switch(light->getLightType())
 	{
 	{
-	case Light::LT_POINT:
+	case Light::Type::POINT:
 		{
 		{
 			PointLight* plight = static_cast<PointLight*>(light);
 			PointLight* plight = static_cast<PointLight*>(light);
 			originalRadius = plight->getRadius();
 			originalRadius = plight->getRadius();
 		}
 		}
 		break;
 		break;
-	case Light::LT_SPOT:
+	case Light::Type::SPOT:
 		ANKI_ASSERT("TODO");
 		ANKI_ASSERT("TODO");
 		break;
 		break;
 	default:
 	default:
@@ -43,14 +43,14 @@ void LightEvent::update(F32 prevUpdateTime, F32 crntTime)
 
 
 	switch(light->getLightType())
 	switch(light->getLightType())
 	{
 	{
-	case Light::LT_POINT:
+	case Light::Type::POINT:
 		{
 		{
 			PointLight* plight = static_cast<PointLight*>(light);
 			PointLight* plight = static_cast<PointLight*>(light);
 			plight->setRadius(
 			plight->setRadius(
 				factor * radiusMultiplier + originalRadius);
 				factor * radiusMultiplier + originalRadius);
 		}
 		}
 		break;
 		break;
-	case Light::LT_SPOT:
+	case Light::Type::SPOT:
 		ANKI_ASSERT("TODO");
 		ANKI_ASSERT("TODO");
 		break;
 		break;
 	default:
 	default:

+ 1 - 1
src/renderer/DebugDrawer.cpp

@@ -471,7 +471,7 @@ void SceneDebugDrawer::draw(FrustumComponent& fr) const
 //==============================================================================
 //==============================================================================
 void SceneDebugDrawer::draw(SpatialComponent& x) const
 void SceneDebugDrawer::draw(SpatialComponent& x) const
 {
 {
-	if(!x.bitsEnabled(SpatialComponent::SF_VISIBLE_CAMERA))
+	if(!x.bitsEnabled(SpatialComponent::Flag::VISIBLE_CAMERA))
 	{
 	{
 		return;
 		return;
 	}
 	}

+ 4 - 4
src/renderer/Is.cpp

@@ -115,7 +115,7 @@ public:
 
 
 			switch(light->getLightType())
 			switch(light->getLightType())
 			{
 			{
-			case Light::LT_POINT:
+			case Light::Type::POINT:
 				{
 				{
 					PointLight& l = 
 					PointLight& l = 
 						*staticCastPtr<PointLight*>(light);
 						*staticCastPtr<PointLight*>(light);
@@ -126,7 +126,7 @@ public:
 					}
 					}
 				}
 				}
 				break;
 				break;
-			case Light::LT_SPOT:
+			case Light::Type::SPOT:
 				{
 				{
 					SpotLight& l = *staticCastPtr<SpotLight*>(light);
 					SpotLight& l = *staticCastPtr<SpotLight*>(light);
 					I pos = doLight(l);
 					I pos = doLight(l);
@@ -527,10 +527,10 @@ void Is::lightPass(GlCommandBufferHandle& cmdBuff)
 		Light* light = staticCastPtr<Light*>(it.m_node);
 		Light* light = staticCastPtr<Light*>(it.m_node);
 		switch(light->getLightType())
 		switch(light->getLightType())
 		{
 		{
-		case Light::LT_POINT:
+		case Light::Type::POINT:
 			++visiblePointLightsCount;
 			++visiblePointLightsCount;
 			break;
 			break;
-		case Light::LT_SPOT:
+		case Light::Type::SPOT:
 			{
 			{
 				SpotLight* slight = staticCastPtr<SpotLight*>(light);
 				SpotLight* slight = staticCastPtr<SpotLight*>(light);
 				
 				

+ 3 - 3
src/renderer/Sm.cpp

@@ -178,20 +178,20 @@ Sm::Shadowmap* Sm::doLight(Light& light, GlCommandBufferHandle& cmdBuff)
 	for(auto& it : vi.m_renderables)
 	for(auto& it : vi.m_renderables)
 	{
 	{
 		SceneNode* node = it.m_node;
 		SceneNode* node = it.m_node;
-		MoveComponent* bmov = node->tryGetComponent<MoveComponent>();
-		FrustumComponent* bfr = node->tryGetComponent<FrustumComponent>();
-		SpatialComponent* sp = node->tryGetComponent<SpatialComponent>();
 
 
+		FrustumComponent* bfr = node->tryGetComponent<FrustumComponent>();
 		if(bfr)
 		if(bfr)
 		{
 		{
 			lastUpdate = std::max(lastUpdate, bfr->getTimestamp());
 			lastUpdate = std::max(lastUpdate, bfr->getTimestamp());
 		}
 		}
 
 
+		MoveComponent* bmov = node->tryGetComponent<MoveComponent>();
 		if(bmov)
 		if(bmov)
 		{
 		{
 			lastUpdate = std::max(lastUpdate, bmov->getTimestamp());
 			lastUpdate = std::max(lastUpdate, bmov->getTimestamp());
 		}
 		}
 
 
+		SpatialComponent* sp = node->tryGetComponent<SpatialComponent>();
 		if(sp)
 		if(sp)
 		{
 		{
 			lastUpdate = std::max(lastUpdate, sp->getTimestamp());
 			lastUpdate = std::max(lastUpdate, sp->getTimestamp());

+ 5 - 7
src/scene/Camera.cpp

@@ -23,8 +23,8 @@ Camera::Camera(
 {
 {
 	// Init components
 	// Init components
 	addComponent(static_cast<MoveComponent*>(this));
 	addComponent(static_cast<MoveComponent*>(this));
-	addComponent(static_cast<SpatialComponent*>(this));
 	addComponent(static_cast<FrustumComponent*>(this));
 	addComponent(static_cast<FrustumComponent*>(this));
+	addComponent(static_cast<SpatialComponent*>(this));
 }
 }
 
 
 //==============================================================================
 //==============================================================================
@@ -50,11 +50,10 @@ void Camera::lookAtPoint(const Vec3& point)
 //==============================================================================
 //==============================================================================
 void Camera::frustumUpdate()
 void Camera::frustumUpdate()
 {
 {
-	// Frustum
+	// Frustum (it's marked for update)
 	FrustumComponent& fr = *this;
 	FrustumComponent& fr = *this;
 	fr.setProjectionMatrix(fr.getFrustum().calculateProjectionMatrix());
 	fr.setProjectionMatrix(fr.getFrustum().calculateProjectionMatrix());
 	fr.setViewProjectionMatrix(fr.getProjectionMatrix() * fr.getViewMatrix());
 	fr.setViewProjectionMatrix(fr.getProjectionMatrix() * fr.getViewMatrix());
-	fr.markForUpdate();
 
 
 	// Spatial
 	// Spatial
 	SpatialComponent& sp = *this;
 	SpatialComponent& sp = *this;
@@ -62,15 +61,14 @@ void Camera::frustumUpdate()
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void Camera::moveUpdate(MoveComponent& move)
+void Camera::onMoveComponentUpdate(SceneNode&, F32, F32)
 {
 {
 	// Frustum
 	// Frustum
 	FrustumComponent& fr = *this;
 	FrustumComponent& fr = *this;
 
 
-	fr.setViewMatrix(Mat4(move.getWorldTransform().getInverse()));
+	fr.setViewMatrix(Mat4(getWorldTransform().getInverse()));
 	fr.setViewProjectionMatrix(fr.getProjectionMatrix() * fr.getViewMatrix());
 	fr.setViewProjectionMatrix(fr.getProjectionMatrix() * fr.getViewMatrix());
-	fr.markForUpdate();
-	fr.getFrustum().resetTransform(move.getWorldTransform());
+	fr.getFrustum().resetTransform(getWorldTransform());
 
 
 	// Spatial
 	// Spatial
 	SpatialComponent& sp = *this;
 	SpatialComponent& sp = *this;

+ 17 - 26
src/scene/Light.cpp

@@ -13,7 +13,7 @@ namespace anki {
 
 
 //==============================================================================
 //==============================================================================
 LightComponent::LightComponent(Light* node)
 LightComponent::LightComponent(Light* node)
-	: SceneComponent(LIGHT_COMPONENT, node)
+:	SceneComponent(Type::LIGHT, node)
 {}
 {}
 
 
 //==============================================================================
 //==============================================================================
@@ -23,17 +23,17 @@ LightComponent::LightComponent(Light* node)
 //==============================================================================
 //==============================================================================
 Light::Light(
 Light::Light(
 	const CString& name, SceneGraph* scene, // SceneNode
 	const CString& name, SceneGraph* scene, // SceneNode
-	LightType t) // Self
+	Type t) // Self
 :	SceneNode(name, scene),
 :	SceneNode(name, scene),
 	LightComponent(this),
 	LightComponent(this),
 	MoveComponent(this),
 	MoveComponent(this),
 	SpatialComponent(this),
 	SpatialComponent(this),
-	type(t)
+	m_type(t)
 {
 {
-	// Init components
-	addComponent(static_cast<LightComponent*>(this));
+	// Register components
 	addComponent(static_cast<MoveComponent*>(this));
 	addComponent(static_cast<MoveComponent*>(this));
 	addComponent(static_cast<SpatialComponent*>(this));
 	addComponent(static_cast<SpatialComponent*>(this));
+	addComponent(static_cast<LightComponent*>(this));
 }
 }
 
 
 //==============================================================================
 //==============================================================================
@@ -49,7 +49,6 @@ void Light::frustumUpdate()
 		fr.setProjectionMatrix(fr.getFrustum().calculateProjectionMatrix());
 		fr.setProjectionMatrix(fr.getFrustum().calculateProjectionMatrix());
 		fr.setViewProjectionMatrix(
 		fr.setViewProjectionMatrix(
 			fr.getProjectionMatrix() * fr.getViewMatrix());
 			fr.getProjectionMatrix() * fr.getViewMatrix());
-		fr.markForUpdate();
 	});
 	});
 
 
 	// Mark the spatial for update
 	// Mark the spatial for update
@@ -58,8 +57,10 @@ void Light::frustumUpdate()
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void Light::moveUpdate(MoveComponent& move)
+void Light::onMoveComponentUpdateCommon()
 {
 {
+	MoveComponent& move = *this;
+
 	// Update the frustums
 	// Update the frustums
 	iterateComponentsOfType<FrustumComponent>([&](FrustumComponent& fr)
 	iterateComponentsOfType<FrustumComponent>([&](FrustumComponent& fr)
 	{
 	{
@@ -82,7 +83,7 @@ void Light::moveUpdate(MoveComponent& move)
 void Light::loadLensFlare(const CString& filename)
 void Light::loadLensFlare(const CString& filename)
 {
 {
 	ANKI_ASSERT(!hasLensFlare());
 	ANKI_ASSERT(!hasLensFlare());
-	flaresTex.load(filename, &getResourceManager());
+	m_flaresTex.load(filename, &getResourceManager());
 }
 }
 
 
 //==============================================================================
 //==============================================================================
@@ -91,19 +92,14 @@ void Light::loadLensFlare(const CString& filename)
 
 
 //==============================================================================
 //==============================================================================
 PointLight::PointLight(const CString& name, SceneGraph* scene)
 PointLight::PointLight(const CString& name, SceneGraph* scene)
-:	Light(name, scene, LT_POINT)
+:	Light(name, scene, Light::Type::POINT)
 {}
 {}
 
 
 //==============================================================================
 //==============================================================================
-void PointLight::componentUpdated(SceneComponent& comp, 
-	SceneComponent::UpdateType)
+void PointLight::onMoveComponentUpdate(SceneNode&, F32, F32)
 {
 {
-	if(comp.getType() == MoveComponent::getClassType())
-	{
-		MoveComponent& move = comp.downCast<MoveComponent>();
-		sphereW.setCenter(move.getWorldTransform().getOrigin());
-		moveUpdate(move);
-	}
+	m_sphereW.setCenter(getWorldTransform().getOrigin());
+	onMoveComponentUpdateCommon();
 }
 }
 
 
 //==============================================================================
 //==============================================================================
@@ -112,7 +108,7 @@ void PointLight::componentUpdated(SceneComponent& comp,
 
 
 //==============================================================================
 //==============================================================================
 SpotLight::SpotLight(const CString& name, SceneGraph* scene)
 SpotLight::SpotLight(const CString& name, SceneGraph* scene)
-:	Light(name, scene, LT_SPOT),
+:	Light(name, scene, Light::Type::SPOT),
 	FrustumComponent(this, &m_frustum)
 	FrustumComponent(this, &m_frustum)
 {
 {
 	// Init components
 	// Init components
@@ -125,15 +121,10 @@ SpotLight::SpotLight(const CString& name, SceneGraph* scene)
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void SpotLight::componentUpdated(SceneComponent& comp,
-	SceneComponent::UpdateType)
+void SpotLight::onMoveComponentUpdate(SceneNode&, F32, F32)
 {
 {
-	if(comp.getType() == MoveComponent::getClassType())
-	{
-		MoveComponent& move = comp.downCast<MoveComponent>();
-		m_frustum.resetTransform(move.getWorldTransform());
-		moveUpdate(move);
-	}
+	m_frustum.resetTransform(getWorldTransform());
+	onMoveComponentUpdateCommon();
 }
 }
 
 
 //==============================================================================
 //==============================================================================

+ 72 - 105
src/scene/ModelNode.cpp

@@ -24,7 +24,8 @@ ModelPatchNode::ModelPatchNode(
 :	SceneNode(name, scene),
 :	SceneNode(name, scene),
 	RenderComponent(this),
 	RenderComponent(this),
 	SpatialComponent(this), 
 	SpatialComponent(this), 
-	m_modelPatch(modelPatch)
+	m_modelPatch(modelPatch),
+	m_spatials(getSceneAllocator())
 {
 {
 	addComponent(static_cast<RenderComponent*>(this));
 	addComponent(static_cast<RenderComponent*>(this));
 	addComponent(static_cast<SpatialComponent*>(this));
 	addComponent(static_cast<SpatialComponent*>(this));
@@ -100,109 +101,53 @@ void ModelPatchNode::getRenderWorldTransform(U index, Transform& trf)
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void ModelPatchNode::frameUpdate(F32, F32, SceneNode::UpdateType uptype)
+void ModelPatchNode::updateInstanceSpatials(
+	const SceneFrameVector<MoveComponent*>& instanceMoves)
 {
 {
-	if(uptype != SceneNode::ASYNC_UPDATE)
-	{
-		return;
-	}
+	Bool fullUpdate = false;
 
 
-	SceneNode* parent = &getParent()->downCast<SceneNode>();
-	ANKI_ASSERT(parent);
-
-	// Update first OBB
-	const MoveComponent& parentMove = parent->getComponent<MoveComponent>();
-	if(parentMove.getTimestamp() == getGlobTimestamp())
+	if(m_spatials.size() < instanceMoves.size())
 	{
 	{
-		m_obb = m_modelPatch->getBoundingShape().getTransformed(
-			parentMove.getWorldTransform());
+		// We need to add spatials
+		
+		fullUpdate = true;
 
 
-		SpatialComponent::markForUpdate();
-	}
+		U diff = instanceMoves.size() - m_spatials.size();
 
 
-	// Get the move components of the instances of the parent
-	SceneFrameVector<MoveComponent*> instanceMoves(getSceneFrameAllocator());
-	Timestamp instancesTimestamp = 0;
-	parent->visitThisAndChildren<SceneNode>([&](SceneNode& sn)
-	{		
-		if(sn.tryGetComponent<InstanceComponent>())
+		while(diff-- != 0)
 		{
 		{
-			MoveComponent& move = sn.getComponent<MoveComponent>();
+			ObbSpatialComponent* newSpatial = getSceneAllocator().
+				newInstance<ObbSpatialComponent>(this);
 
 
-			instanceMoves.push_back(&move);
+			addComponent(newSpatial);
 
 
-			instancesTimestamp = 
-				std::max(instancesTimestamp, move.getTimestamp());
+			m_spatials.push_back(newSpatial);
 		}
 		}
-	});
-
-	// Instancing?
-	if(instanceMoves.size() != 0)
+	}
+	else if(m_spatials.size() > instanceMoves.size())
 	{
 	{
-		Bool needsUpdate = false;
+		// Need to remove spatials
 
 
-		// Get the spatials and their update time
-		SceneFrameVector<ObbSpatialComponent*> 
-			spatials(getSceneFrameAllocator());
+		fullUpdate = true;
 
 
-		Timestamp spatialsTimestamp = 0;
-		U count = 0;
-
-		iterateComponentsOfType<SpatialComponent>([&](SpatialComponent& sp)
-		{
-			// Skip the first
-			if(count != 0)	
-			{
-				ObbSpatialComponent* msp = 
-					staticCastPtr<ObbSpatialComponent*>(&sp);
-		
-				spatialsTimestamp = 
-					std::max(spatialsTimestamp, msp->getTimestamp());
-
-				spatials.push_back(msp);
-			}
-			++count;
-		});
-
-		// If we need to add spatials
-		if(spatials.size() < instanceMoves.size())
-		{
-			needsUpdate = true;
-			U diff = instanceMoves.size() - spatials.size();
-
-			while(diff-- != 0)
-			{
-				ObbSpatialComponent* newSpatial = getSceneAllocator().
-					newInstance<ObbSpatialComponent>(this);
-
-				addComponent(newSpatial);
+		// TODO
+		ANKI_ASSERT(0 && "TODO");
+	}
 
 
-				spatials.push_back(newSpatial);
-			}
-		}
-		// If we need to remove spatials
-		else if(spatials.size() > instanceMoves.size())
-		{
-			needsUpdate = true;
+	U count = instanceMoves.size();
+	while(count-- != 0)
+	{
+		ObbSpatialComponent& sp = *m_spatials[count];
+		const MoveComponent& inst = *instanceMoves[count];
 
 
-			// TODO
-			ANKI_ASSERT(0 && "TODO");
-		}
-		
-		// Now update all spatials if needed
-		if(needsUpdate || spatialsTimestamp < instancesTimestamp)
+		if(sp.getTimestamp() < inst.getTimestamp() || fullUpdate)
 		{
 		{
-			for(U i = 0; i < spatials.size(); i++)
-			{
-				ObbSpatialComponent* sp = spatials[i];
-
-				sp->obb = m_modelPatch->getBoundingShape().getTransformed(
-					instanceMoves[i]->getWorldTransform());
+			sp.m_obb = m_modelPatch->getBoundingShape().getTransformed(
+				inst.getWorldTransform());
 
 
-				sp->markForUpdate();
-			}
+			sp.markForUpdate();
 		}
 		}
-	} // end instancing
+	}
 }
 }
 
 
 //==============================================================================
 //==============================================================================
@@ -215,18 +160,22 @@ ModelNode::ModelNode(
 	const CString& modelFname)
 	const CString& modelFname)
 : 	SceneNode(name, scene),
 : 	SceneNode(name, scene),
 	MoveComponent(this),
 	MoveComponent(this),
+	m_modelPatches(getSceneAllocator()),
 	m_transforms(getSceneAllocator()),
 	m_transforms(getSceneAllocator()),
 	m_transformsTimestamp(0)
 	m_transformsTimestamp(0)
 {
 {
 	addComponent(static_cast<MoveComponent*>(this));
 	addComponent(static_cast<MoveComponent*>(this));
 
 
 	m_model.load(modelFname, &getResourceManager());
 	m_model.load(modelFname, &getResourceManager());
+	m_modelPatches.reserve(m_model->getModelPatches().size());
 
 
 	for(const ModelPatchBase* patch : m_model->getModelPatches())
 	for(const ModelPatchBase* patch : m_model->getModelPatches())
 	{
 	{
 		ModelPatchNode* mpn = 
 		ModelPatchNode* mpn = 
 			getSceneGraph().newSceneNode<ModelPatchNode>(CString(), patch);
 			getSceneGraph().newSceneNode<ModelPatchNode>(CString(), patch);
 
 
+		m_modelPatches.push_back(mpn);
+
 		SceneObject::addChild(mpn);
 		SceneObject::addChild(mpn);
 	}
 	}
 
 
@@ -262,41 +211,40 @@ ModelNode::~ModelNode()
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void ModelNode::frameUpdate(F32, F32, SceneNode::UpdateType uptype)
+void ModelNode::frameUpdate(F32, F32)
 {
 {
-	if(uptype != SceneNode::ASYNC_UPDATE)
-	{
-		return;
-	}
-
-	// Get the move components of the instances of the parent
+	// Gather the move components of the instances
 	SceneFrameVector<MoveComponent*> instanceMoves(getSceneFrameAllocator());
 	SceneFrameVector<MoveComponent*> instanceMoves(getSceneFrameAllocator());
 	Timestamp instancesTimestamp = 0;
 	Timestamp instancesTimestamp = 0;
-	SceneObject::visitThisAndChildren<SceneNode>([&](SceneNode& sn)
-	{		
-		if(sn.tryGetComponent<InstanceComponent>())
+	SceneObject::visitChildren([&](SceneObject& obj)
+	{
+		if(obj.getType() == SceneNode::getClassType())
 		{
 		{
-			MoveComponent& move = sn.getComponent<MoveComponent>();
+			SceneNode& sn = obj.downCast<SceneNode>();
+			if(sn.tryGetComponent<InstanceComponent>())
+			{
+				MoveComponent& move = sn.getComponent<MoveComponent>();
 
 
-			instanceMoves.push_back(&move);
+				instanceMoves.push_back(&move);
 
 
-			instancesTimestamp = 
-				std::max(instancesTimestamp, move.getTimestamp());
+				instancesTimestamp = 
+					std::max(instancesTimestamp, move.getTimestamp());
+			}
 		}
 		}
 	});
 	});
 
 
-	// If instancing
+	// If having instances
 	if(instanceMoves.size() != 0)
 	if(instanceMoves.size() != 0)
 	{
 	{
-		Bool transformsNeedUpdate = false;
+		Bool fullUpdate = false;
 
 
 		if(instanceMoves.size() != m_transforms.size())
 		if(instanceMoves.size() != m_transforms.size())
 		{
 		{
-			transformsNeedUpdate = true;
+			fullUpdate = true;
 			m_transforms.resize(instanceMoves.size());
 			m_transforms.resize(instanceMoves.size());
 		}
 		}
 
 
-		if(transformsNeedUpdate || m_transformsTimestamp < instancesTimestamp)
+		if(fullUpdate || m_transformsTimestamp < instancesTimestamp)
 		{
 		{
 			m_transformsTimestamp = instancesTimestamp;
 			m_transformsTimestamp = instancesTimestamp;
 
 
@@ -305,6 +253,25 @@ void ModelNode::frameUpdate(F32, F32, SceneNode::UpdateType uptype)
 				m_transforms[i] = instanceMoves[i]->getWorldTransform();
 				m_transforms[i] = instanceMoves[i]->getWorldTransform();
 			}
 			}
 		}
 		}
+
+		// Update children
+		for(ModelPatchNode* child : m_modelPatches)
+		{
+			child->updateInstanceSpatials(instanceMoves);
+		}
+	}
+}
+
+//==============================================================================
+void ModelNode::onMoveComponentUpdate(SceneNode&, F32, F32)
+{
+	// Inform the children about the moves
+	for(ModelPatchNode* child : m_modelPatches)
+	{
+		child->m_obb = child->m_modelPatch->getBoundingShape().getTransformed(
+			getWorldTransform());
+
+		child->SpatialComponent::markForUpdate();
 	}
 	}
 }
 }
 
 

+ 48 - 34
src/scene/MoveComponent.cpp

@@ -9,11 +9,10 @@
 namespace anki {
 namespace anki {
 
 
 //==============================================================================
 //==============================================================================
-MoveComponent::MoveComponent(SceneNode* node, U32 flags)
-	:	SceneComponent(MOVE_COMPONENT, node),
-		Base(nullptr, node->getSceneAllocator()),
-		Bitset<U8>(flags),
-		m_node(node)
+MoveComponent::MoveComponent(SceneNode* node, Flag flags)
+:	SceneComponent(Type::MOVE, node),
+	Bitset<Flag>(flags),
+	m_node(node)
 {
 {
 	markForUpdate();
 	markForUpdate();
 }
 }
@@ -23,64 +22,79 @@ MoveComponent::~MoveComponent()
 {}
 {}
 
 
 //==============================================================================
 //==============================================================================
-Bool MoveComponent::update(SceneNode&, F32, F32, UpdateType uptype)
+Bool MoveComponent::update(SceneNode& node, F32, F32)
 {
 {
-	if(uptype == ASYNC_UPDATE && getParent() == nullptr)
-	{
-		// Call this only on roots
-		updateWorldTransform();
-	}
-
-	// move component does it's own updates
-	return false;
+	Bool updated = updateWorldTransform(node);
+	return updated;
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void MoveComponent::updateWorldTransform()
+Bool MoveComponent::updateWorldTransform(SceneNode& node)
 {
 {
 	m_prevWTrf = m_wtrf;
 	m_prevWTrf = m_wtrf;
-	const Bool dirty = bitsEnabled(MF_MARKED_FOR_UPDATE);
+	const Bool dirty = bitsEnabled(Flag::MARKED_FOR_UPDATE);
 
 
 	// If dirty then update world transform
 	// If dirty then update world transform
 	if(dirty)
 	if(dirty)
 	{
 	{
-		const MoveComponent* parent = getParent();
+		const SceneObject* parentObj = node.getParent();
 
 
-		if(parent)
+		if(parentObj)
 		{
 		{
-			if(bitsEnabled(MF_IGNORE_LOCAL_TRANSFORM))
+			const SceneNode* parent = &parentObj->downCast<SceneNode>();
+			const MoveComponent* parentMove = 
+				parent->tryGetComponent<MoveComponent>();
+
+			if(parentMove == nullptr)
+			{
+				// Parent not movable
+				m_wtrf = m_ltrf;
+			}
+			else if(bitsEnabled(Flag::IGNORE_PARENT_TRANSFORM))
+			{
+				m_wtrf = m_ltrf;
+			}
+			else if(bitsEnabled(Flag::IGNORE_LOCAL_TRANSFORM))
 			{
 			{
-				m_wtrf = parent->getWorldTransform();
+				m_wtrf = parentMove->getWorldTransform();
 			}
 			}
 			else
 			else
 			{
 			{
-				m_wtrf = 
-					parent->getWorldTransform().combineTransformations(m_ltrf);
+				m_wtrf = parentMove->getWorldTransform().
+					combineTransformations(m_ltrf);
 			}
 			}
 		}
 		}
 		else
 		else
 		{
 		{
+			// No parent
+
 			m_wtrf = m_ltrf;
 			m_wtrf = m_ltrf;
 		}
 		}
 
 
-		m_node->componentUpdated(*this, ASYNC_UPDATE);
-		timestamp = getGlobTimestamp();
-
 		// Now it's a good time to cleanse parent
 		// Now it's a good time to cleanse parent
-		disableBits(MF_MARKED_FOR_UPDATE);
+		disableBits(Flag::MARKED_FOR_UPDATE);
 	}
 	}
 
 
-	// Update the children
-	visitChildren([&](MoveComponent& mov)
+	// If this is dirty then make children dirty as well. Don't walk the 
+	// whole tree because you will re-walk it later
+	if(dirty)
 	{
 	{
-		// If parent is dirty then make children dirty as well
-		if(dirty)
+		node.visitChildrenMaxDepth(1, [](SceneObject& obj)
 		{
 		{
-			mov.markForUpdate();
-		}
+			if(obj.getType() == SceneNode::getClassType())
+			{
+				SceneNode& childNode = obj.downCast<SceneNode>();
+
+				childNode.iterateComponentsOfType<MoveComponent>([](
+					MoveComponent& mov)
+				{
+					mov.markForUpdate();
+				});
+			}
+		});
+	}
 
 
-		mov.updateWorldTransform();
-	});
+	return dirty;
 }
 }
 
 
 } // end namespace anki
 } // end namespace anki

+ 17 - 29
src/scene/ParticleEmitter.cpp

@@ -314,14 +314,11 @@ const Material& ParticleEmitter::getMaterial()
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void ParticleEmitter::componentUpdated(SceneComponent& comp, 
-	SceneComponent::UpdateType)
+void ParticleEmitter::onMoveComponentUpdate(
+	SceneNode& node, F32 prevTime, F32 crntTime)
 {
 {
-	if(comp.getType() == MoveComponent::getClassType())
-	{
-		m_identityRotation =
-			getWorldTransform().getRotation() == Mat3x4::getIdentity();
-	}
+	m_identityRotation =
+		getWorldTransform().getRotation() == Mat3x4::getIdentity();
 }
 }
 
 
 //==============================================================================
 //==============================================================================
@@ -372,14 +369,8 @@ void ParticleEmitter::createParticlesSimpleSimulation(SceneGraph* scene)
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void ParticleEmitter::frameUpdate(F32 prevUpdateTime, F32 crntTime, 
-	SceneNode::UpdateType uptype)
+void ParticleEmitter::frameUpdate(F32 prevUpdateTime, F32 crntTime)
 {
 {
-	if(uptype == SceneNode::SYNC_UPDATE)
-	{
-		return;
-	}
-
 	// - Deactivate the dead particles
 	// - Deactivate the dead particles
 	// - Calc the AABB
 	// - Calc the AABB
 	// - Calc the instancing stuff
 	// - Calc the instancing stuff
@@ -506,16 +497,20 @@ void ParticleEmitter::doInstancingCalcs()
 	// Gather the move components of the instances
 	// Gather the move components of the instances
 	SceneFrameVector<MoveComponent*> instanceMoves(getSceneFrameAllocator());
 	SceneFrameVector<MoveComponent*> instanceMoves(getSceneFrameAllocator());
 	Timestamp instancesTimestamp = 0;
 	Timestamp instancesTimestamp = 0;
-	SceneObject::visitThisAndChildren<SceneNode>([&](SceneNode& sn)
+	SceneObject::visitChildren([&](SceneObject& obj)
 	{	
 	{	
-		if(sn.tryGetComponent<InstanceComponent>())
+		if(obj.getType() == SceneObject::Type::SCENE_NODE)
 		{
 		{
-			MoveComponent& move = sn.getComponent<MoveComponent>();
+			SceneNode& sn = obj.downCast<SceneNode>();
+			if(sn.tryGetComponent<InstanceComponent>())
+			{
+				MoveComponent& move = sn.getComponent<MoveComponent>();
 
 
-			instanceMoves.push_back(&move);
+				instanceMoves.push_back(&move);
 
 
-			instancesTimestamp = 
-				std::max(instancesTimestamp, move.getTimestamp());
+				instancesTimestamp = 
+					std::max(instancesTimestamp, move.getTimestamp());
+			}
 		}
 		}
 	});
 	});
 
 
@@ -579,7 +574,7 @@ void ParticleEmitter::doInstancingCalcs()
 		
 		
 				Obb aobb = m_obb;
 				Obb aobb = m_obb;
 				aobb.setCenter(Vec4(0.0));
 				aobb.setCenter(Vec4(0.0));
-				msp->obb = aobb.getTransformed(m_transforms[count - 1]);
+				msp->m_obb = aobb.getTransformed(m_transforms[count - 1]);
 
 
 				msp->markForUpdate();
 				msp->markForUpdate();
 			}
 			}
@@ -594,14 +589,7 @@ void ParticleEmitter::doInstancingCalcs()
 //==============================================================================
 //==============================================================================
 Bool ParticleEmitter::getHasWorldTransforms()
 Bool ParticleEmitter::getHasWorldTransforms()
 {
 {
-	if(m_transforms.size() == 0)
-	{
-		return false;
-	}
-	else
-	{
-		return true;
-	}
+	return true;
 }
 }
 
 
 //==============================================================================
 //==============================================================================

+ 3 - 3
src/scene/RenderComponent.cpp

@@ -53,7 +53,7 @@ static Array<const char*, (U)BuildinMaterialVariableId::COUNT - 1>
 //==============================================================================
 //==============================================================================
 RenderComponentVariable::RenderComponentVariable(
 RenderComponentVariable::RenderComponentVariable(
 	const MaterialVariable* mvar)
 	const MaterialVariable* mvar)
-	: m_mvar(mvar)
+:	m_mvar(mvar)
 {
 {
 	ANKI_ASSERT(m_mvar);
 	ANKI_ASSERT(m_mvar);
 
 
@@ -89,8 +89,8 @@ RenderComponentVariable::~RenderComponentVariable()
 
 
 //==============================================================================
 //==============================================================================
 RenderComponent::RenderComponent(SceneNode* node)
 RenderComponent::RenderComponent(SceneNode* node)
-	:	SceneComponent(RENDER_COMPONENT, node), 
-		m_vars(node->getSceneAllocator())
+:	SceneComponent(Type::RENDER, node), 
+	m_vars(node->getSceneAllocator())
 {}
 {}
 
 
 //==============================================================================
 //==============================================================================

+ 5 - 5
src/scene/SceneComponent.cpp

@@ -9,14 +9,14 @@
 namespace anki {
 namespace anki {
 
 
 //==============================================================================
 //==============================================================================
-Bool SceneComponent::updateReal(SceneNode& node, F32 prevTime, F32 crntTime,
-	UpdateType updateType)
+Bool SceneComponent::updateReal(SceneNode& node, F32 prevTime, F32 crntTime)
 {
 {
-	Bool updated = update(node, prevTime, crntTime, updateType);
+	reset();
+	Bool updated = update(node, prevTime, crntTime);
 	if(updated)
 	if(updated)
 	{
 	{
-		node.componentUpdated(*this, updateType);
-		timestamp = getGlobTimestamp();
+		onUpdate(node, prevTime, crntTime);
+		m_timestamp = getGlobTimestamp();
 	}
 	}
 	return updated;
 	return updated;
 }
 }

+ 32 - 50
src/scene/SceneGraph.cpp

@@ -21,52 +21,49 @@ namespace anki {
 namespace {
 namespace {
 
 
 //==============================================================================
 //==============================================================================
-struct UpdateSceneNodesJob: Threadpool::Task
+class UpdateSceneNodesTask: public Threadpool::Task
 {
 {
-	SceneGraph* scene = nullptr;
-	F32 prevUpdateTime;
-	F32 crntTime;
-	Barrier* barrier = nullptr;
+public:
+	SceneGraph* m_scene = nullptr;
+	F32 m_prevUpdateTime;
+	F32 m_crntTime;
 
 
 	void operator()(U32 taskId, PtrSize threadsCount)
 	void operator()(U32 taskId, PtrSize threadsCount)
 	{
 	{
-		ANKI_ASSERT(scene);
 		PtrSize start, end;
 		PtrSize start, end;
 		choseStartEnd(
 		choseStartEnd(
-			taskId, threadsCount, scene->getSceneNodesCount(), start, end);
+			taskId, threadsCount, m_scene->getSceneNodesCount(), start, end);
 
 
-		// First update the move components
-		scene->iterateSceneNodes(start, end, [&](SceneNode& node)
+		// Start with the root nodes
+		m_scene->iterateSceneNodes(start, end, [&](SceneNode& node)
 		{
 		{
-			MoveComponent* move = node.tryGetComponent<MoveComponent>();
-
-			if(move)
+			if(node.getParent() == nullptr)
 			{
 			{
-				move->updateReal(node, prevUpdateTime, crntTime,
-					SceneComponent::ASYNC_UPDATE);
+				updateInternal(node, m_prevUpdateTime, m_crntTime);
 			}
 			}
 		});
 		});
+	}
 
 
-		barrier->wait();
+	void updateInternal(SceneNode& node, F32 prevTime, F32 crntTime)
+	{
+		// Components update
+		node.iterateComponents([&](SceneComponent& comp)
+		{
+			comp.updateReal(node, prevTime, crntTime);
+		});
 
 
-		// Update the rest of the components
-		auto moveComponentTypeId = MoveComponent::getClassType();
-		scene->iterateSceneNodes(start, end, [&](SceneNode& node)
+		// Update children
+		node.visitChildren([&](SceneObject& obj)
 		{
 		{
-			// Components update
-			node.iterateComponents([&](SceneComponent& comp)
+			if(obj.getType() == SceneObject::Type::SCENE_NODE)
 			{
 			{
-				if(comp.getType() != moveComponentTypeId)
-				{
-					comp.updateReal(node, prevUpdateTime, crntTime, 
-						SceneComponent::ASYNC_UPDATE);
-				}
-			});
-
-			// Frame update
-			node.frameUpdate(prevUpdateTime, crntTime, 
-				SceneNode::ASYNC_UPDATE);
+				SceneNode& child = obj.downCast<SceneNode>();
+				updateInternal(child, prevTime, crntTime);
+			}
 		});
 		});
+
+		// Frame update
+		node.frameUpdate(prevTime, crntTime);
 	}
 	}
 };
 };
 
 
@@ -214,19 +211,6 @@ void SceneGraph::update(F32 prevUpdateTime, F32 crntTime, Renderer& renderer)
 	// Delete nodes
 	// Delete nodes
 	deleteNodesMarkedForDeletion();
 	deleteNodesMarkedForDeletion();
 
 
-	// Sync updates
-	iterateSceneNodes([&](SceneNode& node)
-	{
-		node.iterateComponents([&](SceneComponent& comp)
-		{
-			comp.reset();
-			comp.updateReal(node, prevUpdateTime, crntTime, 
-				SceneComponent::SYNC_UPDATE);
-		});
-
-		node.frameUpdate(prevUpdateTime, crntTime, SceneNode::SYNC_UPDATE);
-	});
-
 	Threadpool& threadPool = *m_threadpool;
 	Threadpool& threadPool = *m_threadpool;
 	(void)threadPool;
 	(void)threadPool;
 
 
@@ -236,17 +220,15 @@ void SceneGraph::update(F32 prevUpdateTime, F32 crntTime, Renderer& renderer)
 	m_events.updateAllEvents(prevUpdateTime, crntTime);
 	m_events.updateAllEvents(prevUpdateTime, crntTime);
 
 
 	// Then the rest
 	// Then the rest
-	Array<UpdateSceneNodesJob, Threadpool::MAX_THREADS> jobs2;
-	Barrier barrier(threadPool.getThreadsCount());
+	Array<UpdateSceneNodesTask, Threadpool::MAX_THREADS> jobs2;
 
 
 	for(U i = 0; i < threadPool.getThreadsCount(); i++)
 	for(U i = 0; i < threadPool.getThreadsCount(); i++)
 	{
 	{
-		UpdateSceneNodesJob& job = jobs2[i];
+		UpdateSceneNodesTask& job = jobs2[i];
 
 
-		job.scene = this;
-		job.prevUpdateTime = prevUpdateTime;
-		job.crntTime = crntTime;
-		job.barrier = &barrier;
+		job.m_scene = this;
+		job.m_prevUpdateTime = prevUpdateTime;
+		job.m_crntTime = crntTime;
 
 
 		threadPool.assignNewTask(i, &job);
 		threadPool.assignNewTask(i, &job);
 	}
 	}

+ 1 - 1
src/scene/SceneNode.cpp

@@ -10,7 +10,7 @@ namespace anki {
 
 
 //==============================================================================
 //==============================================================================
 SceneNode::SceneNode(const CString& name, SceneGraph* scene)
 SceneNode::SceneNode(const CString& name, SceneGraph* scene)
-:	SceneObject(SCENE_NODE_TYPE, nullptr, scene),
+:	SceneObject(Type::SCENE_NODE, nullptr, scene),
 	m_name(getSceneAllocator()),
 	m_name(getSceneAllocator()),
 	m_components(getSceneAllocator())
 	m_components(getSceneAllocator())
 {
 {

+ 12 - 12
src/scene/SceneObject.cpp

@@ -9,32 +9,32 @@
 namespace anki {
 namespace anki {
 
 
 //==============================================================================
 //==============================================================================
-SceneObject::SceneObject(Type type, SceneObject* parent, SceneGraph* scene_)
-	:	Base(parent, scene_->getAllocator()),
-		scene(scene_),
-		flags((U8)type)
+SceneObject::SceneObject(Type type, SceneObject* parent, SceneGraph* scene)
+:	Base(parent, scene->getAllocator()),
+	m_scene(scene),
+	m_bits(static_cast<U8>(type))
 {
 {
-	ANKI_ASSERT(scene);
+	ANKI_ASSERT(m_scene);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
 SceneObject::~SceneObject()
 SceneObject::~SceneObject()
 {
 {
-	scene->decreaseObjectsMarkedForDeletion();
+	m_scene->decreaseObjectsMarkedForDeletion();
 }
 }
 
 
 //==============================================================================
 //==============================================================================
 SceneAllocator<U8> SceneObject::getSceneAllocator() const
 SceneAllocator<U8> SceneObject::getSceneAllocator() const
 {
 {
-	ANKI_ASSERT(scene);
-	return scene->getAllocator();
+	ANKI_ASSERT(m_scene);
+	return m_scene->getAllocator();
 }
 }
 
 
 //==============================================================================
 //==============================================================================
 SceneAllocator<U8> SceneObject::getSceneFrameAllocator() const
 SceneAllocator<U8> SceneObject::getSceneFrameAllocator() const
 {
 {
-	ANKI_ASSERT(scene);
-	return scene->getFrameAllocator();
+	ANKI_ASSERT(m_scene);
+	return m_scene->getFrameAllocator();
 }
 }
 
 
 //==============================================================================
 //==============================================================================
@@ -44,8 +44,8 @@ void SceneObject::markForDeletion()
 	// want to increase the counter again
 	// want to increase the counter again
 	if(!isMarkedForDeletion())
 	if(!isMarkedForDeletion())
 	{
 	{
-		flags |= MARKED_FOR_DELETION;
-		scene->increaseObjectsMarkedForDeletion();
+		m_bits |= enumToType(Flag::MARKED_FOR_DELETION);
+		m_scene->increaseObjectsMarkedForDeletion();
 	}
 	}
 
 
 	visitChildren([](SceneObject& obj)
 	visitChildren([](SceneObject& obj)

+ 9 - 11
src/scene/SpatialComponent.cpp

@@ -9,8 +9,9 @@
 namespace anki {
 namespace anki {
 
 
 //==============================================================================
 //==============================================================================
-SpatialComponent::SpatialComponent(SceneNode* node, U32 flags)
-	: SceneComponent(SPATIAL_COMPONENT, node), Bitset<U8>(flags)
+SpatialComponent::SpatialComponent(SceneNode* node, Flag flags)
+:	SceneComponent(Type::SPATIAL, node), 
+	Bitset<Flag>(flags)
 {
 {
 	markForUpdate();
 	markForUpdate();
 }
 }
@@ -20,18 +21,15 @@ SpatialComponent::~SpatialComponent()
 {}
 {}
 
 
 //==============================================================================
 //==============================================================================
-Bool SpatialComponent::update(SceneNode&, F32, F32, UpdateType uptype)
+Bool SpatialComponent::update(SceneNode&, F32, F32)
 {
 {
 	Bool updated = false;
 	Bool updated = false;
 
 
-	if(uptype == ASYNC_UPDATE)
+	updated = bitsEnabled(Flag::MARKED_FOR_UPDATE);
+	if(updated)
 	{
 	{
-		updated = bitsEnabled(SF_MARKED_FOR_UPDATE);
-		if(updated)
-		{
-			getSpatialCollisionShape().computeAabb(aabb);
-			disableBits(SF_MARKED_FOR_UPDATE);
-		}
+		getSpatialCollisionShape().computeAabb(m_aabb);
+		disableBits(Flag::MARKED_FOR_UPDATE);
 	}
 	}
 
 
 	return updated;
 	return updated;
@@ -40,7 +38,7 @@ Bool SpatialComponent::update(SceneNode&, F32, F32, UpdateType uptype)
 //==============================================================================
 //==============================================================================
 void SpatialComponent::reset()
 void SpatialComponent::reset()
 {
 {
-	disableBits(SF_VISIBLE_ANY);
+	disableBits(Flag::VISIBLE_ANY);
 }
 }
 
 
 } // end namespace anki
 } // end namespace anki

+ 2 - 1
src/scene/StaticGeometryNode.cpp

@@ -15,7 +15,8 @@ namespace anki {
 //==============================================================================
 //==============================================================================
 StaticGeometrySpatial::StaticGeometrySpatial(
 StaticGeometrySpatial::StaticGeometrySpatial(
 	SceneNode* node, const Obb* obb)
 	SceneNode* node, const Obb* obb)
-	: SpatialComponent(node), m_obb(obb)
+:	SpatialComponent(node), 
+	m_obb(obb)
 {}
 {}
 
 
 //==============================================================================
 //==============================================================================

+ 9 - 9
src/scene/Visibility.cpp

@@ -68,8 +68,8 @@ public:
 			// Test all spatial components of that node
 			// Test all spatial components of that node
 			struct SpatialTemp
 			struct SpatialTemp
 			{
 			{
-				SpatialComponent* sp;
-				U8 idx;
+				SpatialComponent* m_sp;
+				U8 m_idx;
 			};
 			};
 			Array<SpatialTemp, ANKI_GL_MAX_SUB_DRAWCALLS> sps;
 			Array<SpatialTemp, ANKI_GL_MAX_SUB_DRAWCALLS> sps;
 
 
@@ -82,11 +82,11 @@ public:
 				{
 				{
 					// Inside
 					// Inside
 					ANKI_ASSERT(spIdx < MAX_U8);
 					ANKI_ASSERT(spIdx < MAX_U8);
-					sps[count++] = SpatialTemp{&sp, (U8)spIdx};
+					sps[count++] = SpatialTemp{&sp, static_cast<U8>(spIdx)};
 
 
 					sp.enableBits(isLight 
 					sp.enableBits(isLight 
-						? SpatialComponent::SF_VISIBLE_LIGHT 
-						: SpatialComponent::SF_VISIBLE_CAMERA);
+						? SpatialComponent::Flag::VISIBLE_LIGHT 
+						: SpatialComponent::Flag::VISIBLE_CAMERA);
 				}
 				}
 
 
 				++spIdx;
 				++spIdx;
@@ -100,10 +100,10 @@ public:
 			// Sort spatials
 			// Sort spatials
 			Vec4 origin = testedFr.getFrustumOrigin();
 			Vec4 origin = testedFr.getFrustumOrigin();
 			std::sort(sps.begin(), sps.begin() + count, 
 			std::sort(sps.begin(), sps.begin() + count, 
-				[&](const SpatialTemp& a, const SpatialTemp& b) -> Bool
+				[origin](const SpatialTemp& a, const SpatialTemp& b) -> Bool
 			{
 			{
-				Vec4 spa = a.sp->getSpatialOrigin();
-				Vec4 spb = b.sp->getSpatialOrigin();
+				Vec4 spa = a.m_sp->getSpatialOrigin();
+				Vec4 spb = b.m_sp->getSpatialOrigin();
 
 
 				F32 dist0 = origin.getDistanceSquared(spa);
 				F32 dist0 = origin.getDistanceSquared(spa);
 				F32 dist1 = origin.getDistanceSquared(spb);
 				F32 dist1 = origin.getDistanceSquared(spb);
@@ -117,7 +117,7 @@ public:
 			visibleNode.m_spatialIndices = frameAlloc.newArray<U8>(count);
 			visibleNode.m_spatialIndices = frameAlloc.newArray<U8>(count);
 			for(U i = 0; i < count; i++)
 			for(U i = 0; i < count; i++)
 			{
 			{
-				visibleNode.m_spatialIndices[i] = sps[i].idx;
+				visibleNode.m_spatialIndices[i] = sps[i].m_idx;
 			}
 			}
 
 
 			// Do something with the result
 			// Do something with the result

+ 4 - 0
src/util/Thread.cpp

@@ -41,6 +41,8 @@ Bool Barrier::wait()
 // ThreadpoolThread                                                            =
 // ThreadpoolThread                                                            =
 //==============================================================================
 //==============================================================================
 
 
+#if !ANKI_DISABLE_THREADPOOL_THREADING
+
 namespace detail {
 namespace detail {
 
 
 /// The thread that executes a Threadpool::Task
 /// The thread that executes a Threadpool::Task
@@ -114,6 +116,8 @@ private:
 
 
 } // end namespace detail
 } // end namespace detail
 
 
+#endif
+
 //==============================================================================
 //==============================================================================
 // Threadpool                                                                  =
 // Threadpool                                                                  =
 //==============================================================================
 //==============================================================================

+ 10 - 5
testapp/Main.cpp

@@ -106,7 +106,9 @@ void init()
 	spot->setDistance(30.0);
 	spot->setDistance(30.0);
 	spot->setShadowEnabled(true);
 	spot->setShadowEnabled(true);
 
 
+#endif
 
 
+#if 1
 	spot = scene.newSceneNode<SpotLight>("spot1");
 	spot = scene.newSceneNode<SpotLight>("spot1");
 	spot->setOuterAngle(toRad(45.0));
 	spot->setOuterAngle(toRad(45.0));
 	spot->setInnerAngle(toRad(15.0));
 	spot->setInnerAngle(toRad(15.0));
@@ -199,9 +201,8 @@ void init()
 #if 1
 #if 1
 	// horse
 	// horse
 	horse = scene.newSceneNode<ModelNode>("horse", "models/horse/horse.ankimdl");
 	horse = scene.newSceneNode<ModelNode>("horse", "models/horse/horse.ankimdl");
-	horse->setLocalTransform(Transform(Vec4(-2, 0, 0, 0.0), Mat3x4::getIdentity(),
-		0.7));
-
+	horse->setLocalTransform(
+		Transform(Vec4(-2, 0, 0, 0.0), Mat3x4::getIdentity(), 0.7));
 
 
 	//horse = scene.newSceneNode<ModelNode>("crate", "models/crate0/crate0.ankimdl");
 	//horse = scene.newSceneNode<ModelNode>("crate", "models/crate0/crate0.ankimdl");
 	//horse->setLocalTransform(Transform(Vec3(2, 10.0, 0), Mat3::getIdentity(),
 	//horse->setLocalTransform(Transform(Vec3(2, 10.0, 0), Mat3::getIdentity(),
@@ -399,7 +400,10 @@ I32 mainLoopExtra(App& app, void*)
 	if(in.getKey(KeyCode::LEFT)) mover->rotateLocalY(ang);
 	if(in.getKey(KeyCode::LEFT)) mover->rotateLocalY(ang);
 	if(in.getKey(KeyCode::RIGHT)) mover->rotateLocalY(-ang);
 	if(in.getKey(KeyCode::RIGHT)) mover->rotateLocalY(-ang);
 
 
-	if(in.getKey(KeyCode::A)) mover->moveLocalX(-dist);
+	if(in.getKey(KeyCode::A))
+	{
+		mover->moveLocalX(-dist);
+	}
 	if(in.getKey(KeyCode::D)) mover->moveLocalX(dist);
 	if(in.getKey(KeyCode::D)) mover->moveLocalX(dist);
 	if(in.getKey(KeyCode::Z)) mover->moveLocalY(dist);
 	if(in.getKey(KeyCode::Z)) mover->moveLocalY(dist);
 	if(in.getKey(KeyCode::SPACE)) mover->moveLocalY(-dist);
 	if(in.getKey(KeyCode::SPACE)) mover->moveLocalY(-dist);
@@ -506,7 +510,8 @@ void initSubsystems(int argc, char* argv[])
 	config.set("tilesXCount", 16);
 	config.set("tilesXCount", 16);
 	config.set("tilesYCount", 16);
 	config.set("tilesYCount", 16);
 
 
-	config.set("fullscreenDesktopResolution", true);
+	config.set("fullscreenDesktopResolution", false);
+	config.set("debugContext", false);
 
 
 	app = new App(config, allocAligned, nullptr);
 	app = new App(config, allocAligned, nullptr);