Browse Source

Updated MeshData so it is much easier to use

Marko Pintera 12 years ago
parent
commit
15a13feeb0

+ 10 - 21
CamelotClient/CmTestTextSprite.cpp

@@ -34,37 +34,26 @@ namespace CamelotEngine
 		UINT32 numIndices = numTextFaces * 6;
 		UINT32 numIndices = numTextFaces * 6;
 
 
 		std::shared_ptr<MeshData> textData(new MeshData());
 		std::shared_ptr<MeshData> textData(new MeshData());
-		textData->declaration->addElement(0, 0, VET_FLOAT3, VES_POSITION);
-		textData->declaration->addElement(0, 12, VET_FLOAT2, VES_TEXCOORD);
 
 
-		textData->index = new int[numIndices];
-		textData->indexCount = numIndices;
-		textData->vertexCount = numVertices;
-		
-		std::shared_ptr<MeshData::VertexData> vertData(new MeshData::VertexData(numVertices));
-		vertData->vertex = new Vector3[numVertices];
-		vertData->uv0 = new Vector2[numVertices];
+		auto indices = new UINT32[numIndices];
+		auto vertices = new Vector3[numVertices];
+		auto uvs = new Vector2[numVertices];
 
 
-		Vector2* vec2Buffer = new Vector2[numVertices];
+		auto vec2Buffer = new Vector2[numVertices];
 
 
-		mTextSprite->fillBuffer(vec2Buffer, vertData->uv0, (UINT32*)textData->index, 0, numTextFaces);
+		mTextSprite->fillBuffer(vec2Buffer, uvs, indices, 0, numTextFaces);
 
 
 		for(UINT32 i = 0; i < numVertices; i++)
 		for(UINT32 i = 0; i < numVertices; i++)
-		{
-			vertData->vertex[i] = Vector3(vec2Buffer[i].x, vec2Buffer[i].y, 0.0f);
-		}
+			vertices[i] = Vector3(vec2Buffer[i].x, vec2Buffer[i].y, 0.0f);
 
 
-		textData->vertexBuffers[0] = vertData;
+		delete[] vec2Buffer;
 
 
-		MeshData::SubMeshData subMeshData;
-		subMeshData.indexOffset = 0;
-		subMeshData.indexCount = numIndices;
-		textData->subMeshes.push_back(subMeshData);
+		textData->setPositions(vertices, numVertices);
+		textData->setUV0(uvs, numVertices);
+		textData->setIndices(indices, numIndices);
 
 
 		mTextMesh->setMeshData(textData);
 		mTextMesh->setMeshData(textData);
 
 
-		delete[] vec2Buffer;
-
 		mTextRenderable->setMesh(mTextMesh);
 		mTextRenderable->setMesh(mTextMesh);
 
 
 		UINT32 nearestSize = font->getClosestAvailableSize(12);
 		UINT32 nearestSize = font->getClosestAvailableSize(12);

+ 1 - 0
CamelotCore/CamelotCore.vcxproj

@@ -319,6 +319,7 @@
     <ClCompile Include="Source\CmImportOptions.cpp" />
     <ClCompile Include="Source\CmImportOptions.cpp" />
     <ClCompile Include="Source\CmIndexBuffer.cpp" />
     <ClCompile Include="Source\CmIndexBuffer.cpp" />
     <ClCompile Include="Source\CmIndexData.cpp" />
     <ClCompile Include="Source\CmIndexData.cpp" />
+    <ClCompile Include="Source\CmMeshDataRTTI.cpp" />
     <ClCompile Include="Source\CmMeshManager.cpp" />
     <ClCompile Include="Source\CmMeshManager.cpp" />
     <ClCompile Include="Source\CmOcclusionQuery.cpp" />
     <ClCompile Include="Source\CmOcclusionQuery.cpp" />
     <ClCompile Include="Source\CmPixelBuffer.cpp" />
     <ClCompile Include="Source\CmPixelBuffer.cpp" />

+ 3 - 0
CamelotCore/CamelotCore.vcxproj.filters

@@ -662,5 +662,8 @@
     <ClCompile Include="Source\CmTextSprite.cpp">
     <ClCompile Include="Source\CmTextSprite.cpp">
       <Filter>Source Files\2D</Filter>
       <Filter>Source Files\2D</Filter>
     </ClCompile>
     </ClCompile>
+    <ClCompile Include="Source\CmMeshDataRTTI.cpp">
+      <Filter>Source Files\RTTI</Filter>
+    </ClCompile>
   </ItemGroup>
   </ItemGroup>
 </Project>
 </Project>

+ 229 - 26
CamelotCore/Include/CmMeshData.h

@@ -3,58 +3,261 @@
 #include "CmPrerequisites.h"
 #include "CmPrerequisites.h"
 #include "CmIReflectable.h"
 #include "CmIReflectable.h"
 #include "CmVertexBuffer.h"
 #include "CmVertexBuffer.h"
