Panagiotis Christopoulos Charitos 12 лет назад
Родитель
Сommit
225e10f354

+ 1 - 1
include/anki/resource/Model.h

@@ -74,7 +74,7 @@ public:
 		const ShaderProgram*& prog,
 		const U32* subMeshIndicesArray, U subMeshIndicesCount,
 		Array<U32, ANKI_MAX_MULTIDRAW_PRIMITIVES>& indicesCountArray,
-		Array<const void*, ANKI_MAX_MULTIDRAW_PRIMITIVES>& indicesOffsetArray, 
+		Array<PtrSize, ANKI_MAX_MULTIDRAW_PRIMITIVES>& indicesOffsetArray, 
 		U32& drawcallCount) const;
 
 protected:

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

@@ -137,7 +137,7 @@ public:
 
 	/// @name SpatialComponent virtuals
 	/// @{
-	CollisionShape& getSpatialCollisionShape()
+	const CollisionShape& getSpatialCollisionShape()
 	{
 		return frustum;
 	}
@@ -205,7 +205,7 @@ public:
 
 	/// @name SpatialComponent virtuals
 	/// @{
-	CollisionShape& getSpatialCollisionShape()
+	const CollisionShape& getSpatialCollisionShape()
 	{
 		return frustum;
 	}

+ 38 - 0
include/anki/scene/InstanceNode.h

@@ -0,0 +1,38 @@
+#ifndef ANKI_SCENE_INSTANCE_NODE_H
+#define ANKI_SCENE_INSTANCE_NODE_H
+
+#include "anki/scene/SceneNode.h"
+
+namespace anki {
+
+/// @addtogroup Scene
+/// @{
+
+/// Instance component. Dummy used only for idendification
+class InstanceComponent: public SceneComponent
+{
+public:
+	InstanceComponent(SceneNode* node)
+		: SceneComponent(this, node)
+	{}
+};
+
+/// Instance scene node
+class InstanceNode: public SceneNode, public InstanceComponent, 
+	public MoveComponent
+{
+public:
+	InstanceNode(const char* name, SceneGraph* scene)
+		: SceneNode(name, scene), InstanceComponent(this), MoveComponent(this)
+	{
+		addComponent(static_cast<InstanceComponent*>(this));
+		addComponent(static_cast<MoveComponent*>(this));
+	}
+};
+
+/// @}
+
+} // end namespace anki
+
+#endif
+

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

@@ -240,7 +240,7 @@ public:
 
 	/// @name SpatialComponent virtuals
 	/// @{
-	CollisionShape& getSpatialCollisionShape()
+	const CollisionShape& getSpatialCollisionShape()
 	{
 		return sphereW;
 	}
@@ -320,7 +320,7 @@ public:
 
 	/// @name SpatialComponent virtuals
 	/// @{
-	CollisionShape& getSpatialCollisionShape()
+	const CollisionShape& getSpatialCollisionShape()
 	{
 		return frustum;
 	}

+ 21 - 29
include/anki/scene/ModelNode.h

@@ -11,32 +11,19 @@
 
 namespace anki {
 
-// Forward
-class ModelPatchNode;
-
 /// @addtogroup Scene
 /// @{
 
-/// A model instance
-class Instance: public SceneNode, public MoveComponent
-{
-public:
-	ModelPatchNodeInstance(
-		const char* name, SceneGraph* scene);
-};
-
 /// A fragment of the ModelNode
 class ModelPatchNode: public SceneNode, 
 	public RenderComponent, public SpatialComponent
 {
-	friend class ModelNode;
-
 public:
 	/// @name Constructors/Destructor
 	/// @{
 	ModelPatchNode(
 		const char* name, SceneGraph* scene, // Scene
-		const ModelPatchBase* modelPatch, U instances); // Self
+		const ModelPatchBase* modelPatch); // Self
 
 	~ModelPatchNode();
 	/// @}
@@ -47,8 +34,8 @@ public:
 	/// Implements RenderComponent::getRenderingData
 	void getRenderingData(
 		const PassLodKey& key, 
-		const Vao*& vao, const ShaderProgram*& prog,
 		const U32* subMeshIndicesArray, U subMeshIndicesCount,
+		const Vao*& vao, const ShaderProgram*& prog,
 		Drawcall& dracall);
 
 	/// Implements  RenderComponent::getMaterial
@@ -58,30 +45,38 @@ public:
 	}
 
 	/// Overrides RenderComponent::getRenderComponentWorldTransforms
-	const Transform* getRenderWorldTransforms();
+	const Transform* getRenderWorldTransforms() override;
 	/// @}
 
+	/// Override SceneNode::frameUpdate
+	void frameUpdate(F32, F32, SceneNode::UpdateType uptype) override;
+
+	/// Implement SpatialComponent::getSpatialCollisionShape
+	const CollisionShape& getSpatialCollisionShape()
+	{
+		return obb;
+	}
+
+	/// Implement SpatialComponent::getSpatialOrigin
+	Vec3 getSpatialOrigin()
+	{
+		return obb.getCenter();
+	}
+
 private:
