Browse Source

Added picking code for gizmos

Marko Pintera 11 năm trước cách đây
mục cha
commit
e8383f3cb7

+ 26 - 0
BansheeEditor/Include/BsBuiltinEditorResources.h

@@ -50,6 +50,16 @@ namespace BansheeEngine
 		 */
 		HMaterial createIconGizmoMat() const;
 
+		/**
+		 * @brief	Creates a material used for picking non-transparent gizmos.
+		 */
+		HMaterial createGizmoPickingMat() const;
+
+		/**
+		 * @brief	Creates a material used for picking transparent gizmos.
+		 */
+		HMaterial createAlphaGizmoPickingMat() const;
+
 		static const String ObjectFieldStyleName;
 		static const String ObjectFieldLabelStyleName;
 		static const String ObjectFieldDropBtnStyleName;
@@ -116,6 +126,16 @@ namespace BansheeEngine
 		 */
 		void initIconGizmoShader();
 
+		/**
+		 * @brief	Loads and compiles a shader used for scene picking of non-transparent gizmos.
+		 */
+		void initGizmoPickingShader();
+
+		/**
+		 * @brief	Loads and compiles a shader used for scene picking of possibly transparent gizmos.
+		 */
+		void initGizmoPickingAlphaShader();
+
 		RenderSystemPlugin mRenderSystemPlugin;
 		WString mActiveShaderSubFolder;
 		String mActiveRenderSystem;
@@ -127,6 +147,8 @@ namespace BansheeEngine
 		ShaderPtr mShaderGizmoSolid;
 		ShaderPtr mShaderGizmoWire;
 		ShaderPtr mShaderGizmoIcon;
+		ShaderPtr mShaderGizmoPicking;
+		ShaderPtr mShaderGizmoAlphaPicking;
 
 		GUISkin mSkin;
 
@@ -278,5 +300,9 @@ namespace BansheeEngine
 		static const WString ShaderIconGizmo0PSFile;
 		static const WString ShaderIconGizmo1VSFile;
 		static const WString ShaderIconGizmo1PSFile;
+		static const WString GizmoPickingVSFile;
+		static const WString GizmoPickingPSFile;
+		static const WString GizmoPickingAlphaVSFile;
+		static const WString GizmoPickingAlphaPSFile;
 	};
 }

+ 35 - 3
BansheeEditor/Include/BsGizmoManager.h

@@ -31,6 +31,8 @@ namespace BansheeEngine
 		void drawIcon(Vector3 position, HSpriteTexture image, bool fixedScale);
 
 		void update();
+		void render();
+		void renderForPicking(std::function<Color(UINT32)> idxToColorCallback);
 		void clearGizmos();
 
 	private:
@@ -111,17 +113,41 @@ namespace BansheeEngine
 			GpuParamTexture mTexture;
 		};
 
+		struct PickingMaterialData
+		{
+			HMaterial material;
+
+			// Core
+			MaterialProxyPtr proxy;
+			GpuParamMat4 mViewProj;
+		};
+
+		struct AlphaPickingMaterialData
+		{
+			HMaterial material;
+
+			// Core
+			MaterialProxyPtr proxy;
+			GpuParamMat4 mViewProj;
+			GpuParamTexture mTexture;
+		};
+
 		typedef Vector<IconRenderData> IconRenderDataVec;
 		typedef std::shared_ptr<IconRenderDataVec> IconRenderDataVecPtr;
 
-		void buildSolidMesh();
-		void buildWireMesh();
-		IconRenderDataVecPtr buildIconMesh();
+		TransientMeshPtr buildSolidMesh(const Vector<CubeData>& cubeData, const Vector<SphereData>& sphereData,
+			UINT32 numVertices, UINT32 numIndices);
+		TransientMeshPtr buildWireMesh(const Vector<CubeData>& cubeData, const Vector<SphereData>& sphereData,
+			const Vector<LineData>& lineData, const Vector<FrustumData>& frustumData, UINT32 numVertices, UINT32 numIndices);
+		TransientMeshPtr buildIconMesh(const Vector<IconData>& iconData, bool pickingOnly, IconRenderDataVecPtr& renderData);
 
 		void coreRenderSolidGizmos(Matrix4 viewMatrix, Matrix4 projMatrix, MeshProxyPtr mesh);
 		void coreRenderWireGizmos(Matrix4 viewMatrix, Matrix4 projMatrix, MeshProxyPtr mesh);
 		void coreRenderIconGizmos(RectI screenArea, MeshProxyPtr mesh, IconRenderDataVecPtr renderData);
 
+		void coreRenderGizmosForPicking(Matrix4 viewMatrix, Matrix4 projMatrix, MeshProxyPtr mesh);
+		void coreRenderIconGizmosForPicking(RectI screenArea, MeshProxyPtr mesh, IconRenderDataVecPtr renderData);
+
 		void limitIconSize(UINT32& width, UINT32& height);
 		void calculateIconColors(const Color& tint, const Camera& camera, UINT32 iconHeight, bool fixedScale,
 			Color& normalColor, Color& fadedColor);
