From 926d6ac76f0f1a7858e19e330e71431e4741e1ce Mon Sep 17 00:00:00 2001 From: Lee Morgan Date: Tue, 3 Nov 2015 17:17:20 +0000 Subject: [PATCH] Added RenderTask WorldToViewport coordinates Change-Id: I80b12b21be3395d6b026a4007c867deac14e8e42 --- automated-tests/src/dali/utc-Dali-RenderTask.cpp | 96 ++++++++++++++++++++++ dali/internal/event/actors/actor-impl.cpp | 2 +- dali/internal/event/actors/actor-impl.h | 4 +- dali/internal/event/common/projection.cpp | 36 ++++++++ dali/internal/event/common/projection.h | 11 +++ dali/internal/event/common/stage-impl.cpp | 12 +++ .../event/render-tasks/render-task-impl.cpp | 35 ++++++++ .../internal/event/render-tasks/render-task-impl.h | 10 +++ dali/public-api/render-tasks/render-task.cpp | 19 +++++ dali/public-api/render-tasks/render-task.h | 26 ++++++ 10 files changed, 248 insertions(+), 3 deletions(-) diff --git a/automated-tests/src/dali/utc-Dali-RenderTask.cpp b/automated-tests/src/dali/utc-Dali-RenderTask.cpp index 8cc7e8f..6b7ae7c 100644 --- a/automated-tests/src/dali/utc-Dali-RenderTask.cpp +++ b/automated-tests/src/dali/utc-Dali-RenderTask.cpp @@ -3451,3 +3451,99 @@ int UtcDaliRenderTaskFinishMissingImage(void) END_TEST; } + +int UtcDaliRenderTaskWorldToViewport(void) +{ + TestApplication application( static_cast(400), static_cast(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; + +} diff --git a/dali/internal/event/actors/actor-impl.cpp b/dali/internal/event/actors/actor-impl.cpp index e44c3f2..614c6e4 100644 --- a/dali/internal/event/actors/actor-impl.cpp +++ b/dali/internal/event/actors/actor-impl.cpp @@ -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 diff --git a/dali/internal/event/actors/actor-impl.h b/dali/internal/event/actors/actor-impl.h index 7f2ae5b..9e78b79 100644 --- a/dali/internal/event/actors/actor-impl.h +++ b/dali/internal/event/actors/actor-impl.h @@ -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. diff --git a/dali/internal/event/common/projection.cpp b/dali/internal/event/common/projection.cpp index 2783195..b7b3d23 100644 --- a/dali/internal/event/common/projection.cpp +++ b/dali/internal/event/common/projection.cpp @@ -22,7 +22,10 @@ #include #include #include +#include +#include #include +#include 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 diff --git a/dali/internal/event/common/projection.h b/dali/internal/event/common/projection.h index 3719129..4d562db 100644 --- a/dali/internal/event/common/projection.h +++ b/dali/internal/event/common/projection.h @@ -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 diff --git a/dali/internal/event/common/stage-impl.cpp b/dali/internal/event/common/stage-impl.cpp index 4559a5c..2f5c9fc 100644 --- a/dali/internal/event/common/stage-impl.cpp +++ b/dali/internal/event/common/stage-impl.cpp @@ -205,6 +205,18 @@ void Stage::SetSize(float width, float height) } SetDefaultSurfaceRectMessage( mUpdateManager, Rect( 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 diff --git a/dali/internal/event/render-tasks/render-task-impl.cpp b/dali/internal/event/render-tasks/render-task-impl.cpp index e95e03d..35e5938 100644 --- a/dali/internal/event/render-tasks/render-task-impl.cpp +++ b/dali/internal/event/render-tasks/render-task-impl.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -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 diff --git a/dali/internal/event/render-tasks/render-task-impl.h b/dali/internal/event/render-tasks/render-task-impl.h index bc7c942..c1d8537 100644 --- a/dali/internal/event/render-tasks/render-task-impl.h +++ b/dali/internal/event/render-tasks/render-task-impl.h @@ -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 /** diff --git a/dali/public-api/render-tasks/render-task.cpp b/dali/public-api/render-tasks/render-task.cpp index 51903a7..b646d00 100644 --- a/dali/public-api/render-tasks/render-task.cpp +++ b/dali/public-api/render-tasks/render-task.cpp @@ -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) { diff --git a/dali/public-api/render-tasks/render-task.h b/dali/public-api/render-tasks/render-task.h index a5c316d..5f865bb 100644 --- a/dali/public-api/render-tasks/render-task.h +++ b/dali/public-api/render-tasks/render-task.h @@ -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 /** -- 2.7.4