-	Obb obb; ///< In world space.
+	Obb obb; ///< In world space
 	const ModelPatchBase* modelPatch; ///< The resource
-	SceneVector<ModelPatchNodeInstance*> instances;
-	SceneVector<Transform> transforms;
-
-	/// This is called by the last of the instances on it's moveUpdate()
-	void updateSpatialCs();
 };
 
 /// The model scene node
 class ModelNode: public SceneNode, public MoveComponent
 {
 public:
-	typedef SceneVector<ModelPatchNode*> ModelPatchNodes;
-
 	/// @name Constructors/Destructor
 	/// @{
 	ModelNode(
 		const char* name, SceneGraph* scene, // SceneNode
-		const char* modelFname, U instances = 1); // Self
+		const char* modelFname); // Self
 
 	virtual ~ModelNode();
 	/// @}
@@ -94,12 +89,9 @@ public:
 	}
 	/// @}
 
-	/// Set the local transform of one instance
-	void setInstanceLocalTransform(U instanceIndex, const Transform& trf);
-
 private:
 	ModelResourcePointer model; ///< The resource
-	ModelPatchNodes patches;
+	SceneVector<Transform> transforms;
 };
 
 /// @}

+ 11 - 9
include/anki/scene/ParticleEmitter.h

@@ -10,11 +10,13 @@
 
 namespace anki {
 
+#if 0
+
 class ParticleEmitter;
 
 /// Particle base
 /// XXX Remove SceneNode
-class ParticleBase: public SceneNode, public MoveComponent
+class ParticleBase
 {
 	friend class ParticleEmitter;
 
@@ -25,9 +27,7 @@ public:
 		PT_PHYSICS
 	};
 
-	ParticleBase(
-		const char* name, SceneGraph* scene, // SceneNode
-		ParticleType type); // Self
+	ParticleBase(ParticleType type);
 
 	virtual ~ParticleBase();
 
@@ -111,9 +111,11 @@ private:
 	/// The velocity
 	Vec3 velocity = Vec3(0.0);
 	Vec3 acceleration = Vec3(0.0);
+	Vec3 position;
 };
 
 /// Particle for bullet simulations
+#if 0
 class Particle: public ParticleBase
 {
 public:
@@ -136,6 +138,7 @@ public:
 private:
 	RigidBody* body;
 };
+#endif
 
 /// The particle emitter scene node. This scene node emitts
 class ParticleEmitter: public SceneNode, public SpatialComponent, 
@@ -168,15 +171,13 @@ public:
 		const PassLodKey& key, 
 		const Vao*& vao, const ShaderProgram*& prog,
 		const U32* subMeshIndicesArray, U subMeshIndicesCount,
-		Array<U32, ANKI_MAX_MULTIDRAW_PRIMITIVES>& indicesCountArray,
-		Array<const void*, ANKI_MAX_MULTIDRAW_PRIMITIVES>& indicesOffsetArray, 
-		U32& drawcallCount) const;
+		Drawcall& drawcall);
 
 	/// Implements  RenderComponent::getMaterial
 	const Material& getMaterial();
 
 	/// Overrides RenderComponent::getRenderWorldTransforms
-	const Transform* getRenderWorldTransforms()
+	const Transform* getRenderWorldTransforms() override
 	{
 		return &(*instancingTransformations)[0];
 	}
@@ -200,7 +201,6 @@ private:
 	btCollisionShape* collShape = nullptr;
 	SceneVector<ParticleBase*> particles;
 	F32 timeLeftForNextEmission;
-	/// The resource
 	Aabb aabb;
 
 	// Opt: We dont have to make extra calculations if the ParticleEmitter's
@@ -219,6 +219,8 @@ private:
 	void createParticlesSimpleSimulation(SceneGraph* scene);
 };
 
+#endif
+
 } // end namespace anki
 
 #endif

+ 3 - 1
include/anki/scene/SceneComponent.h

@@ -14,6 +14,7 @@ class RenderComponent;
 class SpatialComponent;
 class LightComponent;
 class RigidBody;
+class InstanceComponent;
 
 class SceneComponent;
 
@@ -24,7 +25,8 @@ typedef VisitableCommonBase<
 	RenderComponent,
 	SpatialComponent,
 	LightComponent,
-	RigidBody> SceneComponentVisitable;
+	RigidBody,
+	InstanceComponent> SceneComponentVisitable;
 
 /// Scene node component
 class SceneComponent: public SceneComponentVisitable

+ 5 - 23
include/anki/scene/SceneNode.h

@@ -3,8 +3,8 @@
 
 #include "anki/scene/Property.h"
 #include "anki/scene/Common.h"
+#include "anki/scene/SceneObject.h"
 #include "anki/scene/SceneComponent.h"