+#include "CmIndexBuffer.h"
+#include "CmVertexDeclaration.h"
 
 
 namespace CamelotEngine
 namespace CamelotEngine
 {
 {
 	class CM_EXPORT MeshData : public IReflectable
 	class CM_EXPORT MeshData : public IReflectable
 	{
 	{
 	public:
 	public:
-		struct SubMeshData
+		struct VertexElementData : public IReflectable
 		{
 		{
-			SubMeshData():
-				indexOffset(0), indexCount(0)
+			VertexElementData(VertexElementType type, VertexElementSemantic semantic, UINT32 semanticIdx, UINT32 streamIdx, UINT8* _data, UINT32 numElements)
+				:data(_data), elementCount(numElements), element(streamIdx, 0, type, semantic, semanticIdx)
 			{ }
 			{ }
 
 
-			int indexOffset;
-			int indexCount;
+			UINT8* data;
+			UINT32 elementCount;
+			VertexElement element;
+
+			/************************************************************************/
+			/* 								SERIALIZATION                      		*/
+			/************************************************************************/
+		public:
+			VertexElementData()
+			:data(nullptr), elementCount(0) 
+			{} // Serialization only constructor
+
+			friend class VertexElementDataRTTI;
+			static RTTITypeBase* getRTTIStatic();
+			virtual RTTITypeBase* getRTTI() const;
 		};
 		};
 
 
-		struct CM_EXPORT VertexData : public IReflectable
+		struct IndexElementData : public IReflectable
 		{
 		{
-			VertexData(UINT32 vertexCount, UINT32 streamIdx = 0);
-			~VertexData();
-
-			Vector3* vertex;
-			Color* color;
-			Vector3* normal;
-			Vector3* tangent;
-			Vector3* bitangent;
-			Vector2* uv0;
-			Vector2* uv1;
+			IndexElementData()
+				:numIndices(0), subMesh(0), elementSize(0), indices(nullptr)
+			{ }
 
 
-			UINT32 vertexCount;
-			UINT32 streamIdx;
+			UINT8* indices;
+			UINT32 numIndices;
+			UINT32 elementSize;
+			UINT32 subMesh;
 
 
 			/************************************************************************/
 			/************************************************************************/
 			/* 								SERIALIZATION                      		*/
 			/* 								SERIALIZATION                      		*/
 			/************************************************************************/
 			/************************************************************************/
 		public:
 		public:
-			friend class VertexDataRTTI;
+			friend class IndexElementDataRTTI;
 			static RTTITypeBase* getRTTIStatic();
 			static RTTITypeBase* getRTTIStatic();
 			virtual RTTITypeBase* getRTTI() const;
 			virtual RTTITypeBase* getRTTI() const;
 		};
 		};
 
 
-		MeshData();
+		MeshData(IndexBuffer::IndexType indexType = IndexBuffer::IT_32BIT);
 		~MeshData();
 		~MeshData();
 
 
-		int* index;
+		/**
+		 * @brief	Provides a convenient way of setting mesh positions. 
+		 *
+		 * @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);
+
+		/**
+		 * @brief	Provides a convenient way of setting mesh positions. 
+		 *
+		 * @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);
+
+		/**
+		 * @brief	Provides a convenient way of setting mesh positions. 
+		 *
+		 * @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);
+
+		/**
+		 * @brief	Provides a convenient way of setting mesh normals.
+		 *
+		 * @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);
+
+		/**
+		 * @brief	Provides a convenient way of setting mesh tangents.
+		 *
+		 * @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);
+
+		/**
+		 * @brief	Provides a convenient way of setting mesh tangents.
+		 *
+		 * @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);
+
+		/**
+		 * @brief	Provides a convenient way of setting mesh bitangents. 
+		 *
+		 * @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);
+
+		/**
+		 * @brief	Provides a convenient way of setting mesh texture coordinates.
+		 *
+		 * @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);
+
+		/**
+		 * @brief	Provides a convenient way of setting mesh texture coordinates. 
+		 *
+		 * @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);
+
+		/**
+		 * @brief	Provides a convenient way of setting mesh colors. 
+		 *
+		 * @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);
+
+		/**
+		 * @brief	Adds (or replaces) a new set of vertex element data. 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);
+
+		/**
+		 * @brief	Sets a list of indices for the specified sub mesh. 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);
+
+		/**
+		 * @brief	Sets a list of indices for the specified sub mesh. 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);
+
+		/**
+		 * @brief	Query if we have vertex data for the specified semantic.
+		 */
+		bool hasElement(VertexElementSemantic semantic, UINT32 semanticIdx = 0, UINT32 streamIdx = 0) const;
+
+		/**
+		 * @brief	Creates a new vertex declaration based on set vertex elements.
+		 */
+		VertexDeclarationPtr createDeclaration() const;
+
+		UINT32 getNumSubmeshes() const { return (UINT32)mIndices.size(); }
+		UINT32 getNumVertices() const;
+		UINT32 getNumIndices(UINT32 subMesh) const;
+
+		UINT16* getIndices16(UINT32 subMesh) const;
+		UINT32* getIndices32(UINT32 subMesh) const;
+
+		vector<VertexElement>::type getVertexElements() const;
+
+		MeshData::VertexElementData& getVertElemData(VertexElementType type, VertexElementSemantic semantic, UINT32 semanticIdx, UINT32 streamIdx);
+
+		UINT32 getIndexElementSize()
+		{
+			return mIndexType == IndexBuffer::IT_32BIT ? sizeof(UINT32) : sizeof(UINT16);
+		}
+
+		static MeshDataPtr combine(const vector<MeshDataPtr>::type& elements);
+
+	private:
+		friend class Mesh;
+
+		vector<IndexElementData>::type mIndices;
+		map<UINT32, vector<VertexElementData>::type>::type mVertexData;
 
 
-		int indexCount;
-		int vertexCount;
+		IndexBuffer::IndexType mIndexType;
 
 
-		VertexDeclarationPtr declaration;
-		map<int, std::shared_ptr<VertexData>>::type vertexBuffers;
-		vector<SubMeshData>::type subMeshes;
+		void clearIfItExists(VertexElementType type, VertexElementSemantic semantic, UINT32 semanticIdx, UINT32 streamIdx);
 
 
 		/************************************************************************/
 		/************************************************************************/
 		/* 								SERIALIZATION                      		*/
 		/* 								SERIALIZATION                      		*/

+ 90 - 80
CamelotCore/Include/CmMeshDataRTTI.h

@@ -8,150 +8,160 @@
 
 
 namespace CamelotEngine
 namespace CamelotEngine
 {
 {
-	class CM_EXPORT VertexDataRTTI : public RTTIType<MeshData::VertexData, IReflectable, VertexDataRTTI>
+	class CM_EXPORT VertexElementDataRTTI : public RTTIType<MeshData::VertexElementData, IReflectable, VertexElementDataRTTI>
 	{
 	{
 	private:
 	private:
-		ManagedDataBlock getVertex(MeshData::VertexData* obj) { return ManagedDataBlock((UINT8*)obj->vertex, obj->vertexCount * sizeof(Vector3), false); }	
-		void setVertex(MeshData::VertexData* obj, ManagedDataBlock val) { obj->vertex = (Vector3*)val.getData(); } 
+		ManagedDataBlock getVertexData(MeshData::VertexElementData* obj) { return ManagedDataBlock(obj->data, obj->elementCount * obj->element.getSize(), false); }	
+		void setVertexData(MeshData::VertexElementData* obj, ManagedDataBlock val) { obj->data = val.getData(); } 
 
 
-		ManagedDataBlock getColor(MeshData::VertexData* obj) { return ManagedDataBlock((UINT8*)obj->color, obj->vertexCount * sizeof(Color), false); }	
-		void setColor(MeshData::VertexData* obj, ManagedDataBlock val) { obj->color = (Color*)val.getData(); } 
+		UINT32& getNumElements(MeshData::VertexElementData* obj) { return obj->elementCount; }
+		void setNumElements(MeshData::VertexElementData* obj, UINT32& value) { obj->elementCount = value; }
 
 
-		ManagedDataBlock getNormal(MeshData::VertexData* obj) { return ManagedDataBlock((UINT8*)obj->normal, obj->vertexCount * sizeof(Vector3), false); }	
-		void setNormal(MeshData::VertexData* obj, ManagedDataBlock val) { obj->normal = (Vector3*)val.getData(); } 
+		VertexElement& getVertexElement(MeshData::VertexElementData* obj) { return obj->element; }
+		void setVertexElement(MeshData::VertexElementData* obj, VertexElement& value) { obj->element = value; }
 
 
-		ManagedDataBlock getTangent(MeshData::VertexData* obj) { return ManagedDataBlock((UINT8*)obj->tangent, obj->vertexCount * sizeof(Vector3), false); }	
-		void setTangent(MeshData::VertexData* obj, ManagedDataBlock val) { obj->tangent = (Vector3*)val.getData(); } 
+	public:
+		VertexElementDataRTTI()
+		{
+			addDataBlockField("data", 0, &VertexElementDataRTTI::getVertexData, &VertexElementDataRTTI::setVertexData);
+			addPlainField("elementCount", 1, &VertexElementDataRTTI::getNumElements, &VertexElementDataRTTI::setNumElements);
+			addPlainField("element", 2, &VertexElementDataRTTI::getVertexElement, &VertexElementDataRTTI::setVertexElement);
+		}
+
+		virtual std::shared_ptr<IReflectable> newRTTIObject() 
+		{
+			return std::shared_ptr<MeshData::VertexElementData>(new MeshData::VertexElementData());
+		}
+
+		virtual const String& getRTTIName() 
+		{
+			static String name = "VertexElementData";
+			throw name;
+		}
+
+		virtual UINT32 getRTTIId() 
+		{
+			return TID_VertexElementData;
+		}
+	};
 
 
-		ManagedDataBlock getBitangent(MeshData::VertexData* obj) { return ManagedDataBlock((UINT8*)obj->bitangent, obj->vertexCount * sizeof(Vector3), false); }	
-		void setBitangent(MeshData::VertexData* obj, ManagedDataBlock val) { obj->bitangent = (Vector3*)val.getData(); } 
+	class CM_EXPORT IndexElementDataRTTI : public RTTIType<MeshData::IndexElementData, IReflectable, IndexElementDataRTTI>
+	{
+	private:
+		ManagedDataBlock getIndexData(MeshData::IndexElementData* obj) { return ManagedDataBlock(obj->indices, obj->numIndices * obj->elementSize, false); }	
+		void setIndexData(MeshData::IndexElementData* obj, ManagedDataBlock val) { obj->indices = val.getData(); } 
 
 
-		ManagedDataBlock getUV0(MeshData::VertexData* obj) { return ManagedDataBlock((UINT8*)obj->uv0, obj->vertexCount * sizeof(Vector2), false); }	
-		void setUV0(MeshData::VertexData* obj, ManagedDataBlock val) { obj->uv0 = (Vector2*)val.getData(); } 
+		UINT32& getNumIndices(MeshData::IndexElementData* obj) { return obj->numIndices; }
+		void setNumIndices(MeshData::IndexElementData* obj, UINT32& value) { obj->numIndices = value; }
 
 
-		ManagedDataBlock getUV1(MeshData::VertexData* obj) { return ManagedDataBlock((UINT8*)obj->uv1, obj->vertexCount * sizeof(Vector2), false); }	
-		void setUV1(MeshData::VertexData* obj, ManagedDataBlock val) { obj->uv1 = (Vector2*)val.getData(); } 
+		UINT32& getElementSize(MeshData::IndexElementData* obj) { return obj->elementSize; }
+		void setElementSize(MeshData::IndexElementData* obj, UINT32& value) { obj->elementSize = value; }
 
 
-		CM_SETGET_MEMBER(vertexCount, UINT32, MeshData::VertexData);
-		CM_SETGET_MEMBER(streamIdx, UINT32, MeshData::VertexData);
+		UINT32& getSubMesh(MeshData::IndexElementData* obj) { return obj->subMesh; }
+		void setSubMesh(MeshData::IndexElementData* obj, UINT32& value) { obj->subMesh = value; }
 	public:
 	public:
-		VertexDataRTTI()
+		IndexElementDataRTTI()
 		{
 		{
-			addDataBlockField("vertex", 0, &VertexDataRTTI::getVertex, &VertexDataRTTI::setVertex);
-			addDataBlockField("color", 1, &VertexDataRTTI::getColor, &VertexDataRTTI::setColor);
-			addDataBlockField("normal", 2, &VertexDataRTTI::getNormal, &VertexDataRTTI::setNormal);
-			addDataBlockField("tangent", 3, &VertexDataRTTI::getTangent, &VertexDataRTTI::setTangent);
-			addDataBlockField("bitangent", 4, &VertexDataRTTI::getBitangent, &VertexDataRTTI::setBitangent);
-			addDataBlockField("uv0", 5, &VertexDataRTTI::getUV0, &VertexDataRTTI::setUV0);
-			addDataBlockField("uv1", 6, &VertexDataRTTI::getUV1, &VertexDataRTTI::setUV1);
-
-			CM_ADD_PLAINFIELD(vertexCount, 7, VertexDataRTTI)
-			CM_ADD_PLAINFIELD(streamIdx, 8, VertexDataRTTI)
+			addDataBlockField("indices", 0, &IndexElementDataRTTI::getIndexData, &IndexElementDataRTTI::setIndexData);
+			addPlainField("numIndices", 1, &IndexElementDataRTTI::getNumIndices, &IndexElementDataRTTI::setNumIndices);
+			addPlainField("elementSize", 2, &IndexElementDataRTTI::getElementSize, &IndexElementDataRTTI::setElementSize);
+			addPlainField("subMesh", 3, &IndexElementDataRTTI::getSubMesh, &IndexElementDataRTTI::setSubMesh);
 		}
 		}
 
 
 		virtual std::shared_ptr<IReflectable> newRTTIObject() 
 		virtual std::shared_ptr<IReflectable> newRTTIObject() 
 		{
 		{
-			return std::shared_ptr<MeshData::VertexData>(new MeshData::VertexData(0));
+			return std::shared_ptr<MeshData::IndexElementData>(new MeshData::IndexElementData());
 		}
 		}
 
 
 		virtual const String& getRTTIName() 
 		virtual const String& getRTTIName() 
 		{
 		{
-			static String name = "MeshData::VertexData";
+			static String name = "IndexElementData";
 			throw name;
 			throw name;
 		}
 		}
 
 
 		virtual UINT32 getRTTIId() 
 		virtual UINT32 getRTTIId() 
 		{
 		{
-			return TID_VertexData;
+			return TID_IndexElementData;
 		}
 		}
 	};
 	};
 
 
-	CM_ALLOW_MEMCPY_SERIALIZATION(MeshData::SubMeshData);
+	CM_ALLOW_MEMCPY_SERIALIZATION(IndexBuffer::IndexType);
 
 
 	class CM_EXPORT MeshDataRTTI : public RTTIType<MeshData, IReflectable, MeshDataRTTI>
 	class CM_EXPORT MeshDataRTTI : public RTTIType<MeshData, IReflectable, MeshDataRTTI>
 	{
 	{
 	private:
 	private:
-		CM_SETGET_MEMBER(indexCount, INT32, MeshData)
-		CM_SETGET_MEMBER(vertexCount, INT32, MeshData);
-
-		ManagedDataBlock getIndex(MeshData* obj) { return ManagedDataBlock((UINT8*)obj->index, obj->indexCount * sizeof(int), false); }	
-		void setIndex(MeshData* obj, ManagedDataBlock val) { obj->index = (int*)val.getData(); } 
+		struct TempMeshData
+		{
+			vector<MeshData::VertexElementData>::type vertexElements;
+		};
 
 
-		/************************************************************************/
-		/* 								subMeshes                      			*/
-		/************************************************************************/
-		MeshData::SubMeshData& getSubmesh(MeshData* obj, UINT32 idx)
+		MeshData::VertexElementData& getVertexElementData(MeshData* obj, UINT32 arrayIdx)
 		{
 		{
-			return obj->subMeshes[idx];
+			auto tempData = boost::any_cast<std::shared_ptr<TempMeshData>>(obj->mRTTIData);
+			return tempData->vertexElements[arrayIdx];
 		}
 		}
 
 
-		void setSubmesh(MeshData* obj, UINT32 idx, MeshData::SubMeshData& data)
+		void setVertexElementData(MeshData* obj, UINT32 arrayIdx, MeshData::VertexElementData& value)
 		{
 		{
-			obj->subMeshes[idx] = data;
+			obj->setVertexElementData(value.element.getType(), value.element.getSemantic(), value.data, value.elementCount, value.element.getIndex(), value.element.getSource());
 		}
 		}
 
 
-		UINT32 getSubmeshArraySize(MeshData* obj)
+		UINT32 getNumVertexElementData(MeshData* obj)
 		{
 		{
-			return (UINT32)obj->subMeshes.size();
+			auto tempData = boost::any_cast<std::shared_ptr<TempMeshData>>(obj->mRTTIData);
+			return (UINT32)tempData->vertexElements.size();
 		}
 		}
 
 
-		void setSubmeshArraySize(MeshData* obj, UINT32 size)
+		void setNumVertexElementData(MeshData* obj, UINT32 numElements)
 		{
 		{
-			obj->subMeshes.resize(size);
+			// Do nothing
 		}
 		}
 
 
-		/************************************************************************/
-		/* 								vertexDeclaration                  		*/
-		/************************************************************************/
-
-		VertexDeclarationPtr getVertexDecl(MeshData* obj) { return obj->declaration; }
-		void setVertexDecl(MeshData* obj, VertexDeclarationPtr vertexDecl) { obj->declaration = vertexDecl; }
-
-		/************************************************************************/
-		/* 								vertexData                      		*/
-		/************************************************************************/
-		std::shared_ptr<MeshData::VertexData> getVertexData(MeshData* obj, UINT32 idx)
+		MeshData::IndexElementData& getIndexElementData(MeshData* obj, UINT32 arrayIdx)
 		{
 		{
-			int curIdx = 0;
-			for(auto iter = obj->vertexBuffers.begin(); iter != obj->vertexBuffers.end(); ++iter)
-			{
-				if(curIdx == idx)
-					return iter->second;
+			return obj->mIndices[arrayIdx];
+		}
 
 
-				curIdx++;
-			}
+		void setIndexElementData(MeshData* obj, UINT32 arrayIdx, MeshData::IndexElementData& value)
+		{
+			obj->mIndices[arrayIdx] = value;
+		}
 
 
-			CM_EXCEPT(InvalidParametersException, "Invalid index: " + toString(idx));
+		UINT32 getNumIndexElementData(MeshData* obj)
+		{
+			return (UINT32)obj->mIndices.size();
 		}
 		}
 
 
-		void setVertexData(MeshData* obj, UINT32 idx, std::shared_ptr<MeshData::VertexData> data)
+		void setNumIndexElementData(MeshData* obj, UINT32 numElements)
 		{
 		{
-			obj->vertexBuffers[data->streamIdx] = data;
+			obj->mIndices.resize(numElements);
 		}
 		}
 
 
-		UINT32 getVertexDataArraySize(MeshData* obj)
+		IndexBuffer::IndexType& getIndexType(MeshData* obj)
 		{
 		{
-			return (UINT32)obj->vertexBuffers.size();
+			return obj->mIndexType;
 		}
 		}
 
 
-		void setVertexDataArraySize(MeshData* obj, UINT32 size)
+		void setIndexType(MeshData* obj, IndexBuffer::IndexType& value)
 		{
 		{
-			// Do nothing, map will expand as entries are added
+			obj->mIndexType = value;
 		}
 		}
+
 	public:
 	public:
 		MeshDataRTTI()
 		MeshDataRTTI()
 		{
 		{
-			addDataBlockField("index", 0, &MeshDataRTTI::getIndex, &MeshDataRTTI::setIndex);
+			addReflectableArrayField("mVertexData", 0, &MeshDataRTTI::getVertexElementData, 
+				&MeshDataRTTI::getNumVertexElementData, &MeshDataRTTI::setVertexElementData, &MeshDataRTTI::setNumVertexElementData);
 
 
-			CM_ADD_PLAINFIELD(indexCount, 1, MeshDataRTTI)
-			CM_ADD_PLAINFIELD(vertexCount, 2, MeshDataRTTI)
+			addReflectableArrayField("mIndexBuffer", 1, &MeshDataRTTI::getIndexElementData, 
+				&MeshDataRTTI::getNumIndexElementData, &MeshDataRTTI::setIndexElementData, &MeshDataRTTI::setNumIndexElementData);
 
 
-			addPlainArrayField("subMeshes", 3, &MeshDataRTTI::getSubmesh, &MeshDataRTTI::getSubmeshArraySize, &MeshDataRTTI::setSubmesh, &MeshDataRTTI::setSubmeshArraySize);
-			addReflectablePtrField("vertexDeclaration", 4, &MeshDataRTTI::getVertexDecl, &MeshDataRTTI::setVertexDecl);
-			addReflectablePtrArrayField("vertexBuffer", 5, &MeshDataRTTI::getVertexData, &MeshDataRTTI::getVertexDataArraySize, 
-				&MeshDataRTTI::setVertexData, &MeshDataRTTI::setVertexDataArraySize);
+			addPlainField("mIndexType", 2, &MeshDataRTTI::getIndexType, &MeshDataRTTI::setIndexType);
 		}
 		}
 
 
+		virtual void onSerializationStarted(IReflectable* obj);
+		virtual void onSerializationEnded(IReflectable* obj);
+
 		virtual std::shared_ptr<IReflectable> newRTTIObject() 
 		virtual std::shared_ptr<IReflectable> newRTTIObject() 
 		{
 		{
 			return std::shared_ptr<MeshData>(new MeshData());
 			return std::shared_ptr<MeshData>(new MeshData());

+ 3 - 2
CamelotCore/Include/CmPrerequisites.h

@@ -232,7 +232,7 @@ namespace CamelotEngine
 		TID_Mesh = 1002,
 		TID_Mesh = 1002,
 		TID_MeshData = 1003,
 		TID_MeshData = 1003,
 		TID_VertexDeclaration = 1004,
 		TID_VertexDeclaration = 1004,
-		TID_VertexData = 1005,
+		TID_VertexElementData = 1005,
 		TID_Component = 1006,
 		TID_Component = 1006,
 		TID_Camera = 1007,
 		TID_Camera = 1007,
 		TID_Renderable = 1008,
 		TID_Renderable = 1008,
@@ -274,7 +274,8 @@ namespace CamelotEngine
 		TID_STDVECTOR = 1054,
 		TID_STDVECTOR = 1054,
 		TID_STDMAP = 1055,
 		TID_STDMAP = 1055,
 		TID_FontImportOptions = 1056,
 		TID_FontImportOptions = 1056,
-		TID_FontData = 1057
+		TID_FontData = 1057,
+		TID_IndexElementData = 1058
 	};
 	};
 
 
 	/**
 	/**

+ 3 - 0
CamelotCore/Include/CmVertexDeclaration.h

@@ -220,6 +220,9 @@ namespace CamelotEngine
 		size_t calculateHash() const;
 		size_t calculateHash() const;
 
 
     };
     };
+
+	CM_ALLOW_MEMCPY_SERIALIZATION(VertexElement);
+
     /** This class declares the format of a set of vertex inputs, which
     /** This class declares the format of a set of vertex inputs, which
         can be issued to the rendering API through a RenderOperation.
         can be issued to the rendering API through a RenderOperation.
 	@remarks
 	@remarks

+ 0 - 2
CamelotCore/Include/CmVertexDeclarationRTTI.h

@@ -7,8 +7,6 @@
 
 
 namespace CamelotEngine
 namespace CamelotEngine
 {
 {
-	CM_ALLOW_MEMCPY_SERIALIZATION(VertexElement);
-
 	class VertexDeclarationRTTI : public RTTIType<VertexDeclaration, IReflectable, VertexDeclarationRTTI>
 	class VertexDeclarationRTTI : public RTTIType<VertexDeclaration, IReflectable, VertexDeclarationRTTI>
 	{
 	{
 	private:
 	private:

+ 89 - 145
CamelotCore/Source/CmMesh.cpp

@@ -38,7 +38,35 @@ namespace CamelotEngine
 
 
 		if(meshData == nullptr)
 		if(meshData == nullptr)
 		{
 		{
-			CM_EXCEPT(InternalErrorException, "Cannot load mesh. Mesh data is null.");
+			CM_EXCEPT(InvalidParametersException, "Cannot load mesh. Mesh data is null.");
+		}
+
+		// Ensure all vertex elements are of proper size
+		UINT32 numVertices = 0;
+
+		auto vertElemDataPerStream = meshData->mVertexData;
+		MeshData::VertexElementData* firstElemData = nullptr;
+		if(vertElemDataPerStream.size() > 0)
+		{
+			auto vertElemData = vertElemDataPerStream.begin()->second;
+			auto firstVertElem = vertElemData.begin();
+			if(firstVertElem != vertElemData.end())
+			{
+				numVertices = firstVertElem->elementCount;
+			}
+		}
+
+		for(auto& vertElems : meshData->mVertexData)
+		{
+			for(auto& vertElem : vertElems.second)
+			{
+				if(vertElem.elementCount != numVertices)
+				{
+					CM_EXCEPT(InvalidParametersException, "All vertex element arrays in MeshData need to be of the same size. Found an array with semantic: "
+						+ toString(vertElem.element.getSemantic()) + " and element count: " + toString(vertElem.elementCount) + ". This doesn't match with other "
+						+ "element with semantic: " + toString(firstElemData->element.getSemantic()) + " and element count: " + toString(firstElemData->elementCount));
+				}
+			}
 		}
 		}
 
 
 		mSubMeshes.clear();
 		mSubMeshes.clear();
@@ -50,23 +78,37 @@ namespace CamelotEngine
 			delete mIndexData;
 			delete mIndexData;
 
 
 		// Submeshes
 		// Submeshes
-		for(UINT32 i = 0; i < meshData->subMeshes.size(); i++)
-			mSubMeshes.push_back(SubMesh(meshData->subMeshes[i].indexOffset, meshData->subMeshes[i].indexCount));
+		UINT32 indexOffset = 0;
+		UINT32 totalIndexCount = 0;
+		for(auto& i : meshData->mIndices)
+		{
+			UINT32 numIndices = i.numIndices;
+
+			if(numIndices > 0)
+			{
+				mSubMeshes.push_back(SubMesh(indexOffset, numIndices));
+				indexOffset += numIndices;
+				totalIndexCount += numIndices;
+			}
+		}
 
 
 		// Indices
 		// Indices
 		mIndexData = new IndexData();
 		mIndexData = new IndexData();
 
 
-		mIndexData->indexCount = meshData->indexCount;
+		mIndexData->indexCount = totalIndexCount;
 		mIndexData->indexBuffer = HardwareBufferManager::instance().createIndexBuffer(
 		mIndexData->indexBuffer = HardwareBufferManager::instance().createIndexBuffer(
-			IndexBuffer::IT_32BIT,
+			meshData->mIndexType,
 			mIndexData->indexCount, 
 			mIndexData->indexCount, 
 			GBU_STATIC);
 			GBU_STATIC);
 
 
-		UINT32* idxData = static_cast<UINT32*>(mIndexData->indexBuffer->lock(GBL_WRITE_ONLY_DISCARD));
+		UINT8* idxData = static_cast<UINT8*>(mIndexData->indexBuffer->lock(GBL_WRITE_ONLY));
+		UINT32 idxElementSize = meshData->getIndexElementSize();
 
 
-		for(UINT32 i = 0; i < mIndexData->indexCount; i++)
+		indexOffset = 0;
+		for(auto& i : meshData->mIndices)
 		{
 		{
-			idxData[i] = (UINT32)meshData->index[i];
+			memcpy(&idxData[indexOffset], i.indices, i.numIndices * idxElementSize);
+			indexOffset += i.numIndices;
 		}
 		}
 
 
 		mIndexData->indexBuffer->unlock();
 		mIndexData->indexBuffer->unlock();
@@ -74,12 +116,15 @@ namespace CamelotEngine
 		// Vertices
 		// Vertices
 		mVertexData = new VertexData();
 		mVertexData = new VertexData();
 
 
-		mVertexData->vertexCount = meshData->vertexCount;
-		mVertexData->vertexDeclaration = meshData->declaration->clone();
+		mVertexData->vertexCount = numVertices;
+		mVertexData->vertexDeclaration = meshData->createDeclaration();
 
 
-		for(auto iter = meshData->vertexBuffers.begin(); iter != meshData->vertexBuffers.end(); ++iter)
+		for(auto& vertElems : meshData->mVertexData)
 		{
 		{
-			int streamIdx = iter->first; 
+			UINT32 streamIdx = vertElems.first;
+
+			if(vertElems.second.size() == 0)
+				continue;
 
 
 			VertexBufferPtr vertexBuffer = HardwareBufferManager::instance().createVertexBuffer(
 			VertexBufferPtr vertexBuffer = HardwareBufferManager::instance().createVertexBuffer(
 				mVertexData->vertexDeclaration->getVertexSize(streamIdx),
 				mVertexData->vertexDeclaration->getVertexSize(streamIdx),
@@ -89,75 +134,22 @@ namespace CamelotEngine
 			mVertexData->setBuffer(streamIdx, vertexBuffer);
 			mVertexData->setBuffer(streamIdx, vertexBuffer);
 
 
 			UINT32 vertexSize = vertexBuffer->getVertexSize();
 			UINT32 vertexSize = vertexBuffer->getVertexSize();
-			UINT8* vertBufferData = static_cast<UINT8*>(vertexBuffer->lock(GBL_WRITE_ONLY_DISCARD));
+			UINT8* vertBufferData = static_cast<UINT8*>(vertexBuffer->lock(GBL_WRITE_ONLY));
 
 
 			UINT32 numElements = mVertexData->vertexDeclaration->getElementCount();
 			UINT32 numElements = mVertexData->vertexDeclaration->getElementCount();
 
 
 			for(UINT32 j = 0; j < numElements; j++)
 			for(UINT32 j = 0; j < numElements; j++)
 			{
 			{
 				const VertexElement* element = mVertexData->vertexDeclaration->getElement(j);
 				const VertexElement* element = mVertexData->vertexDeclaration->getElement(j);
-				VertexElementSemantic semantic = element->getSemantic();
 				UINT32 offset = element->getOffset();
 				UINT32 offset = element->getOffset();
 				UINT32 elemSize = element->getSize();
 				UINT32 elemSize = element->getSize();
 
 
-				std::shared_ptr<MeshData::VertexData> vertexData = meshData->vertexBuffers[streamIdx];
-
-				UINT8* source = nullptr;
-				switch(semantic)
-				{
-				case VES_POSITION:
-					if(vertexData->vertex)
-						source = (UINT8*)vertexData->vertex;
-
-					break;
-				case VES_COLOR:
-					if(vertexData->color)
-						source = (UINT8*)vertexData->color;
-
-					break;
-				case VES_NORMAL:
-					if(vertexData->normal)
-						source = (UINT8*)vertexData->normal;	
-
-					break;
-				case VES_TANGENT:
-					if(vertexData->tangent)
-						source = (UINT8*)vertexData->tangent;	
-
-					break;
-				case VES_BITANGENT:
-					if(vertexData->bitangent)
-						source = (UINT8*)vertexData->bitangent;	
-
-					break;
-				case VES_TEXCOORD:
-					if(element->getIndex() == 0)
-					{
-						if(vertexData->uv0)
-							source = (UINT8*)vertexData->uv0;	
-					}
-					else if(element->getIndex() == 1)
-					{
-						if(vertexData->uv1)
-							source = (UINT8*)vertexData->uv1;	
-					}
-
-					break;
-				default:
-					break;
-				}
+				MeshData::VertexElementData& elemData = meshData->getVertElemData(element->getType(), element->getSemantic(), element->getIndex(), streamIdx);
 
 
-				if(source != nullptr)
-				{
-					for(UINT32 k = 0; k < mVertexData->vertexCount; k++)
-						memcpy(&vertBufferData[k * vertexSize + offset], &source[k * elemSize], elemSize);
-				}
-				else
+				UINT8* sourceData = elemData.data;
+				for(UINT32 k = 0; k < elemData.elementCount; k++)
 				{
 				{
-					LOGWRN("Vertex declaration contains semantic (" + toString(semantic) + ") but mesh doesn't have data for it. Data for the semantic will be zeroed out.");
-
-					for(UINT32 k = 0; k < mVertexData->vertexCount; k++)
-						memset(&vertBufferData[k * vertexSize + offset], 0, elemSize);
+					memcpy(&vertBufferData[k * vertexSize + offset], &sourceData[k * elemSize], elemSize);
 				}
 				}
 			}
 			}
 
 
@@ -174,112 +166,64 @@ namespace CamelotEngine
 
 
 	void Mesh::getMeshData_internal(AsyncOp& asyncOp)
 	void Mesh::getMeshData_internal(AsyncOp& asyncOp)
 	{
 	{
-		MeshDataPtr meshData(new MeshData());
-
-		meshData->declaration = mVertexData->vertexDeclaration->clone();
-		
-		for(UINT32 i = 0; i < mSubMeshes.size(); i++)
-		{
-			MeshData::SubMeshData subMesh;
-			subMesh.indexCount = mSubMeshes[i].indexCount;
-			subMesh.indexOffset = mSubMeshes[i].indexOffset;
+		IndexBuffer::IndexType indexType = IndexBuffer::IT_32BIT;
+		if(mIndexData)
+			indexType = mIndexData->indexBuffer->getType();
 
 
-			meshData->subMeshes.push_back(subMesh);
-		}
+		MeshDataPtr meshData(new MeshData(indexType));
 
 
 		if(mIndexData)
 		if(mIndexData)
 		{
 		{
-			meshData->indexCount = mIndexData->indexCount - mIndexData->indexStart;
-			meshData->index = new int[meshData->indexCount];
+			UINT8* idxData = static_cast<UINT8*>(mIndexData->indexBuffer->lock(GBL_READ_ONLY));
+			UINT32 idxElemSize = mIndexData->indexBuffer->getIndexSize();
 
 
-			UINT32* idxData = static_cast<UINT32*>(mIndexData->indexBuffer->lock(GBL_READ_ONLY));
+			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);
 
 
-			for(UINT32 i = 0; i < mIndexData->indexCount; i++)
-				meshData->index[i] = (UINT32)idxData[i];
+				if(indexType == IndexBuffer::IT_16BIT)
+					meshData->setIndices((UINT16*)indices, mSubMeshes[i].indexCount, i);
+				else
+					meshData->setIndices((UINT32*)indices, mSubMeshes[i].indexCount, i);
+			}
 
 
 			mIndexData->indexBuffer->unlock();
 			mIndexData->indexBuffer->unlock();
 		}
 		}
 
 
 		if(mVertexData)
 		if(mVertexData)
 		{
 		{
-			meshData->vertexCount = mVertexData->vertexCount;
-			
 			auto vertexBuffers = mVertexData->getBuffers();
 			auto vertexBuffers = mVertexData->getBuffers();
 
 
+			UINT32 streamIdx = 0;
 			for(auto iter = vertexBuffers.begin(); iter != vertexBuffers.end() ; ++iter)
 			for(auto iter = vertexBuffers.begin(); iter != vertexBuffers.end() ; ++iter)
 			{
 			{
 				VertexBufferPtr vertexBuffer = iter->second;
 				VertexBufferPtr vertexBuffer = iter->second;
 				UINT32 vertexSize = vertexBuffer->getVertexSize();
 				UINT32 vertexSize = vertexBuffer->getVertexSize();
 				UINT8* vertDataIter = static_cast<UINT8*>(vertexBuffer->lock(GBL_READ_ONLY));
 				UINT8* vertDataIter = static_cast<UINT8*>(vertexBuffer->lock(GBL_READ_ONLY));
 
 
-				std::shared_ptr<MeshData::VertexData> vertexData(new MeshData::VertexData(meshData->vertexCount, iter->first));
-				meshData->vertexBuffers[iter->first] = vertexData;
-
 				UINT32 numElements = mVertexData->vertexDeclaration->getElementCount();
 				UINT32 numElements = mVertexData->vertexDeclaration->getElementCount();
 				for(UINT32 j = 0; j < numElements; j++)
 				for(UINT32 j = 0; j < numElements; j++)
 				{
 				{
 					const VertexElement* element = mVertexData->vertexDeclaration->getElement(j);
 					const VertexElement* element = mVertexData->vertexDeclaration->getElement(j);
-					VertexElementSemantic semantic = element->getSemantic();
+					VertexElementType type = element->getType();
+					VertexElementSemantic semantic = element->getSemantic(); 
+					UINT32 semanticIdx = element->getIndex();
 					UINT32 offset = element->getOffset();
 					UINT32 offset = element->getOffset();
 					UINT32 elemSize = element->getSize();
 					UINT32 elemSize = element->getSize();
 
 
-					UINT8* dest = nullptr;
-					switch(semantic)
-					{
-					case VES_POSITION:
-						vertexData->vertex = new Vector3[meshData->vertexCount];
-						dest = (UINT8*)vertexData->vertex;
-
-						break;
-					case VES_COLOR:
-						vertexData->color = new Color[meshData->vertexCount];
-						dest = (UINT8*)vertexData->color;
-
-						break;
-					case VES_NORMAL:
-						vertexData->normal = new Vector3[meshData->vertexCount];
-						dest = (UINT8*)vertexData->normal;	
-
-						break;
-					case VES_TANGENT:
-						vertexData->tangent = new Vector3[meshData->vertexCount];
-						dest = (UINT8*)vertexData->tangent;	
-
-						break;
-					case VES_BITANGENT:
-						vertexData->bitangent = new Vector3[meshData->vertexCount];
-						dest = (UINT8*)vertexData->bitangent;	
-
-						break;
-					case VES_TEXCOORD:
-						if(element->getIndex() == 0)
-						{
-							vertexData->uv0 = new Vector2[meshData->vertexCount];
-							dest = (UINT8*)vertexData->uv0;	
-						}
-						else if(element->getIndex() == 1)
-						{
-							vertexData->uv1 = new Vector2[meshData->vertexCount];
-							dest = (UINT8*)vertexData->uv1;	
-						}
-
-						break;
-					default:
-						LOGWRN("Vertex declaration contains semantic (" + toString(semantic) + ") but mesh data can't store it.");
-
-						break;
-					}
-
-					if(dest != nullptr)
-					{
-						for(UINT32 k = 0; k < mVertexData->vertexCount; k++)
-							memcpy(&dest[k * elemSize], &vertDataIter[k * vertexSize + offset], elemSize);
-					}
+					UINT8* dest = new UINT8[elemSize * mVertexData->vertexCount];
+					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();
 				vertexBuffer->unlock();
+
+				streamIdx++;
 			}
 			}
-		}		
+		}
 
 
 		asyncOp.completeOperation(meshData);
 		asyncOp.completeOperation(meshData);
 	}
 	}

+ 336 - 32
CamelotCore/Source/CmMeshData.cpp

@@ -3,70 +3,374 @@
 #include "CmVector3.h"
 #include "CmVector3.h"
 #include "CmHardwareBufferManager.h"
 #include "CmHardwareBufferManager.h"
 #include "CmMeshDataRTTI.h"
 #include "CmMeshDataRTTI.h"
+#include "CmVertexDeclaration.h"
+#include "CmException.h"
 
 
 namespace CamelotEngine
 namespace CamelotEngine
 {
 {
-	MeshData::VertexData::VertexData(UINT32 vertexCount, UINT32 streamIdx)
-		:vertex(nullptr), color(nullptr), normal(nullptr), tangent(nullptr), 
-		bitangent(nullptr), uv0(nullptr), uv1(nullptr), 
-		streamIdx(streamIdx), vertexCount(vertexCount)
+	MeshData::MeshData(IndexBuffer::IndexType indexType)
+	   :mIndexType(indexType)
 	{
 	{
+
 	}
 	}
 
 
-	MeshData::VertexData::~VertexData()
+	MeshData::~MeshData()
 	{
 	{
-		if(vertex != nullptr)
-			delete [] vertex;
+		for(auto& vertElems : mVertexData)
+		{
+			for(auto& vertElem : vertElems.second)
+			{
+				if(vertElem.data != nullptr)
+					delete[] vertElem.data;
+			}
+		}
 
 
-		if(color != nullptr)
-			delete [] color;
+		for(auto& indexData : mIndices)
+		{
+			if(indexData.indices != nullptr)
+				delete[] indexData.indices;
+		}
+	}
 
 
-		if(normal != nullptr)
-			delete [] normal;
+	void MeshData::setPositions(Vector2* elements, UINT32 numElements, UINT32 streamIdx)
+	{
+		setVertexElementData(VET_FLOAT2, VES_POSITION, (UINT8*)(elements), numElements, 0, streamIdx);
+	}
 
 
-		if(tangent != nullptr)
-			delete [] tangent;
+	void MeshData::setPositions(Vector3* elements, UINT32 numElements, UINT32 streamIdx)
+	{
+		setVertexElementData(VET_FLOAT3, VES_POSITION, (UINT8*)(elements), numElements, 0, streamIdx);
+	}
 
 
-		if(bitangent != nullptr)
-			delete [] bitangent;
+	void MeshData::setPositions(Vector4* elements, UINT32 numElements, UINT32 streamIdx)
+	{
+		setVertexElementData(VET_FLOAT4, VES_POSITION, (UINT8*)(elements), numElements, 0, streamIdx);
+	}
 
 
-		if(uv0 != nullptr)
-			delete [] uv0;
+	void MeshData::setNormals(Vector3* elements, UINT32 numElements, UINT32 streamIdx)
+	{
+		setVertexElementData(VET_FLOAT3, VES_NORMAL, (UINT8*)(elements), numElements, 0, streamIdx);
+	}
 
 
-		if(uv1 != nullptr)
-			delete [] uv1;
+	void MeshData::setTangents(Vector3* elements, UINT32 numElements, UINT32 streamIdx)
+	{
+		setVertexElementData(VET_FLOAT3, VES_TANGENT, (UINT8*)(elements), numElements, 0, streamIdx);
 	}
 	}
 
 
-	RTTITypeBase* MeshData::VertexData::getRTTIStatic()
+	void MeshData::setTangents(Vector4* elements, UINT32 numElements, UINT32 streamIdx)
 	{
 	{
-		return VertexDataRTTI::instance();
+		setVertexElementData(VET_FLOAT4, VES_TANGENT, (UINT8*)(elements), numElements, 0, streamIdx);
 	}
 	}
 
 
-	RTTITypeBase* MeshData::VertexData::getRTTI() const
+	void MeshData::setBitangents(Vector3* elements, UINT32 numElements, UINT32 streamIdx)
 	{
 	{
-		return getRTTIStatic();
+		setVertexElementData(VET_FLOAT3, VES_BITANGENT, (UINT8*)(elements), numElements, 0, streamIdx);
 	}
 	}
 
 
-	MeshData::MeshData()
-	   :index(nullptr),
-		indexCount(0),
-		vertexCount(0)
+	void MeshData::setUV0(Vector2* elements, UINT32 numElements, UINT32 streamIdx)
 	{
 	{
-		declaration = HardwareBufferManager::instance().createVertexDeclaration();
+		setVertexElementData(VET_FLOAT2, VES_TEXCOORD, (UINT8*)(elements), numElements, 0, streamIdx);
 	}
 	}
 
 
-	MeshData::~MeshData()
+	void MeshData::setUV1(Vector2* elements, UINT32 numElements, UINT32 streamIdx)
+	{
+		setVertexElementData(VET_FLOAT2, VES_TEXCOORD, (UINT8*)(elements), numElements, 1, streamIdx);
+	}
+
+	void MeshData::setColors(Color* elements, UINT32 numElements, UINT32 streamIdx)
+	{
+		setVertexElementData(VET_COLOR, VES_COLOR, (UINT8*)(elements), numElements, 0, streamIdx);
+	}
+
+	void MeshData::setVertexElementData(VertexElementType type, VertexElementSemantic semantic, UINT8* elements, UINT32 numElements, UINT32 semanticIdx, UINT32 streamIdx)
+	{
+		clearIfItExists(type, semantic, semanticIdx, streamIdx);
+
+		if(elements != nullptr)
+		{
+			vector<VertexElementData>::type& elemData = mVertexData[streamIdx];
+
+			VertexElementData newElement(type, semantic, semanticIdx, streamIdx, elements, numElements);
+			elemData.push_back(newElement);
+		}
+	}
+
+	void MeshData::setIndices(UINT32* indices, UINT32 numIndices, UINT32 subMesh)
+	{
+		if(mIndexType != IndexBuffer::IT_32BIT)
+			CM_EXCEPT(InvalidParametersException, "Trying to set 32bit indices but the MeshData was initialized as 16bit.");
+
+		if(subMesh >= mIndices.size())
+			mIndices.resize(subMesh + 1);
+
+		IndexElementData indexData = mIndices[subMesh];
+
+		if(indexData.indices != nullptr)
+			delete[] indexData.indices;
+
+		indexData.indices = (UINT8*)indices;
+		indexData.numIndices = numIndices;
+		indexData.elementSize = getIndexElementSize();
+		indexData.subMesh = subMesh;
+
+		mIndices[subMesh] = indexData;
+	}
+
+	void MeshData::setIndices(UINT16* indices, UINT32 numIndices, UINT32 subMesh)
+	{
+		if(mIndexType != IndexBuffer::IT_16BIT)
+			CM_EXCEPT(InvalidParametersException, "Trying to set 16bit indices but the MeshData was initialized as 32bit.");
+
+		if(subMesh >= mIndices.size())
+			mIndices.resize(subMesh + 1);
+
+		IndexElementData indexData = mIndices[subMesh];
+
+		if(indexData.indices != nullptr)
+			delete[] indexData.indices;
+
+		indexData.indices = (UINT8*)indices;
+		indexData.numIndices = numIndices;
+		indexData.elementSize = getIndexElementSize();
+		indexData.subMesh = subMesh;
+
+		mIndices[subMesh] = indexData;
+	}
+
+	VertexDeclarationPtr MeshData::createDeclaration() const
+	{
+		VertexDeclarationPtr declaration = HardwareBufferManager::instance().createVertexDeclaration();
+
+		for(auto& vertElems : mVertexData)
+		{
+			UINT32 offset = 0;
+			for(auto& vertElem : vertElems.second)
+			{
+				declaration->addElement(vertElems.first, offset, vertElem.element.getType(), vertElem.element.getSemantic(), vertElem.element.getIndex());
+				offset += vertElem.element.getSize();
+			}
+		}
+
+		return declaration;
+	}
+
+	UINT32 MeshData::getNumVertices() const
+	{
+		UINT32 numVertices = 0;
+
+		auto vertElemDataPerStream = mVertexData;
+		MeshData::VertexElementData* firstElemData = nullptr;
+		if(vertElemDataPerStream.size() > 0)
+		{
+			auto vertElemData = vertElemDataPerStream.begin()->second;
+			auto firstVertElem = vertElemData.begin();
+			if(firstVertElem != vertElemData.end())
+			{
+				numVertices = firstVertElem->elementCount;
+			}
+		}
+
+		for(auto& vertElems : mVertexData)
+		{
+			for(auto& vertElem : vertElems.second)
+			{
+				if(vertElem.elementCount != numVertices)
+				{
+					CM_EXCEPT(InvalidParametersException, "All vertex element arrays in MeshData need to be of the same size. Found an array with semantic: " \
+						+ toString(vertElem.element.getSemantic()) + " and element count: " + toString(vertElem.elementCount) + ". This doesn't match with other " \
+						+ "element with semantic: " + toString(firstElemData->element.getSemantic()) + " and element count: " + toString(firstElemData->elementCount));
+				}
+			}
+		}
+
+		return numVertices;
+	}
+
+	UINT32 MeshData::getNumIndices(UINT32 subMesh) const
+	{
+		return mIndices.at(subMesh).numIndices;
+	}
+
+	UINT16* MeshData::getIndices16(UINT32 subMesh) const
+	{
+		return (UINT16*)mIndices.at(subMesh).indices;
+	}
+
+	UINT32* MeshData::getIndices32(UINT32 subMesh) const
+	{
+		return (UINT32*)mIndices.at(subMesh).indices;
+	}
+
+	vector<VertexElement>::type MeshData::getVertexElements() const
+	{
+		vector<VertexElement>::type elements;
+		for(auto& vertElems : mVertexData)
+		{
+			UINT32 offset = 0;
+			for(auto& vertElem : vertElems.second)
+			{
+				elements.push_back(vertElem.element);
+			}
+		}
+
+		return elements;
+	}
+
+	MeshDataPtr MeshData::combine(const vector<MeshDataPtr>::type& elements)
 	{
 	{
-		if(index != nullptr)
-			delete [] index;
+		MeshDataPtr combinedMeshData(new MeshData());
+
+		UINT32 subMeshIndex = 0;
+		vector<VertexElement>::type combinedVertexElements;
+		vector<UINT8*>::type vertexElemData;
+		UINT32 totalVertexCount = 0;
+
+		UINT32 vertexIndexOffset = 0;
+		for(auto& meshData : elements)
+		{
+			for(UINT32 i = 0; i < meshData->getNumSubmeshes(); i++)
+			{
+				UINT32 numIndices = meshData->getNumIndices(i);
+				UINT32* indices = new UINT32[numIndices];
+
+				UINT32* sourceIndices = meshData->getIndices32(i);
+
+				for(UINT32 j = 0; j < numIndices; j++)
+					indices[j] = sourceIndices[j] + vertexIndexOffset;
+
+				combinedMeshData->setIndices(indices, numIndices, subMeshIndex);
+				subMeshIndex++;
+			}
 
 
-		vertexBuffers.clear();
+			UINT32 numVertices = meshData->getNumVertices();
+			totalVertexCount += numVertices;
+			vertexIndexOffset += numVertices;
+		}
+
+		UINT32 vertexOffset = 0;
+		for(auto& meshData : elements)
+		{
+			vector<VertexElement>::type vertexElements = meshData->getVertexElements();
+			UINT32 numVertices = meshData->getNumVertices();
+
+			for(auto& newElement : vertexElements)
+			{
+				INT32 alreadyExistsIdx = -1;
+				UINT32 idx = 0;
+				for(auto& existingElement : combinedVertexElements)
+				{
+					if(newElement == existingElement)
+					{
+						alreadyExistsIdx = idx;
+						break;
+					}
+
+					idx++;
+				}
+
+				if(alreadyExistsIdx == -1)
+				{
+					combinedVertexElements.push_back(newElement);
+					UINT32 newBufferSize = totalVertexCount * newElement.getSize();
+					UINT8* newBuffer = new UINT8[newBufferSize];
+					memset(newBuffer, 0, newBufferSize);
+
+					vertexElemData.push_back(newBuffer);
+					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());
+
+				combinedMeshData->setVertexElementData(newElement.getType(), newElement.getSemantic(), source, numVertices, newElement.getIndex(), newElement.getSource());
+			}
+
+			vertexOffset += meshData->getNumVertices();
+		}
+
+		return combinedMeshData;
+	}
+
+	bool MeshData::hasElement(VertexElementSemantic semantic, UINT32 semanticIdx, UINT32 streamIdx) const
+	{
+		auto elemDataIter = mVertexData.find(streamIdx);
+
+		if(elemDataIter == mVertexData.end())
+			return false;
+
+		const vector<VertexElementData>::type& elemData = elemDataIter->second;
+
+		auto findIter = std::find_if(elemData.begin(), elemData.end(), 
+			[semantic, semanticIdx] (const VertexElementData& x) 
+		{ 
+			return x.element.getSemantic() == semantic && x.element.getIndex() == semanticIdx; 
+		});
+
+		if(findIter != elemData.end())
+			return true;
+
+		return false;
+	}
+
+	void MeshData::clearIfItExists(VertexElementType type, VertexElementSemantic semantic, UINT32 semanticIdx, UINT32 streamIdx)
+	{
+		vector<VertexElementData>::type& elemData = mVertexData[streamIdx];
+
+		auto findIter = std::find_if(elemData.begin(), elemData.end(), 
+			[type, semantic, semanticIdx] (const VertexElementData& x) 
+		{ 
+			return x.element.getSemantic() == semantic && x.element.getIndex() == semanticIdx; 
+		});
+
+		if(findIter != elemData.end())
+		{
+			if(findIter->data != nullptr)
+				delete[] findIter->data;
+
+			elemData.erase(findIter);
+		}
+	}
+
+	MeshData::VertexElementData& MeshData::getVertElemData(VertexElementType type, VertexElementSemantic semantic, UINT32 semanticIdx, UINT32 streamIdx)
+	{
+		vector<VertexElementData>::type& elemData = mVertexData[streamIdx];
+
+		auto findIter = std::find_if(elemData.begin(), elemData.end(), 
+			[type, semantic, semanticIdx] (const VertexElementData& x) 
+		{ 
+			return x.element.getSemantic() == semantic && x.element.getIndex() == semanticIdx; 
+		});
+
+		if(findIter == elemData.end())
+			CM_EXCEPT(InvalidParametersException, "No vertex element of specified type exists.");
+
+		return *findIter;
 	}
 	}
 
 
 	/************************************************************************/
 	/************************************************************************/
 	/* 								SERIALIZATION                      		*/
 	/* 								SERIALIZATION                      		*/
 	/************************************************************************/
 	/************************************************************************/
 
 
+	RTTITypeBase* MeshData::VertexElementData::getRTTIStatic()
+	{
+		return VertexElementDataRTTI::instance();
+	}
+
+	RTTITypeBase* MeshData::VertexElementData::getRTTI() const
+	{
+		return VertexElementData::getRTTIStatic();
+	}
+
+	RTTITypeBase* MeshData::IndexElementData::getRTTIStatic()
+	{
+		return IndexElementDataRTTI::instance();
+	}
+
+	RTTITypeBase* MeshData::IndexElementData::getRTTI() const
+	{
+		return IndexElementData::getRTTIStatic();
+	}
+
 	RTTITypeBase* MeshData::getRTTIStatic()
 	RTTITypeBase* MeshData::getRTTIStatic()
 	{
 	{
 		return MeshDataRTTI::instance();
 		return MeshDataRTTI::instance();

+ 24 - 0
CamelotCore/Source/CmMeshDataRTTI.cpp

@@ -0,0 +1,24 @@
+#include "CmMeshDataRTTI.h"
+
+namespace CamelotEngine
+{
+	void MeshDataRTTI::onSerializationStarted(IReflectable* obj)
+	{
+		MeshData* meshData = static_cast<MeshData*>(obj);
+
+		auto tempData = std::make_shared<TempMeshData>();
+		for(auto vertElems : meshData->mVertexData)
+		{
+			for(auto vertElem : vertElems.second)
+				tempData->vertexElements.push_back(vertElem);
+		}
+
+		meshData->mRTTIData = tempData;
+	}
+
+	void MeshDataRTTI::onSerializationEnded(IReflectable* obj)
+	{
+		MeshData* meshData = static_cast<MeshData*>(obj);
+		meshData->mRTTIData = nullptr;
+	}
+}

+ 8 - 17
CamelotCore/Source/CmMeshManager.cpp

@@ -8,25 +8,16 @@ namespace CamelotEngine
 	{
 	{
 		mNullMeshData = MeshDataPtr(new MeshData());
 		mNullMeshData = MeshDataPtr(new MeshData());
 
 
-		mNullMeshData->indexCount = 3;
-		mNullMeshData->vertexCount = 1;
+		auto indices = new UINT32[3];
+		indices[0] = 0;
+		indices[1] = 0;
+		indices[2] = 0;
 
 
-		mNullMeshData->index = new int[3];
-		mNullMeshData->index[0] = 0;
-		mNullMeshData->index[1] = 0;
-		mNullMeshData->index[2] = 0;
+		auto vertices = new Vector3[1];
+		vertices[0] = Vector3(0, 0, 0);
 
 
-		std::shared_ptr<MeshData::VertexData> vertexData = std::shared_ptr<MeshData::VertexData>(new MeshData::VertexData(1));
-		mNullMeshData->vertexBuffers.insert(std::make_pair(0, vertexData));
-		vertexData->vertex = new Vector3[1];
-		vertexData->vertex[0] = Vector3(0, 0, 0);
-
-		mNullMeshData->declaration->addElement(0, 0, VET_FLOAT3, VES_POSITION);
-
-		MeshData::SubMeshData subMesh;
-		subMesh.indexOffset = 0;
-		subMesh.indexCount = 3;
-		mNullMeshData->subMeshes.push_back(subMesh);
+		mNullMeshData->setPositions(vertices, 3);
+		mNullMeshData->setIndices(indices, 3);
 	}
 	}
 
 
 	MeshManager::~MeshManager()
 	MeshManager::~MeshManager()

+ 0 - 3
CamelotFBXImporter/Include/CmFBXImporter.h

@@ -46,8 +46,5 @@ namespace CamelotEngine
 		MeshDataPtr parseScene(FbxManager* manager, FbxScene* scene);
 		MeshDataPtr parseScene(FbxManager* manager, FbxScene* scene);
 
 
 		MeshDataPtr parseMesh(FbxMesh* mesh, bool createTangentsIfMissing = true);
 		MeshDataPtr parseMesh(FbxMesh* mesh, bool createTangentsIfMissing = true);
-		MeshDataPtr mergeMeshData(vector<MeshDataPtr>::type meshes);
-
-		void initDeclarationForMeshData(MeshDataPtr meshData);
 	};
 	};
 }
 }

+ 97 - 288
CamelotFBXImporter/Source/CmFBXImporter.cpp

@@ -170,7 +170,7 @@ namespace CamelotEngine
 		else if(allMeshes.size() == 1)
 		else if(allMeshes.size() == 1)
 			return allMeshes[0];
 			return allMeshes[0];
 		else
 		else
-			return mergeMeshData(allMeshes);
+			return MeshData::combine(allMeshes);
 	}
 	}
 
 
 	MeshDataPtr FBXImporter::parseMesh(FbxMesh* mesh, bool createTangentsIfMissing)
 	MeshDataPtr FBXImporter::parseMesh(FbxMesh* mesh, bool createTangentsIfMissing)
@@ -188,6 +188,8 @@ namespace CamelotEngine
 		// Count the polygon count of each material
 		// Count the polygon count of each material
 		FbxLayerElementArrayTemplate<int>* lMaterialIndice = NULL;
 		FbxLayerElementArrayTemplate<int>* lMaterialIndice = NULL;
 		FbxGeometryElement::EMappingMode lMaterialMappingMode = FbxGeometryElement::eNone;
 		FbxGeometryElement::EMappingMode lMaterialMappingMode = FbxGeometryElement::eNone;
+		vector<SubMesh>::type subMeshes;
+		vector<UINT32*>::type indices;
 		if (mesh->GetElementMaterial())
 		if (mesh->GetElementMaterial())
 		{
 		{
 			lMaterialIndice = &mesh->GetElementMaterial()->GetIndexArray();
 			lMaterialIndice = &mesh->GetElementMaterial()->GetIndexArray();
@@ -201,23 +203,23 @@ namespace CamelotEngine
 					for (int lPolygonIndex = 0; lPolygonIndex < lPolygonCount; ++lPolygonIndex)
 					for (int lPolygonIndex = 0; lPolygonIndex < lPolygonCount; ++lPolygonIndex)
 					{
 					{
 						const UINT32 lMaterialIndex = (UINT32)lMaterialIndice->GetAt(lPolygonIndex);
 						const UINT32 lMaterialIndex = (UINT32)lMaterialIndice->GetAt(lPolygonIndex);
-						if (meshData->subMeshes.size() < lMaterialIndex + 1)
+						if (subMeshes.size() < lMaterialIndex + 1)
 						{
 						{
-							meshData->subMeshes.resize(lMaterialIndex + 1);
+							subMeshes.resize(lMaterialIndex + 1);
 						}
 						}
 
 
-						meshData->subMeshes[lMaterialIndex].indexCount += 3;
+						subMeshes[lMaterialIndex].indexCount += 3;
 					}
 					}
 
 
-					// Record the offset (how many vertex)
-					const int lMaterialCount = (const int)meshData->subMeshes.size();
+					// Record the offsets and allocate index arrays
+					indices.resize(subMeshes.size());
+					const int lMaterialCount = (const int)subMeshes.size();
 					int lOffset = 0;
 					int lOffset = 0;
 					for (int lIndex = 0; lIndex < lMaterialCount; ++lIndex)
 					for (int lIndex = 0; lIndex < lMaterialCount; ++lIndex)
 					{
 					{
-						meshData->subMeshes[lIndex].indexOffset = lOffset;
-						lOffset += meshData->subMeshes[lIndex].indexCount;
-						// This will be used as counter in the following procedures, reset to zero
-						meshData->subMeshes[lIndex].indexCount = 0;
+						subMeshes[lIndex].indexOffset = lOffset;
+						lOffset += subMeshes[lIndex].indexCount;
+						indices[lIndex] = new UINT32[subMeshes[lIndex].indexCount];
 					}
 					}
 					FBX_ASSERT(lOffset == lPolygonCount * 3);
 					FBX_ASSERT(lOffset == lPolygonCount * 3);
 				}
 				}
@@ -225,8 +227,13 @@ namespace CamelotEngine
 		}
 		}
 
 
 		// All faces will use the same material.
 		// All faces will use the same material.
-		if (meshData->subMeshes.size() == 0)
-			meshData->subMeshes.resize(1);
+		if (subMeshes.size() == 0)
+		{
+			subMeshes.resize(1);
+			indices.resize(1);
+			subMeshes[0].indexCount = lPolygonCount * 3;
+			indices[0] = new UINT32[subMeshes[0].indexCount];
+		}
 
 
 		// Find out which vertex attributes exist
 		// Find out which vertex attributes exist
 		bool allByControlPoint = true;
 		bool allByControlPoint = true;
@@ -324,40 +331,40 @@ namespace CamelotEngine
 		if (!allByControlPoint)
 		if (!allByControlPoint)
 			lPolygonVertexCount = lPolygonCount * 3;
 			lPolygonVertexCount = lPolygonCount * 3;
 
 
-		meshData->indexCount = lPolygonCount * 3;
-		meshData->vertexCount = lPolygonVertexCount;
-		
-		meshData->index = new int[lPolygonCount * 3];
-
-		std::shared_ptr<MeshData::VertexData> vertexData = std::shared_ptr<MeshData::VertexData>(new MeshData::VertexData(lPolygonVertexCount));
-		meshData->vertexBuffers.insert(std::make_pair(0, vertexData));
-		vertexData->vertex = new Vector3[lPolygonVertexCount];
+		UINT32 vertexCount = lPolygonVertexCount;
+		Vector3* vertex = new Vector3[vertexCount];
 
 
+		Color* color = nullptr;
 		if(hasColor)
 		if(hasColor)
-			vertexData->color = new Color[lPolygonVertexCount];
+			color = new Color[vertexCount];
 
 
+		Vector3* normal = nullptr;
 		if (hasNormal)
 		if (hasNormal)
-			vertexData->normal = new Vector3[lPolygonVertexCount];
+			normal = new Vector3[vertexCount];
 
 
+		Vector3* tangent = nullptr;
 		if (hasTangent)
 		if (hasTangent)
-			vertexData->tangent = new Vector3[lPolygonVertexCount];
+			tangent = new Vector3[vertexCount];
 
 
+		Vector3* bitangent = nullptr;
 		if (hasBitangent)
 		if (hasBitangent)
-			vertexData->bitangent = new Vector3[lPolygonVertexCount];
+			bitangent = new Vector3[vertexCount];
 
 
 		FbxStringList lUVNames;
 		FbxStringList lUVNames;
 		mesh->GetUVSetNames(lUVNames);
 		mesh->GetUVSetNames(lUVNames);
 		const char * lUVName0 = NULL;
 		const char * lUVName0 = NULL;
+		Vector2* uv0 = nullptr;
 		if (hasUV0 && lUVNames.GetCount() > 0)
 		if (hasUV0 && lUVNames.GetCount() > 0)
 		{
 		{
-			vertexData->uv0 = new Vector2[lPolygonVertexCount];
+			uv0 = new Vector2[vertexCount];
 			lUVName0 = lUVNames[0];
 			lUVName0 = lUVNames[0];
 		}
 		}
 
 
 		const char * lUVName1 = NULL;
 		const char * lUVName1 = NULL;
+		Vector2* uv1 = nullptr;
 		if (hasUV1 && lUVNames.GetCount() > 1)
 		if (hasUV1 && lUVNames.GetCount() > 1)
 		{
 		{
-			vertexData->uv1 = new Vector2[lPolygonVertexCount];
+			uv1 = new Vector2[vertexCount];
 			lUVName1 = lUVNames[1];
 			lUVName1 = lUVNames[1];
 		}
 		}
 
 
@@ -397,9 +404,9 @@ namespace CamelotEngine
 			{
 			{
 				// Save the vertex position.
 				// Save the vertex position.
 				lCurrentVertex = lControlPoints[lIndex];
 				lCurrentVertex = lControlPoints[lIndex];
-				vertexData->vertex[lIndex][0] = static_cast<float>(lCurrentVertex[0]);
-				vertexData->vertex[lIndex][1] = static_cast<float>(lCurrentVertex[1]);
-				vertexData->vertex[lIndex][2] = static_cast<float>(lCurrentVertex[2]);
+				vertex[lIndex][0] = static_cast<float>(lCurrentVertex[0]);
+				vertex[lIndex][1] = static_cast<float>(lCurrentVertex[1]);
+				vertex[lIndex][2] = static_cast<float>(lCurrentVertex[2]);
 
 
 				// Save vertex color
 				// Save vertex color
 				if(hasColor)
 				if(hasColor)
@@ -409,10 +416,10 @@ namespace CamelotEngine
 						lColorIndex = lColorElement->GetIndexArray().GetAt(lIndex);
 						lColorIndex = lColorElement->GetIndexArray().GetAt(lIndex);
 
 
 					FbxColor lCurrentColor = lColorElement->GetDirectArray().GetAt(lColorIndex);
 					FbxColor lCurrentColor = lColorElement->GetDirectArray().GetAt(lColorIndex);
-					vertexData->color[lIndex][0] = static_cast<float>(lCurrentColor[0]);
-					vertexData->color[lIndex][1] = static_cast<float>(lCurrentColor[1]);
-					vertexData->color[lIndex][2] = static_cast<float>(lCurrentColor[2]);
-					vertexData->color[lIndex][3] = static_cast<float>(lCurrentColor[3]);
+					color[lIndex][0] = static_cast<float>(lCurrentColor[0]);
+					color[lIndex][1] = static_cast<float>(lCurrentColor[1]);
+					color[lIndex][2] = static_cast<float>(lCurrentColor[2]);
+					color[lIndex][3] = static_cast<float>(lCurrentColor[3]);
 				}
 				}
 
 
 				// Save the normal.
 				// Save the normal.
@@ -423,9 +430,9 @@ namespace CamelotEngine
 						lNormalIndex = lNormalElement->GetIndexArray().GetAt(lIndex);
 						lNormalIndex = lNormalElement->GetIndexArray().GetAt(lIndex);
 
 
 					lCurrentNormal = lNormalElement->GetDirectArray().GetAt(lNormalIndex);
 					lCurrentNormal = lNormalElement->GetDirectArray().GetAt(lNormalIndex);
-					vertexData->normal[lIndex][0] = static_cast<float>(lCurrentNormal[0]);
-					vertexData->normal[lIndex][1] = static_cast<float>(lCurrentNormal[1]);
-					vertexData->normal[lIndex][2] = static_cast<float>(lCurrentNormal[2]);
+					normal[lIndex][0] = static_cast<float>(lCurrentNormal[0]);
+					normal[lIndex][1] = static_cast<float>(lCurrentNormal[1]);
+					normal[lIndex][2] = static_cast<float>(lCurrentNormal[2]);
 				}
 				}
 
 
 				// Save the tangent.
 				// Save the tangent.
