Browse Source

Refactored draw helper so it can sort meshes based on distance from camera
Added special materials that ignore depth for handles

Marko Pintera 11 years ago
parent
commit
298de470a6

+ 22 - 0
BansheeEditor/Include/BsBuiltinEditorResources.h

@@ -60,6 +60,16 @@ namespace BansheeEngine
 		 */
 		HMaterial createAlphaGizmoPickingMat() const;
 
+		/**
+		 * @brief	Creates a material used for rendering wireframe handles.
+		 */
+		HMaterial createWireHandleMat() const;
+
+		/**
+		 * @brief	Creates a material used for rendering solid handles.
+		 */
+		HMaterial createSolidHandleMat() const;
+
 		static const String ObjectFieldStyleName;
 		static const String ObjectFieldLabelStyleName;
 		static const String ObjectFieldDropBtnStyleName;
@@ -136,6 +146,16 @@ namespace BansheeEngine
 		 */
 		void initGizmoPickingAlphaShader();
 
+		/**
+		 * @brief	Loads and compiles a shader used for rendering wireframe handles.
+		 */
+		void initWireHandleShader();
+
+		/**
+		 * @brief	Loads and compiles a shader used for rendering solid handles.
+		 */
+		void initSolidHandleShader();
+
 		RenderSystemPlugin mRenderSystemPlugin;
 		WString mActiveShaderSubFolder;
 		String mActiveRenderSystem;
@@ -149,6 +169,8 @@ namespace BansheeEngine
 		ShaderPtr mShaderGizmoIcon;
 		ShaderPtr mShaderGizmoPicking;
 		ShaderPtr mShaderGizmoAlphaPicking;
+		ShaderPtr mShaderHandleSolid;
+		ShaderPtr mShaderHandleWire;
 
 		GUISkin mSkin;
 

+ 0 - 2
BansheeEditor/Include/BsGizmoManager.h

@@ -146,8 +146,6 @@ namespace BansheeEngine
 
 		MeshHeapPtr mIconMeshHeap;
 
-		TransientMeshPtr mSolidMesh;
-		TransientMeshPtr mWireMesh;
 		TransientMeshPtr mIconMesh;
 
 		GizmoManagerCore* mCore;

+ 17 - 8
BansheeEditor/Include/BsHandleDrawManager.h

@@ -42,9 +42,6 @@ namespace BansheeEngine
 
 		HandleDrawManagerCore* mCore;
 		DrawHelper* mDrawHelper;
-
-		TransientMeshPtr mSolidMesh;
-		TransientMeshPtr mWireMesh;
 	};
 
 	class BS_ED_EXPORT HandleDrawManagerCore
@@ -61,6 +58,21 @@ namespace BansheeEngine
 			GpuParamMat4 mViewProj;
 		};
 
+		enum class MeshType
+		{
+			Solid, Wire
+		};
+
+		struct MeshProxyData
+		{
+			MeshProxyData(const MeshProxyPtr& proxy, MeshType type)
+				:proxy(proxy), type(type)
+			{ }
+
+			MeshProxyPtr proxy;
+			MeshType type;
+		};
+
 		struct PrivatelyConstruct { };
 
 	public:
@@ -71,14 +83,11 @@ namespace BansheeEngine
 
 		void initialize(const MaterialProxyPtr& wireMatProxy, const MaterialProxyPtr& solidMatProxy);
 
-		void updateData(const RenderTargetPtr& rt, const MeshProxyPtr& solidMeshProxy, const MeshProxyPtr& wireMeshProxy);
+		void updateData(const RenderTargetPtr& rt, const Vector<MeshProxyData>& proxies);
 		void render(const CameraProxy& camera);
-		void renderSolid(Matrix4 viewMatrix, Matrix4 projMatrix, MeshProxyPtr mesh);
-		void renderWire(Matrix4 viewMatrix, Matrix4 projMatrix, MeshProxyPtr mesh);
 
 		RenderTargetPtr mSceneRenderTarget;
-		MeshProxyPtr mSolidMeshProxy;
-		MeshProxyPtr mWireMeshProxy;
+		Vector<MeshProxyData> mProxies;
 
 		// Immutable
 		SolidMaterialData mSolidMaterial;

+ 49 - 0
BansheeEditor/Source/BsBuiltinEditorResources.cpp

@@ -244,6 +244,8 @@ namespace BansheeEngine
 		initIconGizmoShader();
 		initGizmoPickingShader();
 		initGizmoPickingAlphaShader();
+		initWireHandleShader();
+		initSolidHandleShader();
 
 		Path fontPath = FileSystem::getWorkingDirectoryPath();
 		fontPath.append(DefaultSkinFolder);
@@ -1401,6 +1403,43 @@ namespace BansheeEngine
 		newPass->setFragmentProgram(psProgram);
 	}
 
+	void BuiltinEditorResources::initWireHandleShader()
+	{
+		HGpuProgram vsProgram = getGpuProgram(ShaderWireGizmoVSFile);
+		HGpuProgram psProgram = getGpuProgram(ShaderWireGizmoPSFile);
+
+		mShaderHandleWire = Shader::create("HandleWire");
+
+		mShaderHandleWire->addParameter("matViewProj", "matViewProj", GPDT_MATRIX_4X4);
+
+		TechniquePtr newTechnique = mShaderHandleWire->addTechnique(mActiveRenderSystem, RendererInvariant);
+		PassPtr newPass = newTechnique->addPass();
+		newPass->setVertexProgram(vsProgram);
+		newPass->setFragmentProgram(psProgram);
+	}
+
+	void BuiltinEditorResources::initSolidHandleShader()
+	{
+		HGpuProgram vsProgram = getGpuProgram(ShaderSolidGizmoVSFile);
+		HGpuProgram psProgram = getGpuProgram(ShaderSolidGizmoPSFile);
+
+		mShaderHandleSolid = Shader::create("HandleSolid");
+
+		mShaderHandleSolid->addParameter("matViewProj", "matViewProj", GPDT_MATRIX_4X4);
+
+		DEPTH_STENCIL_STATE_DESC depthStencilStateDesc;
+		depthStencilStateDesc.depthWriteEnable = false;
+		depthStencilStateDesc.depthReadEnable = false;
+
+		HDepthStencilState depthStencilState = DepthStencilState::create(depthStencilStateDesc);
+
+		TechniquePtr newTechnique = mShaderHandleSolid->addTechnique(mActiveRenderSystem, RendererInvariant);
+		PassPtr newPass = newTechnique->addPass();
+		newPass->setVertexProgram(vsProgram);
+		newPass->setFragmentProgram(psProgram);
+		newPass->setDepthStencilState(depthStencilState);
+	}
+
 	void BuiltinEditorResources::initIconGizmoShader()
 	{
 		HGpuProgram vsProgram0 = getGpuProgram(ShaderIconGizmo0VSFile);
@@ -1546,4 +1585,14 @@ namespace BansheeEngine
 	{
 		return Material::create(mShaderGizmoAlphaPicking);
 	}
+
+	HMaterial BuiltinEditorResources::createWireHandleMat() const
+	{
+		return Material::create(mShaderHandleWire);
+	}
+
+	HMaterial BuiltinEditorResources::createSolidHandleMat() const
+	{
+		return Material::create(mShaderHandleSolid);
+	}
 }

+ 42 - 27
BansheeEditor/Source/BsGizmoManager.cpp

