2
0
Эх сурвалжийг харах

Refactored Mesh for use with the new CoreObject design

Marko Pintera 11 жил өмнө
parent
commit
2870e2266b
36 өөрчлөгдсөн 703 нэмэгдсэн , 558 устгасан
  1. 0 1
      BansheeCore/BansheeCore.vcxproj
  2. 0 3
      BansheeCore/BansheeCore.vcxproj.filters
  3. 7 0
      BansheeCore/Include/BsCoreObject.h
  4. 6 0
      BansheeCore/Include/BsCoreObjectCore.h
  5. 4 2
      BansheeCore/Include/BsCorePrerequisites.h
  6. 106 57
      BansheeCore/Include/BsMesh.h
  7. 92 78
      BansheeCore/Include/BsMeshBase.h
  8. 8 8
      BansheeCore/Include/BsMeshBaseRTTI.h
  9. 7 0
      BansheeCore/Include/BsMeshData.h
  10. 4 3
      BansheeCore/Include/BsMeshHeap.h
  11. 0 19
      BansheeCore/Include/BsMeshProxy.h
  12. 1 1
      BansheeCore/Include/BsRenderer.h
  13. 39 25
      BansheeCore/Include/BsTransientMesh.h
  14. 2 0
      BansheeCore/Include/BsVertexDataDesc.h
  15. 26 2
      BansheeCore/Source/BsCoreObjectManager.cpp
  16. 155 175
      BansheeCore/Source/BsMesh.cpp
  17. 61 18
      BansheeCore/Source/BsMeshBase.cpp
  18. 56 0
      BansheeCore/Source/BsMeshData.cpp
  19. 4 4
      BansheeCore/Source/BsMeshHeap.cpp
  20. 2 4
      BansheeCore/Source/BsMeshRTTI.h
  21. 2 11
      BansheeCore/Source/BsRenderer.cpp
  22. 28 32
      BansheeCore/Source/BsTransientMesh.cpp
  23. 7 7
      BansheeEditor/Include/BsGizmoManager.h
  24. 6 6
      BansheeEditor/Include/BsHandleDrawManager.h
  25. 1 1
      BansheeEditor/Include/BsScenePicking.h
  26. 26 32
      BansheeEditor/Source/BsGizmoManager.cpp
  27. 14 14
      BansheeEditor/Source/BsHandleDrawManager.cpp
  28. 4 11
      BansheeEditor/Source/BsScenePicking.cpp
  29. 5 2
      BansheeEngine/Include/BsRenderQueue.h
  30. 8 3
      BansheeEngine/Include/BsRenderableProxy.h
  31. 7 3
      BansheeEngine/Source/BsRenderQueue.cpp
  32. 1 1
      BansheeEngine/Source/BsRenderable.cpp
  33. 4 22
      BansheeEngine/Source/BsRenderableHandler.cpp
  34. 2 1
      BansheeEngine/Source/BsRenderableProxy.cpp
  35. 4 10
      BansheeRenderer/Source/BsBansheeRenderer.cpp
  36. 4 2
      TODO.txt

+ 0 - 1
BansheeCore/BansheeCore.vcxproj

@@ -277,7 +277,6 @@
     <ClInclude Include="Include\BsDrawList.h" />
     <ClInclude Include="Include\BsMaterialParam.h" />
     <ClInclude Include="Include\BsMaterialProxy.h" />
-    <ClInclude Include="Include\BsMeshProxy.h" />
     <ClInclude Include="Include\BsRenderStats.h" />
     <ClInclude Include="Include\BsCoreThread.h" />
     <ClInclude Include="Include\BsProfilerCPU.h" />

+ 0 - 3
BansheeCore/BansheeCore.vcxproj.filters

@@ -507,9 +507,6 @@
     <ClInclude Include="Include\BsDrawList.h">
       <Filter>Header Files\Renderer</Filter>
     </ClInclude>
-    <ClInclude Include="Include\BsMeshProxy.h">
-      <Filter>Header Files\Renderer</Filter>
-    </ClInclude>
     <ClInclude Include="Include\BsMaterialProxy.h">
       <Filter>Header Files\Renderer</Filter>
     </ClInclude>

+ 7 - 0
BansheeCore/Include/BsCoreObject.h

@@ -210,6 +210,7 @@ namespace BansheeEngine
 		 */
 		static void executeReturnGpuCommand(std::shared_ptr<CoreObject> obj, std::function<void(AsyncOp&)> func, AsyncOp& op); 
 
+	protected:
 		/************************************************************************/
 		/* 							CORE OBJECT SYNC                      		*/
 		/************************************************************************/
@@ -245,12 +246,18 @@ namespace BansheeEngine
 		/**
 		 * @brief	Copy internal dirty data to a memory buffer that will be used
 		 *			for updating core thread version of that data.
+		 *
+		 * @note	This generally happens at the end of every sim thread frame. Synced data becomes
+		 *			available to the core thread the start of the next core thread frame.
 		 */
 		virtual CoreSyncData syncToCore(FrameAlloc* allocator) { return CoreSyncData(); }
 
 		/**
 		 * @brief	Update internal data from provided memory buffer that
 		 *			was populated with data from the core thread.
+		 *
+		 * @note	This generally happens at the start of every sim thread frame. Provided data
+		 *			is from a previous core thread frame.
 		 */
 		virtual void syncFromCore(const CoreSyncData& data) { }
 

+ 6 - 0
BansheeCore/Include/BsCoreObjectCore.h

@@ -37,12 +37,18 @@ namespace BansheeEngine
 		/**
 		 * @brief	Copy internal dirty data to a memory buffer that will be used
 		 *			for updating sim thread version of that data.
+		 *
+		 * @note	This generally happens at the end of a core thread frame. Data is then passed
+		 *			to the sim thread and will be available on the next sim thread frame.
 		 */
 		virtual CoreSyncData syncFromCore(FrameAlloc* allocator) { return CoreSyncData(); }
 
 		/**
 		 * @brief	Update internal data from provided memory buffer that
 		 *			was populated with data from the sim thread.
+		 *
+		 * @note	This generally happens at the start of a core thread frame. Data used was
+		 *			recorded on the previous sim thread frame.
 		 */
 		virtual void syncToCore(const CoreSyncData& data) { }
 

+ 4 - 2
BansheeCore/Include/BsCorePrerequisites.h

@@ -140,10 +140,13 @@ namespace BansheeEngine
 	class CameraProxy;
 	struct MaterialProxy;
 	struct MaterialProxyPass;
-	struct MeshProxy;
+	class MeshCoreBase;
+	class MeshCore;
 	struct ShaderProxy;
 	class ViewportProxy;
 	class DrawList;
+	struct SubMesh;
+	class TransientMeshCore;
 	// Asset import
 	class SpecificImporter;
 	class Importer;
@@ -242,7 +245,6 @@ namespace BansheeEngine
 	typedef std::shared_ptr<RenderQueue> RenderQueuePtr;
 	typedef std::shared_ptr<CameraProxy> CameraProxyPtr;
 	typedef std::shared_ptr<MaterialProxy> MaterialProxyPtr;
-	typedef std::shared_ptr<MeshProxy> MeshProxyPtr;
 	typedef std::shared_ptr<ShaderProxy> ShaderProxyPtr;
 	typedef std::shared_ptr<ViewportProxy> ViewportProxyPtr;
 	typedef std::shared_ptr<GpuParamDesc> GpuParamDescPtr;

+ 106 - 57
BansheeCore/Include/BsMesh.h

