From 6fdc5a0cc7c59b4bf6a6294c871ada19c362f40c Mon Sep 17 00:00:00 2001 From: "Eunki, Hong" Date: Wed, 23 Aug 2023 12:52:57 +0900 Subject: [PATCH] Allow epsilon value for ray-test There was some numeric error comes when we touch from edge of the screen. The inputed screen coordiate was exactly 0,0 but the result coordinate was out of bound during calculate matrix invert or etc. To allow this case, let we take some epsilone value during hit-test Change-Id: I57db59a7bab4d57fb07aa087aa675f1c060f81fd Signed-off-by: Eunki, Hong --- dali/internal/event/events/ray-test.cpp | 34 ++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/dali/internal/event/events/ray-test.cpp b/dali/internal/event/events/ray-test.cpp index 9f3aa92..c2e3e29 100644 --- a/dali/internal/event/events/ray-test.cpp +++ b/dali/internal/event/events/ray-test.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * Copyright (c) 2023 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,16 +18,38 @@ // CLASS HEADER #include +// EXTERNAL INCLUDES +#include ///< for std::min, std::max + // INTERNAL INCLUDES #include #include #include +#include #include #include #include using Dali::Internal::SceneGraph::Node; +namespace +{ +constexpr float RAY_TEST_ABSOLUTE_EPSILON = Dali::Epsilon<10>::value; ///< 0.0000011920928955078125 +constexpr float RAY_TEST_RELATIVE_EPSILON = Dali::Epsilon<1000>::value; ///< 0.00011920928955078125 + +/** + * @brief Get the epsilon value that we allow to test. + * It will be used when some numeric error occured. + * + * @param targetScale Scale of target value + * @return The epsilon value for target scale touch case. + */ +constexpr float GetEpsilon(const float targetScale) +{ + return std::max(RAY_TEST_ABSOLUTE_EPSILON, RAY_TEST_RELATIVE_EPSILON * targetScale); +} +} // namespace + namespace Dali { namespace Internal @@ -119,7 +141,10 @@ bool RayTest::SphereTest(const Internal::Actor& actor, const Vector4& rayOrigin, const float width = size.width * scale.width + touchAreaOffset.right - touchAreaOffset.left; const float height = size.height * scale.height + touchAreaOffset.bottom - touchAreaOffset.top; - float squareSphereRadius = 0.5f * (width * width + height * height); + // Correction numeric error. + const float epsilon = GetEpsilon(std::max(width, height)); + + float squareSphereRadius = 0.5f * (width * width + height * height) + epsilon; float a = rayDir.Dot(rayDir); // a float b2 = rayDir.Dot(rayOriginLocal); // b/2 @@ -159,8 +184,11 @@ bool RayTest::ActorTest(const Internal::Actor& actor, const Vector4& rayOrigin, hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f; hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f; + // Correction numeric error. + const float epsilon = GetEpsilon(std::max(size.x, size.y)); + // Test with the actor's geometry. - hit = (hitPointLocal.x >= touchAreaOffset.left) && (hitPointLocal.x <= (size.x + touchAreaOffset.right) && (hitPointLocal.y >= touchAreaOffset.top) && (hitPointLocal.y <= (size.y + touchAreaOffset.bottom))); + hit = (hitPointLocal.x >= touchAreaOffset.left - epsilon) && (hitPointLocal.x <= (size.x + touchAreaOffset.right + epsilon) && (hitPointLocal.y >= touchAreaOffset.top - epsilon) && (hitPointLocal.y <= (size.y + touchAreaOffset.bottom + epsilon))); } } -- 2.7.4