Ver código fonte

Changed picking functions definition to support optional snapping

marco.bellan 9 anos atrás
pai
commit
76b323debf

+ 4 - 3
Source/BansheeEditor/Include/BsScenePicking.h

@@ -58,7 +58,7 @@ namespace BansheeEngine
 		 * @param[out]	data		Picking data regarding position and normal.
 		 * @param[out]	data		Picking data regarding position and normal.
 		 * @return					Nearest SceneObject under the provided area, or an empty handle if no object is found.
 		 * @return					Nearest SceneObject under the provided area, or an empty handle if no object is found.
 		 */
 		 */
-		HSceneObject pickClosestObject(const SPtr<Camera>& cam, const Vector2I& position, const Vector2I& area, SnapData& data, Vector<HSceneObject> ignoreRenderables);
+		HSceneObject pickClosestObject(const SPtr<Camera>& cam, const Vector2I& position, const Vector2I& area, Vector<HSceneObject> ignoreRenderables, SnapData* data = nullptr);
 
 
 		/**
 		/**
 		 * Attempts to find all scene objects under the provided position and area. This does not mean objects occluded by
 		 * Attempts to find all scene objects under the provided position and area. This does not mean objects occluded by
@@ -72,7 +72,7 @@ namespace BansheeEngine
 		 * @param[out]	data		Picking data regarding position and normal.
 		 * @param[out]	data		Picking data regarding position and normal.
 		 * @return					A list of SceneObject%s under the provided area.
 		 * @return					A list of SceneObject%s under the provided area.
 		 */
 		 */
-		Vector<HSceneObject> pickObjects(const SPtr<Camera>& cam, const Vector2I& position, const Vector2I& area, SnapData& data, Vector<HSceneObject> ignoreRenderables);
+		Vector<HSceneObject> pickObjects(const SPtr<Camera>& cam, const Vector2I& position, const Vector2I& area, Vector<HSceneObject> ignoreRenderables, SnapData* data = nullptr);
 
 
 	private:
 	private:
 		friend class ScenePickingCore;
 		friend class ScenePickingCore;
@@ -143,11 +143,12 @@ namespace BansheeEngine
 		 * @param[in]	viewportArea	Normalized area of the render target we're rendering in.
 		 * @param[in]	viewportArea	Normalized area of the render target we're rendering in.
 		 * @param[in]	position		Position of the pointer where to pick objects, in pixels relative to viewport.
 		 * @param[in]	position		Position of the pointer where to pick objects, in pixels relative to viewport.
 		 * @param[in]	area			Width/height of the area to pick objects, in pixels.
 		 * @param[in]	area			Width/height of the area to pick objects, in pixels.
+		 * @param[in]	gatherSnapData	Whether it should gather normal and picking position information.
 		 * @param[out]	asyncOp			Async operation handle that when complete will contain the results of the picking
 		 * @param[out]	asyncOp			Async operation handle that when complete will contain the results of the picking
 		 *								operation in the form of Vector<SelectedObject>.
 		 *								operation in the form of Vector<SelectedObject>.
 		 */
 		 */
 		void corePickingEnd(const SPtr<RenderTargetCore>& target, const Rect2& viewportArea, const Vector2I& position,
 		void corePickingEnd(const SPtr<RenderTargetCore>& target, const Rect2& viewportArea, const Vector2I& position,
-			const Vector2I& area, AsyncOp& asyncOp);
+			const Vector2I& area, bool gatherSnapData, AsyncOp& asyncOp);
 
 
 	private:
 	private:
 		friend class ScenePicking;
 		friend class ScenePicking;

+ 62 - 46
Source/BansheeEditor/Source/BsScenePicking.cpp

@@ -55,20 +55,23 @@ namespace BansheeEngine
 		gCoreAccessor().queueCommand(std::bind(&ScenePickingCore::destroy, mCore));
 		gCoreAccessor().queueCommand(std::bind(&ScenePickingCore::destroy, mCore));
 	}
 	}
 
 
-	HSceneObject ScenePicking::pickClosestObject(const SPtr<Camera>& cam, const Vector2I& position, const Vector2I& area, SnapData& data, Vector<HSceneObject> ignoreRenderables)
+	HSceneObject ScenePicking::pickClosestObject(const SPtr<Camera>& cam, const Vector2I& position, const Vector2I& area, Vector<HSceneObject> ignoreRenderables, SnapData* data)
 	{
 	{
-		Vector<HSceneObject> selectedObjects = pickObjects(cam, position, area, data, ignoreRenderables);
+		Vector<HSceneObject> selectedObjects = pickObjects(cam, position, area, ignoreRenderables, data);
 		if (selectedObjects.size() == 0)
 		if (selectedObjects.size() == 0)
 			return HSceneObject();
 			return HSceneObject();
-		Matrix3 rotation;
-		selectedObjects[0]->getWorldRotation().toRotationMatrix(rotation);
-		data.normal = rotation.inverse().transpose().transform(data.normal);
-		LOGWRN("Pos: " + toString(data.pickPosition.x) + " & " + toString(data.pickPosition.y) + " & " + toString(data.pickPosition.z));
-		LOGWRN("Norm: " + toString(data.normal.x) + " & " + toString(data.normal.y) + " & " + toString(data.normal.z));
+		if (data != nullptr)
+		{
+			Matrix3 rotation;
+			selectedObjects[0]->getWorldRotation().toRotationMatrix(rotation);
+			data->normal = rotation.inverse().transpose().transform(data->normal);
+			LOGWRN("Pos: " + toString(data->pickPosition.x) + " & " + toString(data->pickPosition.y) + " & " + toString(data->pickPosition.z));
+			LOGWRN("Norm: " + toString(data->normal.x) + " & " + toString(data->normal.y) + " & " + toString(data->normal.z));
+		}
 		return selectedObjects[0];
 		return selectedObjects[0];
 	}
 	}
 
 