@@ -436,12 +443,12 @@ namespace CamelotEngine
 						lTangentIndex = lTangentElement->GetIndexArray().GetAt(lIndex);
 						lTangentIndex = lTangentElement->GetIndexArray().GetAt(lIndex);
 
 
 					FbxVector4 lCurrentTangent = lTangentElement->GetDirectArray().GetAt(lTangentIndex);
 					FbxVector4 lCurrentTangent = lTangentElement->GetDirectArray().GetAt(lTangentIndex);
-					vertexData->tangent[lIndex][0] = static_cast<float>(lCurrentTangent[0]);
-					vertexData->tangent[lIndex][1] = static_cast<float>(lCurrentTangent[1]);
-					vertexData->tangent[lIndex][2] = static_cast<float>(lCurrentTangent[2]);
+					tangent[lIndex][0] = static_cast<float>(lCurrentTangent[0]);
+					tangent[lIndex][1] = static_cast<float>(lCurrentTangent[1]);
+					tangent[lIndex][2] = static_cast<float>(lCurrentTangent[2]);
 				}
 				}
 
 
-				// Save the tangent.
+				// Save the bitangent.
 				if (hasBitangent)
 				if (hasBitangent)
 				{
 				{
 					int lBitangentIndex = lIndex;
 					int lBitangentIndex = lIndex;
@@ -449,9 +456,9 @@ namespace CamelotEngine
 						lBitangentIndex = lBitangentElement->GetIndexArray().GetAt(lIndex);
 						lBitangentIndex = lBitangentElement->GetIndexArray().GetAt(lIndex);
 
 
 					FbxVector4 lCurrentBitangent = lBitangentElement->GetDirectArray().GetAt(lBitangentIndex);
 					FbxVector4 lCurrentBitangent = lBitangentElement->GetDirectArray().GetAt(lBitangentIndex);
-					vertexData->bitangent[lIndex][0] = static_cast<float>(lCurrentBitangent[0]);
-					vertexData->bitangent[lIndex][1] = static_cast<float>(lCurrentBitangent[1]);
-					vertexData->bitangent[lIndex][2] = static_cast<float>(lCurrentBitangent[2]);
+					bitangent[lIndex][0] = static_cast<float>(lCurrentBitangent[0]);
+					bitangent[lIndex][1] = static_cast<float>(lCurrentBitangent[1]);
+					bitangent[lIndex][2] = static_cast<float>(lCurrentBitangent[2]);
 				}
 				}
 
 
 				// Save the UV.
 				// Save the UV.