@@ -134,6 +160,7 @@ namespace BansheeEngine
 		static const float MAX_ICON_RANGE;
 		static const UINT32 OPTIMAL_ICON_SIZE;
 		static const float ICON_TEXEL_WORLD_SIZE;
+		static const float PICKING_ALPHA_CUTOFF;
 
 		typedef Set<IconData, std::function<bool(const IconData&, const IconData&)>> IconSet;
 
@@ -166,6 +193,8 @@ namespace BansheeEngine
 		TransientMeshPtr mWireMesh;
 		TransientMeshPtr mIconMesh;
 
+		IconRenderDataVecPtr mIconRenderData;
+
 		// Immutable
 		VertexDataDescPtr mSolidVertexDesc;
 		VertexDataDescPtr mWireVertexDesc;
@@ -175,6 +204,9 @@ namespace BansheeEngine
 		WireMaterialData mWireMaterial;
 		IconMaterialData mIconMaterial;
 
+		PickingMaterialData mPickingMaterial;
+		AlphaPickingMaterialData mAlphaPickingMaterial;
+
 		// Transient
 		struct SortedIconData
 		{

+ 72 - 0
BansheeEditor/Source/BsBuiltinEditorResources.cpp

@@ -205,6 +205,10 @@ namespace BansheeEngine
 	const WString BuiltinEditorResources::ShaderIconGizmo0PSFile = L"iconGizmo0PS.gpuprog";
 	const WString BuiltinEditorResources::ShaderIconGizmo1VSFile = L"iconGizmo1VS.gpuprog";
 	const WString BuiltinEditorResources::ShaderIconGizmo1PSFile = L"iconGizmo1PS.gpuprog";
+	const WString BuiltinEditorResources::GizmoPickingVSFile = L"pickingGizmoVS.gpuprog";
+	const WString BuiltinEditorResources::GizmoPickingPSFile = L"pickingGizmoPS.gpuprog";
+	const WString BuiltinEditorResources::GizmoPickingAlphaVSFile = L"pickingGizmoAlphaVS.gpuprog";
+	const WString BuiltinEditorResources::GizmoPickingAlphaPSFile = L"pickingGizmoAlphaPS.gpuprog";
 
 	BuiltinEditorResources::BuiltinEditorResources(RenderSystemPlugin activeRSPlugin)
 		:mRenderSystemPlugin(activeRSPlugin)
@@ -1075,6 +1079,10 @@ namespace BansheeEngine
 			{ ShaderIconGizmo0PSFile,	"ps_main",	GPT_FRAGMENT_PROGRAM,	GPP_PS_4_0,		"hlsl", HLSL11ShaderSubFolder },
 			{ ShaderIconGizmo1VSFile,	"vs_main",	GPT_VERTEX_PROGRAM,		GPP_VS_4_0,		"hlsl", HLSL11ShaderSubFolder },
 			{ ShaderIconGizmo1PSFile,	"ps_main",	GPT_FRAGMENT_PROGRAM,	GPP_PS_4_0,		"hlsl", HLSL11ShaderSubFolder },
+			{ GizmoPickingVSFile,		"vs_main",	GPT_VERTEX_PROGRAM,		GPP_VS_4_0,		"hlsl", HLSL11ShaderSubFolder },
+			{ GizmoPickingPSFile,		"ps_main",	GPT_FRAGMENT_PROGRAM,	GPP_PS_4_0,		"hlsl", HLSL11ShaderSubFolder },
+			{ GizmoPickingAlphaVSFile,	"vs_main",	GPT_VERTEX_PROGRAM,		GPP_VS_4_0,		"hlsl", HLSL11ShaderSubFolder },
+			{ GizmoPickingAlphaPSFile,	"ps_main",	GPT_FRAGMENT_PROGRAM,	GPP_PS_4_0,		"hlsl", HLSL11ShaderSubFolder },
 			{ SceneGridVSFile,			"vs_main",	GPT_VERTEX_PROGRAM,		GPP_VS_2_0,		"hlsl", HLSL9ShaderSubFolder },
 			{ SceneGridPSFile,			"ps_main",	GPT_FRAGMENT_PROGRAM,	GPP_PS_2_0,		"hlsl", HLSL9ShaderSubFolder },
 			{ ShaderDockOverlayVSFile,	"vs_main",	GPT_VERTEX_PROGRAM,		GPP_VS_2_0,		"hlsl", HLSL9ShaderSubFolder },
@@ -1091,6 +1099,10 @@ namespace BansheeEngine
 			{ ShaderIconGizmo0PSFile,	"ps_main",	GPT_FRAGMENT_PROGRAM,	GPP_PS_4_0,		"hlsl", HLSL9ShaderSubFolder },
 			{ ShaderIconGizmo1VSFile,	"vs_main",	GPT_VERTEX_PROGRAM,		GPP_VS_4_0,		"hlsl", HLSL9ShaderSubFolder },
 			{ ShaderIconGizmo1PSFile,	"ps_main",	GPT_FRAGMENT_PROGRAM,	GPP_PS_4_0,		"hlsl", HLSL9ShaderSubFolder },
+			{ GizmoPickingVSFile,		"vs_main",	GPT_VERTEX_PROGRAM,		GPP_VS_4_0,		"hlsl", HLSL9ShaderSubFolder },
+			{ GizmoPickingPSFile,		"ps_main",	GPT_FRAGMENT_PROGRAM,	GPP_PS_4_0,		"hlsl", HLSL9ShaderSubFolder },
+			{ GizmoPickingAlphaVSFile,	"vs_main",	GPT_VERTEX_PROGRAM,		GPP_VS_4_0,		"hlsl", HLSL9ShaderSubFolder },
+			{ GizmoPickingAlphaPSFile,	"ps_main",	GPT_FRAGMENT_PROGRAM,	GPP_PS_4_0,		"hlsl", HLSL9ShaderSubFolder },
 			{ SceneGridVSFile,			"main",		GPT_VERTEX_PROGRAM,		GPP_VS_4_0,		"glsl", GLSLShaderSubFolder },
 			{ SceneGridPSFile,			"main",		GPT_FRAGMENT_PROGRAM,	GPP_PS_4_0,		"glsl", GLSLShaderSubFolder },
 			{ ShaderDockOverlayVSFile,	"main",		GPT_VERTEX_PROGRAM,		GPP_VS_4_0,		"glsl", GLSLShaderSubFolder },
@@ -1107,6 +1119,10 @@ namespace BansheeEngine
 			{ ShaderIconGizmo0PSFile,	"main",		GPT_FRAGMENT_PROGRAM,	GPP_PS_4_0,		"glsl", GLSLShaderSubFolder },
 			{ ShaderIconGizmo1VSFile,	"main",		GPT_VERTEX_PROGRAM,		GPP_VS_4_0,		"glsl", GLSLShaderSubFolder },
 			{ ShaderIconGizmo1PSFile,	"main",		GPT_FRAGMENT_PROGRAM,	GPP_PS_4_0,		"glsl", GLSLShaderSubFolder },
+			{ GizmoPickingVSFile,		"main",		GPT_VERTEX_PROGRAM,		GPP_VS_4_0,		"glsl", GLSLShaderSubFolder },
+			{ GizmoPickingPSFile,		"main",		GPT_FRAGMENT_PROGRAM,	GPP_PS_4_0,		"glsl", GLSLShaderSubFolder },
+			{ GizmoPickingAlphaVSFile,	"main",		GPT_VERTEX_PROGRAM,		GPP_VS_4_0,		"glsl", GLSLShaderSubFolder },
+			{ GizmoPickingAlphaPSFile,	"main",		GPT_FRAGMENT_PROGRAM,	GPP_PS_4_0,		"glsl", GLSLShaderSubFolder },
 		};
 
 		if (FileSystem::exists(DefaultSkinFolderRaw))
