Browse Source

Removing some virtuals to speedup things

Panagiotis Christopoulos Charitos 13 years ago
parent
commit
6fd1bc19cc

+ 50 - 76
include/anki/resource/Mesh.h

@@ -37,37 +37,73 @@ public:
 		const VertexAttribute attrib, const Vbo*& vbo,
 		U32& size, GLenum& type, U32& stride, U32& offset) const = 0;
 
-	virtual U32 getTextureChannelsCount() const = 0;
+	U32 getTextureChannelsCount() const
+	{
+		return meshProtected.texChannelsCount;
+	}
 
-	virtual Bool hasWeights() const = 0;
+	Bool hasWeights() const
+	{
+		return meshProtected.weights;
+	}
 
 	/// Used only to clone the VBO
-	virtual U32 getVerticesCount() const = 0;
+	U32 getVerticesCount() const
+	{
+		return meshProtected.vertsCount;
+	}
 
-	virtual U32 getIndicesCount() const = 0;
+	U32 getIndicesCount() const
+	{
+		ANKI_ASSERT(meshProtected.subMeshes.size() > 0);
+		return meshProtected.subMeshes[0].indicesCount;
+	}
 
-	virtual const Obb& getBoundingShape() const = 0;
+	const Obb& getBoundingShape() const
+	{
+		return meshProtected.obb;
+	}
 
-	virtual U32 getIndicesCountSub(U32 subMeshId, U32& offset) const
+	U32 getIndicesCountSub(U subMeshId, U32& offset) const
 	{
-		ANKI_ASSERT(subMeshId == 0);
-		offset = 0;
-		return getIndicesCount();
+		ANKI_ASSERT(subMeshId < meshProtected.subMeshes.size());
+		const SubMesh& sm = meshProtected.subMeshes[subMeshId];
+		offset = sm.indicesOffset;
+		return sm.indicesCount;
 	}
 
-	virtual const Obb& getBoundingShapeSub(U32 subMeshId) const
+	const Obb& getBoundingShapeSub(U subMeshId) const
 	{
-		ANKI_ASSERT(subMeshId == 0);
-		return getBoundingShape();
+		ANKI_ASSERT(subMeshId < meshProtected.subMeshes.size());
+		return meshProtected.subMeshes[subMeshId].obb;
 	}
 
-	virtual U32 getSubMeshesCount() const
+	U32 getSubMeshesCount() const
 	{
-		return 1;
+		return meshProtected.subMeshes.size();
 	}
 
 	/// Helper function for correct loading
 	Bool isCompatible(const MeshBase& other) const;
+
+protected:
+	/// Per sub mesh data
+	struct SubMesh
+	{
+		U32 indicesCount;
+		U32 indicesOffset;
+		Obb obb;
+	};
+
+	struct
+	{
+		Vector<SubMesh> subMeshes;
+		U32 indicesCount;
+		U32 vertsCount;
+		Obb obb;
+		U8 texChannelsCount;
+		Bool8 weights;
+	} meshProtected;
 };
 
 /// Mesh Resource. It contains the geometry packed in VBOs
@@ -94,31 +130,6 @@ public:
 
 	/// @name MeshBase implementers
 	/// @{
-	U32 getVerticesCount() const
-	{
-		return vertsCount;
-	}
-
-	U32 getIndicesCount() const
-	{
-		return indicesCount;
-	}
-
-	U32 getTextureChannelsCount() const
-	{
-		return texChannelsCount;
-	}
-
-	Bool hasWeights() const
-	{
-		return weights;
-	}
-
-	const Obb& getBoundingShape() const
-	{
-		return visibilityShape;
-	}
-
 	void getVboInfo(
 		const VertexAttribute attrib, const Vbo*& vbo,
 		U32& size, GLenum& type, U32& stride, U32& offset) const;
@@ -128,12 +139,6 @@ public:
 	void load(const char* filename);
 
 protected:
-	U32 vertsCount;
-	U32 indicesCount; ///< Indices count per level
-	U32 texChannelsCount;
-	Bool8 weights;
-	Obb visibilityShape;
-
 	Vbo vbo;
 	Vbo indicesVbo;
 
@@ -165,39 +170,8 @@ public:
 	~BucketMesh()
 	{}
 
-	/// @name MeshBase implementers
-	/// @{
-	U32 getIndicesCountSub(U32 subMeshId, U32& offset) const
-	{
-		ANKI_ASSERT(subMeshId < subMeshes.size());
-		offset = subMeshes[subMeshId].indicesOffset;
-		return subMeshes[subMeshId].indicesCount;
-	}
-
-	const Obb& getBoundingShapeSub(U32 subMeshId) const
-	{
-		ANKI_ASSERT(subMeshId < subMeshes.size());
-		return subMeshes[subMeshId].visibilityShape;
-	}
-
-	U32 getSubMeshesCount() const
-	{
-		return subMeshes.size();
-	}
-	/// @}
-
 	/// Load from a .mmesh file
 	void load(const char* filename);
