Browse Source

Better way of initializing MeshData

Marko Pintera 12 years ago
parent
commit
404bcd6671

+ 2 - 0
BansheeEngine/Include/BsDrawHelper2D.h

@@ -115,6 +115,8 @@ namespace BansheeEngine
 	private:
 		DebugDraw2DClipSpaceMatInfo mMaterial2DClipSpace;
 
+		CM::VertexDataDescPtr mVertexDesc;
+
 		CM::FRect normalizedCoordToClipSpace(const CM::FRect& area) const;
 		CM::Vector2 normalizedCoordToClipSpace(const CM::Vector2& pos) const;
 

+ 4 - 0
BansheeEngine/Include/BsDrawHelper3D.h

@@ -11,6 +11,8 @@ namespace BansheeEngine
 	class BS_EXPORT DrawHelper3D : public DrawHelperTemplate<CM::Vector3>, public CM::Module<DrawHelper3D>
 	{
 	public:
+		DrawHelper3D();
+
 		/**
 		 * @brief	Fills the mesh data with vertices representing an axis aligned box.
 		 *
@@ -111,6 +113,8 @@ namespace BansheeEngine
 		void drawAABox(const HCamera& camera, const CM::AABox& box, const CM::Color& color = CM::Color::White, float timeout = 0.0f);
 
 	private:
+		CM::VertexDataDescPtr mVertexDesc;
+		
 		CM::Vector3 calcCenter(CM::UINT8* vertices, CM::UINT32 numVertices, CM::UINT32 vertexStride);
 
 	protected:

+ 4 - 4
BansheeEngine/Include/BsDrawHelperTemplate.h

@@ -62,7 +62,7 @@ namespace BansheeEngine
 			assert((vertexOffset + 2) <= meshData->getNumVertices());
 			assert((indexOffset + 2) <= meshData->getNumIndices());
 
-			line_Pixel(a, b, color, positionData, colorData, vertexOffset, meshData->getVertexStride(), indexData, indexOffset);
+			line_Pixel(a, b, color, positionData, colorData, vertexOffset, meshData->getVertexDesc()->getVertexStride(), indexData, indexOffset);
 		}
 
 		void line_AA(const T& a, const T& b, float width, float borderWidth, const CM::Color& color, const CM::MeshDataPtr& meshData, CM::UINT32 vertexOffset, CM::UINT32 indexOffset)
@@ -74,7 +74,7 @@ namespace BansheeEngine
 			assert((vertexOffset + 8) <= meshData->getNumVertices());
 			assert((indexOffset + 30) <= meshData->getNumIndices());
 
-			line_AA(a, b, width, borderWidth, color, positionData, colorData, vertexOffset, meshData->getVertexStride(), indexData, indexOffset);
+			line_AA(a, b, width, borderWidth, color, positionData, colorData, vertexOffset, meshData->getVertexDesc()->getVertexStride(), indexData, indexOffset);
 		}
 
 		void lineList_Pixel(const typename CM::Vector<T>::type& linePoints, const CM::Color& color, const CM::MeshDataPtr& meshData, CM::UINT32 vertexOffset, CM::UINT32 indexOffset)
@@ -94,7 +94,7 @@ namespace BansheeEngine
 			UINT32 numPoints = (UINT32)linePoints.size();
 			for(UINT32 i = 0; i < numPoints; i += 2)
 			{
-				line_Pixel(linePoints[i], linePoints[i + 1], color, positionData, colorData, curVertOffset, meshData->getVertexStride(), indexData, curIdxOffset);
+				line_Pixel(linePoints[i], linePoints[i + 1], color, positionData, colorData, curVertOffset, meshData->getVertexDesc()->getVertexStride(), indexData, curIdxOffset);
 
 				curVertOffset += 2;
 				curIdxOffset += 2;
@@ -118,7 +118,7 @@ namespace BansheeEngine
 			UINT32 numPoints = (UINT32)linePoints.size();
 			for(UINT32 i = 0; i < numPoints; i += 2)
 			{
-				line_AA(linePoints[i], linePoints[i + 1], width, borderWidth, color, positionData, colorData, curVertOffset, meshData->getVertexStride(), indexData, curIdxOffset);
+				line_AA(linePoints[i], linePoints[i + 1], width, borderWidth, color, positionData, colorData, curVertOffset, meshData->getVertexDesc()->getVertexStride(), indexData, curIdxOffset);
 
 				curVertOffset += 8;
 				curIdxOffset += 30;

+ 2 - 0
BansheeEngine/Include/BsGUIManager.h

@@ -121,6 +121,8 @@ namespace BansheeEngine
 		CM::Vector<WidgetInfo>::type mWidgets;
 		CM::UnorderedMap<const CM::Viewport*, GUIRenderData>::type mCachedGUIData;
 
+		CM::VertexDataDescPtr mVertexDesc;
+
 		CM::Stack<GUIElement*>::type mScheduledForDestruction;
 
 		// Element and widget mouse is currently over

+ 13 - 47
BansheeEngine/Source/BsDrawHelper2D.cpp

@@ -10,6 +10,7 @@
 #include "BsCamera.h"
 #include "CmCoreThreadAccessor.h"
 #include "BsBuiltinMaterialManager.h"
+#include "CmVertexDataDesc.h"
 
 using namespace CamelotFramework;
 
@@ -18,6 +19,10 @@ namespace BansheeEngine
 	DrawHelper2D::DrawHelper2D()
 	{
 		mMaterial2DClipSpace = BuiltinMaterialManager::instance().createDebugDraw2DClipSpaceMaterial();
+
+		mVertexDesc = cm_shared_ptr<VertexDataDesc>();
+		mVertexDesc->addVertElem(VET_FLOAT2, VES_POSITION);
+		mVertexDesc->addVertElem(VET_COLOR, VES_COLOR);
 	}
 
 	void DrawHelper2D::quad(const CM::FRect& area, const MeshDataPtr& meshData, CM::UINT32 vertexOffset, CM::UINT32 indexOffset)
@@ -34,7 +39,7 @@ namespace BansheeEngine
 		points.push_back(Vector2(area.x + area.width, area.y + area.height));
 		points.push_back(Vector2(area.x, area.y + area.height));	
 
-		polygonFill_Pixel(points, positionData, vertexOffset, meshData->getVertexStride(), indexData, indexOffset);
+		polygonFill_Pixel(points, positionData, vertexOffset, meshData->getVertexDesc()->getVertexStride(), indexData, indexOffset);
 	}
 
 	void DrawHelper2D::line_Pixel(const Vector2& a, const Vector2& b, const CM::Color& color, const CM::MeshDataPtr& meshData, CM::UINT32 vertexOffset, CM::UINT32 indexOffset)
@@ -71,15 +76,7 @@ namespace BansheeEngine
 		DebugDrawCommand& dbgCmd = commands.back();
 		dbgCmd.endTime = gTime().getTime() + timeout;
 
-		MeshDataPtr meshData = cm_shared_ptr<MeshData, ScratchAlloc>(4);
-
-		meshData->beginDesc();
-
-		meshData->addSubMesh(6);
-		meshData->addVertElem(VET_FLOAT2, VES_POSITION);
-		meshData->addVertElem(VET_COLOR, VES_COLOR);
-
-		meshData->endDesc();
+		MeshDataPtr meshData = cm_shared_ptr<MeshData, ScratchAlloc>(4, 6, mVertexDesc);
 
 		FRect actualArea = area;
 		if(coordType == DebugDrawCoordType::Normalized)
@@ -87,7 +84,7 @@ namespace BansheeEngine
 
 		quad(actualArea, meshData, 0, 0);
 
-		UINT32 vertexStride = meshData->getVertexStride();
+		UINT32 vertexStride = mVertexDesc->getVertexStride();
 		UINT8* colorData = meshData->getElementData(VES_COLOR);
 
 		UINT32* colors = (UINT32*)colorData;
@@ -130,15 +127,7 @@ namespace BansheeEngine
 		DebugDrawCommand& dbgCmd = commands.back();
 		dbgCmd.endTime = gTime().getTime() + timeout;
 
-		MeshDataPtr meshData = cm_shared_ptr<MeshData, ScratchAlloc>(2);
-
-		meshData->beginDesc();
-
-		meshData->addSubMesh(2, 0, DOT_LINE_LIST);
-		meshData->addVertElem(VET_FLOAT2, VES_POSITION);
-		meshData->addVertElem(VET_COLOR, VES_COLOR);
-
-		meshData->endDesc();
+		MeshDataPtr meshData = cm_shared_ptr<MeshData, ScratchAlloc>(2, 2, mVertexDesc, DOT_LINE_LIST);
 
 		Vector2 actualA = a;
 		Vector2 actualB = b;
@@ -179,15 +168,7 @@ namespace BansheeEngine
 		DebugDrawCommand& dbgCmd = commands.back();
 		dbgCmd.endTime = gTime().getTime() + timeout;
 
-		MeshDataPtr meshData = cm_shared_ptr<MeshData, ScratchAlloc>(8);
-
-		meshData->beginDesc();
-
-		meshData->addSubMesh(30, 0, DOT_TRIANGLE_LIST);
-		meshData->addVertElem(VET_FLOAT2, VES_POSITION);
-		meshData->addVertElem(VET_COLOR, VES_COLOR);
-
-		meshData->endDesc();
+		MeshDataPtr meshData = cm_shared_ptr<MeshData, ScratchAlloc>(8, 30, mVertexDesc);
 
 		Vector2 actualA = a;
 		Vector2 actualB = b;
@@ -229,15 +210,8 @@ namespace BansheeEngine
 		DebugDrawCommand& dbgCmd = commands.back();
 		dbgCmd.endTime = gTime().getTime() + timeout;
 
-		MeshDataPtr meshData = cm_shared_ptr<MeshData, ScratchAlloc>((UINT32)(linePoints.size() * 2));
-
-		meshData->beginDesc();
-
-		meshData->addSubMesh((UINT32)(linePoints.size() * 2), 0, DOT_LINE_LIST);
-		meshData->addVertElem(VET_FLOAT2, VES_POSITION);
-		meshData->addVertElem(VET_COLOR, VES_COLOR);
-
-		meshData->endDesc();
+		MeshDataPtr meshData = cm_shared_ptr<MeshData, ScratchAlloc>(
+			(UINT32)(linePoints.size() * 2), (UINT32)(linePoints.size() * 2), mVertexDesc, DOT_LINE_LIST);
 
 		if(coordType == DebugDrawCoordType::Normalized)
 		{
@@ -283,15 +257,7 @@ namespace BansheeEngine
 		DebugDrawCommand& dbgCmd = commands.back();
 		dbgCmd.endTime = gTime().getTime() + timeout;
 
-		MeshDataPtr meshData = cm_shared_ptr<MeshData, ScratchAlloc>((UINT32)(linePoints.size() * 4));
-
-		meshData->beginDesc();
-
-		meshData->addSubMesh((UINT32)(linePoints.size() * 15), 0, DOT_TRIANGLE_LIST);
-		meshData->addVertElem(VET_FLOAT2, VES_POSITION);
-		meshData->addVertElem(VET_COLOR, VES_COLOR);
-
-		meshData->endDesc();
+		MeshDataPtr meshData = cm_shared_ptr<MeshData, ScratchAlloc>((UINT32)(linePoints.size() * 4), (UINT32)(linePoints.size() * 15), mVertexDesc);
 
 		if(coordType == DebugDrawCoordType::Normalized)
 		{

+ 20 - 52
BansheeEngine/Source/BsDrawHelper3D.cpp

@@ -10,11 +10,19 @@
 #include "CmException.h"
 #include "BsCamera.h"
 #include "BsBuiltinMaterialManager.h"
+#include "CmVertexDataDesc.h"
 
 using namespace CamelotFramework;
 
 namespace BansheeEngine
 {
+	DrawHelper3D::DrawHelper3D()
+	{
+		mVertexDesc = cm_shared_ptr<VertexDataDesc>();
+		mVertexDesc->addVertElem(VET_FLOAT2, VES_POSITION);
+		mVertexDesc->addVertElem(VET_COLOR, VES_COLOR);
+	}
+
 	void DrawHelper3D::aabox(const CM::AABox& box, const CM::MeshDataPtr& meshData, CM::UINT32 vertexOffset, CM::UINT32 indexOffset)
 	{
 		UINT32* indexData = meshData->getIndices32();
@@ -23,7 +31,7 @@ namespace BansheeEngine
 		assert((vertexOffset + 8) <= meshData->getNumVertices());
 		assert((indexOffset + 36) <= meshData->getNumIndices());	
 
-		aabox(box, positionData, vertexOffset, meshData->getVertexStride(), indexData, indexOffset);
+		aabox(box, positionData, vertexOffset, meshData->getVertexDesc()->getVertexStride(), indexData, indexOffset);
 	}
 
 	void DrawHelper3D::line_Pixel(const Vector3& a, const Vector3& b, const CM::Color& color, const CM::MeshDataPtr& meshData, CM::UINT32 vertexOffset, CM::UINT32 indexOffset)
@@ -60,20 +68,12 @@ namespace BansheeEngine
 		DebugDrawCommand& dbgCmd = commands.back();
 		dbgCmd.endTime = gTime().getTime() + timeout;
 
-		MeshDataPtr meshData = cm_shared_ptr<MeshData, ScratchAlloc>(2);
-
-		meshData->beginDesc();
-
-		meshData->addSubMesh(2, 0, DOT_LINE_LIST);
-		meshData->addVertElem(VET_FLOAT3, VES_POSITION);
-		meshData->addVertElem(VET_COLOR, VES_COLOR);
-
-		meshData->endDesc();
+		MeshDataPtr meshData = cm_shared_ptr<MeshData, ScratchAlloc>(2, 2, mVertexDesc, DOT_LINE_LIST);
 
 		line_Pixel(a, b, color, meshData, 0, 0);
 
 		UINT8* positionData = meshData->getElementData(VES_POSITION);
-		dbgCmd.worldCenter = calcCenter(positionData, meshData->getNumVertices(), meshData->getVertexStride());
+		dbgCmd.worldCenter = calcCenter(positionData, meshData->getNumVertices(), mVertexDesc->getVertexStride());
 
 		HMesh mesh = Mesh::create();
 
@@ -94,20 +94,12 @@ namespace BansheeEngine
 		DebugDrawCommand& dbgCmd = commands.back();
 		dbgCmd.endTime = gTime().getTime() + timeout;
 
-		MeshDataPtr meshData = cm_shared_ptr<MeshData, ScratchAlloc>(8);
-
-		meshData->beginDesc();
-
-		meshData->addSubMesh(30, 0, DOT_TRIANGLE_LIST);
-		meshData->addVertElem(VET_FLOAT3, VES_POSITION);
-		meshData->addVertElem(VET_COLOR, VES_COLOR);
-
-		meshData->endDesc();
+		MeshDataPtr meshData = cm_shared_ptr<MeshData, ScratchAlloc>(8, 30, mVertexDesc);
 
 		line_AA(a, b, width, borderWidth, color, meshData, 0, 0);
 
 		UINT8* positionData = meshData->getElementData(VES_POSITION);
-		dbgCmd.worldCenter = calcCenter(positionData, meshData->getNumVertices(), meshData->getVertexStride());
+		dbgCmd.worldCenter = calcCenter(positionData, meshData->getNumVertices(), mVertexDesc->getVertexStride());
 
 		HMesh mesh = Mesh::create();
 
@@ -128,20 +120,12 @@ namespace BansheeEngine
 		DebugDrawCommand& dbgCmd = commands.back();
 		dbgCmd.endTime = gTime().getTime() + timeout;
 
-		MeshDataPtr meshData = cm_shared_ptr<MeshData, ScratchAlloc>((UINT32)(linePoints.size() * 2));
-
-		meshData->beginDesc();
-
-		meshData->addSubMesh((UINT32)(linePoints.size() * 2), 0, DOT_LINE_LIST);
-		meshData->addVertElem(VET_FLOAT3, VES_POSITION);
-		meshData->addVertElem(VET_COLOR, VES_COLOR);
-
-		meshData->endDesc();
+		MeshDataPtr meshData = cm_shared_ptr<MeshData, ScratchAlloc>((UINT32)(linePoints.size() * 2), (UINT32)(linePoints.size() * 2), mVertexDesc, DOT_LINE_LIST);
 
 		lineList_Pixel(linePoints, color, meshData, 0, 0);
 
 		UINT8* positionData = meshData->getElementData(VES_POSITION);
-		dbgCmd.worldCenter = calcCenter(positionData, meshData->getNumVertices(), meshData->getVertexStride());
+		dbgCmd.worldCenter = calcCenter(positionData, meshData->getNumVertices(), mVertexDesc->getVertexStride());
 
 		HMesh mesh = Mesh::create();
 
@@ -163,20 +147,12 @@ namespace BansheeEngine
 		DebugDrawCommand& dbgCmd = commands.back();
 		dbgCmd.endTime = gTime().getTime() + timeout;
 
-		MeshDataPtr meshData = cm_shared_ptr<MeshData, ScratchAlloc>((UINT32)(linePoints.size() * 4));
-
-		meshData->beginDesc();
-
-		meshData->addSubMesh((UINT32)(linePoints.size() * 15), 0, DOT_TRIANGLE_LIST);
-		meshData->addVertElem(VET_FLOAT3, VES_POSITION);
-		meshData->addVertElem(VET_COLOR, VES_COLOR);
-
-		meshData->endDesc();
+		MeshDataPtr meshData = cm_shared_ptr<MeshData, ScratchAlloc>((UINT32)(linePoints.size() * 4), (UINT32)(linePoints.size() * 15), mVertexDesc);
 
 		lineList_AA(linePoints, width, borderWidth, color, meshData, 0, 0);	
 
 		UINT8* positionData = meshData->getElementData(VES_POSITION);
-		dbgCmd.worldCenter = calcCenter(positionData, meshData->getNumVertices(), meshData->getVertexStride());
+		dbgCmd.worldCenter = calcCenter(positionData, meshData->getNumVertices(), mVertexDesc->getVertexStride());
 
 		HMesh mesh = Mesh::create();
 
@@ -197,19 +173,11 @@ namespace BansheeEngine
 		DebugDrawCommand& dbgCmd = commands.back();
 		dbgCmd.endTime = gTime().getTime() + timeout;
 
-		MeshDataPtr meshData = cm_shared_ptr<MeshData, ScratchAlloc>(8);
-
-		meshData->beginDesc();
-
-		meshData->addSubMesh(36, 0, DOT_TRIANGLE_LIST);
-		meshData->addVertElem(VET_FLOAT3, VES_POSITION);
-		meshData->addVertElem(VET_COLOR, VES_COLOR);
-
-		meshData->endDesc();
+		MeshDataPtr meshData = cm_shared_ptr<MeshData, ScratchAlloc>(8, 36, mVertexDesc);
 
 		aabox(box, meshData, 0, 0);	
 
-		UINT32 vertexStride = meshData->getVertexStride();
+		UINT32 vertexStride = mVertexDesc->getVertexStride();
 		UINT8* colorData = meshData->getElementData(VES_COLOR);
 
 		for(UINT32 i = 0; i < meshData->getNumVertices(); i++)
@@ -221,7 +189,7 @@ namespace BansheeEngine
 		}
 
 		UINT8* positionData = meshData->getElementData(VES_POSITION);
-		dbgCmd.worldCenter = calcCenter(positionData, meshData->getNumVertices(), meshData->getVertexStride());
+		dbgCmd.worldCenter = calcCenter(positionData, meshData->getNumVertices(), mVertexDesc->getVertexStride());
 
 		HMesh mesh = Mesh::create();
 

+ 7 - 8
BansheeEngine/Source/BsGUIManager.cpp

@@ -7,6 +7,7 @@
 #include "CmSceneObject.h"
 #include "CmMaterial.h"
 #include "CmMeshData.h"
+#include "CmVertexDataDesc.h"
 #include "CmMesh.h"
 #include "CmUtil.h"
 #include "CmRenderWindowManager.h"
@@ -82,6 +83,10 @@ namespace BansheeEngine
 
 		GUIDropDownBoxManager::startUp(cm_new<GUIDropDownBoxManager>());
 
+		mVertexDesc = cm_shared_ptr<VertexDataDesc>();
+		mVertexDesc->addVertElem(VET_FLOAT2, VES_POSITION);
+		mVertexDesc->addVertElem(VET_FLOAT2, VES_TEXCOORD);
+
 		// Need to defer this call because I want to make sure all managers are initialized first
 		deferredCall(std::bind(&GUIManager::updateCaretTexture, this));
 		deferredCall(std::bind(&GUIManager::updateTextSelectionTexture, this));
@@ -476,18 +481,12 @@ namespace BansheeEngine
 					}
 				}
 
-				MeshDataPtr meshData = cm_shared_ptr<MeshData, PoolAlloc>(group->numQuads * 4);
-
-				meshData->beginDesc();
-				meshData->addVertElem(VET_FLOAT2, VES_POSITION);
-				meshData->addVertElem(VET_FLOAT2, VES_TEXCOORD);
-				meshData->addSubMesh(group->numQuads * 6);
-				meshData->endDesc();
+				MeshDataPtr meshData = cm_shared_ptr<MeshData, PoolAlloc>(group->numQuads * 4, group->numQuads * 6, mVertexDesc);
 
 				UINT8* vertices = meshData->getElementData(VES_POSITION);
 				UINT8* uvs = meshData->getElementData(VES_TEXCOORD);
 				UINT32* indices = meshData->getIndices32();
-				UINT32 vertexStride = meshData->getVertexStride();
+				UINT32 vertexStride = meshData->getVertexDesc()->getVertexStride();
 				UINT32 indexStride = meshData->getIndexElementSize();
 
 				UINT32 quadOffset = 0;

+ 6 - 8
CamelotClient/Source/BsDockManager.cpp

@@ -14,6 +14,7 @@
 #include "BsBuiltinMaterialManager.h"
 #include "BsGUIWidget.h"
 #include "BsCamera.h"
+#include "CmVertexDataDesc.h"
 
 using namespace CamelotFramework;
 using namespace BansheeEngine;
@@ -311,15 +312,12 @@ namespace BansheeEditor
 		Vector2 inBotLeft((float)(x + inXOffset), (float)(y + inYOffset + inHeight));
 		Vector2 inBotRight((float)(x + inXOffset + inWidth), (float)(y + inYOffset + inHeight));
 
-		MeshDataPtr meshData = cm_shared_ptr<MeshData, ScratchAlloc>(16);
+		VertexDataDescPtr vertexDesc = cm_shared_ptr<VertexDataDesc>();
+		
+		vertexDesc->addVertElem(VET_FLOAT2, VES_POSITION);
+		vertexDesc->addVertElem(VET_COLOR, VES_COLOR);
 
-		meshData->beginDesc();
-
-		meshData->addSubMesh(24, 0, DOT_TRIANGLE_LIST);
-		meshData->addVertElem(VET_FLOAT2, VES_POSITION);
-		meshData->addVertElem(VET_COLOR, VES_COLOR);
-
-		meshData->endDesc();
+		MeshDataPtr meshData = cm_shared_ptr<MeshData, ScratchAlloc>(16, 24, vertexDesc);
 
 		auto vertIter = meshData->getVec2DataIter(VES_POSITION);
 		auto colIter = meshData->getDWORDDataIter(VES_COLOR);

+ 3 - 0
CamelotCore/CamelotCore.vcxproj

@@ -388,6 +388,8 @@
     <ClInclude Include="Include\CmTextureRTTI.h" />
     <ClInclude Include="Include\CmSamplerState.h" />
     <ClInclude Include="Include\CmIndexData.h" />
+    <ClInclude Include="Include\CmVertexDataDesc.h" />
+    <ClInclude Include="Include\CmVertexDataDescRTTI.h" />
     <ClInclude Include="Include\CmVertexDeclaration.h" />
     <ClInclude Include="Include\CmVertexData.h" />
     <ClInclude Include="Include\CmViewport.h" />
@@ -490,6 +492,7 @@
     <ClCompile Include="Source\CmTexture.cpp" />
     <ClCompile Include="Source\CmTextureManager.cpp" />
     <ClCompile Include="Source\CmSamplerState.cpp" />
+    <ClCompile Include="Source\CmVertexDataDesc.cpp" />
     <ClCompile Include="Source\CmVertexDeclaration.cpp" />
     <ClCompile Include="Source\CmVertexData.cpp" />
     <ClCompile Include="Source\CmViewport.cpp" />

+ 15 - 6
CamelotCore/CamelotCore.vcxproj.filters

@@ -186,9 +186,6 @@
     <ClInclude Include="Include\CmMesh.h">
       <Filter>Header Files\Resources</Filter>
     </ClInclude>
-    <ClInclude Include="Include\CmMeshData.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
     <ClInclude Include="Include\CmMeshDataRTTI.h">
       <Filter>Header Files\RTTI</Filter>
     </ClInclude>
@@ -492,6 +489,15 @@
     <ClInclude Include="Include\CmGpuParam.h">
       <Filter>Header Files\RenderSystem</Filter>
     </ClInclude>
+    <ClInclude Include="Include\CmMeshData.h">
+      <Filter>Header Files\Resources</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\CmVertexDataDesc.h">
+      <Filter>Header Files\Resources</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\CmVertexDataDescRTTI.h">
+      <Filter>Header Files\RTTI</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\CmApplication.cpp">
@@ -569,9 +575,6 @@
     <ClCompile Include="Source\CmMesh.cpp">
       <Filter>Source Files\Resources</Filter>
     </ClCompile>
-    <ClCompile Include="Source\CmMeshData.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
     <ClCompile Include="Source\CmInput.cpp">
       <Filter>Source Files\Input</Filter>
     </ClCompile>
@@ -767,5 +770,11 @@
     <ClCompile Include="Source\CmGpuParam.cpp">
       <Filter>Source Files\RenderSystem</Filter>
     </ClCompile>
+    <ClCompile Include="Source\CmMeshData.cpp">
+      <Filter>Source Files\Resources</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\CmVertexDataDesc.cpp">
+      <Filter>Source Files\Resources</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 1 - 1
CamelotCore/Include/CmMaterialRTTI.h

@@ -547,7 +547,7 @@ namespace CamelotFramework
 			return obj->mShader;
 		}
 
-		void setShader(Material* obj,  ShaderPtr val)
+		void setShader(Material* obj, ShaderPtr val)
 		{
 			obj->mShader = val;
 		}

+ 10 - 43
CamelotCore/Include/CmMeshData.h

@@ -77,32 +77,11 @@ namespace CamelotFramework
 			DrawOperationType drawOp;
 		};
 
-		MeshData(UINT32 numVertices, IndexBuffer::IndexType indexType = IndexBuffer::IT_32BIT);
+		MeshData(UINT32 numVertices, UINT32 numIndexes, const VertexDataDescPtr& vertexData, DrawOperationType drawOp = DOT_TRIANGLE_LIST, IndexBuffer::IndexType indexType = IndexBuffer::IT_32BIT);
 		~MeshData();
 
-		/**
-		 * @brief	Begins the mesh data definition. After this call you may call various add* methods to inform
-		 * 			the internal buffer which data it will need to hold. Each beginDesc() call needs to be followed with
-		 * 			an endDesc().
-		 */
-		void beginDesc();
-
-		/**
-		 * @brief	Call after you are done defining data to actually allocate the internal buffer. Any previous buffer will be overwritten.
-		 * 			Must be called after beginDesc().
-		 */
-		void endDesc();
-
-		/**
-		* @brief	Informs the internal buffer that it needs to make room for the specified vertex element. If a vertex
-		* 			with same stream and semantics already exists it will just be updated. This must be called between beginDesc and endDesc.
-		 *
-		 * @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	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 addVertElem(VertexElementType type, VertexElementSemantic semantic, UINT32 semanticIdx = 0, UINT32 streamIdx = 0);
+		void setVertexWriteOffset(UINT32 offset); // TODO
+		void setIndexWriteOffset(UINT32 offset); // TODO
 
 		/**
 		 * @brief	Informs the internal buffer that it needs to make room for an index buffer of the
@@ -115,11 +94,6 @@ namespace CamelotFramework
 		 */
 		void addSubMesh(UINT32 numIndices, UINT32 subMesh = 0, DrawOperationType drawOp = DOT_TRIANGLE_LIST);
 
-		/**
-		 * @brief	Query if we have vertex data for the specified semantic.
-		 */
-		bool hasElement(VertexElementSemantic semantic, UINT32 semanticIdx = 0, UINT32 streamIdx = 0) const;
-
 		/**
 		 * @brief	Copies data from "data" parameter into the internal buffer for the specified semantic.
 		 *
@@ -163,16 +137,12 @@ namespace CamelotFramework
 		 */
 		VertexElemIter<UINT32> getDWORDDataIter(VertexElementSemantic semantic, UINT32 semanticIdx = 0, UINT32 streamIdx = 0);
 
-		/**
-		 * @brief	Creates a new vertex declaration based on set vertex elements.
-		 */
-		VertexDeclarationPtr createDeclaration() const;
-
 		UINT32 getNumSubmeshes() const { return (UINT32)mSubMeshes.size(); }
 		UINT32 getNumVertices() const { return mNumVertices; }
 		UINT32 getNumIndices(UINT32 subMesh) const;
 		UINT32 getNumIndices() const;
 		DrawOperationType getDrawOp(UINT32 subMesh) const;
+		DrawOperationType getDrawOp() const;
 
 		UINT16* getIndices16(UINT32 subMesh = 0) const;
 		UINT32* getIndices32(UINT32 subMesh = 0) const;
@@ -191,11 +161,10 @@ namespace CamelotFramework
 		 * @return	null if it fails, else the element data.
 		 */
 		UINT8* getElementData(VertexElementSemantic semantic, UINT32 semanticIdx = 0, UINT32 streamIdx = 0) const;
-		UINT32 getElementSize(VertexElementSemantic semantic, UINT32 semanticIdx = 0, UINT32 streamIdx = 0) const;
 		UINT32 getElementOffset(VertexElementSemantic semantic, UINT32 semanticIdx = 0, UINT32 streamIdx = 0) const;
 
-		UINT32 getVertexStride(UINT32 streamIdx = 0) const;
-		
+		const VertexDataDescPtr& getVertexDesc() const { return mVertexData; }
+
 		static MeshDataPtr combine(const Vector<MeshDataPtr>::type& elements);
 
 	protected:
@@ -209,13 +178,12 @@ namespace CamelotFramework
 		UINT8* mData;
 
 		UINT32 mNumVertices;
+		UINT32 mNumIndices;
+		DrawOperationType mDrawOp;
 		IndexBuffer::IndexType mIndexType;
 
 		Vector<IndexElementData>::type mSubMeshes;
-		Vector<VertexElement>::type mVertexElements;
-
-		UINT32 getMaxStreamIdx() const;
-		bool hasStream(UINT32 streamIdx) const;
+		VertexDataDescPtr mVertexData;
 
 		UINT8* getIndexData() const { return getData(); }
 		UINT8* getStreamData(UINT32 streamIdx) const;
@@ -223,12 +191,11 @@ namespace CamelotFramework
 		UINT32 getIndexBufferOffset(UINT32 subMesh) const;
 		UINT32 getStreamOffset(UINT32 streamIdx = 0) const;
 
-		UINT32 getIndexBufferSize() const { return getIndexBufferOffset(getNumSubmeshes()); }
+		UINT32 getIndexBufferSize() const;
 		UINT32 getStreamSize(UINT32 streamIdx) const;
 		UINT32 getStreamSize() const;
 
 		void getDataForIterator(VertexElementSemantic semantic, UINT32 semanticIdx, UINT32 streamIdx, UINT8*& data, UINT32& stride) const;
-		void clearIfItExists(VertexElementType type, VertexElementSemantic semantic, UINT32 semanticIdx, UINT32 streamIdx);
 
 		/************************************************************************/
 		/* 								SERIALIZATION                      		*/

+ 26 - 22
CamelotCore/Include/CmMeshDataRTTI.h

@@ -14,25 +14,8 @@ namespace CamelotFramework
 	class CM_EXPORT MeshDataRTTI : public RTTIType<MeshData, GpuResourceData, MeshDataRTTI>
 	{
 	private:
-		VertexElement& getVertexElementData(MeshData* obj, UINT32 arrayIdx)
-		{
-			return obj->mVertexElements[arrayIdx];
-		}
-
-		void setVertexElementData(MeshData* obj, UINT32 arrayIdx, VertexElement& value)
-		{
-			obj->mVertexElements[arrayIdx] = value;
-		}
-
-		UINT32 getNumVertexElementData(MeshData* obj)
-		{
-			return (UINT32)obj->mVertexElements.size();
-		}
-
-		void setNumVertexElementData(MeshData* obj, UINT32 numElements)
-		{
-			obj->mVertexElements.resize(numElements);
-		}
+		VertexDataDescPtr getVertexData(MeshData* obj) { return obj->mVertexData; }
+		void setVertexData(MeshData* obj, VertexDataDescPtr value) { obj->mVertexData = value; }
 
 		MeshData::IndexElementData& getIndexElementData(MeshData* obj, UINT32 arrayIdx)
 		{
@@ -74,6 +57,26 @@ namespace CamelotFramework
 			obj->mNumVertices = value;
 		}
 
+		UINT32& getNumIndices(MeshData* obj)
+		{
+			return obj->mNumIndices;
+		}
+
+		void setNumIndices(MeshData* obj, UINT32& value)
+		{
+			obj->mNumIndices = value;
+		}
+
+		UINT32& getDrawOp(MeshData* obj)
+		{
+			return (UINT32&)obj->mDrawOp;
+		}
+
+		void setDrawOp(MeshData* obj, UINT32& value)
+		{
+			obj->mDrawOp = (DrawOperationType)value;
+		}
+
 		ManagedDataBlock getData(MeshData* obj) 
 		{ 
 			ManagedDataBlock dataBlock((UINT8*)obj->getData(), obj->getInternalBufferSize());
@@ -96,16 +99,17 @@ namespace CamelotFramework
 	public:
 		MeshDataRTTI()
 		{
-			addPlainArrayField("mVertexData", 0, &MeshDataRTTI::getVertexElementData, 
-				&MeshDataRTTI::getNumVertexElementData, &MeshDataRTTI::setVertexElementData, &MeshDataRTTI::setNumVertexElementData);
+			addReflectablePtrField("mVertexData", 0, &MeshDataRTTI::getVertexData, &MeshDataRTTI::setVertexData);
 
 			addPlainArrayField("mIndexBuffer", 1, &MeshDataRTTI::getIndexElementData, 
 				&MeshDataRTTI::getNumIndexElementData, &MeshDataRTTI::setIndexElementData, &MeshDataRTTI::setNumIndexElementData);
 
 			addPlainField("mIndexType", 2, &MeshDataRTTI::getIndexType, &MeshDataRTTI::setIndexType);
 			addPlainField("mNumVertices", 3, &MeshDataRTTI::getNumVertices, &MeshDataRTTI::setNumVertices);
+			addPlainField("mNumIndices", 4, &MeshDataRTTI::getNumIndices, &MeshDataRTTI::setNumIndices);
+			addPlainField("mDrawOp", 5, &MeshDataRTTI::getDrawOp, &MeshDataRTTI::setDrawOp);
 
-			addDataBlockField("data", 4, &MeshDataRTTI::getData, &MeshDataRTTI::setData, 0, &MeshDataRTTI::allocateData);
+			addDataBlockField("data", 6, &MeshDataRTTI::getData, &MeshDataRTTI::setData, 0, &MeshDataRTTI::allocateData);
 		}
 
 		virtual std::shared_ptr<IReflectable> newRTTIObject() 

+ 4 - 1
CamelotCore/Include/CmPrerequisites.h

@@ -128,6 +128,7 @@ namespace CamelotFramework
 	struct RenderOperation;
 	class RenderQueue;
 	struct ProfilerReport;
+	class VertexDataDesc;
 	// Asset import
 	class SpecificImporter;
 	class Importer;
@@ -204,6 +205,7 @@ namespace CamelotFramework
 	typedef std::shared_ptr<const ImportOptions> ConstImportOptionsPtr;
 	typedef std::shared_ptr<Font> FontPtr;
 	typedef std::shared_ptr<GpuResource> GpuResourcePtr;
+	typedef std::shared_ptr<VertexDataDesc> VertexDataDescPtr;
 	typedef CoreThreadAccessor<CommandQueueNoSync> CoreAccessor;
 	typedef CoreThreadAccessor<CommandQueueSync> SyncedCoreAccessor;
 	typedef std::shared_ptr<CoreThreadAccessor<CommandQueueNoSync>> CoreAccessorPtr;
@@ -266,7 +268,8 @@ namespace CamelotFramework
 		TID_GameObject = 1060,
 		TID_GpuResource = 1061,
 		TID_PixelData = 1062,
-		TID_GpuResourceData = 1063
+		TID_GpuResourceData = 1063,
+		TID_VertexDataDesc = 1064
 	};
 }
 

+ 62 - 0
CamelotCore/Include/CmVertexDataDesc.h

@@ -0,0 +1,62 @@
+#pragma once
+
+#include "CmPrerequisites.h"
+#include "CmVertexDeclaration.h"
+
+namespace CamelotFramework
+{
+	class CM_EXPORT VertexDataDesc : public IReflectable
+	{
+	public:
+		VertexDataDesc() {}
+
+		/**
+		* @brief	Informs the internal buffer that it needs to make room for the specified vertex element. If a vertex
+		* 			with same stream and semantics already exists it will just be updated. 
+		 *
+		 * @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	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 addVertElem(VertexElementType type, VertexElementSemantic semantic, UINT32 semanticIdx = 0, UINT32 streamIdx = 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 getElementSize(VertexElementSemantic semantic, UINT32 semanticIdx = 0, UINT32 streamIdx = 0) const;
+		UINT32 getElementOffsetFromStream(VertexElementSemantic semantic, UINT32 semanticIdx = 0, UINT32 streamIdx = 0) const;
+
+		UINT32 getVertexStride(UINT32 streamIdx) const;
+		UINT32 getVertexStride() const;
+
+		UINT32 getStreamOffset(UINT32 streamIdx) const;
+
+		UINT32 getNumElements() const { return (UINT32)mVertexElements.size(); }
+		const VertexElement& getElement(UINT32 idx) const { return mVertexElements[idx]; }
+	private:
+		friend class Mesh; // To avoid polluting the public interface with a bunch of nearly useless methods for outside world
+
+		Vector<VertexElement>::type mVertexElements;
+
+		UINT32 getMaxStreamIdx() const;
+		bool hasStream(UINT32 streamIdx) const;
+
+		void clearIfItExists(VertexElementType type, VertexElementSemantic semantic, UINT32 semanticIdx, UINT32 streamIdx);
+
+		/************************************************************************/
+		/* 								SERIALIZATION                      		*/
+		/************************************************************************/
+	public:
+		friend class VertexDataDescRTTI;
+		static RTTITypeBase* getRTTIStatic();
+		virtual RTTITypeBase* getRTTI() const;
+	};
+}

+ 55 - 0
CamelotCore/Include/CmVertexDataDescRTTI.h

@@ -0,0 +1,55 @@
+#pragma once
+
+#include "CmPrerequisites.h"
+#include "CmRTTIType.h"
+#include "CmVertexDataDesc.h"
+
+namespace CamelotFramework
+{
+	class CM_EXPORT VertexDataDescRTTI : public RTTIType<VertexDataDesc, IReflectable, VertexDataDescRTTI>
+	{
+	private:
+		VertexElement& getVertexElementData(VertexDataDesc* obj, UINT32 arrayIdx)
+		{
+			return obj->mVertexElements[arrayIdx];
+		}
+
+		void setVertexElementData(VertexDataDesc* obj, UINT32 arrayIdx, VertexElement& value)
+		{
+			obj->mVertexElements[arrayIdx] = value;
+		}
+
+		UINT32 getNumVertexElementData(VertexDataDesc* obj)
+		{
+			return (UINT32)obj->mVertexElements.size();
+		}
+
+		void setNumVertexElementData(VertexDataDesc* obj, UINT32 numElements)
+		{
+			obj->mVertexElements.resize(numElements);
+		}
+
+	public:
+		VertexDataDescRTTI()
+		{
+			addPlainArrayField("mVertexData", 0, &VertexDataDescRTTI::getVertexElementData, 
+				&VertexDataDescRTTI::getNumVertexElementData, &VertexDataDescRTTI::setVertexElementData, &VertexDataDescRTTI::setNumVertexElementData);
+		}
+
+		virtual std::shared_ptr<IReflectable> newRTTIObject() 
+		{
+			return cm_shared_ptr<VertexDataDesc, PoolAlloc>(new (cm_alloc<VertexDataDesc, PoolAlloc>()) VertexDataDesc());
+		}
+
+		virtual const String& getRTTIName() 
+		{
+			static String name = "VertexDataDesc";
+			throw name;
+		}
+
+		virtual UINT32 getRTTIId() 
+		{
+			return TID_VertexDataDesc;
+		}
+	};
+}

+ 34 - 14
CamelotCore/Source/CmMesh.cpp

@@ -9,6 +9,7 @@
 #include "CmCoreThread.h"
 #include "CmAsyncOp.h"
 #include "CmAABox.h"
+#include "CmVertexDataDesc.h"
 
 #include "CmProfiler.h"
 
@@ -56,11 +57,11 @@ namespace CamelotFramework
 		mVertexData = std::shared_ptr<VertexData>(cm_new<VertexData, PoolAlloc>());
 
 		mVertexData->vertexCount = meshData.getNumVertices();
-		mVertexData->vertexDeclaration = meshData.createDeclaration();
+		mVertexData->vertexDeclaration = meshData.getVertexDesc()->createDeclaration();
 
-		for(UINT32 i = 0; i <= meshData.getMaxStreamIdx(); i++)
+		for(UINT32 i = 0; i <= meshData.getVertexDesc()->getMaxStreamIdx(); i++)
 		{
-			if(!meshData.hasStream(i))
+			if(!meshData.getVertexDesc()->hasStream(i))
 				continue;
 
 			UINT32 streamSize = meshData.getStreamSize(i);
@@ -82,10 +83,10 @@ namespace CamelotFramework
 
 			if(vertexBuffer->vertexColorReqRGBFlip())
 			{
-				UINT32 vertexStride = meshData.getVertexStride(i);
+				UINT32 vertexStride = meshData.getVertexDesc()->getVertexStride(i);
 				for(INT32 semanticIdx = 0; semanticIdx < VertexBuffer::MAX_SEMANTIC_IDX; semanticIdx++)
 				{
-					if(!meshData.hasElement(VES_COLOR, semanticIdx, i))
+					if(!meshData.getVertexDesc()->hasElement(VES_COLOR, semanticIdx, i))
 						continue;
 
 					UINT8* colorData = vertBufferData + meshData.getElementOffset(VES_COLOR, semanticIdx, i);
@@ -106,13 +107,25 @@ namespace CamelotFramework
 		// Submeshes
 		mSubMeshes.clear();
 
-		for(UINT32 i = 0; i < meshData.getNumSubmeshes(); i++)
+		if(meshData.getNumSubmeshes() > 0)
 		{
-			UINT32 numIndices = meshData.getNumIndices(i);
+			for(UINT32 i = 0; i < meshData.getNumSubmeshes(); i++)
+			{
+				UINT32 numIndices = meshData.getNumIndices(i);
+
+				if(numIndices > 0)
+				{
+					mSubMeshes.push_back(SubMesh(meshData.getIndexBufferOffset(i), numIndices, meshData.getDrawOp(i), mVertexData, mIndexData, true));
+				}
+			}
+		}
+		else // Read it all as one mesh
+		{
+			UINT32 numIndices = meshData.getNumIndices();
 
 			if(numIndices > 0)
 			{
-				mSubMeshes.push_back(SubMesh(meshData.getIndexBufferOffset(i), numIndices, meshData.getDrawOp(i), mVertexData, mIndexData, true));
+				mSubMeshes.push_back(SubMesh(0, numIndices, meshData.getDrawOp(), mVertexData, mIndexData, true));
 			}
 		}
 	}
@@ -177,15 +190,15 @@ namespace CamelotFramework
 		if(mIndexData)
 			indexType = mIndexData->indexBuffer->getType();
 
-		MeshDataPtr meshData = cm_shared_ptr<MeshData, PoolAlloc>(mVertexData->vertexCount, indexType);
-
-		meshData->beginDesc();
+		UINT32 numIndices = 0;
 		if(mIndexData)
 		{
 			for(UINT32 i = 0; i < mSubMeshes.size(); i++)
-				meshData->addSubMesh(mSubMeshes[i].indexCount, i);
+				numIndices += mSubMeshes[i].indexCount;
 		}
 
+		VertexDataDescPtr vertexDesc = cm_shared_ptr<VertexDataDesc>();
+
 		if(mVertexData)
 		{
 			auto vertexBuffers = mVertexData->getBuffers();
@@ -206,13 +219,20 @@ namespace CamelotFramework
 					UINT32 offset = element->getOffset();
 					UINT32 elemSize = element->getSize();
 
-					meshData->addVertElem(type, semantic, semanticIdx, streamIdx);
+					vertexDesc->addVertElem(type, semantic, semanticIdx, streamIdx);
 				}
 
 				streamIdx++;
 			}
 		}
-		meshData->endDesc();
+
+		MeshDataPtr meshData = cm_shared_ptr<MeshData>(mVertexData->vertexCount, numIndices, vertexDesc, DOT_TRIANGLE_LIST, indexType);
+
+		if(mIndexData)
+		{
+			for(UINT32 i = 0; i < mSubMeshes.size(); i++)
+				meshData->addSubMesh(mSubMeshes[i].indexCount, i);
+		}
 
 		return meshData;
 	}