@@ -1441,6 +1457,52 @@ namespace BansheeEngine
 		newPass1->setRasterizerState(rasterizerState);
 	}
 
+	void BuiltinEditorResources::initGizmoPickingShader()
+	{
+		HGpuProgram vsProgram = getGpuProgram(GizmoPickingVSFile);
+		HGpuProgram psProgram = getGpuProgram(GizmoPickingPSFile);
+
+		mShaderGizmoPicking = Shader::create("GizmoPickingShader");
+		mShaderGizmoPicking->addParameter("matViewProj", "matViewProj", GPDT_MATRIX_4X4);
+
+		TechniquePtr newTechnique = mShaderGizmoPicking->addTechnique(mActiveRenderSystem, RendererInvariant);
+		PassPtr newPass = newTechnique->addPass();
+		newPass->setVertexProgram(vsProgram);
+		newPass->setFragmentProgram(psProgram);
+
+		RASTERIZER_STATE_DESC rasterizerDesc;
+		rasterizerDesc.scissorEnable = true;
+
+		HRasterizerState rasterizerState = RasterizerState::create(rasterizerDesc);
+		newPass->setRasterizerState(rasterizerState);
+	}
+
+	void BuiltinEditorResources::initGizmoPickingAlphaShader()
+	{
+		HGpuProgram vsProgram = getGpuProgram(GizmoPickingAlphaVSFile);
+		HGpuProgram psProgram = getGpuProgram(GizmoPickingAlphaPSFile);
+
+		mShaderGizmoAlphaPicking = Shader::create("GizmoPickingAlphaShader");
+
+		mShaderGizmoAlphaPicking->addParameter("mainTexSamp", "mainTexSamp", GPOT_SAMPLER2D);
+		mShaderGizmoAlphaPicking->addParameter("mainTexSamp", "mainTexture", GPOT_SAMPLER2D);
+
+		mShaderGizmoAlphaPicking->addParameter("mainTexture", "mainTexture", GPOT_TEXTURE2D);
+
+		mShaderGizmoAlphaPicking->addParameter("matViewProj", "matViewProj", GPDT_MATRIX_4X4);
+
+		TechniquePtr newTechnique = mShaderGizmoAlphaPicking->addTechnique(mActiveRenderSystem, RendererInvariant);
+		PassPtr newPass = newTechnique->addPass();
+		newPass->setVertexProgram(vsProgram);
+		newPass->setFragmentProgram(psProgram);
+
+		RASTERIZER_STATE_DESC rasterizerDesc;
+		rasterizerDesc.scissorEnable = true;
+
+		HRasterizerState rasterizerState = RasterizerState::create(rasterizerDesc);
+		newPass->setRasterizerState(rasterizerState);
+	}
+
 	HMaterial BuiltinEditorResources::createDockDropOverlayMaterial() const
 	{
 		return Material::create(mShaderDockOverlay);
@@ -1479,4 +1541,14 @@ namespace BansheeEngine
 	{
 		return Material::create(mShaderGizmoIcon);
 	}
+
+	HMaterial BuiltinEditorResources::createGizmoPickingMat() const
+	{
+		return Material::create(mShaderGizmoPicking);
+	}
+
+	HMaterial BuiltinEditorResources::createAlphaGizmoPickingMat() const
+	{
+		return Material::create(mShaderGizmoAlphaPicking);
+	}
 }