-
-private:
-	struct SubMeshData
-	{
-		U32 indicesCount;
-		U32 indicesOffset; ///< In bytes
-		Obb visibilityShape;
-	};
-
-	Vector<SubMeshData> subMeshes;
 };
 
 } // end namespace anki

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

@@ -24,10 +24,22 @@ public:
 	virtual ~ModelPatchBase()
 	{}
 
-	virtual const Material& getMaterial() const = 0;
+	const Material& getMaterial() const
+	{
+		ANKI_ASSERT(modelPatchProtected.mtl);
+		return *modelPatchProtected.mtl;
+	}
 
-	virtual const MeshBase& getMeshBase(const PassLevelKey& key) const = 0;
-	virtual U32 getMeshesCount() const = 0;
+	const MeshBase& getMeshBase(const PassLevelKey& key) const
+	{
+		ANKI_ASSERT(key.level < modelPatchProtected.meshes.size());
+		return *modelPatchProtected.meshes[key.level];
+	}
+
+	U32 getMeshesCount() const
+	{
+		return modelPatchProtected.meshes.size();
+	}
 
 	const Obb& getBoundingShape() const
 	{
@@ -57,8 +69,13 @@ public:
 		U32* indicesCountArray, U32* indicesOffsetArray, U32& primcount) const;
 
 protected:
-	/// Array [lod][pass]
-	VaosContainer vaos;
+	struct
+	{
+		/// Array [lod][pass]
+		VaosContainer vaos;
+		Material* mtl = nullptr;
+		Vector<MeshBase*> meshes;
+	} modelPatchProtected;
 
 	/// Create VAOs using a material and a mesh. It writes a VaosContainer and
 	/// a hash map
@@ -88,16 +105,21 @@ public:
 		// Load
 		ANKI_ASSERT(meshesCount > 0);
 		meshes.resize(meshesCount);
+		modelPatchProtected.meshes.resize(meshesCount);
+
 		for(U32 i = 0; i < meshesCount; i++)
 		{
 			meshes[i].load(meshFNames[i]);
+			modelPatchProtected.meshes[i] = meshes[i].get();
 
 			if(i > 0 && !meshes[i]->isCompatible(*meshes[i - 1]))
 			{
 				throw ANKI_EXCEPTION("Meshes not compatible");
 			}
 		}
+
 		mtl.load(mtlFName);
+		modelPatchProtected.mtl = mtl.get();
 
 		/// Create VAOs
 		create();
@@ -106,28 +128,6 @@ public:
 	~ModelPatch()
 	{}
 
-	/// @name Accessors
-	/// @{
-
-	/// Implements ModelPatchBase::getMeshBase
-	const MeshBase& getMeshBase(const PassLevelKey& key) const
-	{
-		return *meshes[key.level];
-	}
-
-	/// Implements ModelPatchBase::getMeshesCount
-	U32 getMeshesCount() const
-	{
-		return meshes.size();
-	}
-
-	/// Implements ModelPatchBase::getMaterial
-	const Material& getMaterial() const
-	{
-		return *mtl;
-	}
-	/// @}
-
 private:
 	Vector<MeshResourcePointerType> meshes; ///< The geometries
 	MaterialResourcePointer mtl; ///< Material

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

@@ -56,24 +56,6 @@ public:
 	/// @name SceneNode virtuals
 	/// @{
 
-	/// Override SceneNode::getMovable()
-	Movable* getMovable()
-	{
-		return this;
-	}
-
-	/// Override SceneNode::getSpatial()
-	Spatial* getSpatial()
-	{
-		return this;
-	}
-
-	/// Override SceneNode::getFrustumable()
-	Frustumable* getFrustumable()
-	{
-		return this;
-	}
-
 	/// Override SceneNode::frameUpdate
 	void frameUpdate(F32 prevUpdateTime, F32 crntTime, int frame)
 	{

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

@@ -7,10 +7,32 @@
 
 namespace anki {
 
+/// @addtogroup Scene
+/// @{
+
+/// Scene configuration constants. The enum contains absolute values and other
+/// constants that help to optimize allocations
+struct SceneConfig
+{
+	enum 
+	{
+		SCENE_NODES_AVERAGE_COUNT = 1024,
+		SCENE_ALLOCATOR_SIZE = 0x100000, // 1MB
+		SCENE_FRAME_ALLOCATOR_SIZE = 0x80000, // 512K
+
+		/// Used to optimize the initial vectors of VisibilityTestResults
+		FRUSTUMABLE_AVERAGE_VISIBLE_SCENE_NODES_COUNT = 10
+	};
+};
+
 /// The type of the scene's allocator
 template<typename T>
 using SceneAllocator = StackAllocator<T, false>;
 
+/// The type of the scene's frame allocator
+template<typename T>
+using SceneFrameAllocator = StackAllocator<T, false>;
+
 /// Scene string
 typedef std::basic_string<char, std::char_traits<char>,
 	SceneAllocator<char>> SceneString;
@@ -21,7 +43,9 @@ using SceneVector = Vector<T, SceneAllocator<T>>;
 
 /// The same as SceneVector. Different name to show the difference
 template<typename T>
-using SceneFrameVector = Vector<T, SceneAllocator<T>>;
+using SceneFrameVector = Vector<T, SceneFrameAllocator<T>>;
+
+/// @}
 
 } // end namespace anki
 

+ 0 - 24
include/anki/scene/Light.h

@@ -95,20 +95,6 @@ public:
 
 	/// @name SceneNode virtuals
 	/// @{
-	Movable* getMovable()
-	{
-		return this;
-	}
-
-	Spatial* getSpatial()
-	{
-		return this;
-	}
-
-	Light* getLight()
-	{
-		return this;
-	}
 
 	/// Override SceneNode::frameUpdate
 	void frameUpdate(F32 prevUpdateTime, F32 crntTime, int frame)
@@ -234,16 +220,6 @@ public:
 	}
 	/// @}
 
