Browse Source

Refactor the scene by removing some fat

Panagiotis Christopoulos Charitos 7 years ago
parent
commit
48f17af9a8
64 changed files with 459 additions and 1135 deletions
  1. 0 2
      src/anki/Scene.h
  2. 1 1
      src/anki/physics/PhysicsWorld.cpp
  3. 9 9
      src/anki/scene/BodyNode.cpp
  4. 2 0
      src/anki/scene/BodyNode.h
  5. 18 18
      src/anki/scene/CameraNode.cpp
  6. 3 0
      src/anki/scene/CameraNode.h
  7. 18 18
      src/anki/scene/DecalNode.cpp
  8. 3 3
      src/anki/scene/DecalNode.h
  9. 7 7
      src/anki/scene/FogDensityNode.cpp
  10. 20 19
      src/anki/scene/LightNode.cpp
  11. 55 198
      src/anki/scene/ModelNode.cpp
  12. 10 42
      src/anki/scene/ModelNode.h
  13. 14 14
      src/anki/scene/OccluderNode.cpp
  14. 2 2
      src/anki/scene/OccluderNode.h
  15. 15 20
      src/anki/scene/ParticleEmitterNode.cpp
  16. 7 5
      src/anki/scene/PhysicsDebugNode.cpp
  17. 17 17
      src/anki/scene/PlayerNode.cpp
  18. 3 2
      src/anki/scene/PlayerNode.h
  19. 11 11
      src/anki/scene/ReflectionProbeNode.cpp
  20. 2 2
      src/anki/scene/ReflectionProbeNode.h
  21. 0 125
      src/anki/scene/ReflectionProxyNode.cpp
  22. 0 47
      src/anki/scene/ReflectionProxyNode.h
  23. 20 4
      src/anki/scene/SceneGraph.cpp
  24. 3 3
      src/anki/scene/SceneNode.cpp
  25. 10 17
      src/anki/scene/SceneNode.h
  26. 4 4
      src/anki/scene/StaticGeometryNode.cpp
  27. 2 2
      src/anki/scene/StaticGeometryNode.h
  28. 7 8
      src/anki/scene/TriggerNode.cpp
  29. 0 15
      src/anki/scene/Visibility.cpp
  30. 3 3
      src/anki/scene/components/BodyComponent.h
  31. 4 2
      src/anki/scene/components/DecalComponent.cpp
  32. 2 1
      src/anki/scene/components/DecalComponent.h
  33. 2 9
      src/anki/scene/components/FogDensityComponent.h
  34. 21 3
      src/anki/scene/components/FrustumComponent.cpp
  35. 13 13
      src/anki/scene/components/FrustumComponent.h
  36. 12 10
      src/anki/scene/components/JointComponent.cpp
  37. 5 2
      src/anki/scene/components/JointComponent.h
  38. 4 2
      src/anki/scene/components/LensFlareComponent.cpp
  39. 1 7
      src/anki/scene/components/LensFlareComponent.h
  40. 5 3
      src/anki/scene/components/LightComponent.cpp
  41. 5 4
      src/anki/scene/components/LightComponent.h
  42. 4 10
      src/anki/scene/components/MoveComponent.cpp
  43. 2 16
      src/anki/scene/components/MoveComponent.h
  44. 2 2
      src/anki/scene/components/OccluderComponent.h
  45. 3 3
      src/anki/scene/components/PlayerControllerComponent.h
  46. 5 3
      src/anki/scene/components/ReflectionProbeComponent.h
  47. 0 62
      src/anki/scene/components/ReflectionProxyComponent.cpp
  48. 0 59
      src/anki/scene/components/ReflectionProxyComponent.h
  49. 10 8
      src/anki/scene/components/RenderComponent.cpp
  50. 13 2
      src/anki/scene/components/RenderComponent.h
  51. 0 61
      src/anki/scene/components/SceneComponent.cpp
  52. 16 40
      src/anki/scene/components/SceneComponent.h
  53. 8 5
      src/anki/scene/components/ScriptComponent.cpp
  54. 2 1
      src/anki/scene/components/ScriptComponent.h
  55. 10 4
      src/anki/scene/components/SkinComponent.cpp
  56. 2 1
      src/anki/scene/components/SkinComponent.h
  57. 8 4
      src/anki/scene/components/SpatialComponent.cpp
  58. 15 4
      src/anki/scene/components/SpatialComponent.h
  59. 13 14
      src/anki/scene/components/TriggerComponent.cpp
  60. 1 2
      src/anki/scene/components/TriggerComponent.h
  61. 2 2
      src/anki/scene/events/EventManager.cpp
  62. 3 3
      src/anki/scene/events/EventManager.h
  63. 0 139
      src/anki/script/Scene.cpp
  64. 0 16
      src/anki/script/Scene.xml

+ 0 - 2
src/anki/Scene.h

@@ -14,7 +14,6 @@
 #include <anki/scene/StaticCollisionNode.h>
 #include <anki/scene/BodyNode.h>
 #include <anki/scene/ReflectionProbeNode.h>
-#include <anki/scene/ReflectionProxyNode.h>
 #include <anki/scene/PlayerNode.h>
 #include <anki/scene/OccluderNode.h>
 #include <anki/scene/DecalNode.h>
@@ -35,7 +34,6 @@
 #include <anki/scene/components/LightComponent.h>
 #include <anki/scene/components/BodyComponent.h>
 #include <anki/scene/components/SpatialComponent.h>
-#include <anki/scene/components/ReflectionProxyComponent.h>
 #include <anki/scene/components/FrustumComponent.h>
 #include <anki/scene/components/JointComponent.h>
 #include <anki/scene/components/TriggerComponent.h>

+ 1 - 1
src/anki/physics/PhysicsWorld.cpp

@@ -158,7 +158,7 @@ PhysicsWorld::~PhysicsWorld()
 	m_collisionConfig.destroy();
 	m_broadphase.destroy();
 	m_gpc.destroy();
-	m_alloc.destroy(m_filterCallback);
+	m_alloc.deleteInstance(m_filterCallback);
 
 	gAlloc = nullptr;
 }

+ 9 - 9
src/anki/scene/BodyNode.cpp