-#include "anki/util/Object.h"
 
 namespace anki {
 
@@ -14,7 +14,7 @@ class SceneGraph; // Don't include
 /// @{
 
 /// Interface class backbone of scene
-class SceneNode
+class SceneNode: public SceneObject
 {
 public:
 	/// Scene node update type
@@ -48,15 +48,6 @@ public:
 	{
 		return name.length() > 0 ? name.c_str() : nullptr;
 	}
-
-	SceneAllocator<U8> getSceneAllocator() const;
-
-	SceneAllocator<U8> getSceneFrameAllocator() const;
-
-	SceneGraph& getSceneGraph()
-	{
-		return *scene;
-	}
 	/// @}
 
 	/// This is called by the scene every frame after logic and before
@@ -83,16 +74,6 @@ public:
 	/// Return the last frame the node was updated. It checks all components
 	U32 getLastUpdateFrame() const;
 
-	/// Mark a node for deletion
-	void markForDeletion()
-	{
-		markedForDeletion = true;
-	}
-	Bool isMarkedForDeletion()
-	{
-		return markedForDeletion;
-	}
-
 	/// Iterate all components
 	template<typename Func>
 	void iterateComponents(Func func)
@@ -179,11 +160,12 @@ protected:
 	/// Append a component to the components container
 	void addComponent(SceneComponent* comp);
 
+	/// Remove a component from the container
+	void removeComponent(SceneComponent* comp);
+
 private:
-	SceneGraph* scene = nullptr;
 	SceneString name; ///< A unique name
 	SceneVector<SceneComponent*> components;
-	Bool8 markedForDeletion;
 };
 /// @}
 

+ 12 - 20
include/anki/scene/SceneObject.h

@@ -6,31 +6,17 @@
 
 namespace anki {
 
-#if 0
-
 // Forward
 class SceneGraph;
 
-/// The SceneObject deleter
-template<typename T, typename Alloc>
-struct SceneObjectDeleter
-{
-	void operator()(T* x)
-	{
-		Alloc alloc = x->getSceneAllocator();
-
-		alloc.destroy(x);
-		alloc.deallocate(x, 1);
-	}
-};
+/// @addtogroup Scene
+/// @{
 
 /// The base of all scene related objects
-class SceneObject: public Object<SceneObject, SceneAllocator<SceneObject>,
-	SceneObjectDeleter<SceneObject, SceneAllocator<SceneObject>>>
+class SceneObject: public Object<SceneObject, SceneAllocator<SceneObject>>
 {
 public:
-	typedef Object<SceneObject, SceneAllocator<SceneObject>,
-		SceneObjectDeleter<SceneObject, SceneAllocator<SceneObject>>> Base;
+	typedef Object<SceneObject, SceneAllocator<SceneObject>> Base;
 
 	SceneObject(SceneObject* parent, SceneGraph* scene);
 
@@ -43,11 +29,17 @@ public:
 		return *scene;
 	}
 
+	Bool isMarkedForDeletion() const
+	{
+		return markedForDeletion;
+	}
+	void markForDeletion();
+
 public:
 	SceneGraph* scene;
+	Bool8 markedForDeletion;
 };
-
-#endif
+/// @}
 
 } // end namespace anki
 

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

@@ -45,7 +45,7 @@ public:
 
 	/// @name Accessors
 	/// @{
-	virtual CollisionShape& getSpatialCollisionShape() = 0;
+	virtual const CollisionShape& getSpatialCollisionShape() = 0;
 
 	const Aabb& getAabb() const
 	{
@@ -53,9 +53,9 @@ public:
 	}
 
 	/// Get optimal collision shape for visibility tests
-	CollisionShape& getVisibilityCollisionShape()
+	const CollisionShape& getVisibilityCollisionShape()
 	{
-		CollisionShape& cs = getSpatialCollisionShape();
+		const CollisionShape& cs = getSpatialCollisionShape();
 		if(cs.getCollisionShapeType() == CollisionShape::CST_SPHERE)
 		{
 			return cs;

+ 29 - 15
include/anki/scene/StaticGeometryNode.h

@@ -15,12 +15,20 @@ namespace anki {
 class StaticGeometrySpatial: public SpatialComponent
 {
 public:
-	/// @name Constructors/Destructor
-	/// @{
+	StaticGeometrySpatial(SceneNode* node, const Obb* obb);
 
-	/// @note The node is only to steal the allocator
-	StaticGeometrySpatial(const Obb* obb, SceneNode& node);
-	/// @}
+	const CollisionShape& getSpatialCollisionShape()
+	{
+		return *obb;
+	}
+
+	Vec3 getSpatialOrigin()
+	{
+		return obb->getCenter();
+	}
+
+private:
+	const Obb* obb;
 };
 
 /// Static geometry scene node patch
@@ -37,22 +45,28 @@ public:
 	~StaticGeometryPatchNode();
 	/// @}
 
+	/// @name SpatialComponent virtuals
+	/// @{
+	const CollisionShape& getSpatialCollisionShape()
+	{
+		return *obb;
+	}
+
+	Vec3 getSpatialOrigin()
+	{
+		return obb->getCenter();
+	}
+	/// @}
+
 	/// @name RenderComponent virtuals
 	/// @{
 
 	/// Implements RenderComponent::getRenderingData
 	void getRenderingData(
 		const PassLodKey& key, 
-		const Vao*& vao, const ShaderProgram*& prog,
 		const U32* subMeshIndicesArray, U subMeshIndicesCount,
-		Array<U32, ANKI_MAX_MULTIDRAW_PRIMITIVES>& indicesCountArray,
-		Array<const void*, ANKI_MAX_MULTIDRAW_PRIMITIVES>& indicesOffsetArray, 
-		U32& drawcallCount) const
-	{
-		modelPatch->getRenderingDataSub(key, vao, prog, 
-			subMeshIndicesArray, subMeshIndicesCount, 
-			indicesCountArray, indicesOffsetArray, drawcallCount);
-	}
+		const Vao*& vao, const ShaderProgram*& prog,
+		Drawcall& drawcall);
 
 	/// Implements  RenderComponent::getMaterial
 	const Material& getMaterial()
@@ -63,6 +77,7 @@ public:
 
 private:
 	const ModelPatchBase* modelPatch;
+	const Obb* obb; 
 };
 
 /// Static geometry scene node
@@ -77,7 +92,6 @@ public:
 
 private:
 	ModelResourcePointer model;
-	SceneVector<StaticGeometryPatchNode*> patches;
 };
 
 /// @}

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