+ 205 - 46
BansheeEditor/Source/BsGizmoManager.cpp

@@ -23,6 +23,7 @@ namespace BansheeEngine
 	const float GizmoManager::MAX_ICON_RANGE = 500.0f;
 	const UINT32 GizmoManager::OPTIMAL_ICON_SIZE = 64;
 	const float GizmoManager::ICON_TEXEL_WORLD_SIZE = 0.05f;
+	const float GizmoManager::PICKING_ALPHA_CUTOFF = 0.5f;
 
 	GizmoManager::GizmoManager(const HCamera& camera)
 		:mTotalRequiredSolidIndices(0), mTotalRequiredSolidVertices(0),
@@ -50,10 +51,14 @@ namespace BansheeEngine
 		mSolidMaterial.material = BuiltinEditorResources::instance().createSolidGizmoMat();
 		mWireMaterial.material = BuiltinEditorResources::instance().createWireGizmoMat();
 		mIconMaterial.material = BuiltinEditorResources::instance().createIconGizmoMat();
+		mPickingMaterial.material = BuiltinEditorResources::instance().createGizmoPickingMat();
+		mAlphaPickingMaterial.material = BuiltinEditorResources::instance().createAlphaGizmoPickingMat();
 
 		mSolidMaterial.proxy = mSolidMaterial.material->_createProxy();
 		mWireMaterial.proxy = mWireMaterial.material->_createProxy();
 		mIconMaterial.proxy = mIconMaterial.material->_createProxy();
+		mPickingMaterial.proxy = mPickingMaterial.material->_createProxy();
+		mAlphaPickingMaterial.proxy = mAlphaPickingMaterial.material->_createProxy();
 
 		gCoreAccessor().queueCommand(std::bind(&GizmoManager::initializeCore, this));
 	}
@@ -100,6 +105,28 @@ namespace BansheeEngine
 
 			fragParams->getTextureParam("mainTexture", mIconMaterial.mTexture);
 		}
+
+		{
+			MaterialProxyPtr proxy = mPickingMaterial.proxy;
+			GpuParamsPtr vertParams = proxy->params[proxy->passes[0].vertexProgParamsIdx];
+
+			vertParams->getParam("matViewProj", mPickingMaterial.mViewProj);
+		}
+
+		{
+			MaterialProxyPtr proxy = mAlphaPickingMaterial.proxy;
+			GpuParamsPtr vertParams = proxy->params[proxy->passes[0].vertexProgParamsIdx];
+
+			vertParams->getParam("matViewProj", mAlphaPickingMaterial.mViewProj);
+
+			GpuParamsPtr fragParams = proxy->params[proxy->passes[0].fragmentProgParamsIdx];
+
+			fragParams->getTextureParam("mainTexture", mAlphaPickingMaterial.mTexture);
+
+			GpuParamFloat alphaCutoffParam;
+			fragParams->getParam("alphaCutoff", alphaCutoffParam);
+			alphaCutoffParam.set(PICKING_ALPHA_CUTOFF);
+		}
 	}
 
 	void GizmoManager::startGizmo(const HSceneObject& gizmoParent)