@@ -11,73 +11,140 @@
 namespace BansheeEngine
 {
 	/**
-	 * @brief	Primary class for holding geometry. Stores data in the form of a vertex 
-	 *			buffers and optionally index buffer, which may be bound to the pipeline for drawing.
-	 *			May contain multiple sub-meshes.
+	 * @brief	Core thread portion of a Mesh.
+	 *
+	 * @see		Mesh.
+	 *
+	 * @note	Core thread.
 	 */
-	class BS_CORE_EXPORT Mesh : public MeshBase
+	class BS_CORE_EXPORT MeshCore : public MeshCoreBase
 	{
 	public:
-		virtual ~Mesh();
+		MeshCore(UINT32 numVertices, UINT32 numIndices, const VertexDataDescPtr& vertexDesc,
+			const Vector<SubMesh>& subMeshes, MeshBufferType bufferType, IndexType indexType,
+			MeshDataPtr initialMeshData);
 
 		/**
-		 * @copydoc	MeshBase::initialize
+		 * @brief	CoreObjectCore::initialize
 		 */
 		virtual void initialize();
 
 		/**
-		 * @copydoc GpuResource::_writeSubresourceSim
+		 * @brief	CoreObjectCore::destroy
 		 */
-		virtual void _writeSubresourceSim(UINT32 subresourceIdx, const GpuResourceData& data, bool discardEntireBuffer);
+		virtual void destroy();
 
 		/**
-		 * @copydoc GpuResource::writeSubresource
+		 * @copydoc MeshCoreBase::getVertexData
 		 */
-		virtual void writeSubresource(UINT32 subresourceIdx, const GpuResourceData& data, bool discardEntireBuffer);
+		virtual SPtr<VertexData> getVertexData() const;
 
 		/**
-		 * @copydoc GpuResource::readSubresource
+		 * @copydoc MeshCoreBase::getIndexBuffer
 		 */
-		virtual void readSubresource(UINT32 subresourceIdx, GpuResourceData& data);
+		virtual SPtr<IndexBufferCore> getIndexBuffer() const;
 
 		/**
-		 * @brief	Allocates a buffer you may use for storage when reading a subresource. You
-		 * 			need to allocate such a buffer if you are calling "readSubresource".
-		 * 			
-		 * @param	subresourceIdx	Only 0 is supported. You can only update entire mesh at once.
+		 * @brief	Updates a part of the current mesh with the provided data.
 		 *
-		 * @note	This method is thread safe.
+		 * @param	subresourceIdx		Index of the subresource to update, if the mesh has more than one.
+		 * @param	data				Data to update the mesh with.
+		 * @param	discardEntireBuffer When true the existing contents of the resource you are updating will be discarded. This can make the
+		 * 								operation faster. Resources with certain buffer types might require this flag to be in a specific state
+		 * 								otherwise the operation will fail.
+		 * @param	updateBounds		If true the internal bounds of the mesh will be recalculated based on the provided data.
 		 */
-		MeshDataPtr allocateSubresourceBuffer(UINT32 subresourceIdx) const;
+		virtual void writeSubresource(UINT32 subresourceIdx, const MeshData& data, bool discardEntireBuffer, bool updateBounds = true);
 
 		/**
-		 * @brief	Returns bounds of the geometry contained in the vertex buffers for all sub-meshes.
+		 * @brief	Reads a part of the current resource into the provided "data" parameter.
+		 * 			Data buffer needs to be pre-allocated.
+		 *
+		 * @param	subresourceIdx		Index of the subresource to update, if the mesh has more than one.
+		 * @param	data				Buffer that will receive the data. Should be allocated with "allocateSubresourceBuffer"
+		 *								to ensure it is of valid type and size.
 		 */
-		const Bounds& getBounds() const { return mBounds; }
+		virtual void readSubresource(UINT32 subresourceIdx, MeshData& data);
+
+	protected:
+		friend class Mesh;
 
 		/**
-		 * @copydoc MeshBase::getVertexData
+		 * @brief	Updates bounds by calculating them from the vertices in the provided mesh data object.
 		 */
-		virtual SPtr<VertexData> getVertexData() const;
+		void updateBounds(const MeshData& meshData);
+
+		std::shared_ptr<VertexData> mVertexData;
+		SPtr<IndexBufferCore> mIndexBuffer;
+
+		VertexDataDescPtr mVertexDesc;
+		MeshBufferType mBufferType;
+		IndexType mIndexType;
+		MeshDataPtr mTempInitialMeshData;
+	};
+
+	/**
+	 * @brief	Primary class for holding geometry. Stores data in the form of a vertex 
+	 *			buffers and optionally index buffer, which may be bound to the pipeline for drawing.
+	 *			May contain multiple sub-meshes.
+	 *
+	 * @note	Sim thread.
+	 */
+	class BS_CORE_EXPORT Mesh : public MeshBase
+	{
+	public:
+		virtual ~Mesh();
 
 		/**
-		 * @copydoc MeshBase::getIndexBuffer
+		 * @copydoc	MeshBase::initialize
 		 */
-		virtual SPtr<IndexBufferCore> getIndexBuffer() const;
+		virtual void initialize();
 
 		/**
-		 * @brief	Returns a dummy mesh, containing just one triangle. Don't modify the returned mesh.
+		 * @brief	Updates the mesh with new data. The actual write will be queued for later execution on the core thread.
+		 *			Provided data buffer will be locked until the operation completes.
+		 *
+		 * @param	accessor			Accessor to queue the operation on.
+		 * 
+		 * @return	Async operation object you can use to track operation completion.
+		 *
+		 * @see		MeshCore::writeSubresource
 		 */
-		static HMesh dummy();
+		AsyncOp writeSubresource(CoreAccessor& accessor, UINT32 subresourceIdx, const MeshDataPtr& data, bool discardEntireBuffer);
 
-		/************************************************************************/
-		/* 								CORE PROXY                      		*/
-		/************************************************************************/
+		/**
+		 * @brief	Reads internal mesh data to the provided previously allocated buffer. The read is queued for execution
+		 *			on the core thread and not executed immediately. Provided data buffer will be locked until the
+		 *			operation completes.
+		 *
+		 * @param	accessor			Accessor to queue the operation on.
+		 *
+		 * @return	Async operation object you can use to track operation completion.
+		 *
+		 * @see		MeshCore::readSubresource
+		 */
+		AsyncOp readSubresource(CoreAccessor& accessor, UINT32 subresourceIdx, const MeshDataPtr& data);
+
+		/**
+		 * @brief	Allocates a buffer you may use for storage when reading a subresource. You
+		 * 			need to allocate such a buffer if you are calling "readSubresource".
+		 * 			
+		 * @param	subresourceIdx	Only 0 is supported. You can only update entire mesh at once.
+		 *
+		 * @note	Thread safe.
+		 */
+		MeshDataPtr allocateSubresourceBuffer(UINT32 subresourceIdx) const;
 
 		/**
-		 * @copydoc	MeshBase::_createProxy
+		 * @brief	Retrieves a core implementation of a mesh usable only from the
+		 *			core thread.
 		 */
-		MeshProxyPtr _createProxy(UINT32 subMeshIdx);
+		SPtr<MeshCore> getCore() const;
+
+		/**
+		 * @brief	Returns a dummy mesh, containing just one triangle. Don't modify the returned mesh.
+		 */
+		static HMesh dummy();
 
 	protected:
 		friend class MeshManager;
@@ -95,39 +162,21 @@ namespace BansheeEngine
 
 		Mesh(const MeshDataPtr& initialMeshData, const Vector<SubMesh>& subMeshes, MeshBufferType bufferType = MeshBufferType::Static);
 
-		std::shared_ptr<VertexData> mVertexData; // Core thread
-		SPtr<IndexBufferCore> mIndexBuffer; // Core thread
-
-		Bounds mBounds; // Core thread
-		VertexDataDescPtr mVertexDesc; // Immutable
-		MeshBufferType mBufferType; // Immutable
-		IndexType mIndexType; // Immutable
-
-		MeshDataPtr mTempInitialMeshData; // Immutable
-
-		/**
-		 * @copydoc Resource::initialize_internal()
-		 */
-		virtual void initialize_internal();
-
-		/**
-		 * @copydoc Resource::destroy_internal()
-		 */
-		virtual void destroy_internal();
-
 		/**
 		 * @brief	Updates bounds by calculating them from the vertices in the provided mesh data object.
 		 */
 		void updateBounds(const MeshData& meshData);
 
 		/**
-		 * @brief	Calculates bounds surrounding the vertices in the provided buffer.
-		 *
-		 * @param	verticesPtr	Pointer to the buffer containing the positions of vertices to calculate bounds for.
-		 * @param	numVertices	Number of vertices in the provided buffer.
-		 * @param	stride		How many bytes are needed to advance from one vertex to another.
+		 * @copydoc	RenderTarget::createCore
 		 */
-		Bounds calculateBounds(UINT8* verticesPtr, UINT32 numVertices, UINT32 stride) const;
+		SPtr<CoreObjectCore> createCore() const;
+
+		mutable MeshDataPtr mTempInitialMeshData;
+
+		VertexDataDescPtr mVertexDesc;
+		MeshBufferType mBufferType;
+		IndexType mIndexType;
 
 		/************************************************************************/
 		/* 								SERIALIZATION                      		*/

+ 92 - 78
BansheeCore/Include/BsMeshBase.h

@@ -5,7 +5,6 @@
 #include "BsBounds.h"
 #include "BsDrawOps.h"
 #include "BsSubMesh.h"
-#include "BsMeshProxy.h"
 
 namespace BansheeEngine
 {
@@ -31,78 +30,77 @@ namespace BansheeEngine
 	};
 
 	/**
-	 * @brief	Base class all mesh implementations derive from. Meshes hold geometry information,
-	 *			normally in the form of one or serveral index or vertex buffers. Different mesh implementations
-	 *			might choose to manage those buffers differently.
-	 *
-	 * @note	Core thread only unless noted otherwise.
+	 * @brief	Contains various properties describing a mesh.
 	 */
-	class BS_CORE_EXPORT MeshBase : public GpuResource
+	class BS_CORE_EXPORT MeshProperties
 	{
 	public:
-		/**
-		 * @brief	Constructs a new mesh with no sub-meshes.
-		 *
-		 * @param	numVertices		Number of vertices in the mesh.
-		 * @param	numIndices		Number of indices in the mesh. 
-		 * @param	drawOp			Determines how should the provided indices be interpreted by the pipeline. Default option is triangles,
-		 *							where three indices represent a single triangle.
-		 */
-		MeshBase(UINT32 numVertices, UINT32 numIndices, DrawOperationType drawOp = DOT_TRIANGLE_LIST);
-
-		/**
-		 * @brief	Constructs a new mesh with one or multiple sub-meshes. (When using just one sub-mesh it is equivalent
-		 *			to using the other overload).
-		 *
-		 * @param	numVertices		Number of vertices in the mesh.
-		 * @param	numIndices		Number of indices in the mesh.
-		 * @param	subMeshes		Defines how are indices separated into sub-meshes, and how are those sub-meshes rendered.
-		 */
-		MeshBase(UINT32 numVertices, UINT32 numIndices, const Vector<SubMesh>& subMeshes);
-
-		virtual ~MeshBase();
+		MeshProperties();
+		MeshProperties(UINT32 numVertices, UINT32 numIndices, DrawOperationType drawOp);
+		MeshProperties(UINT32 numVertices, UINT32 numIndices, const Vector<SubMesh>& subMeshes);
 
 		/**
 		 * @brief	Retrieves a sub-mesh containing data used for rendering a
 		 * 			certain portion of this mesh. If no sub-meshes are specified manually
 		 *			a special sub-mesh containing all indices is returned.
-		 *
-		 * @note	Thread safe.
 		 */
 		const SubMesh& getSubMesh(UINT32 subMeshIdx = 0) const;
 
 		/**
 		 * @brief	Retrieves a total number of sub-meshes in this mesh.
-		 *
-		 * @note	Thread safe.
 		 */
 		UINT32 getNumSubMeshes() const;
 
 		/**
 		 * @brief	Returns maximum number of vertices the mesh may store.
-		 *
-		 * @note	Thread safe.
 		 */
 		UINT32 getNumVertices() const { return mNumVertices; }
 
 		/**
 		 * @brief	Returns maximum number of indices the mesh may store.
-		 *
-		 * @note	Thread safe.
 		 */
 		UINT32 getNumIndices() const { return mNumIndices; }
 
+		/**
+		 * @brief	Returns bounds of the geometry contained in the vertex buffers for all sub-meshes.
+		 */
+		const Bounds& getBounds() const { return mBounds; }
+
+	protected:
+		friend class MeshBase;
+		friend class MeshCoreBase;
+		friend class Mesh;
+		friend class MeshCore;
+		friend class TransientMesh;
+		friend class TransientMeshCore;
+		friend class MeshBaseRTTI;
+
+		Vector<SubMesh> mSubMeshes;
+		UINT32 mNumVertices;
+		UINT32 mNumIndices;
+		Bounds mBounds;
+	};
+
+	/**
+	 * @brief	Core version of a class used as a basis for all implemenations of meshes.
+	 *
+	 * @see		MeshBase
+	 *
+	 * @note	Core thread.
+	 */
+	class BS_CORE_EXPORT MeshCoreBase : public CoreObjectCore
+	{
+	public:
+		MeshCoreBase(UINT32 numVertices, UINT32 numIndices, const Vector<SubMesh>& subMeshes);
+		virtual ~MeshCoreBase() { }
+
 		/**
 		 * @brief	Get vertex data used for rendering.
-		 *  
-		 * @note	Core thread only. Internal method.
 		 */
 		virtual SPtr<VertexData> getVertexData() const = 0;
 
 		/**
 		 * @brief	Get index data used for rendering.
-		 *  
-		 * @note	Core thread only. Internal method.
 		 */
 		virtual SPtr<IndexBufferCore> getIndexBuffer() const = 0;
 
@@ -112,8 +110,6 @@ namespace BansheeEngine
 		 * 			begin.
 		 * 			
 		 * @note	Used when multiple meshes share the same buffers.
-		 * 			
-		 *			Core thread only. Internal method.
 		 */
 		virtual UINT32 getVertexOffset() const { return 0; }
 
@@ -123,8 +119,6 @@ namespace BansheeEngine
 		 * 			begin.
 		 * 			
 		 * @note	Used when multiple meshes share the same buffers.
-		 * 			
-		 *			Core thread only. Internal method.
 		 */
 		virtual UINT32 getIndexOffset() const { return 0; }
 
@@ -134,70 +128,90 @@ namespace BansheeEngine
 		 * @note	Needs to be called after all commands referencing this 
 		 * 			mesh have been sent to the GPU.
 		 * 			
-		 *			Core thread only. Internal method.
+		 *			Internal method.
 		 */
 		virtual void _notifyUsedOnGPU() { }
 
-		/************************************************************************/
-		/* 								CORE PROXY                      		*/
-		/************************************************************************/
+		/**
+		 * @brief	Returns properties that contain information about the mesh.
+		 */
+		const MeshProperties& getProperties() const { return mProperties; }
 
+	protected:
 		/**
-		 * @brief	Checks is the core dirty flag set. This is used by external systems 
-		 *			to know when internal data has changed and core thread potentially needs to be notified.
-		 *
-		 * @note	Sim thread only.
+		 * @copydoc	CoreObjectCore::syncFromCore
 		 */
-		bool _isCoreDirty(MeshDirtyFlag flag) const { return (mCoreDirtyFlags & (UINT32)flag) != 0; }
+		virtual CoreSyncData syncFromCore(FrameAlloc* allocator);
 
 		/**
-		 * @brief	Marks the core dirty flag as clean.
+		 * @copydoc	CoreObjectCore::syncToCore
+		 */
+		virtual void syncToCore(const CoreSyncData& data);
+
+		MeshProperties mProperties;
+	};
+
+	/**
+	 * @brief	Base class all mesh implementations derive from. Meshes hold geometry information,
+	 *			normally in the form of one or several index or vertex buffers. Different mesh implementations
+	 *			might choose to manage those buffers differently.
+	 *
+	 * @note	Sim thread.
+	 */
+	class BS_CORE_EXPORT MeshBase : public Resource
+	{
+	public:
+		/**
+		 * @brief	Constructs a new mesh with no sub-meshes.
 		 *
-		 * @note	Sim thread only.
+		 * @param	numVertices		Number of vertices in the mesh.
+		 * @param	numIndices		Number of indices in the mesh. 
+		 * @param	drawOp			Determines how should the provided indices be interpreted by the pipeline. Default option is triangles,
+		 *							where three indices represent a single triangle.
 		 */
-		void _markCoreClean(MeshDirtyFlag flag) { mCoreDirtyFlags &= ~(UINT32)flag; }
+		MeshBase(UINT32 numVertices, UINT32 numIndices, DrawOperationType drawOp = DOT_TRIANGLE_LIST);
 
 		/**
-		 * @brief	Gets the currently active proxy of this material.
+		 * @brief	Constructs a new mesh with one or multiple sub-meshes. (When using just one sub-mesh it is equivalent
+		 *			to using the other overload).
+		 *
+		 * @param	numVertices		Number of vertices in the mesh.
+		 * @param	numIndices		Number of indices in the mesh.
+		 * @param	subMeshes		Defines how are indices separated into sub-meshes, and how are those sub-meshes rendered.
 		 */
-		MeshProxyPtr _getActiveProxy(UINT32 i) const { return mActiveProxies[i]; }
+		MeshBase(UINT32 numVertices, UINT32 numIndices, const Vector<SubMesh>& subMeshes);
+
+		virtual ~MeshBase();
 
 		/**
-		 * @brief	Sets an active proxy for this material.
+		 * @brief	Returns properties that contain information about the mesh.
 		 */
-		void _setActiveProxy(UINT32 i, const MeshProxyPtr& proxy) { mActiveProxies[i] = proxy; }
+		const MeshProperties& getProperties() const { return mProperties; }
 
 		/**
-		 * @brief	Creates a new core proxy from the current mesh data. Core proxy contains a snapshot of 
-		 *			mesh data normally managed on the sim thread (e.g. bounds).
-		 *
-		 * @param	subMeshIdx	Index of the sub-mesh to create a proxy for.
-		 *
-		 * @note	Sim thread only. 
-		 *			You generally need to update the core thread with a new proxy whenever core 
-		 *			dirty flag is set.
+		 * @brief	Retrieves a core implementation of a mesh usable only from the
+		 *			core thread.
 		 */
-		virtual MeshProxyPtr _createProxy(UINT32 subMeshIdx) = 0;
+		SPtr<MeshCoreBase> getCore() const;
 
 	protected:
 		/**
-		 * @brief	Marks the core data as dirty.
+		 * @copydoc	CoreObject::syncToCore
 		 */
-		void markCoreDirty() { mCoreDirtyFlags = 0xFFFFFFFF; }
+		virtual CoreSyncData syncToCore(FrameAlloc* allocator);
 
-	protected:
-		Vector<SubMesh> mSubMeshes; // Immutable
-		UINT32 mNumVertices; // Immutable
-		UINT32 mNumIndices; // Immutable
-		Vector<MeshProxyPtr> mActiveProxies;
+		/**
+		 * @copydoc	CoreObject::syncFromCore
+		 */
+		virtual void syncFromCore(const CoreSyncData& data);
 
-		UINT32 mCoreDirtyFlags;
+		MeshProperties mProperties;
 
 		/************************************************************************/
 		/* 								SERIALIZATION                      		*/
 		/************************************************************************/
 	private:
-		MeshBase(); // Serialization only
+		MeshBase() { } // Serialization only
 
 	public:
 		friend class MeshBaseRTTI;

+ 8 - 8
BansheeCore/Include/BsMeshBaseRTTI.h

@@ -12,16 +12,16 @@ namespace BansheeEngine
 
 	class MeshBaseRTTI : public RTTIType<MeshBase, GpuResource, MeshBaseRTTI>
 	{
-		SubMesh& getSubMesh(MeshBase* obj, UINT32 arrayIdx) { return obj->mSubMeshes[arrayIdx]; }
-		void setSubMesh(MeshBase* obj, UINT32 arrayIdx, SubMesh& value) { obj->mSubMeshes[arrayIdx] = value; }
-		UINT32 getNumSubmeshes(MeshBase* obj) { return (UINT32)obj->mSubMeshes.size(); }
-		void setNumSubmeshes(MeshBase* obj, UINT32 numElements) { obj->mSubMeshes.resize(numElements); obj->mActiveProxies.resize(numElements); }
+		SubMesh& getSubMesh(MeshBase* obj, UINT32 arrayIdx) { return obj->mProperties.mSubMeshes[arrayIdx]; }
+		void setSubMesh(MeshBase* obj, UINT32 arrayIdx, SubMesh& value) { obj->mProperties.mSubMeshes[arrayIdx] = value; }
+		UINT32 getNumSubmeshes(MeshBase* obj) { return (UINT32)obj->mProperties.mSubMeshes.size(); }
+		void setNumSubmeshes(MeshBase* obj, UINT32 numElements) { obj->mProperties.mSubMeshes.resize(numElements); }
 
-		UINT32& getNumVertices(MeshBase* obj) { return obj->mNumVertices; }
-		void setNumVertices(MeshBase* obj, UINT32& value) { obj->mNumVertices = value; }
+		UINT32& getNumVertices(MeshBase* obj) { return obj->mProperties.mNumVertices; }
+		void setNumVertices(MeshBase* obj, UINT32& value) { obj->mProperties.mNumVertices = value; }
 
-		UINT32& getNumIndices(MeshBase* obj) { return obj->mNumIndices; }
-		void setNumIndices(MeshBase* obj, UINT32& value) { obj->mNumIndices = value; }
+		UINT32& getNumIndices(MeshBase* obj) { return obj->mProperties.mNumIndices; }
+		void setNumIndices(MeshBase* obj, UINT32& value) { obj->mProperties.mNumIndices = value; }
 
 	public:
 		MeshBaseRTTI()

+ 7 - 0
BansheeCore/Include/BsMeshData.h

@@ -201,6 +201,11 @@ namespace BansheeEngine
 		 */
 		const VertexDataDescPtr& getVertexDesc() const { return mVertexData; }
 
+		/**
+		 * @brief	Calculates the bounds of all vertices stored in the internal buffer.
+		 */
+		Bounds calculateBounds() const;
+
 		/**
 		 * @brief	Combines a number of submeshes and their mesh data into one large mesh data buffer.
 		 *
@@ -273,7 +278,9 @@ namespace BansheeEngine
 
 	private:
 		friend class Mesh;
+		friend class MeshCore;
 		friend class MeshHeap;
+		friend class MeshHeapCore;
 
 		UINT32 mDescBuilding;
 

+ 4 - 3
BansheeCore/Include/BsMeshHeap.h

@@ -54,7 +54,7 @@ namespace BansheeEngine
 
 			UseFlags useFlags;
 			UINT32 eventQueryIdx;
-			TransientMeshPtr mesh;
+			SPtr<TransientMeshCore> mesh;
 		};
 
 		/**
@@ -97,6 +97,7 @@ namespace BansheeEngine
 
 	private:
 		friend class TransientMesh;
+		friend class TransientMeshCore;
 
 		/**
 		 * @copydoc	create
@@ -122,7 +123,7 @@ namespace BansheeEngine
 		 *
 		 * @note	Core thread.
 		 */
-		void allocInternal(TransientMeshPtr mesh, const MeshDataPtr& meshData);
+		void allocInternal(SPtr<TransientMeshCore> mesh, const MeshDataPtr& meshData);
 
 		/**
 		 * @brief	Deallocates the provided mesh Freed memory
@@ -130,7 +131,7 @@ namespace BansheeEngine
 		 *
 		 * @note	Core thread.
 		 */
-		void deallocInternal(TransientMeshPtr mesh);
+		void deallocInternal(SPtr<TransientMeshCore> mesh);
 
 		/**
 		 * @brief	Resizes the vertex buffers so they max contain the provided

+ 0 - 19
BansheeCore/Include/BsMeshProxy.h

@@ -1,19 +0,0 @@
-#pragma once
-
-#include "BsCorePrerequisites.h"
-#include "BsSubMesh.h"
-#include "BsBounds.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * Contains part of Mesh data that is used on the core thread for rendering.
-	 */
-	struct BS_CORE_EXPORT MeshProxy
-	{
-		std::weak_ptr<MeshBase> mesh;
-		SubMesh subMesh;
-		Bounds bounds;
-		UINT32 submeshIdx;
-	};
-}

+ 1 - 1
BansheeCore/Include/BsRenderer.h

@@ -82,7 +82,7 @@ namespace BansheeEngine
 		 *
 		 * @note	Core thread only.
 		 */
-		static void draw(const MeshProxy& mesh);
+		static void draw(const SPtr<MeshCoreBase>& mesh, const SubMesh& subMesh);
 
 		/**
 		 * @brief	Callback that gets triggered before a viewport gets rendered.

+ 39 - 25
BansheeCore/Include/BsTransientMesh.h

@@ -6,38 +6,26 @@
 namespace BansheeEngine
 {
 	/**
-	 * @brief	Represents a single mesh entry in the MeshHeap. This can be used as a normal mesh
-	 *			but due to the nature of the mesh-heap it is not the type of mesh you should use
-	 *			for storing static data.
+	 * @brief	Core thread portion of a transient mesh.
 	 *
-	 *			Transient meshes don't keep internal index/vertex buffers but instead use the ones
-	 *			provided by their parent mesh heap.
+	 * @see		Transient mesh
 	 *
-	 * @see		MeshHeap
+	 * @note	Core thread.
 	 */
-	class BS_CORE_EXPORT TransientMesh : public MeshBase
+	class BS_CORE_EXPORT TransientMeshCore : public MeshCoreBase
 	{
 	public:
-		virtual ~TransientMesh();
-
-		/**
-		 * @copydoc GpuResource::writeSubresource
-		 */
-		virtual void writeSubresource(UINT32 subresourceIdx, const GpuResourceData& data, bool discardEntireBuffer);
+		TransientMeshCore(const MeshHeapPtr& parentHeap, UINT32 id, UINT32 numVertices,
+			UINT32 numIndices, const Vector<SubMesh>& subMeshes);
 
 		/**
-		 * @copydoc GpuResource::readSubresource
-		 */
-		virtual void readSubresource(UINT32 subresourceIdx, GpuResourceData& data);
-
-		 /**
 		 * @copydoc MeshBase::getVertexData
 		 */
 		SPtr<VertexData> getVertexData() const;
 
 		 /**
-		 * @copydoc MeshBase::getIndexData
-		 */
+		  * @copydoc MeshBase::getIndexData
+		  */
 		SPtr<IndexBufferCore> getIndexBuffer() const;
 
 		/**
@@ -60,14 +48,35 @@ namespace BansheeEngine
 		 */
 		virtual void _notifyUsedOnGPU();
 
-		/************************************************************************/
-		/* 								CORE PROXY                      		*/
-		/************************************************************************/
+	protected:
+		friend class TransientMesh;
+
+		MeshHeapPtr mParentHeap;
+		UINT32 mId;
+	};
+
+	/**
+	 * @brief	Represents a single mesh entry in the MeshHeap. This can be used as a normal mesh
+	 *			but due to the nature of the mesh-heap it is not the type of mesh you should use
+	 *			for storing static data.
+	 *
+	 *			Transient meshes don't keep internal index/vertex buffers but instead use the ones
+	 *			provided by their parent mesh heap.
+	 *
+	 * @see		MeshHeap
+	 *
+	 * @note	Sim thread.
+	 */
+	class BS_CORE_EXPORT TransientMesh : public MeshBase
+	{
+	public:
+		virtual ~TransientMesh();
 
 		/**
-		 * @copydoc	MeshBase::_createProxy
+		 * @brief	Retrieves a core implementation of a mesh usable only from the
+		 *			core thread.
 		 */
-		MeshProxyPtr _createProxy(UINT32 subMeshIdx);
+		SPtr<TransientMeshCore> getCore() const;
 
 	protected:
 		friend class MeshHeap;
@@ -85,6 +94,11 @@ namespace BansheeEngine
 		 */
 		void markAsDestroyed() { mIsDestroyed = true; }
 
+		/**
+		 * @copydoc	RenderTarget::createCore
+		 */
+		SPtr<CoreObjectCore> createCore() const;
+
 	protected:
 		bool mIsDestroyed;
 		MeshHeapPtr mParentHeap;

+ 2 - 0
BansheeCore/Include/BsVertexDataDesc.h

@@ -72,7 +72,9 @@ namespace BansheeEngine
 		const VertexElement& getElement(UINT32 idx) const { return mVertexElements[idx]; }
 	private:
 		friend class Mesh;
+		friend class MeshCore;
 		friend class MeshHeap;
+		friend class MeshHeapCore;
 
 		/**
 		 * @brief	Returns the largest stream index of all the stored vertex elements.

+ 26 - 2
BansheeCore/Source/BsCoreObjectManager.cpp

@@ -48,8 +48,32 @@ namespace BansheeEngine
 
 		UINT64 internalId = object->getInternalID();
 		mObjects.erase(internalId);
-		mSimSyncData.erase(internalId);
-		mCoreSyncData.erase(internalId);
+
+		{
+			auto iterFind = mSimSyncData.find(internalId);
+			if (iterFind != mSimSyncData.end())
+			{
+				UINT8* data = iterFind->second.syncData.getBuffer();
+
+				if (data != nullptr && mSimSyncDataAlloc != nullptr)
+					mSimSyncDataAlloc->dealloc(data);
+
+				mSimSyncData.erase(iterFind);
+			}
+		}
+
+		{
+			auto iterFind = mCoreSyncData.find(internalId);
+			if (iterFind != mCoreSyncData.end())
+			{
+				UINT8* data = iterFind->second.syncData.getBuffer();
+
+				if (data != nullptr && mCoreSyncDataAlloc != nullptr)
+					mCoreSyncDataAlloc->dealloc(data);
+
+				mCoreSyncData.erase(iterFind);
+			}
+		}
 	}
 
 	void CoreObjectManager::syncDownload(CoreObjectSync type, FrameAlloc* allocator)

+ 155 - 175
BansheeCore/Source/BsMesh.cpp

@@ -15,64 +15,89 @@
 
 namespace BansheeEngine
 {
-	Mesh::Mesh(UINT32 numVertices, UINT32 numIndices, const VertexDataDescPtr& vertexDesc, 
-		MeshBufferType bufferType, DrawOperationType drawOp, IndexType indexType)
-		:MeshBase(numVertices, numIndices, drawOp), mVertexData(nullptr), mIndexBuffer(nullptr),
-		mVertexDesc(vertexDesc), mBufferType(bufferType), mIndexType(indexType)
+	MeshCore::MeshCore(UINT32 numVertices, UINT32 numIndices, const VertexDataDescPtr& vertexDesc,
+		const Vector<SubMesh>& subMeshes, MeshBufferType bufferType, IndexType indexType, MeshDataPtr initialMeshData)
+		:MeshCoreBase(numVertices, numIndices, subMeshes), mVertexData(nullptr), mIndexBuffer(nullptr), 
+		mVertexDesc(vertexDesc), mBufferType(bufferType), mIndexType(indexType), mTempInitialMeshData(initialMeshData)
+	{ }
+
+	void MeshCore::initialize()
 	{
+		THROW_IF_NOT_CORE_THREAD;
 
-	}
+		mIndexBuffer = HardwareBufferCoreManager::instance().createIndexBuffer(mIndexType,
+			mProperties.mNumIndices, mBufferType == MeshBufferType::Dynamic ? GBU_DYNAMIC : GBU_STATIC);
 
-	Mesh::Mesh(UINT32 numVertices, UINT32 numIndices, const VertexDataDescPtr& vertexDesc,
-		const Vector<SubMesh>& subMeshes, MeshBufferType bufferType, IndexType indexType)
-		:MeshBase(numVertices, numIndices, subMeshes), mVertexData(nullptr), mIndexBuffer(nullptr),
-		mVertexDesc(vertexDesc), mBufferType(bufferType), mIndexType(indexType)
-	{
+		mVertexData = std::shared_ptr<VertexData>(bs_new<VertexData, PoolAlloc>());
 
-	}
+		mVertexData->vertexCount = mProperties.mNumVertices;
+		mVertexData->vertexDeclaration = mVertexDesc->createDeclaration();
 
-	Mesh::Mesh(const MeshDataPtr& initialMeshData, MeshBufferType bufferType, DrawOperationType drawOp)
-		:MeshBase(initialMeshData->getNumVertices(), initialMeshData->getNumIndices(), drawOp), 
-		mVertexData(nullptr), mIndexBuffer(nullptr), mIndexType(initialMeshData->getIndexType()),
-		mVertexDesc(initialMeshData->getVertexDesc()), mTempInitialMeshData(initialMeshData)
-	{
+		for (UINT32 i = 0; i <= mVertexDesc->getMaxStreamIdx(); i++)
+		{
+			if (!mVertexDesc->hasStream(i))
+				continue;
 
-	}
+			SPtr<VertexBufferCore> vertexBuffer = HardwareBufferCoreManager::instance().createVertexBuffer(
+				mVertexData->vertexDeclaration->getVertexSize(i),
+				mVertexData->vertexCount,
+				mBufferType == MeshBufferType::Dynamic ? GBU_DYNAMIC : GBU_STATIC);
 
-	Mesh::Mesh(const MeshDataPtr& initialMeshData, const Vector<SubMesh>& subMeshes, MeshBufferType bufferType)
-		:MeshBase(initialMeshData->getNumVertices(), initialMeshData->getNumIndices(), subMeshes),
-		mVertexData(nullptr), mIndexBuffer(nullptr), mIndexType(initialMeshData->getIndexType()),
-		mVertexDesc(initialMeshData->getVertexDesc()), mTempInitialMeshData(initialMeshData)
-	{
+			mVertexData->setBuffer(i, vertexBuffer);
+		}
 
+		// TODO Low priority - DX11 (and maybe OpenGL)? allow an optimization that allows you to set
+		// buffer data upon buffer construction, instead of setting it in a second step like I do here
+		if (mTempInitialMeshData != nullptr)
+		{
+			writeSubresource(0, *mTempInitialMeshData, mBufferType == MeshBufferType::Dynamic);
+			mTempInitialMeshData = nullptr;
+		}
+
+		MeshCoreBase::initialize();
 	}
 
-	Mesh::Mesh()
-		:MeshBase(0, 0, DOT_TRIANGLE_LIST), mVertexData(nullptr), mIndexBuffer(nullptr), 
-		mBufferType(MeshBufferType::Static), mIndexType(IT_32BIT)
+	void MeshCore::destroy()
 	{
+		THROW_IF_NOT_CORE_THREAD;
 
-	}
+		if (mVertexData != nullptr)
+		{
+			for (UINT32 i = 0; i < mVertexData->getBufferCount(); i++)
+			{
+				if (mVertexData->getBuffer(i) != nullptr)
+					mVertexData->getBuffer(i)->destroy();
+			}
+		}
 
-	Mesh::~Mesh()
-	{
-		
+		if (mIndexBuffer != nullptr)
+			mIndexBuffer->destroy();
+
+		mVertexData = nullptr;
+		mIndexBuffer = nullptr;
+		mVertexDesc = nullptr;
+		mTempInitialMeshData = nullptr;
+
+		MeshCoreBase::destroy();
 	}
 
-	void Mesh::_writeSubresourceSim(UINT32 subresourceIdx, const GpuResourceData& data, bool discardEntireBuffer)
+	std::shared_ptr<VertexData> MeshCore::getVertexData() const
 	{
-		const MeshData& meshData = static_cast<const MeshData&>(data);
-		updateBounds(meshData);
+		THROW_IF_NOT_CORE_THREAD;
+
+		return mVertexData;
 	}
 
-	void Mesh::writeSubresource(UINT32 subresourceIdx, const GpuResourceData& data, bool discardEntireBuffer)
+	SPtr<IndexBufferCore> MeshCore::getIndexBuffer() const
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
-		if(data.getTypeId() != TID_MeshData)
-			BS_EXCEPT(InvalidParametersException, "Invalid GpuResourceData type. Only MeshData is supported.");
+		return mIndexBuffer;
+	}
 
-		const MeshData& meshData = static_cast<const MeshData&>(data);
+	void MeshCore::writeSubresource(UINT32 subresourceIdx, const MeshData& meshData, bool discardEntireBuffer, bool performUpdateBounds)
+	{
+		THROW_IF_NOT_CORE_THREAD;
 
 		if (discardEntireBuffer)
 		{
@@ -166,28 +191,26 @@ namespace BansheeEngine
 				vertexBuffer->writeData(0, bufferSize, srcVertBufferData, discardEntireBuffer ? BufferWriteType::Discard : BufferWriteType::Normal);
 			}
 		}
+
+		if (performUpdateBounds)
+			updateBounds(meshData);
 	}
 
-	void Mesh::readSubresource(UINT32 subresourceIdx, GpuResourceData& data)
+	void MeshCore::readSubresource(UINT32 subresourceIdx, MeshData& meshData)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
-		if(data.getTypeId() != TID_MeshData)
-			BS_EXCEPT(InvalidParametersException, "Invalid GpuResourceData type. Only MeshData is supported.");
-
 		IndexType indexType = IT_32BIT;
 		if (mIndexBuffer)
 			indexType = mIndexBuffer->getProperties().getType();
 
-		MeshData& meshData = static_cast<MeshData&>(data);
-
-		if(mIndexBuffer)
+		if (mIndexBuffer)
 		{
 			const IndexBufferProperties& ibProps = mIndexBuffer->getProperties();
 
 			if (meshData.getIndexElementSize() != ibProps.getIndexSize())
 			{
-				BS_EXCEPT(InvalidParametersException, "Provided index size doesn't match meshes index size. Needed: " + 
+				BS_EXCEPT(InvalidParametersException, "Provided index size doesn't match meshes index size. Needed: " +
 					toString(ibProps.getIndexSize()) + ". Got: " + toString(meshData.getIndexElementSize()));
 			}
 
@@ -196,15 +219,15 @@ namespace BansheeEngine
 
 			UINT8* indices = nullptr;
 
-			if(indexType == IT_16BIT)
+			if (indexType == IT_16BIT)
 				indices = (UINT8*)meshData.getIndices16();
 			else
 				indices = (UINT8*)meshData.getIndices32();
 
-			UINT32 numIndicesToCopy = std::min(mNumIndices, meshData.getNumIndices());
+			UINT32 numIndicesToCopy = std::min(mProperties.mNumIndices, meshData.getNumIndices());
 
 			UINT32 indicesSize = numIndicesToCopy * idxElemSize;
-			if(indicesSize > meshData.getIndexBufferSize())
+			if (indicesSize > meshData.getIndexBufferSize())
 				BS_EXCEPT(InvalidParametersException, "Provided buffer doesn't have enough space to store mesh indices.");
 
 			memcpy(indices, idxData, numIndicesToCopy * idxElemSize);
@@ -212,14 +235,14 @@ namespace BansheeEngine
 			mIndexBuffer->unlock();
 		}
 
-		if(mVertexData)
+		if (mVertexData)
 		{
 			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)
 			{
-				if(!meshData.getVertexDesc()->hasStream(streamIdx))
+				if (!meshData.getVertexDesc()->hasStream(streamIdx))
 					continue;
 
 				SPtr<VertexBufferCore> vertexBuffer = iter->second;
@@ -228,16 +251,16 @@ namespace BansheeEngine
 				// Ensure both have the same sized vertices
 				UINT32 myVertSize = mVertexDesc->getVertexStride(streamIdx);
 				UINT32 otherVertSize = meshData.getVertexDesc()->getVertexStride(streamIdx);
-				if(myVertSize != otherVertSize)
+				if (myVertSize != otherVertSize)
 				{
-					BS_EXCEPT(InvalidParametersException, "Provided vertex size for stream " + toString(streamIdx) + " doesn't match meshes vertex size. Needed: " + 
+					BS_EXCEPT(InvalidParametersException, "Provided vertex size for stream " + toString(streamIdx) + " doesn't match meshes vertex size. Needed: " +
 						toString(myVertSize) + ". Got: " + toString(otherVertSize));
 				}
 
 				UINT32 numVerticesToCopy = meshData.getNumVertices();
 				UINT32 bufferSize = vbProps.getVertexSize() * numVerticesToCopy;
-				
-				if(bufferSize > vertexBuffer->getSizeInBytes())
+
+				if (bufferSize > vertexBuffer->getSizeInBytes())
 					BS_EXCEPT(InvalidParametersException, "Vertex buffer values for stream \"" + toString(streamIdx) + "\" are being read out of valid range.");
 
 				UINT8* vertDataPtr = static_cast<UINT8*>(vertexBuffer->lock(GBL_READ_ONLY));
@@ -252,173 +275,130 @@ namespace BansheeEngine
 		}
 	}
 
-	MeshDataPtr Mesh::allocateSubresourceBuffer(UINT32 subresourceIdx) const
+	void MeshCore::updateBounds(const MeshData& meshData)
 	{
-		IndexType indexType = IT_32BIT;
-		if(mIndexBuffer)
-			indexType = mIndexBuffer->getProperties().getType();
+		mProperties.mBounds = meshData.calculateBounds();
+		markCoreDirty();
+	}
 
-		MeshDataPtr meshData = bs_shared_ptr<MeshData>(mVertexData->vertexCount, mNumIndices, mVertexDesc, indexType);
+	Mesh::Mesh(UINT32 numVertices, UINT32 numIndices, const VertexDataDescPtr& vertexDesc, 
+		MeshBufferType bufferType, DrawOperationType drawOp, IndexType indexType)
+		:MeshBase(numVertices, numIndices, drawOp), mVertexDesc(vertexDesc), mBufferType(bufferType), 
+		mIndexType(indexType)
+	{
 
-		return meshData;
 	}
 
-	std::shared_ptr<VertexData> Mesh::getVertexData() const
+	Mesh::Mesh(UINT32 numVertices, UINT32 numIndices, const VertexDataDescPtr& vertexDesc,
+		const Vector<SubMesh>& subMeshes, MeshBufferType bufferType, IndexType indexType)
+		:MeshBase(numVertices, numIndices, subMeshes), mVertexDesc(vertexDesc), mBufferType(bufferType), 
+		mIndexType(indexType)
 	{
-		THROW_IF_NOT_CORE_THREAD;
 
-		return mVertexData;
 	}
 
-	SPtr<IndexBufferCore> Mesh::getIndexBuffer() const
+	Mesh::Mesh(const MeshDataPtr& initialMeshData, MeshBufferType bufferType, DrawOperationType drawOp)
+		:MeshBase(initialMeshData->getNumVertices(), initialMeshData->getNumIndices(), drawOp), 
+		mIndexType(initialMeshData->getIndexType()), mVertexDesc(initialMeshData->getVertexDesc()), 
+		mTempInitialMeshData(initialMeshData)
 	{
-		THROW_IF_NOT_CORE_THREAD;
 
-		return mIndexBuffer;
 	}
 
-	void Mesh::initialize()
+	Mesh::Mesh(const MeshDataPtr& initialMeshData, const Vector<SubMesh>& subMeshes, MeshBufferType bufferType)
+		:MeshBase(initialMeshData->getNumVertices(), initialMeshData->getNumIndices(), subMeshes),
+		mIndexType(initialMeshData->getIndexType()), mVertexDesc(initialMeshData->getVertexDesc()), 
+		mTempInitialMeshData(initialMeshData)
 	{
-		if (mTempInitialMeshData != nullptr)
-		{
-			updateBounds(*mTempInitialMeshData);
-		}
 
-		MeshBase::initialize();
 	}
 
-	void Mesh::initialize_internal()
+	Mesh::Mesh()
+		:MeshBase(0, 0, DOT_TRIANGLE_LIST), mBufferType(MeshBufferType::Static), mIndexType(IT_32BIT)
 	{
-		THROW_IF_NOT_CORE_THREAD;
-		
-		mIndexBuffer = HardwareBufferCoreManager::instance().createIndexBuffer(mIndexType,
-			mNumIndices, mBufferType == MeshBufferType::Dynamic ? GBU_DYNAMIC : GBU_STATIC);
 
-		mVertexData = std::shared_ptr<VertexData>(bs_new<VertexData, PoolAlloc>());
-
-		mVertexData->vertexCount = mNumVertices;
-		mVertexData->vertexDeclaration = mVertexDesc->createDeclaration();
+	}
 
-		for(UINT32 i = 0; i <= mVertexDesc->getMaxStreamIdx(); i++)
-		{
-			if(!mVertexDesc->hasStream(i))
-				continue;
+	Mesh::~Mesh()
+	{
+		
+	}
 
-			SPtr<VertexBufferCore> vertexBuffer = HardwareBufferCoreManager::instance().createVertexBuffer(
-				mVertexData->vertexDeclaration->getVertexSize(i),
-				mVertexData->vertexCount,
-				mBufferType == MeshBufferType::Dynamic ? GBU_DYNAMIC : GBU_STATIC);
+	AsyncOp Mesh::writeSubresource(CoreAccessor& accessor, UINT32 subresourceIdx, const MeshDataPtr& data, bool discardEntireBuffer)
+	{
+		updateBounds(*data);
 
-			mVertexData->setBuffer(i, vertexBuffer);
-		}
+		data->_lock();
 
-		// TODO Low priority - DX11 (and maybe OpenGL)? allow an optimization that allows you to set
-		// buffer data upon buffer construction, instead of setting it in a second step like I do here
-		if(mTempInitialMeshData != nullptr)
+		std::function<void(const SPtr<MeshCore>&, UINT32, const MeshDataPtr&, bool, AsyncOp&)> func =
+			[&](const SPtr<MeshCore>& mesh, UINT32 _subresourceIdx, const MeshDataPtr& _meshData, bool _discardEntireBuffer, AsyncOp& asyncOp)
 		{
-			writeSubresource(0, *mTempInitialMeshData, mBufferType == MeshBufferType::Dynamic);
-			mTempInitialMeshData = nullptr;
-		}
+			mesh->writeSubresource(_subresourceIdx, *_meshData, _discardEntireBuffer, false);
+			_meshData->_unlock();
+			asyncOp._completeOperation();
 
-		MeshBase::initialize_internal();
+		};
+
+		return accessor.queueReturnCommand(std::bind(func, getCore(), subresourceIdx,
+			 data, discardEntireBuffer, std::placeholders::_1));
 	}
 
-	void Mesh::destroy_internal()
+	AsyncOp Mesh::readSubresource(CoreAccessor& accessor, UINT32 subresourceIdx, const MeshDataPtr& data)
 	{
-		THROW_IF_NOT_CORE_THREAD;
+		updateBounds(*data);
 
-		if (mVertexData != nullptr)
-		{
-			for (UINT32 i = 0; i < mVertexData->getBufferCount(); i++)
-			{
-				if (mVertexData->getBuffer(i) != nullptr)
-					mVertexData->getBuffer(i)->destroy();
-			}
-		}
+		data->_lock();
 
-		if (mIndexBuffer != nullptr)
-			mIndexBuffer->destroy();
+		std::function<void(const SPtr<MeshCore>&, UINT32, const MeshDataPtr&, AsyncOp&)> func =
+			[&](const SPtr<MeshCore>& mesh, UINT32 _subresourceIdx, const MeshDataPtr& _meshData, AsyncOp& asyncOp)
+		{
+			mesh->readSubresource(_subresourceIdx, *_meshData);
+			_meshData->_unlock();
+			asyncOp._completeOperation();
 
-		mVertexData = nullptr;
-		mIndexBuffer = nullptr;
-		mVertexDesc = nullptr;
-		mTempInitialMeshData = nullptr;
+		};
 
-		MeshBase::destroy_internal();
+		return accessor.queueReturnCommand(std::bind(func, getCore(), subresourceIdx,
+			data, std::placeholders::_1));
 	}
 
-	void Mesh::updateBounds(const MeshData& meshData)
+	MeshDataPtr Mesh::allocateSubresourceBuffer(UINT32 subresourceIdx) const
 	{
-		VertexDataDescPtr vertexDesc = meshData.getVertexDesc();
-		for (UINT32 i = 0; i < vertexDesc->getNumElements(); i++)
-		{
-			const VertexElement& curElement = vertexDesc->getElement(i);
-
-			if (curElement.getSemantic() != VES_POSITION || (curElement.getType() != VET_FLOAT3 && curElement.getType() != VET_FLOAT4))
-				continue;
-
-			UINT8* data = meshData.getElementData(curElement.getSemantic(), curElement.getSemanticIdx(), curElement.getStreamIdx());
-			UINT32 stride = vertexDesc->getVertexStride(curElement.getStreamIdx());
+		MeshDataPtr meshData = bs_shared_ptr<MeshData>(mProperties.mNumVertices, mProperties.mNumIndices, mVertexDesc, mIndexType);
 
-			mBounds = calculateBounds((UINT8*)data, mTempInitialMeshData->getNumVertices(), stride);
-			markCoreDirty();
-
-			break;
-		}
+		return meshData;
 	}
 
-	Bounds Mesh::calculateBounds(UINT8* verticesPtr, UINT32 numVertices, UINT32 stride) const
+	void Mesh::initialize()
 	{
-		Bounds bounds;
-
-		if (mNumVertices > 0)
+		if (mTempInitialMeshData != nullptr)
 		{
-			Vector3 accum;
-			Vector3 min;
-			Vector3 max;
-
-			Vector3 curPosition = *(Vector3*)verticesPtr;
-			accum = curPosition;
-			min = curPosition;
-			max = curPosition;
-
-			for (UINT32 i = 1; i < mNumVertices; i++)
-			{
-				curPosition = *(Vector3*)(verticesPtr + stride * i);
-				accum += curPosition;
-				min = Vector3::min(min, curPosition);
-				max = Vector3::max(max, curPosition);
-			}
-
-			Vector3 center = accum / (float)mNumVertices;
-			float radiusSqrd = 0.0f;
-
-			for (UINT32 i = 0; i < mNumVertices; i++)
-			{
-				curPosition = *(Vector3*)(verticesPtr + stride * i);
-				float dist = center.squaredDistance(curPosition);
-
-				if (dist > radiusSqrd)
-					radiusSqrd = dist;
-			}
+			updateBounds(*mTempInitialMeshData);
+		}
 
-			float radius = Math::sqrt(radiusSqrd);
+		MeshBase::initialize();
+	}
 
-			bounds = Bounds(AABox(min, max), Sphere(center, radius));
-		}
+	void Mesh::updateBounds(const MeshData& meshData)
+	{
+		mProperties.mBounds = meshData.calculateBounds();
+		markCoreDirty();
+	}
 
-		return bounds;
+	SPtr<MeshCore> Mesh::getCore() const
+	{
+		return std::static_pointer_cast<MeshCore>(mCoreSpecific);
 	}
 
-	MeshProxyPtr Mesh::_createProxy(UINT32 subMeshIdx)
+	SPtr<CoreObjectCore> Mesh::createCore() const
 	{
-		MeshProxyPtr coreProxy = bs_shared_ptr<MeshProxy>();
-		coreProxy->mesh = std::static_pointer_cast<MeshBase>(getThisPtr());
-		coreProxy->bounds = mBounds;
-		coreProxy->subMesh = getSubMesh(subMeshIdx);
-		coreProxy->submeshIdx = subMeshIdx;
+		MeshCore* obj = new (bs_alloc<MeshCore>()) MeshCore(mProperties.mNumVertices, mProperties.mNumIndices, 
+			mVertexDesc, mProperties.mSubMeshes, mBufferType, mIndexType, mTempInitialMeshData);
+
+		SPtr<CoreObjectCore> meshCore = bs_shared_ptr<MeshCore, GenAlloc>(obj);
+		mTempInitialMeshData = nullptr;
 
-		return coreProxy;
+		return meshCore;
 	}
 
 	HMesh Mesh::dummy()

+ 61 - 18
BansheeCore/Source/BsMeshBase.cpp

@@ -1,48 +1,91 @@
 #include "BsMeshBase.h"
 #include "BsMeshBaseRTTI.h"
 #include "BsCoreThread.h"
+#include "BsFrameAlloc.h"
 #include "BsDebug.h"
 
 namespace BansheeEngine
 {
-	MeshBase::MeshBase(UINT32 numVertices, UINT32 numIndices, DrawOperationType drawOp)
-		:mNumIndices(numIndices), mNumVertices(numVertices), mCoreDirtyFlags(0xFFFFFF)
+	MeshProperties::MeshProperties()
+		:mNumIndices(0), mNumVertices(0)
+	{
+		mSubMeshes.reserve(10);
+	}
+
+	MeshProperties::MeshProperties(UINT32 numVertices, UINT32 numIndices, DrawOperationType drawOp)
+		:mNumIndices(numIndices), mNumVertices(numVertices)
 	{
 		mSubMeshes.push_back(SubMesh(0, numIndices, drawOp));
-		mActiveProxies.resize(mSubMeshes.size());
 	}
 
-	MeshBase::MeshBase(UINT32 numVertices, UINT32 numIndices, const Vector<SubMesh>& subMeshes)
-		: mNumIndices(numIndices), mNumVertices(numVertices), mCoreDirtyFlags(0xFFFFFF)
+	MeshProperties::MeshProperties(UINT32 numVertices, UINT32 numIndices, const Vector<SubMesh>& subMeshes)
+		:mNumIndices(numIndices), mNumVertices(numVertices)
 	{
 		mSubMeshes = subMeshes;
-		mActiveProxies.resize(mSubMeshes.size());
 	}
 
-	MeshBase::MeshBase()
+	const SubMesh& MeshProperties::getSubMesh(UINT32 subMeshIdx) const
 	{
-		mSubMeshes.reserve(10);
+		if (subMeshIdx < 0 || subMeshIdx >= mSubMeshes.size())
+		{
+			BS_EXCEPT(InvalidParametersException, "Invalid sub-mesh index ("
+				+ toString(subMeshIdx) + "). Number of sub-meshes available: " + toString((int)mSubMeshes.size()));
+		}
+
+		return mSubMeshes[subMeshIdx];
 	}
 
-	MeshBase::~MeshBase()
+	UINT32 MeshProperties::getNumSubMeshes() const
+	{
+		return (UINT32)mSubMeshes.size();
+	}
+
+	MeshCoreBase::MeshCoreBase(UINT32 numVertices, UINT32 numIndices, const Vector<SubMesh>& subMeshes)
+		:mProperties(numVertices, numIndices, subMeshes)
+	{ }
+
+	CoreSyncData MeshCoreBase::syncFromCore(FrameAlloc* allocator)
 	{
+		UINT32 size = sizeof(Bounds);
+		UINT8* buffer = allocator->alloc(size);
 
+		memcpy(buffer, &mProperties.mBounds, size);
+		return CoreSyncData(buffer, size);
 	}
 
-	const SubMesh& MeshBase::getSubMesh(UINT32 subMeshIdx) const
+	void MeshCoreBase::syncToCore(const CoreSyncData& data)
 	{
-		if(subMeshIdx < 0 || subMeshIdx >= mSubMeshes.size())
-		{
-			BS_EXCEPT(InvalidParametersException, "Invalid sub-mesh index (" 
-				+ toString(subMeshIdx) + "). Number of sub-meshes available: " + toString((int)mSubMeshes.size()));
-		}
+		mProperties.mBounds = data.getData<Bounds>();
+	}
 
-		return mSubMeshes[subMeshIdx];
+	MeshBase::MeshBase(UINT32 numVertices, UINT32 numIndices, DrawOperationType drawOp)
+		:mProperties(numVertices, numIndices, drawOp)
+	{ }
+
+	MeshBase::MeshBase(UINT32 numVertices, UINT32 numIndices, const Vector<SubMesh>& subMeshes)
+		:mProperties(numVertices, numIndices, subMeshes)
+	{ }
+
+	MeshBase::~MeshBase()
+	{ }
+
+	CoreSyncData MeshBase::syncToCore(FrameAlloc* allocator)
+	{
+		UINT32 size = sizeof(Bounds);
+		UINT8* buffer = allocator->alloc(size);
+
+		memcpy(buffer, &mProperties.mBounds, size);
+		return CoreSyncData(buffer, size);
 	}
 
-	UINT32 MeshBase::getNumSubMeshes() const
+	void MeshBase::syncFromCore(const CoreSyncData& data)
 	{
-		return (UINT32)mSubMeshes.size();
+		mProperties.mBounds = data.getData<Bounds>();
+	}
+
+	SPtr<MeshCoreBase> MeshBase::getCore() const
+	{
+		return std::static_pointer_cast<MeshCoreBase>(mCoreSpecific);
 	}
 
 	/************************************************************************/

+ 56 - 0
BansheeCore/Source/BsMeshData.cpp

@@ -312,6 +312,62 @@ namespace BansheeEngine
 		return mVertexData->getVertexStride() * mNumVertices;
 	}
 
+	Bounds MeshData::calculateBounds() const
+	{
+		Bounds bounds;
+
+		VertexDataDescPtr vertexDesc = getVertexDesc();
+		for (UINT32 i = 0; i < vertexDesc->getNumElements(); i++)
+		{
+			const VertexElement& curElement = vertexDesc->getElement(i);
+
+			if (curElement.getSemantic() != VES_POSITION || (curElement.getType() != VET_FLOAT3 && curElement.getType() != VET_FLOAT4))
+				continue;
+
+			UINT8* data = getElementData(curElement.getSemantic(), curElement.getSemanticIdx(), curElement.getStreamIdx());
+			UINT32 stride = vertexDesc->getVertexStride(curElement.getStreamIdx());
+
+			if (getNumVertices() > 0)
+			{
+				Vector3 accum;
+				Vector3 min;
+				Vector3 max;
+
+				Vector3 curPosition = *(Vector3*)data;
+				accum = curPosition;
+				min = curPosition;
+				max = curPosition;
+
+				for (UINT32 i = 1; i < getNumVertices(); i++)
+				{
+					curPosition = *(Vector3*)(data + stride * i);
+					accum += curPosition;
+					min = Vector3::min(min, curPosition);
+					max = Vector3::max(max, curPosition);
+				}
+
+				Vector3 center = accum / (float)getNumVertices();
+				float radiusSqrd = 0.0f;
+
+				for (UINT32 i = 0; i < getNumVertices(); i++)
+				{
+					curPosition = *(Vector3*)(data + stride * i);
+					float dist = center.squaredDistance(curPosition);
+
+					if (dist > radiusSqrd)
+						radiusSqrd = dist;
+				}
+
+				float radius = Math::sqrt(radiusSqrd);
+
+				bounds = Bounds(AABox(min, max), Sphere(center, radius));
+				break;
+			}
+		}
+
+		return bounds;
+	}
+
 	/************************************************************************/
 	/* 								SERIALIZATION                      		*/
 	/************************************************************************/

+ 4 - 4
BansheeCore/Source/BsMeshHeap.cpp

@@ -93,7 +93,7 @@ namespace BansheeEngine
 
 		mMeshes[meshIdx] = transientMeshPtr;
 
-		queueGpuCommand(getThisPtr(), std::bind(&MeshHeap::allocInternal, this, transientMeshPtr, meshData));
+		queueGpuCommand(getThisPtr(), std::bind(&MeshHeap::allocInternal, this, transientMeshPtr->getCore(), meshData));
 
 		return transientMeshPtr;
 	}
@@ -107,10 +107,10 @@ namespace BansheeEngine
 		mesh->markAsDestroyed();
 		mMeshes.erase(iterFind);
 
-		queueGpuCommand(getThisPtr(), std::bind(&MeshHeap::deallocInternal, this, mesh));
+		queueGpuCommand(getThisPtr(), std::bind(&MeshHeap::deallocInternal, this, mesh->getCore()));
 	}
 
-	void MeshHeap::allocInternal(TransientMeshPtr mesh, const MeshDataPtr& meshData)
+	void MeshHeap::allocInternal(SPtr<TransientMeshCore> mesh, const MeshDataPtr& meshData)
 	{
 		// Find free vertex chunk and grow if needed
 		UINT32 smallestVertFit = 0;
@@ -327,7 +327,7 @@ namespace BansheeEngine
 		mIndexBuffer->writeData(idxChunkStart * idxSize, meshData->getNumIndices() * idxSize, idxDest, BufferWriteType::NoOverwrite);
 	}
 
-	void MeshHeap::deallocInternal(TransientMeshPtr mesh)
+	void MeshHeap::deallocInternal(SPtr<TransientMeshCore> mesh)
 	{
 		auto findIter = mMeshAllocData.find(mesh->getMeshHeapId());
 		assert(findIter != mMeshAllocData.end());

+ 2 - 4
BansheeCore/Source/BsMeshRTTI.h

@@ -23,11 +23,9 @@ namespace BansheeEngine
 		MeshDataPtr getMeshData(Mesh* obj) 
 		{ 
 			MeshDataPtr meshData = obj->allocateSubresourceBuffer(0);
-			GpuResourcePtr sharedMeshPtr = std::static_pointer_cast<GpuResource>(obj->getThisPtr());
 
-			meshData->_lock();
-			gCoreThread().queueReturnCommand(std::bind(&RenderSystem::readSubresource, RenderSystem::instancePtr(), 
-				sharedMeshPtr, 0, std::static_pointer_cast<GpuResourceData>(meshData), std::placeholders::_1), true);
+			obj->readSubresource(gCoreAccessor(), 0, meshData);
+			gCoreAccessor().submitToCoreThread(true);
 
 			return meshData;
 		}

+ 2 - 11
BansheeCore/Source/BsRenderer.cpp

@@ -2,7 +2,6 @@
 #include "BsCoreThread.h"
 #include "BsRenderSystem.h"
 #include "BsMaterialProxy.h"
-#include "BsMeshProxy.h"
 #include "BsMesh.h"
 #include "BsBlendState.h"
 #include "BsDepthStencilState.h"
@@ -84,19 +83,12 @@ namespace BansheeEngine
 			rs.setRasterizerState(RasterizerState::getDefault());
 	}
 
-	void Renderer::draw(const MeshProxy& meshProxy)
+	void Renderer::draw(const SPtr<MeshCoreBase>& mesh, const SubMesh& subMesh)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
 		RenderSystem& rs = RenderSystem::instance();
-		MeshBasePtr mesh;
-
-		// TODO: Instead of this lock consider just storing all needed data in MeshProxy and not referencing Mesh at all?
-		if (!meshProxy.mesh.expired())
-			mesh = meshProxy.mesh.lock();
-		else
-			return;
-
+		const MeshProperties& meshProps = mesh->getProperties();
 		std::shared_ptr<VertexData> vertexData = mesh->getVertexData();
 
 		rs.setVertexDeclaration(vertexData->vertexDeclaration);
@@ -125,7 +117,6 @@ namespace BansheeEngine
 			rs.setVertexBuffers(startSlot, buffers, endSlot - startSlot + 1);
 		}
 