@@ -66,12 +66,6 @@ namespace BansheeEngine
 
 	GizmoManager::~GizmoManager()
 	{
-		if (mSolidMesh != nullptr)
-			mDrawHelper->releaseSolidMesh(mSolidMesh);
-
-		if (mWireMesh != nullptr)
-			mDrawHelper->releaseWireMesh(mWireMesh);
-
 		if (mIconMesh != nullptr)
 			mIconMeshHeap->dealloc(mIconMesh);
 
@@ -237,11 +231,7 @@ namespace BansheeEngine
 
 	void GizmoManager::update()
 	{
-		if (mSolidMesh != nullptr)
-			mDrawHelper->releaseSolidMesh(mSolidMesh);
-
-		if (mWireMesh != nullptr)
-			mDrawHelper->releaseWireMesh(mWireMesh);
+		mDrawHelper->clearMeshes();
 
 		if (mIconMesh != nullptr)
 			mIconMeshHeap->dealloc(mIconMesh);
@@ -256,20 +246,37 @@ namespace BansheeEngine
 
 			IconRenderDataVecPtr iconRenderData;
 
-			mSolidMesh = mDrawHelper->buildSolidMesh();
-			mWireMesh = mDrawHelper->buildWireMesh();
-			mIconMesh = buildIconMesh(sceneCamera, mIconData, false, iconRenderData);
+			mDrawHelper->buildMeshes();
+			const Vector<DrawHelper::ShapeMeshData>& meshes = mDrawHelper->getMeshes();
+
+			MeshProxyPtr solidMeshProxy = nullptr;
+			MeshProxyPtr wireMeshProxy = nullptr;
+			for (auto& meshData : meshes)
+			{
+				if (meshData.type == DrawHelper::MeshType::Solid)
+				{
+					if (solidMeshProxy == nullptr)
+						solidMeshProxy = meshData.mesh->_createProxy(0);
+				}
+				else // Wire
+				{
+					if (wireMeshProxy == nullptr)
+						wireMeshProxy = meshData.mesh->_createProxy(0);
+				}
+
+			}
+
+			// Since there is no sorting used with draw helper meshes we only expect up to two of them,
+			// one for solids, one for wireframe
+			assert(meshes.size() <= 2);
 
-			MeshProxyPtr solidMeshProxy = mSolidMesh->_createProxy(0);
-			MeshProxyPtr wireMeshProxy = mWireMesh->_createProxy(0);
+			mIconMesh = buildIconMesh(sceneCamera, mIconData, false, iconRenderData);
 			MeshProxyPtr iconMeshProxy = mIconMesh->_createProxy(0);
 
 			gCoreAccessor().queueCommand(std::bind(&GizmoManagerCore::updateData, mCore, rt, solidMeshProxy, wireMeshProxy, iconMeshProxy, iconRenderData));
 		}
 		else
 		{
-			mSolidMesh = nullptr;
-			mWireMesh = nullptr;
 			mIconMesh = nullptr;
 
 			IconRenderDataVecPtr iconRenderData = bs_shared_ptr<IconRenderDataVec>();
@@ -360,8 +367,9 @@ namespace BansheeEngine
 			iconData.back().color = idxToColorCallback(iconDataEntry.idx);
 		}
 
-		TransientMeshPtr solidMesh = mPickingDrawHelper->buildSolidMesh();
-		TransientMeshPtr wireMesh = mPickingDrawHelper->buildWireMesh();
+		mPickingDrawHelper->buildMeshes();
+		const Vector<DrawHelper::ShapeMeshData>& meshes = mPickingDrawHelper->getMeshes();
+
 		TransientMeshPtr iconMesh = buildIconMesh(camera, iconData, true, iconRenderData);
 
 		// Note: This must be rendered while Scene view is being rendered
@@ -369,19 +377,26 @@ namespace BansheeEngine
 		Matrix4 projMat = camera->getProjectionMatrixRS();
 		ViewportPtr viewport = camera->getViewport();
 
-		gCoreAccessor().queueCommand(std::bind(&GizmoManagerCore::renderGizmos,
-			mCore, viewMat, projMat, solidMesh->_createProxy(0), GizmoMaterial::Picking));
-
-		gCoreAccessor().queueCommand(std::bind(&GizmoManagerCore::renderGizmos,
-			mCore, viewMat, projMat, wireMesh->_createProxy(0), GizmoMaterial::Picking));
+		for (auto& meshData : meshes)
+		{
+			if (meshData.type == DrawHelper::MeshType::Solid)
+			{
+				gCoreAccessor().queueCommand(std::bind(&GizmoManagerCore::renderGizmos,
+					mCore, viewMat, projMat, meshData.mesh->_createProxy(0), GizmoMaterial::Picking));
+			}
+			else // Wire
+			{
+				gCoreAccessor().queueCommand(std::bind(&GizmoManagerCore::renderGizmos,
+					mCore, viewMat, projMat, meshData.mesh->_createProxy(0), GizmoMaterial::Picking));
+			}
+		}
 
 		Rect2I screenArea = camera->getViewport()->getArea();
 
 		gCoreAccessor().queueCommand(std::bind(&GizmoManagerCore::renderIconGizmos,
 			mCore, screenArea, iconMesh->_createProxy(0), iconRenderData, true));
 
-		mPickingDrawHelper->releaseSolidMesh(solidMesh);
-		mPickingDrawHelper->releaseWireMesh(wireMesh);
+		mPickingDrawHelper->clearMeshes();
 		mIconMeshHeap->dealloc(iconMesh);
 	}
 

+ 49 - 42
BansheeEditor/Source/BsHandleDrawManager.cpp

@@ -7,6 +7,7 @@
 #include "BsRenderer.h"
 #include "BsTransientMesh.h"
 #include "BsCamera.h"
+#include "BsSceneObject.h"
 
 using namespace std::placeholders;
 
@@ -21,8 +22,8 @@ namespace BansheeEngine
 	{
 		mDrawHelper = bs_new<DrawHelper>();
 
-		HMaterial solidMaterial = BuiltinEditorResources::instance().createSolidGizmoMat();
-		HMaterial wireMaterial = BuiltinEditorResources::instance().createWireGizmoMat();
+		HMaterial solidMaterial = BuiltinEditorResources::instance().createSolidHandleMat();
+		HMaterial wireMaterial = BuiltinEditorResources::instance().createWireHandleMat();
 
 		MaterialProxyPtr solidMaterialProxy = solidMaterial->_createProxy();
 		MaterialProxyPtr wireMaterialProxy = wireMaterial->_createProxy();
@@ -34,12 +35,6 @@ namespace BansheeEngine
 
 	HandleDrawManager::~HandleDrawManager()
 	{
-		if (mSolidMesh != nullptr)
-			mDrawHelper->releaseSolidMesh(mSolidMesh);
-
-		if (mWireMesh != nullptr)
-			mDrawHelper->releaseWireMesh(mWireMesh);
-
 		bs_delete(mDrawHelper);
 
 		gCoreAccessor().queueCommand(std::bind(&HandleDrawManager::destroyCore, this, mCore));
@@ -126,22 +121,30 @@ namespace BansheeEngine
 
 	void HandleDrawManager::draw(const HCamera& camera)
 	{
-		if (mSolidMesh != nullptr)
-			mDrawHelper->releaseSolidMesh(mSolidMesh);
-
-		if (mWireMesh != nullptr)
-			mDrawHelper->releaseWireMesh(mWireMesh);
+		mDrawHelper->clearMeshes();
+		mDrawHelper->buildMeshes(DrawHelper::SortType::BackToFront, camera->SO()->getWorldPosition());
 
-		mSolidMesh = mDrawHelper->buildSolidMesh();
-		mWireMesh = mDrawHelper->buildWireMesh();
-
-		MeshProxyPtr solidMeshProxy = mSolidMesh->_createProxy(0);
-		MeshProxyPtr wireMeshProxy = mWireMesh->_createProxy(0);
+		const Vector<DrawHelper::ShapeMeshData>& meshes = mDrawHelper->getMeshes();
+		
+		Vector<HandleDrawManagerCore::MeshProxyData> 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));
+			}
+			else // Wire
+			{
+				MeshProxyPtr proxy = meshData.mesh->_createProxy(0);
+				proxyData.push_back(HandleDrawManagerCore::MeshProxyData(proxy, HandleDrawManagerCore::MeshType::Wire));
+			}
+		}
 
 		RenderTargetPtr sceneRenderTarget = camera->getViewport()->getTarget();
 
 		gCoreAccessor().queueCommand(std::bind(&HandleDrawManagerCore::updateData, mCore, 
-			sceneRenderTarget, solidMeshProxy, wireMeshProxy));
+			sceneRenderTarget, proxyData));
 
 		mDrawHelper->clear();
 	}