@@ -15,23 +15,23 @@ namespace anki
 {
 
 /// Body feedback component.
-class BodyFeedbackComponent : public SceneComponent
+class BodyNode::FeedbackComponent : public SceneComponent
 {
 public:
-	BodyFeedbackComponent(SceneNode* node)
-		: SceneComponent(SceneComponentType::NONE, node)
+	FeedbackComponent()
+		: SceneComponent(SceneComponentType::NONE)
 	{
 	}
 
-	ANKI_USE_RESULT Error update(Second, Second, Bool& updated) override
+	ANKI_USE_RESULT Error update(SceneNode& node, Second prevTime, Second crntTime, Bool& updated) override
 	{
 		updated = false;
 
-		BodyComponent& bodyc = m_node->getComponent<BodyComponent>();
+		BodyComponent& bodyc = node.getComponent<BodyComponent>();
 
-		if(bodyc.getTimestamp() == m_node->getGlobalTimestamp())
+		if(bodyc.getTimestamp() == node.getGlobalTimestamp())
 		{
-			MoveComponent& move = m_node->getComponent<MoveComponent>();
+			MoveComponent& move = node.getComponent<MoveComponent>();
 			move.setLocalTransform(bodyc.getTransform());
 		}
 
@@ -61,13 +61,13 @@ Error BodyNode::init(const CString& resourceFname)
 	m_body->setUserData(this);
 
 	// Joint component
-	newComponent<JointComponent>();
+	newComponent<JointComponent>(this);
 
 	// Body component
 	newComponent<BodyComponent>(m_body);
 
 	// Feedback component
-	newComponent<BodyFeedbackComponent>();
+	newComponent<FeedbackComponent>();
 
 	// Move component
 	newComponent<MoveComponent>(MoveComponentFlag::IGNORE_PARENT_TRANSFORM);

+ 2 - 0
src/anki/scene/BodyNode.h

@@ -25,6 +25,8 @@ public:
 	ANKI_USE_RESULT Error init(const CString& resourceFname);
 
 private:
+	class FeedbackComponent;
+
 	CollisionResourcePtr m_rsrc;
 	PhysicsBodyPtr m_body;
 };

+ 18 - 18
src/anki/scene/CameraNode.cpp

@@ -11,22 +11,22 @@ namespace anki
 {
 
 /// Feedback component.
-class CameraMoveFeedbackComponent : public SceneComponent
+class CameraNode::MoveFeedbackComponent : public SceneComponent
 {
 public:
-	CameraMoveFeedbackComponent(SceneNode* node)
-		: SceneComponent(SceneComponentType::NONE, node)
+	MoveFeedbackComponent()
+		: SceneComponent(SceneComponentType::NONE)
 	{
 	}
 
-	ANKI_USE_RESULT Error update(Second, Second, Bool& updated) override
+	ANKI_USE_RESULT Error update(SceneNode& node, Second prevTime, Second crntTime, Bool& updated) override
 	{
 		updated = false;
 
-		MoveComponent& move = m_node->getComponent<MoveComponent>();
-		if(move.getTimestamp() == getGlobalTimestamp())
+		MoveComponent& move = node.getComponent<MoveComponent>();
+		if(move.getTimestamp() == node.getGlobalTimestamp())
 		{
-			CameraNode& cam = *static_cast<CameraNode*>(m_node);
+			CameraNode& cam = static_cast<CameraNode&>(node);
 			cam.onMoveComponentUpdate(move);
 		}
 
@@ -35,22 +35,22 @@ public:
 };
 
 /// Feedback component.
-class CameraFrustumFeedbackComponent : public SceneComponent
+class CameraNode::FrustumFeedbackComponent : public SceneComponent
 {
 public:
-	CameraFrustumFeedbackComponent(SceneNode* node)
-		: SceneComponent(SceneComponentType::NONE, node)
+	FrustumFeedbackComponent()
+		: SceneComponent(SceneComponentType::NONE)
 	{
 	}
 
-	ANKI_USE_RESULT Error update(Second, Second, Bool& updated) override
+	ANKI_USE_RESULT Error update(SceneNode& node, Second prevTime, Second crntTime, Bool& updated) override
 	{
 		updated = false;
 
-		FrustumComponent& fr = m_node->getComponent<FrustumComponent>();
-		if(fr.getTimestamp() == getGlobalTimestamp())
+		FrustumComponent& fr = node.getComponent<FrustumComponent>();
+		if(fr.getTimestamp() == node.getGlobalTimestamp())
 		{
-			CameraNode& cam = *static_cast<CameraNode*>(m_node);
+			CameraNode& cam = static_cast<CameraNode&>(node);
 			cam.onFrustumComponentUpdate(fr);
 		}
 
@@ -70,10 +70,10 @@ Error CameraNode::init(Frustum* frustum)
 	newComponent<MoveComponent>();
 
 	// Feedback component
-	newComponent<CameraMoveFeedbackComponent>();
+	newComponent<MoveFeedbackComponent>();
 
 	// Frustum component
-	FrustumComponent* frc = newComponent<FrustumComponent>(frustum);
+	FrustumComponent* frc = newComponent<FrustumComponent>(this, frustum);
 	frc->setEnabledVisibilityTests(
 		FrustumComponentVisibilityTestFlag::RENDER_COMPONENTS | FrustumComponentVisibilityTestFlag::LIGHT_COMPONENTS
 		| FrustumComponentVisibilityTestFlag::LENS_FLARE_COMPONENTS
@@ -82,10 +82,10 @@ Error CameraNode::init(Frustum* frustum)
 		| FrustumComponentVisibilityTestFlag::FOG_DENSITY_COMPONENTS | FrustumComponentVisibilityTestFlag::EARLY_Z);
 
 	// Feedback component #2
-	newComponent<CameraFrustumFeedbackComponent>();
+	newComponent<FrustumFeedbackComponent>();
 
 	// Spatial component
-	newComponent<SpatialComponent>(frustum);
+	newComponent<SpatialComponent>(this, frustum);
 
 	return Error::NONE;
 }

+ 3 - 0
src/anki/scene/CameraNode.h

@@ -44,6 +44,9 @@ public:
 	void lookAtPoint(const Vec3& point);
 
 private:
+	class MoveFeedbackComponent;
+	class FrustumFeedbackComponent;
+
 	Type m_type;
 
 	/// Called when moved.

+ 18 - 18
src/anki/scene/DecalNode.cpp

@@ -12,23 +12,23 @@ namespace anki
 {
 
 /// Decal feedback component.
-class DecalMoveFeedbackComponent : public SceneComponent
+class DecalNode::MoveFeedbackComponent : public SceneComponent
 {
 public:
-	DecalMoveFeedbackComponent(SceneNode* node)
-		: SceneComponent(SceneComponentType::NONE, node)
+	MoveFeedbackComponent()
+		: SceneComponent(SceneComponentType::NONE)
 	{
 	}
 
-	ANKI_USE_RESULT Error update(Second, Second, Bool& updated) override
+	ANKI_USE_RESULT Error update(SceneNode& node, Second prevTime, Second crntTime, Bool& updated) override
 	{
 		updated = false;
 
-		MoveComponent& movec = m_node->getComponent<MoveComponent>();
+		MoveComponent& movec = node.getComponent<MoveComponent>();
 
-		if(movec.getTimestamp() == m_node->getGlobalTimestamp())
+		if(movec.getTimestamp() == node.getGlobalTimestamp())
 		{
-			static_cast<DecalNode*>(m_node)->onMove(movec);
+			static_cast<DecalNode&>(node).onMove(movec);
 		}
 
 		return Error::NONE;
@@ -36,23 +36,23 @@ public:
 };
 
 /// Decal feedback component.
-class DecalShapeFeedbackComponent : public SceneComponent
+class DecalNode::ShapeFeedbackComponent : public SceneComponent
 {
 public:
-	DecalShapeFeedbackComponent(SceneNode* node)
-		: SceneComponent(SceneComponentType::NONE, node)
+	ShapeFeedbackComponent()
+		: SceneComponent(SceneComponentType::NONE)
 	{
 	}
 
-	ANKI_USE_RESULT Error update(Second, Second, Bool& updated) override
+	ANKI_USE_RESULT Error update(SceneNode& node, Second prevTime, Second crntTime, Bool& updated) override
 	{
 		updated = false;
 
-		DecalComponent& decalc = m_node->getComponent<DecalComponent>();
+		DecalComponent& decalc = node.getComponent<DecalComponent>();
 
-		if(decalc.getTimestamp() == m_node->getGlobalTimestamp())
+		if(decalc.getTimestamp() == node.getGlobalTimestamp())
 		{
-			static_cast<DecalNode*>(m_node)->onDecalUpdated();
+			static_cast<DecalNode&>(node).onDecalUpdated();
 		}
 
 		return Error::NONE;
@@ -66,10 +66,10 @@ DecalNode::~DecalNode()
 Error DecalNode::init()
 {
 	newComponent<MoveComponent>();
-	newComponent<DecalMoveFeedbackComponent>();
-	DecalComponent* decalc = newComponent<DecalComponent>();
-	newComponent<DecalShapeFeedbackComponent>();
-	newComponent<SpatialComponent>(&decalc->getBoundingVolume());
+	newComponent<MoveFeedbackComponent>();
+	DecalComponent* decalc = newComponent<DecalComponent>(this);
+	newComponent<ShapeFeedbackComponent>();
+	newComponent<SpatialComponent>(this, &decalc->getBoundingVolume());
 
 	return Error::NONE;
 }

+ 3 - 3
src/anki/scene/DecalNode.h

@@ -17,9 +17,6 @@ namespace anki
 /// Node that has a decal component.
 class DecalNode : public SceneNode
 {
-	friend class DecalMoveFeedbackComponent;
-	friend class DecalShapeFeedbackComponent;
-
 public:
 	DecalNode(SceneGraph* scene, CString name)
 		: SceneNode(scene, name)
@@ -31,6 +28,9 @@ public:
 	ANKI_USE_RESULT Error init();
 
 private:
+	class MoveFeedbackComponent;
+	class ShapeFeedbackComponent;
+
 	void onMove(MoveComponent& movec);
 	void onDecalUpdated();
 };

+ 7 - 7
src/anki/scene/FogDensityNode.cpp

@@ -14,19 +14,19 @@ namespace anki
 class FogDensityNode::FeedbackComponent : public SceneComponent
 {
 public:
-	FeedbackComponent(SceneNode* node)
-		: SceneComponent(SceneComponentType::NONE, node)
+	FeedbackComponent()
+		: SceneComponent(SceneComponentType::NONE)
 	{
 	}
 
-	ANKI_USE_RESULT Error update(Second, Second, Bool& updated) override
+	ANKI_USE_RESULT Error update(SceneNode& node, Second prevTime, Second crntTime, Bool& updated) override
 	{
 		updated = false;
 
-		const MoveComponent& movec = m_node->getComponent<MoveComponent>();
-		if(movec.getTimestamp() == m_node->getGlobalTimestamp())
+		const MoveComponent& movec = node.getComponent<MoveComponent>();
+		if(movec.getTimestamp() == node.getGlobalTimestamp())
 		{
-			static_cast<FogDensityNode*>(m_node)->moveUpdated(movec);
+			static_cast<FogDensityNode&>(node).moveUpdated(movec);
 		}
 
 		return Error::NONE;
@@ -40,7 +40,7 @@ FogDensityNode::FogDensityNode(SceneGraph* scene, CString name)
 	newComponent<MoveComponent>(MoveComponentFlag::NONE);
 	newComponent<FeedbackComponent>();
 	newComponent<FogDensityComponent>();
-	newComponent<SpatialComponent>(&m_spatialBox);
+	newComponent<SpatialComponent>(this, &m_spatialBox);
 }
 
 FogDensityNode::~FogDensityNode()

+ 20 - 19
src/anki/scene/LightNode.cpp

@@ -4,6 +4,7 @@
 // http://www.anki3d.org/LICENSE
 
 #include <anki/scene/LightNode.h>
+#include <anki/scene/SceneGraph.h>
 #include <anki/scene/components/LensFlareComponent.h>
 #include <anki/scene/components/MoveComponent.h>
 #include <anki/scene/components/SpatialComponent.h>
@@ -16,18 +17,18 @@ namespace anki
 class LightNode::MovedFeedbackComponent : public SceneComponent
 {
 public:
-	MovedFeedbackComponent(SceneNode* node)
-		: SceneComponent(SceneComponentType::NONE, node)
+	MovedFeedbackComponent()
+		: SceneComponent(SceneComponentType::NONE)
 	{
 	}
 
-	Error update(Second, Second, Bool& updated) override
+	Error update(SceneNode& node, Second prevTime, Second crntTime, Bool& updated) override
 	{
 		updated = false;
-		LightNode& lnode = *static_cast<LightNode*>(m_node);
+		LightNode& lnode = static_cast<LightNode&>(node);
 
-		const MoveComponent& move = m_node->getComponentAt<MoveComponent>(0);
-		if(move.getTimestamp() == m_node->getGlobalTimestamp())
+		const MoveComponent& move = node.getComponentAt<MoveComponent>(0);
+		if(move.getTimestamp() == node.getGlobalTimestamp())
 		{
 			// Move updated
 			lnode.onMoveUpdate(move);
@@ -41,18 +42,18 @@ public:
 class LightNode::LightChangedFeedbackComponent : public SceneComponent
 {
 public:
-	LightChangedFeedbackComponent(SceneNode* node)
-		: SceneComponent(SceneComponentType::NONE, node)
+	LightChangedFeedbackComponent()
+		: SceneComponent(SceneComponentType::NONE)
 	{
 	}
 
-	Error update(Second, Second, Bool& updated) override
+	Error update(SceneNode& node, Second prevTime, Second crntTime, Bool& updated) override
 	{
 		updated = false;
-		LightNode& lnode = *static_cast<LightNode*>(m_node);
+		LightNode& lnode = static_cast<LightNode&>(node);
 
-		LightComponent& light = m_node->getComponentAt<LightComponent>(getIndex() - 1);
-		if(light.getTimestamp() == m_node->getGlobalTimestamp())
+		LightComponent& light = node.getComponent<LightComponent>();
+		if(light.getTimestamp() == node.getGlobalTimestamp())
 		{
 			// Shape updated
 			lnode.onShapeUpdate(light);
@@ -80,13 +81,13 @@ Error LightNode::init(LightComponentType type, CollisionShape* shape)
 	newComponent<MovedFeedbackComponent>();
 
 	// Light component
-	newComponent<LightComponent>(type);
+	newComponent<LightComponent>(type, getSceneGraph().getNewUuid());
 
 	// Feedback component
 	newComponent<LightChangedFeedbackComponent>();
 
 	// Spatial component
-	newComponent<SpatialComponent>(shape);
+	newComponent<SpatialComponent>(this, shape);
 
 	return Error::NONE;
 }
@@ -149,7 +150,7 @@ Error LightNode::loadLensFlare(const CString& filename)
 {
 	ANKI_ASSERT(tryGetComponent<LensFlareComponent>() == nullptr);
 
-	LensFlareComponent* flareComp = newComponent<LensFlareComponent>();
+	LensFlareComponent* flareComp = newComponent<LensFlareComponent>(this);
 
 	Error err = flareComp->init(filename);
 	if(err)
@@ -168,7 +169,7 @@ PointLightNode::PointLightNode(SceneGraph* scene, CString name)
 
 PointLightNode::~PointLightNode()
 {
-	m_shadowData.destroy(getSceneAllocator());
+	m_shadowData.destroy(getAllocator());
 }
 
 Error PointLightNode::init()
@@ -214,7 +215,7 @@ Error PointLightNode::frameUpdate(Second prevUpdateTime, Second crntTime)
 {
 	if(getComponent<LightComponent>().getShadowEnabled() && m_shadowData.isEmpty())
 	{
-		m_shadowData.create(getSceneAllocator(), 6);
+		m_shadowData.create(getAllocator(), 6);
 
 		const F32 ang = toRad(90.0);
 		const F32 dist = m_sphereW.getRadius();
@@ -244,7 +245,7 @@ Error PointLightNode::frameUpdate(Second prevUpdateTime, Second crntTime)
 			trf.setOrigin(origin);
 			m_shadowData[i].m_frustum.resetTransform(trf);
 
-			newComponent<FrustumComponent>(&m_shadowData[i].m_frustum);
+			newComponent<FrustumComponent>(this, &m_shadowData[i].m_frustum);
 		}
 	}
 
@@ -262,7 +263,7 @@ Error SpotLightNode::init()
 {
 	ANKI_CHECK(LightNode::init(LightComponentType::SPOT, &m_frustum));
 
-	FrustumComponent* fr = newComponent<FrustumComponent>(&m_frustum);
+	FrustumComponent* fr = newComponent<FrustumComponent>(this, &m_frustum);
 	fr->setEnabledVisibilityTests(FrustumComponentVisibilityTestFlag::NONE);
 
 	return Error::NONE;

+ 55 - 198
src/anki/scene/ModelNode.cpp

@@ -16,144 +16,23 @@
 namespace anki
 {
 
-/// Render component implementation.
-class ModelPatchNode::MRenderComponent : public MaterialRenderComponent
-{
-public:
-	const ModelPatchNode& getNode() const
-	{
-		return static_cast<const ModelPatchNode&>(getSceneNode());
-	}
-
-	MRenderComponent(SceneNode* node)
-		: MaterialRenderComponent(node, static_cast<ModelPatchNode*>(node)->m_modelPatch->getMaterial())
-	{
-	}
-
-	void setupRenderableQueueElement(RenderableQueueElement& el) const override
-	{
-		getNode().setupRenderableQueueElement(el);
-	}
-};
-
-ModelPatchNode::ModelPatchNode(SceneGraph* scene, CString name)
-	: SceneNode(scene, name)
-{
-}
-
-ModelPatchNode::~ModelPatchNode()
-{
-}
-
-Error ModelPatchNode::init(const ModelPatch* modelPatch, U idx, const ModelNode& parent)
-{
-	ANKI_ASSERT(modelPatch);
-
-	m_modelPatch = modelPatch;
-
-	// Spatial component
-	newComponent<SpatialComponent>(&m_obb);
-
-	// Render component
-	newComponent<MRenderComponent>();
-
-	// Merge key
-	Array<U64, 2> toHash;
-	toHash[0] = idx;
-	toHash[1] = parent.m_model->getUuid();
-	m_mergeKey = computeHash(&toHash[0], sizeof(toHash));
-
-	return Error::NONE;
-}
-
-void ModelPatchNode::drawCallback(RenderQueueDrawContext& ctx, ConstWeakArray<void*> userData)
-{
-	ANKI_ASSERT(userData.getSize() > 0 && userData.getSize() <= MAX_INSTANCES);
-	ANKI_ASSERT(ctx.m_key.m_instanceCount == userData.getSize());
-
-	const ModelPatchNode& self = *static_cast<const ModelPatchNode*>(userData[0]);
-
-	CommandBufferPtr& cmdb = ctx.m_commandBuffer;
-
-	// That will not work on multi-draw and instanced at the same time. Make sure that there is no multi-draw anywhere
-	ANKI_ASSERT(self.m_modelPatch->getSubMeshCount() == 1);
-
-	// Transforms
-	Array<Mat4, MAX_INSTANCES> trfs;
-	Array<Mat4, MAX_INSTANCES> prevTrfs;
-	const MoveComponent& movec = self.getParent()->getComponentAt<MoveComponent>(0);
-	trfs[0] = Mat4(movec.getWorldTransform());
-	prevTrfs[0] = Mat4(movec.getPreviousWorldTransform());
-	Bool moved = trfs[0] != prevTrfs[0]; // If at least one is moved then it's dynamic
-	for(U i = 1; i < userData.getSize(); ++i)
-	{
-		const ModelPatchNode& self2 = *static_cast<const ModelPatchNode*>(userData[i]);
-		const MoveComponent& movec = self2.getParent()->getComponentAt<MoveComponent>(0);
-		trfs[i] = Mat4(movec.getWorldTransform());
-		prevTrfs[i] = Mat4(movec.getPreviousWorldTransform());
-
-		moved = moved || (trfs[i] != prevTrfs[i]);
-	}
-
-	ModelRenderingInfo modelInf;
-	ctx.m_key.m_velocity = moved && ctx.m_key.m_pass == Pass::GB;
-	self.m_modelPatch->getRenderingDataSub(ctx.m_key, WeakArray<U8>(), modelInf);
-
-	// Program
-	cmdb->bindShaderProgram(modelInf.m_program);
-
-	// Uniforms
-	static_cast<const MaterialRenderComponent&>(self.getComponentAt<RenderComponent>(1))
-		.allocateAndSetupUniforms(self.m_modelPatch->getMaterial()->getDescriptorSetIndex(),
-			ctx,
-			ConstWeakArray<Mat4>(&trfs[0], userData.getSize()),
-			ConstWeakArray<Mat4>(&prevTrfs[0], userData.getSize()),
-			*ctx.m_stagingGpuAllocator);
-
-	// Set attributes
-	for(U i = 0; i < modelInf.m_vertexAttributeCount; ++i)
-	{
-		const VertexAttributeInfo& attrib = modelInf.m_vertexAttributes[i];
-		cmdb->setVertexAttribute(
-			U32(attrib.m_location), attrib.m_bufferBinding, attrib.m_format, attrib.m_relativeOffset);
-	}
-
-	// Set vertex buffers
-	for(U i = 0; i < modelInf.m_vertexBufferBindingCount; ++i)
-	{
-		const VertexBufferBinding& binding = modelInf.m_vertexBufferBindings[i];
-		cmdb->bindVertexBuffer(i, binding.m_buffer, binding.m_offset, binding.m_stride, VertexStepRate::VERTEX);
-	}
-
-	// Index buffer
-	cmdb->bindIndexBuffer(modelInf.m_indexBuffer, 0, IndexType::U16);
-
-	// Draw
-	cmdb->drawElements(PrimitiveTopology::TRIANGLES,
-		modelInf.m_indicesCountArray[0],
-		userData.getSize(),
-		modelInf.m_indicesOffsetArray[0] / sizeof(U16),
-		0,
-		0);
-}
-
 /// Feedback component.
 class ModelNode::MoveFeedbackComponent : public SceneComponent
 {
 public:
-	MoveFeedbackComponent(SceneNode* node)
-		: SceneComponent(SceneComponentType::NONE, node)
+	MoveFeedbackComponent()
+		: SceneComponent(SceneComponentType::NONE)
 	{
 	}
 
-	ANKI_USE_RESULT Error update(Second, Second, Bool& updated) override
+	ANKI_USE_RESULT Error update(SceneNode& node, Second prevTime, Second crntTime, Bool& updated) override
 	{
 		updated = false;
 
-		const MoveComponent& move = m_node->getComponent<MoveComponent>();
-		if(move.getTimestamp() == m_node->getGlobalTimestamp())
+		const MoveComponent& move = node.getComponent<MoveComponent>();
+		if(move.getTimestamp() == node.getGlobalTimestamp())
 		{
-			ModelNode& mnode = *static_cast<ModelNode*>(m_node);
+			ModelNode& mnode = static_cast<ModelNode&>(node);
 			mnode.onMoveComponentUpdate(move);
 		}
 
@@ -161,11 +40,11 @@ public:
 	}
 };
 
-class ModelNode::MRenderComponent : public MaterialRenderComponent
+class ModelNode::MyRenderComponent : public MaterialRenderComponent
 {
 public:
-	MRenderComponent(SceneNode* node)
-		: MaterialRenderComponent(node, static_cast<ModelNode*>(node)->m_model->getModelPatches()[0]->getMaterial())
+	MyRenderComponent(ModelNode* node)
+		: MaterialRenderComponent(node, node->m_model->getModelPatches()[node->m_modelPatchIdx]->getMaterial())
 	{
 	}
 
@@ -182,96 +61,74 @@ ModelNode::ModelNode(SceneGraph* scene, CString name)
 
 ModelNode::~ModelNode()
 {
-	m_modelPatches.destroy(getSceneAllocator());
 }
 
-Error ModelNode::init(const CString& modelFname)
+Error ModelNode::init(ModelResourcePtr resource, U32 modelPatchIdx)
 {
-	ANKI_CHECK(getResourceManager().loadResource(modelFname, m_model));
+	ANKI_ASSERT(modelPatchIdx < resource->getModelPatches().getSize());
 
-	if(m_model->getModelPatches().getSize() > 1)
-	{
-		// Multiple patches, create multiple nodes
+	ANKI_CHECK(getResourceManager().loadResource("shaders/SceneDebug.glslp", m_dbgProg));
+	m_model = resource;
+	m_modelPatchIdx = modelPatchIdx;
 
-		m_modelPatches.create(getSceneAllocator(), m_model->getModelPatches().getSize(), nullptr);
+	// Merge key
+	Array<U64, 2> toHash;
+	toHash[0] = modelPatchIdx;
+	toHash[1] = resource->getUuid();
+	m_mergeKey = computeHash(&toHash[0], sizeof(toHash));
 
-		U count = 0;
-		auto it = m_model->getModelPatches().getBegin();
-		auto end = m_model->getModelPatches().getEnd();
-		for(; it != end; it++)
-		{
-			ModelPatchNode* mpn;
-			StringAuto nname(getFrameAllocator());
-			ANKI_CHECK(getSceneGraph().newSceneNode(CString(), mpn, *it, count, *this));
+	// Components
+	if(m_model->getSkeleton().isCreated())
+	{
+		newComponent<SkinComponent>(this, m_model->getSkeleton());
+	}
+	newComponent<MoveComponent>();
+	newComponent<MoveFeedbackComponent>();
+	newComponent<SpatialComponent>(this, &m_obb);
+	newComponent<MyRenderComponent>(this);
 
-			m_modelPatches[count++] = mpn;
-			addChild(mpn);
-		}
+	return Error::NONE;
+}
 
-		// Move component
-		newComponent<MoveComponent>();
+Error ModelNode::init(const CString& modelFname)
+{
+	ModelResourcePtr model;
+	ANKI_CHECK(getResourceManager().loadResource(modelFname, model));
 
-		// Feedback component
-		newComponent<MoveFeedbackComponent>();
-	}
-	else
-	{
-		// Only one patch, don't need to create multiple nodes. Pack everything in this one.
+	// Init this
+	ANKI_CHECK(init(model, 0));
 
-		m_mergeKey = m_model->getUuid();
+	// Create separate nodes for the model patches and make the children
+	for(U i = 1; i < model->getModelPatches().getSize(); ++i)
+	{
+		ModelNode* other;
+		ANKI_CHECK(getSceneGraph().newSceneNode(CString(), other, model, i));
 
-		if(m_model->getSkeleton().isCreated())
-		{
-			newComponent<SkinComponent>(m_model->getSkeleton());
-		}
-		newComponent<MoveComponent>();
-		newComponent<MoveFeedbackComponent>();
-		newComponent<SpatialComponent>(&m_obb);
-		newComponent<MRenderComponent>();
+		addChild(other);
 	}
 
-	ANKI_CHECK(getResourceManager().loadResource("shaders/SceneDebug.glslp", m_dbgProg));
-
 	return Error::NONE;
 }
 
 void ModelNode::onMoveComponentUpdate(const MoveComponent& move)
 {
-	if(!isSinglePatch())
-	{
-		// Inform the children about the moves
-		for(ModelPatchNode* child : m_modelPatches)
-		{
-			child->m_obb = child->m_modelPatch->getBoundingShape().getTransformed(move.getWorldTransform());
-
-			SpatialComponent& sp = child->getComponent<SpatialComponent>();
-			sp.markForUpdate();
-			sp.setSpatialOrigin(move.getWorldTransform().getOrigin());
-		}
-	}
-	else
-	{
-		m_obb = m_model->getModelPatches()[0]->getBoundingShape().getTransformed(move.getWorldTransform());
+	m_obb = m_model->getModelPatches()[m_modelPatchIdx]->getBoundingShape().getTransformed(move.getWorldTransform());
 
-		SpatialComponent& sp = getComponent<SpatialComponent>();
-		sp.markForUpdate();
-		sp.setSpatialOrigin(move.getWorldTransform().getOrigin());
-	}
+	SpatialComponent& sp = getComponent<SpatialComponent>();
+	sp.markForUpdate();
+	sp.setSpatialOrigin(move.getWorldTransform().getOrigin());
 }
 
-void ModelNode::drawCallback(RenderQueueDrawContext& ctx, ConstWeakArray<void*> userData)
+void ModelNode::draw(RenderQueueDrawContext& ctx, ConstWeakArray<void*> userData) const
 {
 	ANKI_ASSERT(userData.getSize() > 0 && userData.getSize() <= MAX_INSTANCES);
 	ANKI_ASSERT(ctx.m_key.m_instanceCount == userData.getSize());
 
 	CommandBufferPtr& cmdb = ctx.m_commandBuffer;
 
-	const ModelNode& self = *static_cast<const ModelNode*>(userData[0]);
-	ANKI_ASSERT(self.isSinglePatch());
-
 	if(!ctx.m_debugDraw)
 	{
-		const ModelPatch* patch = self.m_model->getModelPatches()[0];
+		const ModelPatch* patch = m_model->getModelPatches()[m_modelPatchIdx];
 
 		// That will not work on multi-draw and instanced at the same time. Make sure that there is no multi-draw
 		// anywhere
@@ -280,7 +137,7 @@ void ModelNode::drawCallback(RenderQueueDrawContext& ctx, ConstWeakArray<void*>
 		// Transforms
 		Array<Mat4, MAX_INSTANCES> trfs;
 		Array<Mat4, MAX_INSTANCES> prevTrfs;
-		const MoveComponent& movec = self.getComponent<MoveComponent>();
+		const MoveComponent& movec = getComponent<MoveComponent>();
 		trfs[0] = Mat4(movec.getWorldTransform());
 		prevTrfs[0] = Mat4(movec.getPreviousWorldTransform());
 		Bool moved = trfs[0] != prevTrfs[0];
@@ -295,9 +152,9 @@ void ModelNode::drawCallback(RenderQueueDrawContext& ctx, ConstWeakArray<void*>
 		}
 
 		// Bones storage
-		if(self.m_model->getSkeleton())
+		if(m_model->getSkeleton())
 		{
-			const SkinComponent& skinc = self.getComponentAt<SkinComponent>(0);
+			const SkinComponent& skinc = getComponentAt<SkinComponent>(0);
 			StagingGpuMemoryToken token;
 			void* trfs = ctx.m_stagingGpuAllocator->allocateFrame(
 				skinc.getBoneTransforms().getSize() * sizeof(Mat4), StagingGpuMemoryType::STORAGE, token);
@@ -314,7 +171,7 @@ void ModelNode::drawCallback(RenderQueueDrawContext& ctx, ConstWeakArray<void*>
 		cmdb->bindShaderProgram(modelInf.m_program);
 
 		// Uniforms
-		static_cast<const MaterialRenderComponent&>(self.getComponent<RenderComponent>())
+		static_cast<const MaterialRenderComponent&>(getComponent<RenderComponent>())
 			.allocateAndSetupUniforms(patch->getMaterial()->getDescriptorSetIndex(),
 				ctx,
 				ConstWeakArray<Mat4>(&trfs[0], userData.getSize()),
@@ -429,13 +286,13 @@ void ModelNode::drawCallback(RenderQueueDrawContext& ctx, ConstWeakArray<void*>
 		*color = Vec4(1.0f, 0.0f, 1.0f, 1.0f);
 
 		// Setup state
-		ShaderProgramResourceMutationInitList<2> mutators(self.m_dbgProg);
+		ShaderProgramResourceMutationInitList<2> mutators(m_dbgProg);
 		mutators.add("COLOR_TEXTURE", 0);
 		mutators.add("DITHERED_DEPTH_TEST", ctx.m_debugDrawFlags.get(RenderQueueDebugDrawFlag::DITHERED_DEPTH_TEST_ON));
-		ShaderProgramResourceConstantValueInitList<1> consts(self.m_dbgProg);
+		ShaderProgramResourceConstantValueInitList<1> consts(m_dbgProg);
 		consts.add("INSTANCE_COUNT", U32(userData.getSize()));
 		const ShaderProgramResourceVariant* variant;
-		self.m_dbgProg->getOrCreateVariant(mutators.get(), consts.get(), variant);
+		m_dbgProg->getOrCreateVariant(mutators.get(), consts.get(), variant);
 		cmdb->bindShaderProgram(variant->getProgram());
 
 		const Bool enableDepthTest = ctx.m_debugDrawFlags.get(RenderQueueDebugDrawFlag::DEPTH_TEST_ON);

+ 10 - 42
src/anki/scene/ModelNode.h

@@ -23,35 +23,6 @@ class ModelNode;
 /// @addtogroup scene
 /// @{
 
-/// A fragment of the ModelNode
-class ModelPatchNode : public SceneNode
-{
-	friend class ModelNode;
-
-public:
-	ModelPatchNode(SceneGraph* scene, CString name);
-
-	~ModelPatchNode();
-
-	ANKI_USE_RESULT Error init(const ModelPatch* modelPatch, U idx, const ModelNode& parent);
-
-private:
-	class MRenderComponent;
-
-	Obb m_obb; ///< In world space. ModelNode will update it.
-	const ModelPatch* m_modelPatch = nullptr; ///< The resource
-	U64 m_mergeKey = 0;
-
-	void setupRenderableQueueElement(RenderableQueueElement& el) const
-	{
-		el.m_callback = drawCallback;
-		el.m_userData = this;
-		el.m_mergeKey = m_mergeKey;
-	}
-
-	static void drawCallback(RenderQueueDrawContext& ctx, ConstWeakArray<void*> userData);
-};
-
 /// The model scene node.
 class ModelNode : public SceneNode
 {
@@ -64,35 +35,32 @@ public:
 
 	ANKI_USE_RESULT Error init(const CString& modelFname);
 
-	const ModelResource& getModel() const
-	{
-		return *m_model;
-	}
+	ANKI_USE_RESULT Error init(ModelResourcePtr resource, U32 modelPatchIdx);
 
 private:
 	class MoveFeedbackComponent;
-	class MRenderComponent;
+	class MyRenderComponent;
 
 	ModelResourcePtr m_model; ///< The resource
-	DynamicArray<ModelPatchNode*> m_modelPatches;
 
 	Obb m_obb;
 	U64 m_mergeKey = 0;
+	U32 m_modelPatchIdx = 0;
 
 	ShaderProgramResourcePtr m_dbgProg;
 
-	Bool isSinglePatch() const
-	{
-		return m_modelPatches.getSize() == 0;
-	}
-
 	void onMoveComponentUpdate(const MoveComponent& move);
 
-	static void drawCallback(RenderQueueDrawContext& ctx, ConstWeakArray<void*> userData);
+	void draw(RenderQueueDrawContext& ctx, ConstWeakArray<void*> userData) const;
+
+	static void drawCallback(RenderQueueDrawContext& ctx, ConstWeakArray<void*> userData)
+	{
+		const ModelNode& self = *static_cast<const ModelNode*>(userData[0]);
+		self.draw(ctx, userData);
+	}
 
 	void setupRenderableQueueElement(RenderableQueueElement& el) const
 	{
-		ANKI_ASSERT(isSinglePatch());
 		el.m_callback = drawCallback;
 		el.m_userData = this;
 		el.m_mergeKey = m_mergeKey;

+ 14 - 14
src/anki/scene/OccluderNode.cpp

@@ -13,22 +13,22 @@ namespace anki
 {
 
 /// Feedback component.
-class OccluderMoveFeedbackComponent : public SceneComponent
+class OccluderNode::MoveFeedbackComponent : public SceneComponent
 {
 public:
-	OccluderMoveFeedbackComponent(SceneNode* node)
-		: SceneComponent(SceneComponentType::NONE, node)
+	MoveFeedbackComponent()
+		: SceneComponent(SceneComponentType::NONE)
 	{
 	}
 
-	ANKI_USE_RESULT Error update(Second, Second, Bool& updated) override
+	ANKI_USE_RESULT Error update(SceneNode& node, Second prevTime, Second crntTime, Bool& updated) override
 	{
 		updated = false;
 
-		MoveComponent& move = m_node->getComponent<MoveComponent>();
-		if(move.getTimestamp() == m_node->getGlobalTimestamp())
+		MoveComponent& move = node.getComponent<MoveComponent>();
+		if(move.getTimestamp() == node.getGlobalTimestamp())
 		{
-			OccluderNode& mnode = *static_cast<OccluderNode*>(m_node);
+			OccluderNode& mnode = static_cast<OccluderNode&>(node);
 			mnode.onMoveComponentUpdate(move);
 		}
 
@@ -38,8 +38,8 @@ public:
 
 OccluderNode::~OccluderNode()
 {
-	m_vertsL.destroy(getSceneAllocator());
-	m_vertsW.destroy(getSceneAllocator());
+	m_vertsL.destroy(getAllocator());
+	m_vertsW.destroy(getAllocator());
 }
 
 Error OccluderNode::init(const CString& meshFname)
@@ -49,11 +49,11 @@ Error OccluderNode::init(const CString& meshFname)
 	ANKI_CHECK(loader.load(meshFname));
 
 	const U indexCount = loader.getHeader().m_totalIndexCount;
-	m_vertsL.create(getSceneAllocator(), indexCount);
-	m_vertsW.create(getSceneAllocator(), indexCount);
+	m_vertsL.create(getAllocator(), indexCount);
+	m_vertsW.create(getAllocator(), indexCount);
 
-	DynamicArrayAuto<Vec3> positions(getSceneAllocator());
-	DynamicArrayAuto<U32> indices(getSceneAllocator());
+	DynamicArrayAuto<Vec3> positions(getAllocator());
+	DynamicArrayAuto<U32> indices(getAllocator());
 	ANKI_CHECK(loader.storeIndicesAndPosition(indices, positions));
 
 	for(U i = 0; i < indices.getSize(); ++i)
@@ -63,7 +63,7 @@ Error OccluderNode::init(const CString& meshFname)
 
 	// Create the components
 	newComponent<MoveComponent>();
-	newComponent<OccluderMoveFeedbackComponent>();
+	newComponent<MoveFeedbackComponent>();
 	newComponent<OccluderComponent>();
 
 	return Error::NONE;

+ 2 - 2
src/anki/scene/OccluderNode.h

@@ -17,8 +17,6 @@ namespace anki
 /// Occluder scene node.
 class OccluderNode : public SceneNode
 {
-	friend class OccluderMoveFeedbackComponent;
-
 public:
 	OccluderNode(SceneGraph* scene, CString name)
 		: SceneNode(scene, name)
@@ -30,6 +28,8 @@ public:
 	ANKI_USE_RESULT Error init(const CString& meshFname);
 
 private:
+	class MoveFeedbackComponent;
+
 	DynamicArray<Vec3> m_vertsL; ///< Verts in local space.
 	DynamicArray<Vec3> m_vertsW; ///< Verts in world space.
 

+ 15 - 20
src/anki/scene/ParticleEmitterNode.cpp

@@ -208,11 +208,6 @@ public:
 class ParticleEmitterNode::MyRenderComponent : public MaterialRenderComponent
 {
 public:
-	const ParticleEmitterNode& getNode() const
-	{
-		return static_cast<const ParticleEmitterNode&>(getSceneNode());
-	}
-
 	MyRenderComponent(SceneNode* node)
 		: MaterialRenderComponent(
 			  node, static_cast<ParticleEmitterNode*>(node)->m_particleEmitterResource->getMaterial())
@@ -221,7 +216,7 @@ public:
 
 	void setupRenderableQueueElement(RenderableQueueElement& el) const override
 	{
-		getNode().setupRenderableQueueElement(el);
+		static_cast<const ParticleEmitterNode&>(getSceneNode()).setupRenderableQueueElement(el);
 	}
 };
 
@@ -229,19 +224,19 @@ public:
 class ParticleEmitterNode::MoveFeedbackComponent : public SceneComponent
 {
 public:
-	MoveFeedbackComponent(SceneNode* node)
-		: SceneComponent(SceneComponentType::NONE, node)
+	MoveFeedbackComponent()
+		: SceneComponent(SceneComponentType::NONE)
 	{
 	}
 
-	ANKI_USE_RESULT Error update(Second, Second, Bool& updated) override
+	ANKI_USE_RESULT Error update(SceneNode& node, Second prevTime, Second crntTime, Bool& updated) override
 	{
 		updated = false; // Don't care about updates for this component
 
-		MoveComponent& move = m_node->getComponent<MoveComponent>();
-		if(move.getTimestamp() == m_node->getGlobalTimestamp())
+		MoveComponent& move = node.getComponent<MoveComponent>();
+		if(move.getTimestamp() == node.getGlobalTimestamp())
 		{
-			static_cast<ParticleEmitterNode*>(m_node)->onMoveComponentUpdate(move);
+			static_cast<ParticleEmitterNode&>(node).onMoveComponentUpdate(move);
 		}
 
 		return Error::NONE;
@@ -258,10 +253,10 @@ ParticleEmitterNode::~ParticleEmitterNode()
 	// Delete simple particles
 	for(ParticleBase* part : m_particles)
 	{
-		getSceneAllocator().deleteInstance(part);
+		getAllocator().deleteInstance(part);
 	}
 
-	m_particles.destroy(getSceneAllocator());
+	m_particles.destroy(getAllocator());
 }
 
 Error ParticleEmitterNode::init(const CString& filename)
@@ -276,10 +271,10 @@ Error ParticleEmitterNode::init(const CString& filename)
 	newComponent<MoveFeedbackComponent>();
 
 	// Spatial component
-	newComponent<SpatialComponent>(&m_obb);
+	newComponent<SpatialComponent>(this, &m_obb);
 
 	// Render component
-	newComponent<MyRenderComponent>();
+	newComponent<MyRenderComponent>(this);
 
 	// Other
 	m_obb.setCenter(Vec4(0.0));
@@ -378,13 +373,13 @@ void ParticleEmitterNode::createParticlesPhysicsSimulation(SceneGraph* scene)
 	PhysicsBodyInitInfo binit;
 	binit.m_shape = collisionShape;
 
-	m_particles.create(getSceneAllocator(), m_maxNumOfParticles);
+	m_particles.create(getAllocator(), m_maxNumOfParticles);
 
 	for(U i = 0; i < m_maxNumOfParticles; i++)
 	{
 		binit.m_mass = getRandom(m_particle.m_minMass, m_particle.m_maxMass);
 
-		PhysParticle* part = getSceneAllocator().newInstance<PhysParticle>(binit, this);
+		PhysParticle* part = getAllocator().newInstance<PhysParticle>(binit, this);
 
 		m_particles[i] = part;
 	}
@@ -392,11 +387,11 @@ void ParticleEmitterNode::createParticlesPhysicsSimulation(SceneGraph* scene)
 
 void ParticleEmitterNode::createParticlesSimpleSimulation()
 {
-	m_particles.create(getSceneAllocator(), m_maxNumOfParticles);
+	m_particles.create(getAllocator(), m_maxNumOfParticles);
 
 	for(U i = 0; i < m_maxNumOfParticles; i++)
 	{
-		ParticleSimple* part = getSceneAllocator().newInstance<ParticleSimple>();
+		ParticleSimple* part = getAllocator().newInstance<ParticleSimple>();
 
 		m_particles[i] = part;
 	}

+ 7 - 5
src/anki/scene/PhysicsDebugNode.cpp

@@ -17,20 +17,22 @@ namespace anki
 class PhysicsDebugNode::MyRenderComponent : public RenderComponent
 {
 public:
+	SceneNode* m_node;
 	DebugDrawer m_dbgDrawer;
 	PhysicsDebugDrawer m_physDbgDrawer;
 
 	MyRenderComponent(SceneNode* node)
-		: RenderComponent(node)
+		: m_node(node)
 		, m_physDbgDrawer(&m_dbgDrawer)
 	{
+		ANKI_ASSERT(node);
 		m_castsShadow = false;
 		m_isForwardShading = false;
 	}
 
 	ANKI_USE_RESULT Error init()
 	{
-		return m_dbgDrawer.init(&getSceneGraph().getResourceManager());
+		return m_dbgDrawer.init(&m_node->getSceneGraph().getResourceManager());
 	}
 
 	void setupRenderableQueueElement(RenderableQueueElement& el) const override
@@ -54,7 +56,7 @@ public:
 			m_dbgDrawer.prepareFrame(&ctx);
 			m_dbgDrawer.setViewProjectionMatrix(ctx.m_viewProjectionMatrix);
 			m_dbgDrawer.setModelMatrix(Mat4::getIdentity());
-			m_physDbgDrawer.drawWorld(getSceneGraph().getPhysicsWorld());
+			m_physDbgDrawer.drawWorld(m_node->getSceneGraph().getPhysicsWorld());
 			m_dbgDrawer.finishFrame();
 		}
 	}
@@ -66,10 +68,10 @@ PhysicsDebugNode::~PhysicsDebugNode()
 
 Error PhysicsDebugNode::init()
 {
-	MyRenderComponent* rcomp = newComponent<MyRenderComponent>();
+	MyRenderComponent* rcomp = newComponent<MyRenderComponent>(this);
 	ANKI_CHECK(rcomp->init());
 
-	ObbSpatialComponent* scomp = newComponent<ObbSpatialComponent>();
+	ObbSpatialComponent* scomp = newComponent<ObbSpatialComponent>(this);
 	Vec3 center = (getSceneGraph().getSceneMax() + getSceneGraph().getSceneMin()) / 2.0f;
 	scomp->m_obb.setCenter(center.xyz0());
 	scomp->m_obb.setExtend((getSceneGraph().getSceneMax() - center).xyz0());

+ 17 - 17
src/anki/scene/PlayerNode.cpp

@@ -15,27 +15,27 @@ namespace anki
 {
 
 /// Feedback component.
-class PlayerNodeFeedbackComponent final : public SceneComponent
+class PlayerNode::FeedbackComponent final : public SceneComponent
 {
 public:
-	PlayerNodeFeedbackComponent(SceneNode* node)
-		: SceneComponent(SceneComponentType::NONE, node)
+	FeedbackComponent()
+		: SceneComponent(SceneComponentType::NONE)
 	{
 	}
 
-	Error update(Second, Second, Bool& updated) override
+	Error update(SceneNode& node, Second prevTime, Second crntTime, Bool& updated) override
 	{
 		updated = false;
 
-		PlayerControllerComponent& playerc = m_node->getComponent<PlayerControllerComponent>();
-		const Input& in = m_node->getSceneGraph().getInput();
+		PlayerControllerComponent& playerc = node.getComponent<PlayerControllerComponent>();
+		const Input& in = node.getSceneGraph().getInput();
 		const F32 ang = toRad(7.0);
 
 		F32 y = in.getMousePosition().y();
 		F32 x = in.getMousePosition().x();
-		if(playerc.getTimestamp() == m_node->getGlobalTimestamp() || y != 0.0 || x != 0.0)
+		if(playerc.getTimestamp() == node.getGlobalTimestamp() || y != 0.0 || x != 0.0)
 		{
-			MoveComponent& move = m_node->getComponent<MoveComponent>();
+			MoveComponent& move = node.getComponent<MoveComponent>();
 
 			// Set origin
 			Vec4 origin = playerc.getTransform().getOrigin();
@@ -61,21 +61,21 @@ public:
 };
 
 /// Feedback component.
-class PlayerNodeFeedbackComponent2 final : public SceneComponent
+class PlayerNode::FeedbackComponent2 final : public SceneComponent
 {
 public:
-	PlayerNodeFeedbackComponent2(SceneNode* node)
-		: SceneComponent(SceneComponentType::NONE, node)
+	FeedbackComponent2()
+		: SceneComponent(SceneComponentType::NONE)
 	{
 	}
 
-	Error update(Second, Second, Bool& updated) override
+	Error update(SceneNode& node, Second prevTime, Second crntTime, Bool& updated) override
 	{
 		updated = false;
 
-		PlayerControllerComponent& playerc = m_node->getComponent<PlayerControllerComponent>();
-		MoveComponent& move = m_node->getComponent<MoveComponent>();
-		const Input& in = m_node->getSceneGraph().getInput();
+		PlayerControllerComponent& playerc = node.getComponent<PlayerControllerComponent>();
+		MoveComponent& move = node.getComponent<MoveComponent>();
+		const Input& in = node.getSceneGraph().getInput();
 
 		const F32 speed = 0.5;
 
@@ -131,13 +131,13 @@ Error PlayerNode::init(const Vec4& position)
 	newComponent<PlayerControllerComponent>(m_player);
 
 	// Feedback component
-	newComponent<PlayerNodeFeedbackComponent>();
+	newComponent<FeedbackComponent>();
 
 	// Move component
 	newComponent<MoveComponent>();
 
 	// Feedback component #2
-	newComponent<PlayerNodeFeedbackComponent2>();
+	newComponent<FeedbackComponent2>();
 
 	return Error::NONE;
 }

+ 3 - 2
src/anki/scene/PlayerNode.h

@@ -18,8 +18,6 @@ namespace anki
 /// Player scene node. It uses input and physics to move inside the world.
 class PlayerNode : public SceneNode
 {
-	friend class PlayerNodeFeedbackComponent;
-
 public:
 	PlayerNode(SceneGraph* scene, CString name);
 
@@ -28,6 +26,9 @@ public:
 	ANKI_USE_RESULT Error init(const Vec4& position);
 
 private:
+	class FeedbackComponent;
+	class FeedbackComponent2;
+
 	PhysicsPlayerControllerPtr m_player;
 };
 /// @}

+ 11 - 11
src/anki/scene/ReflectionProbeNode.cpp

@@ -18,23 +18,23 @@ const FrustumComponentVisibilityTestFlag FRUSTUM_TEST_FLAGS =
 	FrustumComponentVisibilityTestFlag::RENDER_COMPONENTS | FrustumComponentVisibilityTestFlag::LIGHT_COMPONENTS;
 
 /// Feedback component
-class ReflectionProbeMoveFeedbackComponent : public SceneComponent
+class ReflectionProbeNode::MoveFeedbackComponent : public SceneComponent
 {
 public:
-	ReflectionProbeMoveFeedbackComponent(SceneNode* node)
-		: SceneComponent(SceneComponentType::NONE, node)
+	MoveFeedbackComponent()
+		: SceneComponent(SceneComponentType::NONE)
 	{
 	}
 
-	Error update(Second, Second, Bool& updated) override
+	Error update(SceneNode& node, Second prevTime, Second crntTime, Bool& updated) override
 	{
 		updated = false;
 
-		MoveComponent& move = m_node->getComponent<MoveComponent>();
-		if(move.getTimestamp() == m_node->getGlobalTimestamp())
+		MoveComponent& move = node.getComponent<MoveComponent>();
+		if(move.getTimestamp() == node.getGlobalTimestamp())
 		{
 			// Move updated
-			ReflectionProbeNode& dnode = *static_cast<ReflectionProbeNode*>(m_node);
+			ReflectionProbeNode& dnode = static_cast<ReflectionProbeNode&>(node);
 			dnode.onMoveUpdate(move);
 		}
 
@@ -52,7 +52,7 @@ Error ReflectionProbeNode::init(const Vec4& aabbMinLSpace, const Vec4& aabbMaxLS
 	newComponent<MoveComponent>();
 
 	// Feedback component
-	newComponent<ReflectionProbeMoveFeedbackComponent>();
+	newComponent<MoveFeedbackComponent>();
 
 	// The frustum components
 	const F32 ang = toRad(90.0f);
@@ -81,7 +81,7 @@ Error ReflectionProbeNode::init(const Vec4& aabbMinLSpace, const Vec4& aabbMaxLS
 		m_cubeSides[i].m_frustum.setAll(ang, ang, zNear, EFFECTIVE_DISTANCE);
 		m_cubeSides[i].m_frustum.resetTransform(m_cubeSides[i].m_localTrf);
 
-		FrustumComponent* frc = newComponent<FrustumComponent>(&m_cubeSides[i].m_frustum);
+		FrustumComponent* frc = newComponent<FrustumComponent>(this, &m_cubeSides[i].m_frustum);
 
 		frc->setEnabledVisibilityTests(FrustumComponentVisibilityTestFlag::NONE);
 	}
@@ -91,10 +91,10 @@ Error ReflectionProbeNode::init(const Vec4& aabbMinLSpace, const Vec4& aabbMaxLS
 	m_aabbMaxLSpace = aabbMaxLSpace.xyz();
 	m_spatialAabb.setMin(aabbMinLSpace);
 	m_spatialAabb.setMax(aabbMaxLSpace);
-	newComponent<SpatialComponent>(&m_spatialAabb);
+	newComponent<SpatialComponent>(this, &m_spatialAabb);
 
 	// Reflection probe comp
-	ReflectionProbeComponent* reflc = newComponent<ReflectionProbeComponent>();
+	ReflectionProbeComponent* reflc = newComponent<ReflectionProbeComponent>(getSceneGraph().getNewUuid());
 	reflc->setPosition(Vec4(0.0f));
 	reflc->setBoundingBox(aabbMinLSpace, aabbMaxLSpace);
 

+ 2 - 2
src/anki/scene/ReflectionProbeNode.h

@@ -19,8 +19,6 @@ namespace anki
 /// Probe used in realtime reflections.
 class ReflectionProbeNode : public SceneNode
 {
-	friend class ReflectionProbeMoveFeedbackComponent;
-
 public:
 	const F32 FRUSTUM_NEAR_PLANE = 0.1f / 4.0f;
 	const F32 EFFECTIVE_DISTANCE = 256.0f;
@@ -37,6 +35,8 @@ public:
 	ANKI_USE_RESULT Error frameUpdate(Second prevUpdateTime, Second crntTime) override;
 
 private:
+	class MoveFeedbackComponent;
+
 	class CubeSide
 	{
 	public:

+ 0 - 125
src/anki/scene/ReflectionProxyNode.cpp

@@ -1,125 +0,0 @@
-// Copyright (C) 2009-2018, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#include <anki/scene/ReflectionProxyNode.h>
-#include <anki/scene/components/ReflectionProxyComponent.h>
-#include <anki/scene/components/MoveComponent.h>
-#include <anki/scene/components/SpatialComponent.h>
-#include <anki/resource/MeshLoader.h>
-#include <anki/util/WeakArray.h>
-
-namespace anki
-{
-
-/// Feedback component
-class ReflectionProxyMoveFeedbackComponent : public SceneComponent
-{
-public:
-	ReflectionProxyMoveFeedbackComponent(SceneNode* node)
-		: SceneComponent(SceneComponentType::NONE, node)
-	{
-	}
-
-	Error update(Second, Second, Bool& updated) final
-	{
-		updated = false;
-
-		MoveComponent& move = m_node->getComponent<MoveComponent>();
-		if(move.getTimestamp() == m_node->getGlobalTimestamp())
-		{
-			// Move updated
-			ReflectionProxyNode& dnode = *static_cast<ReflectionProxyNode*>(m_node);
-			dnode.onMoveUpdate(move);
-		}
-
-		return Error::NONE;
-	}
-};
-
-Error ReflectionProxyNode::init(const CString& proxyMesh)
-{
-#if 0
-	// Move component first
-	newComponent<MoveComponent>(this);
-
-	// Feedback component
-	newComponent<ReflectionProxyMoveFeedbackComponent>(this);
-
-	// Load vertices
-	MeshLoader loader(&getResourceManager());
-	ANKI_CHECK(loader.load(proxyMesh));
-
-	if(!(loader.getHeader().m_flags & MeshBinaryFile::Flag::QUAD))
-	{
-		ANKI_SCENE_LOGE("Expecting quad mesh");
-		return Error::USER_DATA;
-	}
-
-	const U indexCount = loader.getHeader().m_totalIndexCount;
-	const U quadCount = indexCount / 4;
-	m_quadsLSpace.create(getSceneAllocator(), quadCount);
-
-	const U8* buff = loader.getVertexData();
-	const U8* buffEnd = loader.getVertexData() + loader.getVertexDataSize();
-	ConstWeakArray<U16> indices(reinterpret_cast<const U16*>(loader.getIndexData()), indexCount);
-	for(U i = 0; i < quadCount; ++i)
-	{
-		Array<Vec4, 4>& quad = m_quadsLSpace[i];
-
-		for(U j = 0; j < 4; ++j)
-		{
-			U index = indices[i * 4 + j];
-
-			const Vec3* vert = reinterpret_cast<const Vec3*>(buff + loader.getVertexSize() * index);
-			ANKI_ASSERT(vert + 1 < reinterpret_cast<const Vec3*>(buffEnd));
-			(void)buffEnd;
-
-			quad[j] = vert->xyz0();
-		}
-	}
-
-	// Proxy component
-	newComponent<ReflectionProxyComponent>(this, quadCount);
-
-	// Spatial component
-	m_boxLSpace.setFromPointCloud(loader.getVertexData(),
-		loader.getHeader().m_totalVerticesCount,
-		loader.getVertexSize(),
-		loader.getVertexDataSize());
-
-	m_boxWSpace = m_boxLSpace;
-
-	newComponent<SpatialComponent>(this, &m_boxWSpace);
-#endif
-
-	return Error::NONE;
-}
-
-void ReflectionProxyNode::onMoveUpdate(const MoveComponent& move)
-{
-	const Transform& trf = move.getWorldTransform();
-
-	// Update proxy comp
-	ReflectionProxyComponent& proxyc = getComponent<ReflectionProxyComponent>();
-	for(U i = 0; i < m_quadsLSpace.getSize(); ++i)
-	{
-		Array<Vec4, 4> quadWSpace;
-		for(U j = 0; j < 4; ++j)
-		{
-			quadWSpace[j] = trf.transform(m_quadsLSpace[i][j]);
-		}
-
-		proxyc.setQuad(i, quadWSpace[0], quadWSpace[1], quadWSpace[2], quadWSpace[3]);
-	}
-
-	// Update spatial
-	m_boxWSpace = m_boxLSpace;
-	m_boxWSpace.transform(trf);
-	SpatialComponent& spatial = getComponent<SpatialComponent>();
-	spatial.setSpatialOrigin(move.getWorldTransform().getOrigin());
-	spatial.markForUpdate();
-}
-
-} // end namespace anki

+ 0 - 47
src/anki/scene/ReflectionProxyNode.h

@@ -1,47 +0,0 @@
-// Copyright (C) 2009-2018, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#pragma once
-
-#include <anki/scene/SceneNode.h>
-#include <anki/Math.h>
-#include <anki/collision/Obb.h>
-
-namespace anki
-{
-
-/// @addtogroup scene
-/// @{
-
-/// Proxy used in realtime reflections.
-class ReflectionProxyNode : public SceneNode
-{
-	friend class ReflectionProxyMoveFeedbackComponent;
-
-public:
-	ReflectionProxyNode(SceneGraph* scene, CString name)
-		: SceneNode(scene, name)
-	{
-	}
-
-	~ReflectionProxyNode()
-	{
-		m_quadsLSpace.destroy(getSceneAllocator());
-	}
-
-	/// Create the proxy. The points form a quad and they should be in local
-	/// space.
-	ANKI_USE_RESULT Error init(const CString& proxyMesh);
-
-private:
-	DynamicArray<Array<Vec4, 4>> m_quadsLSpace; ///< Quads in local space.
-	Obb m_boxLSpace;
-	Obb m_boxWSpace;
-
-	void onMoveUpdate(const MoveComponent& move);
-};
-/// @}
-
-} // end namespace anki

+ 20 - 4
src/anki/scene/SceneGraph.cpp

@@ -187,6 +187,7 @@ Error SceneGraph::update(Second prevUpdateTime, Second crntTime)
 	m_stats.m_updateTime = HighRezTimer::getCurrentTime();
 
 	m_timestamp = *m_globalTimestamp;
+	ANKI_ASSERT(m_timestamp > 0);
 
 	// Reset the framepool
 	m_frameAlloc.getMemoryPool().reset();
@@ -254,11 +255,17 @@ Error SceneGraph::updateNode(Second prevTime, Second crntTime, SceneNode& node)
 	Error err = Error::NONE;
 
 	// Components update
-	Timestamp componentTimestam = 0;
+	Timestamp componentTimestamp = 0;
 	err = node.iterateComponents([&](SceneComponent& comp) -> Error {
 		Bool updated = false;
-		Error e = comp.updateReal(prevTime, crntTime, updated);
-		componentTimestam = max(componentTimestam, comp.getTimestamp());
+		Error e = comp.update(node, prevTime, crntTime, updated);
+
+		if(updated)
+		{
+			comp.setTimestamp(node.getSceneGraph().m_timestamp);
+			componentTimestamp = max(componentTimestamp, node.getSceneGraph().m_timestamp);
+			ANKI_ASSERT(componentTimestamp > 0);
+		}
 
 		return e;
 	});
@@ -273,7 +280,16 @@ Error SceneGraph::updateNode(Second prevTime, Second crntTime, SceneNode& node)
 	// Frame update
 	if(!err)
 	{
-		err = node.frameUpdateComplete(prevTime, crntTime, componentTimestam);
+		if(componentTimestamp != 0)
+		{
+			node.setComponentMaxTimestamp(componentTimestamp);
+		}
+		else
+		{
+			// No components or nothing updated, don't change the timestamp
+		}
+
+		err = node.frameUpdate(prevTime, crntTime);
 	}
 
 	return err;

+ 3 - 3
src/anki/scene/SceneNode.cpp

@@ -15,13 +15,13 @@ SceneNode::SceneNode(SceneGraph* scene, CString name)
 {
 	if(name)
 	{
-		m_name.create(getSceneAllocator(), name);
+		m_name.create(getAllocator(), name);
 	}
 }
 
 SceneNode::~SceneNode()
 {
-	auto alloc = getSceneAllocator();
+	auto alloc = getAllocator();
 
 	auto it = m_components.getBegin();
 	auto end = m_components.getEnd();
@@ -58,7 +58,7 @@ Timestamp SceneNode::getGlobalTimestamp() const
 	return m_scene->getGlobalTimestamp();
 }
 
-SceneAllocator<U8> SceneNode::getSceneAllocator() const
+SceneAllocator<U8> SceneNode::getAllocator() const
 {
 	ANKI_ASSERT(m_scene);
 	return m_scene->getAllocator();

+ 10 - 17
src/anki/scene/SceneNode.h

@@ -68,17 +68,22 @@ public:
 
 	Timestamp getComponentMaxTimestamp() const
 	{
-		ANKI_ASSERT(m_maxComponentTimestamp > 0);
 		return m_maxComponentTimestamp;
 	}
 
-	SceneAllocator<U8> getSceneAllocator() const;
+	void setComponentMaxTimestamp(Timestamp maxComponentTimestamp)
+	{
+		ANKI_ASSERT(maxComponentTimestamp > 0);
+		m_maxComponentTimestamp = maxComponentTimestamp;
+	}
+
+	SceneAllocator<U8> getAllocator() const;
 
 	SceneFrameAllocator<U8> getFrameAllocator() const;
 
 	void addChild(SceneNode* obj)
 	{
-		Base::addChild(getSceneAllocator(), obj);
+		Base::addChild(getAllocator(), obj);
 	}
 
 	/// This is called by the scene every frame after logic and before rendering. By default it does nothing.
@@ -91,16 +96,6 @@ public:
 		return Error::NONE;
 	}
 
-	ANKI_USE_RESULT Error frameUpdateComplete(Second prevUpdateTime, Second crntTime, Timestamp maxComponentTimestamp)
-	{
-		m_maxComponentTimestamp = maxComponentTimestamp;
-		if(m_components.getSize() > 0)
-		{
-			ANKI_ASSERT(maxComponentTimestamp > 0);
-		}
-		return frameUpdate(prevUpdateTime, crntTime);
-	}
-
 	/// Iterate all components
 	template<typename Func>
 	ANKI_USE_RESULT Error iterateComponents(Func func) const
@@ -211,8 +206,8 @@ protected:
 	template<typename TComponent, typename... TArgs>
 	TComponent* newComponent(TArgs&&... args)
 	{
-		TComponent* comp = getSceneAllocator().newInstance<TComponent>(this, std::forward<TArgs>(args)...);
-		m_components.emplaceBack(getSceneAllocator(), comp);
+		TComponent* comp = getAllocator().newInstance<TComponent>(std::forward<TArgs>(args)...);
+		m_components.emplaceBack(getAllocator(), comp);
 		return comp;
 	}
 
@@ -228,8 +223,6 @@ private:
 	Timestamp m_maxComponentTimestamp = 0;
 
 	Bool8 m_markedForDeletion = false;
-
-	void cacheImportantComponents();
 };
 /// @}
 

+ 4 - 4
src/anki/scene/StaticGeometryNode.cpp

@@ -12,10 +12,10 @@ namespace anki
 {
 
 /// The implementation of static geometry node renderable component.
-class StaticGeometryRenderComponent : public MaterialRenderComponent
+class StaticGeometryPatchNode::RenderComponent : public MaterialRenderComponent
 {
 public:
-	StaticGeometryRenderComponent(SceneNode* node)
+	RenderComponent(SceneNode* node)
 		: MaterialRenderComponent(node, static_cast<StaticGeometryPatchNode*>(node)->m_modelPatch->getMaterial())
 	{
 	}
@@ -44,13 +44,13 @@ Error StaticGeometryPatchNode::init(const ModelPatch* modelPatch)
 	// Create spatial components
 	for(U i = 1; i < m_modelPatch->getSubMeshCount(); i++)
 	{
-		SpatialComponent* spatial = newComponent<SpatialComponent>(&m_modelPatch->getBoundingShapeSub(i));
+		SpatialComponent* spatial = newComponent<SpatialComponent>(this, &m_modelPatch->getBoundingShapeSub(i));
 
 		spatial->setSpatialOrigin(m_modelPatch->getBoundingShapeSub(i).getCenter());
 	}
 
 	// Create render component
-	newComponent<StaticGeometryRenderComponent>();
+	newComponent<RenderComponent>(this);
 
 	return Error::NONE;
 }

+ 2 - 2
src/anki/scene/StaticGeometryNode.h

@@ -22,8 +22,6 @@ class ModelPatch;
 /// Static geometry scene node patch
 class StaticGeometryPatchNode : public SceneNode
 {
-	friend class StaticGeometryRenderComponent;
-
 public:
 	StaticGeometryPatchNode(SceneGraph* scene, CString name);
 
@@ -32,6 +30,8 @@ public:
 	ANKI_USE_RESULT Error init(const ModelPatch* modelPatch);
 
 private:
+	class RenderComponent;
+
 	const ModelPatch* m_modelPatch;
 };
 

+ 7 - 8
src/anki/scene/TriggerNode.cpp

@@ -17,20 +17,19 @@ namespace anki
 class TriggerNode::MoveFeedbackComponent : public SceneComponent
 {
 public:
-	MoveFeedbackComponent(SceneNode* node)
-		: SceneComponent(SceneComponentType::NONE, node)
+	MoveFeedbackComponent()
+		: SceneComponent(SceneComponentType::NONE)
 	{
 	}
 
-	ANKI_USE_RESULT Error update(Second, Second, Bool& updated) final
+	ANKI_USE_RESULT Error update(SceneNode& node, Second prevTime, Second crntTime, Bool& updated) final
 	{
 		updated = false;
 
-		const MoveComponent& move = m_node->getComponent<MoveComponent>();
-		if(move.getTimestamp() == m_node->getGlobalTimestamp())
+		const MoveComponent& move = node.getComponent<MoveComponent>();
+		if(move.getTimestamp() == node.getGlobalTimestamp())
 		{
-			TriggerNode* node = static_cast<TriggerNode*>(m_node);
-			node->m_trigger->setTransform(move.getWorldTransform());
+			static_cast<TriggerNode&>(node).m_trigger->setTransform(move.getWorldTransform());
 		}
 
 		return Error::NONE;
@@ -54,7 +53,7 @@ Error TriggerNode::init(F32 sphereRadius)
 
 	newComponent<MoveComponent>();
 	newComponent<MoveFeedbackComponent>();
-	newComponent<TriggerComponent>(m_trigger);
+	newComponent<TriggerComponent>(this, m_trigger);
 
 	return Error::NONE;
 }

+ 0 - 15
src/anki/scene/Visibility.cpp

@@ -9,7 +9,6 @@
 #include <anki/scene/components/LensFlareComponent.h>
 #include <anki/scene/components/RenderComponent.h>
 #include <anki/scene/components/ReflectionProbeComponent.h>
-#include <anki/scene/components/ReflectionProxyComponent.h>
 #include <anki/scene/components/OccluderComponent.h>
 #include <anki/scene/components/DecalComponent.h>
 #include <anki/scene/components/MoveComponent.h>
@@ -217,9 +216,6 @@ void VisibilityTestTask::test(ThreadHive& hive, U32 taskId)
 	const Bool wantsReflectionProbes =
 		testedFrc.visibilityTestsEnabled(FrustumComponentVisibilityTestFlag::REFLECTION_PROBES);
 
-	const Bool wantsReflectionProxies =
-		testedFrc.visibilityTestsEnabled(FrustumComponentVisibilityTestFlag::REFLECTION_PROXIES);
-
 	const Bool wantsDecals = testedFrc.visibilityTestsEnabled(FrustumComponentVisibilityTestFlag::DECALS);
 
 	const Bool wantsFogDensityComponents =
@@ -274,12 +270,6 @@ void VisibilityTestTask::test(ThreadHive& hive, U32 taskId)
 			wantNode = true;
 		}
 
-		const ReflectionProxyComponent* proxyc = nullptr;
-		if(wantsReflectionProxies && (proxyc = node.tryGetComponent<ReflectionProxyComponent>()))
-		{
-			wantNode = true;
-		}
-
 		DecalComponent* decalc = nullptr;
 		if(wantsDecals && (decalc = node.tryGetComponent<DecalComponent>()))
 		{
@@ -455,11 +445,6 @@ void VisibilityTestTask::test(ThreadHive& hive, U32 taskId)
 			}
 		}
 
-		if(proxyc)
-		{
-			ANKI_ASSERT(!"TODO");
-		}
-
 		if(decalc)
 		{
 			DecalQueueElement* el = result.m_decals.newElement(alloc);

+ 3 - 3
src/anki/scene/components/BodyComponent.h

@@ -20,8 +20,8 @@ class BodyComponent : public SceneComponent
 public:
 	static const SceneComponentType CLASS_TYPE = SceneComponentType::BODY;
 
-	BodyComponent(SceneNode* node, PhysicsBodyPtr body)
-		: SceneComponent(CLASS_TYPE, node)
+	BodyComponent(PhysicsBodyPtr body)
+		: SceneComponent(CLASS_TYPE)
 		, m_body(body)
 	{
 	}
@@ -43,7 +43,7 @@ public:
 		return m_body;
 	}
 
-	ANKI_USE_RESULT Error update(Second, Second, Bool& updated) override
+	ANKI_USE_RESULT Error update(SceneNode& node, Second, Second, Bool& updated) override
 	{
 		Transform newTrf = m_body->getTransform();
 		updated = newTrf != m_trf;

+ 4 - 2
src/anki/scene/components/DecalComponent.cpp

@@ -11,8 +11,10 @@ namespace anki
 {
 
 DecalComponent::DecalComponent(SceneNode* node)
-	: SceneComponent(CLASS_TYPE, node)
+	: SceneComponent(CLASS_TYPE)
+	, m_node(node)
 {
+	ANKI_ASSERT(node);
 }
 
 DecalComponent::~DecalComponent()
@@ -23,7 +25,7 @@ Error DecalComponent::setLayer(CString texAtlasFname, CString texAtlasSubtexName
 {
 	Layer& l = m_layers[type];
 
-	ANKI_CHECK(getSceneGraph().getResourceManager().loadResource(texAtlasFname, l.m_atlas));
+	ANKI_CHECK(m_node->getSceneGraph().getResourceManager().loadResource(texAtlasFname, l.m_atlas));
 
 	ANKI_CHECK(l.m_atlas->getSubTextureInfo(texAtlasSubtexName, &l.m_uv[0]));
 

+ 2 - 1
src/anki/scene/components/DecalComponent.h

@@ -74,7 +74,7 @@ public:
 	}
 
 	/// Implements SceneComponent::update.
-	ANKI_USE_RESULT Error update(Second, Second, Bool& updated) override
+	ANKI_USE_RESULT Error update(SceneNode& node, Second, Second, Bool& updated) override
 	{
 		updated = m_markedForUpdate;
 
@@ -154,6 +154,7 @@ private:
 		F32 m_blendFactor = 0.0f;
 	};
 
+	SceneNode* m_node;
 	Array<Layer, U(LayerType::COUNT)> m_layers;
 	Mat4 m_biasProjViewMat;
 	Vec3 m_sizes = Vec3(1.0f);

+ 2 - 9
src/anki/scene/components/FogDensityComponent.h

@@ -22,8 +22,8 @@ class FogDensityComponent : public SceneComponent
 public:
 	static const SceneComponentType CLASS_TYPE = SceneComponentType::FOG_DENSITY;
 
-	FogDensityComponent(SceneNode* node)
-		: SceneComponent(CLASS_TYPE, node)
+	FogDensityComponent()
+		: SceneComponent(CLASS_TYPE)
 	{
 	}
 
@@ -90,13 +90,6 @@ public:
 		}
 	}
 
-	/// Implements SceneComponent::update.
-	ANKI_USE_RESULT Error update(Second, Second, Bool& updated) override
-	{
-		updated = false;
-		return Error::NONE;
-	}
-
 private:
 	Vec4 m_aabbMin{0.0f};
 

+ 21 - 3
src/anki/scene/components/FrustumComponent.cpp

@@ -4,16 +4,19 @@
 // http://www.anki3d.org/LICENSE
 
 #include <anki/scene/components/FrustumComponent.h>
+#include <anki/scene/SceneNode.h>
 
 namespace anki
 {
 
 FrustumComponent::FrustumComponent(SceneNode* node, Frustum* frustum)
-	: SceneComponent(CLASS_TYPE, node)
+	: SceneComponent(CLASS_TYPE)
+	, m_node(node)
 	, m_frustum(frustum)
 	, m_flags(0)
 {
 	// WARNING: Never touch m_frustum in constructor
+	ANKI_ASSERT(node);
 	ANKI_ASSERT(frustum);
 	markShapeForUpdate();
 	markTransformForUpdate();
@@ -23,11 +26,13 @@ FrustumComponent::FrustumComponent(SceneNode* node, Frustum* frustum)
 
 FrustumComponent::~FrustumComponent()
 {
-	m_coverageBuff.m_depthMap.destroy(getAllocator());
+	m_coverageBuff.m_depthMap.destroy(m_node->getAllocator());
 }
 
-Error FrustumComponent::update(Second, Second, Bool& updated)
+Error FrustumComponent::update(SceneNode& node, Second prevTime, Second crntTime, Bool& updated)
 {
+	ANKI_ASSERT(&node == m_node);
+
 	updated = false;
 	m_prevViewProjMat = m_viewProjMat;
 
@@ -52,4 +57,17 @@ Error FrustumComponent::update(Second, Second, Bool& updated)
 	return Error::NONE;
 }
 
+void FrustumComponent::fillCoverageBufferCallback(void* userData, F32* depthValues, U32 width, U32 height)
+{
+	ANKI_ASSERT(userData && depthValues && width > 0 && height > 0);
+	FrustumComponent& self = *static_cast<FrustumComponent*>(userData);
+
+	self.m_coverageBuff.m_depthMap.destroy(self.m_node->getAllocator());
+	self.m_coverageBuff.m_depthMap.create(self.m_node->getAllocator(), width * height);
+	memcpy(&self.m_coverageBuff.m_depthMap[0], depthValues, self.m_coverageBuff.m_depthMap.getSizeInBytes());
+
+	self.m_coverageBuff.m_depthMapWidth = width;
+	self.m_coverageBuff.m_depthMapHeight = height;
+}
+
 } // end namespace anki

+ 13 - 13
src/anki/scene/components/FrustumComponent.h

@@ -55,6 +55,16 @@ public:
 
 	~FrustumComponent();
 
+	SceneNode& getSceneNode()
+	{
+		return *m_node;
+	}
+
+	const SceneNode& getSceneNode() const
+	{
+		return *m_node;
+	}
+
 	Frustum& getFrustum()
 	{
 		return *m_frustum;
@@ -117,7 +127,7 @@ public:
 
 	/// @name SceneComponent overrides
 	/// @{
-	ANKI_USE_RESULT Error update(Second, Second, Bool& updated) override;
+	ANKI_USE_RESULT Error update(SceneNode& node, Second prevTime, Second crntTime, Bool& updated) override;
 	/// @}
 
 	void setEnabledVisibilityTests(FrustumComponentVisibilityTestFlag bits)
@@ -149,18 +159,7 @@ public:
 	}
 
 	/// The type is FillCoverageBufferCallback.
-	static void fillCoverageBufferCallback(void* userData, F32* depthValues, U32 width, U32 height)
-	{
-		ANKI_ASSERT(userData && depthValues && width > 0 && height > 0);
-		FrustumComponent& self = *static_cast<FrustumComponent*>(userData);
-
-		self.m_coverageBuff.m_depthMap.destroy(self.getAllocator());
-		self.m_coverageBuff.m_depthMap.create(self.getAllocator(), width * height);
-		memcpy(&self.m_coverageBuff.m_depthMap[0], depthValues, self.m_coverageBuff.m_depthMap.getSizeInBytes());
-
-		self.m_coverageBuff.m_depthMapWidth = width;
-		self.m_coverageBuff.m_depthMapHeight = height;
-	}
+	static void fillCoverageBufferCallback(void* userData, F32* depthValues, U32 width, U32 height);
 
 	Bool hasCoverageBuffer() const
 	{
@@ -190,6 +189,7 @@ private:
 	};
 	ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(Flags, friend)
 
+	SceneNode* m_node;
 	Frustum* m_frustum;
 	Mat4 m_projMat = Mat4::getIdentity(); ///< Projection matrix
 	Mat4 m_viewMat = Mat4::getIdentity(); ///< View matrix

+ 12 - 10
src/anki/scene/components/JointComponent.cpp

@@ -30,7 +30,7 @@ void JointComponent::removeAllJoints()
 		JointNode* node = &m_jointList.getFront();
 		m_jointList.popFront();
 
-		getAllocator().deleteInstance(node);
+		m_node->getAllocator().deleteInstance(node);
 	}
 }
 
@@ -64,11 +64,11 @@ void JointComponent::newJoint(const Vec3& relPosFactor, F32 breakingImpulse, TAr
 	{
 		Vec3 relPos = computeLocalPivotFromFactors(bodyc->getPhysicsBody(), relPosFactor);
 
-		PhysicsJointPtr joint = getSceneGraph().getPhysicsWorld().newInstance<TJoint>(
+		PhysicsJointPtr joint = m_node->getSceneGraph().getPhysicsWorld().newInstance<TJoint>(
 			bodyc->getPhysicsBody(), relPos, std::forward<TArgs>(args)...);
 		joint->setBreakingImpulseThreshold(breakingImpulse);
 
-		JointNode* newNode = getAllocator().newInstance<JointNode>();
+		JointNode* newNode = m_node->getAllocator().newInstance<JointNode>();
 		newNode->m_joint = joint;
 		m_jointList.pushBack(newNode);
 	}
@@ -97,11 +97,11 @@ void JointComponent::newPoint2PointJoint2(const Vec3& relPosFactorA, const Vec3&
 		Vec3 relPosA = computeLocalPivotFromFactors(bodycA->getPhysicsBody(), relPosFactorA);
 		Vec3 relPosB = computeLocalPivotFromFactors(bodycB->getPhysicsBody(), relPosFactorB);
 
-		PhysicsJointPtr joint = getSceneGraph().getPhysicsWorld().newInstance<PhysicsPoint2PointJoint>(
+		PhysicsJointPtr joint = m_node->getSceneGraph().getPhysicsWorld().newInstance<PhysicsPoint2PointJoint>(
 			bodycA->getPhysicsBody(), relPosA, bodycB->getPhysicsBody(), relPosB);
 		joint->setBreakingImpulseThreshold(breakingImpulse);
 
-		JointNode* newNode = getAllocator().newInstance<JointNode>();
+		JointNode* newNode = m_node->getAllocator().newInstance<JointNode>();
 		newNode->m_joint = joint;
 		newNode->m_parentNode = m_node->getParent();
 		m_jointList.pushBack(newNode);
@@ -117,18 +117,20 @@ void JointComponent::newHingeJoint(const Vec3& relPosFactor, const Vec3& axis, F
 	newJoint<PhysicsHingeJoint>(relPosFactor, breakingImpulse, axis);
 }
 
-Error JointComponent::update(Second prevTime, Second crntTime, Bool& updated)
+Error JointComponent::update(SceneNode& node, Second prevTime, Second crntTime, Bool& updated)
 {
+	ANKI_ASSERT(&node == m_node);
+
 	// Iterate the joints and check if the connected scene node is not the parent of this node anymore.
 	while(true)
 	{
 		Bool erasedOne = false;
-		for(auto node : m_jointList)
+		for(auto otherNode : m_jointList)
 		{
-			if(node.m_parentNode != m_node->getParent() || node.m_joint->isBroken())
+			if(otherNode.m_parentNode != node.getParent() || otherNode.m_joint->isBroken())
 			{
-				m_jointList.erase(&node);
-				getAllocator().deleteInstance(&node);
+				m_jointList.erase(&otherNode);
+				node.getAllocator().deleteInstance(&otherNode);
 				erasedOne = true;
 				updated = true;
 				break;

+ 5 - 2
src/anki/scene/components/JointComponent.h

@@ -21,8 +21,10 @@ public:
 	static const SceneComponentType CLASS_TYPE = SceneComponentType::JOINT;
 
 	JointComponent(SceneNode* node)
-		: SceneComponent(SceneComponentType::JOINT, node)
+		: SceneComponent(CLASS_TYPE)
+		, m_node(node)
 	{
+		ANKI_ASSERT(node);
 	}
 
 	~JointComponent();
@@ -36,11 +38,12 @@ public:
 	/// Create a hinge joint on the BodyComponent of the SceneNode.
 	void newHingeJoint(const Vec3& relPosFactor, const Vec3& axis, F32 brakingImpulse = MAX_F32);
 
-	ANKI_USE_RESULT Error update(Second prevTime, Second crntTime, Bool& updated) override;
+	ANKI_USE_RESULT Error update(SceneNode& node, Second prevTime, Second crntTime, Bool& updated) override;
 
 private:
 	class JointNode;
 
+	SceneNode* m_node;
 	IntrusiveList<JointNode> m_jointList;
 
 	/// Given a 3 coodrinates that lie in [-1.0, +1.0] compute a pivot point that lies into the AABB of the collision

+ 4 - 2
src/anki/scene/components/LensFlareComponent.cpp

@@ -12,8 +12,10 @@ namespace anki
 {
 
 LensFlareComponent::LensFlareComponent(SceneNode* node)
-	: SceneComponent(CLASS_TYPE, node)
+	: SceneComponent(CLASS_TYPE)
+	, m_node(node)
 {
+	ANKI_ASSERT(node);
 }
 
 LensFlareComponent::~LensFlareComponent()
@@ -23,7 +25,7 @@ LensFlareComponent::~LensFlareComponent()
 Error LensFlareComponent::init(const CString& textureFilename)
 {
 	// Texture
-	ANKI_CHECK(getSceneGraph().getResourceManager().loadResource(textureFilename, m_tex));
+	ANKI_CHECK(m_node->getSceneGraph().getResourceManager().loadResource(textureFilename, m_tex));
 
 	return Error::NONE;
 }

+ 1 - 7
src/anki/scene/components/LensFlareComponent.h

@@ -73,13 +73,6 @@ public:
 		return m_tex->getGrTexture();
 	}
 
-	/// Implements SceneComponent::update.
-	Error update(Second prevTime, Second crntTime, Bool& updated) override
-	{
-		updated = false;
-		return Error::NONE;
-	}
-
 	void setupLensFlareQueueElement(LensFlareQueueElement& el) const
 	{
 		el.m_worldPosition = m_worldPosition.xyz();
@@ -91,6 +84,7 @@ public:
 	}
 
 private:
+	SceneNode* m_node;
 	TextureResourcePtr m_tex; ///< Array of textures.
 
 	Vec4 m_colorMul = Vec4(1.0); ///< Color multiplier.

+ 5 - 3
src/anki/scene/components/LightComponent.cpp

@@ -8,16 +8,18 @@
 namespace anki
 {
 
-LightComponent::LightComponent(SceneNode* node, LightComponentType type)
-	: SceneComponent(CLASS_TYPE, node)
+LightComponent::LightComponent(LightComponentType type, U64 uuid)
+	: SceneComponent(CLASS_TYPE)
+	, m_uuid(uuid)
 	, m_type(type)
 {
+	ANKI_ASSERT(m_uuid > 0);
 	setInnerAngle(toRad(45.0));
 	setOuterAngle(toRad(30.0));
 	m_radius = 1.0;
 }
 
-Error LightComponent::update(Second, Second, Bool& updated)
+Error LightComponent::update(SceneNode& node, Second prevTime, Second crntTime, Bool& updated)
 {
 	updated = false;
 

+ 5 - 4
src/anki/scene/components/LightComponent.h

@@ -32,7 +32,7 @@ public:
 	/// WARNING: If you change here update the shaders.
 	static constexpr F32 FRUSTUM_NEAR_PLANE = 0.1f / 4.0f;
 
-	LightComponent(SceneNode* node, LightComponentType type);
+	LightComponent(LightComponentType type, U64 uuid);
 
 	LightComponentType getLightComponentType() const
 	{
@@ -121,12 +121,12 @@ public:
 		m_flags.set(SHADOW, x);
 	}
 
-	ANKI_USE_RESULT Error update(Second, Second, Bool& updated) override;
+	ANKI_USE_RESULT Error update(SceneNode& node, Second prevTime, Second crntTime, Bool& updated) override;
 
 	void setupPointLightQueueElement(PointLightQueueElement& el) const
 	{
 		ANKI_ASSERT(m_type == LightComponentType::POINT);
-		el.m_uuid = getUuid();
+		el.m_uuid = m_uuid;
 		el.m_worldPosition = m_trf.getOrigin().xyz();
 		el.m_radius = m_radius;
 		el.m_diffuseColor = m_diffColor.xyz();
@@ -137,7 +137,7 @@ public:
 	void setupSpotLightQueueElement(SpotLightQueueElement& el) const
 	{
 		ANKI_ASSERT(m_type == LightComponentType::SPOT);
-		el.m_uuid = getUuid();
+		el.m_uuid = m_uuid;
 		el.m_worldTransform = Mat4(m_trf);
 		el.m_textureMatrix = m_spotTextureMatrix;
 		el.m_distance = m_distance;
@@ -149,6 +149,7 @@ public:
 	}
 
 private:
+	U64 m_uuid;
 	LightComponentType m_type;
 	Vec4 m_diffColor = Vec4(0.5f);
 	union

+ 4 - 10
src/anki/scene/components/MoveComponent.cpp

@@ -9,8 +9,8 @@
 namespace anki
 {
 
-MoveComponent::MoveComponent(SceneNode* node, MoveComponentFlag flags)
-	: SceneComponent(CLASS_TYPE, node)
+MoveComponent::MoveComponent(MoveComponentFlag flags)
+	: SceneComponent(CLASS_TYPE)
 	, m_flags(flags)
 {
 	markForUpdate();
@@ -20,15 +20,9 @@ MoveComponent::~MoveComponent()
 {
 }
 
-Error MoveComponent::update(Second prevTime, Second crntTime, Bool& updated)
+Error MoveComponent::update(SceneNode& node, Second prevTime, Second crntTime, Bool& updated)
 {
-	updated = updateWorldTransform(*m_node);
-
-	if(updated)
-	{
-		onMoveComponentUpdate(*m_node, prevTime, crntTime);
-	}
-
+	updated = updateWorldTransform(node);
 	return Error::NONE;
 }
 

+ 2 - 16
src/anki/scene/components/MoveComponent.h

@@ -39,9 +39,8 @@ public:
 	static const SceneComponentType CLASS_TYPE = SceneComponentType::MOVE;
 
 	/// The one and only constructor
-	/// @param node The scene node to steal it's allocators
 	/// @param flags The flags
-	MoveComponent(SceneNode* node, MoveComponentFlag flags = MoveComponentFlag::NONE);
+	MoveComponent(MoveComponentFlag flags = MoveComponentFlag::NONE);
 
 	~MoveComponent();
 
@@ -99,20 +98,7 @@ public:
 		return m_prevWTrf;
 	}
 
-	/// Called when there is an update in the world transformation.
-	virtual ANKI_USE_RESULT Error onMoveComponentUpdate(SceneNode& node, Second prevTime, Second crntTime)
-	{
-		return Error::NONE;
-	}
-
-	/// @name SceneComponent overrides
-	/// @{
-
-	/// Update self and children world transform recursively, if root node. Need to call this at every frame.
-	/// @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 parent
-	ANKI_USE_RESULT Error update(Second, Second, Bool& updated) override;
-	/// @}
+	ANKI_USE_RESULT Error update(SceneNode& node, Second prevTime, Second crntTime, Bool& updated) override;
 
 	/// @name Mess with the local transform
 	/// @{

+ 2 - 2
src/anki/scene/components/OccluderComponent.h

@@ -22,8 +22,8 @@ public:
 	static const SceneComponentType CLASS_TYPE = SceneComponentType::OCCLUDER;
 
 	/// @note The component won't own the triangles.
-	OccluderComponent(SceneNode* node)
-		: SceneComponent(CLASS_TYPE, node)
+	OccluderComponent()
+		: SceneComponent(CLASS_TYPE)
 	{
 	}
 

+ 3 - 3
src/anki/scene/components/PlayerControllerComponent.h

@@ -20,8 +20,8 @@ class PlayerControllerComponent : public SceneComponent
 public:
 	static const SceneComponentType CLASS_TYPE = SceneComponentType::PLAYER_CONTROLLER;
 
-	PlayerControllerComponent(SceneNode* node, PhysicsPlayerControllerPtr player)
-		: SceneComponent(CLASS_TYPE, node)
+	PlayerControllerComponent(PhysicsPlayerControllerPtr player)
+		: SceneComponent(CLASS_TYPE)
 		, m_player(player)
 	{
 	}
@@ -48,7 +48,7 @@ public:
 		m_player->moveToPosition(pos);
 	}
 
-	ANKI_USE_RESULT Error update(Second, Second, Bool& updated) override
+	ANKI_USE_RESULT Error update(SceneNode& node, Second prevTime, Second crntTime, Bool& updated) override
 	{
 		m_trf = m_player->getTransform(updated);
 		return Error::NONE;

+ 5 - 3
src/anki/scene/components/ReflectionProbeComponent.h

@@ -20,8 +20,9 @@ class ReflectionProbeComponent : public SceneComponent
 public:
 	static const SceneComponentType CLASS_TYPE = SceneComponentType::REFLECTION_PROBE;
 
-	ReflectionProbeComponent(SceneNode* node)
-		: SceneComponent(CLASS_TYPE, node)
+	ReflectionProbeComponent(U64 uuid)
+		: SceneComponent(CLASS_TYPE)
+		, m_uuid(uuid)
 	{
 	}
 
@@ -62,7 +63,7 @@ public:
 		ANKI_ASSERT(m_pos > m_aabbMin && m_pos < m_aabbMax);
 		el.m_feedbackCallback = reflectionProbeQueueElementFeedbackCallback;
 		el.m_userData = const_cast<ReflectionProbeComponent*>(this);
-		el.m_uuid = getUuid();
+		el.m_uuid = m_uuid;
 		el.m_worldPosition = m_pos;
 		el.m_aabbMin = m_aabbMin;
 		el.m_aabbMax = m_aabbMax;
@@ -71,6 +72,7 @@ public:
 	}
 
 private:
+	U64 m_uuid;
 	Vec3 m_pos = Vec3(0.0f);
 	Vec3 m_aabbMin = Vec3(+1.0f);
 	Vec3 m_aabbMax = Vec3(-1.0f);

+ 0 - 62
src/anki/scene/components/ReflectionProxyComponent.cpp

@@ -1,62 +0,0 @@
-// Copyright (C) 2009-2018, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#include <anki/scene/components/ReflectionProxyComponent.h>
-
-namespace anki
-{
-
-void ReflectionProxyComponent::setQuad(U index, const Vec4& a, const Vec4& b, const Vec4& c, const Vec4& d)
-{
-	m_dirty = true;
-
-	m_faces[index].m_vertices[0] = a;
-	m_faces[index].m_vertices[1] = b;
-	m_faces[index].m_vertices[2] = c;
-	m_faces[index].m_vertices[3] = d;
-}
-
-Error ReflectionProxyComponent::update(Second prevTime, Second crntTime, Bool& updated)
-{
-	if(m_dirty)
-	{
-		m_dirty = false;
-		updated = true;
-
-		for(Face& face : m_faces)
-		{
-			const Vec4& a = face.m_vertices[0];
-			const Vec4& b = face.m_vertices[1];
-			const Vec4& c = face.m_vertices[2];
-			const Vec4& d = face.m_vertices[3];
-			(void)d;
-
-			// Update the plane
-			face.m_plane.setFrom3Points(a, b, c);
-
-#if ANKI_EXTRA_CHECKS == 1
-			// Make sure that all points are co-planar
-			Vec4 n0 = (b - a).cross(c - b);
-			Vec4 n1 = (c - b).cross(d - c);
-			Vec4 n2 = (d - c).cross(a - d);
-			n0.normalize();
-			n1.normalize();
-			n2.normalize();
-
-			F32 dota = absolute(n0.dot(n1) - n1.dot(n2));
-			F32 dotb = absolute(n0.dot(n2) - n0.dot(n1));
-			ANKI_ASSERT(dota < 0.001 && dotb < 0.001);
-#endif
-		}
-	}
-	else
-	{
-		updated = false;
-	}
-
-	return Error::NONE;
-}
-
-} // end namespace anki

+ 0 - 59
src/anki/scene/components/ReflectionProxyComponent.h

@@ -1,59 +0,0 @@
-// Copyright (C) 2009-2018, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#pragma once
-
-#include <anki/scene/components/SceneComponent.h>
-#include <anki/collision/Plane.h>
-
-namespace anki
-{
-
-/// @addtogroup scene
-/// @{
-
-/// Reflection proxy component.
-class ReflectionProxyComponent : public SceneComponent
-{
-public:
-	static const SceneComponentType CLASS_TYPE = SceneComponentType::REFLECTION_PROXY;
-
-	/// Reflection proxy face. One out of many
-	class Face
-	{
-	public:
-		Array<Vec4, 4> m_vertices;
-		Plane m_plane;
-	};
-
-	ReflectionProxyComponent(SceneNode* node, U faceCount)
-		: SceneComponent(CLASS_TYPE, node)
-	{
-		ANKI_ASSERT(faceCount > 0);
-		m_faces.create(getAllocator(), faceCount);
-	}
-
-	~ReflectionProxyComponent()
-	{
-		m_faces.destroy(getAllocator());
-	}
-
-	void setQuad(U index, const Vec4& a, const Vec4& b, const Vec4& c, const Vec4& d);
-
-	const DynamicArray<Face>& getFaces() const
-	{
-		ANKI_ASSERT(m_faces.getSize() > 0);
-		return m_faces;
-	}
-
-	ANKI_USE_RESULT Error update(Second prevTime, Second crntTime, Bool& updated) final;
-
-private:
-	DynamicArray<Face> m_faces; ///< Quads.
-	Bool8 m_dirty = true;
-};
-/// @}
-
-} // end namespace anki

+ 10 - 8
src/anki/scene/components/RenderComponent.cpp

@@ -13,11 +13,13 @@ namespace anki
 {
 
 MaterialRenderComponent::MaterialRenderComponent(SceneNode* node, MaterialResourcePtr mtl)
-	: RenderComponent(node)
+	: m_node(node)
 	, m_mtl(mtl)
 {
+	ANKI_ASSERT(node);
+
 	// Create the material variables
-	m_vars.create(getAllocator(), m_mtl->getVariables().getSize());
+	m_vars.create(m_node->getAllocator(), m_mtl->getVariables().getSize());
 	U count = 0;
 	for(const MaterialVariable& mv : m_mtl->getVariables())
 	{
@@ -30,7 +32,7 @@ MaterialRenderComponent::MaterialRenderComponent(SceneNode* node, MaterialResour
 
 MaterialRenderComponent::~MaterialRenderComponent()
 {
-	m_vars.destroy(getAllocator());
+	m_vars.destroy(m_node->getAllocator());
 }
 
 void MaterialRenderComponent::allocateAndSetupUniforms(U set,
@@ -134,7 +136,7 @@ void MaterialRenderComponent::allocateAndSetupUniforms(U set,
 			{
 				ANKI_ASSERT(transforms.getSize() > 0);
 
-				DynamicArrayAuto<Mat3> normMats(getFrameAllocator());
+				DynamicArrayAuto<Mat3> normMats(m_node->getFrameAllocator());
 				normMats.create(transforms.getSize());
 
 				for(U i = 0; i < transforms.getSize(); i++)
@@ -152,7 +154,7 @@ void MaterialRenderComponent::allocateAndSetupUniforms(U set,
 			{
 				ANKI_ASSERT(transforms.getSize() > 0);
 
-				DynamicArrayAuto<Mat3> rots(getFrameAllocator());
+				DynamicArrayAuto<Mat3> rots(m_node->getFrameAllocator());
 				rots.create(transforms.getSize());
 
 				for(U i = 0; i < transforms.getSize(); i++)
@@ -189,7 +191,7 @@ void MaterialRenderComponent::allocateAndSetupUniforms(U set,
 			{
 				ANKI_ASSERT(transforms.getSize() > 0);
 
-				DynamicArrayAuto<Mat4> mvp(getFrameAllocator());
+				DynamicArrayAuto<Mat4> mvp(m_node->getFrameAllocator());
 				mvp.create(transforms.getSize());
 
 				for(U i = 0; i < transforms.getSize(); i++)
@@ -204,7 +206,7 @@ void MaterialRenderComponent::allocateAndSetupUniforms(U set,
 			{
 				ANKI_ASSERT(prevTransforms.getSize() > 0);
 
-				DynamicArrayAuto<Mat4> mvp(getFrameAllocator());
+				DynamicArrayAuto<Mat4> mvp(m_node->getFrameAllocator());
 				mvp.create(prevTransforms.getSize());
 
 				for(U i = 0; i < prevTransforms.getSize(); i++)
@@ -220,7 +222,7 @@ void MaterialRenderComponent::allocateAndSetupUniforms(U set,
 			{
 				ANKI_ASSERT(transforms.getSize() > 0);
 
-				DynamicArrayAuto<Mat4> mv(getFrameAllocator());
+				DynamicArrayAuto<Mat4> mv(m_node->getFrameAllocator());
 				mv.create(transforms.getSize());
 
 				for(U i = 0; i < transforms.getSize(); i++)

+ 13 - 2
src/anki/scene/components/RenderComponent.h

@@ -23,8 +23,8 @@ class RenderComponent : public SceneComponent
 public:
 	static const SceneComponentType CLASS_TYPE = SceneComponentType::RENDER;
 
-	RenderComponent(SceneNode* node)
-		: SceneComponent(CLASS_TYPE, node)
+	RenderComponent()
+		: SceneComponent(CLASS_TYPE)
 	{
 	}
 
@@ -106,6 +106,16 @@ public:
 		return *m_mtl;
 	}
 
+	const SceneNode& getSceneNode() const
+	{
+		return *m_node;
+	}
+
+	SceneNode& getSceneNode()
+	{
+		return *m_node;
+	}
+
 	/// Iterate variables using a lambda
 	template<typename Func>
 	ANKI_USE_RESULT Error iterateVariables(Func func)
@@ -127,6 +137,7 @@ public:
 		StagingGpuMemoryManager& alloc) const;
 
 private:
+	SceneNode* m_node;
 	Variables m_vars;
 	MaterialResourcePtr m_mtl;
 };

+ 0 - 61
src/anki/scene/components/SceneComponent.cpp

@@ -1,61 +0,0 @@
-// Copyright (C) 2009-2018, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#include <anki/scene/components/SceneComponent.h>
-#include <anki/scene/SceneNode.h>
-#include <anki/scene/SceneGraph.h>
-
-namespace anki
-{
-
-SceneComponent::SceneComponent(SceneComponentType type, SceneNode* node)
-	: m_node(node)
-	, m_uuid(node->getSceneGraph().getNewUuid())
-	, m_idx(node->getComponentCount())
-	, m_type(type)
-{
-}
-
-SceneComponent::~SceneComponent()
-{
-}
-
-Timestamp SceneComponent::getGlobalTimestamp() const
-{
-	return m_node->getGlobalTimestamp();
-}
-
-Error SceneComponent::updateReal(Second prevTime, Second crntTime, Bool& updated)
-{
-	Error err = update(prevTime, crntTime, updated);
-	if(!err && updated)
-	{
-		m_timestamp = getGlobalTimestamp();
-	}
-
-	return err;
-}
-
-SceneGraph& SceneComponent::getSceneGraph()
-{
-	return m_node->getSceneGraph();
-}
-
-const SceneGraph& SceneComponent::getSceneGraph() const
-{
-	return m_node->getSceneGraph();
-}
-
-SceneAllocator<U8> SceneComponent::getAllocator() const
-{
-	return m_node->getSceneAllocator();
-}
-
-SceneFrameAllocator<U8> SceneComponent::getFrameAllocator() const
-{
-	return m_node->getFrameAllocator();
-}
-
-} // end namespace anki

+ 16 - 40
src/anki/scene/components/SceneComponent.h

@@ -27,7 +27,6 @@ enum class SceneComponentType : U16
 	LENS_FLARE,
 	BODY,
 	REFLECTION_PROBE,
-	REFLECTION_PROXY,
 	OCCLUDER,
 	DECAL,
 	SKIN,
@@ -46,9 +45,14 @@ class SceneComponent
 {
 public:
 	/// Construct the scene component.
-	SceneComponent(SceneComponentType type, SceneNode* node);
+	SceneComponent(SceneComponentType type)
+		: m_type(type)
+	{
+	}
 
-	virtual ~SceneComponent();
+	virtual ~SceneComponent()
+	{
+	}
 
 	SceneComponentType getType() const
 	{
@@ -60,58 +64,30 @@ public:
 		return m_timestamp;
 	}
 
-	Timestamp getGlobalTimestamp() const;
-
 	/// Do some updating
+	/// @param node The owner node of this component.
 	/// @param prevTime Previous update time.
 	/// @param crntTime Current update time.
 	/// @param[out] updated true if an update happened.
-	virtual ANKI_USE_RESULT Error update(Second prevTime, Second crntTime, Bool& updated)
+	virtual ANKI_USE_RESULT Error update(SceneNode& node, Second prevTime, Second crntTime, Bool& updated)
 	{
 		updated = false;
 		return Error::NONE;
 	}
 
 	/// Called only by the SceneGraph
-	ANKI_USE_RESULT Error updateReal(Second prevTime, Second crntTime, Bool& updated);
-
-	/// Unique ID in the same run.
-	U64 getUuid() const
-	{
-		return m_uuid;
-	}
-
-	SceneNode& getSceneNode()
-	{
-		return *m_node;
-	}
+	ANKI_USE_RESULT Error updateReal(SceneNode& node, Second prevTime, Second crntTime, Bool& updated);
 
-	const SceneNode& getSceneNode() const
+	/// Don't call it.
+	void setTimestamp(Timestamp timestamp)
 	{
-		return *m_node;
+		ANKI_ASSERT(timestamp > 0);
+		ANKI_ASSERT(timestamp >= m_timestamp);
+		m_timestamp = timestamp;
 	}
 
-	/// The position in the owner SceneNode.
-	U getIndex() const
-	{
-		return m_idx;
-	}
-
-	SceneAllocator<U8> getAllocator() const;
-
-	SceneFrameAllocator<U8> getFrameAllocator() const;
-
-	SceneGraph& getSceneGraph();
-
-	const SceneGraph& getSceneGraph() const;
-
-protected:
-	SceneNode* m_node = nullptr;
-	Timestamp m_timestamp = 1; ///< Indicates when an update happened
-
 private:
-	U64 m_uuid;
-	U32 m_idx;
+	Timestamp m_timestamp = 1; ///< Indicates when an update happened
 	SceneComponentType m_type;
 };
 /// @}

+ 8 - 5
src/anki/scene/components/ScriptComponent.cpp

@@ -14,8 +14,10 @@ namespace anki
 {
 
 ScriptComponent::ScriptComponent(SceneNode* node)
-	: SceneComponent(CLASS_TYPE, node)
+	: SceneComponent(CLASS_TYPE)
+	, m_node(node)
 {
+	ANKI_ASSERT(node);
 }
 
 ScriptComponent::~ScriptComponent()
@@ -25,10 +27,10 @@ ScriptComponent::~ScriptComponent()
 Error ScriptComponent::load(CString fname)
 {
 	// Load
-	ANKI_CHECK(getSceneGraph().getResourceManager().loadResource(fname, m_script));
+	ANKI_CHECK(m_node->getSceneGraph().getResourceManager().loadResource(fname, m_script));
 
 	// Create the env
-	ANKI_CHECK(getSceneGraph().getScriptManager().newScriptEnvironment(m_env));
+	ANKI_CHECK(m_node->getSceneGraph().getScriptManager().newScriptEnvironment(m_env));
 
 	// Exec the script
 	ANKI_CHECK(m_env->evalString(m_script->getSource()));
@@ -36,8 +38,9 @@ Error ScriptComponent::load(CString fname)
 	return Error::NONE;
 }
 
-Error ScriptComponent::update(Second prevTime, Second crntTime, Bool& updated)
+Error ScriptComponent::update(SceneNode& node, Second prevTime, Second crntTime, Bool& updated)
 {
+	ANKI_ASSERT(&node == m_node);
 	updated = false;
 	lua_State* lua = &m_env->getLuaState();
 
@@ -45,7 +48,7 @@ Error ScriptComponent::update(Second prevTime, Second crntTime, Bool& updated)
 	lua_getglobal(lua, "update");
 
 	// Push args
-	LuaBinder::pushVariableToTheStack(lua, m_node);
+	LuaBinder::pushVariableToTheStack(lua, &node);
 	lua_pushnumber(lua, prevTime);
 	lua_pushnumber(lua, crntTime);
 

+ 2 - 1
src/anki/scene/components/ScriptComponent.h

@@ -27,9 +27,10 @@ public:
 
 	ANKI_USE_RESULT Error load(CString fname);
 
-	ANKI_USE_RESULT Error update(Second prevTime, Second crntTime, Bool& updated) override;
+	ANKI_USE_RESULT Error update(SceneNode& node, Second prevTime, Second crntTime, Bool& updated) override;
 
 private:
+	SceneNode* m_node;
 	ScriptResourcePtr m_script;
 	ScriptEnvironmentPtr m_env;
 };

+ 10 - 4
src/anki/scene/components/SkinComponent.cpp

@@ -4,6 +4,7 @@
 // http://www.anki3d.org/LICENSE
 
 #include <anki/scene/components/SkinComponent.h>
+#include <anki/scene/SceneNode.h>
 #include <anki/resource/SkeletonResource.h>
 #include <anki/resource/AnimationResource.h>
 #include <anki/util/BitSet.h>
@@ -12,10 +13,13 @@ namespace anki
 {
 
 SkinComponent::SkinComponent(SceneNode* node, SkeletonResourcePtr skeleton)
-	: SceneComponent(CLASS_TYPE, node)
+	: SceneComponent(CLASS_TYPE)
+	, m_node(node)
 	, m_skeleton(skeleton)
 {
-	m_boneTrfs.create(getAllocator(), m_skeleton->getBones().getSize());
+	ANKI_ASSERT(node);
+
+	m_boneTrfs.create(m_node->getAllocator(), m_skeleton->getBones().getSize());
 	for(Mat4& trf : m_boneTrfs)
 	{
 		trf.setIdentity();
@@ -24,7 +28,7 @@ SkinComponent::SkinComponent(SceneNode* node, SkeletonResourcePtr skeleton)
 
 SkinComponent::~SkinComponent()
 {
-	m_boneTrfs.destroy(getAllocator());
+	m_boneTrfs.destroy(m_node->getAllocator());
 }
 
 void SkinComponent::playAnimation(U track, AnimationResourcePtr anim, Second startTime, Bool repeat)
@@ -34,8 +38,10 @@ void SkinComponent::playAnimation(U track, AnimationResourcePtr anim, Second sta
 	m_tracks[track].m_repeat = repeat;
 }
 
-Error SkinComponent::update(Second prevTime, Second crntTime, Bool& updated)
+Error SkinComponent::update(SceneNode& node, Second prevTime, Second crntTime, Bool& updated)
 {
+	ANKI_ASSERT(&node == m_node);
+
 	updated = false;
 	const Second timeDiff = crntTime - prevTime;
 

+ 2 - 1
src/anki/scene/components/SkinComponent.h

@@ -27,7 +27,7 @@ public:
 
 	~SkinComponent();
 
-	ANKI_USE_RESULT Error update(Second, Second, Bool& updated) override;
+	ANKI_USE_RESULT Error update(SceneNode& node, Second prevTime, Second crntTime, Bool& updated) override;
 
 	void playAnimation(U track, AnimationResourcePtr anim, Second startTime, Bool repeat);
 
@@ -45,6 +45,7 @@ private:
 		Bool8 m_repeat;
 	};
 
+	SceneNode* m_node;
 	SkeletonResourcePtr m_skeleton;
 	DynamicArray<Mat4> m_boneTrfs;
 	Array<Track, MAX_ANIMATION_TRACKS> m_tracks;

+ 8 - 4
src/anki/scene/components/SpatialComponent.cpp

@@ -11,9 +11,11 @@ namespace anki
 {
 
 SpatialComponent::SpatialComponent(SceneNode* node, const CollisionShape* shape)
-	: SceneComponent(CLASS_TYPE, node)
+	: SceneComponent(CLASS_TYPE)
+	, m_node(node)
 	, m_shape(shape)
 {
+	ANKI_ASSERT(node);
 	ANKI_ASSERT(shape);
 	markForUpdate();
 	m_octreeInfo.m_userData = this;
@@ -23,19 +25,21 @@ SpatialComponent::~SpatialComponent()
 {
 	if(m_placed)
 	{
-		getSceneGraph().getOctree().remove(m_octreeInfo);
+		m_node->getSceneGraph().getOctree().remove(m_octreeInfo);
 	}
 }
 
-Error SpatialComponent::update(Second, Second, Bool& updated)
+Error SpatialComponent::update(SceneNode& node, Second prevTime, Second crntTime, Bool& updated)
 {
+	ANKI_ASSERT(&node == m_node);
+
 	updated = m_markedForUpdate;
 	if(updated)
 	{
 		m_shape->computeAabb(m_aabb);
 		m_markedForUpdate = false;
 
-		getSceneGraph().getOctree().place(m_aabb, &m_octreeInfo);
+		m_node->getSceneGraph().getOctree().place(m_aabb, &m_octreeInfo);
 		m_placed = true;
 	}
 

+ 15 - 4
src/anki/scene/components/SpatialComponent.h

@@ -38,6 +38,16 @@ public:
 		return m_aabb;
 	}
 
+	const SceneNode& getSceneNode() const
+	{
+		return *m_node;
+	}
+
+	SceneNode& getSceneNode()
+	{
+		return *m_node;
+	}
+
 	/// Get optimal collision shape for visibility tests
 	const CollisionShape& getVisibilityCollisionShape()
 	{
@@ -73,17 +83,18 @@ public:
 
 	/// @name SceneComponent overrides
 	/// @{
-	ANKI_USE_RESULT Error update(Second, Second, Bool& updated) override;
+	ANKI_USE_RESULT Error update(SceneNode& node, Second prevTime, Second crntTime, Bool& updated) override;
 	/// @}
 
 private:
-	Bool8 m_markedForUpdate = false;
-	Bool8 m_placed = false;
-
+	SceneNode* m_node;
 	const CollisionShape* m_shape;
 	Aabb m_aabb; ///< A faster shape
 	Vec4 m_origin = Vec4(MAX_F32, MAX_F32, MAX_F32, 0.0);
 
+	Bool8 m_markedForUpdate = false;
+	Bool8 m_placed = false;
+
 	OctreePlaceable m_octreeInfo;
 };
 

+ 13 - 14
src/anki/scene/components/TriggerComponent.cpp

@@ -4,6 +4,7 @@
 // http://www.anki3d.org/LICENSE
 
 #include <anki/scene/components/TriggerComponent.h>
+#include <anki/scene/SceneNode.h>
 
 namespace anki
 {
@@ -24,36 +25,34 @@ public:
 };
 
 TriggerComponent::TriggerComponent(SceneNode* node, PhysicsTriggerPtr trigger)
-	: SceneComponent(CLASS_TYPE, node)
+	: SceneComponent(CLASS_TYPE)
+	, m_node(node)
 	, m_trigger(trigger)
 {
-	m_contactCb = getAllocator().newInstance<MyPhysicsTriggerProcessContactCallback>();
+	ANKI_ASSERT(node);
+	m_contactCb = m_node->getAllocator().newInstance<MyPhysicsTriggerProcessContactCallback>();
 	m_contactCb->m_comp = this;
 	m_trigger->setContactProcessCallback(m_contactCb);
 }
 
 TriggerComponent::~TriggerComponent()
 {
-	getAllocator().deleteInstance(m_contactCb);
-	m_contactNodes.destroy(getAllocator());
-}
-
-Error TriggerComponent::update(Second, Second, Bool& updated)
-{
-	updated = false;
-	return Error::NONE;
+	m_node->getAllocator().deleteInstance(m_contactCb);
+	m_contactNodes.destroy(m_node->getAllocator());
 }
 
 void TriggerComponent::processContact(SceneNode& node)
 {
+	ANKI_ASSERT(&node != m_node);
+
 	// Clear the list if it's a new frame
-	if(m_contactNodesArrayTimestamp != getGlobalTimestamp())
+	if(m_contactNodesArrayTimestamp != node.getGlobalTimestamp())
 	{
-		m_contactNodesArrayTimestamp = getGlobalTimestamp();
-		m_contactNodes.destroy(getAllocator());
+		m_contactNodesArrayTimestamp = node.getGlobalTimestamp();
+		m_contactNodes.destroy(node.getAllocator());
 	}
 
-	m_contactNodes.emplaceBack(getAllocator(), &node);
+	m_contactNodes.emplaceBack(node.getAllocator(), &node);
 }
 
 } // end namespace anki

+ 1 - 2
src/anki/scene/components/TriggerComponent.h

@@ -24,8 +24,6 @@ public:
 
 	~TriggerComponent();
 
-	ANKI_USE_RESULT Error update(Second, Second, Bool& updated) override;
-
 	/// Process a contact.
 	virtual void processContact(SceneNode& node);
 
@@ -37,6 +35,7 @@ public:
 private:
 	class MyPhysicsTriggerProcessContactCallback;
 
+	SceneNode* m_node;
 	PhysicsTriggerPtr m_trigger;
 	DynamicArray<SceneNode*> m_contactNodes;
 	Timestamp m_contactNodesArrayTimestamp = 0;

+ 2 - 2
src/anki/scene/events/EventManager.cpp

@@ -32,7 +32,7 @@ Error EventManager::init(SceneGraph* scene)
 	return Error::NONE;
 }
 
-SceneAllocator<U8> EventManager::getSceneAllocator() const
+SceneAllocator<U8> EventManager::getAllocator() const
 {
 	return m_scene->getAllocator();
 }
@@ -127,7 +127,7 @@ void EventManager::markEventForDeletion(Event* event)
 
 void EventManager::deleteEventsMarkedForDeletion()
 {
-	SceneAllocator<U8> alloc = getSceneAllocator();
+	SceneAllocator<U8> alloc = getAllocator();
 
 	// Gather events for deletion
 	while(!m_eventsMarkedForDeletion.isEmpty())

+ 3 - 3
src/anki/scene/events/EventManager.h

@@ -34,7 +34,7 @@ public:
 		return *m_scene;
 	}
 
-	SceneAllocator<U8> getSceneAllocator() const;
+	SceneAllocator<U8> getAllocator() const;
 	SceneFrameAllocator<U8> getFrameAllocator() const;
 
 	/// Iterate events
@@ -57,11 +57,11 @@ public:
 	template<typename T, typename... Args>
 	ANKI_USE_RESULT Error newEvent(T*& event, Args... args)
 	{
-		event = getSceneAllocator().template newInstance<T>(this);
+		event = getAllocator().template newInstance<T>(this);
 		Error err = event->init(std::forward<Args>(args)...);
 		if(err)
 		{
-			getSceneAllocator().deleteInstance(event);
+			getAllocator().deleteInstance(event);
 		}
 		else
 		{

+ 0 - 139
src/anki/script/Scene.cpp

@@ -2962,75 +2962,6 @@ static inline void wrapReflectionProbeNode(lua_State* l)
 	lua_settop(l, 0);
 }
 
-LuaUserDataTypeInfo luaUserDataTypeInfoReflectionProxyNode = {2307826176097073810,
-	"ReflectionProxyNode",
-	LuaUserData::computeSizeForGarbageCollected<ReflectionProxyNode>(),
-	nullptr,
-	nullptr};
-
-template<>
-const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<ReflectionProxyNode>()
-{
-	return luaUserDataTypeInfoReflectionProxyNode;
-}
-
-/// Pre-wrap method ReflectionProxyNode::getSceneNodeBase.
-static inline int pwrapReflectionProxyNodegetSceneNodeBase(lua_State* l)
-{
-	LuaUserData* ud;
-	(void)ud;
-	void* voidp;
-	(void)voidp;
-	PtrSize size;
-	(void)size;
-
-	if(ANKI_UNLIKELY(LuaBinder::checkArgsCount(l, 1)))
-	{
-		return -1;
-	}
-
-	// Get "this" as "self"
-	if(LuaBinder::checkUserData(l, 1, luaUserDataTypeInfoReflectionProxyNode, ud))
-	{
-		return -1;
-	}
-
-	ReflectionProxyNode* self = ud->getData<ReflectionProxyNode>();
-
-	// Call the method
-	SceneNode& ret = *self;
-
-	// Push return value
-	voidp = lua_newuserdata(l, sizeof(LuaUserData));
-	ud = static_cast<LuaUserData*>(voidp);
-	luaL_setmetatable(l, "SceneNode");
-	extern LuaUserDataTypeInfo luaUserDataTypeInfoSceneNode;
-	ud->initPointed(&luaUserDataTypeInfoSceneNode, const_cast<SceneNode*>(&ret));
-
-	return 1;
-}
-
-/// Wrap method ReflectionProxyNode::getSceneNodeBase.
-static int wrapReflectionProxyNodegetSceneNodeBase(lua_State* l)
-{
-	int res = pwrapReflectionProxyNodegetSceneNodeBase(l);
-	if(res >= 0)
-	{
-		return res;
-	}
-
-	lua_error(l);
-	return 0;
-}
-
-/// Wrap class ReflectionProxyNode.
-static inline void wrapReflectionProxyNode(lua_State* l)
-{
-	LuaBinder::createClass(l, &luaUserDataTypeInfoReflectionProxyNode);
-	LuaBinder::pushLuaCFuncMethod(l, "getSceneNodeBase", wrapReflectionProxyNodegetSceneNodeBase);
-	lua_settop(l, 0);
-}
-
 LuaUserDataTypeInfo luaUserDataTypeInfoOccluderNode = {-6885028590097645115,
 	"OccluderNode",
 	LuaUserData::computeSizeForGarbageCollected<OccluderNode>(),
@@ -3789,74 +3720,6 @@ static int wrapSceneGraphnewReflectionProbeNode(lua_State* l)
 	return 0;
 }
 
-/// Pre-wrap method SceneGraph::newReflectionProxyNode.
-static inline int pwrapSceneGraphnewReflectionProxyNode(lua_State* l)
-{
-	LuaUserData* ud;
-	(void)ud;
-	void* voidp;
-	(void)voidp;
-	PtrSize size;
-	(void)size;
-
-	if(ANKI_UNLIKELY(LuaBinder::checkArgsCount(l, 3)))
-	{
-		return -1;
-	}
-
-	// Get "this" as "self"
-	if(LuaBinder::checkUserData(l, 1, luaUserDataTypeInfoSceneGraph, ud))
-	{
-		return -1;
-	}
-
-	SceneGraph* self = ud->getData<SceneGraph>();
-
-	// Pop arguments
-	const char* arg0;
-	if(ANKI_UNLIKELY(LuaBinder::checkString(l, 2, arg0)))
-	{
-		return -1;
-	}
-
-	const char* arg1;
-	if(ANKI_UNLIKELY(LuaBinder::checkString(l, 3, arg1)))
-	{
-		return -1;
-	}
-
-	// Call the method
-	ReflectionProxyNode* ret = newSceneNode<ReflectionProxyNode>(self, arg0, arg1);
-
-	// Push return value
-	if(ANKI_UNLIKELY(ret == nullptr))
-	{
-		lua_pushstring(l, "Glue code returned nullptr");
-		return -1;
-	}
-
-	voidp = lua_newuserdata(l, sizeof(LuaUserData));
-	ud = static_cast<LuaUserData*>(voidp);
-	luaL_setmetatable(l, "ReflectionProxyNode");
-	extern LuaUserDataTypeInfo luaUserDataTypeInfoReflectionProxyNode;
-	ud->initPointed(&luaUserDataTypeInfoReflectionProxyNode, const_cast<ReflectionProxyNode*>(ret));
-
-	return 1;
-}
-
-/// Wrap method SceneGraph::newReflectionProxyNode.
-static int wrapSceneGraphnewReflectionProxyNode(lua_State* l)
-{
-	int res = pwrapSceneGraphnewReflectionProxyNode(l);
-	if(res >= 0)
-	{
-		return res;
-	}
-
-	lua_error(l);
-	return 0;
-}
-
 /// Pre-wrap method SceneGraph::newOccluderNode.
 static inline int pwrapSceneGraphnewOccluderNode(lua_State* l)
 {
@@ -4118,7 +3981,6 @@ static inline void wrapSceneGraph(lua_State* l)
 	LuaBinder::pushLuaCFuncMethod(l, "newStaticCollisionNode", wrapSceneGraphnewStaticCollisionNode);
 	LuaBinder::pushLuaCFuncMethod(l, "newParticleEmitterNode", wrapSceneGraphnewParticleEmitterNode);
 	LuaBinder::pushLuaCFuncMethod(l, "newReflectionProbeNode", wrapSceneGraphnewReflectionProbeNode);
-	LuaBinder::pushLuaCFuncMethod(l, "newReflectionProxyNode", wrapSceneGraphnewReflectionProxyNode);
 	LuaBinder::pushLuaCFuncMethod(l, "newOccluderNode", wrapSceneGraphnewOccluderNode);
 	LuaBinder::pushLuaCFuncMethod(l, "newDecalNode", wrapSceneGraphnewDecalNode);
 	LuaBinder::pushLuaCFuncMethod(l, "newTriggerNode", wrapSceneGraphnewTriggerNode);
@@ -4528,7 +4390,6 @@ void wrapModuleScene(lua_State* l)
 	wrapStaticCollisionNode(l);
 	wrapParticleEmitterNode(l);
 	wrapReflectionProbeNode(l);
-	wrapReflectionProxyNode(l);
 	wrapOccluderNode(l);
 	wrapDecalNode(l);
 	wrapTriggerNode(l);

+ 0 - 16
src/anki/script/Scene.xml

@@ -341,14 +341,6 @@ using WeakArraySceneNodePtr = WeakArray<SceneNode*>;
 				</method>
 			</methods>
 		</class>
-		<class name="ReflectionProxyNode">
-			<methods>
-				<method name="getSceneNodeBase">
-					<overrideCall>SceneNode&amp; ret = *self;</overrideCall>
-					<return>SceneNode&amp;</return>
-				</method>
-			</methods>
-		</class>
 		<class name="OccluderNode">
 			<methods>
 				<method name="getSceneNodeBase">
@@ -438,14 +430,6 @@ using WeakArraySceneNodePtr = WeakArray<SceneNode*>;
 					</args>
 					<return>ReflectionProbeNode*</return>
 				</method>
-				<method name="newReflectionProxyNode">
-					<overrideCall><![CDATA[ReflectionProxyNode* ret = newSceneNode<ReflectionProxyNode>(self, arg0, arg1);]]></overrideCall>
-					<args>
-						<arg>const CString&amp;</arg>
-						<arg>const CString&amp;</arg>
-					</args>
-					<return>ReflectionProxyNode*</return>
-				</method>
 				<method name="newOccluderNode">
 					<overrideCall><![CDATA[OccluderNode* ret = newSceneNode<OccluderNode>(self, arg0, arg1);]]></overrideCall>
 					<args>