@@ -91,9 +91,9 @@ struct DistanceSortFunctor
 		ANKI_ASSERT(a.node && b.node);
 
 		F32 dist0 = origin.getDistanceSquared(
-			a.node->getComponent<SpatialComponent>().getOrigin());
+			a.node->getComponent<SpatialComponent>().getSpatialOrigin());
 		F32 dist1 = origin.getDistanceSquared(
-			b.node->getComponent<SpatialComponent>().getOrigin());
+			b.node->getComponent<SpatialComponent>().getSpatialOrigin());
 
 		return dist0 < dist1;
 	}

+ 11 - 0
include/anki/util/Functions.h

@@ -132,6 +132,17 @@ struct RemovePointer<T*>
 	typedef T Type;
 };
 
+/// Perform a static cast
+template<typename To, typename From>
+To staticCast(From from)
+{
+#if ANKI_DEBUG
+	return dynamic_cast<To>(from);
+#else
+	return static_cast<To>(from);
+#endif
+}
+
 /// @}
 /// @}
 

+ 1 - 0
include/anki/util/Object.h

@@ -154,6 +154,7 @@ public:
 		for(Value* c : children)
 		{
 			vis(*c);
+			c->visitChildren(vis);
 		}
 	}
 

+ 3 - 4
src/resource/Model.cpp

