Previously, SceneGraph::Camera was not a SceneGraph::Node.
If we try to animate property of Camera, then
we use some PropertyBase s.t. PropertyOwner(==Node) doesn't owned.
To fix this logical unmatched issue, we make SceneGraph::Camera
as sub-class of SceneGraph::Node.
Moreover, We make Camera's FieldOfView Animatable.
After this patch merged, we try to refactor Camera's properties
and make them animatable.
Change-Id: I184f75b51a2152aea52879adc1e783cea7d190a0
Signed-off-by: Eunki, Hong <eunkiki.hong@samsung.com>
for(std::vector<Property::Index>::iterator iter = indices.begin(); iter != indices.end(); ++iter)
{
DALI_TEST_EQUALS(*iter, actor.GetPropertyIndex(actor.GetPropertyName(*iter)), TEST_LOCATION);
- DALI_TEST_CHECK(!actor.IsPropertyAnimatable(*iter));
+
+ if(*iter == CameraActor::Property::FIELD_OF_VIEW)
+ {
+ DALI_TEST_CHECK(actor.IsPropertyAnimatable(*iter));
+ }
+ else
+ {
+ DALI_TEST_CHECK(!actor.IsPropertyAnimatable(*iter));
+ }
if((*iter == CameraActor::Property::PROJECTION_MATRIX) ||
(*iter == CameraActor::Property::VIEW_MATRIX))
// camera own
{"type", Property::INTEGER, true, false, true, Dali::CameraActor::Property::TYPE},
{"projectionMode", Property::INTEGER, true, false, true, Dali::CameraActor::Property::PROJECTION_MODE},
- {"fieldOfView", Property::FLOAT, true, false, true, Dali::CameraActor::Property::FIELD_OF_VIEW},
+ {"fieldOfView", Property::FLOAT, true, true, true, Dali::CameraActor::Property::FIELD_OF_VIEW},
{"aspectRatio", Property::FLOAT, true, false, true, Dali::CameraActor::Property::ASPECT_RATIO},
{"nearPlaneDistance", Property::FLOAT, true, false, true, Dali::CameraActor::Property::NEAR_PLANE_DISTANCE},
{"farPlaneDistance", Property::FLOAT, true, false, true, Dali::CameraActor::Property::FAR_PLANE_DISTANCE},
END_TEST;
}
-int UtcDaliCameraActorAnimatedProperties(void)
+int UtcDaliCameraActorAnimatedProperties01(void)
{
TestApplication application;
tet_infoline("Testing Dali::Internal::CameraActor::GetSceneObjectAnimatableProperty()");
END_TEST;
}
+int UtcDaliCameraActorAnimatedProperties02(void)
+{
+ TestApplication application;
+ tet_infoline("Testing Dali::Internal::CameraActor::GetSceneObjectAnimatableProperty()");
+
+ CameraActor camera = application.GetScene().GetRenderTaskList().GetTask(0u).GetCameraActor();
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::POSITION, Vector2(0.1f, 0.0f));
+ application.GetScene().Add(actor);
+
+ camera.SetFieldOfView(0.1f);
+
+ Constraint constraint = Constraint::New<float>(actor, Actor::Property::POSITION_X, EqualToConstraint());
+ constraint.AddSource(Source(camera, CameraActor::Property::FIELD_OF_VIEW));
+ constraint.Apply();
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS(actor.GetCurrentProperty<float>(Actor::Property::POSITION_X), 0.1f, TEST_LOCATION);
+
+ camera.SetFieldOfView(0.5f);
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS(actor.GetCurrentProperty<float>(Actor::Property::POSITION_X), 0.5f, TEST_LOCATION);
+ END_TEST;
+}
+
+int UtcDaliCameraActorAnimatedProperties03(void)
+{
+ TestApplication application;
+ tet_infoline("Testing Dali::Internal::CameraActor::GetSceneObjectAnimatableProperty()");
+
+ CameraActor camera = application.GetScene().GetRenderTaskList().GetTask(0u).GetCameraActor();
+
+ // Add dummy actor
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::POSITION, Vector2(0.1f, 0.0f));
+ application.GetScene().Add(actor);
+
+ Radian sourceFoV = Radian(0.6f);
+ Radian targetFoV = Radian(0.1f);
+
+ Matrix expectedProjectionMatrix1;
+ Matrix expectedProjectionMatrix2;
+ Matrix expectedProjectionMatrix3;
+
+ // Reduce near-far value for projection matrix epsilon
+ camera.SetNearClippingPlane(1.0f);
+ camera.SetFarClippingPlane(3.0f);
+
+ // Build expect projection matrix
+ camera.SetFieldOfView(sourceFoV.radian);
+ application.SendNotification();
+ application.Render();
+ camera.GetProperty(CameraActor::Property::PROJECTION_MATRIX).Get(expectedProjectionMatrix1);
+
+ camera.SetFieldOfView(sourceFoV.radian * 0.6f + targetFoV.radian * 0.4f);
+ application.SendNotification();
+ application.Render();
+ camera.GetProperty(CameraActor::Property::PROJECTION_MATRIX).Get(expectedProjectionMatrix2);
+
+ camera.SetFieldOfView(targetFoV.radian);
+ application.SendNotification();
+ application.Render();
+ camera.GetProperty(CameraActor::Property::PROJECTION_MATRIX).Get(expectedProjectionMatrix3);
+
+ auto TestAnimationProgress = [&]() {
+ Matrix projectionMatrix;
+
+ application.SendNotification();
+ application.Render(0);
+
+ // progress 0.0
+ DALI_TEST_EQUALS(camera.GetCurrentProperty<float>(CameraActor::Property::FIELD_OF_VIEW), sourceFoV.radian, TEST_LOCATION);
+
+ camera.GetProperty(CameraActor::Property::PROJECTION_MATRIX).Get(projectionMatrix);
+ DALI_TEST_EQUALS(projectionMatrix, expectedProjectionMatrix1, Epsilon<100000>::value, TEST_LOCATION);
+
+ application.SendNotification();
+ application.Render(400);
+
+ // progress 0.4
+ DALI_TEST_EQUALS(camera.GetCurrentProperty<float>(CameraActor::Property::FIELD_OF_VIEW), sourceFoV.radian * 0.6f + targetFoV.radian * 0.4f, TEST_LOCATION);
+
+ camera.GetProperty(CameraActor::Property::PROJECTION_MATRIX).Get(projectionMatrix);
+ DALI_TEST_EQUALS(projectionMatrix, expectedProjectionMatrix2, Epsilon<100000>::value, TEST_LOCATION);
+
+ application.SendNotification();
+ application.Render(600);
+
+ // progress 1.0
+ DALI_TEST_EQUALS(camera.GetCurrentProperty<float>(CameraActor::Property::FIELD_OF_VIEW), targetFoV.radian, TEST_LOCATION);
+
+ camera.GetProperty(CameraActor::Property::PROJECTION_MATRIX).Get(projectionMatrix);
+ DALI_TEST_EQUALS(projectionMatrix, expectedProjectionMatrix3, Epsilon<100000>::value, TEST_LOCATION);
+
+ // Ensure Animate finished.
+ application.SendNotification();
+ application.Render(16);
+ };
+
+ // AnimateTo
+ {
+ tet_printf("AnimateTo\n");
+ camera.SetProperty(CameraActor::Property::FIELD_OF_VIEW, sourceFoV.radian);
+ Animation animation = Animation::New(1.0f);
+ animation.AnimateTo(Property(camera, CameraActor::Property::FIELD_OF_VIEW), targetFoV.radian);
+ animation.AnimateTo(Property(camera, Actor::Property::POSITION_X), 0.0f); ///< For line coverage.
+ animation.Play();
+
+ TestAnimationProgress();
+ }
+
+ // AnimateBetween
+ {
+ tet_printf("AnimateBetween\n");
+ Animation animation = Animation::New(1.0f);
+ KeyFrames keyFrames = KeyFrames::New();
+ keyFrames.Add(0.0f, sourceFoV.radian);
+ keyFrames.Add(1.0f, targetFoV.radian);
+ animation.AnimateBetween(Property(camera, CameraActor::Property::FIELD_OF_VIEW), keyFrames);
+ animation.Play();
+
+ TestAnimationProgress();
+ }
+
+ // AnimateBy
+ {
+ tet_printf("AnimateBy\n");
+ camera.SetProperty(CameraActor::Property::FIELD_OF_VIEW, sourceFoV.radian);
+ Animation animation = Animation::New(1.0f);
+ animation.AnimateBy(Property(camera, CameraActor::Property::FIELD_OF_VIEW), targetFoV.radian - sourceFoV.radian);
+ animation.Play();
+
+ TestAnimationProgress();
+ }
+
+ END_TEST;
+}
+
int UtcDaliCameraActorPropertyIndices(void)
{
TestApplication application;
#include <dali/internal/event/common/thread-local-storage.h>
#include <dali/public-api/object/type-registry.h>
+#include <dali/internal/update/common/property-base.h>
#include <dali/internal/update/manager/update-manager.h>
namespace Dali
DALI_PROPERTY_TABLE_BEGIN
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, false, true, Dali::CameraActor::Property::FIELD_OF_VIEW )
+DALI_PROPERTY( "fieldOfView", FLOAT, true, true, 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 )
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<SceneGraph::Node> 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();
CameraActor::CameraActor(const SceneGraph::Node& node)
: Actor(Actor::BASIC, node),
- mSceneObject(nullptr),
mTarget(SceneGraph::Camera::DEFAULT_TARGET_POSITION),
mType(SceneGraph::Camera::DEFAULT_TYPE),
mProjectionMode(SceneGraph::Camera::DEFAULT_MODE),
CameraActor::~CameraActor()
{
- if(EventThreadServices::IsCoreRunning())
- {
- // Create scene-object and transfer ownership through message
- RemoveCameraMessage(GetEventThreadServices().GetUpdateManager(), mSceneObject);
- }
-}
-
-void CameraActor::OnInitialize()
-{
- // 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);
}
void CameraActor::OnSceneConnectionInternal()
void CameraActor::SetReflectByPlane(const Vector4& plane)
{
- if(mSceneObject)
- {
- SetReflectByPlaneMessage(GetEventThreadServices(), *mSceneObject, plane);
- }
+ SetReflectByPlaneMessage(GetEventThreadServices(), GetCameraSceneObject(), plane);
}
void CameraActor::SetTarget(const Vector3& target)
{
mTarget = target;
- SetTargetPositionMessage(GetEventThreadServices(), *mSceneObject, mTarget);
+ SetTargetPositionMessage(GetEventThreadServices(), GetCameraSceneObject(), mTarget);
}
}
mType = type;
// sceneObject is being used in a separate thread; queue a message to set
- SetTypeMessage(GetEventThreadServices(), *mSceneObject, mType);
+ SetTypeMessage(GetEventThreadServices(), GetCameraSceneObject(), mType);
}
}
mProjectionMode = mode;
// sceneObject is being used in a separate thread; queue a message to set
- SetProjectionModeMessage(GetEventThreadServices(), *mSceneObject, mProjectionMode);
+ SetProjectionModeMessage(GetEventThreadServices(), GetCameraSceneObject(), mProjectionMode);
}
}
mProjectionDirection = direction;
// sceneObject is being used in a separate thread; queue a message to set
- SetProjectionDirectionMessage(GetEventThreadServices(), *mSceneObject, mProjectionDirection);
+ SetProjectionDirectionMessage(GetEventThreadServices(), GetCameraSceneObject(), mProjectionDirection);
}
}
mFieldOfView = fieldOfView;
// sceneObject is being used in a separate thread; queue a message to set
- SetFieldOfViewMessage(GetEventThreadServices(), *mSceneObject, mFieldOfView);
+ BakeFieldOfViewMessage(GetEventThreadServices(), GetCameraSceneObject(), mFieldOfView);
}
}
return mFieldOfView;
}
+float CameraActor::GetCurrentFieldOfView() const
+{
+ // node is being used in a separate thread; copy the value from the previous update
+ return GetCameraSceneObject().GetFieldOfView(GetEventThreadServices().GetEventBufferIndex());
+}
+
void CameraActor::SetAspectRatio(float aspectRatio)
{
mPropertyChanged = true;
mAspectRatio = aspectRatio;
// sceneObject is being used in a separate thread; queue a message to set
- SetAspectRatioMessage(GetEventThreadServices(), *mSceneObject, mAspectRatio);
+ SetAspectRatioMessage(GetEventThreadServices(), GetCameraSceneObject(), mAspectRatio);
}
}
mNearClippingPlane = nearClippingPlane;
// sceneObject is being used in a separate thread; queue a message to set
- SetNearClippingPlaneMessage(GetEventThreadServices(), *mSceneObject, mNearClippingPlane);
+ SetNearClippingPlaneMessage(GetEventThreadServices(), GetCameraSceneObject(), mNearClippingPlane);
}
}
mFarClippingPlane = farClippingPlane;
// sceneObject is being used in a separate thread; queue a message to set
- SetFarClippingPlaneMessage(GetEventThreadServices(), *mSceneObject, mFarClippingPlane);
+ SetFarClippingPlaneMessage(GetEventThreadServices(), GetCameraSceneObject(), mFarClippingPlane);
}
}
mLeftClippingPlane = leftClippingPlane;
// sceneObject is being used in a separate thread; queue a message to set
- SetLeftClippingPlaneMessage(GetEventThreadServices(), *mSceneObject, mLeftClippingPlane);
+ SetLeftClippingPlaneMessage(GetEventThreadServices(), GetCameraSceneObject(), mLeftClippingPlane);
}
}
mRightClippingPlane = rightClippingPlane;
// sceneObject is being used in a separate thread; queue a message to set
- SetRightClippingPlaneMessage(GetEventThreadServices(), *mSceneObject, mRightClippingPlane);
+ SetRightClippingPlaneMessage(GetEventThreadServices(), GetCameraSceneObject(), mRightClippingPlane);
}
}
mTopClippingPlane = topClippingPlane;
// sceneObject is being used in a separate thread; queue a message to set
- SetTopClippingPlaneMessage(GetEventThreadServices(), *mSceneObject, mTopClippingPlane);
+ SetTopClippingPlaneMessage(GetEventThreadServices(), GetCameraSceneObject(), mTopClippingPlane);
}
}
mBottomClippingPlane = bottomClippingPlane;
// sceneObject is being used in a separate thread; queue a message to set
- SetBottomClippingPlaneMessage(GetEventThreadServices(), *mSceneObject, mBottomClippingPlane);
+ SetBottomClippingPlaneMessage(GetEventThreadServices(), GetCameraSceneObject(), mBottomClippingPlane);
}
}
mInvertYAxis = invertYAxis;
// sceneObject is being used in a separate thread; queue a message to set
- SetInvertYAxisMessage(GetEventThreadServices(), *mSceneObject, mInvertYAxis);
+ SetInvertYAxisMessage(GetEventThreadServices(), GetCameraSceneObject(), mInvertYAxis);
}
}
static_cast<float>(viewport.height) - (screenCoordinates.y - static_cast<float>(viewport.y)),
0.f,
1.f);
- const Matrix& inverseViewProjection = mSceneObject->GetInverseViewProjectionMatrix(GetEventThreadServices().GetEventBufferIndex());
+ const Matrix& inverseViewProjection = GetCameraSceneObject().GetInverseViewProjectionMatrix(GetEventThreadServices().GetEventBufferIndex());
success = Unproject(near, inverseViewProjection, static_cast<float>(viewport.width), static_cast<float>(viewport.height), near);
// Compute the ray's director vector.
{
if(OnScene())
{
- return mSceneObject->GetViewMatrix(GetEventThreadServices().GetEventBufferIndex());
+ return GetCameraSceneObject().GetViewMatrix(GetEventThreadServices().GetEventBufferIndex());
}
else
{
{
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<const SceneGraph::Camera&>(GetNode());
}
void CameraActor::RotateProjection(int rotationAngle)
{
// sceneObject is being used in a separate thread; queue a message to set
- RotateProjectionMessage(GetEventThreadServices(), *mSceneObject, rotationAngle);
+ RotateProjectionMessage(GetEventThreadServices(), GetCameraSceneObject(), rotationAngle);
}
void CameraActor::SetDefaultProperty(Property::Index index, const Property::Value& propertyValue)
}
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;
+ }
+ default:
+ {
+ ret = GetDefaultProperty(index); // Most are event-side properties, the scene-graph properties are only on the scene-graph
+ }
+ } // switch(index)
}
return ret;
}
+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;
+ }
+ }
+ break;
+ }
+ case Animation::BY:
+ {
+ switch(index)
+ {
+ case Dali::CameraActor::Property::FIELD_OF_VIEW:
+ {
+ AdjustValue<float>(mFieldOfView, 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;
+ }
+ // 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(nullptr);
switch(index)
{
+ case Dali::CameraActor::Property::FIELD_OF_VIEW:
+ {
+ property = GetCameraSceneObject().GetFieldOfView();
+ 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
float GetFieldOfView() const;
/**
+ * @brief Retrieve the CameraActor's field of view from update side.
+ * This field of view will be the fov set or animating but will be a frame behind.
+ * @return The field of view.
+ */
+ float GetCurrentFieldOfView() const;
+
+ /**
* @copydoc Dali::CameraActor::SetAspectRatio
*/
void SetAspectRatio(float aspectRatio);
const Matrix& GetProjectionMatrix() const;
/**
- * Return the scene graph camera (for RenderTask)
+ * Return the scene graph camera
* @return The scene graph camera.
*/
- const SceneGraph::Camera* GetCamera() const;
+ const SceneGraph::Camera& GetCameraSceneObject() const;
/**
* Rotate the projection.
Property::Value GetDefaultPropertyCurrentValue(Property::Index index) const override;
/**
+ * @copydoc Dali::Internal::Object::OnNotifyDefaultPropertyAnimation()
+ */
+ void OnNotifyDefaultPropertyAnimation(Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType) override;
+
+ /**
+ * @copydoc Dali::Internal::Object::GetSceneObjectAnimatableProperty()
+ */
+ const SceneGraph::PropertyBase* GetSceneObjectAnimatableProperty(Property::Index index) const override;
+
+ /**
* @copydoc Dali::Internal::Object::GetSceneObjectInputProperty()
*/
const PropertyInputImpl* GetSceneObjectInputProperty(Property::Index index) const override;
~CameraActor() override;
/**
- * @copydoc Dali::Internal::Actor::OnInitialize()
- */
- void OnInitialize() override;
-
- /**
* @copydoc Dali::Internal::Actor::OnSceneConnectionInternal()
*/
void OnSceneConnectionInternal() override;
*/
void OnPropertySet(Property::Index index, const Property::Value& propertyValue) override;
-private: // Data
- const SceneGraph::Camera* mSceneObject; ///< Not owned
-
+private: // Data
Vector3 mTarget;
Vector2 mCanvasSize;
Dali::Camera::Type mType;
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
mCameraActor.SetActor(cameraActor);
if(cameraActor)
{
- SetCameraMessage(GetEventThreadServices(), GetRenderTaskSceneObject(), &cameraActor->GetNode(), cameraActor->GetCamera());
+ SetCameraMessage(GetEventThreadServices(), GetRenderTaskSceneObject(), &cameraActor->GetNode(), &cameraActor->GetCameraSceneObject());
}
else
{
}
const Camera* camera = instruction.GetCamera();
- if(camera->mType == Camera::DEFAULT_TYPE && camera->mTargetPosition == Camera::DEFAULT_TARGET_POSITION)
+ if(camera && camera->mType == Camera::DEFAULT_TYPE && camera->mTargetPosition == Camera::DEFAULT_TARGET_POSITION)
{
- const Node* node = instruction.GetCamera()->GetNode();
- if(node)
+ Vector3 position;
+ Vector3 scale;
+ Quaternion orientation;
+ camera->GetWorldMatrix(mImpl->renderBufferIndex).GetTransformComponents(position, orientation, scale);
+
+ Vector3 orientationAxis;
+ Radian orientationAngle;
+ orientation.ToAxisAngle(orientationAxis, orientationAngle);
+
+ if(position.x > Math::MACHINE_EPSILON_10000 ||
+ position.y > Math::MACHINE_EPSILON_10000 ||
+ orientationAxis != Vector3(0.0f, 1.0f, 0.0f) ||
+ orientationAngle != ANGLE_180 ||
+ scale != Vector3(1.0f, 1.0f, 1.0f))
{
- Vector3 position;
- Vector3 scale;
- Quaternion orientation;
- node->GetWorldMatrix(mImpl->renderBufferIndex).GetTransformComponents(position, orientation, scale);
-
- Vector3 orientationAxis;
- Radian orientationAngle;
- orientation.ToAxisAngle(orientationAxis, orientationAngle);
-
- if(position.x > Math::MACHINE_EPSILON_10000 ||
- position.y > Math::MACHINE_EPSILON_10000 ||
- orientationAxis != Vector3(0.0f, 1.0f, 0.0f) ||
- orientationAngle != ANGLE_180 ||
- scale != Vector3(1.0f, 1.0f, 1.0f))
- {
- return;
- }
+ return;
}
}
else
#include <dali/internal/render/shaders/render-shader.h>
#include <dali/internal/update/common/scene-graph-scene.h>
#include <dali/internal/update/nodes/node.h>
-#include <dali/internal/update/render-tasks/scene-graph-camera.h>
namespace Dali
{
mNodeQueue(),
mShaderQueue(),
mRendererQueue(),
- mCameraQueue(),
mSceneQueue()
{
}
mRendererQueue[updateBufferIndex].PushBack(renderer);
}
-void DiscardQueue::Add(BufferIndex updateBufferIndex, Camera* camera)
-{
- DALI_ASSERT_DEBUG(NULL != camera);
-
- mCameraQueue[updateBufferIndex].PushBack(camera);
-}
-
void DiscardQueue::Add(BufferIndex updateBufferIndex, Scene* scene)
{
DALI_ASSERT_DEBUG(NULL != scene);
mNodeQueue[updateBufferIndex].Clear();
mRendererQueue[updateBufferIndex].Clear();
mShaderQueue[updateBufferIndex].Clear();
- mCameraQueue[updateBufferIndex].Clear();
mSceneQueue[updateBufferIndex].Clear();
}
#define DALI_INTERNAL_DISCARD_QUEUE_H
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
public:
using ShaderQueue = OwnerContainer<Shader*>;
using RendererQueue = OwnerContainer<Renderer*>;
- using CameraQueue = OwnerContainer<Camera*>;
using SceneQueue = OwnerContainer<Scene*>;
/**
void Add(BufferIndex updateBufferIndex, Renderer* renderer);
/**
- * Adds an unwanted Camera to the discard queue.
- * This is done because Render thread may use Matrices from the camera
- * @param[in] updateBufferIndex The current update buffer index.
- * @param[in] camera The discarded renderer; DiscardQueue takes ownership.
- */
- void Add(BufferIndex updateBufferIndex, Camera* camera);
-
- /**
* Adds an unwanted Scene to the discard queue.
* A message will be sent to clean up GL resources in the next Render.
* @param[in] updateBufferIndex The current update buffer index.
OwnerContainer<Node*> mNodeQueue[2];
ShaderQueue mShaderQueue[2];
RendererQueue mRendererQueue[2];
- CameraQueue mCameraQueue[2];
SceneQueue mSceneQueue[2];
};
* @param viewport The viewport
* @param cull Whether frustum culling is enabled or not
*/
-inline void AddRendererToRenderList(BufferIndex updateBufferIndex,
- RenderList& renderList,
- Renderable& renderable,
- const Matrix& viewMatrix,
- SceneGraph::Camera& camera,
- bool isLayer3d,
- bool viewportSet,
- const Viewport& viewport,
- bool cull)
+inline void AddRendererToRenderList(BufferIndex updateBufferIndex,
+ RenderList& renderList,
+ Renderable& renderable,
+ const Matrix& viewMatrix,
+ const SceneGraph::Camera& camera,
+ bool isLayer3d,
+ bool viewportSet,
+ const Viewport& viewport,
+ bool cull)
{
bool inside(true);
Node* node = renderable.mNode;
* @param isLayer3d Whether we are processing a 3D layer or not
* @param cull Whether frustum culling is enabled or not
*/
-inline void AddRenderersToRenderList(BufferIndex updateBufferIndex,
- RenderList& renderList,
- RenderableContainer& renderers,
- const Matrix& viewMatrix,
- SceneGraph::Camera& camera,
- bool isLayer3d,
- bool viewportSet,
- const Viewport& viewport,
- bool cull)
+inline void AddRenderersToRenderList(BufferIndex updateBufferIndex,
+ RenderList& renderList,
+ RenderableContainer& renderers,
+ const Matrix& viewMatrix,
+ const SceneGraph::Camera& camera,
+ bool isLayer3d,
+ bool viewportSet,
+ const Viewport& viewport,
+ bool cull)
{
DALI_LOG_INFO(gRenderListLogFilter, Debug::Verbose, "AddRenderersToRenderList()\n");
bool isRenderListAdded = false;
bool isRootLayerDirty = false;
- const Matrix& viewMatrix = renderTask.GetViewMatrix(updateBufferIndex);
- SceneGraph::Camera& camera = renderTask.GetCamera();
+ const Matrix& viewMatrix = renderTask.GetViewMatrix(updateBufferIndex);
+ const SceneGraph::Camera& camera = renderTask.GetCamera();
Viewport viewport;
bool viewportSet = renderTask.QueryViewport(updateBufferIndex, viewport);
for(SortedLayersIter iter = sortedLayers.begin(); iter != endIter; ++iter)
{
Layer& layer = **iter;
- const bool tryReuseRenderList(viewMatrixHasNotChanged && layer.CanReuseRenderers(&renderTask.GetCamera()));
+ const bool tryReuseRenderList(viewMatrixHasNotChanged && layer.CanReuseRenderers(&camera));
const bool isLayer3D = layer.GetBehavior() == Dali::Layer::LAYER_3D;
RenderList* renderList = nullptr;
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
// Retrieve size of Scene and default camera position to update viewport of each RenderTask if the RenderTask uses ViewportGuideNode.
RenderTaskList::RenderTaskContainer::Iterator iter = taskContainer.Begin();
RenderTask& defaultRenderTask = **iter;
- auto defaultCamera = defaultRenderTask.GetCamera().GetNode();
+ const Camera& defaultCamera = defaultRenderTask.GetCamera();
auto defaultRootNode = defaultRenderTask.GetSourceNode();
Vector3 defaultCameraPosition = Vector3::ZERO;
Vector2 sceneSize = Vector2::ZERO;
- if(defaultCamera && defaultRootNode)
+ if(defaultRootNode)
{
- defaultCameraPosition = defaultCamera->GetWorldPosition(updateBufferIndex);
+ defaultCameraPosition = defaultCamera.GetWorldPosition(updateBufferIndex);
sceneSize = Vector2(defaultRootNode->GetSize(updateBufferIndex) * defaultRootNode->GetWorldScale(updateBufferIndex));
}
Vector<Node*> nodes; ///< A container of all instantiated nodes
- OwnerContainer<Camera*> cameras; ///< A container of cameras
+ Vector<Camera*> cameras; ///< A container of cameras. Note : these cameras are owned by Impl::nodes.
+
OwnerContainer<PropertyOwner*> customObjects; ///< A container of owned objects (with custom properties)
OwnerContainer<PropertyResetterBase*> propertyResetters; ///< A container of property resetters
Node* rawNode = node.Release();
DALI_LOG_INFO(gLogFilter, Debug::General, "[%x] AddNode\n", rawNode);
+ // Add camera nodes occured rarely.
+ if(DALI_UNLIKELY(rawNode->IsCamera()))
+ {
+ AddCamera(static_cast<Camera*>(rawNode));
+ }
+
mImpl->nodes.PushBack(rawNode);
rawNode->CreateTransform(&mImpl->transformManager);
}
}
}
+ // Remove camera nodes occured rarely.
+ if(DALI_UNLIKELY(node->IsCamera()))
+ {
+ RemoveCamera(static_cast<Camera*>(node));
+ }
+
mImpl->discardQueue.Add(mSceneGraphBuffers.GetUpdateBufferIndex(), node);
// Notify the Node about impending destruction
node->OnDestroy();
}
-void UpdateManager::AddCamera(OwnerPointer<Camera>& camera)
+void UpdateManager::AddCamera(Camera* camera)
{
- mImpl->cameras.PushBack(camera.Release()); // takes ownership
+ DALI_LOG_INFO(gLogFilter, Debug::General, "[%x] AddCamera\n", camera);
+
+ mImpl->cameras.PushBack(camera);
}
void UpdateManager::RemoveCamera(Camera* camera)
{
- // Find the camera and destroy it
- EraseUsingDiscardQueue(mImpl->cameras, camera, mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex());
+ DALI_LOG_INFO(gLogFilter, Debug::General, "[%x] RemoveCamera\n", camera);
+
+ // Find the camera and remove it from list of cameras
+ Vector<Camera*>::Iterator iter = mImpl->cameras.Begin();
+ Vector<Camera*>::Iterator endIter = mImpl->cameras.End();
+ for(; iter != endIter; ++iter)
+ {
+ if((*iter) == camera)
+ {
+ mImpl->cameras.Erase(iter);
+ break;
+ }
+ }
}
void UpdateManager::AddObject(OwnerPointer<PropertyOwner>& object)
#define DALI_INTERNAL_SCENE_GRAPH_UPDATE_MANAGER_H
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
void DestroyNode(Node* node);
/**
- * Add a camera on scene
- * @param[in] camera The camera to add
- */
- void AddCamera(OwnerPointer<Camera>& camera);
-
- /**
- * Remove a camera from scene
- * @param[in] camera to remove
- */
- void RemoveCamera(Camera* camera);
-
- /**
* Add a newly created object.
* @param[in] object The object to add.
* @post The object is owned by UpdateManager.
* @param[in] size The new size of the buffer
* @post Sends a message to RenderManager to set the new data to the property buffer.
*/
- void SetVertexBufferData(Render::VertexBuffer* vertexBuffer, OwnerPointer<Vector<uint8_t> >& data, uint32_t size);
+ void SetVertexBufferData(Render::VertexBuffer* vertexBuffer, OwnerPointer<Vector<uint8_t>>& data, uint32_t size);
/**
* Adds a geometry to the RenderManager
UpdateManager& operator=(const UpdateManager& rhs);
/**
+ * Add a camera on scene
+ * @param[in] camera The camera to add
+ */
+ void AddCamera(Camera* camera);
+
+ /**
+ * Remove a camera from scene
+ * @param[in] camera to remove
+ */
+ void RemoveCamera(Camera* camera);
+
+ /**
* Helper to check whether the update-thread should keep going.
* @param[in] elapsedSeconds The time in seconds since the previous update.
* @return True if the update-thread should keep going.
inline void InstallRootMessage(UpdateManager& manager, OwnerPointer<Layer>& root)
{
// Message has ownership of Layer while in transit from event -> update
- using LocalType = MessageValue1<UpdateManager, OwnerPointer<Layer> >;
+ using LocalType = MessageValue1<UpdateManager, OwnerPointer<Layer>>;
// Reserve some memory inside the message queue
uint32_t* slot = manager.ReserveMessageSlot(sizeof(LocalType));
inline void AddNodeMessage(UpdateManager& manager, OwnerPointer<Node>& node)
{
// Message has ownership of Node while in transit from event -> update
- using LocalType = MessageValue1<UpdateManager, OwnerPointer<Node> >;
+ using LocalType = MessageValue1<UpdateManager, OwnerPointer<Node>>;
// Reserve some memory inside the message queue
uint32_t* slot = manager.ReserveMessageSlot(sizeof(LocalType));
new(slot) LocalType(&manager, &UpdateManager::DestroyNode, &node);
}
-inline void AddCameraMessage(UpdateManager& manager, OwnerPointer<Camera>& camera)
-{
- // Message has ownership of Camera while in transit from event -> update
- using LocalType = MessageValue1<UpdateManager, OwnerPointer<Camera> >;
-
- // Reserve some memory inside the message queue
- uint32_t* slot = manager.ReserveMessageSlot(sizeof(LocalType));
-
- // Construct message in the message queue memory; note that delete should not be called on the return value
- new(slot) LocalType(&manager, &UpdateManager::AddCamera, camera);
-}
-
-inline void RemoveCameraMessage(UpdateManager& manager, const Camera* camera)
-{
- using LocalType = MessageValue1<UpdateManager, Camera*>;
-
- // Reserve some memory inside the message queue
- uint32_t* slot = manager.ReserveMessageSlot(sizeof(LocalType));
-
- // Construct message in the message queue memory; note that delete should not be called on the return value
- new(slot) LocalType(&manager, &UpdateManager::RemoveCamera, const_cast<Camera*>(camera));
-}
-
inline void AddObjectMessage(UpdateManager& manager, OwnerPointer<PropertyOwner>& object)
{
// Message has ownership of object while in transit from event -> update
- using LocalType = MessageValue1<UpdateManager, OwnerPointer<PropertyOwner> >;
+ using LocalType = MessageValue1<UpdateManager, OwnerPointer<PropertyOwner>>;
// Reserve some memory inside the message queue
uint32_t* slot = manager.ReserveMessageSlot(sizeof(LocalType));
inline void AddAnimationMessage(UpdateManager& manager, OwnerPointer<SceneGraph::Animation>& animation)
{
- using LocalType = MessageValue1<UpdateManager, OwnerPointer<SceneGraph::Animation> >;
+ using LocalType = MessageValue1<UpdateManager, OwnerPointer<SceneGraph::Animation>>;
// Reserve some memory inside the message queue
uint32_t* slot = manager.ReserveMessageSlot(sizeof(LocalType));
inline void AddRenderTaskListMessage(UpdateManager& manager, OwnerPointer<SceneGraph::RenderTaskList>& taskList)
{
- using LocalType = MessageValue1<UpdateManager, OwnerPointer<SceneGraph::RenderTaskList> >;
+ using LocalType = MessageValue1<UpdateManager, OwnerPointer<SceneGraph::RenderTaskList>>;
// Reserve some memory inside the message queue
uint32_t* slot = manager.ReserveMessageSlot(sizeof(LocalType));
inline void AddSceneMessage(UpdateManager& manager, OwnerPointer<SceneGraph::Scene>& scene)
{
- using LocalType = MessageValue1<UpdateManager, OwnerPointer<SceneGraph::Scene> >;
+ using LocalType = MessageValue1<UpdateManager, OwnerPointer<SceneGraph::Scene>>;
// Reserve some memory inside the message queue
uint32_t* slot = manager.ReserveMessageSlot(sizeof(LocalType));
inline void AddPropertyNotificationMessage(UpdateManager& manager, OwnerPointer<PropertyNotification>& propertyNotification)
{
// Message has ownership of PropertyNotification while in transit from event -> update
- using LocalType = MessageValue1<UpdateManager, OwnerPointer<PropertyNotification> >;
+ using LocalType = MessageValue1<UpdateManager, OwnerPointer<PropertyNotification>>;
// Reserve some memory inside the message queue
uint32_t* slot = manager.ReserveMessageSlot(sizeof(LocalType));
// The render thread can safely change the Shader
inline void AddShaderMessage(UpdateManager& manager, OwnerPointer<Shader>& shader)
{
- using LocalType = MessageValue1<UpdateManager, OwnerPointer<Shader> >;
+ using LocalType = MessageValue1<UpdateManager, OwnerPointer<Shader>>;
// Reserve some memory inside the message queue
uint32_t* slot = manager.ReserveMessageSlot(sizeof(LocalType));
inline void AddRendererMessage(UpdateManager& manager, OwnerPointer<Renderer>& object)
{
- using LocalType = MessageValue1<UpdateManager, OwnerPointer<Renderer> >;
+ using LocalType = MessageValue1<UpdateManager, OwnerPointer<Renderer>>;
// Reserve some memory inside the message queue
uint32_t* slot = manager.ReserveMessageSlot(sizeof(LocalType));
// The render thread can safely change the Shader
inline void AddTextureSetMessage(UpdateManager& manager, OwnerPointer<TextureSet>& textureSet)
{
- using LocalType = MessageValue1<UpdateManager, OwnerPointer<TextureSet> >;
+ using LocalType = MessageValue1<UpdateManager, OwnerPointer<TextureSet>>;
// Reserve some memory inside the message queue
uint32_t* slot = manager.ReserveMessageSlot(sizeof(LocalType));
inline void AddSamplerMessage(UpdateManager& manager, OwnerPointer<Render::Sampler>& sampler)
{
// Message has ownership of Sampler while in transit from event -> update
- using LocalType = MessageValue1<UpdateManager, OwnerPointer<Render::Sampler> >;
+ using LocalType = MessageValue1<UpdateManager, OwnerPointer<Render::Sampler>>;
// Reserve some memory inside the message queue
uint32_t* slot = manager.ReserveMessageSlot(sizeof(LocalType));
inline void AddVertexBuffer(UpdateManager& manager, OwnerPointer<Render::VertexBuffer>& vertexBuffer)
{
// Message has ownership of vertexBuffer while in transit from event -> update
- using LocalType = MessageValue1<UpdateManager, OwnerPointer<Render::VertexBuffer> >;
+ using LocalType = MessageValue1<UpdateManager, OwnerPointer<Render::VertexBuffer>>;
// Reserve some memory inside the message queue
uint32_t* slot = manager.ReserveMessageSlot(sizeof(LocalType));
inline void SetVertexBufferFormat(UpdateManager& manager, Render::VertexBuffer& vertexBuffer, OwnerPointer<Render::VertexBuffer::Format>& format)
{
// Message has ownership of VertexBuffer::Format while in transit from event -> update
- using LocalType = MessageValue2<UpdateManager, Render::VertexBuffer*, OwnerPointer<Render::VertexBuffer::Format> >;
+ using LocalType = MessageValue2<UpdateManager, Render::VertexBuffer*, OwnerPointer<Render::VertexBuffer::Format>>;
// Reserve some memory inside the message queue
uint32_t* slot = manager.ReserveMessageSlot(sizeof(LocalType));
new(slot) LocalType(&manager, &UpdateManager::SetVertexBufferFormat, &vertexBuffer, format);
}
-inline void SetVertexBufferData(UpdateManager& manager, Render::VertexBuffer& vertexBuffer, OwnerPointer<Vector<uint8_t> >& data, uint32_t size)
+inline void SetVertexBufferData(UpdateManager& manager, Render::VertexBuffer& vertexBuffer, OwnerPointer<Vector<uint8_t>>& data, uint32_t size)
{
// Message has ownership of VertexBuffer data while in transit from event -> update
- using LocalType = MessageValue3<UpdateManager, Render::VertexBuffer*, OwnerPointer<Vector<uint8_t> >, uint32_t>;
+ using LocalType = MessageValue3<UpdateManager, Render::VertexBuffer*, OwnerPointer<Vector<uint8_t>>, uint32_t>;
// Reserve some memory inside the message queue
uint32_t* slot = manager.ReserveMessageSlot(sizeof(LocalType));
inline void AddGeometry(UpdateManager& manager, OwnerPointer<Render::Geometry>& geometry)
{
// Message has ownership of Geometry while in transit from event -> update
- using LocalType = MessageValue1<UpdateManager, OwnerPointer<Render::Geometry> >;
+ using LocalType = MessageValue1<UpdateManager, OwnerPointer<Render::Geometry>>;
// Reserve some memory inside the message queue
uint32_t* slot = manager.ReserveMessageSlot(sizeof(LocalType));
inline void AddTexture(UpdateManager& manager, OwnerPointer<Render::Texture>& texture)
{
// Message has ownership of Texture while in transit from event -> update
- using LocalType = MessageValue1<UpdateManager, OwnerPointer<Render::Texture> >;
+ using LocalType = MessageValue1<UpdateManager, OwnerPointer<Render::Texture>>;
// Reserve some memory inside the message queue
uint32_t* slot = manager.ReserveMessageSlot(sizeof(LocalType));
inline void AddFrameBuffer(UpdateManager& manager, OwnerPointer<Render::FrameBuffer>& frameBuffer)
{
- using LocalType = MessageValue1<UpdateManager, OwnerPointer<Render::FrameBuffer> >;
+ using LocalType = MessageValue1<UpdateManager, OwnerPointer<Render::FrameBuffer>>;
// Reserve some memory inside the message queue
uint32_t* slot = manager.ReserveMessageSlot(sizeof(LocalType));
inline void SetDepthIndicesMessage(UpdateManager& manager, OwnerPointer<NodeDepths>& nodeDepths)
{
- using LocalType = MessageValue1<UpdateManager, OwnerPointer<NodeDepths> >;
+ using LocalType = MessageValue1<UpdateManager, OwnerPointer<NodeDepths>>;
// Reserve some memory inside the message queue
uint32_t* slot = manager.ReserveMessageSlot(sizeof(LocalType));
inline void AddResetterMessage(UpdateManager& manager, OwnerPointer<PropertyResetterBase> resetter)
{
- using LocalType = MessageValue1<UpdateManager, OwnerPointer<PropertyResetterBase> >;
+ using LocalType = MessageValue1<UpdateManager, OwnerPointer<PropertyResetterBase>>;
// Reserve some memory inside the message queue
uint32_t* slot = manager.ReserveMessageSlot(sizeof(LocalType));
void Node::Delete(Node* node)
{
- // check we have a node not a layer
- if(!node->mIsLayer)
+ // check we have a node not a derived node
+ if(!node->mIsLayer && !node->mIsCamera)
{
// Manually call the destructor
node->~Node();
mClippingMode(ClippingMode::DISABLED),
mIsRoot(false),
mIsLayer(false),
+ mIsCamera(false),
mPositionUsesAnchorPoint(true),
mTransparent(false)
{
* Query whether the node is a layer.
* @return True if the node is a layer.
*/
- bool IsLayer()
+ bool IsLayer() const
{
return mIsLayer;
}
return nullptr;
}
+ // Camera interface
+
+ /**
+ * Query whether the node is a camera.
+ * @return True if the node is a camera.
+ */
+ bool IsCamera() const
+ {
+ return mIsCamera;
+ }
+
/**
* Mark an node and its sub tree according to the updated flag.
* @param[in] updated The updated flag
}
private:
- // Undefined
- Node(const Node&);
-
- // Undefined
- Node& operator=(const Node& rhs);
+ // Delete copy and move
+ Node(const Node&) = delete;
+ Node(Node&&) = delete;
+ Node& operator=(const Node& rhs) = delete;
+ Node& operator=(Node&& rhs) = delete;
/**
* Recursive helper to disconnect a Node and its children.
ClippingMode::Type mClippingMode : 3; ///< The clipping mode of this node
bool mIsRoot : 1; ///< True if the node cannot have a parent
bool mIsLayer : 1; ///< True if the node is a layer
+ bool mIsCamera : 1; ///< True if the node is a camera
bool mPositionUsesAnchorPoint : 1; ///< True if the node should use the anchor-point when calculating the position
bool mTransparent : 1; ///< True if this node is transparent. This value do not affect children.
#define DALI_INTERNAL_SCENE_GRAPH_LAYER_H
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
* to use is the same than the one used before ( Otherwise View transform will be different )
*
*/
- bool CanReuseRenderers(Camera* camera)
+ bool CanReuseRenderers(const Camera* camera)
{
bool bReturn(mAllChildTransformsClean[0] && mAllChildTransformsClean[1] && camera == mLastCamera);
mLastCamera = camera;
*/
Layer();
- // Undefined
- Layer(const Layer&);
-
- // Undefined
- Layer& operator=(const Layer& rhs);
+ // Delete copy and move
+ Layer(const Layer&) = delete;
+ Layer(Layer&&) = delete;
+ Layer& operator=(const Layer& rhs) = delete;
+ Layer& operator=(Layer&& rhs) = delete;
public: // For update-algorithms
RenderableContainer colorRenderables;
private:
SortFunctionType mSortFunction; ///< Used to sort semi-transparent geometry
- ClippingBox mClippingBox; ///< The clipping box, in window coordinates
- Camera* mLastCamera; ///< Pointer to the last camera that has rendered the layer
+ ClippingBox mClippingBox; ///< The clipping box, in window coordinates
+ const Camera* mLastCamera; ///< Pointer to the last camera that has rendered the layer
Dali::Layer::Behavior mBehavior; ///< The behavior of the layer
// INTERNAL INCLUDES
#include <dali/integration-api/debug.h>
+#include <dali/internal/common/memory-pool-object-allocator.h>
#include <dali/internal/update/nodes/node.h>
#include <dali/public-api/common/dali-common.h>
#include <dali/public-api/math/math-utils.h>
{
namespace
{
+//Memory pool used to allocate new camera. Memory used by this pool will be released when shutting down DALi
+MemoryPoolObjectAllocator<Camera> gCameraMemoryPool;
+
template<typename T>
T Sign(T value)
{
const Vector3 Camera::DEFAULT_TARGET_POSITION(0.0f, 0.0f, 0.0f);
Camera::Camera()
-: mUpdateViewFlag(UPDATE_COUNT),
+: Node(),
+ mUpdateViewFlag(UPDATE_COUNT),
mUpdateProjectionFlag(UPDATE_COUNT),
mProjectionRotation(0),
- mNode(nullptr),
mType(DEFAULT_TYPE),
mProjectionMode(DEFAULT_MODE),
mProjectionDirection(DEFAULT_PROJECTION_DIRECTION),
mInverseViewProjection(Matrix::IDENTITY),
mFinalProjection(Matrix::IDENTITY)
{
+ // set a flag the node to say this is a camera
+ mIsCamera = true;
}
Camera* Camera::New()
{
- return new Camera();
+ return new(gCameraMemoryPool.AllocateRawThreadSafe()) Camera();
}
Camera::~Camera() = default;
-void Camera::SetNode(const Node* node)
-{
- mNode = node;
-}
-
-const Node* Camera::GetNode() const
+void Camera::operator delete(void* ptr)
{
- return mNode;
+ gCameraMemoryPool.FreeThreadSafe(static_cast<Camera*>(ptr));
}
void Camera::SetType(Dali::Camera::Type type)
mUpdateProjectionFlag = UPDATE_COUNT;
}
-void Camera::SetFieldOfView(float fieldOfView)
+void Camera::BakeFieldOfView(BufferIndex updateBufferIndex, float fieldOfView)
{
- mFieldOfView = fieldOfView;
+ mFieldOfView.Bake(updateBufferIndex, fieldOfView);
mUpdateProjectionFlag = UPDATE_COUNT;
}
return mFinalProjection[bufferIndex];
}
+const PropertyBase* Camera::GetFieldOfView() const
+{
+ return &mFieldOfView;
+}
+
const PropertyInputImpl* Camera::GetProjectionMatrix() const
{
return &mProjectionMatrix;
void Camera::Update(BufferIndex updateBufferIndex)
{
- // if owning node has changes in world position we need to update camera for next 2 frames
- if(mNode->IsLocalMatrixDirty())
+ // if this has changes in world position we need to update camera for next 2 frames
+ if(IsLocalMatrixDirty())
{
mUpdateViewFlag = UPDATE_COUNT;
}
- if(mNode->GetDirtyFlags() & NodePropertyFlags::VISIBLE)
+ if(GetDirtyFlags() & NodePropertyFlags::VISIBLE)
{
// If the visibility changes, the projection matrix needs to be re-calculated.
// It may happen the first time an actor is rendered it's rendered only once and becomes invisible,
mUpdateProjectionFlag = UPDATE_COUNT;
}
+ // If projection matrix relative properties are animated now, flag change.
+ if(IsProjectionMatrixAnimated())
+ {
+ mUpdateProjectionFlag = UPDATE_COUNT;
+ }
+
// if either matrix changed, we need to recalculate the inverse matrix for hit testing to work
uint32_t viewUpdateCount = UpdateViewMatrix(updateBufferIndex);
uint32_t projectionUpdateCount = UpdateProjection(updateBufferIndex);
}
}
-bool Camera::ViewMatrixUpdated()
+bool Camera::ViewMatrixUpdated() const
{
return 0u != mUpdateViewFlag;
}
+bool Camera::IsProjectionMatrixAnimated() const
+{
+ return !mFieldOfView.IsClean();
+}
+
uint32_t Camera::UpdateViewMatrix(BufferIndex updateBufferIndex)
{
uint32_t retval(mUpdateViewFlag);
case Dali::Camera::FREE_LOOK:
{
Matrix& viewMatrix = mViewMatrix.Get(updateBufferIndex);
- viewMatrix = mNode->GetWorldMatrix(updateBufferIndex);
+ viewMatrix = GetWorldMatrix(updateBufferIndex);
if(mUseReflection)
{
- const Matrix& owningNodeMatrix(mNode->GetWorldMatrix(updateBufferIndex));
+ const Matrix& owningNodeMatrix(GetWorldMatrix(updateBufferIndex));
Vector3 position{}, scale{};
Quaternion orientation{};
owningNodeMatrix.GetTransformComponents(position, orientation, scale);
// camera orientation constrained to look at a target
case Dali::Camera::LOOK_AT_TARGET:
{
- const Matrix& owningNodeMatrix(mNode->GetWorldMatrix(updateBufferIndex));
+ const Matrix& owningNodeMatrix(GetWorldMatrix(updateBufferIndex));
Vector3 position, scale;
Quaternion orientation;
owningNodeMatrix.GetTransformComponents(position, orientation, scale);
mFrustum[updateBufferIndex ? 0 : 1] = planes;
}
-bool Camera::CheckSphereInFrustum(BufferIndex bufferIndex, const Vector3& origin, float radius)
+bool Camera::CheckSphereInFrustum(BufferIndex bufferIndex, const Vector3& origin, float radius) const
{
const FrustumPlanes& planes = mFrustum[bufferIndex];
for(uint32_t i = 0; i < 6; ++i)
return true;
}
-bool Camera::CheckAABBInFrustum(BufferIndex bufferIndex, const Vector3& origin, const Vector3& halfExtents)
+bool Camera::CheckAABBInFrustum(BufferIndex bufferIndex, const Vector3& origin, const Vector3& halfExtents) const
{
const FrustumPlanes& planes = mFrustum[bufferIndex];
for(uint32_t i = 0; i < 6; ++i)
Matrix& projectionMatrix = mProjectionMatrix.Get(updateBufferIndex);
Perspective(projectionMatrix,
mProjectionDirection,
- mFieldOfView,
+ mFieldOfView[updateBufferIndex],
mAspectRatio,
mNearClippingPlane,
mFarClippingPlane,
#include <dali/internal/common/message.h>
#include <dali/internal/common/type-abstraction-enums.h>
#include <dali/internal/event/common/event-thread-services.h>
+#include <dali/internal/update/common/animatable-property.h>
#include <dali/internal/update/common/double-buffered.h>
#include <dali/internal/update/common/inherited-property.h>
+#include <dali/internal/update/nodes/node.h>
#include <dali/public-api/actors/camera-actor.h>
#include <dali/public-api/math/rect.h>
namespace SceneGraph
{
-class Node;
class SceneController;
/**
* Scene-graph camera object
*/
-class Camera
+class Camera : public Node
{
public:
static const Dali::Camera::Type DEFAULT_TYPE;
static Camera* New();
/**
- * Destructor
+ * Virtual destructor
*/
- ~Camera();
+ ~Camera() override;
/**
- * Set the node this scene graph camera belongs to.
- * @param[in] node The owning node.
+ * Overriden delete operator
+ * Deletes the camera from its global memory pool
*/
- void SetNode(const Node* node);
-
- /**
- * Get the node this scene graph camera belongs to.
- * @return node The owning node.
- */
- const Node* GetNode() const;
+ void operator delete(void* ptr);
/**
* @copydoc Dali::Internal::CameraActor::SetType
void SetProjectionDirection(Dali::DevelCameraActor::ProjectionDirection direction);
/**
- * @copydoc Dali::Internal::CameraActor::SetFieldOfView
- */
- void SetFieldOfView(float fieldOfView);
-
- /**
* @copydoc Dali::Internal::CameraActor::SetAspectRatio
*/
void SetAspectRatio(float aspectRatio);
void SetTargetPosition(const Vector3& targetPosition);
/**
+ * @brief Bakes the field of view.
+ * @param[in] updateBufferIndex The current update buffer index.
+ * @param[in] opacity The field of view.
+ */
+ void BakeFieldOfView(BufferIndex updateBufferIndex, float fieldOfView);
+
+ /**
+ * @brief Retrieve the field of view.
+ * @param[in] bufferIndex The buffer to read from.
+ * @return The field of view.
+ */
+ float GetFieldOfView(BufferIndex bufferIndex) const
+ {
+ return mFieldOfView[bufferIndex];
+ }
+
+ /**
* Sets the reflection plane
* @param[in] plane reflection plane
*/
*
* @return false if the sphere lies outside of the frustum.
*/
- bool CheckSphereInFrustum(BufferIndex bufferIndex, const Vector3& origin, float radius);
+ bool CheckSphereInFrustum(BufferIndex bufferIndex, const Vector3& origin, float radius) const;
/**
* @brief Check to see if a bounding box lies within the view frustum.
*
* @return false if the cubeoid lies completely outside of the frustum, true otherwise
*/
- bool CheckAABBInFrustum(BufferIndex bufferIndex, const Vector3& origin, const Vector3& halfExtents);
+ bool CheckAABBInFrustum(BufferIndex bufferIndex, const Vector3& origin, const Vector3& halfExtents) const;
/**
* Retrieve the projection-matrix; this is double buffered for input handling.
const Matrix& GetFinalProjectionMatrix(BufferIndex bufferIndex) const;
/**
+ * Retrieve the field of view property querying interface.
+ * @pre The camera is on-stage.
+ * @return The field of view property querying interface.
+ */
+ const PropertyBase* GetFieldOfView() const;
+
+ /**
* Retrieve the projection-matrix property querying interface.
* @pre The camera is on-stage.
* @return The projection-matrix property querying interface.
/**
* @return true if the view matrix of camera is updated this or the previous frame
*/
- bool ViewMatrixUpdated();
+ bool ViewMatrixUpdated() const;
+
+ /**
+ * @return true if the projection matrix projection matrix relative properties are animated this or the previous frame
+ */
+ bool IsProjectionMatrixAnimated() const;
private:
/**
*/
Camera();
- // Non copyable
- // Undefined
- Camera(const Camera&);
- // Undefined
- Camera& operator=(const Camera& rhs);
+ // Delete copy and move
+ Camera(const Camera&) = delete;
+ Camera(Camera&&) = delete;
+ Camera& operator=(const Camera& rhs) = delete;
+ Camera& operator=(Camera&& rhs) = delete;
/**
* Recalculates the view matrix.
*/
void AdjustNearPlaneForPerspective(Matrix& perspective, const Vector4& clipPlane);
- uint32_t mUpdateViewFlag; ///< This is non-zero if the view matrix requires an update
- uint32_t mUpdateProjectionFlag; ///< This is non-zero if the projection matrix requires an update
- int mProjectionRotation; ///< The rotaion angle of the projection
- const Node* mNode; ///< The node this scene graph camera belongs to
+ uint32_t mUpdateViewFlag; ///< This is non-zero if the view matrix requires an update
+ uint32_t mUpdateProjectionFlag; ///< This is non-zero if the projection matrix requires an update
+ int mProjectionRotation; ///< The rotaion angle of the projection
public: // PROPERTIES
Dali::Camera::Type mType; // Non-animatable
Dali::DevelCameraActor::ProjectionDirection mProjectionDirection; // Non-animatable
bool mInvertYAxis; // Non-animatable
- float mFieldOfView;
+ AnimatableProperty<float> mFieldOfView; // Animatable
+
float mAspectRatio;
float mLeftClippingPlane;
float mRightClippingPlane;
new(slot) LocalProjectionDirection(&camera, &Camera::SetProjectionDirection, parameter);
}
-inline void SetFieldOfViewMessage(EventThreadServices& eventThreadServices, const Camera& camera, float parameter)
+inline void BakeFieldOfViewMessage(EventThreadServices& eventThreadServices, const Camera& camera, float parameter)
{
- using LocalType = MessageValue1<Camera, float>;
+ using LocalType = MessageDoubleBuffered1<Camera, float>;
// Reserve some memory inside the message queue
uint32_t* slot = eventThreadServices.ReserveMessageSlot(sizeof(LocalType));
// Construct message in the message queue memory; note that delete should not be called on the return value
- new(slot) LocalType(&camera, &Camera::SetFieldOfView, parameter);
+ new(slot) LocalType(&camera, &Camera::BakeFieldOfView, parameter);
}
inline void SetAspectRatioMessage(EventThreadServices& eventThreadServices, const Camera& camera, float parameter)
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
return mCamera->GetViewMatrix(bufferIndex);
}
-SceneGraph::Camera& RenderTask::GetCamera() const
+const SceneGraph::Camera& RenderTask::GetCamera() const
{
DALI_ASSERT_DEBUG(nullptr != mCamera);
return *mCamera;
{
if(GetViewportGuideNode() && GetViewportGuideNode()->ConnectedToScene())
{
- Vector3 worldPosition = GetViewportGuideNode()->GetWorldPosition(updateBufferIndex);
+ Vector3 worldPosition = GetViewportGuideNode()->GetWorldPosition(updateBufferIndex);
worldPosition -= cameraPosition;
Vector3 nodeSize = GetViewportGuideNode()->GetSize(updateBufferIndex) * GetViewportGuideNode()->GetWorldScale(updateBufferIndex);
#define DALI_INTERNAL_SCENE_GRAPH_RENDER_TASK_H
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
*
* @return The camera.
*/
- SceneGraph::Camera& GetCamera() const;
+ const SceneGraph::Camera& GetCamera() const;
/**
* Retrieve the projection-matrix; this is double buffered for input handling.