-		SubMesh subMesh = meshProxy.subMesh;
 		rs.setDrawOperation(subMesh.drawOp);
 
 		SPtr<IndexBufferCore> indexBuffer = mesh->getIndexBuffer();

+ 28 - 32
BansheeCore/Source/BsTransientMesh.cpp

@@ -6,67 +6,63 @@
 
 namespace BansheeEngine
 {
-	TransientMesh::TransientMesh(const MeshHeapPtr& parentHeap, UINT32 id, UINT32 numVertices, UINT32 numIndices, DrawOperationType drawOp)
-		:MeshBase(numVertices, numIndices, drawOp), mParentHeap(parentHeap), mId(id), mIsDestroyed(false)
+	TransientMeshCore::TransientMeshCore(const MeshHeapPtr& parentHeap, UINT32 id, UINT32 numVertices, UINT32 numIndices, const Vector<SubMesh>& subMeshes)
+		:MeshCoreBase(numVertices, numIndices, subMeshes), mParentHeap(parentHeap), mId(id)
 	{
 
 	}
 
-	TransientMesh::~TransientMesh()
+	SPtr<VertexData> TransientMeshCore::getVertexData() const
 	{
-		if (!mIsDestroyed)
-		{
-			TransientMeshPtr meshPtr = std::static_pointer_cast<TransientMesh>(getThisPtr());
-			mParentHeap->dealloc(meshPtr);
-		}
+		return mParentHeap->getVertexData();
 	}
 
-	void TransientMesh::writeSubresource(UINT32 subresourceIdx, const GpuResourceData& data, bool discardEntireBuffer)
+	SPtr<IndexBufferCore> TransientMeshCore::getIndexBuffer() const
 	{
-		BS_EXCEPT(InvalidStateException, "Updating is not supported on a transient mesh.");
+		return mParentHeap->getIndexBuffer();
 	}
 
-	void TransientMesh::readSubresource(UINT32 subresourceIdx, GpuResourceData& data)
+	UINT32 TransientMeshCore::getVertexOffset() const
 	{
-		BS_EXCEPT(InvalidStateException, "Reading is not supported on a transient mesh.");
+		return mParentHeap->getVertexOffset(mId);
 	}
 
-	SPtr<VertexData> TransientMesh::getVertexData() const
+	UINT32 TransientMeshCore::getIndexOffset() const
 	{
-		return mParentHeap->getVertexData();
+		return mParentHeap->getIndexOffset(mId);
 	}
 
-	SPtr<IndexBufferCore> TransientMesh::getIndexBuffer() const
+	void TransientMeshCore::_notifyUsedOnGPU()
 	{
-		return mParentHeap->getIndexBuffer();
+		mParentHeap->notifyUsedOnGPU(mId);
 	}
 
-	UINT32 TransientMesh::getVertexOffset() const
+	TransientMesh::TransientMesh(const MeshHeapPtr& parentHeap, UINT32 id, UINT32 numVertices, UINT32 numIndices, DrawOperationType drawOp)
+		:MeshBase(numVertices, numIndices, drawOp), mParentHeap(parentHeap), mId(id), mIsDestroyed(false)
 	{
-		return mParentHeap->getVertexOffset(mId);
+
 	}
 
-	UINT32 TransientMesh::getIndexOffset() const
+	TransientMesh::~TransientMesh()
 	{
-		return mParentHeap->getIndexOffset(mId);
+		if (!mIsDestroyed)
+		{
+			TransientMeshPtr meshPtr = std::static_pointer_cast<TransientMesh>(getThisPtr());
+			mParentHeap->dealloc(meshPtr);
+		}
 	}
 
-	void TransientMesh::_notifyUsedOnGPU()
+	SPtr<TransientMeshCore> TransientMesh::getCore() const
 	{
-		mParentHeap->notifyUsedOnGPU(mId);
+		return std::static_pointer_cast<TransientMeshCore>(mCoreSpecific);
 	}
 
-	MeshProxyPtr TransientMesh::_createProxy(UINT32 subMeshIdx)
+	SPtr<CoreObjectCore> TransientMesh::createCore() const
 	{
-		MeshProxyPtr coreProxy = bs_shared_ptr<MeshProxy>();		
-		coreProxy->mesh = std::static_pointer_cast<MeshBase>(getThisPtr());
-		coreProxy->subMesh = mSubMeshes[0];
-		coreProxy->submeshIdx = subMeshIdx;
+		TransientMeshCore* core = new (bs_alloc<TransientMeshCore>()) TransientMeshCore(
+			mParentHeap, mId, mProperties.mNumVertices, mProperties.mNumIndices, mProperties.mSubMeshes);
 
-		// Note: Not calculating bounds for transient meshes yet
-		// (No particular reason, I just didn't bother)
-		coreProxy->bounds = Bounds(); 
-		
-		return coreProxy;
+		SPtr<CoreObjectCore> meshCore = bs_shared_ptr<TransientMeshCore, GenAlloc>(core);
+		return meshCore;
 	}
 }