@@ -243,11 +270,25 @@ namespace BansheeEngine
 
 	void GizmoManager::update()
 	{
-		buildSolidMesh();
-		buildWireMesh();
-		IconRenderDataVecPtr iconRenderData = buildIconMesh();
+		if (mSolidMesh != nullptr)
+			mSolidMeshHeap->dealloc(mSolidMesh);
+
+		if (mWireMesh != nullptr)
+			mWireMeshHeap->dealloc(mWireMesh);
+
+		if (mIconMesh != nullptr)
+			mIconMeshHeap->dealloc(mIconMesh);
 
-		// TODO - This must be rendered while Scene view is being rendered
+		mSolidMesh = buildSolidMesh(mSolidCubeData, mSolidSphereData, mTotalRequiredSolidVertices, mTotalRequiredSolidIndices);
+		mWireMesh = buildWireMesh(mWireCubeData, mWireSphereData, mLineData, mFrustumData, mTotalRequiredWireVertices, mTotalRequiredWireIndices);
+		mIconMesh = buildIconMesh(mIconData, false, mIconRenderData);
+
+		clearGizmos();
+	}
+
+	void GizmoManager::render()
+	{
+		// Note: This must be rendered while Scene view is being rendered
 		Matrix4 viewMat = mCamera->getViewMatrix();
 		Matrix4 projMat = mCamera->getProjectionMatrix();
 		ViewportPtr viewport = mCamera->getViewport();
@@ -261,7 +302,67 @@ namespace BansheeEngine
 		RectI screenArea = mCamera->getViewport()->getArea();
 
 		gCoreAccessor().queueCommand(std::bind(&GizmoManager::coreRenderIconGizmos, 
-			this, screenArea, mIconMesh->_createProxy(0), iconRenderData));
+			this, screenArea, mIconMesh->_createProxy(0), mIconRenderData));
+	}
+
+	void GizmoManager::renderForPicking(std::function<Color(UINT32)> idxToColorCallback)
+	{
+		Vector<CubeData> solidCubeData = mSolidCubeData;
+		Vector<CubeData> wireCubeData = mWireCubeData;
+		Vector<SphereData> solidSphereData = mSolidSphereData;
+		Vector<SphereData> wireSphereData = mWireSphereData;
+		Vector<LineData> lineData = mLineData;
+		Vector<FrustumData> frustumData = mFrustumData;
+		Vector<IconData> iconData = mIconData;
+		IconRenderDataVecPtr iconRenderData;
+
+		UINT32 gizmoIdx = 0; // TODO - Since I need to be able to quickly access gizmo data per ID i'll probably want to assign this when they're initially added and used an unordered map
+		for (auto& cubeDataEntry : solidCubeData)
+			cubeDataEntry.color = idxToColorCallback(gizmoIdx++);
+
+		for (auto& cubeDataEntry : wireCubeData)
+			cubeDataEntry.color = idxToColorCallback(gizmoIdx++);
+
+		for (auto& sphereDataEntry : solidSphereData)
+			sphereDataEntry.color = idxToColorCallback(gizmoIdx++);
+
+		for (auto& sphereDataEntry : wireSphereData)
+			sphereDataEntry.color = idxToColorCallback(gizmoIdx++);
+
+		for (auto& lineDataEntry : lineData)
+			lineDataEntry.color = idxToColorCallback(gizmoIdx++);
+
+		for (auto& iconDataEntry : iconData)
+			iconDataEntry.color = idxToColorCallback(gizmoIdx++);
+
+		TransientMeshPtr solidMesh = buildSolidMesh(solidCubeData, solidSphereData, mTotalRequiredSolidVertices, mTotalRequiredSolidIndices);
+		TransientMeshPtr wireMesh = buildWireMesh(wireCubeData, wireSphereData, lineData, frustumData, mTotalRequiredWireVertices, mTotalRequiredWireIndices);
+		TransientMeshPtr iconMesh = buildIconMesh(iconData, true, iconRenderData);
+
+		// Note: This must be rendered while Scene view is being rendered
+		Matrix4 viewMat = mCamera->getViewMatrix();
+		Matrix4 projMat = mCamera->getProjectionMatrix();
+		ViewportPtr viewport = mCamera->getViewport();
+
+		gCoreAccessor().queueCommand(std::bind(&GizmoManager::coreRenderGizmosForPicking,
+			this, viewMat, projMat, solidMesh->_createProxy(0)));
+
+		gCoreAccessor().queueCommand(std::bind(&GizmoManager::coreRenderGizmosForPicking,
+			this, viewMat, projMat, wireMesh->_createProxy(0)));
+
+		RectI screenArea = mCamera->getViewport()->getArea();
+
+		gCoreAccessor().queueCommand(std::bind(&GizmoManager::coreRenderIconGizmosForPicking,
+			this, screenArea, iconMesh->_createProxy(0), iconRenderData));
+
+		if (solidMesh != nullptr)
+			mSolidMeshHeap->dealloc(solidMesh);
+
+		if (wireMesh != nullptr)
+			mWireMeshHeap->dealloc(wireMesh);
+
+		if (iconMesh != nullptr)
+			mIconMeshHeap->dealloc(iconMesh);
 	}
 
 	void GizmoManager::clearGizmos()