@@ -116,7 +116,7 @@ void ModelPatchBase::getRenderingDataSub(const PassLodKey& key,
 	const Vao*& vao, const ShaderProgram*& prog, 
 	const U32* subMeshIndexArray, U subMeshIndexCount,
 	Array<U32, ANKI_MAX_MULTIDRAW_PRIMITIVES>& indicesCountArray,
-	Array<const void*, ANKI_MAX_MULTIDRAW_PRIMITIVES>& indicesOffsetArray, 
+	Array<PtrSize, ANKI_MAX_MULTIDRAW_PRIMITIVES>& indicesOffsetArray, 
 	U32& drawcallCount) const
 {
 	const U meshLods = getMeshesCount();
@@ -150,7 +150,7 @@ void ModelPatchBase::getRenderingDataSub(const PassLodKey& key,
 		|| mesh.getSubMeshesCount() == 0)
 	{
 		drawcallCount = 1;
-		indicesOffsetArray[0] = nullptr;
+		indicesOffsetArray[0] = 0;
 		indicesCountArray[0] = mesh.getIndicesCount();
 	}
 	else
@@ -181,8 +181,7 @@ void ModelPatchBase::getRenderingDataSub(const PassLodKey& key,
 				indicesCountArray[drawcallCount] =
 					mesh.getIndicesCountSub((U)index, offset);
 
-				indicesOffsetArray[drawcallCount] = 
-					reinterpret_cast<const void*>((PtrSize)offset);
+				indicesOffsetArray[drawcallCount] = (PtrSize)offset;
 
 				++drawcallCount;
 			}

+ 67 - 135
src/scene/ModelNode.cpp

@@ -1,25 +1,14 @@
 #include "anki/scene/ModelNode.h"
 #include "anki/scene/SceneGraph.h"
+#include "anki/scene/InstanceNode.h"
 #include "anki/resource/Model.h"
 #include "anki/resource/Skeleton.h"
 #include "anki/physics/RigidBody.h"
 #include "anki/physics/PhysicsWorld.h"
+#include "anki/gl/Drawcall.h"
 
 namespace anki {
 
-//==============================================================================
-// Instance                                                                    =
-//==============================================================================
-
-//==============================================================================
-Instance::Instance(
-	const char* name, SceneGraph* scene)
-	:	SceneNode(name, scene),
-		MoveComponent(this)
-{
-	addComponent(static_cast<MoveComponent*>(this));
-}
-
 //==============================================================================
 // ModelPatchNode                                                              =
 //==============================================================================
@@ -27,129 +16,105 @@ Instance::Instance(
 //==============================================================================
 ModelPatchNode::ModelPatchNode(
 	const char* name, SceneGraph* scene,
-	const ModelPatchBase* modelPatch_, U instancesCount)
+	const ModelPatchBase* modelPatch_)
 	:	SceneNode(name, scene),
-		MoveComponent(this, MoveComponent::MF_IGNORE_LOCAL_TRANSFORM),
 		RenderComponent(this),
-		SpatialComponent(this, &obb), 
-		modelPatch(modelPatch_),
-		instances(getSceneAllocator()),
-		transforms(getSceneAllocator())
+		SpatialComponent(this), 
+		modelPatch(modelPatch_)
 {
-	sceneNodeProtected.moveC = this;
-	sceneNodeProtected.renderC = this;
-	sceneNodeProtected.spatialC = this;
+	addComponent(static_cast<RenderComponent*>(this));
+	addComponent(static_cast<SpatialComponent*>(this));
 
 	RenderComponent::init();
-
-	// Create the instances as ModelPatchNodeInstance
-	if(instancesCount > 1)
-	{
-		instances.resize(instancesCount, nullptr);
-		transforms.resize(instancesCount, Transform::getIdentity());
-
-		Vec3 pos = Vec3(0.0);
-
-		for(U i = 0; i < instancesCount; i++)
-		{
-			ModelPatchNodeInstance* instance;
-			getSceneGraph().newSceneNode(instance, nullptr, this);
-
-			//MoveComponent::addChild(instance);
-
-			instance->setLocalOrigin(pos);
-			pos.x() += 2.0;
-
-			SpatialComponent::addChild(instance);
-			instances[i] = instance;
-		}
-	}
 }
 
 //==============================================================================
 ModelPatchNode::~ModelPatchNode()
-{
-	for(ModelPatchNodeInstance* instance : instances)
-	{
-		getSceneGraph().deleteSceneNode(instance);
-	}
-}
+{}
 
 //==============================================================================
 void ModelPatchNode::getRenderingData(
 	const PassLodKey& key, 
-	const Vao*& vao, const ShaderProgram*& prog,
 	const U32* subMeshIndicesArray, U subMeshIndicesCount,
-	Drawcall& dracall)
+	const Vao*& vao, const ShaderProgram*& prog,
+	Drawcall& dc)
 {
-	drawcall.prim
+	dc.primitiveType = GL_TRIANGLES;
+	dc.indicesType = GL_UNSIGNED_SHORT;
+
+	U spatialsCount = 0;
+	iterateComponentsOfType<SpatialComponent>([&](SpatialComponent&)
+	{
+		++spatialsCount;
+	});
+
+	dc.instancesCount = spatialsCount;
 
 	modelPatch->getRenderingDataSub(key, vao, prog, 
 		subMeshIndicesArray, subMeshIndicesCount, 
-		indicesCountArray, indicesOffsetArray, drawcallCount);
+		dc.countArray, dc.offsetArray, dc.drawCount);
 }
 
 //==============================================================================
 const Transform* ModelPatchNode::getRenderWorldTransforms()
 {
-	if(transforms.size() == 0)
+	SceneNode* parent = staticCast<SceneNode*>(getParent());
+	ANKI_ASSERT(parent);
+	MoveComponent& move = parent->getComponent<MoveComponent>();
+
+	if(1) // XXX
 	{
 		// NO instancing
-		return &getWorldTransform();
+		return &move.getWorldTransform();
 	}
 	else
 	{
 		// Instancing
 
-		ANKI_ASSERT(transforms.size() == instances.size());
-
-		// Set the transforms buffer
-		for(U i = 0; i < instances.size(); i++)
-		{
-			transforms[i] = instances[i]->getWorldTransform();
-		}
-
-		return &transforms[0];
+		// XXX
+		ANKI_ASSERT(0 && "todo");
 	}
 }
 
 //==============================================================================
-void ModelPatchNode::moveUpdate()
+void ModelPatchNode::frameUpdate(F32, F32, SceneNode::UpdateType uptype)
 {
-	if(instances.size() == 0)
+	if(uptype != SceneNode::ASYNC_UPDATE)
 	{
-		// NO instancing
+		return;
+	}
 
-		obb = modelPatch->getBoundingShape().getTransformed(
-			getWorldTransform());
+	SceneNode* parent = staticCast<SceneNode*>(getParent());
+	ANKI_ASSERT(parent);
 
-		SpatialComponent::markForUpdate();
-	}
-	else
+	// Count the instances of the parent
+	U instancesCount = 0;
+	parent->visitThisAndChildren([&](SceneObject& so)
 	{
-		// Instancing
+		SceneNode* sn = staticCast<SceneNode*>(&so);
 		
-		// Do nothing. You cannot update the obb because the instances have
-		// not been updated their CSs yet. The update will be triggered by the 
-		// last instance.
-	}
-}
-
-//==============================================================================
-void ModelPatchNode::updateSpatialCs()
-{
-	ANKI_ASSERT(instances.size() > 0);
-
-	obb = instances[0]->obb;
+		if(sn->tryGetComponent<InstanceComponent>())
+		{
+			++instancesCount;
+		}
+	});
 