@@ -167,15 +170,16 @@ namespace BansheeEngine
 		activeRenderer->onCorePostRenderViewport.connect(std::bind(&HandleDrawManagerCore::render, this, _1));
 	}
 
-	void HandleDrawManagerCore::updateData(const RenderTargetPtr& rt, const MeshProxyPtr& solidMeshProxy, const MeshProxyPtr& wireMeshProxy)
+	void HandleDrawManagerCore::updateData(const RenderTargetPtr& rt, const Vector<MeshProxyData>& proxies)
 	{
 		mSceneRenderTarget = rt;
-		mSolidMeshProxy = solidMeshProxy;
-		mWireMeshProxy = wireMeshProxy;
+		mProxies = proxies;
 	}
 
 	void HandleDrawManagerCore::render(const CameraProxy& camera)
 	{
+		THROW_IF_NOT_CORE_THREAD;
+
 		if (camera.viewport.getTarget() != mSceneRenderTarget)
 			return;
 
@@ -190,31 +194,34 @@ namespace BansheeEngine
 		screenArea.width = (int)(normArea.width * width);
 		screenArea.height = (int)(normArea.height * height);
 
-		renderSolid(camera.viewMatrix, camera.projMatrix, mSolidMeshProxy);
-		renderWire(camera.viewMatrix, camera.projMatrix, mWireMeshProxy);
-	}
-
-	void HandleDrawManagerCore::renderSolid(Matrix4 viewMatrix, Matrix4 projMatrix, MeshProxyPtr meshProxy)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		Matrix4 viewProjMat = projMatrix * viewMatrix;
-
+		Matrix4 viewProjMat = camera.projMatrix * camera.viewMatrix;
 		mSolidMaterial.mViewProj.set(viewProjMat);
+		mWireMaterial.mViewProj.set(viewProjMat);
 
-		Renderer::setPass(*mSolidMaterial.proxy, 0);
-		Renderer::draw(*meshProxy);
-	}
+		MeshType currentType = MeshType::Solid;
+		if (mProxies.size() > 0)
+		{
+			currentType = mProxies[0].type;
 
-	void HandleDrawManagerCore::renderWire(Matrix4 viewMatrix, Matrix4 projMatrix, MeshProxyPtr meshProxy)
-	{
-		THROW_IF_NOT_CORE_THREAD;
+			if (currentType == MeshType::Solid)
+				Renderer::setPass(*mSolidMaterial.proxy, 0);
+			else
+				Renderer::setPass(*mWireMaterial.proxy, 0);
+		}
 
-		Matrix4 viewProjMat = projMatrix * viewMatrix;
+		for (auto& proxyData : mProxies)
+		{
+			if (currentType != proxyData.type)
+			{
+				if (currentType == MeshType::Solid)
+					Renderer::setPass(*mSolidMaterial.proxy, 0);
+				else
+					Renderer::setPass(*mWireMaterial.proxy, 0);
 
-		mWireMaterial.mViewProj.set(viewProjMat);
+				currentType = proxyData.type;
+			}
 
-		Renderer::setPass(*mWireMaterial.proxy, 0);
-		Renderer::draw(*meshProxy);
+			Renderer::draw(*proxyData.proxy);
+		}
 	}
 }

+ 1 - 1
BansheeEditorExec/BsEditorExec.cpp

@@ -11,7 +11,7 @@ int CALLBACK WinMain(
 	_In_  int nCmdShow
 	)
 {
-	EditorApplication::startUp(RenderSystemPlugin::DX11);
+	EditorApplication::startUp(RenderSystemPlugin::DX9);
 	EditorApplication::instance().runMainLoop();
 	EditorApplication::shutDown();
 

+ 44 - 18
BansheeEngine/Include/BsDrawHelper.h

@@ -14,6 +14,35 @@ namespace BansheeEngine
 	class BS_EXPORT DrawHelper
 	{
 	public:
+		/**
+		 * @brief	Controls in what order will elements be rendered,
+		 *			depending on some reference point
+		 */
+		enum class SortType
+		{
+			BackToFront,
+			FrontToBack,
+			None
+		};
+
+		/**
+		 * @brief	Type of meshes that are output by DrawHelper.
+		 */
+		enum class MeshType
+		{
+			Solid, Wire
+		};
+
+		/**
+		 * @brief	Container for mesh of a specific type output by
+		 *			the DrawHelper.
+		 */
+		struct ShapeMeshData
+		{
+			TransientMeshPtr mesh;
+			MeshType type;
+		};
+
 		DrawHelper();
 		~DrawHelper();
 
@@ -93,34 +122,35 @@ namespace BansheeEngine
 		void clear();
 
 		/**
-		 * @brief	Generates a mesh from all the recorded solid shapes.
+		 * @brief	Generates a set of meshes from all the recorded solid and wireframe shapes.
+		 *			The meshes can be accessed via "getMeshes" and released via "clearMeshes". 
+		 *			Any previously active meshes will be cleared when this method is called.
 		 *
-		 * @note	You must call releaseSolidMesh when done.
-		 */
-		TransientMeshPtr buildSolidMesh();
-
-		/**
-		 * @brief	Generates a mesh from all the recorded wireframe shapes.
+		 * @param	sorting		Determines how (and if) should elements be sorted
+		 *						based on their distance from the reference point.
+		 * @param	reference	Reference point to use for determining distance when
+		 *						sorting.
 		 *
-		 * @note	You must call releaseWireMesh when done.
+		 * @note	You must call releaseSolidMesh when done.
 		 */
-		TransientMeshPtr buildWireMesh();
+		void buildMeshes(SortType sorting = SortType::None, const Vector3& reference = Vector3::ZERO);
 
 		/**
-		 * @brief	Releases a previously allocated solid mesh once you are done with it.
+		 * @brief	Returns a set of meshes you have previously built using "buildMeshes".
 		 */
-		void releaseSolidMesh(const TransientMeshPtr& mesh);
+		const Vector<ShapeMeshData>& getMeshes() const { return mMeshes; }
 
 		/**
-		 * @brief	Releases a previously allocated wireframe mesh once you are done with it.
+		 * @brief	Deallocates all active meshes.
 		 */
-		void releaseWireMesh(const TransientMeshPtr& mesh);
+		void clearMeshes();
 
 	private:
 		struct CommonData
 		{
 			Color color;
 			Matrix4 transform;
+			Vector3 center;
 		};
 
 		struct CubeData : public CommonData
@@ -202,11 +232,7 @@ namespace BansheeEngine
 		Vector<ArcData> mArcData;
 		Vector<ArcData> mWireArcData;
 
-		UINT32 mTotalRequiredSolidVertices;
-		UINT32 mTotalRequiredSolidIndices;
-
-		UINT32 mTotalRequiredWireVertices;
-		UINT32 mTotalRequiredWireIndices;
+		Vector<ShapeMeshData> mMeshes;
 
 		MeshHeapPtr mSolidMeshHeap;
 		MeshHeapPtr mWireMeshHeap;

+ 447 - 289
BansheeEngine/Source/BsDrawHelper.cpp

@@ -12,8 +12,6 @@ namespace BansheeEngine
 	const UINT32 DrawHelper::INDEX_BUFFER_GROWTH = 4096 * 2;
 
 	DrawHelper::DrawHelper()
-		: mTotalRequiredSolidVertices(0), mTotalRequiredSolidIndices(0), 
-		mTotalRequiredWireVertices(0), mTotalRequiredWireIndices(0)
 	{
 		mTransform = Matrix4::IDENTITY;
 
@@ -32,7 +30,7 @@ namespace BansheeEngine
 
 	DrawHelper::~DrawHelper()
 	{
-
+		clearMeshes();
 	}
 
 	void DrawHelper::setColor(const Color& color)
@@ -54,9 +52,7 @@ namespace BansheeEngine
 		cubeData.extents = extents;
 		cubeData.color = mColor;
 		cubeData.transform = mTransform;
-
-		mTotalRequiredSolidVertices += 24;
-		mTotalRequiredSolidIndices += 36;
+		cubeData.center = mTransform.multiply3x4(position);
 	}
 
 	void DrawHelper::sphere(const Vector3& position, float radius, UINT32 quality)
@@ -69,12 +65,7 @@ namespace BansheeEngine
 		sphereData.quality = quality;
 		sphereData.color = mColor;
 		sphereData.transform = mTransform;
-
-		UINT32 numVertices, numIndices;
-		ShapeMeshes3D::getNumElementsSphere(quality, numVertices, numIndices);
-
-		mTotalRequiredSolidVertices += numVertices;
-		mTotalRequiredSolidIndices += numIndices;
+		sphereData.center = mTransform.multiply3x4(position);
 	}
 
 	void DrawHelper::wireCube(const Vector3& position, const Vector3& extents)
@@ -86,9 +77,7 @@ namespace BansheeEngine
 		cubeData.extents = extents;
 		cubeData.color = mColor;
 		cubeData.transform = mTransform;
-
-		mTotalRequiredWireVertices += 8;
-		mTotalRequiredWireIndices += 24;
+		cubeData.center = mTransform.multiply3x4(position);
 	}
 
 	void DrawHelper::wireSphere(const Vector3& position, float radius, UINT32 quality)