-	/// @name SceneNode virtuals
-	/// @{
-
-	/// Override SceneNode::getFrustumable()
-	Frustumable* getFrustumable()
-	{
-		return (getShadowEnabled()) ? this : nullptr;
-	}
-	/// @}
-
 	/// @name Movable virtuals
 	/// @{
 

+ 0 - 24
include/anki/scene/ModelNode.h

@@ -29,24 +29,6 @@ public:
 	/// @name SceneNode virtuals
 	/// @{
 
-	/// Override SceneNode::getMovable()
-	Movable* getMovable()
-	{
-		return this;
-	}
-
-	/// Override SceneNode::getSpatial()
-	Spatial* getSpatial()
-	{
-		return this;
-	}
-
-	/// Override SceneNode::getRenderable
-	Renderable* getRenderable()
-	{
-		return this;
-	}
-
 	/// Override SceneNode::frameUpdate
 	void frameUpdate(F32 prevUpdateTime, F32 crntTime, I frame)
 	{
@@ -121,12 +103,6 @@ public:
 	/// @name SceneNode virtuals
 	/// @{
 
-	/// Override SceneNode::getMovable()
-	Movable* getMovable()
-	{
-		return this;
-	}
-
 	/// Override SceneNode::frameUpdate
 	void frameUpdate(float prevUpdateTime, float crntTime, int frame)
 	{

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

@@ -63,16 +63,6 @@ public:
 	}
 	/// @}
 
-	/// @name SceneNode virtuals
-	/// @{
-
-	/// Override SceneNode::getMovable()
-	Movable* getMovable()
-	{
-		return this;
-	}
-	/// @}
-
 	Bool isDead() const
 	{
 		return timeOfDeath < 0.0;
@@ -143,16 +133,6 @@ public:
 
 	~Particle();
 
-	/// @name SceneNode virtuals
-	/// @{
-
-	/// Override SceneNode::getRigidBody()
-	RigidBody* getRigidBody()
-	{
-		return this;
-	}
-	/// @}
-
 	void kill()
 	{
 		ParticleBase::kill();
@@ -184,24 +164,6 @@ public:
 	/// @name SceneNode virtuals
 	/// @{
 
-	/// Override SceneNode::getMovable()
-	Movable* getMovable()
-	{
-		return this;
-	}
-
-	/// Override SceneNode::getSpatial()
-	Spatial* getSpatial()
-	{
-		return this;
-	}
-
-	/// Override SceneNode::getRenderable()
-	Renderable* getRenderable()
-	{
-		return this;
-	}
-
 	/// Override SceneNode::frameUpdate()
 	void frameUpdate(F32 prevUpdateTime, F32 crntTime, I frame);
 	/// @}

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

@@ -31,12 +31,10 @@ public:
 		typedef SceneVector<T*> Container;
 		typedef typename Container::iterator Iterator;
 		typedef typename Container::const_iterator ConstIterator;
+		// XXX Change the map with map with allocator
 		typedef typename ConstCharPtrHashMap<T*>::Type NameToItemMap;
 	};
 
-	/// The size of the internal allocator. 1MB
-	const PtrSize ALLOCATOR_SIZE = 0x100000;
-
 	/// @name Constructors/Destructor
 	/// @{
 	Scene();

+ 47 - 12
include/anki/scene/SceneNode.h

@@ -57,34 +57,58 @@ public:
 
 	/// @name Accessors of components
 	/// @{
-	virtual Movable* getMovable()
+	Movable* getMovable()
 	{
-		return nullptr;
+		return sceneNodeProtected.movable;
+	}
+	const Movable* getMovable() const
+	{
+		return sceneNodeProtected.movable;
 	}
 
-	virtual Renderable* getRenderable()
+	Renderable* getRenderable()
+	{
+		return sceneNodeProtected.renderable;
+	}
+	const Renderable* getRenderable() const
 	{
-		return nullptr;
+		return sceneNodeProtected.renderable;
 	}
 
-	virtual Frustumable* getFrustumable()
+	Frustumable* getFrustumable()
 	{
-		return nullptr;
+		return sceneNodeProtected.frustumable;
+	}
+	const Frustumable* getFrustumable() const
+	{
+		return sceneNodeProtected.frustumable;
 	}
 
-	virtual Spatial* getSpatial()
+	Spatial* getSpatial()
+	{
+		return sceneNodeProtected.spatial;
+	}
+	const Spatial* getSpatial() const
 	{
-		return nullptr;
+		return sceneNodeProtected.spatial;
 	}
 
-	virtual Light* getLight()
+	Light* getLight()
+	{
+		return sceneNodeProtected.light;
+	}
+	const Light* getLight() const 
 	{
-		return nullptr;
+		return sceneNodeProtected.light;
 	}
 
-	virtual RigidBody* getRigidBody()
+	RigidBody* getRigidBody()
 	{
-		return nullptr;
+		return sceneNodeProtected.rigidBody;
+	}
+	const RigidBody* getRigidBody() const
+	{
+		return sceneNodeProtected.rigidBody;
 	}
 	/// @}
 
@@ -103,6 +127,17 @@ public:
 	/// Return the last frame the node was updated. It checks all components
 	U32 getLastUpdateFrame();
 
+protected:
+	struct
+	{
+		Movable* movable = nullptr;
+		Renderable* renderable = nullptr;
+		Frustumable* frustumable = nullptr;
+		Spatial* spatial = nullptr;
+		Light* light = nullptr;
+		RigidBody* rigidBody = nullptr;
+	} sceneNodeProtected;
+
 private:
 	SceneString name; ///< A unique name
 	Scene* scene = nullptr; ///< Keep it here for unregistering

+ 0 - 28
include/anki/scene/SkinNode.h

@@ -154,28 +154,6 @@ public:
 	}
 	/// @}
 
-	/// @name SceneNode virtuals
-	/// @{
-
-	/// Override SceneNode::getMovable()
-	Movable* getMovable()
-	{
-		return this;
-	}
-
-	/// Override SceneNode::getSpatial()
-	Spatial* getSpatial()
-	{
-		return this;
-	}
-
-	/// Override SceneNode::getRenderable
-	Renderable* getRenderable()
-	{
-		return this;
-	}
-	/// @}
-
 	/// @name Renderable virtuals
 	/// @{
 
@@ -218,12 +196,6 @@ public:
 	/// @name SceneNode virtuals
 	/// @{
 
-	/// Override SceneNode::getMovable()
-	Movable* getMovable()
-	{
-		return this;
-	}
-
 	/// Update the animation stuff
 	void frameUpdate(F32 prevUpdateTime, F32 crntTime, int frame);
 	/// @}

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

@@ -21,16 +21,6 @@ public:
 		const char* name, Scene* scene); // Scene
 	/// @}
 