+ 50 - 214
CamelotCore/Source/CmMeshData.cpp

@@ -4,66 +4,20 @@
 #include "CmHardwareBufferManager.h"
 #include "CmMeshDataRTTI.h"
 #include "CmVertexDeclaration.h"
+#include "CmVertexDataDesc.h"
 #include "CmException.h"
 
 namespace CamelotFramework
 {
-	MeshData::MeshData(UINT32 numVertices, IndexBuffer::IndexType indexType)
-	   :mNumVertices(numVertices), mIndexType(indexType), mData(nullptr), mDescBuilding(false)
+	MeshData::MeshData(UINT32 numVertices, UINT32 numIndexes, const VertexDataDescPtr& vertexData, DrawOperationType drawOp, IndexBuffer::IndexType indexType)
+	   :mNumVertices(numVertices), mNumIndices(numIndexes), mVertexData(vertexData), mIndexType(indexType), mDrawOp(drawOp), mData(nullptr)
 	{
-
-	}
-
-	MeshData::~MeshData()
-	{
-
-	}
-
-	void MeshData::beginDesc()
-	{
-		if(mDescBuilding)
-			CM_EXCEPT(InternalErrorException, "beginDesc() but description building has already began.");
-
-		mVertexElements.clear();
-		mSubMeshes.clear();
-
-		mDescBuilding = true;
-	}
-
-	void MeshData::endDesc()
-	{
-		if(!mDescBuilding)
-			CM_EXCEPT(InternalErrorException, "endDesc() called without beginDesc().");
-
 		allocateInternalBuffer();
-
-		mDescBuilding = false;
 	}
 
-	void MeshData::addVertElem(VertexElementType type, VertexElementSemantic semantic, UINT32 semanticIdx, UINT32 streamIdx)
+	MeshData::~MeshData()
 	{
-		if(!mDescBuilding)
-			CM_EXCEPT(InternalErrorException, "Cannot add vertex element when not building description. Call beginDesc() first.");
-
-		clearIfItExists(type, semantic, semanticIdx, streamIdx);
-
-		VertexElement newElement(streamIdx, 0, type, semantic, semanticIdx);
-
-		// Insert it so it is sorted by stream
-		UINT32 insertToIndex = (UINT32)mVertexElements.size();
-		UINT32 idx = 0;
-		for(auto& elem : mVertexElements)
-		{
-			if(elem.getStreamIdx() > streamIdx)
-			{
-				insertToIndex = idx;
-				break;
-			}
-
-			idx++;
-		}
 
-		mVertexElements.insert(mVertexElements.begin() + insertToIndex, newElement);
 	}
 
 	void MeshData::addSubMesh(UINT32 numIndices, UINT32 subMesh, DrawOperationType drawOp)
@@ -84,41 +38,27 @@ namespace CamelotFramework
 		mSubMeshes[subMesh] = indexData;
 	}
 