@@ -101,12 +90,7 @@ namespace BansheeEngine
 		sphereData.quality = quality;
 		sphereData.color = mColor;
 		sphereData.transform = mTransform;
-
-		UINT32 numVertices, numIndices;
-		ShapeMeshes3D::getNumElementsWireSphere(quality, numVertices, numIndices);
-
-		mTotalRequiredWireVertices += numVertices;
-		mTotalRequiredWireIndices += numIndices;
+		sphereData.center = mTransform.multiply3x4(position);
 	}
 
 	void DrawHelper::line(const Vector3& start, const Vector3& end)
@@ -118,9 +102,7 @@ namespace BansheeEngine
 		lineData.end = end;
 		lineData.color = mColor;
 		lineData.transform = mTransform;
-
-		mTotalRequiredWireVertices += 2;
-		mTotalRequiredWireIndices += 2;
+		lineData.center = mTransform.multiply3x4((start + end) * 0.5f);
 	}
 
 	void DrawHelper::frustum(const Vector3& position, float aspect, Degree FOV, float near, float far)
@@ -135,9 +117,7 @@ namespace BansheeEngine
 		frustumData.far = far;
 		frustumData.color = mColor;
 		frustumData.transform = mTransform;
-
-		mTotalRequiredWireVertices += 8;
-		mTotalRequiredWireIndices += 36;
+		frustumData.center = mTransform.multiply3x4(position);
 	}
 
 	void DrawHelper::cone(const Vector3& base, const Vector3& normal, float height, float radius, UINT32 quality)
@@ -152,12 +132,7 @@ namespace BansheeEngine
 		coneData.quality = quality;
 		coneData.color = mColor;
 		coneData.transform = mTransform;
-
-		UINT32 numVertices, numIndices;
-		ShapeMeshes3D::getNumElementsCone(quality, numVertices, numIndices);
-
-		mTotalRequiredSolidVertices += numVertices;
-		mTotalRequiredSolidIndices += numIndices;
+		coneData.center = mTransform.multiply3x4(base + normal * height * 0.5f);
 	}
 
 	void DrawHelper::disc(const Vector3& position, const Vector3& normal, float radius, UINT32 quality)
@@ -171,12 +146,7 @@ namespace BansheeEngine
 		discData.quality = quality;
 		discData.color = mColor;
 		discData.transform = mTransform;
-
-		UINT32 numVertices, numIndices;
-		ShapeMeshes3D::getNumElementsDisc(quality, numVertices, numIndices);
-
-		mTotalRequiredSolidVertices += numVertices;
-		mTotalRequiredSolidIndices += numIndices;
+		discData.center = mTransform.multiply3x4(position);
 	}
 
 	void DrawHelper::wireDisc(const Vector3& position, const Vector3& normal, float radius, UINT32 quality)
@@ -190,12 +160,7 @@ namespace BansheeEngine
 		discData.quality = quality;
 		discData.color = mColor;
 		discData.transform = mTransform;
-
-		UINT32 numVertices, numIndices;
-		ShapeMeshes3D::getNumElementsWireDisc(quality, numVertices, numIndices);
-
-		mTotalRequiredWireVertices += numVertices;
-		mTotalRequiredWireIndices += numIndices;
+		discData.center = mTransform.multiply3x4(position);
 	}
 
 	void DrawHelper::arc(const Vector3& position, const Vector3& normal, float radius, 
@@ -212,12 +177,7 @@ namespace BansheeEngine
 		arcData.quality = quality;
 		arcData.color = mColor;
 		arcData.transform = mTransform;
-
-		UINT32 numVertices, numIndices;
-		ShapeMeshes3D::getNumElementsArc(quality, numVertices, numIndices);
-
-		mTotalRequiredSolidVertices += numVertices;
-		mTotalRequiredSolidIndices += numIndices;
+		arcData.center = mTransform.multiply3x4(position);
 	}
 
 	void DrawHelper::wireArc(const Vector3& position, const Vector3& normal, float radius, 
@@ -234,12 +194,7 @@ namespace BansheeEngine
 		arcData.quality = quality;
 		arcData.color = mColor;
 		arcData.transform = mTransform;
-
-		UINT32 numVertices, numIndices;
-		ShapeMeshes3D::getNumElementsWireArc(quality, numVertices, numIndices);
-
-		mTotalRequiredWireVertices += numVertices;
-		mTotalRequiredWireIndices += numIndices;
+		arcData.center = mTransform.multiply3x4(position);
 	}
 
 	void DrawHelper::rectangle(const Rect3& area)
@@ -250,9 +205,7 @@ namespace BansheeEngine
 		rectData.area = area;
 		rectData.color = mColor;
 		rectData.transform = mTransform;
-
-		mTotalRequiredSolidVertices += 4;
-		mTotalRequiredSolidIndices += 6;
+		rectData.center = mTransform.multiply3x4(area.getCenter());
 	}
 
 	void DrawHelper::clear()
@@ -270,311 +223,516 @@ namespace BansheeEngine
 		mArcData.clear();
 		mWireArcData.clear();
 		mConeData.clear();