-	/// @name SceneNode virtuals
-	/// @{
-
-	/// Override SceneNode::getSpatial()
-	Spatial* getSpatial()
-	{
-		return this;
-	}
-	/// @}
-
 public:
 	Obb obb;
 };
@@ -46,22 +36,6 @@ public:
 		const char* name, Scene* scene); // Scene
 	/// @}
 
-	/// @name SceneNode virtuals
-	/// @{
-
-	/// Override SceneNode::getSpatial()
-	Spatial* getSpatial()
-	{
-		return this;
-	}
-
-	/// Override SceneNode::getRenderable()
-	Renderable* getRenderable()
-	{
-		return this;
-	}
-	/// @}
-
 	/// @name Renderable virtuals
 	/// @{
 

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

@@ -37,15 +37,14 @@ struct VisibilityTestResults
 {
 	typedef SceneFrameVector<SceneNode*> Container;
 
-	/// Used to optimize the initial vector size a bit
-	static const U32 AVERAGE_NUMBER_OF_VISIBLE_SCENE_NODES = 10;
-
 	Container renderables;
 	Container lights;
 
 	VisibilityTestResults(const SceneAllocator<U8>& frameAlloc,
-		U32 renderablesReservedSize = AVERAGE_NUMBER_OF_VISIBLE_SCENE_NODES,
-		U32 lightsReservedSize = AVERAGE_NUMBER_OF_VISIBLE_SCENE_NODES)
+		U32 renderablesReservedSize = 
+		SceneConfig::FRUSTUMABLE_AVERAGE_VISIBLE_SCENE_NODES_COUNT,
+		U32 lightsReservedSize =
+		SceneConfig::FRUSTUMABLE_AVERAGE_VISIBLE_SCENE_NODES_COUNT)
 		: renderables(frameAlloc), lights(frameAlloc)
 	{
 		renderables.reserve(renderablesReservedSize);

+ 48 - 45
src/resource/Mesh.cpp

@@ -29,20 +29,20 @@ void Mesh::load(const char* filename)
 	{
 		MeshLoader loader(filename);
 
-		// Set the non-VBO members
-		vertsCount = loader.getPositions().size();
-		ANKI_ASSERT(vertsCount > 0);
+		meshProtected.indicesCount = loader.getIndices().size();
+		meshProtected.obb.set(loader.getPositions());
+		ANKI_ASSERT(meshProtected.indicesCount > 0);
+		ANKI_ASSERT(meshProtected.indicesCount % 3 == 0 
+			&& "Expecting triangles");
 
-		indicesCount = loader.getIndices().size();
-		ANKI_ASSERT(indicesCount > 0);
-		ANKI_ASSERT(indicesCount % 3 == 0 && "Expecting triangles");
+		// Set the non-VBO members
+		meshProtected.vertsCount = loader.getPositions().size();
+		ANKI_ASSERT(meshProtected.vertsCount > 0);
 
-		weights = loader.getWeights().size() > 1;
-		texChannelsCount = loader.getTextureChannelsCount();
+		meshProtected.texChannelsCount = loader.getTextureChannelsCount();
+		meshProtected.weights = loader.getWeights().size() > 1;
 
 		createVbos(loader);
-
-		visibilityShape.set(loader.getPositions());
 	}
 	catch(std::exception& e)
 	{
@@ -54,8 +54,8 @@ void Mesh::load(const char* filename)
 U32 Mesh::calcVertexSize() const
 {
 	U32 a = sizeof(Vec3) + sizeof(Vec3) + sizeof(Vec4) 
-		+ texChannelsCount * sizeof(Vec2);
-	if(weights)
+		+ meshProtected.texChannelsCount * sizeof(Vec2);
+	if(meshProtected.weights)
 	{
 		a += sizeof(MeshLoader::VertexWeight);
 	}
@@ -65,19 +65,19 @@ U32 Mesh::calcVertexSize() const
 //==============================================================================
 void Mesh::createVbos(const MeshLoader& loader)
 {
-	ANKI_ASSERT(vertsCount == loader.getPositions().size()
-		&& vertsCount == loader.getNormals().size()
-		&& vertsCount == loader.getTangents().size());
+	ANKI_ASSERT(meshProtected.vertsCount == loader.getPositions().size()
+		&& meshProtected.vertsCount == loader.getNormals().size()
+		&& meshProtected.vertsCount == loader.getTangents().size());
 
 	// Calculate VBO size
 	U32 vertexsize = calcVertexSize();
-	U32 vbosize = vertexsize * vertsCount;
+	U32 vbosize = vertexsize * meshProtected.vertsCount;
 
 	// Create a temp buffer and populate it
 	Vector<U8> buff(vbosize, 0);
 
 	U8* ptr = &buff[0];
-	for(U i = 0; i < vertsCount; i++)
+	for(U i = 0; i < meshProtected.vertsCount; i++)
 	{
 		ANKI_ASSERT(ptr + vertexsize <= &buff[0] + vbosize);
 
@@ -90,13 +90,13 @@ void Mesh::createVbos(const MeshLoader& loader)
 		memcpy(ptr, &loader.getTangents()[i], sizeof(Vec4));
 		ptr += sizeof(Vec4);
 
-		for(U j = 0; j < texChannelsCount; j++)
+		for(U j = 0; j < meshProtected.texChannelsCount; j++)
 		{
 			memcpy(ptr, &loader.getTextureCoordinates(j)[i], sizeof(Vec2));
 			ptr += sizeof(Vec2);
 		}
 
-		if(weights)
+		if(meshProtected.weights)
 		{
 			memcpy(ptr, &loader.getWeights()[i], 
 				sizeof(MeshLoader::VertexWeight));
@@ -152,7 +152,7 @@ void Mesh::getVboInfo(const VertexAttribute attrib, const Vbo*& v, U32& size,
 		offset = sizeof(Vec3) * 2;
 		break;
 	case VA_TEXTURE_COORDS:
-		if(texChannelsCount > 0)
+		if(meshProtected.texChannelsCount > 0)
 		{
 			v = &vbo;
 			size = 2;
@@ -161,7 +161,7 @@ void Mesh::getVboInfo(const VertexAttribute attrib, const Vbo*& v, U32& size,
 		}
 		break;
 	case VA_TEXTURE_COORDS_1:
-		if(texChannelsCount > 1)
+		if(meshProtected.texChannelsCount > 1)
 		{
 			v = &vbo;
 			size = 2;
@@ -170,33 +170,33 @@ void Mesh::getVboInfo(const VertexAttribute attrib, const Vbo*& v, U32& size,
 		}
 		break;
 	case VA_BONE_COUNT:
-		if(weights)
+		if(meshProtected.weights)
 		{
 			v = &vbo;
 			size = 1;
 			type = GL_UNSIGNED_INT;
 			offset = sizeof(Vec3) * 2 + sizeof(Vec4) 
-				+ texChannelsCount * sizeof(Vec2);
+				+ meshProtected.texChannelsCount * sizeof(Vec2);
 		}
 		break;
 	case VA_BONE_IDS:
-		if(weights)
+		if(meshProtected.weights)
 		{
 			v = &vbo;
 			size = 4;
 			type = GL_UNSIGNED_INT;
 			offset = sizeof(Vec3) * 2 + sizeof(Vec4) 
-				+ texChannelsCount * sizeof(Vec2) + sizeof(U32);
+				+ meshProtected.texChannelsCount * sizeof(Vec2) + sizeof(U32);
 		}
 		break;
 	case VA_BONE_WEIGHTS:
-		if(weights)
+		if(meshProtected.weights)
 		{
 			v = &vbo;
 			size = 4;
 			type = GL_FLOAT;
 			offset = sizeof(Vec3) * 2 + sizeof(Vec4) 
-				+ texChannelsCount * sizeof(Vec2) + sizeof(U32) 
+				+ meshProtected.texChannelsCount * sizeof(Vec2) + sizeof(U32) 
 				+ sizeof(U32) * 4;
 		}
 	case VA_INDICES:
@@ -224,12 +224,12 @@ void BucketMesh::load(const char* filename)
 		XmlElement meshesEl = rootEl.getChildElement("meshes");
 		XmlElement meshEl = meshesEl.getChildElement("mesh");
 
-		vertsCount = 0;
-		indicesCount = 0;
-		U i = 0;
+		meshProtected.vertsCount = 0;
+		meshProtected.subMeshes.reserve(4); // XXX
+		meshProtected.indicesCount = 0;
 
 		MeshLoader fullLoader;
-
+		U i = 0;
 		do
 		{
 			std::string subMeshFilename = meshEl.getText();
@@ -251,13 +251,14 @@ void BucketMesh::load(const char* filename)
 				loader = &subLoader;
 
 				// Sanity checks
-				if(weights != (loader->getWeights().size() > 1))
+				if(meshProtected.weights != (loader->getWeights().size() > 1))
 				{
 					throw ANKI_EXCEPTION("All sub meshes should have or not "
 						"have vertex weights");
 				}
 
-				if(texChannelsCount != loader->getTextureChannelsCount())
+				if(meshProtected.texChannelsCount 
+					!= loader->getTextureChannelsCount())
 				{
 					throw ANKI_EXCEPTION("All sub meshes should have the "
 						"same number of texture channels");
@@ -268,18 +269,19 @@ void BucketMesh::load(const char* filename)
 				fullLoader.appendNormals(subLoader.getNormals());
 				fullLoader.appendTangents(subLoader.getTangents());
 
-				for(U j = 0; j < texChannelsCount; j++)
+				for(U j = 0; j < meshProtected.texChannelsCount; j++)
 				{
 					fullLoader.appendTextureCoordinates(
 						subLoader.getTextureCoordinates(j), j);
 				}
 
-				if(weights)
+				if(meshProtected.weights)
 				{
 					fullLoader.appendWeights(subLoader.getWeights());
 				}
 
-				fullLoader.appendIndices(loader->getIndices(), vertsCount);
+				fullLoader.appendIndices(loader->getIndices(), 
+					meshProtected.vertsCount);
 			}
 			else
 			{
@@ -288,22 +290,23 @@ void BucketMesh::load(const char* filename)
 				loader = &fullLoader;
 
 				// Set properties
-				weights = loader->getWeights().size() > 1;
-				texChannelsCount = loader->getTextureChannelsCount();
+				meshProtected.weights = loader->getWeights().size() > 1;
+				meshProtected.texChannelsCount = 
+					loader->getTextureChannelsCount();
 			}
 
 			// Push back the new submesh
-			SubMeshData submesh;
+			SubMesh submesh;
 
 			submesh.indicesCount = loader->getIndices().size();
-			submesh.indicesOffset = indicesCount * sizeof(U16);
-			submesh.visibilityShape.set(loader->getPositions());
+			submesh.indicesOffset = meshProtected.indicesCount * sizeof(U16);
+			submesh.obb.set(loader->getPositions());
 
-			subMeshes.push_back(submesh);
+			meshProtected.subMeshes.push_back(submesh);
 
 			// Set the global numbers
-			vertsCount += loader->getPositions().size();
-			indicesCount += loader->getIndices().size();
+			meshProtected.vertsCount += loader->getPositions().size();
+			meshProtected.indicesCount += loader->getIndices().size();
 
 			// Move to next
 			meshEl = meshEl.getNextSiblingElement("mesh");
@@ -312,7 +315,7 @@ void BucketMesh::load(const char* filename)
 
 		// Create the bucket mesh
 		createVbos(fullLoader);
-		visibilityShape.set(fullLoader.getPositions());
+		meshProtected.obb.set(fullLoader.getPositions());
 	}
 	catch(std::exception& e)
 	{

+ 6 - 6
src/resource/Model.cpp

@@ -87,8 +87,8 @@ void ModelPatchBase::getRenderingData(const PassLevelKey& key, const Vao*& vao,
 
 	U index = key.pass + std::min((U)key.level, lodsCount - 1) * lodsCount;
 
-	ANKI_ASSERT(index < vaos.size());
-	vao = &vaos[index];
+	ANKI_ASSERT(index < modelPatchProtected.vaos.size());
+	vao = &modelPatchProtected.vaos[index];
 
 	// Mesh and indices
 	PassLevelKey meshKey;
@@ -121,8 +121,8 @@ void ModelPatchBase::getRenderingDataSub(const PassLevelKey& key,
 
 	U index = key.pass + std::min((U)key.level, lodsCount - 1) * lodsCount;
 
-	ANKI_ASSERT(index < vaos.size());
-	vao = &vaos[index];
+	ANKI_ASSERT(index < modelPatchProtected.vaos.size());
+	vao = &modelPatchProtected.vaos[index];
 
 	// Prog
 	PassLevelKey mtlKey;
@@ -159,7 +159,7 @@ void ModelPatchBase::create()
 	U lodsCount = std::max(getMeshesCount(), mtl.getLevelsOfDetail());
 	U passesCount = mtl.getPasses().size();
 
-	vaos.resize(lodsCount * passesCount);
+	modelPatchProtected.vaos.resize(lodsCount * passesCount);
 
 	for(U lod = 0; lod < lodsCount; ++lod)
 	{
@@ -185,7 +185,7 @@ void ModelPatchBase::create()
 			Vao vao;
 			createVao(*prog, *mesh, vao);
 
-			vaos[i] = std::move(vao);
+			modelPatchProtected.vaos[i] = std::move(vao);
 			++i;
 		}
 	}

+ 5 - 1
src/scene/Camera.cpp

@@ -16,7 +16,11 @@ Camera::Camera(CameraType type_,
 		Spatial(frustum),
 		Frustumable(frustum),
 		type(type_)
-{}
+{
+	sceneNodeProtected.movable = this;
+	sceneNodeProtected.spatial = this;
+	sceneNodeProtected.frustumable = this;
+}
 
 //==============================================================================
 Camera::~Camera()

+ 6 - 0
src/scene/Light.cpp

@@ -16,6 +16,10 @@ Light::Light(LightType t, // Light
 		Spatial(cs),
 		type(t)
 {
+	sceneNodeProtected.movable = this;
+	sceneNodeProtected.spatial = this;
+	sceneNodeProtected.light = this;
+
 	addNewProperty(new ReadWritePointerProperty<Vec4>("color", &color));
 
 	addNewProperty(
@@ -51,6 +55,8 @@ SpotLight::SpotLight(const char* name, Scene* scene,
 	: 	Light(LT_SPOT, name, scene, movableFlags, movParent, &frustum),
 		Frustumable(&frustum)
 {
+	sceneNodeProtected.frustumable = this;
+
 	const F32 ang = toRad(45.0);
 	setOuterAngle(ang / 2.0);
 	const F32 dist = 1.0;

+ 6 - 0
src/scene/ModelNode.cpp

@@ -17,6 +17,10 @@ ModelPatchNode::ModelPatchNode(const ModelPatchBase *modelPatch_,
 		Renderable(getSceneAllocator()),
 		Spatial(&obb), modelPatch(modelPatch_)
 {
+	sceneNodeProtected.movable = this;
+	sceneNodeProtected.renderable = this;
+	sceneNodeProtected.spatial = this;
+
 	Renderable::init(*this);
 }
 
@@ -32,6 +36,8 @@ ModelNode::ModelNode(const char* modelFname,
 		Movable(movableFlags, movParent, *this, getSceneAllocator()),
 		patches(getSceneAllocator())
 {
+	sceneNodeProtected.movable = this;
+
 	model.load(modelFname);
 
 	patches.reserve(model->getModelPatches().size());

+ 12 - 3
src/scene/ParticleEmitter.cpp

@@ -47,10 +47,12 @@ ParticleBase::ParticleBase(
 	const char* name, Scene* scene, 
 	// Movable
 	U32 movableFlags, Movable* movParent)
-	: SceneNode(name, scene),
+	:	SceneNode(name, scene),
 		Movable(movableFlags, movParent, *this, getSceneAllocator()),
 		type(type_)
-{}
+{
+	sceneNodeProtected.movable = this;
+}
 
 //==============================================================================
 ParticleBase::~ParticleBase()
@@ -141,7 +143,9 @@ Particle::Particle(
 	PhysWorld* masterContainer, const Initializer& init)
 	: ParticleBase(PT_PHYSICS, name, scene, movableFlags, movParent),
 		RigidBody(masterContainer, init, this)
-{}
+{
+	sceneNodeProtected.rigidBody = this;
+}
 
 //==============================================================================
 Particle::~Particle()
@@ -229,6 +233,11 @@ ParticleEmitter::ParticleEmitter(
 		Renderable(getSceneAllocator()),
 		particles(getSceneAllocator())
 {
+	sceneNodeProtected.spatial = this;
+	sceneNodeProtected.movable = this;
+	sceneNodeProtected.renderable = this;
+	sceneNodeProtected.renderable = this;
+
 	// Load resource
 	particleEmitterResource.load(filename);
 

+ 51 - 2
src/scene/Scene.cpp

@@ -32,17 +32,66 @@ struct UpdateMovablesJob: ThreadJob
 	}
 };
 
+//==============================================================================
+#if 0
+struct UpdateSceneNodesJob: ThreadJob
+{
+	Scene::Types<SceneNode>::Iterator sceneNodesBegin;
+	U32 sceneNodesCount;
+
+	void operator()(U threadId, U threadsCount)
+	{
+		U64 start, end;
+		choseStartEnd(threadId, threadsCount, sceneNodesCount, start, end);
+
+		for(U64 i = start; i < end; i++)
+		{
+			SceneNode* n = *(sceneNodesBegin + i);
+
+			n->frameUpdate(prevUpdateTime, crntTime, Timestamp::getTimestamp());
+
+			// Do some spatial stuff
+			Spatial* sp = n->getSpatial();
+			if(sp)
+			{
+				if(sp->getSpatialTimestamp() == Timestamp::getTimestamp())
+				{
+					sectorGroup.placeSceneNode(n);
+				}
+				sp->disableFlags(Spatial::SF_VISIBLE_ANY);
+			}
+
+			// Do some frustumable stuff
+			Frustumable* fr = n->getFrustumable();
+			if(fr)
+			{
+				fr->setVisibilityTestResults(nullptr);
+			}
+
+			// Do some renderable stuff
+			Renderable* r = n->getRenderable();
+			if(r)
+			{
+				r->resetFrame();
+			}
+		}
+	}
+}
+#endif
+
 //==============================================================================
 // Scene                                                                       =
 //==============================================================================
 
 //==============================================================================
 Scene::Scene()
-	: alloc(ALLOCATOR_SIZE),
-		frameAlloc(ALLOCATOR_SIZE),
+	:	alloc(SceneConfig::SCENE_ALLOCATOR_SIZE),
+		frameAlloc(SceneConfig::SCENE_FRAME_ALLOCATOR_SIZE),
 		nodes(alloc),
 		sectorGroup(this)
 {
+	nodes.reserve(SceneConfig::SCENE_NODES_AVERAGE_COUNT);
+
 	ambientCol = Vec3(0.1, 0.05, 0.05) * 2;
 }
 

+ 7 - 0
src/scene/SkinNode.cpp

@@ -63,6 +63,7 @@ SkinModelPatch::SkinModelPatch(const ModelPatchBase* mpatch_,
 		skinMeshes(alloc),
 		xfbVaos(alloc)
 {
+	// XXX set spatial private
 #if 0
 	// Create the model patch
 	skinMeshes.resize(mpatch->getMeshesCount());
@@ -133,6 +134,10 @@ SkinPatchNode::SkinPatchNode(const ModelPatchBase* modelPatch_,
 		Renderable(getSceneAllocator()),
 		Spatial(spatialCs)
 {
+	sceneNodeProtected.movable = this;
+	sceneNodeProtected.renderable = this;
+	sceneNodeProtected.spatial = this;
+
 	skinModelPatch.reset(new SkinModelPatch(modelPatch_, getSceneAllocator()));
 	Renderable::init(*this);
 }
@@ -153,6 +158,8 @@ SkinNode::SkinNode(const char* skinFname,
 		boneRotations(getSceneAllocator()),
 		boneTranslations(getSceneAllocator())
 {
+	sceneNodeProtected.movable = this;
+
 	skin.load(skinFname);
 
 	uint i = 0;

+ 6 - 1
src/scene/StaticGeometryNode.cpp

@@ -11,7 +11,9 @@ namespace anki {
 StaticGeometrySpatialNode::StaticGeometrySpatialNode(const Obb& obb_,
 	const char* name, Scene* scene)
 	: SceneNode(name, scene), Spatial(&obb), obb(obb_)
-{}
+{
+	sceneNodeProtected.spatial = this;
+}
 
 //==============================================================================
 // StaticGeometryPatchNode                                                     =
@@ -25,6 +27,9 @@ StaticGeometryPatchNode::StaticGeometryPatchNode(
 		Renderable(getSceneAllocator()),
 		modelPatch(modelPatch_)
 {
+	sceneNodeProtected.spatial = this;
+	sceneNodeProtected.renderable = this;
+
 	ANKI_ASSERT(modelPatch);
 	Renderable::init(*this);