Added RenderTask WorldToViewport coordinates 44/51444/4
authorLee Morgan <Lee.morgan@partner.samsung.com>
Tue, 3 Nov 2015 17:17:20 +0000 (17:17 +0000)
committerLee Morgan <Lee.morgan@partner.samsung.com>
Thu, 3 Dec 2015 15:24:33 +0000 (15:24 +0000)
Change-Id: I80b12b21be3395d6b026a4007c867deac14e8e42

automated-tests/src/dali/utc-Dali-RenderTask.cpp
dali/internal/event/actors/actor-impl.cpp
dali/internal/event/actors/actor-impl.h
dali/internal/event/common/projection.cpp
dali/internal/event/common/projection.h
dali/internal/event/common/stage-impl.cpp
dali/internal/event/render-tasks/render-task-impl.cpp
dali/internal/event/render-tasks/render-task-impl.h
dali/public-api/render-tasks/render-task.cpp
dali/public-api/render-tasks/render-task.h

index 8cc7e8f..6b7ae7c 100644 (file)
@@ -3451,3 +3451,99 @@ int UtcDaliRenderTaskFinishMissingImage(void)
 
   END_TEST;
 }
+
+int UtcDaliRenderTaskWorldToViewport(void)
+{
+  TestApplication application( static_cast<size_t>(400), static_cast<size_t>(400) ); // square surface
+
+  RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetPosition( Vector3(0.0, 0.0, 0.0) );
+
+  actor.SetParentOrigin( Vector3(0.5, 0.5, 0.5) );
+  actor.SetAnchorPoint( Vector3(0.5, 0.5, 0.5) );
+
+  Stage::GetCurrent().Add(actor);
+
+  application.Render();
+  application.SendNotification();
+  application.Render();
+  application.SendNotification();
+
+  RenderTask task = taskList.GetTask( 0u );
+
+  CameraActor camera = task.GetCameraActor();
+
+  Vector2 screenSize = task.GetCurrentViewportSize();
+
+  float screenX = 0.0;
+  float screenY = 0.0;
+
+  bool ok = task.WorldToViewport(actor.GetCurrentWorldPosition(), screenX, screenY);
+  DALI_TEST_CHECK(ok == true);
+
+  DALI_TEST_EQUALS(screenX, screenSize.x/2, Math::MACHINE_EPSILON_10000, TEST_LOCATION);
+  DALI_TEST_EQUALS(screenY, screenSize.y/2, Math::MACHINE_EPSILON_10000, TEST_LOCATION);
+
+  Actor actor2 = Actor::New();
+  float actor2Size = 100.f;
+  actor2.SetSize( actor2Size, actor2Size );
+  actor2.SetPosition( Vector3(0.0, 0.0, 0.0) );
+  actor2.SetParentOrigin( Vector3(0.5, 0.5, 0.0) );
+  actor2.SetAnchorPoint( Vector3(0.5, 0.5, 0.0) );
+  Stage::GetCurrent().Add( actor2 );
+  actor2.Add(actor);
+  actor.SetParentOrigin( Vector3(0,0,0) );
+
+  application.Render();
+  application.SendNotification();
+  application.Render();
+  application.SendNotification();
+
+  ok = task.WorldToViewport(actor.GetCurrentWorldPosition(), screenX, screenY);
+  DALI_TEST_CHECK(ok == true);
+
+  DALI_TEST_EQUALS(screenX, screenSize.x/2 - actor2Size/2, Math::MACHINE_EPSILON_10000, TEST_LOCATION);
+  DALI_TEST_EQUALS(screenY, screenSize.y/2 - actor2Size/2, Math::MACHINE_EPSILON_10000, TEST_LOCATION);
+
+  END_TEST;
+}
+
+
+int UtcDaliRenderTaskViewportToLocal(void)
+{
+  TestApplication application;
+  Actor actor = Actor::New();
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetPosition(10.0f, 10.0f);
+  Stage::GetCurrent().Add(actor);
+
+  RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
+  RenderTask task = taskList.GetTask( 0u );
+
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  float localX;
+  float localY;
+
+  float rtLocalX;
+  float rtLocalY;
+
+  float screenX = 50.0f;
+  float screenY = 50.0f;
+
+  DALI_TEST_CHECK( actor.ScreenToLocal(localX, localY, screenX, screenY) );
+
+  DALI_TEST_CHECK( task.ViewportToLocal(actor, screenX, screenY, rtLocalX, rtLocalY ) );
+
+  DALI_TEST_EQUALS(localX, rtLocalX, 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(localY, rtLocalY, 0.01f, TEST_LOCATION);
+
+  END_TEST;
+
+}
index e44c3f2..614c6e4 100644 (file)
@@ -1476,7 +1476,7 @@ bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float sc
   return false;
 }
 