-
-		mTotalRequiredSolidVertices = 0;
-		mTotalRequiredSolidIndices = 0;
-
-		mTotalRequiredWireVertices = 0;
-		mTotalRequiredWireIndices = 0;
 	}
 
-	TransientMeshPtr DrawHelper::buildSolidMesh()
+	void DrawHelper::buildMeshes(SortType sorting, const Vector3& reference)
 	{
-		MeshDataPtr meshData = bs_shared_ptr<MeshData>(mTotalRequiredSolidVertices, mTotalRequiredSolidIndices, mSolidVertexDesc);
-
-		UINT32 curVertexOffset = 0;
-		UINT32 curIndexOffet = 0;
+		clearMeshes();
 
-		auto positionIter = meshData->getVec3DataIter(VES_POSITION);
-		auto normalIter = meshData->getVec3DataIter(VES_NORMAL);
-		auto colorIter = meshData->getDWORDDataIter(VES_COLOR);
-
-		for (auto& cubeData : mSolidCubeData)
+		enum class ShapeType
 		{
-			AABox box(cubeData.position - cubeData.extents, cubeData.position + cubeData.extents);
-			ShapeMeshes3D::solidAABox(box, meshData, curVertexOffset, curIndexOffet);
-
-			Matrix4 transformIT = cubeData.transform.inverseAffine().transpose();
-			RGBA color = cubeData.color.getAsRGBA();
-
-			UINT32 numVertices = 24;
-			for (UINT32 i = 0; i < numVertices; i++)
-			{
-				Vector3 worldPos = cubeData.transform.multiply3x4(positionIter.getValue());
-				Vector3 worldNormal = transformIT.multiply3x4(normalIter.getValue());
-
-				positionIter.addValue(worldPos);
-				normalIter.addValue(worldNormal);
-				colorIter.addValue(color);
-			}
+			Cube, Sphere, WireCube, WireSphere, Line, Frustum, 
+			Cone, Disc, WireDisc, Arc, WireArc, Rectangle
+		};
 
-			curVertexOffset += numVertices;
-			curIndexOffet += 36;
+		struct RawData
+		{
+			ShapeType shapeType;
+			MeshType meshType;
+			UINT32 idx;
+			float distance;
+			UINT32 numVertices;
+			UINT32 numIndices;
+		};
+
+		/************************************************************************/
+		/* 			Sort everything according to specified sorting rule         */
+		/************************************************************************/
+
+		UINT32 totalNumShapes = (UINT32)(mSolidCubeData.size() + mSolidSphereData.size() + 
+			mWireCubeData.size() + mWireSphereData.size() + mLineData.size() + mFrustumData.size() + mConeData.size() +
+			mDiscData.size() + mWireDiscData.size() + mArcData.size() + mWireArcData.size() + mRect3Data.size());
+
+		UINT32 idx = 0;
+		Vector<RawData> allShapes(totalNumShapes);
+
+		UINT32 localIdx = 0;
+		for (auto& shapeData : mSolidCubeData)
+		{
+			RawData& rawData = allShapes[idx];
+
+			rawData.idx = localIdx++;
+			rawData.meshType = MeshType::Solid;
+			rawData.shapeType = ShapeType::Cube;
+			rawData.distance = shapeData.center.distance(reference);
+			rawData.numVertices = 24;
+			rawData.numIndices = 36;
+			idx++;
 		}
 
-		for (auto& sphereData : mSolidSphereData)
+		localIdx = 0;
+		for (auto& shapeData : mSolidSphereData)
 		{
-			UINT32 numVertices, numIndices;
-			ShapeMeshes3D::getNumElementsSphere(sphereData.quality, numVertices, numIndices);
-
-			Sphere sphere(sphereData.position, sphereData.radius);
-			ShapeMeshes3D::solidSphere(sphere, meshData, curVertexOffset, curIndexOffet, sphereData.quality);
+			RawData& rawData = allShapes[idx];
 
-			Matrix4 transformIT = sphereData.transform.inverseAffine().transpose();
-			RGBA color = sphereData.color.getAsRGBA();
+			rawData.idx = localIdx++;
+			rawData.meshType = MeshType::Solid;
+			rawData.shapeType = ShapeType::Sphere;
+			rawData.distance = shapeData.center.distance(reference);
 
-			for (UINT32 i = 0; i < numVertices; i++)
-			{
-				Vector3 worldPos = sphereData.transform.multiply3x4(positionIter.getValue());
-				Vector3 worldNormal = transformIT.multiply3x4(normalIter.getValue());
-
-				positionIter.addValue(worldPos);
-				normalIter.addValue(worldNormal);
-				colorIter.addValue(color);
-			}
+			ShapeMeshes3D::getNumElementsSphere(shapeData.quality, 
+				rawData.numVertices, rawData.numIndices);
 
-			curVertexOffset += numVertices;
-			curIndexOffet += numIndices;
+			idx++;
 		}
 
-		for (auto& coneData : mConeData)
+		localIdx = 0;
+		for (auto& shapeData : mConeData)
 		{
-			UINT32 numVertices, numIndices;
-			ShapeMeshes3D::getNumElementsCone(coneData.quality, numVertices, numIndices);
+			RawData& rawData = allShapes[idx];
 
-			ShapeMeshes3D::solidCone(coneData.base, coneData.normal, coneData.height, coneData.radius,
-				meshData, curVertexOffset, curIndexOffet, coneData.quality);
+			rawData.idx = localIdx++;
+			rawData.meshType = MeshType::Solid;
+			rawData.shapeType = ShapeType::Cone;
+			rawData.distance = shapeData.center.distance(reference);
 
-			Matrix4 transformIT = coneData.transform.inverseAffine().transpose();
-			RGBA color = coneData.color.getAsRGBA();
+			ShapeMeshes3D::getNumElementsCone(shapeData.quality, 
+				rawData.numVertices, rawData.numIndices);
 
-			for (UINT32 i = 0; i < numVertices; i++)
-			{
-				Vector3 worldPos = coneData.transform.multiply3x4(positionIter.getValue());
-				Vector3 worldNormal = transformIT.multiply3x4(normalIter.getValue());
-
-				positionIter.addValue(worldPos);
-				normalIter.addValue(worldNormal);
-				colorIter.addValue(color);
-			}
-
-			curVertexOffset += numVertices;
-			curIndexOffet += numIndices;
+			idx++;
 		}
 
-		for (auto& discData : mDiscData)
+		localIdx = 0;
+		for (auto& shapeData : mDiscData)
 		{
-			UINT32 numVertices, numIndices;
-			ShapeMeshes3D::getNumElementsDisc(discData.quality, numVertices, numIndices);
-
-			ShapeMeshes3D::solidDisc(discData.position, discData.radius, discData.normal,
-				meshData, curVertexOffset, curIndexOffet, discData.quality);
+			RawData& rawData = allShapes[idx];
 
-			Matrix4 transformIT = discData.transform.inverseAffine().transpose();
-			RGBA color = discData.color.getAsRGBA();
+			rawData.idx = localIdx++;
+			rawData.meshType = MeshType::Solid;
+			rawData.shapeType = ShapeType::Disc;
+			rawData.distance = shapeData.center.distance(reference);
 
-			for (UINT32 i = 0; i < numVertices; i++)
-			{
-				Vector3 worldPos = discData.transform.multiply3x4(positionIter.getValue());
-				Vector3 worldNormal = transformIT.multiply3x4(normalIter.getValue());
+			ShapeMeshes3D::getNumElementsDisc(shapeData.quality,
+				rawData.numVertices, rawData.numIndices);
 
-				positionIter.addValue(worldPos);
-				normalIter.addValue(worldNormal);
-				colorIter.addValue(color);
-			}
-
-			curVertexOffset += numVertices;
-			curIndexOffet += numIndices;
+			idx++;
 		}
 
-		for (auto& arcData : mArcData)
+		localIdx = 0;
+		for (auto& shapeData : mArcData)
 		{
-			UINT32 numVertices, numIndices;
-			ShapeMeshes3D::getNumElementsArc(arcData.quality, numVertices, numIndices);
+			RawData& rawData = allShapes[idx];
 
-			ShapeMeshes3D::solidArc(arcData.position, arcData.radius, arcData.normal, 
-				arcData.startAngle, arcData.amountAngle, meshData, curVertexOffset, curIndexOffet, arcData.quality);
+			rawData.idx = localIdx++;
+			rawData.meshType = MeshType::Solid;
+			rawData.shapeType = ShapeType::Arc;
+			rawData.distance = shapeData.center.distance(reference);
 
-			Matrix4 transformIT = arcData.transform.inverseAffine().transpose();
-			RGBA color = arcData.color.getAsRGBA();
+			ShapeMeshes3D::getNumElementsArc(shapeData.quality, 
+				rawData.numVertices, rawData.numIndices);
 
-			for (UINT32 i = 0; i < numVertices; i++)
-			{
-				Vector3 worldPos = arcData.transform.multiply3x4(positionIter.getValue());
-				Vector3 worldNormal = transformIT.multiply3x4(normalIter.getValue());
-
-				positionIter.addValue(worldPos);
-				normalIter.addValue(worldNormal);
-				colorIter.addValue(color);
-			}
+			idx++;
+		}
 
-			curVertexOffset += numVertices;
-			curIndexOffet += numIndices;
+		localIdx = 0;
+		for (auto& shapeData : mRect3Data)
+		{
+			RawData& rawData = allShapes[idx];
+
+			rawData.idx = localIdx++;
+			rawData.meshType = MeshType::Solid;
+			rawData.shapeType = ShapeType::Rectangle;
+			rawData.distance = shapeData.center.distance(reference);
+			rawData.numVertices = 4;
+			rawData.numIndices = 6;
+			idx++;
 		}
 
-		for (auto& rectData : mRect3Data)
+		localIdx = 0;
+		for (auto& shapeData : mWireCubeData)
 		{
-			ShapeMeshes3D::solidQuad(rectData.area, meshData, curVertexOffset, curIndexOffet);
+			RawData& rawData = allShapes[idx];
+
+			rawData.idx = localIdx++;
+			rawData.meshType = MeshType::Wire;
+			rawData.shapeType = ShapeType::WireCube;
+			rawData.distance = shapeData.center.distance(reference);
+			rawData.numVertices = 8;
+			rawData.numIndices = 24;
+			idx++;
+		}
 
-			Matrix4 transformIT = rectData.transform.inverseAffine().transpose();
-			RGBA color = rectData.color.getAsRGBA();
+		localIdx = 0;
+		for (auto& shapeData : mWireSphereData)
+		{
+			RawData& rawData = allShapes[idx];
 
-			for (UINT32 i = 0; i < 4; i++)
-			{
-				Vector3 worldPos = rectData.transform.multiply3x4(positionIter.getValue());
-				Vector3 worldNormal = transformIT.multiply3x4(normalIter.getValue());
+			rawData.idx = localIdx++;
+			rawData.meshType = MeshType::Wire;
+			rawData.shapeType = ShapeType::WireSphere;
+			rawData.distance = shapeData.center.distance(reference);
 
-				positionIter.addValue(worldPos);
-				normalIter.addValue(worldNormal);
-				colorIter.addValue(color);
-			}
+			ShapeMeshes3D::getNumElementsWireSphere(shapeData.quality,
+				rawData.numVertices, rawData.numIndices);
 
-			curVertexOffset += 4;
-			curIndexOffet += 6;
+			idx++;
 		}
 
-		return mSolidMeshHeap->alloc(meshData, DOT_TRIANGLE_LIST);
-	}
-
-	TransientMeshPtr DrawHelper::buildWireMesh()
-	{
-		MeshDataPtr meshData = bs_shared_ptr<MeshData>(mTotalRequiredWireVertices, 
-			mTotalRequiredWireIndices, mWireVertexDesc);
-
-		UINT32 curVertexOffset = 0;
-		UINT32 curIndexOffet = 0;
-
-		auto positionIter = meshData->getVec3DataIter(VES_POSITION);
-		auto colorIter = meshData->getDWORDDataIter(VES_COLOR);
+		localIdx = 0;
+		for (auto& shapeData : mLineData)
+		{
+			RawData& rawData = allShapes[idx];
+
+			rawData.idx = localIdx++;
+			rawData.meshType = MeshType::Wire;
+			rawData.shapeType = ShapeType::Line;
+			rawData.distance = shapeData.center.distance(reference);
+			rawData.numVertices = 2;
+			rawData.numIndices = 2;
+			idx++;
+		}
 
-		for (auto& cubeData : mWireCubeData)
+		localIdx = 0;
+		for (auto& shapeData : mFrustumData)
 		{
-			AABox box(cubeData.position - cubeData.extents, cubeData.position + cubeData.extents);
-			ShapeMeshes3D::wireAABox(box, meshData, curVertexOffset, curIndexOffet);
+			RawData& rawData = allShapes[idx];
+
+			rawData.idx = localIdx++;
+			rawData.meshType = MeshType::Wire;
+			rawData.shapeType = ShapeType::Frustum;
+			rawData.distance = shapeData.center.distance(reference);
+			rawData.numVertices = 8;
+			rawData.numIndices = 36;
+			idx++;
+		}
 
-			RGBA color = cubeData.color.getAsRGBA();
+		localIdx = 0;
+		for (auto& shapeData : mWireDiscData)
+		{
+			RawData& rawData = allShapes[idx];
 
-			UINT32 numVertices = 8;
-			for (UINT32 i = 0; i < numVertices; i++)
-			{
-				Vector3 worldPos = cubeData.transform.multiply3x4(positionIter.getValue());
+			rawData.idx = localIdx++;
+			rawData.meshType = MeshType::Wire;
+			rawData.shapeType = ShapeType::WireDisc;
+			rawData.distance = shapeData.center.distance(reference);
 
-				positionIter.addValue(worldPos);
-				colorIter.addValue(color);
-			}
+			ShapeMeshes3D::getNumElementsWireDisc(shapeData.quality, 
+				rawData.numVertices, rawData.numIndices);
 
-			curVertexOffset += numVertices;
-			curIndexOffet += 24;
+			idx++;
 		}
 
-		for (auto& sphereData : mWireSphereData)
+		localIdx = 0;
+		for (auto& shapeData : mWireArcData)
 		{
-			UINT32 numVertices, numIndices;
-			ShapeMeshes3D::getNumElementsWireSphere(sphereData.quality, numVertices, numIndices);
+			RawData& rawData = allShapes[idx];
 
-			Sphere sphere(sphereData.position, sphereData.radius);
-			ShapeMeshes3D::wireSphere(sphere, meshData, curVertexOffset, curIndexOffet, sphereData.quality);
+			rawData.idx = localIdx++;
+			rawData.meshType = MeshType::Wire;
+			rawData.shapeType = ShapeType::WireArc;
+			rawData.distance = shapeData.center.distance(reference);
 
-			RGBA color = sphereData.color.getAsRGBA();
-			for (UINT32 i = 0; i < numVertices; i++)
-			{
-				Vector3 worldPos = sphereData.transform.multiply3x4(positionIter.getValue());
+			ShapeMeshes3D::getNumElementsWireArc(shapeData.quality,
+				rawData.numVertices, rawData.numIndices);
 
-				positionIter.addValue(worldPos);
-				colorIter.addValue(color);
-			}
-
-			curVertexOffset += numVertices;
-			curIndexOffet += numIndices;
+			idx++;
 		}
 
-		for (auto& lineData : mLineData)
+		if (sorting == SortType::FrontToBack)
 		{
-			ShapeMeshes3D::pixelLine(lineData.start, lineData.end, meshData, curVertexOffset, curIndexOffet);
-
-			RGBA color = lineData.color.getAsRGBA();
-			for (UINT32 i = 0; i < 2; i++)
+			std::sort(begin(allShapes), end(allShapes),
+				[&](const RawData& x, const RawData& y)
 			{
-				Vector3 worldPos = lineData.transform.multiply3x4(positionIter.getValue());
-
-				positionIter.addValue(worldPos);
-				colorIter.addValue(color);
-			}
-
-			curVertexOffset += 2;
-			curIndexOffet += 2;
+				return x.distance < y.distance;
+			});
 		}