+ 7 - 7
BansheeEditor/Include/BsGizmoManager.h

@@ -211,19 +211,19 @@ namespace BansheeEngine
 		void initialize(const GizmoManager::CoreInitData& initData);
 
 		void render(const CameraProxy& camera);
-		void renderGizmos(Matrix4 viewMatrix, Matrix4 projMatrix, MeshProxyPtr mesh, GizmoManager::GizmoMaterial material);
-		void renderIconGizmos(Rect2I screenArea, MeshProxyPtr mesh, GizmoManager::IconRenderDataVecPtr renderData, bool usePickingMaterial);
+		void renderGizmos(Matrix4 viewMatrix, Matrix4 projMatrix, SPtr<MeshCoreBase> mesh, GizmoManager::GizmoMaterial material);
+		void renderIconGizmos(Rect2I screenArea, SPtr<MeshCoreBase> mesh, GizmoManager::IconRenderDataVecPtr renderData, bool usePickingMaterial);
 
-		void updateData(const RenderTargetPtr& rt, const MeshProxyPtr& solidMeshProxy, const MeshProxyPtr& wireMeshProxy,
-			const MeshProxyPtr& iconMeshProxy, const GizmoManager::IconRenderDataVecPtr& iconRenderData);
+		void updateData(const RenderTargetPtr& rt, const SPtr<MeshCoreBase>& solidMesh, const SPtr<MeshCoreBase>& wireMesh,
+			const SPtr<MeshCoreBase>& iconMesh, const GizmoManager::IconRenderDataVecPtr& iconRenderData);
 
 		static const float PICKING_ALPHA_CUTOFF;
 
 		RenderTargetPtr mSceneRenderTarget;
 
