Browse Source

Ported MeshData so it both allocates and deallocates memory internally

Marko Pintera 12 years ago
parent
commit
ad0d30efcd

+ 60 - 70
CamelotCore/Include/CmMeshData.h

@@ -58,168 +58,158 @@ namespace CamelotEngine
 		~MeshData();
 
 		/**
-		 * @brief	Provides a convenient way of setting mesh positions. 
+		 * @brief	Allocates a buffer for holding a specified amount of vertex positions, and returns a
+		 * 			pointer the user can use to populate the buffer. If a previous set of data exists 
+		 * 			in this same stream slot, it will be deleted.
 		 *
-		 * @param 	elements			Pointer to pre-allocated array of positions. Any previous position data will be deleted.
 		 * @param	numElements			Number of elements in the elements array.
 		 * @param	streamIdx			(optional) Zero-based index of the stream. Each stream will 
 		 * 								internally be represented as a single vertex buffer.
-		 * 								
-		 * @note MeshData will take ownership of the provided memory, and will delete it upon 
-		 * 		 destruction or when you replace it with other data.
 		 */
-		void setPositions(Vector2* elements, UINT32 numElements, UINT32 streamIdx = 0);
+		Vector2* addPositionsVec2(UINT32 numElements, UINT32 streamIdx = 0);
 
 		/**
-		 * @brief	Provides a convenient way of setting mesh positions. 
+		 * @brief	Allocates a buffer for holding a specified amount of vertex positions, and returns a
+		 * 			pointer the user can use to populate the buffer. If a previous set of data exists 
+		 * 			in this same stream slot, it will be deleted.
 		 *
-		 * @param 	elements			Pointer to pre-allocated array of positions. Any previous position data will be deleted.
 		 * @param	numElements			Number of elements in the elements array.
 		 * @param	streamIdx			(optional) Zero-based index of the stream. Each stream will 
 		 * 								internally be represented as a single vertex buffer.
-		 * 								
-		 * @note MeshData will take ownership of the provided memory, and will delete it upon 
-		 * 		 destruction or when you replace it with other data.
 		 */
-		void setPositions(Vector3* elements, UINT32 numElements, UINT32 streamIdx = 0);
+		Vector3* addPositionsVec3(UINT32 numElements, UINT32 streamIdx = 0);
 
 		/**
-		 * @brief	Provides a convenient way of setting mesh positions. 
+		 * @brief	Allocates a buffer for holding a specified amount of vertex positions, and returns a
+		 * 			pointer the user can use to populate the buffer. If a previous set of data exists 
+		 * 			in this same stream slot, it will be deleted.
 		 *
-		 * @param 	elements			Pointer to pre-allocated array of positions. Any previous position data will be deleted.
 		 * @param	numElements			Number of elements in the elements array.
 		 * @param	streamIdx			(optional) Zero-based index of the stream. Each stream will 
 		 * 								internally be represented as a single vertex buffer.
-		 * 								
-		 * @note MeshData will take ownership of the provided memory, and will delete it upon 
-		 * 		 destruction or when you replace it with other data.
-		 * 		 
 		 */
-		void setPositions(Vector4* elements, UINT32 numElements, UINT32 streamIdx = 0);
+		Vector4* addPositionsVec4(UINT32 numElements, UINT32 streamIdx = 0);
 
 		/**
-		 * @brief	Provides a convenient way of setting mesh normals.
+		 * @brief	Allocates a buffer for holding a specified amount of vertex normals, and returns a
+		 * 			pointer the user can use to populate the buffer. If a previous set of data exists 
+		 * 			in this same stream slot, it will be deleted.
 		 *
-		 * @param 	elements			Pointer to pre-allocated array of normals. Any previous normal data will be deleted.
 		 * @param	numElements			Number of elements in the elements array.
 		 * @param	streamIdx			(optional) Zero-based index of the stream. Each stream will 
 		 * 								internally be represented as a single vertex buffer.
-		 * 								
-		 * @note MeshData will take ownership of the provided memory, and will delete it upon 
-		 * 		 destruction or when you replace it with other data.
 		 */