@@ -462,8 +469,8 @@ namespace CamelotEngine
 						lUVIndex = lUVElement0->GetIndexArray().GetAt(lIndex);
 						lUVIndex = lUVElement0->GetIndexArray().GetAt(lIndex);
 
 
 					lCurrentUV = lUVElement0->GetDirectArray().GetAt(lUVIndex);
 					lCurrentUV = lUVElement0->GetDirectArray().GetAt(lUVIndex);
-					vertexData->uv0[lIndex][0] = static_cast<float>(lCurrentUV[0]);
-					vertexData->uv0[lIndex][1] = static_cast<float>(lCurrentUV[1]);
+					uv0[lIndex][0] = static_cast<float>(lCurrentUV[0]);
+					uv0[lIndex][1] = static_cast<float>(lCurrentUV[1]);
 				}
 				}
 
 
 				if (hasUV1)
 				if (hasUV1)
@@ -473,13 +480,16 @@ namespace CamelotEngine
 						lUVIndex = lUVElement1->GetIndexArray().GetAt(lIndex);
 						lUVIndex = lUVElement1->GetIndexArray().GetAt(lIndex);
 
 
 					lCurrentUV = lUVElement1->GetDirectArray().GetAt(lUVIndex);
 					lCurrentUV = lUVElement1->GetDirectArray().GetAt(lUVIndex);