-	Vector<HSceneObject> ScenePicking::pickObjects(const SPtr<Camera>& cam, const Vector2I& position, const Vector2I& area, SnapData& data, Vector<HSceneObject> ignoreRenderables)
+	Vector<HSceneObject> ScenePicking::pickObjects(const SPtr<Camera>& cam, const Vector2I& position, const Vector2I& area, Vector<HSceneObject> ignoreRenderables, SnapData* data)
 	{
 	{
 		auto comparePickElement = [&] (const ScenePicking::RenderablePickData& a, const ScenePicking::RenderablePickData& b)
 		auto comparePickElement = [&] (const ScenePicking::RenderablePickData& a, const ScenePicking::RenderablePickData& b)
 		{
 		{
@@ -181,30 +184,34 @@ namespace BansheeEngine
 		GizmoManager::instance().renderForPicking(cam, [&](UINT32 inputIdx) { return encodeIndex(firstGizmoIdx + inputIdx); });
 		GizmoManager::instance().renderForPicking(cam, [&](UINT32 inputIdx) { return encodeIndex(firstGizmoIdx + inputIdx); });
 
 
 		AsyncOp op = gCoreAccessor().queueReturnCommand(std::bind(&ScenePickingCore::corePickingEnd, mCore, target, 
 		AsyncOp op = gCoreAccessor().queueReturnCommand(std::bind(&ScenePickingCore::corePickingEnd, mCore, target, 
-			cam->getViewport()->getNormArea(), position, area, _1));
+			cam->getViewport()->getNormArea(), position, area, data != nullptr, _1));
 		gCoreAccessor().submitToCoreThread(true);
 		gCoreAccessor().submitToCoreThread(true);
 
 
 		assert(op.hasCompleted());
 		assert(op.hasCompleted());
 
 
 		PickResults returnValue = op.getReturnValue<PickResults>();
 		PickResults returnValue = op.getReturnValue<PickResults>();
-		Vector3 pos = returnValue.data.pickPosition;
-		Vector2 ndcPoint = cam->screenToNdcPoint(Vector2I(pos.x,pos.y));
-		Vector4 worldPoint(ndcPoint.x, ndcPoint.y, pos.z, 1.0f);
-		worldPoint = cam->getProjectionMatrixRS().inverse().multiply(worldPoint);
-		Vector3 worldPoint3D;
 
 
-		if (Math::abs(worldPoint.w) > 1e-7f)
+		if (data != nullptr)
 		{
 		{
-			float invW = 1.0f / worldPoint.w;
+			Vector3 pos = returnValue.data.pickPosition;
+			Vector2 ndcPoint = cam->screenToNdcPoint(Vector2I(pos.x, pos.y));
+			Vector4 worldPoint(ndcPoint.x, ndcPoint.y, pos.z, 1.0f);
+			worldPoint = cam->getProjectionMatrixRS().inverse().multiply(worldPoint);
+			Vector3 worldPoint3D;
 
 
-			worldPoint3D.x = worldPoint.x * invW;
-			worldPoint3D.y = worldPoint.y * invW;
-			worldPoint3D.z = worldPoint.z * invW;
+			if (Math::abs(worldPoint.w) > 1e-7f)
+			{
+				float invW = 1.0f / worldPoint.w;
+
+				worldPoint3D.x = worldPoint.x * invW;
+				worldPoint3D.y = worldPoint.y * invW;
+				worldPoint3D.z = worldPoint.z * invW;
+			}
+			pos = cam->viewToWorldPoint(worldPoint3D);
+			*data = returnValue.data;
+			data->pickPosition = pos;
+			//Todo: camera to world ray if object is too far
 		}
 		}
-		pos = cam->viewToWorldPoint(worldPoint3D);
-		data = returnValue.data;
-		data.pickPosition = pos;
-		//Todo: camera to world ray if object is too far
 
 
 		Vector<UINT32> selectedObjects = returnValue.objects;
 		Vector<UINT32> selectedObjects = returnValue.objects;
 		Vector<HSceneObject> results;
 		Vector<HSceneObject> results;
@@ -370,7 +377,7 @@ namespace BansheeEngine
 	}
 	}
 
 
 	void ScenePickingCore::corePickingEnd(const SPtr<RenderTargetCore>& target, const Rect2& viewportArea, const Vector2I& position,
 	void ScenePickingCore::corePickingEnd(const SPtr<RenderTargetCore>& target, const Rect2& viewportArea, const Vector2I& position,
-		const Vector2I& area, AsyncOp& asyncOp)
+		const Vector2I& area, bool gatherSnapData, AsyncOp& asyncOp)
 	{
 	{
 		const RenderTargetProperties& rtProps = target->getProperties();
 		const RenderTargetProperties& rtProps = target->getProperties();
 		RenderAPICore& rs = RenderAPICore::instance();
 		RenderAPICore& rs = RenderAPICore::instance();
@@ -396,8 +403,13 @@ namespace BansheeEngine
 		}
 		}
 
 
 		SPtr<PixelData> outputPixelData = outputTexture->getProperties().allocateSubresourceBuffer(0);
 		SPtr<PixelData> outputPixelData = outputTexture->getProperties().allocateSubresourceBuffer(0);
-		SPtr<PixelData> normalsPixelData = normalsTexture->getProperties().allocateSubresourceBuffer(0);
-		SPtr<PixelData> depthPixelData = depthTexture->getProperties().allocateSubresourceBuffer(0);
+		SPtr<PixelData> normalsPixelData;
+		SPtr<PixelData> depthPixelData;
+		if (gatherSnapData)
+		{
+			normalsPixelData = normalsTexture->getProperties().allocateSubresourceBuffer(0);
+			depthPixelData = depthTexture->getProperties().allocateSubresourceBuffer(0);
+		}
 
 
 		outputTexture->readSubresource(0, *outputPixelData);
 		outputTexture->readSubresource(0, *outputPixelData);
 
 
@@ -469,29 +481,33 @@ namespace BansheeEngine
 		for (auto& selectedObject : selectedObjects)
 		for (auto& selectedObject : selectedObjects)
 			objects.push_back(selectedObject.index);
 			objects.push_back(selectedObject.index);
 		
 		
-		depthTexture->readSubresource(0, *depthPixelData);
-		normalsTexture->readSubresource(0, *normalsPixelData);
-		float depth;
-		Color normal;
-		if (rtProps.requiresTextureFlipping())
-		{
-			depth = depthPixelData->getDepthAt(position.x, depthPixelData->getHeight() - position.y);
-			normal = normalsPixelData->getColorAt(position.x, depthPixelData->getHeight() - position.y);
-		}
-		else
+		PickResults result;
+		if (gatherSnapData)
 		{
 		{
-			depth = depthPixelData->getDepthAt(position.x, position.y);
-			normal = normalsPixelData->getColorAt(position.x, position.y);
+			depthTexture->readSubresource(0, *depthPixelData);
+			normalsTexture->readSubresource(0, *normalsPixelData);
+			float depth;
+			Color normal;
+			if (rtProps.requiresTextureFlipping())
+			{
+				depth = depthPixelData->getDepthAt(position.x, depthPixelData->getHeight() - position.y);
+				normal = normalsPixelData->getColorAt(position.x, depthPixelData->getHeight() - position.y);
+			}
+			else
+			{
+				depth = depthPixelData->getDepthAt(position.x, position.y);
+				normal = normalsPixelData->getColorAt(position.x, position.y);
+			}
+			LOGWRN(toString(normal.r) + " & " + toString(normal.g) + " & " + toString(normal.b));
+
+			SnapData data;
+			const RenderAPIInfo& rapiInfo = rs.getAPIInfo();
+			depth = depth * Math::abs(rapiInfo.getMaximumDepthInputValue() - rapiInfo.getMinimumDepthInputValue()) + rapiInfo.getMinimumDepthInputValue();
+			data.pickPosition = Vector3(position.x, position.y, depth);
+			data.normal = Vector3((normal.r * 2) - 1, (normal.g * 2) - 1, (normal.b * 2) - 1);
+			result.data = data;
 		}
 		}
-
-		PickResults result;
-		SnapData data;
 		result.objects = objects;
 		result.objects = objects;
-		const RenderAPIInfo& rapiInfo = rs.getAPIInfo();
-		depth = depth * Math::abs(rapiInfo.getMinimumDepthInputValue() - rapiInfo.getMinimumDepthInputValue()) + rapiInfo.getMinimumDepthInputValue();
-		data.pickPosition = Vector3(position.x, position.y, depth);
-		data.normal = Vector3((normal.r * 2) - 1, (normal.g * 2) - 1, (normal.b * 2) - 1);
-		result.data = data;
 		asyncOp._completeOperation(result);
 		asyncOp._completeOperation(result);
 		mNormalsTexture = nullptr;
 		mNormalsTexture = nullptr;
 	}
 	}