-
-		for (auto& frustumData : mFrustumData)
+		else if (sorting == SortType::BackToFront)
 		{
-			ShapeMeshes3D::wireFrustum(frustumData.position, frustumData.aspect, frustumData.FOV, frustumData.near,
-				frustumData.far, meshData, curVertexOffset, curIndexOffet);
-
-			RGBA color = frustumData.color.getAsRGBA();
-			for (UINT32 i = 0; i < 8; i++)
+			std::sort(begin(allShapes), end(allShapes),
+				[&](const RawData& x, const RawData& y)
 			{
-				Vector3 worldPos = frustumData.transform.multiply3x4(positionIter.getValue());
-
-				positionIter.addValue(worldPos);
-				colorIter.addValue(color);
-			}
-
-			curVertexOffset += 8;
-			curIndexOffet += 24;
+				return y.distance < x.distance;
+			});
 		}
 
-		for (auto& discData : mWireDiscData)
+		/************************************************************************/
+		/* 							Create batches                      		*/
+		/************************************************************************/
+		struct Batch
 		{
-			UINT32 numVertices, numIndices;
-			ShapeMeshes3D::getNumElementsDisc(discData.quality, numVertices, numIndices);
-
-			ShapeMeshes3D::solidDisc(discData.position, discData.radius, discData.normal,
-				meshData, curVertexOffset, curIndexOffet, discData.quality);
+			MeshType type;
+			UINT32 startIdx;
+			UINT32 endIdx;
+			UINT32 numVertices;
+			UINT32 numIndices;
+		};
+
+		Vector<Batch> batches;
+		if (totalNumShapes > 0)
+		{
+			batches.push_back(Batch());
 
-			RGBA color = discData.color.getAsRGBA();
-			for (UINT32 i = 0; i < numVertices; i++)
 			{
-				Vector3 worldPos = discData.transform.multiply3x4(positionIter.getValue());
+				Batch& currentBatch = batches.back();
+				currentBatch.startIdx = 0;
+				currentBatch.type = allShapes[0].meshType;
+				currentBatch.numVertices = allShapes[0].numVertices;
+				currentBatch.numIndices = allShapes[0].numIndices;
+			}
 
-				positionIter.addValue(worldPos);
-				colorIter.addValue(color);
+			for (UINT32 i = 1; i < totalNumShapes; i++)
+			{
+				Batch& currentBatch = batches.back();
+
+				if (allShapes[i].meshType != currentBatch.type)
+				{
+					currentBatch.endIdx = i - 1;
+
+					batches.push_back(Batch());
+
+					Batch& newBatch = batches.back();
+					newBatch.startIdx = i;
+					newBatch.type = allShapes[i].meshType;
+					newBatch.numVertices = allShapes[i].numVertices;
+					newBatch.numIndices = allShapes[i].numIndices;
+				}
+				else
+				{
+					currentBatch.endIdx = i;
+					currentBatch.numVertices += allShapes[i].numVertices;
+					currentBatch.numIndices += allShapes[i].numIndices;
+				}
 			}
 
-			curVertexOffset += numVertices;
-			curIndexOffet += numIndices;
+			{
+				Batch& currentBatch = batches.back();
+				currentBatch.endIdx = totalNumShapes - 1;
+			}
 		}
 