-bool Actor::ScreenToLocal( RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
+bool Actor::ScreenToLocal( const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
 {
   bool retval = false;
   // only valid when on-stage
index 7f2ae5b..9e78b79 100644 (file)
@@ -1199,7 +1199,7 @@ public:
    * @copydoc Dali::Actor::GetMaximumSize
    */
   float GetMaximumSize( Dimension::Type dimension ) const;
-  
+
   /**
    * @copydoc Dali::Actor::AddRenderer()
    */
@@ -1248,7 +1248,7 @@ public:
    * @param[in] screenY The screen Y-coordinate.
    * @return True if the conversion succeeded.
    */
-  bool ScreenToLocal( RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const;
+  bool ScreenToLocal( const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const;
 
   /**
    * Converts from the actor's coordinate system to screen coordinates.
index 2783195..b7b3d23 100644 (file)
 #include <dali/public-api/math/rect.h>
 #include <dali/public-api/math/matrix.h>
 #include <dali/public-api/math/vector4.h>
+#include <dali/public-api/math/vector2.h>
+#include <dali/public-api/math/viewport.h>
 #include <dali/integration-api/debug.h>
+#include <dali/public-api/math/math-utils.h>
 
 namespace Dali
 {
@@ -110,6 +113,39 @@ bool XyPlaneIntersect( const Vector4& pointA, const Vector4& pointB, Vector4& in
   return true;
 }
 
+bool ProjectFull( const Vector4& position,
+                  const Matrix& modelView,
+                  const Matrix& projection,
+                  float viewportX,
+                  float viewportY,
+                  float viewportWidth,
+                  float viewportHeight,
+                  Vector4& windowPos )
+{
+  bool ok = false;
+
+  Matrix Mvp( false ); // Don't initialize.
+  Matrix::Multiply( Mvp, modelView, projection );
+
+  Vector4 p = Mvp * position;
+
+  Vector2 depthRange(0,1);
+
+  if( !EqualsZero( p.w ) )
+  {
+    float div = 1.0 / p.w;
+
+    windowPos = Vector4( (1 + p.x * div) * viewportWidth  / 2 + viewportX,
+                         (1 - p.y * div) * viewportHeight / 2 + viewportY,
+                         (p.z * div) * (depthRange.y - depthRange.x) + depthRange.x,
+                         div);
+    ok = true;
+  }
+
+  return ok;
+}
+
+
 } // namespace Internal
 
 } // namespace Dali
index 3719129..4d562db 100644 (file)
@@ -22,6 +22,8 @@ namespace Dali
 {
 
 struct Vector4;
+struct Vector2;
+
 class Matrix;
 
 namespace Internal
@@ -44,6 +46,15 @@ bool Unproject(const Dali::Vector4& windowPos,
                float viewportHeight,
                Dali::Vector4& objectPos);
 
+bool ProjectFull( const Vector4& position,
+                  const Matrix& modelView,
+                  const Matrix& projection,
+                  float viewportX,
+                  float viewportY,
+                  float viewportWidth,
+                  float viewportHeight,
+                  Vector4& windowPos );
+
 } // namespace Internal
 
 } // namespace Dali
index 4559a5c..2f5c9fc 100644 (file)
@@ -205,6 +205,18 @@ void Stage::SetSize(float width, float height)
   }
 
   SetDefaultSurfaceRectMessage( mUpdateManager, Rect<int>( 0, 0, width, height ) );
+
+  // if single render task to screen then set its viewport parameters
+  if( 1 == mRenderTaskList->GetTaskCount() )
+  {
+    Dali::RenderTask mDefaultRenderTask = mRenderTaskList->GetTask(0);
+
+    if(!mDefaultRenderTask.GetTargetFrameBuffer())
+    {
+      mDefaultRenderTask.SetViewport( Viewport(0, 0, width, height) );
+    }
+  }
+
 }
 
 Vector2 Stage::GetSize() const
index e95e03d..35e5938 100644 (file)
@@ -29,6 +29,7 @@
 #include <dali/internal/event/actors/camera-actor-impl.h>
 #include <dali/internal/event/common/property-helper.h>
 #include <dali/internal/event/common/stage-impl.h>
+#include <dali/internal/event/common/projection.h>
 #include <dali/internal/event/images/frame-buffer-image-impl.h>
 #include <dali/internal/update/nodes/node.h>
 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
@@ -413,6 +414,40 @@ bool RenderTask::IsSystemLevel() const
   return mIsSystemLevel;
 }
 
+bool RenderTask::WorldToViewport(const Vector3 &position, float& viewportX, float& viewportY) const
+{
+  CameraActor* cam = GetCameraActor();
+
+  Vector4 pos(position);
+  pos.w = 1.0;
+
+  Vector4 viewportPosition;
+
+  Viewport viewport;
+  GetViewport( viewport );
+
+  bool ok = ProjectFull(pos,
+                        cam->GetViewMatrix(),
+                        cam->GetProjectionMatrix(),
+                        viewport.x,
+                        viewport.y,
+                        viewport.width,
+                        viewport.height,
+                        viewportPosition);
+  if(ok)
+  {
+    viewportX = viewportPosition.x;
+    viewportY = viewportPosition.y;
+  }
+
+  return ok;
+}
+
+bool RenderTask::ViewportToLocal(Actor* actor, float viewportX, float viewportY, float &localX, float &localY) const
+{
+  return actor->ScreenToLocal( *this, localX, localY, viewportX, viewportY );
+}
+
 SceneGraph::RenderTask* RenderTask::CreateSceneObject()
 {
   // This should only be called once, with no existing scene-object
index bc7c942..c1d8537 100644 (file)
@@ -211,6 +211,16 @@ public:
    */
   bool IsSystemLevel() const;
 
+  /**
+   * @copydoc Dali::RenderTask::WorldToViewport()
+   */
+  bool WorldToViewport(const Vector3 &position, float& viewportX, float& viewportY) const;
+
+  /**
+   * @copydoc Dali::RenderTask::ViewportToLocal()
+   */
+  bool ViewportToLocal(Actor* actor, float viewportX, float viewportY, float &localX, float &localY) const;
+
 public: // Used by RenderTaskList, which owns the SceneGraph::RenderTasks
 
   /**
index 51903a7..b646d00 100644 (file)
@@ -240,6 +240,25 @@ bool RenderTask::GetInputEnabled() const
   return GetImplementation(*this).GetInputEnabled();
 }
 
+bool RenderTask::WorldToViewport(const Vector3 &position, float& viewportX, float& viewportY) const
+{
+  return GetImplementation(*this).WorldToViewport(position, viewportX, viewportY);
+}
+
+bool RenderTask::ViewportToLocal(Actor actor, float viewportX, float viewportY, float &localX, float &localY) const
+{
+  if( actor )
+  {
+    Internal::Actor* actorImpl( &GetImplementation( actor ) );
+    return GetImplementation(*this).ViewportToLocal( actorImpl, viewportX, viewportY, localX, localY );
+  }
+  else
+  {
+    return false;
+  }
+}
+
+
 RenderTask::RenderTask( Internal::RenderTask* internal )
 : Handle(internal)
 {
index a5c316d..5f865bb 100644 (file)
@@ -402,6 +402,32 @@ public:
    */
   unsigned int GetRefreshRate() const;
 
+  /*
+   * @brief Get viewport coordinates for given world position
+   *
+   * @since DALi 1.1.13
+   *
+   * @param[in] position The world position.
+   * @param[out] viewportX The viewport x position.
+   * @param[out] viewportY The viewport y position.
+   * @return true if the position has a screen coordinate
+   */
+  bool WorldToViewport(const Vector3 &position, float& viewportX, float& viewportY) const;
+
+  /*
+   * @brief Get actor local coordinates for given viewport coordinates
+   *
+   * @since DALi 1.1.13
+   *
+   * @param[in] actor The actor describing local coordinate system.
+   * @param[in] viewportX The viewport x position.
+   * @param[in] viewportY The viewport y position.
+   * @param[out] localX The local x position.
+   * @param[out] localY The local y position.
+   * @return true if the screen position has a local coordinate
+   */
+  bool ViewportToLocal(Actor actor, float viewportX, float viewportY, float &localX, float &localY) const;
+
 public: // Signals
 
   /**