-	for(U i = 1; i < instances.size(); i++)
+	if(instancesCount == 0)
 	{
-		ANKI_ASSERT(instances[i]);
+		// No instances
+		const MoveComponent& parentMove = parent->getComponent<MoveComponent>();
 
-		obb = obb.getCompoundShape(instances[i]->obb);
+		if(parentMove.getTimestamp() == getGlobTimestamp())
+		{
+			obb = modelPatch->getBoundingShape().getTransformed(
+				parentMove.getWorldTransform());
+		}
+	}
+	else
+	{
+		// XXX
+		ANKI_ASSERT(0 && "todo");
 	}
-
-	SpatialComponent::markForUpdate();
 }
 
 //==============================================================================
@@ -159,27 +124,21 @@ void ModelPatchNode::updateSpatialCs()
 //==============================================================================
 ModelNode::ModelNode(
 	const char* name, SceneGraph* scene,
-	const char* modelFname, U instances)
+	const char* modelFname)
 	: 	SceneNode(name, scene),
 		MoveComponent(this),
-		patches(getSceneAllocator())
+		transforms(getSceneAllocator())
 {
-	sceneNodeProtected.moveC = this;
+	addComponent(static_cast<MoveComponent*>(this));
 
 	model.load(modelFname);
 
-	patches.reserve(model->getModelPatches().size());
-
-	U i = 0;
 	for(const ModelPatchBase* patch : model->getModelPatches())
 	{
 		ModelPatchNode* mpn;
-		getSceneGraph().newSceneNode(mpn, nullptr, patch, instances);
+		getSceneGraph().newSceneNode(mpn, nullptr, patch);
 
-		MoveComponent::addChild(mpn);
-
-		patches.push_back(mpn);
-		++i;
+		SceneObject::addChild(mpn);
 	}
 
 	// Load rigid body
@@ -188,51 +147,24 @@ ModelNode::ModelNode(
 		RigidBody::Initializer init;
 		init.mass = 1.0;
 		init.shape = const_cast<btCollisionShape*>(model->getCollisionShape());
-		init.startTrf.getOrigin().y() = 20.0;
+		init.node = this;
 
 		RigidBody* body;
 		
 		getSceneGraph().getPhysics().newPhysicsObject<RigidBody>(
 			body, init);
 
-		sceneNodeProtected.rigidBodyC = body;
+		addComponent(static_cast<RigidBody*>(body));
 	}
 }
 
 //==============================================================================
 ModelNode::~ModelNode()
 {
-	for(ModelPatchNode* patch : patches)
-	{
-		getSceneGraph().deleteSceneNode(patch);
-	}
-
-	if(sceneNodeProtected.rigidBodyC)
-	{
-		getSceneGraph().getPhysics().deletePhysicsObject(
-			sceneNodeProtected.rigidBodyC);
-	}
-}
-
-//==============================================================================
-void ModelNode::setInstanceLocalTransform(U instanceIndex, const Transform& trf)
-{
-	ANKI_ASSERT(patches.size() > 0);
-
-	if(patches[0]->instances.size() > 0)
+	RigidBody* body = tryGetComponent<RigidBody>();
+	if(body)
 	{
-		ANKI_ASSERT(instanceIndex < patches[0]->instances.size());
-
-		for(ModelPatchNode* patch : patches)
-		{
-			patch->instances[instanceIndex]->setLocalTransform(trf);
-		}
-	}
-	else
-	{
-		ANKI_ASSERT(instanceIndex == 0);
-
-		setLocalTransform(trf);
+		getSceneGraph().getPhysics().deletePhysicsObject(body);
 	}
 }
 

+ 20 - 24
src/scene/ParticleEmitter.cpp