-		void setNormals(Vector3* elements, UINT32 numElements, UINT32 streamIdx = 0);
+		Vector3* addNormals(UINT32 numElements, UINT32 streamIdx = 0);
 
 		/**
-		 * @brief	Provides a convenient way of setting mesh tangents.
+		 * @brief	Allocates a buffer for holding a specified amount of vertex tangents, and returns a
+		 * 			pointer the user can use to populate the buffer. If a previous set of data exists 
+		 * 			in this same stream slot, it will be deleted.
 		 *
-		 * @param 	elements			Pointer to pre-allocated array of tangents. Any previous tangent data will be deleted.
 		 * @param	numElements			Number of elements in the elements array.
 		 * @param	streamIdx			(optional) Zero-based index of the stream. Each stream will 
 		 * 								internally be represented as a single vertex buffer.
-		 * 								
-		 * @note MeshData will take ownership of the provided memory, and will delete it upon 
-		 * 		 destruction or when you replace it with other data.
 		 */
-		void setTangents(Vector3* elements, UINT32 numElements, UINT32 streamIdx = 0);
+		Vector3* addTangentsVec3(UINT32 numElements, UINT32 streamIdx = 0);
 
 		/**
-		 * @brief	Provides a convenient way of setting mesh tangents.
+		 * @brief	Allocates a buffer for holding a specified amount of vertex tangents, and returns a
+		 * 			pointer the user can use to populate the buffer. If a previous set of data exists 
+		 * 			in this same stream slot, it will be deleted.
 		 *
-		 * @param 	elements			Pointer to pre-allocated array of tangents. Any previous tangent data will be deleted.
 		 * @param	numElements			Number of elements in the elements array.
 		 * @param	streamIdx			(optional) Zero-based index of the stream. Each stream will 
 		 * 								internally be represented as a single vertex buffer.
-		 * 								
-		 * @note MeshData will take ownership of the provided memory, and will delete it upon 
-		 * 		 destruction or when you replace it with other data.
 		 */
-		void setTangents(Vector4* elements, UINT32 numElements, UINT32 streamIdx = 0);
+		Vector4* addTangentsVec4(UINT32 numElements, UINT32 streamIdx = 0);
 
 		/**
-		 * @brief	Provides a convenient way of setting mesh bitangents. 
+		 * @brief	Allocates a buffer for holding a specified amount of vertex bitangents, and returns a
+		 * 			pointer the user can use to populate the buffer. If a previous set of data exists 
+		 * 			in this same stream slot, it will be deleted.
 		 *
-		 * @param 	elements			Pointer to pre-allocated array of bitangents. Any previous bitangent data will be deleted.
 		 * @param	numElements			Number of elements in the elements array.
 		 * @param	streamIdx			(optional) Zero-based index of the stream. Each stream will 
 		 * 								internally be represented as a single vertex buffer.
-		 * 								
-		 * @note MeshData will take ownership of the provided memory, and will delete it upon 
-		 * 		 destruction or when you replace it with other data.
 		 */
-		void setBitangents(Vector3* elements, UINT32 numElements, UINT32 streamIdx = 0);
+		Vector3* addBitangents(UINT32 numElements, UINT32 streamIdx = 0);
 
 		/**
-		 * @brief	Provides a convenient way of setting mesh texture coordinates.
+		 * @brief	Allocates a buffer for holding a specified amount of vertex texture coordinates, 
+		 * 			and returns a pointer the user can use to populate the buffer. If a previous set 
+		 * 			of data exists in this same stream slot, it will be deleted.
 		 *
-		 * @param 	elements			Pointer to pre-allocated array of texture coordinates. Any previous uv0 data will be deleted.
 		 * @param	numElements			Number of elements in the elements array.
 		 * @param	streamIdx			(optional) Zero-based index of the stream. Each stream will 
 		 * 								internally be represented as a single vertex buffer.
-		 * 								
-		 * @note MeshData will take ownership of the provided memory, and will delete it upon 
-		 * 		 destruction or when you replace it with other data.
 		 */
-		void setUV0(Vector2* elements, UINT32 numElements, UINT32 streamIdx = 0);
+		Vector2* addUV0(UINT32 numElements, UINT32 streamIdx = 0);
 
 		/**
-		 * @brief	Provides a convenient way of setting mesh texture coordinates. 
+		 * @brief	Allocates a buffer for holding a specified amount of vertex texture coordinates, 
+		 * 			and returns a pointer the user can use to populate the buffer. If a previous set 
+		 * 			of data exists in this same stream slot, it will be deleted.
 		 *
-		 * @param 	elements			Pointer to pre-allocated array of texture coordinates. Any previous uv1 data will be deleted.
 		 * @param	numElements			Number of elements in the elements array.
 		 * @param	streamIdx			(optional) Zero-based index of the stream. Each stream will 
 		 * 								internally be represented as a single vertex buffer.
-		 * 								
-		 * @note MeshData will take ownership of the provided memory, and will delete it upon 
-		 * 		 destruction or when you replace it with other data.
 		 */