-		MeshProxyPtr mSolidMeshProxy;
-		MeshProxyPtr mWireMeshProxy;
-		MeshProxyPtr mIconMeshProxy;
+		SPtr<MeshCoreBase> mSolidMesh;
+		SPtr<MeshCoreBase> mWireMesh;
+		SPtr<MeshCoreBase> mIconMesh;
 		GizmoManager::IconRenderDataVecPtr mIconRenderData;
 
 		// Immutable

+ 6 - 6
BansheeEditor/Include/BsHandleDrawManager.h

@@ -64,13 +64,13 @@ namespace BansheeEngine
 			Solid, Wire
 		};
 
-		struct MeshProxyData
+		struct MeshData
 		{
-			MeshProxyData(const MeshProxyPtr& proxy, MeshType type)
-				:proxy(proxy), type(type)
+			MeshData(const SPtr<MeshCoreBase>& mesh, MeshType type)
+				:mesh(mesh), type(type)
 			{ }
 
-			MeshProxyPtr proxy;
+			SPtr<MeshCoreBase> mesh;
 			MeshType type;
 		};
 
@@ -84,11 +84,11 @@ namespace BansheeEngine
 
 		void initialize(const MaterialProxyPtr& wireMatProxy, const MaterialProxyPtr& solidMatProxy);
 