@@ -7,6 +7,8 @@
 
 namespace anki {
 
+#if 0
+
 //==============================================================================
 // Misc                                                                        =
 //==============================================================================
@@ -41,12 +43,8 @@ Vec3 getRandom(const Vec3& initial, const Vec3& deviation)
 //==============================================================================
 
 //==============================================================================
-ParticleBase::ParticleBase(
-	const char* name, SceneGraph* scene, // SceneNode
-	ParticleType type_)
-	:	SceneNode(name, scene),
-		MoveComponent(this),
-		type(type_)
+ParticleBase::ParticleBase(ParticleType type_)
+	: type(type_)
 {
 	sceneNodeProtected.moveC = this;
 }
@@ -73,9 +71,8 @@ void ParticleBase::revive(const ParticleEmitter& pe,
 //==============================================================================
 
 //==============================================================================
-ParticleSimple::ParticleSimple(
-	const char* name, SceneGraph* scene)
-	: ParticleBase(name, scene, PT_SIMPLE)
+ParticleSimple::ParticleSimple()
+	: ParticleBase(PT_SIMPLE)
 {}
 
 //==============================================================================
@@ -88,13 +85,10 @@ void ParticleSimple::simulate(const ParticleEmitter& pe,
 		static_cast<const ParticleEmitterProperties&>(pe).
 		particle.gravity.getLength() > 0.0);
 
-	Transform trf = getWorldTransform();
-	Vec3 xp = trf.getOrigin();
+	Vec3 xp = position;
 	Vec3 xc = acceleration * (dt * dt) + velocity * dt + xp;
 
-	trf.setOrigin(xc);
-
-	setLocalTransform(trf);
+	position = xc;
 
 	velocity += acceleration * dt;
 }
@@ -112,21 +106,18 @@ void ParticleSimple::revive(const ParticleEmitter& pe,
 			props.particle.gravityDeviation);
 
 	// Set the initial position
-	Vec3 pos = getRandom(props.particle.startingPos,
+	position = getRandom(props.particle.startingPos,
 		props.particle.startingPosDeviation);
 
-	pos += pe.getWorldTransform().getOrigin();
-
-	Transform trf;
-	trf.setIdentity();
-	trf.setOrigin(pos);
-	setLocalTransform(trf);
+	position += pe.getWorldTransform().getOrigin();
 }
 
 //==============================================================================
 // Particle                                                                    =
 //==============================================================================
 
+#if 0
+
 //==============================================================================
 Particle::Particle(
 	const char* name, SceneGraph* scene, // SceneNode
@@ -209,6 +200,7 @@ void Particle::revive(const ParticleEmitter& pe,
 		toBt(Transform(pos, pe.getWorldTransform().getRotation(), 1.0)));
 	body->setWorldTransform(trf);
 }
+#endif
 
 //==============================================================================
 // ParticleEmitter                                                             =
@@ -224,9 +216,9 @@ ParticleEmitter::ParticleEmitter(
 		RenderComponent(this),
 		particles(getSceneAllocator())
 {
-	sceneNodeProtected.spatialC = this;
-	sceneNodeProtected.moveC = this;
-	sceneNodeProtected.renderC = this;
+	addComponent(static_cast<MoveComponent>(this));
+	addComponent(static_cast<SpatialComponent>(this));
+	addComponent(static_cast<RenderComponent>(this));
 
 	// Load resource
 	particleEmitterResource.load(filename);
@@ -304,6 +296,7 @@ void ParticleEmitter::moveUpdate()
 //==============================================================================
 void ParticleEmitter::createParticlesSimulation(SceneGraph* scene)
 {
+#if 0
 	collShape = getSceneAllocator().newInstance<btSphereShape>(particle.size);
 
 	RigidBody::Initializer binit;
@@ -327,6 +320,7 @@ void ParticleEmitter::createParticlesSimulation(SceneGraph* scene)
 
 		particles.push_back(part);
 	}
+#endif
 }
 
 //==============================================================================
@@ -463,4 +457,6 @@ void ParticleEmitter::frameUpdate(F32 prevUpdateTime, F32 crntTime, I frame)
 	}
 }
 
+#endif
+
 } // end namespace anki

+ 10 - 17
src/scene/SceneNode.cpp

@@ -8,10 +8,9 @@ namespace anki {
 
 //==============================================================================
 SceneNode::SceneNode(const char* name_, SceneGraph* scene_)
-	:	scene(scene_),
+	:	SceneObject(nullptr, scene_),
 		name(getSceneAllocator()),
-		components(getSceneAllocator()),
-		markedForDeletion(false)
+		components(getSceneAllocator())
 {
 	ANKI_ASSERT(scene);
 
@@ -33,20 +32,6 @@ SceneNode::~SceneNode()
 	}
 }
 
-//==============================================================================
-SceneAllocator<U8> SceneNode::getSceneAllocator() const
-{
-	ANKI_ASSERT(scene);
-	return scene->getAllocator();
-}
-
-//==============================================================================
-SceneAllocator<U8> SceneNode::getSceneFrameAllocator() const
-{
-	ANKI_ASSERT(scene);
-	return scene->getFrameAllocator();
-}
-
 //==============================================================================
 U32 SceneNode::getLastUpdateFrame() const
 {
@@ -67,4 +52,12 @@ void SceneNode::addComponent(SceneComponent* comp)
 	components.push_back(comp);
 }
 
+//==============================================================================
+void SceneNode::removeComponent(SceneComponent* comp)
+{
+	auto it = std::find(components.begin(), components.end(), comp);
+	ANKI_ASSERT(it != components.end());
+	components.erase(it);
+}
+
 } // end namespace anki

+ 16 - 5
src/scene/SceneObject.cpp

@@ -3,12 +3,14 @@
 
 namespace anki {
 
-#if 0
-
 //==============================================================================
 SceneObject::SceneObject(SceneObject* parent, SceneGraph* scene_)
-	: Base(parent, scene_->getAllocator()), scene(scene_)
-{}
+	:	Base(parent, scene_->getAllocator()),
+		scene(scene_),
+		markedForDeletion(false)
+{
+	ANKI_ASSERT(scene);
+}
 
 //==============================================================================
 SceneAllocator<U8> SceneObject::getSceneAllocator() const
@@ -24,6 +26,15 @@ SceneAllocator<U8> SceneObject::getSceneFrameAllocator() const
 	return scene->getFrameAllocator();
 }
 
-#endif
+//==============================================================================
+void SceneObject::markForDeletion()
+{
+	markedForDeletion = true;
+
+	visitChildren([](SceneObject& obj)
+	{
+		obj.markForDeletion();
+	});
+}
 
 } // end namespace anki

