Add BuildPickingRay to devel api 70/289370/1
authorDavid Steele <david.steele@samsung.com>
Mon, 6 Mar 2023 18:54:41 +0000 (18:54 +0000)
committerDavid Steele <david.steele@samsung.com>
Mon, 6 Mar 2023 18:54:41 +0000 (18:54 +0000)
Change-Id: I93874e9b546c9f56f90a0cf11e8c4dbc3b7e7b6a

automated-tests/src/dali/utc-Dali-HitTestAlgorithm.cpp
dali/devel-api/events/hit-test-algorithm.cpp
dali/devel-api/events/hit-test-algorithm.h

index 4d17b65..a9167e0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022 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.
@@ -628,4 +628,75 @@ int UtcDaliHitTestAlgorithmOrder(void)
   DALI_TEST_CHECK(results.actor == green);
 
   END_TEST;
-}
\ No newline at end of file
+}
+
+int UtcDaliHitTestAlgorithmBuildPickingRay01(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::HitTestAlgorithm::BuildPickingRay positive test");
+
+  Stage             stage             = Stage::GetCurrent();
+  RenderTaskList    renderTaskList    = stage.GetRenderTaskList();
+  RenderTask        defaultRenderTask = renderTaskList.GetTask(0u);
+  Dali::CameraActor cameraActor       = defaultRenderTask.GetCameraActor();
+
+  Vector2 stageSize(stage.GetSize());
+
+  Vector2 actorSize(stageSize * 0.5f);
+  // Create two actors with half the size of the stage and set them to be overlapping
+  Actor blue = Actor::New();
+  blue.SetProperty(Actor::Property::NAME, "Blue");
+  blue.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+  blue.SetProperty(Actor::Property::PARENT_ORIGIN, AnchorPoint::CENTER);
+  blue.SetProperty(Actor::Property::SIZE, actorSize);
+
+  Actor green = Actor::New();
+  green.SetProperty(Actor::Property::NAME, "Green");
+  green.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+  green.SetProperty(Actor::Property::PARENT_ORIGIN, AnchorPoint::CENTER);
+  green.SetProperty(Actor::Property::SIZE, actorSize);
+
+  // Add the actors to the view
+  stage.Add(blue);
+  stage.Add(green);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render(0);
+
+  Vector2 screenCoords(stageSize * 0.5f); // touch center of screen
+  Vector3 origin;
+  Vector3 direction;
+  bool    built = HitTestAlgorithm::BuildPickingRay(defaultRenderTask, screenCoords, origin, direction);
+
+  Vector3 camPos = cameraActor[Actor::Property::POSITION];
+  DALI_TEST_EQUALS(built, true, TEST_LOCATION);
+  DALI_TEST_EQUALS(camPos, origin, TEST_LOCATION);
+  direction.Normalize();
+  DALI_TEST_EQUALS(direction, -Vector3::ZAXIS, 0.01f, TEST_LOCATION);
+
+  screenCoords.x = stageSize.width * 0.75f;
+  built          = HitTestAlgorithm::BuildPickingRay(defaultRenderTask, screenCoords, origin, direction);
+  DALI_TEST_EQUALS(built, true, TEST_LOCATION);
+  DALI_TEST_EQUALS(camPos, origin, TEST_LOCATION);
+  direction.Normalize();
+  DALI_TEST_EQUALS(direction, Vector3(0.075f, 0.0f, -1.0f), 0.01f, TEST_LOCATION);
+
+  screenCoords.x = 0.0f;
+  screenCoords.y = 0.0f;
+  built          = HitTestAlgorithm::BuildPickingRay(defaultRenderTask, screenCoords, origin, direction);
+  DALI_TEST_EQUALS(built, true, TEST_LOCATION);
+  DALI_TEST_EQUALS(camPos, origin, TEST_LOCATION);
+  direction.Normalize();
+  DALI_TEST_EQUALS(direction, Vector3(-0.144f, -0.24f, -0.96f), 0.01f, TEST_LOCATION);
+
+  screenCoords.x = stageSize.width;
+  screenCoords.y = stageSize.height;
+  built          = HitTestAlgorithm::BuildPickingRay(defaultRenderTask, screenCoords, origin, direction);
+  DALI_TEST_EQUALS(built, true, TEST_LOCATION);
+  DALI_TEST_EQUALS(camPos, origin, TEST_LOCATION);
+  direction.Normalize();
+  DALI_TEST_EQUALS(direction, Vector3(0.144f, 0.24f, -0.96f), 0.01f, TEST_LOCATION);
+
+  END_TEST;
+}
index 5f0ba26..e9e3e7f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 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.
@@ -19,6 +19,7 @@
 #include <dali/devel-api/events/hit-test-algorithm.h>
 
 // INTERNAL INCLUDES