-		void updateData(const RenderTargetPtr& rt, const Vector<MeshProxyData>& proxies);
+		void updateData(const RenderTargetPtr& rt, const Vector<MeshData>& meshes);
 		void render(const CameraProxy& camera);
 
 		RenderTargetPtr mSceneRenderTarget;
-		Vector<MeshProxyData> mProxies;
+		Vector<MeshData> mMeshes;
 
 		// Immutable
 		SolidMaterialData mSolidMaterial;

+ 1 - 1
BansheeEditor/Include/BsScenePicking.h

@@ -11,7 +11,7 @@ namespace BansheeEngine
 	{
 		struct RenderablePickData
 		{
-			MeshProxyPtr mesh;
+			SPtr<MeshCore> mesh;
 			UINT32 index;
 			Matrix4 wvpTransform;
 			bool alpha;

+ 26 - 32
BansheeEditor/Source/BsGizmoManager.cpp

@@ -247,19 +247,19 @@ namespace BansheeEngine
 			mDrawHelper->buildMeshes();
 			const Vector<DrawHelper::ShapeMeshData>& meshes = mDrawHelper->getMeshes();
 
-			MeshProxyPtr solidMeshProxy = nullptr;
-			MeshProxyPtr wireMeshProxy = nullptr;
+			SPtr<MeshCoreBase> solidMesh = nullptr;
+			SPtr<MeshCoreBase> wireMesh = nullptr;
 			for (auto& meshData : meshes)
 			{
 				if (meshData.type == DrawHelper::MeshType::Solid)
 				{
-					if (solidMeshProxy == nullptr)
-						solidMeshProxy = meshData.mesh->_createProxy(0);
+					if (solidMesh == nullptr)
+						solidMesh = meshData.mesh->getCore();
 				}
 				else // Wire
 				{
-					if (wireMeshProxy == nullptr)
-						wireMeshProxy = meshData.mesh->_createProxy(0);
+					if (wireMesh == nullptr)
+						wireMesh = meshData.mesh->getCore();
 				}
 			}
 
@@ -268,9 +268,9 @@ namespace BansheeEngine
 			assert(meshes.size() <= 2);
 
 			mIconMesh = buildIconMesh(camera, mIconData, false, iconRenderData);
-			MeshProxyPtr iconMeshProxy = mIconMesh->_createProxy(0);
+			SPtr<MeshCoreBase> iconMesh = mIconMesh->getCore();
 
-			gCoreAccessor().queueCommand(std::bind(&GizmoManagerCore::updateData, mCore, rt, solidMeshProxy, wireMeshProxy, iconMeshProxy, iconRenderData));
+			gCoreAccessor().queueCommand(std::bind(&GizmoManagerCore::updateData, mCore, rt, solidMesh, wireMesh, iconMesh, iconRenderData));
 		}
 		else
 		{
@@ -379,19 +379,19 @@ namespace BansheeEngine
 			if (meshData.type == DrawHelper::MeshType::Solid)
 			{
 				gCoreAccessor().queueCommand(std::bind(&GizmoManagerCore::renderGizmos,
-					mCore, viewMat, projMat, meshData.mesh->_createProxy(0), GizmoMaterial::Picking));
+					mCore, viewMat, projMat, meshData.mesh->getCore(), GizmoMaterial::Picking));
 			}
 			else // Wire
 			{
 				gCoreAccessor().queueCommand(std::bind(&GizmoManagerCore::renderGizmos,
-					mCore, viewMat, projMat, meshData.mesh->_createProxy(0), GizmoMaterial::Picking));
+					mCore, viewMat, projMat, meshData.mesh->getCore(), GizmoMaterial::Picking));
 			}
 		}
 
 		Rect2I screenArea = camera->getViewport()->getArea();
 
 		gCoreAccessor().queueCommand(std::bind(&GizmoManagerCore::renderIconGizmos,
-			mCore, screenArea, iconMesh->_createProxy(0), iconRenderData, true));
+			mCore, screenArea, iconMesh->getCore(), iconRenderData, true));
 
 		mPickingDrawHelper->clearMeshes();
 		mIconMeshHeap->dealloc(iconMesh);