@@ -280,9 +381,10 @@ namespace BansheeEngine
 		mTotalRequiredWireIndices = 0;
 	}
 
-	void GizmoManager::buildSolidMesh()
+	TransientMeshPtr GizmoManager::buildSolidMesh(const Vector<CubeData>& cubeData, const Vector<SphereData>& sphereData,
+		UINT32 numVertices, UINT32 numIndices)
 	{
-		MeshDataPtr meshData = bs_shared_ptr<MeshData>(mTotalRequiredSolidVertices, mTotalRequiredSolidIndices, mSolidVertexDesc);
+		MeshDataPtr meshData = bs_shared_ptr<MeshData>(numVertices, numIndices, mSolidVertexDesc);
 
 		UINT32 curVertexOffset = 0;
 		UINT32 curIndexOffet = 0;
@@ -291,7 +393,7 @@ namespace BansheeEngine
 		auto normalIter = meshData->getVec3DataIter(VES_NORMAL);
 		auto colorIter = meshData->getDWORDDataIter(VES_COLOR);
 
-		for (auto& cubeData : mSolidCubeData)
+		for (auto& cubeData : cubeData)
 		{
 			AABox box(cubeData.position - cubeData.extents, cubeData.position + cubeData.extents);
 			DrawHelper3D::instance().solidAABox(box, meshData, curVertexOffset, curIndexOffet); // TODO - These should be static methods
@@ -317,7 +419,7 @@ namespace BansheeEngine
 		UINT32 numSphereVertices, numSphereIndices;
 		DrawHelper3D::getNumElementsSphere(SPHERE_QUALITY, numSphereVertices, numSphereIndices);
 
-		for (auto& sphereData : mSolidSphereData)
+		for (auto& sphereData : sphereData)
 		{
 			Sphere sphere(sphereData.position, sphereData.radius);
 			DrawHelper3D::instance().solidSphere(sphere, meshData, curVertexOffset, curIndexOffet, SPHERE_QUALITY);
@@ -339,15 +441,13 @@ namespace BansheeEngine
 			curIndexOffet += numSphereIndices;
 		}
 
-		if (mSolidMesh != nullptr)
-			mSolidMeshHeap->dealloc(mSolidMesh);
-
-		mSolidMesh = mSolidMeshHeap->alloc(meshData, DOT_TRIANGLE_LIST);
+		return mSolidMeshHeap->alloc(meshData, DOT_TRIANGLE_LIST);
 	}
 
-	void GizmoManager::buildWireMesh()
+	TransientMeshPtr GizmoManager::buildWireMesh(const Vector<CubeData>& cubeData, const Vector<SphereData>& sphereData,
+		const Vector<LineData>& lineData, const Vector<FrustumData>& frustumData, UINT32 numVertices, UINT32 numIndices)
 	{
-		MeshDataPtr meshData = bs_shared_ptr<MeshData>(mTotalRequiredWireVertices, mTotalRequiredWireIndices, mWireVertexDesc);
+		MeshDataPtr meshData = bs_shared_ptr<MeshData>(numVertices, numIndices, mWireVertexDesc);
 
 		UINT32 curVertexOffset = 0;
 		UINT32 curIndexOffet = 0;
@@ -355,7 +455,7 @@ namespace BansheeEngine
 		auto positionIter = meshData->getVec3DataIter(VES_POSITION);
 		auto colorIter = meshData->getDWORDDataIter(VES_COLOR);
 
-		for (auto& cubeData : mWireCubeData)
+		for (auto& cubeData : cubeData)
 		{
 			AABox box(cubeData.position - cubeData.extents, cubeData.position + cubeData.extents);
 			DrawHelper3D::instance().wireAABox(box, meshData, curVertexOffset, curIndexOffet); // TODO - These should be static methods
@@ -378,7 +478,7 @@ namespace BansheeEngine
 		UINT32 numSphereVertices, numSphereIndices;
 		DrawHelper3D::getNumElementsWireSphere(SPHERE_QUALITY, numSphereVertices, numSphereIndices);
 
-		for (auto& sphereData : mWireSphereData)
+		for (auto& sphereData : sphereData)
 		{
 			Sphere sphere(sphereData.position, sphereData.radius);
 			DrawHelper3D::instance().wireSphere(sphere, meshData, curVertexOffset, curIndexOffet, SPHERE_QUALITY);
@@ -396,7 +496,7 @@ namespace BansheeEngine
 			curIndexOffet += numSphereIndices;
 		}
 
-		for (auto& lineData : mLineData)
+		for (auto& lineData : lineData)
 		{
 			DrawHelper3D::instance().pixelLine(lineData.start, lineData.end, meshData, curVertexOffset, curIndexOffet);
 
@@ -413,7 +513,7 @@ namespace BansheeEngine
 			curIndexOffet += 2;
 		}
 
-		for (auto& frustumData : mFrustumData)
+		for (auto& frustumData : frustumData)
 		{
 			DrawHelper3D::instance().wireFrustum(frustumData.aspect, frustumData.FOV, frustumData.near, 
 				frustumData.far, meshData, curVertexOffset, curIndexOffet);
@@ -431,18 +531,15 @@ namespace BansheeEngine
 			curIndexOffet += 24;
 		}
 
-		if (mWireMesh != nullptr)
-			mWireMeshHeap->dealloc(mWireMesh);
-
-		mWireMesh = mWireMeshHeap->alloc(meshData, DOT_LINE_LIST);
+		return mWireMeshHeap->alloc(meshData, DOT_LINE_LIST);
 	}
 
-	GizmoManager::IconRenderDataVecPtr GizmoManager::buildIconMesh()
+	TransientMeshPtr GizmoManager::buildIconMesh(const Vector<IconData>& iconData, bool pickingOnly, GizmoManager::IconRenderDataVecPtr& iconRenderData)
 	{
 		mSortedIconData.clear();
 		
-		if (mIconData.size() > mSortedIconData.size())
-			mSortedIconData.resize(mIconData.size());
+		if (iconData.size() > mSortedIconData.size())
+			mSortedIconData.resize(iconData.size());
 
 		UINT32 i = 0;
 		for (auto& iconData : mIconData)
@@ -459,6 +556,9 @@ namespace BansheeEngine
 			if (!iconData.texture) // Ignore missing texture
 				continue;
 
+			if (pickingOnly && !iconData.pickable)
+				continue;
+
 			SortedIconData& sortedIconData = mSortedIconData[i];
 			sortedIconData.iconIdx = i;
 			sortedIconData.distance = distance;
@@ -475,8 +575,8 @@ namespace BansheeEngine
 		{
 			if (a.distance == b.distance)
 			{
-				HSpriteTexture texA = mIconData[a.iconIdx].texture->getTexture();
-				HSpriteTexture texB = mIconData[b.iconIdx].texture->getTexture();
+				HSpriteTexture texA = iconData[a.iconIdx].texture->getTexture();
+				HSpriteTexture texB = iconData[b.iconIdx].texture->getTexture();
 
 				if (texA == texB)
 					return a.iconIdx < b.iconIdx;
@@ -505,7 +605,7 @@ namespace BansheeEngine
 			cameraScale = (mCamera->getViewport()->getHeight() * 0.5f) / vertFOV.valueRadians();
 		}
 
-		IconRenderDataVecPtr iconRenderData = bs_shared_ptr<IconRenderDataVec>();
+		iconRenderData = bs_shared_ptr<IconRenderDataVec>();
 		UINT32 lastTextureIdx = 0;
 		HTexture curTexture;
 
@@ -514,9 +614,9 @@ namespace BansheeEngine
 		for (i = 0; i < actualNumIcons; i++)
 		{
 			SortedIconData& sortedIconData = mSortedIconData[i];
-			IconData& iconData = mIconData[sortedIconData.iconIdx];
+			const IconData& curIconData = iconData[sortedIconData.iconIdx];
 
-			if (curTexture != iconData.texture)
+			if (curTexture != curIconData.texture)
 			{
 				UINT32 numIconsPerTexture = i - lastTextureIdx;
 				if (numIconsPerTexture > 0)
@@ -528,16 +628,16 @@ namespace BansheeEngine
 				}
 
 				lastTextureIdx = i;
-				curTexture = iconData.texture;
+				curTexture = curIconData.texture;
 			}
 
-			UINT32 iconWidth = iconData.texture->getWidth();
-			UINT32 iconHeight = iconData.texture->getHeight();
+			UINT32 iconWidth = curIconData.texture->getWidth();
+			UINT32 iconHeight = curIconData.texture->getHeight();
 
 			limitIconSize(iconWidth, iconHeight);
 
 			Color normalColor, fadedColor;
-			calculateIconColors(iconData.color, *mCamera.get(), iconHeight, iconData.fixedScale, normalColor, fadedColor);
+			calculateIconColors(curIconData.color, *mCamera.get(), iconHeight, curIconData.fixedScale, normalColor, fadedColor);
 
 			Vector3 position((float)sortedIconData.screenPosition.x, (float)sortedIconData.screenPosition.y, sortedIconData.distance);
 			// TODO - Does the depth need to be corrected since it was taken from a projective camera (probably)?
@@ -545,7 +645,7 @@ namespace BansheeEngine
 			float halfWidth = iconWidth * 0.5f;
 			float halfHeight = iconHeight * 0.5f;
 
-			if (!iconData.fixedScale)
+			if (!curIconData.fixedScale)
 			{
 				float iconScale = 1.0f;
 				if (mCamera->getProjectionType() == PT_ORTHOGRAPHIC)
@@ -564,10 +664,10 @@ namespace BansheeEngine
 			positions[3] = position + Vector3(halfWidth, halfHeight, 0.0f);
 
 			Vector2 uvs[4];
-			uvs[0] = iconData.texture->transformUV(Vector2(0.0f, 0.0f));
-			uvs[1] = iconData.texture->transformUV(Vector2(1.0f, 0.0f));
-			uvs[2] = iconData.texture->transformUV(Vector2(0.0f, 1.0f));
-			uvs[3] = iconData.texture->transformUV(Vector2(1.0f, 1.0f));
+			uvs[0] = curIconData.texture->transformUV(Vector2(0.0f, 0.0f));
+			uvs[1] = curIconData.texture->transformUV(Vector2(1.0f, 0.0f));
+			uvs[2] = curIconData.texture->transformUV(Vector2(0.0f, 1.0f));
+			uvs[3] = curIconData.texture->transformUV(Vector2(1.0f, 1.0f));
 
 			for (UINT32 j = 0; j < 4; j++)
 			{
@@ -589,12 +689,7 @@ namespace BansheeEngine
 			indices += 6;
 		}
 
-		if (mIconMesh != nullptr)
-			mIconMeshHeap->dealloc(mIconMesh);
-
-		mIconMesh = mIconMeshHeap->alloc(meshData, DOT_TRIANGLE_LIST);
-
-		return iconRenderData;
+		return mIconMeshHeap->alloc(meshData, DOT_TRIANGLE_LIST);
 	}
 
 	void GizmoManager::limitIconSize(UINT32& width, UINT32& height)
@@ -717,4 +812,68 @@ namespace BansheeEngine
 
 		mesh->_notifyUsedOnGPU();
 	}
+
+	void GizmoManager::coreRenderGizmosForPicking(Matrix4 viewMatrix, Matrix4 projMatrix, MeshProxyPtr meshProxy)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		Matrix4 viewProjMat = projMatrix * viewMatrix;
+
+		mSolidMaterial.mViewProj.set(viewProjMat);
+
+		Renderer::setPass(*mPickingMaterial.proxy, 0);
+		Renderer::draw(*meshProxy);
+	}
+
+	void GizmoManager::coreRenderIconGizmosForPicking(RectI screenArea, MeshProxyPtr meshProxy, IconRenderDataVecPtr renderData)
+	{
+		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;
+
+		std::shared_ptr<VertexData> vertexData = mesh->_getVertexData();
+
+		rs.setVertexDeclaration(vertexData->vertexDeclaration);
+		auto vertexBuffers = vertexData->getBuffers();
+
+		VertexBufferPtr vertBuffers[1] = { vertexBuffers.begin()->second };
+		rs.setVertexBuffers(0, vertBuffers, 1);
+
+		IndexBufferPtr indexBuffer = mesh->_getIndexBuffer();
+		rs.setIndexBuffer(indexBuffer);
+
+		rs.setDrawOperation(DOT_TRIANGLE_LIST);
+
+		// Set up ortho matrix
+		Matrix4 projMat;
+
+		float left = screenArea.x + rs.getHorizontalTexelOffset();
+		float right = screenArea.x + screenArea.width + rs.getHorizontalTexelOffset();
+		float top = screenArea.y + rs.getVerticalTexelOffset();
+		float bottom = screenArea.y + screenArea.height + rs.getVerticalTexelOffset();
+		float near = rs.getMinimumDepthInputValue();
+		float far = rs.getMaximumDepthInputValue();
+
+		projMat.makeProjectionOrtho(left, right, top, bottom, near, far);
+		mAlphaPickingMaterial.mViewProj.set(projMat);
+
+		Renderer::setPass(*mAlphaPickingMaterial.proxy, 0);
+
+		UINT32 curIndexOffset = 0;
+		for (auto curRenderData : *renderData)
+		{
+			mAlphaPickingMaterial.mTexture.set(curRenderData.texture);
+
+			rs.drawIndexed(curIndexOffset, curRenderData.count * 6, 0, curRenderData.count * 4);
+			curIndexOffset += curRenderData.count * 6;
+
+		}
+
+		mesh->_notifyUsedOnGPU();
+	}
 }

+ 1 - 0
SceneView.txt

@@ -15,6 +15,7 @@ IMMEDIATE:
   - IMPORTANT: Gizmo rendering happens in update() but it should happen whenever scene view is being rendered as the render target isn't set anywhere
   - Add a method that renders gizmos for picking
   - Figure out how to deal with builtin components like Camera and Renderable (e.g. how will they have gizmos since they're not managed components?)
+  - Don't forget to call clearGizmos every frame
 
 LATER:
  - Need a way to render text for gizmos and handles, and in scene in general