+#include <dali/internal/event/actors/camera-actor-impl.h>
 #include <dali/internal/event/common/scene-impl.h>
 #include <dali/internal/event/common/stage-impl.h>
 #include <dali/internal/event/events/hit-test-algorithm-impl.h>
@@ -34,6 +35,30 @@ bool HitTest(Stage stage, const Vector2& screenCoordinates, Results& results, Hi
   return Internal::HitTestAlgorithm::HitTest(stageImpl.GetSize(), stageImpl.GetRenderTaskList(), stageImpl.GetLayerList(), screenCoordinates, results, func);
 }
 
+bool BuildPickingRay(RenderTask renderTask, const Vector2& screenCoordinates, Vector3& origin, Vector3& direction)
+{
+  Viewport viewport = renderTask.GetViewport();
+  if(screenCoordinates.x < static_cast<float>(viewport.x) ||
+     screenCoordinates.x > static_cast<float>(viewport.x + viewport.width) ||
+     screenCoordinates.y < static_cast<float>(viewport.y) ||
+     screenCoordinates.y > static_cast<float>(viewport.y + viewport.height))
+  {
+    // The screen coordinate is outside the viewport of render task. The viewport clips all layers.
+    return false;
+  }
+  CameraActor            cameraActor     = renderTask.GetCameraActor();
+  Internal::CameraActor& cameraActorImpl = GetImplementation(cameraActor);
+  Vector4                rayOrigin;
+  Vector4                rayDirection;
+  bool                   success = cameraActorImpl.BuildPickingRay(screenCoordinates, viewport, rayOrigin, rayDirection);
+  if(success)
+  {
+    origin    = Vector3(rayOrigin.x, rayOrigin.y, rayOrigin.z);
+    direction = Vector3(rayDirection.x, rayDirection.y, rayDirection.z);
+  }
+  return success;
+}
+
 } // namespace HitTestAlgorithm
 
 } // namespace Dali
index 1417f6e..cc7aad9 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_HIT_TEST_ALGORITHM_H__
 
 /*
- * Copyright (c) 2020 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.
@@ -143,6 +143,17 @@ using HitTestFunction = bool (*)(Actor, TraverseType);
  */
 DALI_CORE_API bool HitTest(Stage stage, const Vector2& screenCoordinates, Results& results, HitTestFunction func);
 
+/**
+ * @brief Given screen coordinates, this method returns the camera origin in world coordinates and the direction of the picking ray in world-space.
+ *
+ * @param[in] renderTask The render task owning a camera.
+ * @param[in] screenCoordinates The screen coordinates.
+ * @param[out] origin The camera origin in world coordinates
+ * @param[out] direction The direction of the picking ray in world-space
+ * @return true if the screen coordinates are inside the render task's viewport
+ */
+DALI_CORE_API bool BuildPickingRay(RenderTask renderTask, const Vector2& screenCoordinates, Vector3& origin, Vector3& direction);
+
 } // namespace HitTestAlgorithm
 
 } // namespace Dali