X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Finternal%2Fevent%2Factors%2Fcamera-actor-impl.cpp;h=f714d74f52847e1b8798d265838feac77e988462;hb=a9058d861e58c0eda7945f531d909723670df505;hp=ae63c9f7ec169f3609e0e99b2618eccad889ad23;hpb=da298bea0d5f6dd40092511fcd255b423ceb79e3;p=platform%2Fcore%2Fuifw%2Fdali-core.git diff --git a/dali/internal/event/actors/camera-actor-impl.cpp b/dali/internal/event/actors/camera-actor-impl.cpp index ae63c9f..f714d74 100644 --- a/dali/internal/event/actors/camera-actor-impl.cpp +++ b/dali/internal/event/actors/camera-actor-impl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 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. @@ -23,27 +23,22 @@ #include // for strcmp // INTERNAL INCLUDES -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include #include +#include #include -#include +#include + +#include +#include namespace Dali { - namespace Internal { - namespace { - // Properties /** @@ -51,29 +46,33 @@ namespace * particularly for the default properties. * Name Type writable animatable constraint-input enum for index-checking */ +// clang-format off DALI_PROPERTY_TABLE_BEGIN -DALI_PROPERTY( "type", STRING, true, false, true, Dali::CameraActor::Property::TYPE ) -DALI_PROPERTY( "projectionMode", STRING, true, false, true, Dali::CameraActor::Property::PROJECTION_MODE ) -DALI_PROPERTY( "fieldOfView", FLOAT, true, false, true, Dali::CameraActor::Property::FIELD_OF_VIEW ) -DALI_PROPERTY( "aspectRatio", FLOAT, true, false, true, Dali::CameraActor::Property::ASPECT_RATIO ) -DALI_PROPERTY( "nearPlaneDistance", FLOAT, true, false, true, Dali::CameraActor::Property::NEAR_PLANE_DISTANCE ) -DALI_PROPERTY( "farPlaneDistance", FLOAT, true, false, true, Dali::CameraActor::Property::FAR_PLANE_DISTANCE ) -DALI_PROPERTY( "leftPlaneDistance", FLOAT, true, false, true, Dali::CameraActor::Property::LEFT_PLANE_DISTANCE ) -DALI_PROPERTY( "rightPlaneDistance", FLOAT, true, false, true, Dali::CameraActor::Property::RIGHT_PLANE_DISTANCE ) -DALI_PROPERTY( "topPlaneDistance", FLOAT, true, false, true, Dali::CameraActor::Property::TOP_PLANE_DISTANCE ) -DALI_PROPERTY( "bottomPlaneDistance", FLOAT, true, false, true, Dali::CameraActor::Property::BOTTOM_PLANE_DISTANCE ) -DALI_PROPERTY( "targetPosition", VECTOR3, true, false, true, Dali::CameraActor::Property::TARGET_POSITION ) -DALI_PROPERTY( "projectionMatrix", MATRIX, false, false, true, Dali::CameraActor::Property::PROJECTION_MATRIX ) -DALI_PROPERTY( "viewMatrix", MATRIX, false, false, true, Dali::CameraActor::Property::VIEW_MATRIX ) -DALI_PROPERTY( "invertYAxis", BOOLEAN, true, false, true, Dali::CameraActor::Property::INVERT_Y_AXIS ) +DALI_PROPERTY( "type", INTEGER, true, false, true, Dali::CameraActor::Property::TYPE ) +DALI_PROPERTY( "projectionMode", INTEGER, true, false, true, Dali::CameraActor::Property::PROJECTION_MODE ) +DALI_PROPERTY( "fieldOfView", FLOAT, true, true, true, Dali::CameraActor::Property::FIELD_OF_VIEW ) +DALI_PROPERTY( "aspectRatio", FLOAT, true, true, true, Dali::CameraActor::Property::ASPECT_RATIO ) +DALI_PROPERTY( "nearPlaneDistance", FLOAT, true, false, true, Dali::CameraActor::Property::NEAR_PLANE_DISTANCE ) +DALI_PROPERTY( "farPlaneDistance", FLOAT, true, false, true, Dali::CameraActor::Property::FAR_PLANE_DISTANCE ) +DALI_PROPERTY( "leftPlaneDistance", FLOAT, false, false, true, Dali::CameraActor::Property::LEFT_PLANE_DISTANCE ) +DALI_PROPERTY( "rightPlaneDistance", FLOAT, false, false, true, Dali::CameraActor::Property::RIGHT_PLANE_DISTANCE ) +DALI_PROPERTY( "topPlaneDistance", FLOAT, false, false, true, Dali::CameraActor::Property::TOP_PLANE_DISTANCE ) +DALI_PROPERTY( "bottomPlaneDistance", FLOAT, false, false, true, Dali::CameraActor::Property::BOTTOM_PLANE_DISTANCE ) +DALI_PROPERTY( "targetPosition", VECTOR3, true, false, true, Dali::CameraActor::Property::TARGET_POSITION ) +DALI_PROPERTY( "projectionMatrix", MATRIX, false, false, true, Dali::CameraActor::Property::PROJECTION_MATRIX ) +DALI_PROPERTY( "viewMatrix", MATRIX, false, false, true, Dali::CameraActor::Property::VIEW_MATRIX ) +DALI_PROPERTY( "invertYAxis", BOOLEAN, true, false, true, Dali::CameraActor::Property::INVERT_Y_AXIS ) +DALI_PROPERTY( "orthographicSize", FLOAT, true, true, true, Dali::DevelCameraActor::Property::ORTHOGRAPHIC_SIZE ) +DALI_PROPERTY( "projectionDirection", INTEGER, true, false, true, Dali::DevelCameraActor::Property::PROJECTION_DIRECTION ) DALI_PROPERTY_TABLE_END( DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX, CameraDefaultProperties ) +// clang-format on // calculate the far plane distance for a 16bit depth buffer with 4 bits per unit precision -void CalculateClippingAndZ( float width, float height, float& nearClippingPlane, float& farClippingPlane, float& cameraZ ) +void CalculateClippingAndZ(float width, float height, float& nearClippingPlane, float& farClippingPlane, float& cameraZ) { - nearClippingPlane = std::max( width, height ); - farClippingPlane = nearClippingPlane + static_cast( 0xFFFF >> 4 ); - cameraZ = 2.0f * nearClippingPlane; + nearClippingPlane = std::max(width, height); + farClippingPlane = nearClippingPlane + static_cast(0xFFFF >> 4); + cameraZ = 2.0f * nearClippingPlane; } BaseHandle Create() @@ -81,7 +80,7 @@ BaseHandle Create() return Dali::CameraActor::New(); } -TypeRegistration mType( typeid( Dali::CameraActor ), typeid( Dali::Actor ), Create, CameraDefaultProperties ); +TypeRegistration mType(typeid(Dali::CameraActor), typeid(Dali::Actor), Create, CameraDefaultProperties); /** * Builds the picking ray in the world reference system from an orthographic camera @@ -89,14 +88,14 @@ TypeRegistration mType( typeid( Dali::CameraActor ), typeid( Dali::Actor ), Crea * plane at the camera origin. The ray direction is the direction the camera is facing * (i.e. Z=-1 in view space). */ -void BuildOrthoPickingRay( const Matrix& viewMatrix, - const Matrix& projectionMatrix, - const Viewport& viewport, - float screenX, - float screenY, - Vector4& rayOrigin, - Vector4& rayDir, - float nearPlaneDistance ) +void BuildOrthoPickingRay(const Matrix& viewMatrix, + const Matrix& projectionMatrix, + const Viewport& viewport, + float screenX, + float screenY, + Vector4& rayOrigin, + Vector4& rayDir, + float nearPlaneDistance) { // inv( modelMatrix ) inv( viewMatrix ) inv( projectionMatrix ) normalize // <----------------- <----------------- <-------------- <------------- @@ -107,29 +106,30 @@ void BuildOrthoPickingRay( const Matrix& viewMatrix, // modelMatrix viewMatrix projectionMatrix viewport // Transforms the touch point from the screen reference system to the world reference system. - Matrix invViewProjection( false ); // Don't initialize. - Matrix::Multiply( invViewProjection, viewMatrix, projectionMatrix ); - if( !invViewProjection.Invert() ) + Matrix invViewProjection(false); // Don't initialize. + MatrixUtils::MultiplyProjectionMatrix(invViewProjection, viewMatrix, projectionMatrix); + if(!invViewProjection.Invert()) { - DALI_ASSERT_DEBUG( false ); + DALI_ASSERT_DEBUG(false); } - Vector4 near( screenX - static_cast( viewport.x ), - static_cast( viewport.height ) - (screenY - static_cast( viewport.y ) ), - 0.f, 1.f ); - if( !Unproject( near, invViewProjection, static_cast( viewport.width ), static_cast( viewport.height ), rayOrigin ) ) + Vector4 near(screenX - static_cast(viewport.x), + static_cast(viewport.height) - (screenY - static_cast(viewport.y)), + 0.f, + 1.f); + if(!Unproject(near, invViewProjection, static_cast(viewport.width), static_cast(viewport.height), rayOrigin)) { - DALI_ASSERT_DEBUG( false ); + DALI_ASSERT_DEBUG(false); } Matrix invView = viewMatrix; - if( !invView.Invert() ) + if(!invView.Invert()) { - DALI_ASSERT_DEBUG( false ); + DALI_ASSERT_DEBUG(false); } - Vector4 cameraOrigin = invView * Vector4( 0.f, 0.f, 0.f, 1.f ); - Vector4 nearPlaneOrigin = invView * Vector4( 0.0f, 0.0f, -nearPlaneDistance, 1.0f); + Vector4 cameraOrigin = invView * Vector4(0.f, 0.f, 0.f, 1.f); + Vector4 nearPlaneOrigin = invView * Vector4(0.0f, 0.0f, -nearPlaneDistance, 1.0f); // Vector pointing from the camera to the near plane rayDir = cameraOrigin - nearPlaneOrigin; @@ -138,74 +138,124 @@ void BuildOrthoPickingRay( const Matrix& viewMatrix, rayDir.w = 1.0f; } +/** + * @brief Helper class to calculate left/right/top/bottom plane distance by orthographicSize and something other info. + * It will resolve some confuse case of plane distance value. + * (Something like, Is top plane distance is positive or negative? is aspect ratio is width/height or height/width?) + */ +struct OrthographicSizeConverter +{ + constexpr OrthographicSizeConverter(float orthographicSize, float aspectRatio, Dali::DevelCameraActor::ProjectionDirection projectionDirection) + : mOrthographicSize(orthographicSize), + mAspectRatio(aspectRatio), + mProjectionDirection(projectionDirection) + { + } + + inline float LeftPlaneDistance() const + { + return -(mProjectionDirection == DevelCameraActor::ProjectionDirection::VERTICAL ? mOrthographicSize * mAspectRatio : mOrthographicSize); + } + + inline float RightPlaneDistance() const + { + return (mProjectionDirection == DevelCameraActor::ProjectionDirection::VERTICAL ? mOrthographicSize * mAspectRatio : mOrthographicSize); + } + + inline float TopPlaneDistance() const + { + return (mProjectionDirection == DevelCameraActor::ProjectionDirection::VERTICAL ? mOrthographicSize : mOrthographicSize / mAspectRatio); + } + + inline float BottomPlaneDistance() const + { + return -(mProjectionDirection == DevelCameraActor::ProjectionDirection::VERTICAL ? mOrthographicSize : mOrthographicSize / mAspectRatio); + } + + float mOrthographicSize; + float mAspectRatio; + Dali::DevelCameraActor::ProjectionDirection mProjectionDirection; +}; + } // namespace -CameraActorPtr CameraActor::New( const Size& size ) +CameraActorPtr CameraActor::New(const Size& size) { - CameraActorPtr actor( new CameraActor( *CreateNode() ) ); + // create camera. Cameras are owned by the update manager + SceneGraph::Camera* camera = SceneGraph::Camera::New(); + OwnerPointer transferOwnership(camera); + Internal::ThreadLocalStorage* tls = Internal::ThreadLocalStorage::GetInternal(); + + DALI_ASSERT_ALWAYS(tls && "ThreadLocalStorage is null"); + + // Send ownership of camera. + AddNodeMessage(tls->GetUpdateManager(), transferOwnership); + + CameraActorPtr actor(new CameraActor(*camera)); // Second-phase construction actor->Initialize(); - actor->SetName( "DefaultCamera" ); - actor->SetPerspectiveProjection( size ); + actor->SetName("DefaultCamera"); + actor->SetPerspectiveProjection(size); // By default Actors face in the positive Z direction in world space // CameraActors should face in the negative Z direction, towards the other actors - actor->SetOrientation( Quaternion( Dali::ANGLE_180, Vector3::YAXIS ) ); + actor->SetOrientation(Quaternion(Dali::ANGLE_180, Vector3::YAXIS)); return actor; } -CameraActor::CameraActor( const SceneGraph::Node& node ) -: Actor( Actor::BASIC, node ), - mSceneObject( NULL ), - mTarget( SceneGraph::Camera::DEFAULT_TARGET_POSITION ), - mType( SceneGraph::Camera::DEFAULT_TYPE ), - mProjectionMode( SceneGraph::Camera::DEFAULT_MODE ), - mFieldOfView( SceneGraph::Camera::DEFAULT_FIELD_OF_VIEW ), - mAspectRatio( SceneGraph::Camera::DEFAULT_ASPECT_RATIO ), - mNearClippingPlane( SceneGraph::Camera::DEFAULT_NEAR_CLIPPING_PLANE ), - mFarClippingPlane( SceneGraph::Camera::DEFAULT_FAR_CLIPPING_PLANE ), - mLeftClippingPlane( SceneGraph::Camera::DEFAULT_LEFT_CLIPPING_PLANE ), - mRightClippingPlane( SceneGraph::Camera::DEFAULT_RIGHT_CLIPPING_PLANE ), - mTopClippingPlane( SceneGraph::Camera::DEFAULT_TOP_CLIPPING_PLANE ), - mBottomClippingPlane( SceneGraph::Camera::DEFAULT_BOTTOM_CLIPPING_PLANE ), - mInvertYAxis( SceneGraph::Camera::DEFAULT_INVERT_Y_AXIS ) +CameraActor::CameraActor(const SceneGraph::Node& node) +: Actor(Actor::BASIC, node), + mTarget(SceneGraph::Camera::DEFAULT_TARGET_POSITION), + mType(SceneGraph::Camera::DEFAULT_TYPE), + mProjectionMode(SceneGraph::Camera::DEFAULT_MODE), + mProjectionDirection(SceneGraph::Camera::DEFAULT_PROJECTION_DIRECTION), + mFieldOfView(SceneGraph::Camera::DEFAULT_FIELD_OF_VIEW), + mOrthographicSize(SceneGraph::Camera::DEFAULT_ORTHOGRAPHIC_SIZE), + mAspectRatio(SceneGraph::Camera::DEFAULT_ASPECT_RATIO), + mNearClippingPlane(SceneGraph::Camera::DEFAULT_NEAR_CLIPPING_PLANE), + mFarClippingPlane(SceneGraph::Camera::DEFAULT_FAR_CLIPPING_PLANE), + mInvertYAxis(SceneGraph::Camera::DEFAULT_INVERT_Y_AXIS), + mPropertyChanged(false) { } CameraActor::~CameraActor() { - if( EventThreadServices::IsCoreRunning() ) +} + +void CameraActor::OnSceneConnectionInternal() +{ + // If the canvas size has not been set, then use the size of the scene to which we've been added + // in order to set up the current projection + if(!mPropertyChanged && ((mCanvasSize.width < Math::MACHINE_EPSILON_1000) || (mCanvasSize.height < Math::MACHINE_EPSILON_1000))) { - // Create scene-object and transfer ownership through message - RemoveCameraMessage( GetEventThreadServices().GetUpdateManager(), mSceneObject ); + if(mProjectionMode == Dali::Camera::ORTHOGRAPHIC_PROJECTION) + { + SetOrthographicProjection(GetScene().GetSize()); + } + else //if(mProjectionMode == Dali::Camera::PERSPECTIVE_PROJECTION) + { + SetPerspectiveProjection(GetScene().GetSize()); + } } } -void CameraActor::OnInitialize() +void CameraActor::SetReflectByPlane(const Vector4& plane) { - // Create scene-object and keep raw pointer for message passing. - SceneGraph::Camera* sceneGraphCamera = SceneGraph::Camera::New(); - - // Store a pointer to this camera node inside the scene-graph camera. - sceneGraphCamera->SetNode( &GetNode() ); - - mSceneObject = sceneGraphCamera; - OwnerPointer< SceneGraph::Camera > sceneGraphCameraOwner( sceneGraphCamera ); - - // Send message to inform update of this camera (and move ownership). - AddCameraMessage( GetEventThreadServices().GetUpdateManager(), sceneGraphCameraOwner ); + SetReflectByPlaneMessage(GetEventThreadServices(), GetCameraSceneObject(), plane); } -void CameraActor::SetTarget( const Vector3& target ) +void CameraActor::SetTarget(const Vector3& target) { - if( target != mTarget ) // using range epsilon + mPropertyChanged = true; + if(target != mTarget) // using range epsilon { mTarget = target; - SetTargetPositionMessage( GetEventThreadServices(), *mSceneObject, mTarget ); + SetTargetPositionMessage(GetEventThreadServices(), GetCameraSceneObject(), mTarget); } } @@ -214,14 +264,14 @@ Vector3 CameraActor::GetTarget() const return mTarget; } -void CameraActor::SetType( Dali::Camera::Type type ) +void CameraActor::SetType(Dali::Camera::Type type) { - if( type != mType ) + if(type != mType) { mType = type; // sceneObject is being used in a separate thread; queue a message to set - SetTypeMessage( GetEventThreadServices(), *mSceneObject, mType ); + SetTypeMessage(GetEventThreadServices(), GetCameraSceneObject(), mType); } } @@ -230,14 +280,14 @@ Dali::Camera::Type CameraActor::GetType() const return mType; } -void CameraActor::SetProjectionMode( Dali::Camera::ProjectionMode mode ) +void CameraActor::SetProjectionMode(Dali::Camera::ProjectionMode mode) { - if( mode != mProjectionMode ) + if(mode != mProjectionMode) { mProjectionMode = mode; // sceneObject is being used in a separate thread; queue a message to set - SetProjectionModeMessage( GetEventThreadServices(), *mSceneObject, mProjectionMode ); + SetProjectionModeMessage(GetEventThreadServices(), GetCameraSceneObject(), mProjectionMode); } } @@ -246,122 +296,129 @@ Dali::Camera::ProjectionMode CameraActor::GetProjectionMode() const return mProjectionMode; } -void CameraActor::SetFieldOfView( float fieldOfView ) +void CameraActor::SetProjectionDirection(Dali::DevelCameraActor::ProjectionDirection direction) { - if( ! Equals( fieldOfView, mFieldOfView ) ) + mPropertyChanged = true; + if(direction != mProjectionDirection) { - mFieldOfView = fieldOfView; + mProjectionDirection = direction; // sceneObject is being used in a separate thread; queue a message to set - SetFieldOfViewMessage( GetEventThreadServices(), *mSceneObject, mFieldOfView ); + SetProjectionDirectionMessage(GetEventThreadServices(), GetCameraSceneObject(), mProjectionDirection); } } -float CameraActor::GetFieldOfView() const -{ - return mFieldOfView; -} - -void CameraActor::SetAspectRatio( float aspectRatio ) +void CameraActor::SetFieldOfView(float fieldOfView) { - if( ! Equals( aspectRatio, mAspectRatio ) ) + mPropertyChanged = true; + if(!Equals(fieldOfView, mFieldOfView)) { - mAspectRatio = aspectRatio; + mFieldOfView = fieldOfView; // sceneObject is being used in a separate thread; queue a message to set - SetAspectRatioMessage( GetEventThreadServices(), *mSceneObject, mAspectRatio ); + BakeFieldOfViewMessage(GetEventThreadServices(), GetCameraSceneObject(), mFieldOfView); } } -float CameraActor::GetAspectRatio() const +float CameraActor::GetFieldOfView() const { - return mAspectRatio; + return mFieldOfView; } -void CameraActor::SetNearClippingPlane( float nearClippingPlane ) +float CameraActor::GetCurrentFieldOfView() const { - if( ! Equals( nearClippingPlane, mNearClippingPlane ) ) + // node is being used in a separate thread; copy the value from the previous update + return GetCameraSceneObject().GetFieldOfView(GetEventThreadServices().GetEventBufferIndex()); +} + +void CameraActor::SetOrthographicSize(float orthographicSize) +{ + mPropertyChanged = true; + if(!Equals(orthographicSize, mOrthographicSize)) { - mNearClippingPlane = nearClippingPlane; + mOrthographicSize = orthographicSize; // sceneObject is being used in a separate thread; queue a message to set - SetNearClippingPlaneMessage( GetEventThreadServices(), *mSceneObject, mNearClippingPlane ); + BakeOrthographicSizeMessage(GetEventThreadServices(), GetCameraSceneObject(), mOrthographicSize); } } -float CameraActor::GetNearClippingPlane() const +float CameraActor::GetOrthographicSize() const { - return mNearClippingPlane; + return mOrthographicSize; +} + +float CameraActor::GetCurrentOrthographicSize() const +{ + // node is being used in a separate thread; copy the value from the previous update + return GetCameraSceneObject().GetOrthographicSize(GetEventThreadServices().GetEventBufferIndex()); } -void CameraActor::SetFarClippingPlane( float farClippingPlane ) +void CameraActor::SetAspectRatio(float aspectRatio) { - if( ! Equals( farClippingPlane, mFarClippingPlane ) ) + mPropertyChanged = true; + if(!Equals(aspectRatio, mAspectRatio)) { - mFarClippingPlane = farClippingPlane; + mAspectRatio = aspectRatio; // sceneObject is being used in a separate thread; queue a message to set - SetFarClippingPlaneMessage( GetEventThreadServices(), *mSceneObject, mFarClippingPlane ); + BakeAspectRatioMessage(GetEventThreadServices(), GetCameraSceneObject(), mAspectRatio); } } -float CameraActor::GetFarClippingPlane() const +float CameraActor::GetAspectRatio() const { - return mFarClippingPlane; + return mAspectRatio; } -void CameraActor::SetLeftClippingPlane( float leftClippingPlane ) +float CameraActor::GetCurrentAspectRatio() const { - if( ! Equals( leftClippingPlane, mLeftClippingPlane ) ) - { - mLeftClippingPlane = leftClippingPlane; - - // sceneObject is being used in a separate thread; queue a message to set - SetLeftClippingPlaneMessage( GetEventThreadServices(), *mSceneObject, mLeftClippingPlane ); - } + // node is being used in a separate thread; copy the value from the previous update + return GetCameraSceneObject().GetAspectRatio(GetEventThreadServices().GetEventBufferIndex()); } -void CameraActor::SetRightClippingPlane( float rightClippingPlane ) +void CameraActor::SetNearClippingPlane(float nearClippingPlane) { - if( ! Equals( rightClippingPlane, mRightClippingPlane ) ) + mPropertyChanged = true; + if(!Equals(nearClippingPlane, mNearClippingPlane)) { - mRightClippingPlane = rightClippingPlane; + mNearClippingPlane = nearClippingPlane; // sceneObject is being used in a separate thread; queue a message to set - SetRightClippingPlaneMessage( GetEventThreadServices(), *mSceneObject, mRightClippingPlane ); + SetNearClippingPlaneMessage(GetEventThreadServices(), GetCameraSceneObject(), mNearClippingPlane); } } -void CameraActor::SetTopClippingPlane( float topClippingPlane ) +float CameraActor::GetNearClippingPlane() const { - if( ! Equals( topClippingPlane, mTopClippingPlane ) ) - { - mTopClippingPlane = topClippingPlane; - - // sceneObject is being used in a separate thread; queue a message to set - SetTopClippingPlaneMessage( GetEventThreadServices(), *mSceneObject, mTopClippingPlane ); - } + return mNearClippingPlane; } -void CameraActor::SetBottomClippingPlane( float bottomClippingPlane ) +void CameraActor::SetFarClippingPlane(float farClippingPlane) { - if( ! Equals( bottomClippingPlane, mBottomClippingPlane ) ) + mPropertyChanged = true; + if(!Equals(farClippingPlane, mFarClippingPlane)) { - mBottomClippingPlane = bottomClippingPlane; + mFarClippingPlane = farClippingPlane; // sceneObject is being used in a separate thread; queue a message to set - SetBottomClippingPlaneMessage( GetEventThreadServices(), *mSceneObject, mBottomClippingPlane ); + SetFarClippingPlaneMessage(GetEventThreadServices(), GetCameraSceneObject(), mFarClippingPlane); } } +float CameraActor::GetFarClippingPlane() const +{ + return mFarClippingPlane; +} + void CameraActor::SetInvertYAxis(bool invertYAxis) { - if( invertYAxis != mInvertYAxis ) + if(invertYAxis != mInvertYAxis) { mInvertYAxis = invertYAxis; // sceneObject is being used in a separate thread; queue a message to set - SetInvertYAxisMessage( GetEventThreadServices(), *mSceneObject, mInvertYAxis ); + SetInvertYAxisMessage(GetEventThreadServices(), GetCameraSceneObject(), mInvertYAxis); } } @@ -370,29 +427,73 @@ bool CameraActor::GetInvertYAxis() const return mInvertYAxis; } -void CameraActor::SetPerspectiveProjection( const Size& size ) +void CameraActor::SetPerspectiveProjection(const Size& size) +{ + SetProjectionMode(Dali::Camera::PERSPECTIVE_PROJECTION); + mCanvasSize = static_cast(size); + + if((size.width < Math::MACHINE_EPSILON_1000) || (size.height < Math::MACHINE_EPSILON_1000)) + { + // If the size given is invalid, i.e. ZERO, then check if we've been added to a scene + if(OnScene()) + { + // We've been added to a scene already, set the canvas size to the scene's size + mCanvasSize = GetScene().GetSize(); + } + else + { + // We've not been added to a scene yet, so just return. + // We'll set the canvas size when we get added to a scene later + return; + } + } + ApplyDefaultProjection(); +} + +void CameraActor::SetOrthographicProjection(const Size& size) { - if( ( size.width < Math::MACHINE_EPSILON_1000 ) || ( size.height < Math::MACHINE_EPSILON_1000 ) ) + SetProjectionMode(Dali::Camera::ORTHOGRAPHIC_PROJECTION); + mCanvasSize = static_cast(size); + + if((size.width < Math::MACHINE_EPSILON_1000) || (size.height < Math::MACHINE_EPSILON_1000)) { - // Not allowed to set the canvas size to be 0. - DALI_LOG_ERROR( "Canvas size can not be 0\n" ); - return; + // If the size given is invalid, i.e. ZERO, then check if we've been added to a scene + if(OnScene()) + { + // We've been added to a scene already, set the canvas size to the scene's size + mCanvasSize = GetScene().GetSize(); + } + else + { + // We've not been added to a scene yet, so just return. + // We'll set the canvas size when we get added to a scene later + return; + } } - float width = size.width; - float height = size.height; + ApplyDefaultProjection(); +} + +void CameraActor::ApplyDefaultProjection() +{ + const float width = mCanvasSize.width; + const float height = mCanvasSize.height; + // Choose near, far and Z parameters to match the SetPerspectiveProjection above. float nearClippingPlane; float farClippingPlane; float cameraZ; - CalculateClippingAndZ( width, height, nearClippingPlane, farClippingPlane, cameraZ ); + CalculateClippingAndZ(width, height, nearClippingPlane, farClippingPlane, cameraZ); + + // calculate orthographic size. + const float orthographicSize = (mProjectionDirection == DevelCameraActor::ProjectionDirection::VERTICAL ? height : width) * 0.5f; // calculate the position of the camera to have the desired aspect ratio - const float fieldOfView = 2.0f * std::atan( height * 0.5f / cameraZ ); + const float fieldOfView = 2.0f * std::atan(orthographicSize / cameraZ); // unless it is too small, we want at least as much space to the back as we have torwards the front const float minClippingFarPlane = 2.f * nearClippingPlane; - if ( farClippingPlane < minClippingFarPlane ) + if(farClippingPlane < minClippingFarPlane) { farClippingPlane = minClippingFarPlane; } @@ -400,57 +501,34 @@ void CameraActor::SetPerspectiveProjection( const Size& size ) const float aspectRatio = width / height; // sceneObject is being used in a separate thread; queue a message to set - SetProjectionMode(Dali::Camera::PERSPECTIVE_PROJECTION); - SetFieldOfView( fieldOfView ); - SetNearClippingPlane( nearClippingPlane ); - SetFarClippingPlane( farClippingPlane ); - SetAspectRatio( aspectRatio ); - SetZ( cameraZ ); + SetFieldOfView(fieldOfView); + SetNearClippingPlane(nearClippingPlane); + SetFarClippingPlane(farClippingPlane); + SetAspectRatio(aspectRatio); + SetOrthographicSize(orthographicSize); + SetZ(cameraZ); } - -void CameraActor::SetOrthographicProjection( const Vector2& size ) -{ - // Choose near, far and Z parameters to match the SetPerspectiveProjection above. - float nearClippingPlane; - float farClippingPlane; - float cameraZ; - CalculateClippingAndZ( size.width, size.height, nearClippingPlane, farClippingPlane, cameraZ ); - SetOrthographicProjection( -size.x*0.5f, size.x*0.5f, size.y*0.5f, -size.y*0.5f, - nearClippingPlane, farClippingPlane ); - SetZ( cameraZ ); -} - -void CameraActor::SetOrthographicProjection( float left, float right, float top, float bottom, float near, float far ) -{ - SetLeftClippingPlane( left ); - SetRightClippingPlane( right ); - SetTopClippingPlane( top ); - SetBottomClippingPlane( bottom ); - SetNearClippingPlane( near ); - SetFarClippingPlane( far ); - SetProjectionMode( Dali::Camera::ORTHOGRAPHIC_PROJECTION ); -} - -bool CameraActor::BuildPickingRay( const Vector2& screenCoordinates, - const Viewport& viewport, - Vector4& rayOrigin, - Vector4& rayDirection ) +bool CameraActor::BuildPickingRay(const Vector2& screenCoordinates, + const Viewport& viewport, + Vector4& rayOrigin, + Vector4& rayDirection) { bool success = true; - if( mProjectionMode == Dali::Camera::PERSPECTIVE_PROJECTION ) + if(mProjectionMode == Dali::Camera::PERSPECTIVE_PROJECTION) { // Build a picking ray in the world reference system. // ray starts from the camera world position - rayOrigin = GetNode().GetWorldMatrix(0).GetTranslation(); + rayOrigin = GetNode().GetWorldMatrix(0).GetTranslation(); rayOrigin.w = 1.0f; // Transform the touch point from the screen coordinate system to the world coordinates system. - Vector4 near( screenCoordinates.x - static_cast(viewport.x), - static_cast( viewport.height ) - (screenCoordinates.y - static_cast( viewport.y ) ), - 0.f, 1.f ); - const Matrix& inverseViewProjection = mSceneObject->GetInverseViewProjectionMatrix( GetEventThreadServices().GetEventBufferIndex() ); - success = Unproject( near, inverseViewProjection, static_cast( viewport.width ), static_cast( viewport.height ), near ); + Vector4 near(screenCoordinates.x - static_cast(viewport.x), + static_cast(viewport.height) - (screenCoordinates.y - static_cast(viewport.y)), + 0.f, + 1.f); + const Matrix& inverseViewProjection = GetCameraSceneObject().GetInverseViewProjectionMatrix(GetEventThreadServices().GetEventBufferIndex()); + success = Unproject(near, inverseViewProjection, static_cast(viewport.width), static_cast(viewport.height), near); // Compute the ray's director vector. rayDirection.x = near.x - rayOrigin.x; @@ -462,13 +540,14 @@ bool CameraActor::BuildPickingRay( const Vector2& screenCoordinates, else { float nearPlaneDistance = GetNearClippingPlane(); - BuildOrthoPickingRay( GetViewMatrix(), - GetProjectionMatrix(), - viewport, screenCoordinates.x, - screenCoordinates.y, - rayOrigin, - rayDirection, - nearPlaneDistance ); + BuildOrthoPickingRay(GetViewMatrix(), + GetProjectionMatrix(), + viewport, + screenCoordinates.x, + screenCoordinates.y, + rayOrigin, + rayDirection, + nearPlaneDistance); } return success; @@ -476,9 +555,9 @@ bool CameraActor::BuildPickingRay( const Vector2& screenCoordinates, const Matrix& CameraActor::GetViewMatrix() const { - if ( OnStage() ) + if(OnScene()) { - return mSceneObject->GetViewMatrix( GetEventThreadServices().GetEventBufferIndex() ); + return GetCameraSceneObject().GetViewMatrix(GetEventThreadServices().GetEventBufferIndex()); } else { @@ -488,21 +567,27 @@ const Matrix& CameraActor::GetViewMatrix() const const Matrix& CameraActor::GetProjectionMatrix() const { - if ( OnStage() ) + if(OnScene()) { - return mSceneObject->GetProjectionMatrix( GetEventThreadServices().GetEventBufferIndex() ); + return GetCameraSceneObject().GetProjectionMatrix(GetEventThreadServices().GetEventBufferIndex()); } else { return Matrix::IDENTITY; } } -const SceneGraph::Camera* CameraActor::GetCamera() const +const SceneGraph::Camera& CameraActor::GetCameraSceneObject() const { - return mSceneObject; + return static_cast(GetNode()); +} + +void CameraActor::RotateProjection(int rotationAngle) +{ + // sceneObject is being used in a separate thread; queue a message to set + RotateProjectionMessage(GetEventThreadServices(), GetCameraSceneObject(), rotationAngle); } -void CameraActor::SetDefaultProperty( Property::Index index, const Property::Value& propertyValue ) +void CameraActor::SetDefaultProperty(Property::Index index, const Property::Value& propertyValue) { if(index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT) { @@ -514,93 +599,96 @@ void CameraActor::SetDefaultProperty( Property::Index index, const Property::Val { case Dali::CameraActor::Property::TYPE: { - std::string s( propertyValue.Get() ); - if(s == "LOOK_AT_TARGET") - { - SetType( Dali::Camera::LOOK_AT_TARGET ); - } - else if(s == "FREE_LOOK") - { - SetType( Dali::Camera::FREE_LOOK ); - } + Dali::Camera::Type cameraType = Dali::Camera::Type(propertyValue.Get()); + SetType(cameraType); break; } case Dali::CameraActor::Property::PROJECTION_MODE: { - std::string s( propertyValue.Get() ); - if( s == "PERSPECTIVE_PROJECTION" ) - { - SetProjectionMode( Dali::Camera::PERSPECTIVE_PROJECTION ); - } - else if( s == "ORTHOGRAPHIC_PROJECTION" ) - { - SetProjectionMode( Dali::Camera::ORTHOGRAPHIC_PROJECTION ); - } + Dali::Camera::ProjectionMode projectionMode = Dali::Camera::ProjectionMode(propertyValue.Get()); + SetProjectionMode(projectionMode); break; } case Dali::CameraActor::Property::FIELD_OF_VIEW: { - SetFieldOfView( propertyValue.Get() ); // set to 0 in case property is not float + SetFieldOfView(propertyValue.Get()); // set to 0 in case property is not float + break; + } + case Dali::DevelCameraActor::Property::ORTHOGRAPHIC_SIZE: + { + SetOrthographicSize(propertyValue.Get()); // set to 0 in case property is not float break; } case Dali::CameraActor::Property::ASPECT_RATIO: { - SetAspectRatio( propertyValue.Get() ); // set to 0 in case property is not float + SetAspectRatio(propertyValue.Get()); // set to 0 in case property is not float break; } case Dali::CameraActor::Property::NEAR_PLANE_DISTANCE: { - SetNearClippingPlane( propertyValue.Get() ); // set to 0 in case property is not float + SetNearClippingPlane(propertyValue.Get()); // set to 0 in case property is not float break; } case Dali::CameraActor::Property::FAR_PLANE_DISTANCE: { - SetFarClippingPlane( propertyValue.Get() ); // set to 0 in case property is not float + SetFarClippingPlane(propertyValue.Get()); // set to 0 in case property is not float break; } case Dali::CameraActor::Property::LEFT_PLANE_DISTANCE: { - SetLeftClippingPlane( propertyValue.Get() ); // set to 0 in case property is not float + DALI_LOG_WARNING("LEFT_PLANE_DISTANCE is read-only\n"); break; } case Dali::CameraActor::Property::RIGHT_PLANE_DISTANCE: { - SetRightClippingPlane( propertyValue.Get() ); // set to 0 in case property is not float + DALI_LOG_WARNING("RIGHT_PLANE_DISTANCE is read-only\n"); break; } case Dali::CameraActor::Property::TOP_PLANE_DISTANCE: { - SetTopClippingPlane( propertyValue.Get() ); // set to 0 in case property is not float + DALI_LOG_WARNING("TOP_PLANE_DISTANCE is read-only\n"); break; } case Dali::CameraActor::Property::BOTTOM_PLANE_DISTANCE: { - SetBottomClippingPlane( propertyValue.Get() ); // set to 0 in case property is not float + DALI_LOG_WARNING("BOTTOM_PLANE_DISTANCE is read-only\n"); break; } case Dali::CameraActor::Property::TARGET_POSITION: { - SetTarget( propertyValue.Get() ); // set to 0 in case property is not Vector3 + SetTarget(propertyValue.Get()); // set to 0 in case property is not Vector3 break; } case Dali::CameraActor::Property::PROJECTION_MATRIX: { - DALI_LOG_WARNING( "projection-matrix is read-only\n" ); + DALI_LOG_WARNING("projection-matrix is read-only\n"); break; } case Dali::CameraActor::Property::VIEW_MATRIX: { - DALI_LOG_WARNING( "view-matrix is read-only\n" ); + DALI_LOG_WARNING("view-matrix is read-only\n"); break; } case Dali::CameraActor::Property::INVERT_Y_AXIS: { - SetInvertYAxis( propertyValue.Get() ); // set to false in case property is not bool + SetInvertYAxis(propertyValue.Get()); // set to false in case property is not bool + break; + } + case Dali::DevelCameraActor::Property::REFLECTION_PLANE: + { + SetReflectByPlane(propertyValue.Get()); + break; + } + case Dali::DevelCameraActor::Property::PROJECTION_DIRECTION: + { + Dali::DevelCameraActor::ProjectionDirection projectionDirection = Dali::DevelCameraActor::ProjectionDirection(propertyValue.Get()); + SetProjectionDirection(projectionDirection); break; } + default: { - DALI_LOG_WARNING( "Unknown property (%d)\n", index ); + DALI_LOG_WARNING("Unknown property (%d)\n", index); break; } } // switch(index) @@ -608,10 +696,10 @@ void CameraActor::SetDefaultProperty( Property::Index index, const Property::Val } // else } -Property::Value CameraActor::GetDefaultProperty( Property::Index index ) const +Property::Value CameraActor::GetDefaultProperty(Property::Index index) const { Property::Value ret; - if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT ) + if(index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT) { ret = Actor::GetDefaultProperty(index); } @@ -621,26 +709,12 @@ Property::Value CameraActor::GetDefaultProperty( Property::Index index ) const { case Dali::CameraActor::Property::TYPE: { - if( Dali::Camera::LOOK_AT_TARGET == mType ) - { - ret = "LOOK_AT_TARGET"; - } - else if( Dali::Camera::FREE_LOOK == mType ) - { - ret = "FREE_LOOK"; - } + ret = mType; break; } case Dali::CameraActor::Property::PROJECTION_MODE: { - if( Dali::Camera::PERSPECTIVE_PROJECTION == mProjectionMode ) - { - ret = "PERSPECTIVE_PROJECTION"; - } - else if( Dali::Camera::ORTHOGRAPHIC_PROJECTION == mProjectionMode ) - { - ret = "ORTHOGRAPHIC_PROJECTION"; - } + ret = mProjectionMode; break; } case Dali::CameraActor::Property::FIELD_OF_VIEW: @@ -648,6 +722,11 @@ Property::Value CameraActor::GetDefaultProperty( Property::Index index ) const ret = mFieldOfView; break; } + case Dali::DevelCameraActor::Property::ORTHOGRAPHIC_SIZE: + { + ret = mOrthographicSize; + break; + } case Dali::CameraActor::Property::ASPECT_RATIO: { ret = mAspectRatio; @@ -665,22 +744,22 @@ Property::Value CameraActor::GetDefaultProperty( Property::Index index ) const } case Dali::CameraActor::Property::LEFT_PLANE_DISTANCE: { - ret = mLeftClippingPlane; + ret = OrthographicSizeConverter(mOrthographicSize, mAspectRatio, mProjectionDirection).LeftPlaneDistance(); break; } case Dali::CameraActor::Property::RIGHT_PLANE_DISTANCE: { - ret = mRightClippingPlane; + ret = OrthographicSizeConverter(mOrthographicSize, mAspectRatio, mProjectionDirection).RightPlaneDistance(); break; } case Dali::CameraActor::Property::TOP_PLANE_DISTANCE: { - ret = mTopClippingPlane; + ret = OrthographicSizeConverter(mOrthographicSize, mAspectRatio, mProjectionDirection).TopPlaneDistance(); break; } case Dali::CameraActor::Property::BOTTOM_PLANE_DISTANCE: { - ret = mBottomClippingPlane; + ret = OrthographicSizeConverter(mOrthographicSize, mAspectRatio, mProjectionDirection).BottomPlaneDistance(); break; } case Dali::CameraActor::Property::TARGET_POSITION: @@ -703,53 +782,217 @@ Property::Value CameraActor::GetDefaultProperty( Property::Index index ) const ret = mInvertYAxis; break; } + case Dali::DevelCameraActor::Property::PROJECTION_DIRECTION: + { + ret = mProjectionDirection; + break; + } } // switch(index) } return ret; } -Property::Value CameraActor::GetDefaultPropertyCurrentValue( Property::Index index ) const +Property::Value CameraActor::GetDefaultPropertyCurrentValue(Property::Index index) const { Property::Value ret; - if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT ) + if(index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT) { ret = Actor::GetDefaultPropertyCurrentValue(index); } else { - ret = GetDefaultProperty( index ); // Most are event-side properties, the scene-graph properties are only on the scene-graph + switch(index) + { + case Dali::CameraActor::Property::FIELD_OF_VIEW: + { + ret = GetCurrentFieldOfView(); + break; + } + case Dali::DevelCameraActor::Property::ORTHOGRAPHIC_SIZE: + { + ret = GetCurrentOrthographicSize(); + break; + } + case Dali::CameraActor::Property::ASPECT_RATIO: + { + ret = GetCurrentAspectRatio(); + break; + } + case Dali::CameraActor::Property::LEFT_PLANE_DISTANCE: + { + ret = OrthographicSizeConverter(GetCurrentOrthographicSize(), GetCurrentAspectRatio(), mProjectionDirection).LeftPlaneDistance(); + break; + } + case Dali::CameraActor::Property::RIGHT_PLANE_DISTANCE: + { + ret = OrthographicSizeConverter(GetCurrentOrthographicSize(), GetCurrentAspectRatio(), mProjectionDirection).RightPlaneDistance(); + break; + } + case Dali::CameraActor::Property::TOP_PLANE_DISTANCE: + { + ret = OrthographicSizeConverter(GetCurrentOrthographicSize(), GetCurrentAspectRatio(), mProjectionDirection).TopPlaneDistance(); + break; + } + case Dali::CameraActor::Property::BOTTOM_PLANE_DISTANCE: + { + ret = OrthographicSizeConverter(GetCurrentOrthographicSize(), GetCurrentAspectRatio(), mProjectionDirection).BottomPlaneDistance(); + break; + } + default: + { + ret = GetDefaultProperty(index); // Most are event-side properties, the scene-graph properties are only on the scene-graph + } + } // switch(index) } return ret; } -const PropertyInputImpl* CameraActor::GetSceneObjectInputProperty( Property::Index index ) const +void CameraActor::OnNotifyDefaultPropertyAnimation(Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType) +{ + if(index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT) + { + Actor::OnNotifyDefaultPropertyAnimation(animation, index, value, animationType); + } + else + { + switch(animationType) + { + case Animation::TO: + case Animation::BETWEEN: + { + switch(index) + { + case Dali::CameraActor::Property::FIELD_OF_VIEW: + { + value.Get(mFieldOfView); + break; + } + case Dali::DevelCameraActor::Property::ORTHOGRAPHIC_SIZE: + { + value.Get(mOrthographicSize); + break; + } + case Dali::CameraActor::Property::ASPECT_RATIO: + { + value.Get(mAspectRatio); + break; + } + } + break; + } + case Animation::BY: + { + switch(index) + { + case Dali::CameraActor::Property::FIELD_OF_VIEW: + { + AdjustValue(mFieldOfView, value); + break; + } + case Dali::DevelCameraActor::Property::ORTHOGRAPHIC_SIZE: + { + AdjustValue(mOrthographicSize, value); + break; + } + case Dali::CameraActor::Property::ASPECT_RATIO: + { + AdjustValue(mAspectRatio, value); + break; + } + } + break; + } + } + } +} + +const SceneGraph::PropertyBase* CameraActor::GetSceneObjectAnimatableProperty(Property::Index index) const +{ + const SceneGraph::PropertyBase* property(nullptr); + switch(index) + { + case Dali::CameraActor::Property::FIELD_OF_VIEW: + { + property = GetCameraSceneObject().GetFieldOfView(); + break; + } + case Dali::DevelCameraActor::Property::ORTHOGRAPHIC_SIZE: + { + property = GetCameraSceneObject().GetOrthographicSize(); + break; + } + case Dali::CameraActor::Property::ASPECT_RATIO: + { + property = GetCameraSceneObject().GetAspectRatio(); + break; + } + // no default on purpose as we chain method up to actor + } + if(!property) + { + // not our property, ask base + property = Actor::GetSceneObjectAnimatableProperty(index); + } + + return property; +} + +const PropertyInputImpl* CameraActor::GetSceneObjectInputProperty(Property::Index index) const { - const PropertyInputImpl* property( NULL ); + const PropertyInputImpl* property(nullptr); - switch( index ) + switch(index) { + case Dali::CameraActor::Property::FIELD_OF_VIEW: + { + property = GetCameraSceneObject().GetFieldOfView(); + break; + } + case Dali::DevelCameraActor::Property::ORTHOGRAPHIC_SIZE: + { + property = GetCameraSceneObject().GetOrthographicSize(); + break; + } + case Dali::CameraActor::Property::ASPECT_RATIO: + { + property = GetCameraSceneObject().GetAspectRatio(); + break; + } case Dali::CameraActor::Property::PROJECTION_MATRIX: { - property = mSceneObject->GetProjectionMatrix(); + property = GetCameraSceneObject().GetProjectionMatrix(); break; } case Dali::CameraActor::Property::VIEW_MATRIX: { - property = mSceneObject->GetViewMatrix(); + property = GetCameraSceneObject().GetViewMatrix(); break; } - // no default on purpose as we chain method up to actor + // no default on purpose as we chain method up to actor } - if( !property ) + if(!property) { - property = Actor::GetSceneObjectInputProperty( index ); + property = Actor::GetSceneObjectInputProperty(index); } return property; } +void CameraActor::OnPropertySet(Property::Index index, const Property::Value& propertyValue) +{ + // If Position or Orientation are explicitly set, make mPropertyChanged flag true. + if(index == Dali::Actor::Property::POSITION || + index == Dali::Actor::Property::POSITION_X || + index == Dali::Actor::Property::POSITION_Y || + index == Dali::Actor::Property::POSITION_Z || + index == Dali::Actor::Property::ORIENTATION) + { + mPropertyChanged = true; + } +} + } // namespace Internal } // namespace Dali