-		void setUV1(Vector2* elements, UINT32 numElements, UINT32 streamIdx = 0);
+		Vector2* addUV1(UINT32 numElements, UINT32 streamIdx = 0);
 
 		/**
-		 * @brief	Provides a convenient way of setting mesh colors. 
+		 * @brief	Allocates a buffer for holding a specified amount of vertex colors, and returns a
+		 * 			pointer the user can use to populate the buffer. If a previous set of data exists 
+		 * 			in this same stream slot, it will be deleted.
 		 *
-		 * @param 	elements			Pointer to pre-allocated array of colors. Any previous color data will be deleted.
 		 * @param	numElements			Number of elements in the elements array.
 		 * @param	streamIdx			(optional) Zero-based index of the stream. Each stream will 
 		 * 								internally be represented as a single vertex buffer.
-		 * 								
-		 * @note MeshData will take ownership of the provided memory, and will delete it upon 
-		 * 		 destruction or when you replace it with other data.
 		 */
-		void setColors(Color* elements, UINT32 numElements, UINT32 streamIdx = 0);
+		Color* addColorsFloat(UINT32 numElements, UINT32 streamIdx = 0);
 
 		/**
-		 * @brief	Adds (or replaces) a new set of vertex element data. Anything that was previously
+		 * @brief	Allocates a buffer for holding a specified amount of vertex colors, and returns a
+		 * 			pointer the user can use to populate the buffer. If a previous set of data exists 
+		 * 			in this same stream slot, it will be deleted.
+		 *
+		 * @param	numElements			Number of elements in the elements array.
+		 * @param	streamIdx			(optional) Zero-based index of the stream. Each stream will 
+		 * 								internally be represented as a single vertex buffer.
+		 */
+		UINT32* addColorsDWORD(UINT32 numElements, UINT32 streamIdx = 0);
+
+		/**
+		* @brief	Allocates a buffer for holding a specified amount of vertex data, and returns a
+		* 			pointer the user can use to populate the buffer. Anything that was previously
 		 * 			present at the same data slot is removed.
 		 *
 		 * @param	type	   	Type of the vertex element. Determines size.
 		 * @param	semantic   	Semantic that allows the engine to connect the data to a shader input slot.
-		 * @param	elements   	Allocated array of elements. Total size should be size of element type * number of elements. Any previous data at the same slot will be deleted.
 		 * @param	numElements	Number of elements in the array.
 		 * @param	semanticIdx	(optional) If there are multiple semantics with the same name, use different index to differentiate between them.
 		 * @param	streamIdx  	(optional) Zero-based index of the stream. Each stream will internally be represented as a single vertex buffer.
 		 */
-		void setVertexElementData(VertexElementType type, VertexElementSemantic semantic, UINT8* elements, UINT32 numElements, UINT32 semanticIdx = 0, UINT32 streamIdx = 0);
+		UINT8* addVertexElementData(VertexElementType type, VertexElementSemantic semantic, UINT32 numElements, UINT32 semanticIdx = 0, UINT32 streamIdx = 0);
 
 		/**
-		 * @brief	Sets a list of indices for the specified sub mesh. Any indexes previously
+		* @brief	Allocates buffer for the indices for the specified sub mesh, and returns a
+		* 			pointer the user can use to populate the buffer. Any indexes previously
 		 * 			set for the sub mesh are deleted.
 		 *
-		 * @param 	indices	If non-null, the indices.
 		 * @param	numIndices	   	Number of indices.
 		 * @param	subMesh		   	(optional) the sub mesh.
 		 */
-		void setIndices(UINT32* indices, UINT32 numIndices, UINT32 subMesh = 0);
+		UINT32* addIndices32(UINT32 numIndices, UINT32 subMesh = 0);
 
 		/**
-		 * @brief	Sets a list of indices for the specified sub mesh. Any indexes previously
+		* @brief	Allocates buffer for the indices for the specified sub mesh, and returns a
+		* 			pointer the user can use to populate the buffer. Any indexes previously
 		 * 			set for the sub mesh are deleted.
 		 *
-		 * @param 	indices	If non-null, the indices.
 		 * @param	numIndices	   	Number of indices.
 		 * @param	subMesh		   	(optional) the sub mesh.
 		 */