-					vertexData->uv1[lIndex][0] = static_cast<float>(lCurrentUV[0]);
-					vertexData->uv1[lIndex][1] = static_cast<float>(lCurrentUV[1]);
+					uv1[lIndex][0] = static_cast<float>(lCurrentUV[0]);
+					uv1[lIndex][1] = static_cast<float>(lCurrentUV[1]);
 				}
 				}
 			}
 			}
 		}
 		}
 
 
 		int lVertexCount = 0;
 		int lVertexCount = 0;
+		vector<UINT32>::type indexOffsetPerSubmesh;
+		indexOffsetPerSubmesh.resize(subMeshes.size(), 0);
+
 		for (int lPolygonIndex = 0; lPolygonIndex < lPolygonCount; ++lPolygonIndex)
 		for (int lPolygonIndex = 0; lPolygonIndex < lPolygonCount; ++lPolygonIndex)
 		{
 		{
 			// The material for current face.
 			// The material for current face.
@@ -490,24 +500,24 @@ namespace CamelotEngine
 			}
 			}
 
 
 			// Where should I save the vertex attribute index, according to the material
 			// Where should I save the vertex attribute index, according to the material
-			const int lIndexOffset = meshData->subMeshes[lMaterialIndex].indexOffset + meshData->subMeshes[lMaterialIndex].indexCount;
+			int lIndexOffset = subMeshes[lMaterialIndex].indexOffset + indexOffsetPerSubmesh[lMaterialIndex];
 			for (int lVerticeIndex = 0; lVerticeIndex < 3; ++lVerticeIndex)
 			for (int lVerticeIndex = 0; lVerticeIndex < 3; ++lVerticeIndex)
 			{
 			{
 				const int lControlPointIndex = mesh->GetPolygonVertex(lPolygonIndex, lVerticeIndex);
 				const int lControlPointIndex = mesh->GetPolygonVertex(lPolygonIndex, lVerticeIndex);
 
 
 				if (allByControlPoint)
 				if (allByControlPoint)
 				{
 				{
-					meshData->index[lIndexOffset + lVerticeIndex] = static_cast<unsigned int>(lControlPointIndex);
+					indices[lMaterialIndex][lIndexOffset + lVerticeIndex] = static_cast<unsigned int>(lControlPointIndex);
 				}
 				}
 				// Populate the array with vertex attribute, if by polygon vertex.
 				// Populate the array with vertex attribute, if by polygon vertex.
 				else
 				else
 				{
 				{
-					meshData->index[lIndexOffset + lVerticeIndex] = static_cast<unsigned int>(lVertexCount);
+					indices[lMaterialIndex][lIndexOffset + lVerticeIndex] = static_cast<unsigned int>(lVertexCount);
 
 
 					lCurrentVertex = lControlPoints[lControlPointIndex];
 					lCurrentVertex = lControlPoints[lControlPointIndex];
-					vertexData->vertex[lVertexCount][0] = static_cast<float>(lCurrentVertex[0]);
-					vertexData->vertex[lVertexCount][1] = static_cast<float>(lCurrentVertex[1]);
-					vertexData->vertex[lVertexCount][2] = static_cast<float>(lCurrentVertex[2]);
+					vertex[lVertexCount][0] = static_cast<float>(lCurrentVertex[0]);
+					vertex[lVertexCount][1] = static_cast<float>(lCurrentVertex[1]);
+					vertex[lVertexCount][2] = static_cast<float>(lCurrentVertex[2]);
 
 
 					if(hasColor)
 					if(hasColor)
 					{
 					{
@@ -516,18 +526,18 @@ namespace CamelotEngine
 							lColorIndex = lColorElement->GetIndexArray().GetAt(lColorIndex);
 							lColorIndex = lColorElement->GetIndexArray().GetAt(lColorIndex);
 
 
 						FbxColor lCurrentColor = lColorElement->GetDirectArray().GetAt(lColorIndex);
 						FbxColor lCurrentColor = lColorElement->GetDirectArray().GetAt(lColorIndex);
-						vertexData->color[lVertexCount][0] = static_cast<float>(lCurrentColor[0]);
-						vertexData->color[lVertexCount][1] = static_cast<float>(lCurrentColor[1]);
-						vertexData->color[lVertexCount][2] = static_cast<float>(lCurrentColor[2]);
-						vertexData->color[lVertexCount][3] = static_cast<float>(lCurrentColor[3]);
+						color[lVertexCount][0] = static_cast<float>(lCurrentColor[0]);
+						color[lVertexCount][1] = static_cast<float>(lCurrentColor[1]);
+						color[lVertexCount][2] = static_cast<float>(lCurrentColor[2]);
+						color[lVertexCount][3] = static_cast<float>(lCurrentColor[3]);
 					}
 					}
 
 
 					if (hasNormal)
 					if (hasNormal)
 					{
 					{
 						mesh->GetPolygonVertexNormal(lPolygonIndex, lVerticeIndex, lCurrentNormal);
 						mesh->GetPolygonVertexNormal(lPolygonIndex, lVerticeIndex, lCurrentNormal);
-						vertexData->normal[lVertexCount][0] = static_cast<float>(lCurrentNormal[0]);
-						vertexData->normal[lVertexCount][1] = static_cast<float>(lCurrentNormal[1]);
-						vertexData->normal[lVertexCount][2] = static_cast<float>(lCurrentNormal[2]);
+						normal[lVertexCount][0] = static_cast<float>(lCurrentNormal[0]);
+						normal[lVertexCount][1] = static_cast<float>(lCurrentNormal[1]);
+						normal[lVertexCount][2] = static_cast<float>(lCurrentNormal[2]);
 					}
 					}
 
 
 					if (hasTangent)
 					if (hasTangent)
@@ -537,9 +547,9 @@ namespace CamelotEngine
 							lTangentIndex = lTangentElement->GetIndexArray().GetAt(lTangentIndex);
 							lTangentIndex = lTangentElement->GetIndexArray().GetAt(lTangentIndex);
 
 
 						FbxVector4 lCurrentTangent = lTangentElement->GetDirectArray().GetAt(lTangentIndex);
 						FbxVector4 lCurrentTangent = lTangentElement->GetDirectArray().GetAt(lTangentIndex);
-						vertexData->tangent[lVertexCount][0] = static_cast<float>(lCurrentTangent[0]);
-						vertexData->tangent[lVertexCount][1] = static_cast<float>(lCurrentTangent[1]);
-						vertexData->tangent[lVertexCount][2] = static_cast<float>(lCurrentTangent[2]);
+						tangent[lVertexCount][0] = static_cast<float>(lCurrentTangent[0]);
+						tangent[lVertexCount][1] = static_cast<float>(lCurrentTangent[1]);
+						tangent[lVertexCount][2] = static_cast<float>(lCurrentTangent[2]);
 					}
 					}
 
 
 					if (hasBitangent)
 					if (hasBitangent)
@@ -549,257 +559,56 @@ namespace CamelotEngine
 							lBitangentIndex = lBitangentElement->GetIndexArray().GetAt(lBitangentIndex);
 							lBitangentIndex = lBitangentElement->GetIndexArray().GetAt(lBitangentIndex);
 
 
 						FbxVector4 lCurrentBitangent = lBitangentElement->GetDirectArray().GetAt(lBitangentIndex);
 						FbxVector4 lCurrentBitangent = lBitangentElement->GetDirectArray().GetAt(lBitangentIndex);
-						vertexData->bitangent[lVertexCount][0] = static_cast<float>(lCurrentBitangent[0]);
-						vertexData->bitangent[lVertexCount][1] = static_cast<float>(lCurrentBitangent[1]);
-						vertexData->bitangent[lVertexCount][2] = static_cast<float>(lCurrentBitangent[2]);
+						bitangent[lVertexCount][0] = static_cast<float>(lCurrentBitangent[0]);
+						bitangent[lVertexCount][1] = static_cast<float>(lCurrentBitangent[1]);
+						bitangent[lVertexCount][2] = static_cast<float>(lCurrentBitangent[2]);
 					}
 					}
 
 
 					if (hasUV0)
 					if (hasUV0)
 					{
 					{
 						mesh->GetPolygonVertexUV(lPolygonIndex, lVerticeIndex, lUVName0, lCurrentUV);
 						mesh->GetPolygonVertexUV(lPolygonIndex, lVerticeIndex, lUVName0, lCurrentUV);
-						vertexData->uv0[lVertexCount][0] = static_cast<float>(lCurrentUV[0]);
-						vertexData->uv0[lVertexCount][1] = static_cast<float>(lCurrentUV[1]);
+						uv0[lVertexCount][0] = static_cast<float>(lCurrentUV[0]);
+						uv0[lVertexCount][1] = static_cast<float>(lCurrentUV[1]);
 					}
 					}
 
 
 					if (hasUV1)
 					if (hasUV1)
 					{
 					{
 						mesh->GetPolygonVertexUV(lPolygonIndex, lVerticeIndex, lUVName1, lCurrentUV);
 						mesh->GetPolygonVertexUV(lPolygonIndex, lVerticeIndex, lUVName1, lCurrentUV);
-						vertexData->uv1[lVertexCount][0] = static_cast<float>(lCurrentUV[0]);
-						vertexData->uv1[lVertexCount][1] = static_cast<float>(lCurrentUV[1]);
+						uv1[lVertexCount][0] = static_cast<float>(lCurrentUV[0]);
+						uv1[lVertexCount][1] = static_cast<float>(lCurrentUV[1]);
 					}
 					}
 				}
 				}
 				++lVertexCount;
 				++lVertexCount;
 			}
 			}
 
 