@@ -701,13 +701,13 @@ namespace BansheeEngine
 		activeRenderer->onCorePostRenderViewport.connect(std::bind(&GizmoManagerCore::render, this, _1));
 	}
 
-	void GizmoManagerCore::updateData(const RenderTargetPtr& rt, const MeshProxyPtr& solidMeshProxy, const MeshProxyPtr& wireMeshProxy,
-		const MeshProxyPtr& iconMeshProxy, const GizmoManager::IconRenderDataVecPtr& iconRenderData)
+	void GizmoManagerCore::updateData(const RenderTargetPtr& rt, const SPtr<MeshCoreBase>& solidMesh, const SPtr<MeshCoreBase>& wireMesh,
+		const SPtr<MeshCoreBase>& iconMesh, const GizmoManager::IconRenderDataVecPtr& iconRenderData)
 	{
 		mSceneRenderTarget = rt;
-		mSolidMeshProxy = solidMeshProxy;
-		mWireMeshProxy = wireMeshProxy;
-		mIconMeshProxy = iconMeshProxy;
+		mSolidMesh = solidMesh;
+		mWireMesh = wireMesh;
+		mIconMesh = iconMesh;
 		mIconRenderData = iconRenderData;
 	}
 
@@ -729,17 +729,17 @@ namespace BansheeEngine
 		screenArea.width = (int)(normArea.width * width);
 		screenArea.height = (int)(normArea.height * height);
 
-		if (mSolidMeshProxy != nullptr)
-			renderGizmos(camera.viewMatrix, camera.projMatrix, mSolidMeshProxy, GizmoManager::GizmoMaterial::Solid);
+		if (mSolidMesh != nullptr)
+			renderGizmos(camera.viewMatrix, camera.projMatrix, mSolidMesh, GizmoManager::GizmoMaterial::Solid);
 
-		if (mWireMeshProxy != nullptr)
-			renderGizmos(camera.viewMatrix, camera.projMatrix, mWireMeshProxy, GizmoManager::GizmoMaterial::Wire);
+		if (mWireMesh != nullptr)
+			renderGizmos(camera.viewMatrix, camera.projMatrix, mWireMesh, GizmoManager::GizmoMaterial::Wire);
 
-		if (mIconMeshProxy != nullptr)
-			renderIconGizmos(screenArea, mIconMeshProxy, mIconRenderData, false);
+		if (mIconMesh != nullptr)
+			renderIconGizmos(screenArea, mIconMesh, mIconRenderData, false);
 	}
 
-	void GizmoManagerCore::renderGizmos(Matrix4 viewMatrix, Matrix4 projMatrix, MeshProxyPtr meshProxy, GizmoManager::GizmoMaterial material)
+	void GizmoManagerCore::renderGizmos(Matrix4 viewMatrix, Matrix4 projMatrix, SPtr<MeshCoreBase> mesh, GizmoManager::GizmoMaterial material)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
@@ -761,19 +761,13 @@ namespace BansheeEngine
 			break;
 		}
 		
-		Renderer::draw(*meshProxy);
+		Renderer::draw(mesh, mesh->getProperties().getSubMesh(0));
 	}
 
-	void GizmoManagerCore::renderIconGizmos(Rect2I screenArea, MeshProxyPtr meshProxy, GizmoManager::IconRenderDataVecPtr renderData, bool usePickingMaterial)
+	void GizmoManagerCore::renderIconGizmos(Rect2I screenArea, SPtr<MeshCoreBase> mesh, GizmoManager::IconRenderDataVecPtr renderData, bool usePickingMaterial)
 	{
 		RenderSystem& rs = RenderSystem::instance();
-		MeshBasePtr mesh;
-
-		// TODO: Instead of this lock consider just storing all needed data in MeshProxy and not referencing Mesh at all?
-		if (!meshProxy->mesh.expired())
-			mesh = meshProxy->mesh.lock();
-		else
-			return;
+		const MeshProperties& meshProps = mesh->getProperties();
 
 		std::shared_ptr<VertexData> vertexData = mesh->getVertexData();
 

+ 14 - 14
BansheeEditor/Source/BsHandleDrawManager.cpp

@@ -160,18 +160,18 @@ namespace BansheeEngine
 
 		const Vector<DrawHelper::ShapeMeshData>& meshes = mDrawHelper->getMeshes();
 		
-		Vector<HandleDrawManagerCore::MeshProxyData> proxyData;
+		Vector<HandleDrawManagerCore::MeshData> proxyData;
 		for (auto& meshData : meshes)
 		{
 			if (meshData.type == DrawHelper::MeshType::Solid)
 			{
-				MeshProxyPtr proxy = meshData.mesh->_createProxy(0);
-				proxyData.push_back(HandleDrawManagerCore::MeshProxyData(proxy, HandleDrawManagerCore::MeshType::Solid));
+				proxyData.push_back(HandleDrawManagerCore::MeshData(
+					meshData.mesh->getCore(), HandleDrawManagerCore::MeshType::Solid));
 			}
 			else // Wire
 			{
-				MeshProxyPtr proxy = meshData.mesh->_createProxy(0);
-				proxyData.push_back(HandleDrawManagerCore::MeshProxyData(proxy, HandleDrawManagerCore::MeshType::Wire));
+				proxyData.push_back(HandleDrawManagerCore::MeshData(
+					meshData.mesh->getCore(), HandleDrawManagerCore::MeshType::Wire));
 			}
 		}
 
@@ -204,10 +204,10 @@ namespace BansheeEngine
 		activeRenderer->onCorePostRenderViewport.connect(std::bind(&HandleDrawManagerCore::render, this, _1));
 	}
 
-	void HandleDrawManagerCore::updateData(const RenderTargetPtr& rt, const Vector<MeshProxyData>& proxies)
+	void HandleDrawManagerCore::updateData(const RenderTargetPtr& rt, const Vector<MeshData>& meshes)
 	{
 		mSceneRenderTarget = rt;
-		mProxies = proxies;
+		mMeshes = meshes;
 	}
 
 	void HandleDrawManagerCore::render(const CameraProxy& camera)
@@ -234,9 +234,9 @@ namespace BansheeEngine
 		mWireMaterial.mViewProj.set(viewProjMat);
 
 		MeshType currentType = MeshType::Solid;
-		if (mProxies.size() > 0)
+		if (mMeshes.size() > 0)
 		{
-			currentType = mProxies[0].type;
+			currentType = mMeshes[0].type;
 
 			if (currentType == MeshType::Solid)
 				Renderer::setPass(*mSolidMaterial.proxy, 0);
@@ -244,19 +244,19 @@ namespace BansheeEngine
 				Renderer::setPass(*mWireMaterial.proxy, 0);
 		}
 
-		for (auto& proxyData : mProxies)
+		for (auto& meshData : mMeshes)
 		{
-			if (currentType != proxyData.type)
+			if (currentType != meshData.type)
 			{
-				if (proxyData.type == MeshType::Solid)
+				if (meshData.type == MeshType::Solid)
 					Renderer::setPass(*mSolidMaterial.proxy, 0);
 				else
 					Renderer::setPass(*mWireMaterial.proxy, 0);
 
-				currentType = proxyData.type;
+				currentType = meshData.type;
 			}
 
-			Renderer::draw(*proxyData.proxy);
+			Renderer::draw(meshData.mesh, meshData.mesh->getProperties().getSubMesh(0));
 		}
 	}
 }