-		void setIndices(UINT16* indices, UINT32 numIndices, UINT32 subMesh = 0);
+		UINT16* addIndices16(UINT32 numIndices, UINT32 subMesh = 0);
 
 		/**
 		 * @brief	Query if we have vertex data for the specified semantic.

+ 3 - 1
CamelotCore/Include/CmMeshDataRTTI.h

@@ -103,7 +103,9 @@ namespace CamelotEngine
 
 		void setVertexElementData(MeshData* obj, UINT32 arrayIdx, MeshData::VertexElementData& value)
 		{
-			obj->setVertexElementData(value.element.getType(), value.element.getSemantic(), value.data, value.elementCount, value.element.getIndex(), value.element.getSource());
+			obj->clearIfItExists(value.element.getType(), value.element.getSemantic(), value.element.getIndex(), value.element.getSource());
+
+			obj->mVertexData[value.element.getSource()].push_back(value);
 		}
 
 		UINT32 getNumVertexElementData(MeshData* obj)

+ 6 - 10
CamelotCore/Source/CmGUIWidget.cpp

@@ -65,6 +65,7 @@ namespace CamelotEngine
 			Vector2* uvs;
 			UINT32* indices;
 			HMaterial material;
+			std::shared_ptr<MeshData> meshData;
 		};
 
 		std::unordered_map<UINT64, TempMeshData> meshDataPerRenderElement;
@@ -92,9 +93,10 @@ namespace CamelotEngine
 		UINT32 numMeshes = 0;
 		for(auto& renderElem : meshDataPerRenderElement)
 		{
-			renderElem.second.vertices = new Vector2[renderElem.second.numQuads * 4];
-			renderElem.second.uvs = new Vector2[renderElem.second.numQuads * 4];
-			renderElem.second.indices = new UINT32[renderElem.second.numQuads * 6];
+			renderElem.second.meshData = std::shared_ptr<MeshData>(new MeshData());
+			renderElem.second.vertices = renderElem.second.meshData->addPositionsVec2(renderElem.second.numQuads * 4);
+			renderElem.second.uvs = renderElem.second.meshData->addUV0(renderElem.second.numQuads * 4);
+			renderElem.second.indices = renderElem.second.meshData->addIndices32(renderElem.second.numQuads * 6);
 			numMeshes++;
 		}
 
@@ -140,13 +142,7 @@ namespace CamelotEngine
 		UINT32 meshIdx = 0;
 		for(auto& renderElem : meshDataPerRenderElement)
 		{
-			std::shared_ptr<MeshData> meshData(new MeshData());
-
-			meshData->setPositions(renderElem.second.vertices, renderElem.second.numQuads * 4);
-			meshData->setUV0(renderElem.second.uvs, renderElem.second.numQuads * 4);
-			meshData->setIndices(renderElem.second.indices, renderElem.second.numQuads * 6);
-
-			mCachedMeshes[meshIdx]->setMeshData(meshData);
+			mCachedMeshes[meshIdx]->setMeshData(renderElem.second.meshData);
 			mCachedMaterials[meshIdx] = renderElem.second.material;
 
 			meshIdx++;

+ 7 - 8
CamelotCore/Source/CmMesh.cpp

@@ -179,13 +179,14 @@ namespace CamelotEngine
 
 			for(UINT32 i = 0; i < mSubMeshes.size(); i++)
 			{
-				UINT8* indices = new UINT8[mSubMeshes[i].indexCount * idxElemSize];
-				memcpy(indices, &idxData[mSubMeshes[i].indexOffset * idxElemSize], mSubMeshes[i].indexCount * idxElemSize);
-
+				UINT8* indices = nullptr;
+				
 				if(indexType == IndexBuffer::IT_16BIT)
-					meshData->setIndices((UINT16*)indices, mSubMeshes[i].indexCount, i);
+					indices = (UINT8*)meshData->addIndices16(mSubMeshes[i].indexCount, i);
 				else
-					meshData->setIndices((UINT32*)indices, mSubMeshes[i].indexCount, i);
+					indices = (UINT8*)meshData->addIndices32(mSubMeshes[i].indexCount, i);
+				
+				memcpy(indices, &idxData[mSubMeshes[i].indexOffset * idxElemSize], mSubMeshes[i].indexCount * idxElemSize);
 			}
 
 			mIndexData->indexBuffer->unlock();
@@ -212,11 +213,9 @@ namespace CamelotEngine
 					UINT32 offset = element->getOffset();
 					UINT32 elemSize = element->getSize();
 
-					UINT8* dest = new UINT8[elemSize * mVertexData->vertexCount];
+					UINT8* dest = meshData->addVertexElementData(type, semantic, mVertexData->vertexCount, semanticIdx, streamIdx);
 					for(UINT32 k = 0; k < mVertexData->vertexCount; k++)
 						memcpy(&dest[k * elemSize], &vertDataIter[k * vertexSize + offset], elemSize);
-
-					meshData->setVertexElementData(type, semantic, dest, mVertexData->vertexCount, semanticIdx, streamIdx);
 				}
 
 				vertexBuffer->unlock();

+ 52 - 34
CamelotCore/Source/CmMeshData.cpp

@@ -32,70 +32,77 @@ namespace CamelotEngine
 		}
 	}
 
-	void MeshData::setPositions(Vector2* elements, UINT32 numElements, UINT32 streamIdx)
+	Vector2* MeshData::addPositionsVec2(UINT32 numElements, UINT32 streamIdx)
 	{
-		setVertexElementData(VET_FLOAT2, VES_POSITION, (UINT8*)(elements), numElements, 0, streamIdx);
+		return reinterpret_cast<Vector2*>(addVertexElementData(VET_FLOAT2, VES_POSITION, numElements, 0, streamIdx));
 	}
 
-	void MeshData::setPositions(Vector3* elements, UINT32 numElements, UINT32 streamIdx)
+	Vector3* MeshData::addPositionsVec3(UINT32 numElements, UINT32 streamIdx)
 	{
-		setVertexElementData(VET_FLOAT3, VES_POSITION, (UINT8*)(elements), numElements, 0, streamIdx);
+		return reinterpret_cast<Vector3*>(addVertexElementData(VET_FLOAT3, VES_POSITION, numElements, 0, streamIdx));
 	}
 
-	void MeshData::setPositions(Vector4* elements, UINT32 numElements, UINT32 streamIdx)
+	Vector4* MeshData::addPositionsVec4(UINT32 numElements, UINT32 streamIdx)
 	{
-		setVertexElementData(VET_FLOAT4, VES_POSITION, (UINT8*)(elements), numElements, 0, streamIdx);
+		return reinterpret_cast<Vector4*>(addVertexElementData(VET_FLOAT4, VES_POSITION, numElements, 0, streamIdx));
 	}
 
-	void MeshData::setNormals(Vector3* elements, UINT32 numElements, UINT32 streamIdx)
+	Vector3* MeshData::addNormals(UINT32 numElements, UINT32 streamIdx)
 	{
-		setVertexElementData(VET_FLOAT3, VES_NORMAL, (UINT8*)(elements), numElements, 0, streamIdx);
+		return reinterpret_cast<Vector3*>(addVertexElementData(VET_FLOAT3, VES_NORMAL, numElements, 0, streamIdx));
 	}
 
-	void MeshData::setTangents(Vector3* elements, UINT32 numElements, UINT32 streamIdx)
+	Vector3* MeshData::addTangentsVec3(UINT32 numElements, UINT32 streamIdx)
 	{
-		setVertexElementData(VET_FLOAT3, VES_TANGENT, (UINT8*)(elements), numElements, 0, streamIdx);
+		return reinterpret_cast<Vector3*>(addVertexElementData(VET_FLOAT3, VES_TANGENT, numElements, 0, streamIdx));
 	}
 
-	void MeshData::setTangents(Vector4* elements, UINT32 numElements, UINT32 streamIdx)
+	Vector4* MeshData::addTangentsVec4(UINT32 numElements, UINT32 streamIdx)
 	{
-		setVertexElementData(VET_FLOAT4, VES_TANGENT, (UINT8*)(elements), numElements, 0, streamIdx);
+		return reinterpret_cast<Vector4*>(addVertexElementData(VET_FLOAT4, VES_TANGENT, numElements, 0, streamIdx));
 	}
 
-	void MeshData::setBitangents(Vector3* elements, UINT32 numElements, UINT32 streamIdx)
+	Vector3* MeshData::addBitangents(UINT32 numElements, UINT32 streamIdx)
 	{
-		setVertexElementData(VET_FLOAT3, VES_BITANGENT, (UINT8*)(elements), numElements, 0, streamIdx);
+		return reinterpret_cast<Vector3*>(addVertexElementData(VET_FLOAT3, VES_BITANGENT, numElements, 0, streamIdx));
 	}
 
-	void MeshData::setUV0(Vector2* elements, UINT32 numElements, UINT32 streamIdx)
+	Vector2* MeshData::addUV0(UINT32 numElements, UINT32 streamIdx)
 	{
-		setVertexElementData(VET_FLOAT2, VES_TEXCOORD, (UINT8*)(elements), numElements, 0, streamIdx);
+		return reinterpret_cast<Vector2*>(addVertexElementData(VET_FLOAT2, VES_TEXCOORD, numElements, 0, streamIdx));
 	}
 
-	void MeshData::setUV1(Vector2* elements, UINT32 numElements, UINT32 streamIdx)
+	Vector2* MeshData::addUV1(UINT32 numElements, UINT32 streamIdx)
 	{
-		setVertexElementData(VET_FLOAT2, VES_TEXCOORD, (UINT8*)(elements), numElements, 1, streamIdx);
+		return reinterpret_cast<Vector2*>(addVertexElementData(VET_FLOAT2, VES_TEXCOORD, numElements, 1, streamIdx));
 	}
 
-	void MeshData::setColors(Color* elements, UINT32 numElements, UINT32 streamIdx)
+	Color* MeshData::addColorsFloat(UINT32 numElements, UINT32 streamIdx)
 	{
-		setVertexElementData(VET_COLOR, VES_COLOR, (UINT8*)(elements), numElements, 0, streamIdx);
+		return reinterpret_cast<Color*>(addVertexElementData(VET_FLOAT4, VES_COLOR, numElements, 0, streamIdx));
 	}
 
-	void MeshData::setVertexElementData(VertexElementType type, VertexElementSemantic semantic, UINT8* elements, UINT32 numElements, UINT32 semanticIdx, UINT32 streamIdx)
+	UINT32* MeshData::addColorsDWORD(UINT32 numElements, UINT32 streamIdx)
+	{
+		return reinterpret_cast<UINT32*>(addVertexElementData(VET_COLOR, VES_COLOR, numElements, 0, streamIdx));
+	}
+
+	UINT8* MeshData::addVertexElementData(VertexElementType type, VertexElementSemantic semantic, UINT32 numElements, UINT32 semanticIdx, UINT32 streamIdx)
 	{
 		clearIfItExists(type, semantic, semanticIdx, streamIdx);
 
-		if(elements != nullptr)
-		{
-			vector<VertexElementData>::type& elemData = mVertexData[streamIdx];
+		UINT32 elemSize = VertexElement::getTypeSize(type);
+		UINT8* elements = new UINT8[elemSize * numElements];
 
-			VertexElementData newElement(type, semantic, semanticIdx, streamIdx, elements, numElements);
-			elemData.push_back(newElement);
-		}
+		vector<VertexElementData>::type& elemData = mVertexData[streamIdx];
+
+		VertexElementData newElement(type, semantic, semanticIdx, streamIdx, elements, numElements);
+		elemData.push_back(newElement);
+
+		return elements;
 	}
 
-	void MeshData::setIndices(UINT32* indices, UINT32 numIndices, UINT32 subMesh)
+	UINT32* MeshData::addIndices32(UINT32 numIndices, UINT32 subMesh)
 	{
 		if(mIndexType != IndexBuffer::IT_32BIT)
 			CM_EXCEPT(InvalidParametersException, "Trying to set 32bit indices but the MeshData was initialized as 16bit.");
@@ -108,15 +115,19 @@ namespace CamelotEngine
 		if(indexData.indices != nullptr)
 			delete[] indexData.indices;
 
+		UINT32* indices = new UINT32[numIndices];
+
 		indexData.indices = (UINT8*)indices;
 		indexData.numIndices = numIndices;
 		indexData.elementSize = getIndexElementSize();
 		indexData.subMesh = subMesh;
 
 		mIndices[subMesh] = indexData;
+
+		return indices;
 	}
 
-	void MeshData::setIndices(UINT16* indices, UINT32 numIndices, UINT32 subMesh)
+	UINT16* MeshData::addIndices16(UINT32 numIndices, UINT32 subMesh)
 	{
 		if(mIndexType != IndexBuffer::IT_16BIT)
 			CM_EXCEPT(InvalidParametersException, "Trying to set 16bit indices but the MeshData was initialized as 32bit.");
@@ -129,12 +140,16 @@ namespace CamelotEngine
 		if(indexData.indices != nullptr)
 			delete[] indexData.indices;
 
+		UINT16* indices = new UINT16[numIndices];
+
 		indexData.indices = (UINT8*)indices;
 		indexData.numIndices = numIndices;
 		indexData.elementSize = getIndexElementSize();
 		indexData.subMesh = subMesh;
 
 		mIndices[subMesh] = indexData;
+
+		return indices;
 	}
 
 	VertexDeclarationPtr MeshData::createDeclaration() const
@@ -223,6 +238,7 @@ namespace CamelotEngine
 		UINT32 subMeshIndex = 0;
 		vector<VertexElement>::type combinedVertexElements;
 		vector<UINT8*>::type vertexElemData;
+		vector<UINT32>::type bufferOffsets;
 		UINT32 totalVertexCount = 0;
 
 		UINT32 vertexIndexOffset = 0;
@@ -231,14 +247,13 @@ namespace CamelotEngine
 			for(UINT32 i = 0; i < meshData->getNumSubmeshes(); i++)
 			{
 				UINT32 numIndices = meshData->getNumIndices(i);
-				UINT32* indices = new UINT32[numIndices];
+				UINT32* indices = combinedMeshData->addIndices32(numIndices, subMeshIndex);
 
 				UINT32* sourceIndices = meshData->getIndices32(i);
 
 				for(UINT32 j = 0; j < numIndices; j++)
 					indices[j] = sourceIndices[j] + vertexIndexOffset;
 
-				combinedMeshData->setIndices(indices, numIndices, subMeshIndex);
 				subMeshIndex++;
 			}
 
@@ -271,18 +286,21 @@ namespace CamelotEngine
 				if(alreadyExistsIdx == -1)
 				{
 					combinedVertexElements.push_back(newElement);
+					
+					UINT8* newBuffer = combinedMeshData->addVertexElementData(newElement.getType(), newElement.getSemantic(), totalVertexCount, newElement.getIndex(), newElement.getSource());
+					
 					UINT32 newBufferSize = totalVertexCount * newElement.getSize();
-					UINT8* newBuffer = new UINT8[newBufferSize];
 					memset(newBuffer, 0, newBufferSize);
 
 					vertexElemData.push_back(newBuffer);
+					bufferOffsets.push_back(0);
 					alreadyExistsIdx = (UINT32)vertexElemData.size() - 1;
 				}
 
 				UINT8* source = meshData->getVertElemData(newElement.getType(), newElement.getSemantic(), newElement.getIndex(), newElement.getSource()).data;
-				memcpy(&(vertexElemData[alreadyExistsIdx]), source, numVertices * newElement.getSize());
+				UINT32 offset = vertexOffset * newElement.getSize();
 
-				combinedMeshData->setVertexElementData(newElement.getType(), newElement.getSemantic(), source, numVertices, newElement.getIndex(), newElement.getSource());
+				memcpy(&(vertexElemData[alreadyExistsIdx]) + offset, source, numVertices * newElement.getSize());
 			}
 
 			vertexOffset += meshData->getNumVertices();

+ 2 - 5
CamelotCore/Source/CmMeshManager.cpp

@@ -8,16 +8,13 @@ namespace CamelotEngine
 	{
 		mNullMeshData = MeshDataPtr(CM_NEW(MeshData, GenAlloc) MeshData(), &MemAllocDeleter<MeshData, GenAlloc>::deleter);
 
-		auto indices = new UINT32[3];
+		auto indices = mNullMeshData->addIndices32(3);
 		indices[0] = 0;
 		indices[1] = 0;
 		indices[2] = 0;
 
-		auto vertices = new Vector3[1];
+		auto vertices = mNullMeshData->addPositionsVec3(1);
 		vertices[0] = Vector3(0, 0, 0);
-
-		mNullMeshData->setPositions(vertices, 3);
-		mNullMeshData->setIndices(indices, 3);
 	}
 
 	MeshManager::~MeshManager()

+ 9 - 35
CamelotFBXImporter/Source/CmFBXImporter.cpp

@@ -219,7 +219,7 @@ namespace CamelotEngine
 					{
 						subMeshes[lIndex].indexOffset = lOffset;
 						lOffset += subMeshes[lIndex].indexCount;
-						indices[lIndex] = new UINT32[subMeshes[lIndex].indexCount];
+						indices[lIndex] = meshData->addIndices32(subMeshes[lIndex].indexCount, lIndex);
 					}
 					FBX_ASSERT(lOffset == lPolygonCount * 3);
 				}
@@ -232,7 +232,7 @@ namespace CamelotEngine
 			subMeshes.resize(1);
 			indices.resize(1);
 			subMeshes[0].indexCount = lPolygonCount * 3;
-			indices[0] = new UINT32[subMeshes[0].indexCount];
+			indices[0] = meshData->addIndices32(subMeshes[0].indexCount);
 		}
 
 		// Find out which vertex attributes exist
@@ -332,23 +332,23 @@ namespace CamelotEngine
 			lPolygonVertexCount = lPolygonCount * 3;
 
 		UINT32 vertexCount = lPolygonVertexCount;
-		Vector3* vertex = new Vector3[vertexCount];
+		Vector3* vertex = meshData->addPositionsVec3(vertexCount);
 
 		Color* color = nullptr;
 		if(hasColor)
-			color = new Color[vertexCount];
+			color = meshData->addColorsFloat(vertexCount);
 
 		Vector3* normal = nullptr;
 		if (hasNormal)
-			normal = new Vector3[vertexCount];
+			normal = meshData->addNormals(vertexCount);
 
 		Vector3* tangent = nullptr;
 		if (hasTangent)
-			tangent = new Vector3[vertexCount];
+			tangent = meshData->addTangentsVec3(vertexCount);
 
 		Vector3* bitangent = nullptr;
 		if (hasBitangent)
-			bitangent = new Vector3[vertexCount];
+			bitangent = meshData->addBitangents(vertexCount);
 
 		FbxStringList lUVNames;
 		mesh->GetUVSetNames(lUVNames);
@@ -356,7 +356,7 @@ namespace CamelotEngine
 		Vector2* uv0 = nullptr;
 		if (hasUV0 && lUVNames.GetCount() > 0)
 		{
-			uv0 = new Vector2[vertexCount];
+			uv0 = meshData->addUV0(vertexCount);
 			lUVName0 = lUVNames[0];
 		}
 
@@ -364,7 +364,7 @@ namespace CamelotEngine
 		Vector2* uv1 = nullptr;
 		if (hasUV1 && lUVNames.GetCount() > 1)
 		{
-			uv1 = new Vector2[vertexCount];
+			uv1 = meshData->addUV1(vertexCount);
 			lUVName1 = lUVNames[1];
 		}
 
@@ -584,32 +584,6 @@ namespace CamelotEngine
 			indexOffsetPerSubmesh[lMaterialIndex] += 3;
 		}
 
-		if(vertex != nullptr)
-			meshData->setPositions(vertex, vertexCount);
-
-		if(color != nullptr)
-			meshData->setColors(color, vertexCount);
-
-		if(normal != nullptr)
-			meshData->setNormals(normal, vertexCount);
-
-		if(tangent != nullptr)
-			meshData->setTangents(tangent, vertexCount);
-
-		if(bitangent != nullptr)
-			meshData->setBitangents(bitangent, vertexCount);
-
-		if(uv0 != nullptr)
-			meshData->setUV0(uv0, vertexCount);
-
-		if(uv1 != nullptr)
-			meshData->setUV1(uv1, vertexCount);
-
-		for(size_t i = 0; i < subMeshes.size(); i++)
-		{
-			meshData->setIndices(indices[i], subMeshes[i].indexCount, (UINT32)i);
-		}
-
 		return meshData;
 	}
 }

+ 22 - 0
TODO.txt

@@ -24,6 +24,8 @@ Move Debug to CamelotCore and add SetFillMode
 GameObjectREAL is IReflectable but doesn't have RTTI
  - COmponentRTTI doesn't account its new parent is GameObjectREAL so change that
 
+GameObjectHandle has  SceneObject friend which doesn't make sense
+
 Make GameObjectHandle hold a normal pointer instead of a shared one
  - By its definition its guaranteed to have only one reference so there's no need for shared ptr
 
@@ -103,6 +105,26 @@ Can be delayed:
 
 ---------------------------------------------------
 
+<<<<DirectDraw>>>>
+ - Used for quickly drawing something, usually for debug and editor purposes.
+ - It consists of methods like: DrawLine, DrawPolygon, DrawCube, DrawSphere, etc.
+ - It may also contain other fancier methods like DrawWireframeMesh, DrawWorldGrid etc.
+ - Commands get queued from various Component::update methods and get executed at the end of frame. After they're executed they are cleared and need to be re-queued next frame.
+ - Internally DirectDraw manages dynamic meshes so it can merge multiple DrawLine class into one and such. This can help performance, but generally performance of this class should not be a major concern.
+ - Example uses for it: 
+    - Drawing GUI element bounds when debugging GUI
+    - Drawing a wireframe selection effect when a mesh is selected in the scene
+
+
+<<<<Multithreaded memory allocator>>>>
+ - Singlethreaded implementation from Game Engine Gems 2 book
+ - Small and medium allocators separate for each thread. Memory overhead should be minimal considering how small the pages are. But performance benefits are great.
+ - Large allocator just uses some simple form of page allocation and reuse, using atomics?
+ - Must ensure that memory allocated on one thread can only be freed from that thread
+ - How do I easily tell which allocator to call based on current thread? Require a thread ID with each alloc/dealloc?
+ - Need to think this through more
+ 
+
 <<<<Resource changes and reimport>>>>
 Use case example:
  - User reimports a .gpuproginc file