-		for (auto& arcData : mWireArcData)
+		/************************************************************************/
+		/* 					Generate geometry for each batch                    */
+		/************************************************************************/
+		for (auto& batch : batches)
 		{
-			UINT32 numVertices, numIndices;
-			ShapeMeshes3D::getNumElementsArc(arcData.quality, numVertices, numIndices);
-
-			ShapeMeshes3D::solidArc(arcData.position, arcData.radius, arcData.normal,
-				arcData.startAngle, arcData.amountAngle, meshData, curVertexOffset, curIndexOffet, arcData.quality);
-
-			RGBA color = arcData.color.getAsRGBA();
-			for (UINT32 i = 0; i < numVertices; i++)
+			if (batch.type == MeshType::Solid)
 			{
-				Vector3 worldPos = arcData.transform.multiply3x4(positionIter.getValue());
-
-				positionIter.addValue(worldPos);
-				colorIter.addValue(color);
+				MeshDataPtr meshData = bs_shared_ptr<MeshData>(batch.numVertices, batch.numIndices, mSolidVertexDesc);
+
+				UINT32 curVertexOffset = 0;
+				UINT32 curIndexOffet = 0;
+
+				auto positionIter = meshData->getVec3DataIter(VES_POSITION);
+				auto normalIter = meshData->getVec3DataIter(VES_NORMAL);
+				auto colorIter = meshData->getDWORDDataIter(VES_COLOR);
+
+				for (UINT32 i = batch.startIdx; i <= batch.endIdx; i++)
+				{
+					RawData& shapeData = allShapes[i];
+
+					Matrix4* transform = nullptr;
+					RGBA color = 0;
+
+					switch (shapeData.shapeType)
+					{
+					case ShapeType::Cube:
+					{
+						CubeData& cubeData = mSolidCubeData[shapeData.idx];
+						AABox box(cubeData.position - cubeData.extents, cubeData.position + cubeData.extents);
+						ShapeMeshes3D::solidAABox(box, meshData, curVertexOffset, curIndexOffet);
+
+						transform = &cubeData.transform;
+						color = cubeData.color.getAsRGBA();
+					}
+						break;
+					case ShapeType::Sphere:
+					{
+						SphereData& sphereData = mSolidSphereData[shapeData.idx];
+						Sphere sphere(sphereData.position, sphereData.radius);
+						ShapeMeshes3D::solidSphere(sphere, meshData, curVertexOffset, curIndexOffet, sphereData.quality);
+
+						transform = &sphereData.transform;
+						color = sphereData.color.getAsRGBA();
+					}
+						break;
+					case ShapeType::Cone:
+					{
+						ConeData& coneData = mConeData[shapeData.idx];
+						ShapeMeshes3D::solidCone(coneData.base, coneData.normal, coneData.height, coneData.radius,
+							meshData, curVertexOffset, curIndexOffet, coneData.quality);
+
+						transform = &coneData.transform;
+						color = coneData.color.getAsRGBA();
+					}
+						break;
+					case ShapeType::Disc:
+					{
+						DiscData& discData = mDiscData[shapeData.idx];
+						ShapeMeshes3D::solidDisc(discData.position, discData.radius, discData.normal,
+							meshData, curVertexOffset, curIndexOffet, discData.quality);
+
+						transform = &discData.transform;
+						color = discData.color.getAsRGBA();
+					}
+						break;
+					case ShapeType::Arc:
+					{
+						ArcData& arcData = mArcData[shapeData.idx];
+						ShapeMeshes3D::solidArc(arcData.position, arcData.radius, arcData.normal,
+							arcData.startAngle, arcData.amountAngle, meshData, curVertexOffset, curIndexOffet, arcData.quality);
+
+						transform = &arcData.transform;
+						color = arcData.color.getAsRGBA();
+					}
+						break;
+					case ShapeType::Rectangle:
+					{
+						Rect3Data rectData = mRect3Data[shapeData.idx];
+						ShapeMeshes3D::solidQuad(rectData.area, meshData, curVertexOffset, curIndexOffet);
+
+						transform = &rectData.transform;
+						color = rectData.color.getAsRGBA();
+					}
+						break;
+					}
+
+					Matrix4 transformIT = transform->inverseAffine().transpose();
+					for (UINT32 i = 0; i < shapeData.numVertices; i++)
+					{
+						Vector3 worldPos = transform->multiply3x4(positionIter.getValue());
+						Vector3 worldNormal = transformIT.multiply3x4(normalIter.getValue());
+
+						positionIter.addValue(worldPos);
+						normalIter.addValue(worldNormal);
+						colorIter.addValue(color);
+					}
+
+					curVertexOffset += shapeData.numVertices;
+					curIndexOffet += shapeData.numIndices;
+				}
+
+				mMeshes.push_back(ShapeMeshData());
+				ShapeMeshData& newMesh = mMeshes.back();
+				newMesh.mesh = mSolidMeshHeap->alloc(meshData, DOT_TRIANGLE_LIST);
+				newMesh.type = MeshType::Solid;
+			}
+			else // Wire
+			{
+				MeshDataPtr meshData = bs_shared_ptr<MeshData>(batch.numVertices,
+					batch.numIndices, mWireVertexDesc);
+
+				UINT32 curVertexOffset = 0;
+				UINT32 curIndexOffet = 0;
+
+				auto positionIter = meshData->getVec3DataIter(VES_POSITION);
+				auto colorIter = meshData->getDWORDDataIter(VES_COLOR);
+
+				for (UINT32 i = batch.startIdx; i <= batch.endIdx; i++)
+				{
+					RawData& shapeData = allShapes[i];
+
+					Matrix4* transform = nullptr;
+					RGBA color = 0;
+
+					switch (shapeData.shapeType)
+					{
+					case ShapeType::WireCube:
+					{
+						CubeData& cubeData = mWireCubeData[shapeData.idx];
+
+						AABox box(cubeData.position - cubeData.extents, cubeData.position + cubeData.extents);
+						ShapeMeshes3D::wireAABox(box, meshData, curVertexOffset, curIndexOffet);
+
+						transform = &cubeData.transform;
+						color = cubeData.color.getAsRGBA();
+					}
+						break;
+					case ShapeType::WireSphere:
+					{
+						SphereData& sphereData = mWireSphereData[shapeData.idx];
+
+						Sphere sphere(sphereData.position, sphereData.radius);
+						ShapeMeshes3D::wireSphere(sphere, meshData, curVertexOffset, curIndexOffet, sphereData.quality);
+
+						transform = &sphereData.transform;
+						color = sphereData.color.getAsRGBA();
+					}
+						break;
+					case ShapeType::Line:
+					{
+						LineData& lineData = mLineData[shapeData.idx];
+
+						ShapeMeshes3D::pixelLine(lineData.start, lineData.end, meshData, curVertexOffset, curIndexOffet);
+
+						transform = &lineData.transform;
+						color = lineData.color.getAsRGBA();
+					}
+						break;
+					case ShapeType::Frustum:
+					{
+						FrustumData& frustumData = mFrustumData[shapeData.idx];
+
+						ShapeMeshes3D::wireFrustum(frustumData.position, frustumData.aspect, frustumData.FOV, frustumData.near,
+							frustumData.far, meshData, curVertexOffset, curIndexOffet);
+
+						transform = &frustumData.transform;
+						color = frustumData.color.getAsRGBA();
+					}
+						break;
+					case ShapeType::WireDisc:
+					{
+						DiscData& discData = mWireDiscData[shapeData.idx];
+
+						ShapeMeshes3D::wireDisc(discData.position, discData.radius, discData.normal,
+							meshData, curVertexOffset, curIndexOffet, discData.quality);
+
+						transform = &discData.transform;
+						color = discData.color.getAsRGBA();
+					}
+						break;
+					case ShapeType::WireArc:
+					{
+						ArcData& arcData = mWireArcData[shapeData.idx];
+
+						ShapeMeshes3D::wireArc(arcData.position, arcData.radius, arcData.normal,
+							arcData.startAngle, arcData.amountAngle, meshData, curVertexOffset, curIndexOffet, arcData.quality);
+
+						transform = &arcData.transform;
+						color = arcData.color.getAsRGBA();
+					}
+						break;
+					}
+
+					for (UINT32 i = 0; i < shapeData.numVertices; i++)
+					{
+						Vector3 worldPos = transform->multiply3x4(positionIter.getValue());
+
+						positionIter.addValue(worldPos);
+						colorIter.addValue(color);
+					}
+
+					curVertexOffset += shapeData.numVertices;
+					curIndexOffet += shapeData.numIndices;
+				}
+
+				mMeshes.push_back(ShapeMeshData());
+				ShapeMeshData& newMesh = mMeshes.back();
+				newMesh.mesh = mWireMeshHeap->alloc(meshData, DOT_LINE_LIST);
+				newMesh.type = MeshType::Wire;
 			}
-
-			curVertexOffset += numVertices;
-			curIndexOffet += numIndices;
 		}