-			meshData->subMeshes[lMaterialIndex].indexCount += 3;
+			indexOffsetPerSubmesh[lMaterialIndex] += 3;
 		}
 		}
 
 
-		initDeclarationForMeshData(meshData);
+		if(vertex != nullptr)
+			meshData->setPositions(vertex, vertexCount);
 
 
-		return meshData;
-	}
+		if(color != nullptr)
+			meshData->setColors(color, vertexCount);
 
 
-	void FBXImporter::initDeclarationForMeshData(MeshDataPtr meshData)
-	{
-		std::shared_ptr<MeshData::VertexData> vertexData = meshData->vertexBuffers[0];
+		if(normal != nullptr)
+			meshData->setNormals(normal, vertexCount);
 
 
-		UINT32 offset = 0;
-		if(vertexData->vertex)
-		{
-			meshData->declaration->addElement(0, offset, VET_FLOAT3, VES_POSITION, 0);
-			offset += VertexElement::getTypeSize(VET_FLOAT3);
-		}
+		if(tangent != nullptr)
+			meshData->setTangents(tangent, vertexCount);
 
 
-		if(vertexData->color)
-		{
-			meshData->declaration->addElement(0, offset, VET_COLOR, VES_COLOR, 0);
-			offset += VertexElement::getTypeSize(VET_COLOR);
-		}
+		if(bitangent != nullptr)
+			meshData->setBitangents(bitangent, vertexCount);
 
 
-		if(vertexData->normal)
-		{
-			meshData->declaration->addElement(0, offset, VET_FLOAT3, VES_NORMAL, 0);
-			offset += VertexElement::getTypeSize(VET_FLOAT3);
-		}
-
-		if(vertexData->tangent)
-		{
-			meshData->declaration->addElement(0, offset, VET_FLOAT3, VES_TANGENT, 0);
-			offset += VertexElement::getTypeSize(VET_FLOAT3);
-		}
-
-		// TODO - Storing bitangents with the mesh is probably not a good idea. It's likely cheaper to recreate them in the shader
-		if(vertexData->bitangent)
-		{
-			meshData->declaration->addElement(0, offset, VET_FLOAT3, VES_BITANGENT, 0);
-			offset += VertexElement::getTypeSize(VET_FLOAT3);
-		}
+		if(uv0 != nullptr)
+			meshData->setUV0(uv0, vertexCount);
 
 
-		if(vertexData->uv0)
-		{
-			meshData->declaration->addElement(0, offset, VET_FLOAT2, VES_TEXCOORD, 0);
-			offset += VertexElement::getTypeSize(VET_FLOAT2);
-		}
+		if(uv1 != nullptr)
+			meshData->setUV1(uv1, vertexCount);
 
 
-		if(vertexData->uv1)
+		for(size_t i = 0; i < subMeshes.size(); i++)
 		{
 		{
-			meshData->declaration->addElement(0, offset, VET_FLOAT2, VES_TEXCOORD, 1);
-			offset += VertexElement::getTypeSize(VET_FLOAT2);
+			meshData->setIndices(indices[i], subMeshes[i].indexCount, (UINT32)i);
 		}
 		}
-	}
-
-	MeshDataPtr FBXImporter::mergeMeshData(vector<MeshDataPtr>::type meshes)
-	{
-		// TODO Low priority - Throughout this method we're assuming mesh data only has a single stream, which is a fair assumption now, but that might change later.
-
-		MeshDataPtr meshData = MeshDataPtr(new MeshData());
-
-		bool hasPosition = false;
-		bool hasColors = false;
-		bool hasNormals = false;
-		bool hasTangents = false;
-		bool hasBitangents = false;
-		bool hasUV0 = false;
-		bool hasUV1 = false;
-
-		// Count all vertices and indexes. And determine all data types.
-		for(auto iter = meshes.begin(); iter != meshes.end(); ++iter)
-		{
-			meshData->indexCount += (*iter)->indexCount;
-			meshData->vertexCount += (*iter)->vertexCount;
-
-			std::shared_ptr<MeshData::VertexData> vertData = (*iter)->vertexBuffers[0];
-			if(vertData)
-			{
-				if(vertData->vertex)
-					hasPosition = true;
-
-				if(vertData->color)
-					hasColors = true;
-
-				if(vertData->normal)
-					hasNormals = true;
-
-				if(vertData->tangent)
-					hasTangents = true;
-
-				if(vertData->bitangent)
-					hasBitangents = true;
-
-				if(vertData->uv0)
-					hasUV0 = true;
-
-				if(vertData->uv1)
-					hasUV1 = true;
-			}
-		}
-
-		// Copy indices
-		meshData->index = new int[meshData->indexCount];
-
-		int currentIndexIdx = 0;
-		int currentVertIdx = 0;
-		for(auto iter = meshes.begin(); iter != meshes.end(); ++iter)
-		{
-			int indexCount = (*iter)->indexCount;
-
-			for(int i = 0; i < indexCount; i++)
-				meshData->index[currentIndexIdx + i] = (*iter)->index[i] + currentVertIdx;
-
-			currentIndexIdx += indexCount;
-			currentVertIdx += (*iter)->vertexCount;
-		}
-
-		// Copy vertex data
-		std::shared_ptr<MeshData::VertexData> combinedVertData(new MeshData::VertexData(meshData->vertexCount, 0));
-		meshData->vertexBuffers[0] = combinedVertData;
-
-		if(hasPosition)
-			combinedVertData->vertex = new Vector3[meshData->vertexCount];
-
-		if(hasColors)
-			combinedVertData->color = new Color[meshData->vertexCount];
-
-		if(hasNormals)
-			combinedVertData->normal = new Vector3[meshData->vertexCount];
-
-		if(hasTangents)
-			combinedVertData->tangent = new Vector3[meshData->vertexCount];
-
-		if(hasBitangents)
-			combinedVertData->bitangent = new Vector3[meshData->vertexCount];
-
-		if(hasUV0)
-			combinedVertData->uv0 = new Vector2[meshData->vertexCount];
-
-		if(hasUV1)
-			combinedVertData->uv1 = new Vector2[meshData->vertexCount];
-
-		currentVertIdx = 0;
-		for(auto iter = meshes.begin(); iter != meshes.end(); ++iter)
-		{
-			int indexCount = (*iter)->indexCount;
-
-			std::shared_ptr<MeshData::VertexData> vertData = (*iter)->vertexBuffers[0];
-
-			if(hasPosition)
-			{
-				if(vertData && vertData->vertex)
-					memcpy(&combinedVertData->vertex[currentVertIdx], vertData->vertex, (*iter)->vertexCount * sizeof(Vector3));
-				else
-					memset(&combinedVertData->vertex[currentVertIdx], 0, (*iter)->vertexCount * sizeof(Vector3));
-			}
-
-			if(hasColors)
-			{
-				if(vertData && vertData->color)
-					memcpy(&combinedVertData->color[currentVertIdx], vertData->color, (*iter)->vertexCount * sizeof(Color));
-				else
-					memset(&combinedVertData->color[currentVertIdx], 0, (*iter)->vertexCount * sizeof(Color));
-			}
-
-			if(hasNormals)
-			{
-				if(vertData && vertData->normal)
-					memcpy(&combinedVertData->normal[currentVertIdx], vertData->normal, (*iter)->vertexCount * sizeof(Vector3));
-				else
-					memset(&combinedVertData->normal[currentVertIdx], 0, (*iter)->vertexCount * sizeof(Vector3));
-			}
-
-			if(hasTangents)
-			{
-				if(vertData && vertData->tangent)
-					memcpy(&combinedVertData->tangent[currentVertIdx], vertData->tangent, (*iter)->vertexCount * sizeof(Vector3));
-				else
-					memset(&combinedVertData->tangent[currentVertIdx], 0, (*iter)->vertexCount * sizeof(Vector3));
-			}
-
-			if(hasBitangents)
-			{
-				if(vertData && vertData->bitangent)
-					memcpy(&combinedVertData->bitangent[currentVertIdx], vertData->bitangent, (*iter)->vertexCount * sizeof(Vector3));
-				else
-					memset(&combinedVertData->bitangent[currentVertIdx], 0, (*iter)->vertexCount * sizeof(Vector3));
-			}
-
-			if(hasUV0)
-			{
-				if(vertData && vertData->uv0)
-					memcpy(&combinedVertData->uv0[currentVertIdx], vertData->uv0, (*iter)->vertexCount * sizeof(Vector2));
-				else
-					memset(&combinedVertData->uv0[currentVertIdx], 0, (*iter)->vertexCount * sizeof(Vector2));
-			}
-
-			if(hasUV1)
-			{
-				if(vertData && vertData->uv1)
-					memcpy(&combinedVertData->uv1[currentVertIdx], vertData->uv1, (*iter)->vertexCount * sizeof(Vector2));
-				else
-					memset(&combinedVertData->uv1[currentVertIdx], 0, (*iter)->vertexCount * sizeof(Vector2));
-			}
-
-			currentVertIdx += (*iter)->vertexCount;
-		}
-
-		// Copy submesh data
-		currentIndexIdx = 0;
-		for(auto iter = meshes.begin(); iter != meshes.end(); ++iter)
-		{
-			UINT32 subMeshCount = (UINT32)(*iter)->subMeshes.size();
-
-			for(UINT32 i = 0; i < subMeshCount; i++)
-			{
-				MeshData::SubMeshData newSubMesh;
-				newSubMesh.indexCount = (*iter)->subMeshes[i].indexCount;
-				newSubMesh.indexOffset = (*iter)->subMeshes[i].indexOffset + currentIndexIdx;
-
-				meshData->subMeshes.push_back(newSubMesh);
-			}
-
-			currentIndexIdx += (*iter)->indexCount;
-		}
-
-		initDeclarationForMeshData(meshData);
 
 
 		return meshData;
 		return meshData;
 	}
 	}