+ 53 - 22
src/scene/StaticGeometryNode.cpp

@@ -1,5 +1,6 @@
 #include "anki/scene/StaticGeometryNode.h"
 #include "anki/scene/SceneGraph.h"
+#include "anki/gl/Drawcall.h"
 
 namespace anki {
 
@@ -8,9 +9,9 @@ namespace anki {
 //==============================================================================
 
 //==============================================================================
-StaticGeometrySpatial::StaticGeometrySpatial(const Obb* obb,
-	SceneNode& node)
-	: SpatialComponent(&node, obb)
+StaticGeometrySpatial::StaticGeometrySpatial(
+	SceneNode* node, const Obb* obb_)
+	: SpatialComponent(node), obb(obb_)
 {}
 
 //==============================================================================
@@ -21,37 +22,75 @@ StaticGeometrySpatial::StaticGeometrySpatial(const Obb* obb,
 StaticGeometryPatchNode::StaticGeometryPatchNode(
 	const char* name, SceneGraph* scene, const ModelPatchBase* modelPatch_)
 	:	SceneNode(name, scene),
-		SpatialComponent(this, &modelPatch_->getBoundingShape()),
+		SpatialComponent(this),
 		RenderComponent(this),
 		modelPatch(modelPatch_)
 {
-	sceneNodeProtected.spatialC = this;
-	sceneNodeProtected.renderC = this;
+	addComponent(static_cast<SpatialComponent*>(this));
+	addComponent(static_cast<RenderComponent*>(this));
 
 	ANKI_ASSERT(modelPatch);
 	RenderComponent::init();
 
-	// For all submeshes create a StaticGeometrySp[atial
+	// Check if multimesh
 	if(modelPatch->getSubMeshesCount() > 1)
 	{
-		for(U i = 0; i < modelPatch->getSubMeshesCount(); i++)
+		// If multimesh create additional spatial components
+
+		obb = &modelPatch->getBoundingShapeSub(0);
+
+		for(U i = 1; i < modelPatch->getSubMeshesCount(); i++)
 		{
 			StaticGeometrySpatial* spatial =
 				getSceneAllocator().newInstance<StaticGeometrySpatial>(
-				&modelPatch->getBoundingShapeSub(i), *this);
+				this, &modelPatch->getBoundingShapeSub(i));
 
-			SpatialComponent::addChild(spatial);
+			addComponent(static_cast<SpatialComponent*>(spatial));
 		}
 	}
+	else
+	{
+		// If not multimesh then set the current spatial component
+
+		obb = &modelPatch->getBoundingShape();
+	}
 }
 
 //==============================================================================
 StaticGeometryPatchNode::~StaticGeometryPatchNode()
 {
-	visitSubSpatials([&](SpatialComponent& spatial)
+	U i = 0;
+	iterateComponentsOfType<SpatialComponent>([&](SpatialComponent& spatial)
+	{
+		if(i != 0)
+		{
+			getSceneAllocator().deleteInstance(&spatial);
+		}
+		++i;
+	});
+}
+
+//==============================================================================
+void StaticGeometryPatchNode::getRenderingData(
+	const PassLodKey& key, 
+	const U32* subMeshIndicesArray, U subMeshIndicesCount,
+	const Vao*& vao, const ShaderProgram*& prog,
+	Drawcall& dc)
+{
+	dc.primitiveType = GL_TRIANGLES;
+	dc.indicesType = GL_UNSIGNED_SHORT;
+
+	U spatialsCount = 0;
+	iterateComponentsOfType<SpatialComponent>([&](SpatialComponent&)
 	{
-		getSceneAllocator().deleteInstance(&spatial);
+		++spatialsCount;
 	});
+
+	dc.instancesCount = spatialsCount;
+
+	modelPatch->getRenderingDataSub(key, vao, prog, 
+		subMeshIndicesArray, subMeshIndicesCount, 
+		dc.countArray, dc.offsetArray, dc.drawCount);
 }
 
 //==============================================================================
@@ -61,12 +100,10 @@ StaticGeometryPatchNode::~StaticGeometryPatchNode()
 //==============================================================================
 StaticGeometryNode::StaticGeometryNode(
 	const char* name, SceneGraph* scene, const char* filename)
-	: SceneNode(name, scene), patches(getSceneAllocator())
+	: SceneNode(name, scene)
 {
 	model.load(filename);
 
-	patches.reserve(model->getModelPatches().size());
-
 	U i = 0;
 	for(const ModelPatchBase* patch : model->getModelPatches())
 	{
@@ -75,18 +112,12 @@ StaticGeometryNode::StaticGeometryNode(
 		StaticGeometryPatchNode* node;
 		getSceneGraph().newSceneNode(node, name_.c_str(), patch);
 
-		patches.push_back(node);
 		++i;
 	}
 }
 
 //==============================================================================
 StaticGeometryNode::~StaticGeometryNode()
-{
-	for(StaticGeometryPatchNode* patch : patches)
-	{
-		getSceneGraph().deleteSceneNode(patch);
-	}
-}
+{}
 
 } // end namespace anki