-	VertexDeclarationPtr MeshData::createDeclaration() const
-	{
-		VertexDeclarationPtr declaration = HardwareBufferManager::instance().createVertexDeclaration();
-
-		UINT32 maxStreamIdx = getMaxStreamIdx();
-
-		UINT32 numStreams = maxStreamIdx + 1;
-		UINT32* streamOffsets = cm_newN<UINT32, ScratchAlloc>(numStreams);
-		for(UINT32 i = 0; i < numStreams; i++)
-			streamOffsets[i] = 0;
-
-		for(auto& vertElem : mVertexElements)
-		{
-			UINT32 streamIdx = vertElem.getStreamIdx();
-			declaration->addElement(streamIdx, streamOffsets[streamIdx], vertElem.getType(), vertElem.getSemantic(), vertElem.getSemanticIdx());
-			streamOffsets[streamIdx] += vertElem.getSize();
-		}
-
-		cm_deleteN<ScratchAlloc>(streamOffsets, numStreams);
-
-		return declaration;
-	}
-
 	UINT32 MeshData::getNumIndices(UINT32 subMesh) const
 	{
+		if(mSubMeshes.size() == 0)
+			return mNumIndices;
+
 		return mSubMeshes.at(subMesh).numIndices;
 	}
 
 	DrawOperationType MeshData::getDrawOp(UINT32 subMesh) const
 	{
+		if(mSubMeshes.size() == 0)
+			return mDrawOp;
+
 		return mSubMeshes.at(subMesh).drawOp;
 	}
 
 	UINT32 MeshData::getNumIndices() const
 	{
+		if(mSubMeshes.size() == 0)
+			return mNumIndices;
+
 		UINT32 count = 0;
 		for(UINT32 i = 0; i < getNumSubmeshes(); i++)
 		{
@@ -128,6 +68,11 @@ namespace CamelotFramework
 		return count;
 	}
 
+	DrawOperationType MeshData::getDrawOp() const
+	{
+		return mDrawOp;
+	}
+
 	UINT16* MeshData::getIndices16(UINT32 subMesh) const
 	{
 		if(mIndexType != IndexBuffer::IT_16BIT)
@@ -148,32 +93,6 @@ namespace CamelotFramework
 		return (UINT32*)(getData() + indexBufferOffset);
 	}
 
-	UINT32 MeshData::getMaxStreamIdx() const
-	{
-		UINT32 maxStreamIdx = 0;
-		for(auto& vertElems : mVertexElements)
-		{
-			UINT32 offset = 0;
-			for(auto& vertElem : mVertexElements)
-			{
-				maxStreamIdx = std::max((UINT32)maxStreamIdx, (UINT32)vertElem.getStreamIdx());
-			}
-		}
-
-		return maxStreamIdx;
-	}
-
-	bool MeshData::hasStream(UINT32 streamIdx) const
-	{
-		for(auto& vertElem : mVertexElements)
-		{
-			if(vertElem.getStreamIdx() == streamIdx)
-				return true;
-		}
-
-		return false;
-	}
-
 	UINT32 MeshData::getInternalBufferSize()
 	{
 		return getIndexBufferSize() + getStreamSize();
@@ -184,15 +103,15 @@ namespace CamelotFramework
 	MeshDataPtr MeshData::combine(const Vector<MeshDataPtr>::type& meshes)
 	{
 		UINT32 totalVertexCount = 0;
+		UINT32 totalIndexCount = 0;
 		for(auto& meshData : meshes)
 		{
-			UINT32 numVertices = meshData->getNumVertices();
-			totalVertexCount += numVertices;
+			totalVertexCount += meshData->getNumVertices();
+			totalIndexCount += meshData->getNumIndices();
 		}
 
-		MeshDataPtr combinedMeshData = cm_shared_ptr<MeshData, PoolAlloc>(totalVertexCount);
-
-		combinedMeshData->beginDesc();
+		VertexDataDescPtr combinedVertexData = cm_shared_ptr<VertexDataDesc, PoolAlloc>();
+		MeshDataPtr combinedMeshData = cm_shared_ptr<MeshData, PoolAlloc>(totalVertexCount, totalIndexCount, combinedVertexData);
 
 		UINT32 subMeshIndex = 0;
 		for(auto& meshData : meshes)
@@ -209,10 +128,13 @@ namespace CamelotFramework
 		Vector<VertexElement>::type combinedVertexElements;
 		for(auto& meshData : meshes)
 		{
-			for(auto& newElement : meshData->mVertexElements)
+			for(UINT32 i = 0; i < meshData->getVertexDesc()->getNumElements(); i++)
 			{
+				const VertexElement& newElement = meshData->getVertexDesc()->getElement(i);
+
 				INT32 alreadyExistsIdx = -1;
 				UINT32 idx = 0;
+
 				for(auto& existingElement : combinedVertexElements)
 				{
 					if(newElement.getSemantic() == existingElement.getSemantic() && newElement.getSemanticIdx() == existingElement.getSemanticIdx()
@@ -233,12 +155,12 @@ namespace CamelotFramework
 				if(alreadyExistsIdx == -1)
 				{
 					combinedVertexElements.push_back(newElement);
-					combinedMeshData->addVertElem(newElement.getType(), newElement.getSemantic(), newElement.getSemanticIdx(), newElement.getStreamIdx());
+					combinedVertexData->addVertElem(newElement.getType(), newElement.getSemantic(), newElement.getSemanticIdx(), newElement.getStreamIdx());
 				}
 			}
 		}
 
-		combinedMeshData->endDesc();
+		VertexDataDescPtr vertexData = combinedMeshData->getVertexDesc();
 
 		// Copy indices
 		subMeshIndex = 0;
@@ -265,18 +187,18 @@ namespace CamelotFramework
 		vertexOffset = 0;
 		for(auto& meshData : meshes)
 		{
-			for(auto& element : combinedMeshData->mVertexElements)
+			for(auto& element : combinedVertexElements)
 			{
-				UINT32 dstVertexStride = combinedMeshData->getVertexStride(element.getStreamIdx());
+				UINT32 dstVertexStride = vertexData->getVertexStride(element.getStreamIdx());
 				UINT8* dstData = combinedMeshData->getElementData(element.getSemantic(), element.getSemanticIdx(), element.getStreamIdx());
 				dstData += vertexOffset * dstVertexStride;
 
 				UINT32 numSrcVertices = meshData->getNumVertices();
-				UINT32 vertexSize = combinedMeshData->getElementSize(element.getSemantic(), element.getSemanticIdx(), element.getStreamIdx());
+				UINT32 vertexSize = vertexData->getElementSize(element.getSemantic(), element.getSemanticIdx(), element.getStreamIdx());
 
-				if(meshData->hasElement(element.getSemantic(), element.getSemanticIdx(), element.getStreamIdx()))
+				if(meshData->getVertexDesc()->hasElement(element.getSemantic(), element.getSemanticIdx(), element.getStreamIdx()))
 				{
-					UINT32 srcVertexStride = meshData->getVertexStride(element.getStreamIdx());
+					UINT32 srcVertexStride = vertexData->getVertexStride(element.getStreamIdx());
 					UINT8* srcData = meshData->getElementData(element.getSemantic(), element.getSemanticIdx(), element.getStreamIdx());
 
 					for(UINT32 i = 0; i < numSrcVertices; i++)
@@ -302,33 +224,17 @@ namespace CamelotFramework
 		return combinedMeshData;
 	}
 
-	bool MeshData::hasElement(VertexElementSemantic semantic, UINT32 semanticIdx, UINT32 streamIdx) const
-	{
-		auto findIter = std::find_if(mVertexElements.begin(), mVertexElements.end(), 
-			[semantic, semanticIdx, streamIdx] (const VertexElement& x) 
-		{ 
-			return x.getSemantic() == semantic && x.getSemanticIdx() == semanticIdx && x.getStreamIdx() == streamIdx; 
-		});
-
-		if(findIter != mVertexElements.end())
-		{
-			return true;
-		}
-
-		return false;
-	}
-
 	void MeshData::setVertexData(VertexElementSemantic semantic, UINT8* data, UINT32 size, UINT32 semanticIdx, UINT32 streamIdx)
 	{
 		assert(data != nullptr);
 
-		if(!hasElement(semantic, semanticIdx, streamIdx))
+		if(!mVertexData->hasElement(semantic, semanticIdx, streamIdx))
 		{
 			CM_EXCEPT(InvalidParametersException, "MeshData doesn't contain an element of specified type: Semantic: " + toString(semantic) + ", Semantic index: "
 				+ toString(semanticIdx) + ", Stream index: " + toString(streamIdx));
 		}
 
-		UINT32 elementSize = getElementSize(semantic, semanticIdx, streamIdx);
+		UINT32 elementSize = mVertexData->getElementSize(semantic, semanticIdx, streamIdx);
 		UINT32 totalSize = elementSize * mNumVertices;
 
 		if(totalSize != size)
@@ -339,7 +245,7 @@ namespace CamelotFramework
 		UINT32 indexBufferOffset = getIndexBufferSize();
 
 		UINT32 elementOffset = getElementOffset(semantic, semanticIdx, streamIdx);
-		UINT32 vertexStride = getVertexStride(streamIdx);
+		UINT32 vertexStride = mVertexData->getVertexStride(streamIdx);
 
 		UINT8* dst = getData() + indexBufferOffset + elementOffset;
 		UINT8* src = data;
@@ -389,7 +295,7 @@ namespace CamelotFramework
 
 	void MeshData::getDataForIterator(VertexElementSemantic semantic, UINT32 semanticIdx, UINT32 streamIdx, UINT8*& data, UINT32& stride) const
 	{
-		if(!hasElement(semantic, semanticIdx, streamIdx))
+		if(!mVertexData->hasElement(semantic, semanticIdx, streamIdx))
 		{
 			CM_EXCEPT(InvalidParametersException, "MeshData doesn't contain an element of specified type: Semantic: " + toString(semantic) + ", Semantic index: "
 				+ toString(semanticIdx) + ", Stream index: " + toString(streamIdx));
@@ -400,11 +306,14 @@ namespace CamelotFramework
 		UINT32 elementOffset = getElementOffset(semantic, semanticIdx, streamIdx);
 
 		data = getData() + indexBufferOffset + elementOffset;
-		stride = getVertexStride(streamIdx);
+		stride = mVertexData->getVertexStride(streamIdx);
 	}
 
 	UINT32 MeshData::getIndexBufferOffset(UINT32 subMesh) const
 	{
+		if(mSubMeshes.size() == 0) // No submeshes, we assume all is one big mesh
+			return 0;
+
 		if(subMesh < 0 || (subMesh > (UINT32)mSubMeshes.size()))
 		{
 			CM_EXCEPT(InvalidParametersException, "Submesh out of range: " + toString(subMesh) + ". Allowed range: 0 .. " + toString((UINT32)mSubMeshes.size()));
@@ -421,36 +330,11 @@ namespace CamelotFramework
 
 	UINT32 MeshData::getStreamOffset(UINT32 streamIdx) const
 	{
-		UINT32 streamOffset = 0;
-		bool found = false;
-		for(auto& element : mVertexElements)
-		{
-			if(element.getStreamIdx() == streamIdx)
-			{
-				found = true;
-				break;
-			}
-
-			streamOffset += element.getSize();
-		}
-
-		if(!found)
-			CM_EXCEPT(InternalErrorException, "Cannot find the specified stream: " + toString(streamIdx));
+		UINT32 streamOffset = mVertexData->getStreamOffset(streamIdx);
 
 		return streamOffset * mNumVertices;
 	}
 
-	UINT32 MeshData::getElementSize(VertexElementSemantic semantic, UINT32 semanticIdx, UINT32 streamIdx) const
-	{
-		for(auto& element : mVertexElements)
-		{
-			if(element.getSemantic() == semantic && element.getSemanticIdx() == semanticIdx && element.getStreamIdx() == streamIdx)
-				return element.getSize();
-		}
-
-		return -1;
-	}
-
 	UINT8* MeshData::getElementData(VertexElementSemantic semantic, UINT32 semanticIdx, UINT32 streamIdx) const
 	{ 
 		return getData() + getIndexBufferSize() + getElementOffset(semantic, semanticIdx, streamIdx); 
@@ -468,70 +352,22 @@ namespace CamelotFramework
 
 	UINT32 MeshData::getElementOffset(VertexElementSemantic semantic, UINT32 semanticIdx, UINT32 streamIdx) const
 	{
-		UINT32 streamOffset = getStreamOffset(streamIdx);
-
-		UINT32 vertexOffset = 0;
-		for(auto& element : mVertexElements)
-		{
-			if(element.getStreamIdx() != streamIdx)
-				continue;
-
-			if(element.getSemantic() == semantic && element.getSemanticIdx() == semanticIdx)
-				break;
-
-			vertexOffset += element.getSize();
-		}
+		return getStreamOffset(streamIdx) + mVertexData->getElementOffsetFromStream(semantic, semanticIdx, streamIdx);
+	}
 
-		return streamOffset * mNumVertices + vertexOffset;
+	UINT32 MeshData::getIndexBufferSize() const
+	{ 
+		return mNumIndices * getIndexElementSize(); 
 	}
 
 	UINT32 MeshData::getStreamSize(UINT32 streamIdx) const
 	{
-		UINT32 vertexStride = 0;
-		for(auto& element : mVertexElements)
-		{
-			if(element.getStreamIdx() == streamIdx)
-				vertexStride += element.getSize();
-		}
-
-		return vertexStride * mNumVertices;
+		return mVertexData->getVertexStride(streamIdx) * mNumVertices;
 	}
 
 	UINT32 MeshData::getStreamSize() const
 	{
-		UINT32 vertexStride = 0;
-		for(auto& element : mVertexElements)
-		{
-			vertexStride += element.getSize();
-		}
-
-		return vertexStride * mNumVertices;
-	}
-
-	UINT32 MeshData::getVertexStride(UINT32 streamIdx) const
-	{
-		UINT32 vertexStride = 0;
-		for(auto& element : mVertexElements)
-		{
-			if(element.getStreamIdx() == streamIdx)
-				vertexStride += element.getSize();
-		}
-
-		return vertexStride;
-	}
-
-	void MeshData::clearIfItExists(VertexElementType type, VertexElementSemantic semantic, UINT32 semanticIdx, UINT32 streamIdx)
-	{
-		auto findIter = std::find_if(mVertexElements.begin(), mVertexElements.end(), 
-			[semantic, semanticIdx, streamIdx] (const VertexElement& x) 
-		{ 
-			return x.getSemantic() == semantic && x.getSemanticIdx() == semanticIdx && x.getStreamIdx() == streamIdx; 
-		});
-
-		if(findIter != mVertexElements.end())
-		{
-			mVertexElements.erase(findIter);
-		}
+		return mVertexData->getVertexStride() * mNumVertices;
 	}
 
 	/************************************************************************/

+ 4 - 5
CamelotCore/Source/CmMeshManager.cpp

@@ -3,6 +3,7 @@
 #include "CmApplication.h"
 #include "CmVector3.h"
 #include "CmMesh.h"
+#include "CmVertexDataDesc.h"
 
 namespace CamelotFramework
 {
@@ -35,12 +36,10 @@ namespace CamelotFramework
 
 	void MeshManager::onStartUp()
 	{
-		mDummyMeshData = cm_shared_ptr<MeshData>(1);
+		VertexDataDescPtr vertexDesc = cm_shared_ptr<VertexDataDesc>();
+		vertexDesc->addVertElem(VET_FLOAT3, VES_POSITION);
 
-		mDummyMeshData->beginDesc();
-		mDummyMeshData->addVertElem(VET_FLOAT3, VES_POSITION);
-		mDummyMeshData->addSubMesh(3);
-		mDummyMeshData->endDesc();
+		mDummyMeshData = cm_shared_ptr<MeshData>(1, 3, vertexDesc);
 
 		auto vecIter = mDummyMeshData->getVec3DataIter(VES_POSITION);
 		vecIter.setValue(Vector3(0, 0, 0));

+ 188 - 0
CamelotCore/Source/CmVertexDataDesc.cpp

@@ -0,0 +1,188 @@
+#include "CmVertexDataDesc.h"
+#include "CmHardwareBufferManager.h"
+#include "CmVertexDataDescRTTI.h"
+
+namespace CamelotFramework
+{
+	void VertexDataDesc::addVertElem(VertexElementType type, VertexElementSemantic semantic, UINT32 semanticIdx, UINT32 streamIdx)
+	{
+		clearIfItExists(type, semantic, semanticIdx, streamIdx);
+
+		VertexElement newElement(streamIdx, 0, type, semantic, semanticIdx);
+
+		// Insert it so it is sorted by stream
+		UINT32 insertToIndex = (UINT32)mVertexElements.size();
+		UINT32 idx = 0;
+		for(auto& elem : mVertexElements)
+		{
+			if(elem.getStreamIdx() > streamIdx)
+			{
+				insertToIndex = idx;
+				break;
+			}
+
+			idx++;
+		}
+
+		mVertexElements.insert(mVertexElements.begin() + insertToIndex, newElement);
+	}
+
+	VertexDeclarationPtr VertexDataDesc::createDeclaration() const
+	{
+		VertexDeclarationPtr declaration = HardwareBufferManager::instance().createVertexDeclaration();
+
+		UINT32 maxStreamIdx = getMaxStreamIdx();
+
+		UINT32 numStreams = maxStreamIdx + 1;
+		UINT32* streamOffsets = cm_newN<UINT32, ScratchAlloc>(numStreams);
+		for(UINT32 i = 0; i < numStreams; i++)
+			streamOffsets[i] = 0;
+
+		for(auto& vertElem : mVertexElements)
+		{
+			UINT32 streamIdx = vertElem.getStreamIdx();
+			declaration->addElement(streamIdx, streamOffsets[streamIdx], vertElem.getType(), vertElem.getSemantic(), vertElem.getSemanticIdx());
+			streamOffsets[streamIdx] += vertElem.getSize();
+		}
+
+		cm_deleteN<ScratchAlloc>(streamOffsets, numStreams);
+
+		return declaration;
+	}
+
+	UINT32 VertexDataDesc::getMaxStreamIdx() const
+	{
+		UINT32 maxStreamIdx = 0;
+		for(auto& vertElems : mVertexElements)
+		{
+			UINT32 offset = 0;
+			for(auto& vertElem : mVertexElements)
+			{
+				maxStreamIdx = std::max((UINT32)maxStreamIdx, (UINT32)vertElem.getStreamIdx());
+			}
+		}
+
+		return maxStreamIdx;
+	}
+
+	bool VertexDataDesc::hasStream(UINT32 streamIdx) const
+	{
+		for(auto& vertElem : mVertexElements)
+		{
+			if(vertElem.getStreamIdx() == streamIdx)
+				return true;
+		}
+
+		return false;
+	}
+
+	bool VertexDataDesc::hasElement(VertexElementSemantic semantic, UINT32 semanticIdx, UINT32 streamIdx) const
+	{
+		auto findIter = std::find_if(mVertexElements.begin(), mVertexElements.end(), 
+			[semantic, semanticIdx, streamIdx] (const VertexElement& x) 
+		{ 
+			return x.getSemantic() == semantic && x.getSemanticIdx() == semanticIdx && x.getStreamIdx() == streamIdx; 
+		});
+
+		if(findIter != mVertexElements.end())
+		{
+			return true;
+		}
+
+		return false;
+	}
+
+	UINT32 VertexDataDesc::getElementSize(VertexElementSemantic semantic, UINT32 semanticIdx, UINT32 streamIdx) const
+	{
+		for(auto& element : mVertexElements)
+		{
+			if(element.getSemantic() == semantic && element.getSemanticIdx() == semanticIdx && element.getStreamIdx() == streamIdx)
+				return element.getSize();
+		}
+
+		return -1;
+	}
+
+	UINT32 VertexDataDesc::getElementOffsetFromStream(VertexElementSemantic semantic, UINT32 semanticIdx, UINT32 streamIdx) const
+	{
+		UINT32 vertexOffset = 0;
+		for(auto& element : mVertexElements)
+		{
+			if(element.getStreamIdx() != streamIdx)
+				continue;
+
+			if(element.getSemantic() == semantic && element.getSemanticIdx() == semanticIdx)
+				break;
+
+			vertexOffset += element.getSize();
+		}
+
+		return vertexOffset;
+	}
+
+	UINT32 VertexDataDesc::getVertexStride(UINT32 streamIdx) const
+	{
+		UINT32 vertexStride = 0;
+		for(auto& element : mVertexElements)
+		{
+			if(element.getStreamIdx() == streamIdx)
+				vertexStride += element.getSize();
+		}
+
+		return vertexStride;
+	}
+
+	UINT32 VertexDataDesc::getVertexStride() const
+	{
+		UINT32 vertexStride = 0;
+		for(auto& element : mVertexElements)
+		{
+			vertexStride += element.getSize();
+		}
+
+		return vertexStride;
+	}
+
+	UINT32 VertexDataDesc::getStreamOffset(UINT32 streamIdx) const
+	{
+		UINT32 streamOffset = 0;
+		bool found = false;
+		for(auto& element : mVertexElements)
+		{
+			if(element.getStreamIdx() == streamIdx)
+				break;
+
+			streamOffset += element.getSize();
+		}
+
+		return streamOffset;
+	}
+
+	void VertexDataDesc::clearIfItExists(VertexElementType type, VertexElementSemantic semantic, UINT32 semanticIdx, UINT32 streamIdx)
+	{
+		auto findIter = std::find_if(mVertexElements.begin(), mVertexElements.end(), 
+			[semantic, semanticIdx, streamIdx] (const VertexElement& x) 
+		{ 
+			return x.getSemantic() == semantic && x.getSemanticIdx() == semanticIdx && x.getStreamIdx() == streamIdx; 
+		});
+
+		if(findIter != mVertexElements.end())
+		{
+			mVertexElements.erase(findIter);
+		}
+	}
+
+	/************************************************************************/
+	/* 								SERIALIZATION                      		*/
+	/************************************************************************/
+
+	RTTITypeBase* VertexDataDesc::getRTTIStatic()
+	{
+		return VertexDataDescRTTI::instance();
+	}
+
+	RTTITypeBase* VertexDataDesc::getRTTI() const
+	{
+		return VertexDataDesc::getRTTIStatic();
+	}
+}

+ 23 - 14
CamelotFBXImporter/Source/CmFBXImporter.cpp

@@ -9,6 +9,7 @@
 #include "CmVector2.h"
 #include "CmVector3.h"
 #include "CmVector4.h"
+#include "CmVertexDataDesc.h"
 
 namespace CamelotFramework
 {
@@ -177,7 +178,10 @@ namespace CamelotFramework
 	MeshDataPtr FBXImporter::parseMesh(FbxMesh* mesh, bool createTangentsIfMissing)
 	{
 		if (!mesh->GetNode())
-			return cm_shared_ptr<MeshData, ScratchAlloc>(0);
+		{
+			VertexDataDescPtr tmpVertDesc = cm_shared_ptr<VertexDataDesc>();
+			return cm_shared_ptr<MeshData, ScratchAlloc>(0, 0, tmpVertDesc);
+		}
 
 		// Find out which vertex attributes exist
 		bool allByControlPoint = true;
@@ -283,36 +287,35 @@ namespace CamelotFramework
 
 		UINT32 vertexCount = lPolygonVertexCount;
 
-		MeshDataPtr meshData = cm_shared_ptr<MeshData, ScratchAlloc>(vertexCount);
-		
-		meshData->beginDesc();
-		meshData->addVertElem(VET_FLOAT3, VES_POSITION);
+		VertexDataDescPtr vertexDesc = cm_shared_ptr<VertexDataDesc>();
+
+		vertexDesc->addVertElem(VET_FLOAT3, VES_POSITION);
 
 		if(hasColor)
-			meshData->addVertElem(VET_COLOR, VES_COLOR);
+			vertexDesc->addVertElem(VET_COLOR, VES_COLOR);
 
 		if(hasNormal)
-			meshData->addVertElem(VET_FLOAT3, VES_NORMAL);
+			vertexDesc->addVertElem(VET_FLOAT3, VES_NORMAL);
 
 		if(hasTangent)
-			meshData->addVertElem(VET_FLOAT3, VES_TANGENT);
+			vertexDesc->addVertElem(VET_FLOAT3, VES_TANGENT);
 
 		if(hasBitangent)
-			meshData->addVertElem(VET_FLOAT3, VES_BITANGENT);
+			vertexDesc->addVertElem(VET_FLOAT3, VES_BITANGENT);
 
 		FbxStringList lUVNames;
 		mesh->GetUVSetNames(lUVNames);
 		const char * lUVName0 = NULL;
 		if (hasUV0 && lUVNames.GetCount() > 0)
 		{
-			meshData->addVertElem(VET_FLOAT2, VES_TEXCOORD, 0);
+			vertexDesc->addVertElem(VET_FLOAT2, VES_TEXCOORD, 0);
 			lUVName0 = lUVNames[0];
 		}
 
 		const char * lUVName1 = NULL;
 		if (hasUV1 && lUVNames.GetCount() > 1)
 		{
-			meshData->addVertElem(VET_FLOAT2, VES_TEXCOORD, 1);
+			vertexDesc->addVertElem(VET_FLOAT2, VES_TEXCOORD, 1);
 			lUVName1 = lUVNames[1];
 		}
 
@@ -321,6 +324,7 @@ namespace CamelotFramework
 		FbxGeometryElement::EMappingMode lMaterialMappingMode = FbxGeometryElement::eNone;
 		Vector<SubMesh>::type subMeshes;
 
+		UINT32 numIndices = 0;
 		if (mesh->GetElementMaterial())
 		{
 			lMaterialIndice = &mesh->GetElementMaterial()->GetIndexArray();
@@ -349,7 +353,8 @@ namespace CamelotFramework
 					{
 						subMeshes[lIndex].indexOffset = lOffset;
 						lOffset += subMeshes[lIndex].indexCount;
-						meshData->addSubMesh(subMeshes[lIndex].indexCount, lIndex);
+
+						numIndices += subMeshes[lIndex].indexCount;
 					}
 					FBX_ASSERT(lOffset == lPolygonCount * 3);
 				}
@@ -359,12 +364,16 @@ namespace CamelotFramework
 		// All faces will use the same material.
 		if (subMeshes.size() == 0)
 		{
+			numIndices = lPolygonCount * 3;
+
 			subMeshes.resize(1);
 			subMeshes[0].indexCount = lPolygonCount * 3;
-			meshData->addSubMesh(subMeshes[0].indexCount);
 		}
 
-		meshData->endDesc();
+		MeshDataPtr meshData = cm_shared_ptr<MeshData, ScratchAlloc>(vertexCount, numIndices, vertexDesc);
+
+		for(UINT32 i = 0; i < (UINT32)subMeshes.size(); i++)
+			meshData->addSubMesh(subMeshes[i].indexCount, i);
 
 		// Allocate the array memory, by control point or by polygon vertex.
 		VertexElemIter<Vector3> positions = meshData->getVec3DataIter(VES_POSITION);

+ 45 - 3
Opts.txt

@@ -2,9 +2,6 @@ Make sure to also update TextSprite and ImageSprite and anything else in UpdateM
 
 GpuParamBlock should be tied directly with GpuParamBlockBuffer
   - Modify material so it always sets just the first GpuParams with a specific name. This will avoid updating same buffer multiple times.
-When GpuParams are destroyed (when another shader is set in Material for example), make sure to set all GpuParam internal data to null
-Add material parameter handles for texture, sampler state, and structs
-
 
 FrameAlloc
    Keeps two internal stacks
@@ -32,3 +29,48 @@ When optimizing UpdateLayout make sure to mark elements that are fully culled as
 
  -------------
 
+ Mesh
+ - Change initialization so it requires number of vertices, indices and vertex description, also number of vertex streams
+ - Move those required fields from MeshData into another MeshDesc structure that is used for initialization
+ - During initialization also provide STATIC or DYNAMIC flags
+ - writeSubresource
+  - add size and offset fields in MeshData which tell the method where exactly to write data and how much data is used
+    - also determines which part of the buffer is rendered
+    - throw exception if mesh data offset/size go over the limit of the buffer
+  - add "discardEntireBuffer" flag
+   - ensure buffer is compatible with the flag (I think it needs to be dynamic)
+ - allocateSubresourceBuffer used for reading must not be broken by these changes
+ - Don't forget to update mesh RTTI
+ - Implement VertexDataDesc and use it during Mesh initialization, and also internally in MeshData
+
+Texture
+ - Texture already works the way mesh should
+
+TransientMesh
+ - Only used for writing, only dynamic, and only MAP_NO_OVERWRITE writing
+ - Accepts starting buffer sizes, and will enlarge them as needed
+  - When buffer is enlarged send a warning so user knows to use a bigger buffer next time
+ - Keeps track of parts of the buffer used by GPU using GPU queries
+
+----------
+
+OT: When setting buffers I should modify RenderSystem::setVertexBuffer so it can accept multiple buffers. So when mesh is bound all its streams can be bound in one call.
+
+BIG TODO FINALLY: Reorganize GUI so it all uses one big vertex buffer (probably in the form of a TransientMesh). This means I need better support for drawing individual objects
+from a transient mesh by drawing only parts of its buffer. But only do this after I have optimized and tested the normal mesh (on all render systems)
+
+---------
+
+Immediate implementation issues:
+MeshData with 0 submeshes should be assumed to have one sub-mesh that covers the entire buffer. I need to take that into consideration when writing to resource.
+
+Places that use MeshData:
+DrawHelper2D, DrawHelper3D - 5 methods each
+GUIManager::updateMeshes
+DockManager:updateDropOverlay
+FBXImporter::parseMesh
+
+Fix how I handle sub-meshes
+ - right now they are read on sim thread, but set on core thread which is wrong
+
+ Don't forget to add vert/index offsets to meshData