+ 4 - 11
BansheeEditor/Source/BsScenePicking.cpp

@@ -122,7 +122,7 @@ namespace BansheeEngine
 			if (!mesh)
 				continue;
 
-			Bounds worldBounds = mesh->getBounds();
+			Bounds worldBounds = mesh->getProperties().getBounds();
 			Matrix4 worldTransform = so->getWorldTfrm();
 			worldBounds.transformAffine(worldTransform);
 
@@ -134,7 +134,7 @@ namespace BansheeEngine
 				// More precise with the box
 				if (frustum.intersects(worldBounds.getBox()))
 				{
-					for (UINT32 i = 0; i < mesh->getNumSubMeshes(); i++)
+					for (UINT32 i = 0; i < mesh->getProperties().getNumSubMeshes(); i++)
 					{
 						UINT32 idx = (UINT32)pickData.size();
 
@@ -157,13 +157,6 @@ namespace BansheeEngine
 
 						CullingMode cullMode = rasterizerState->getCullMode();
 
-						MeshProxyPtr meshProxy;
-
-						if (mesh->_isCoreDirty(MeshDirtyFlag::Proxy))
-							meshProxy = mesh->_createProxy(i);
-						else
-							meshProxy = mesh->_getActiveProxy(i);
-
 						HTexture mainTexture;
 						if (useAlphaShader)
 						{
@@ -181,7 +174,7 @@ namespace BansheeEngine
 						idxToRenderable[idx] = so;
 
 						Matrix4 wvpTransform = viewProjMatrix * worldTransform;
-						pickData.insert({ meshProxy, idx, wvpTransform, useAlphaShader, cullMode, mainTexture });
+						pickData.insert({ mesh->getCore(), idx, wvpTransform, useAlphaShader, cullMode, mainTexture });
 					}
 				}
 			}
@@ -275,7 +268,7 @@ namespace BansheeEngine
 				rs.bindGpuParams(GPT_FRAGMENT_PROGRAM, md.mParamPickingFragParams);
 			}
 
-			Renderer::draw(*renderable.mesh);
+			Renderer::draw(renderable.mesh, renderable.mesh->getProperties().getSubMesh(0));
 		}
 	}
 

+ 5 - 2
BansheeEngine/Include/BsRenderQueue.h

@@ -2,6 +2,7 @@
 
 #include "BsPrerequisites.h"
 #include "BsVector3.h"
+#include "BsSubMesh.h"
 
 namespace BansheeEngine 
 {
@@ -16,7 +17,8 @@ namespace BansheeEngine
 
 		RenderableElement* renderElem;
 		MaterialProxyPtr material;
-		MeshProxyPtr mesh;
+		SPtr<MeshCoreBase> mesh;
+		SubMesh subMesh;
 		UINT32 passIdx;
 	};
 
@@ -55,9 +57,10 @@ namespace BansheeEngine
 		 *
 		 * @param	material		Material that will be used for rendering the object.
 		 * @param	mesh			Mesh representing the geometry of the object.
+		 * @param	subMesh			Portion of the mesh to draw.
 		 * @param	distFromCamera	Distance of this object from the camera. Used for distance sorting.
 		 */
-		void add(const MaterialProxyPtr& material, const MeshProxyPtr& mesh, float distFromCamera);
+		void add(const MaterialProxyPtr& material, const SPtr<MeshCoreBase>& mesh, const SubMesh& subMesh, float distFromCamera);
 
 		/**
 		 * @brief	Adds new entries from the provided render queue to this queue.

+ 8 - 3
BansheeEngine/Include/BsRenderableProxy.h

@@ -2,9 +2,9 @@
 
 #include "BsPrerequisites.h"
 #include "BsMaterialProxy.h"
-#include "BsMeshProxy.h"
 #include "BsBounds.h"
 #include "BsMatrix4.h"
+#include "BsSubMesh.h"
 
 namespace BansheeEngine
 {
@@ -34,9 +34,14 @@ namespace BansheeEngine
 		Matrix4 worldTransform;
 
 		/**
-		 * @brief	Proxy of the sub-mesh to render.
+		 * @brief	Reference to the mesh to render.
 		 */
-		MeshProxyPtr mesh;
+		SPtr<MeshCore> mesh;
+
+		/**
+		 * @brief	Portion of the mesh to render.
+		 */
+		SubMesh subMesh;
 
 		/**
 		 * @brief	Proxy of the material to render the mesh with.

+ 7 - 3
BansheeEngine/Source/BsRenderQueue.cpp

@@ -1,8 +1,9 @@
 #include "BsRenderQueue.h"
 #include "BsMaterialProxy.h"
-#include "BsMeshProxy.h"
 #include "BsShaderProxy.h"
 #include "BsRenderableProxy.h"
+#include "BsSubMesh.h"
+#include "BsMesh.h"
 
 namespace BansheeEngine
 {
@@ -26,6 +27,7 @@ namespace BansheeEngine
 		renderOp.renderElem = element;
 		renderOp.material = element->material;
 		renderOp.mesh = element->mesh;
+		renderOp.subMesh = element->subMesh;
 
 		sortData.distFromCamera = distFromCamera;
 		sortData.priority = element->material->shader->queuePriority;
@@ -36,7 +38,7 @@ namespace BansheeEngine
 		mRenderElements.insert(sortData);
 	}
 
-	void RenderQueue::add(const MaterialProxyPtr& material, const MeshProxyPtr& mesh, float distFromCamera)
+	void RenderQueue::add(const MaterialProxyPtr& material, const SPtr<MeshCoreBase>& mesh, const SubMesh& subMesh, float distFromCamera)
 	{
 		SortData sortData;
 
@@ -44,6 +46,7 @@ namespace BansheeEngine
 		renderOp.renderElem = nullptr;
 		renderOp.material = material;
 		renderOp.mesh = mesh;
+		renderOp.subMesh = subMesh;
 
 		sortData.distFromCamera = distFromCamera;
 		sortData.priority = material->shader->queuePriority;
@@ -61,7 +64,7 @@ namespace BansheeEngine
 			if (elem.element.renderElem != nullptr)
 				add(elem.element.renderElem, elem.distFromCamera);
 			else
-				add(elem.element.material, elem.element.mesh, elem.distFromCamera);
+				add(elem.element.material, elem.element.mesh, elem.element.subMesh, elem.distFromCamera);
 		}
 	}
 
@@ -80,6 +83,7 @@ namespace BansheeEngine
 				sortedElem.renderElem = renderElem.renderElem;
 				sortedElem.material = renderElem.material;
 				sortedElem.mesh = renderElem.mesh;
+				sortedElem.subMesh = renderElem.subMesh;
 				sortedElem.passIdx = i;
 			}
 		}

+ 1 - 1
BansheeEngine/Source/BsRenderable.cpp

@@ -32,7 +32,7 @@ namespace BansheeEngine
 		}
 		else
 		{
-			Bounds bounds = mesh->getBounds();
+			Bounds bounds = mesh->getProperties().getBounds();
 			bounds.transformAffine(SO()->getWorldTfrm());
 
 			return bounds;

+ 4 - 22
BansheeEngine/Source/BsRenderableHandler.cpp

@@ -30,7 +30,7 @@ namespace BansheeEngine
 	void RenderableHandler::setMesh(HMesh mesh)
 	{
 		mMeshData = mesh;
-		mMaterialData.resize(mesh->getNumSubMeshes());
+		mMaterialData.resize(mesh->getProperties().getNumSubMeshes());
 
 		_markCoreDirty();
 	}
@@ -76,9 +76,6 @@ namespace BansheeEngine
 				return true;
 		}
 
-		if (mMeshData.mesh != nullptr && mMeshData.mesh.isLoaded() && mMeshData.mesh->_isCoreDirty(MeshDirtyFlag::Mesh))
-			return true;
-
 		return mCoreDirtyFlags != 0;
 	}
 
@@ -90,9 +87,6 @@ namespace BansheeEngine
 				materialData.material->_markCoreClean(MaterialDirtyFlag::Material);
 		}
 
-		if (mMeshData.mesh != nullptr && mMeshData.mesh.isLoaded())
-			mMeshData.mesh->_markCoreClean(MeshDirtyFlag::Mesh);
-
 		mCoreDirtyFlags = 0;
 	}
 
@@ -123,20 +117,13 @@ namespace BansheeEngine
 
 		RenderableProxyPtr proxy = bs_shared_ptr<RenderableProxy>();
 
-		bool markMeshProxyClean = false;
-		for (UINT32 i = 0; i < mMeshData.mesh->getNumSubMeshes(); i++)
+		for (UINT32 i = 0; i < mMeshData.mesh->getProperties().getNumSubMeshes(); i++)
 		{
 			RenderableElement* renElement = bs_new<RenderableElement>();
 			renElement->layer = mLayer;
 			renElement->worldTransform = worldTransform;
-
-			if (mMeshData.mesh->_isCoreDirty(MeshDirtyFlag::Proxy))
-			{
-				mMeshData.mesh->_setActiveProxy(i, mMeshData.mesh->_createProxy(i));
-				markMeshProxyClean = true;
-			}
-
-			renElement->mesh = mMeshData.mesh->_getActiveProxy(i);
+			renElement->mesh = mMeshData.mesh->getCore();
+			renElement->subMesh = mMeshData.mesh->getProperties().getSubMesh(i);
 
 			HMaterial material;
 			if (mMaterialData[i].material != nullptr)
@@ -158,11 +145,6 @@ namespace BansheeEngine
 			proxy->renderableElements.push_back(renElement);
 		}
 
-		if (markMeshProxyClean)
-		{
-			mMeshData.mesh->_markCoreClean(MeshDirtyFlag::Proxy);
-		}
-
 		proxy->renderableType = RenType_LitTextured;
 
 		return proxy;

+ 2 - 1
BansheeEngine/Source/BsRenderableProxy.cpp

@@ -1,4 +1,5 @@
 #include "BsRenderableProxy.h"
+#include "BsMesh.h"
 
 namespace BansheeEngine
 {
@@ -11,7 +12,7 @@ namespace BansheeEngine
 		if (mesh == nullptr)
 			return Bounds();
 
-		Bounds worldBounds = mesh->bounds;
+		Bounds worldBounds = mesh->getProperties().getBounds();
 		worldBounds.transformAffine(worldTransform);
 
 		return worldBounds;

+ 4 - 10
BansheeRenderer/Source/BsBansheeRenderer.cpp

@@ -375,15 +375,9 @@ namespace BansheeEngine
 						drawOp.material->_markCoreClean(MaterialDirtyFlag::Params);
 				}
 
-				if (drawOp.mesh->_isCoreDirty(MeshDirtyFlag::Proxy))
-				{
-					drawOp.mesh->_setActiveProxy(drawOp.submeshIdx, drawOp.mesh->_createProxy(drawOp.submeshIdx));
-					drawOp.mesh->_markCoreClean(MeshDirtyFlag::Proxy);
-					drawOp.mesh->_markCoreClean(MeshDirtyFlag::Mesh);
-				}
-
 				MaterialProxyPtr materialProxy = drawOp.material->_getActiveProxy();
-				MeshProxyPtr meshProxy = drawOp.mesh->_getActiveProxy(drawOp.submeshIdx);
+				SPtr<MeshCoreBase> meshCore = drawOp.mesh->getCore();
+				SubMesh subMesh = meshCore->getProperties().getSubMesh(drawOp.submeshIdx);
 
 				if (dirtyParams != nullptr)
 				{
@@ -392,7 +386,7 @@ namespace BansheeEngine
 				}
 
 				float distanceToCamera = (cameraSO->getPosition() - drawOp.worldPosition).length();
-				renderQueue->add(materialProxy, meshProxy, distanceToCamera);
+				renderQueue->add(materialProxy, meshCore, subMesh, distanceToCamera);
 			}
 
 			gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::addToRenderQueue, this, camera->_getActiveProxy(), renderQueue));
@@ -531,7 +525,7 @@ namespace BansheeEngine
 			MaterialProxyPtr materialProxy = iter->material;
 
 			setPass(*materialProxy, iter->passIdx);
-			draw(*iter->mesh);
+			draw(iter->mesh, iter->subMesh);
 		}
 
 		renderQueue->clear();

+ 4 - 2
TODO.txt

@@ -9,7 +9,6 @@ Resource
  - SamplerState
  - Font
  - Texture
- - Mesh
  - GpuProgram
  - Material
  - Shader
@@ -25,7 +24,10 @@ Disallow CoreObject creation from core thread
  - Add asserts in CoreObject::destroy and CoreObject::initialize
  - Possibly also add asserts to CoreThread::queueCommand and CoreThread::queueReturnCommand
 
-Move CoreAccessor methods relating to render target, to the render targets themselves
+After I refactor Texture remove write/read subresource from core accessor
+ - Also get rid of GpuResource class
+
+Since Mesh refactor when I select/deselect a gizmo the entire render texture flashes white for one frame (might be related to RT refactor instead)
 
 -----------------