+ 1 - 0
CamelotUtility/Include/CmStdHeaders.h

@@ -27,6 +27,7 @@
 #include <cmath>
 #include <cmath>
 
 
 #include <memory>
 #include <memory>
+#include <boost/shared_array.hpp>
 
 
 // STL containers
 // STL containers
 #include <vector>
 #include <vector>

+ 0 - 12
TODO.txt

@@ -27,22 +27,10 @@ Add 0.5 offset to GUI shader (depending on render system)
 Add transparency to GUI shader
 Add transparency to GUI shader
 TextSprite needs to return multiple buffers in case characters are from different pages
 TextSprite needs to return multiple buffers in case characters are from different pages
 
 
-
 Mesh usability overhaul:
 Mesh usability overhaul:
- I need to be able to initialize Mesh without manually populating MeshData because it's very inconvenient
- I need to be able to provide non-fixed vertex data. Right now for example VertexData only accepts Vector3 as vertex data. While for UI stuff I need Vector2.
  A way to clear a mesh  (Mesh.Clear)
  A way to clear a mesh  (Mesh.Clear)
  A way to update mesh buffers without recreating vertex/index buffers (Setting data currently does exactly that)
  A way to update mesh buffers without recreating vertex/index buffers (Setting data currently does exactly that)
 
 
-Mesh
- -> Make sure MeshData can use 16bit index buffers, and variable size elements (not just limited for Vector3 for position for example)
- -> Make sure buffers aren't re-created each time SetMeshData is called. Instead clear existing buffers and update them. Possibly delete extra sub-mesh buffers.
- -> setVertices(data, num, stream = 0, submesh = 0)
- -> setVertices2D(data, num, stream = 0, submesh = 0)
- -> setUV(data, num, stream = 0, submesh = 0)
- - > similar methods for Normal, Color, Tangent Bitangent, UV1 and indices
- -> make MeshData.index a UINT32* ptr
-
  Names: TextMesh & SpriteMesh instead of 2DText and 2DSprite!
  Names: TextMesh & SpriteMesh instead of 2DText and 2DSprite!
 
 
 -----------------------IMMEDIATE TODO---------------------------------------------------------------
 -----------------------IMMEDIATE TODO---------------------------------------------------------------