-
-		return mWireMeshHeap->alloc(meshData, DOT_LINE_LIST);
 	}
 
-	void DrawHelper::releaseSolidMesh(const TransientMeshPtr& mesh)
+	void DrawHelper::clearMeshes()
 	{
-		mSolidMeshHeap->dealloc(mesh);
-	}
+		for (auto meshData : mMeshes)
+		{
+			if (meshData.type == MeshType::Solid)
+				mSolidMeshHeap->dealloc(meshData.mesh);
+			else
+				mWireMeshHeap->dealloc(meshData.mesh);
+		}
 
-	void DrawHelper::releaseWireMesh(const TransientMeshPtr& mesh)
-	{
-		mWireMeshHeap->dealloc(mesh);
+		mMeshes.clear();
 	}
 }

+ 5 - 6
SceneView.txt

@@ -3,12 +3,13 @@
   - Make a C# wrapper for Camera and Renderable
 
 REFACTOR material getParams* and related classes. Those params should update all gpu program params that share that variable, not just the first found
-Line slider collider intersection doesn't work properly
 Handles need to render in front of everything
+ - But I still need to respect depth between overlapping handles
+ - Just sort by distance?
 Clicking on empty space needs to deselect everything
-
-Test gizmos
- - HOOK UP GIZMO SELECTION and test it
+Dragging a slider doesn't move it properly (also need to fix colliders so not all handles overlap)
+Need a way to drag and drop items from Scene tree view to Scene view
+HandleManager::update is meant to be called every frame but it is called only when mouse input is received (and isn't even called on mouse movement it seems)
 
 Test handles
  - Test basic move handle
@@ -21,8 +22,6 @@ IMPROVE SceneGrid LOOK
  - LIKELY USE PIXEL SceneGrid WITH AA
  - OR (better) instead of drawing rows and columns of lines, just draw a plane with procedural texture
 
-Need a way to drag and drop items from Scene tree view to Scene view
-
 LATER:
  - Need a way to render text for gizmos and handles, and in scene in general
  - Add drag to select