X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Finternal%2Fevent%2Factors%2Factor-coords.cpp;h=4ee65663da29346aa024e2aed0a2bb7f44da4b9f;hb=74aca73794f55767b0fb9a94fc3653fae8ed3e62;hp=9d1010e6eef563ea9f9c9469b472465725286520;hpb=ba1e5e67b3b087e1caed1cb3f7794930e5eae7bb;p=platform%2Fcore%2Fuifw%2Fdali-core.git diff --git a/dali/internal/event/actors/actor-coords.cpp b/dali/internal/event/actors/actor-coords.cpp index 9d1010e..4ee6566 100644 --- a/dali/internal/event/actors/actor-coords.cpp +++ b/dali/internal/event/actors/actor-coords.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -14,6 +14,7 @@ * limitations under the License. */ +#include #include #include #include @@ -22,6 +23,49 @@ namespace Dali::Internal { +namespace +{ +/** + * @brief Get the Viewport Extents from RenderTask + * + * @param[in] renderTask RenderTask what we want to get viewport. + * @param[out] viewportExtent Calculated extent by renderTask. + * @return True if we success to get viewports. False otherwise + */ +bool GetViewportExtentsFromRenderTask(const RenderTask& renderTask, Rect& viewportExtent) +{ + if(renderTask.GetFrameBuffer()) + { + Dali::Actor mappingActor = renderTask.GetScreenToFrameBufferMappingActor(); + if(mappingActor) + { + // NOTE : We will assume that mapping actor always use default camera. + Vector2 screenPosition = mappingActor.GetProperty(Dali::Actor::Property::SCREEN_POSITION); + Vector3 size = mappingActor.GetCurrentProperty(Dali::Actor::Property::SIZE) * mappingActor.GetCurrentProperty(Dali::Actor::Property::WORLD_SCALE); + Vector3 anchorPointOffSet = size * GetImplementation(mappingActor).GetAnchorPointForPosition(); + Vector2 position = Vector2(screenPosition.x - anchorPointOffSet.x, screenPosition.y - anchorPointOffSet.y); + viewportExtent.x = position.x; + viewportExtent.y = position.y; + viewportExtent.width = size.x; + viewportExtent.height = size.y; + } + else + { + return false; + } + } + else + { + Viewport viewport; + renderTask.GetViewport(viewport); + viewportExtent.x = viewport.x; + viewportExtent.y = viewport.y; + viewportExtent.width = viewport.width; + viewportExtent.height = viewport.height; + } + return true; +} +} // namespace bool ConvertScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, @@ -35,11 +79,11 @@ bool ConvertScreenToLocal( { // Get the ModelView matrix Matrix modelView; - Matrix::Multiply(modelView, worldMatrix, viewMatrix); + MatrixUtils::Multiply(modelView, worldMatrix, viewMatrix); // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects Matrix invertedMvp(false /*don't init*/); - Matrix::Multiply(invertedMvp, modelView, projectionMatrix); + MatrixUtils::Multiply(invertedMvp, modelView, projectionMatrix); bool success = invertedMvp.Invert(); // Convert to GL coordinates @@ -136,7 +180,7 @@ const Vector2 CalculateActorScreenPosition(const Actor& actor, BufferIndex buffe worldPosition -= cameraPosition; Vector3 actorSize = node.GetSize(bufferIndex) * node.GetWorldScale(bufferIndex); - auto sceneSize = scene.GetCurrentSurfaceRect(); // Use the update object's size + auto sceneSize = scene.GetCurrentSurfaceRect(); // Use the update object's size Vector2 halfSceneSize(sceneSize.width * 0.5f, sceneSize.height * 0.5f); // World position origin is center of scene Vector3 halfActorSize(actorSize * 0.5f); Vector3 anchorPointOffSet = halfActorSize - actorSize * actor.GetAnchorPointForPosition(); @@ -155,4 +199,416 @@ Rect<> CalculateActorScreenExtents(const Actor& actor, const Vector2& screenPosi return {position.x, position.y, size.x, size.y}; } +bool ConvertLocalToScreen( + const Matrix& viewMatrix, + const Matrix& projectionMatrix, + const Matrix& worldMatrix, + const Rect<>& viewportExtent, + const Vector3& localPosition, + float& screenX, + float& screenY) +{ + bool success = false; + + // Convert local to projection coordinates + // note, P*(V*(M*pos))) is faster than (P*V*M)*pos + Vector4 mvpPos(localPosition.x, localPosition.y, localPosition.z, 1.0f); + + mvpPos = worldMatrix * mvpPos; + mvpPos = viewMatrix * mvpPos; + mvpPos = projectionMatrix * mvpPos; + + if(DALI_LIKELY(!EqualsZero(mvpPos.w))) + { + success = true; + screenX = viewportExtent.x + (mvpPos.x + mvpPos.w) * viewportExtent.width * 0.5f / mvpPos.w; + screenY = viewportExtent.y + (-mvpPos.y + mvpPos.w) * viewportExtent.height * 0.5f / mvpPos.w; + } + return success; +} + +bool ConvertLocalToScreenRenderTask( + const RenderTask& renderTask, + const Actor& actor, + const Matrix& worldMatrix, + const Vector3& localPosition, + float& screenX, + float& screenY) +{ + bool success = false; + const Actor* sourceActor = renderTask.GetSourceActor(); + if(sourceActor == nullptr) + { + return success; + } + + // Check whether current actor is in this rendertask. + bool actorInRendertask = false; + const Actor* targetActor = &actor; + while(targetActor) + { + if(sourceActor == targetActor) + { + actorInRendertask = true; + break; + } + targetActor = targetActor->GetParent(); + } + if(!actorInRendertask) + { + return success; + } + + CameraActor* camera = renderTask.GetCameraActor(); + if(camera) + { + Rect viewportExtent = {0.f, 0.f, 0.f, 0.f}; + if(!GetViewportExtentsFromRenderTask(renderTask, viewportExtent)) + { + return success; + } + + if(ConvertLocalToScreen(camera->GetViewMatrix(), camera->GetProjectionMatrix(), worldMatrix, viewportExtent, localPosition, screenX, screenY)) + { + success = true; + } + } + return success; +} + +bool ConvertLocalToScreenRenderTaskList( + const RenderTaskList& renderTaskList, + const Actor& actor, + const Matrix& worldMatrix, + const Vector3& localPosition, + float& screenX, + float& screenY) +{ + // do a reverse traversal of all lists (as the default onscreen one is typically the last one) + uint32_t taskCount = renderTaskList.GetTaskCount(); + for(uint32_t i = taskCount; i > 0; --i) + { + RenderTaskPtr task = renderTaskList.GetTask(i - 1); + if(ConvertLocalToScreenRenderTask(*task, actor, worldMatrix, localPosition, screenX, screenY)) + { + // found a task where this conversion was ok so return + return true; + } + } + return false; +} + +const Vector2 CalculateActorScreenPositionRenderTaskList(const Actor& actor, BufferIndex bufferIndex) +{ + if(actor.OnScene()) + { + const auto& node = actor.GetNode(); + Scene& scene = actor.GetScene(); + + Vector2 result; + + auto worldMatrix = node.GetWorldMatrix(bufferIndex); + const auto& renderTaskList = scene.GetRenderTaskList(); + ConvertLocalToScreenRenderTaskList(renderTaskList, actor, worldMatrix, node.GetSize(bufferIndex) * (actor.GetAnchorPointForPosition() - Vector3(0.5f, 0.5f, 0.5f)), result.x, result.y); + + return result; + } + return Vector2::ZERO; +} + +bool ConvertLocalToScreenExtentRenderTask( + const RenderTask& renderTask, + const Actor& actor, + const Matrix& worldMatrix, + const Vector3& currentSize, + Rect<>& screenExtent) +{ + bool success = false; + const Actor* sourceActor = renderTask.GetSourceActor(); + if(sourceActor == nullptr) + { + return success; + } + + // Check whether current actor is in this rendertask. + bool actorInRendertask = false; + const Actor* targetActor = &actor; + while(targetActor) + { + if(sourceActor == targetActor) + { + actorInRendertask = true; + break; + } + targetActor = targetActor->GetParent(); + } + if(!actorInRendertask) + { + return success; + } + + CameraActor* camera = renderTask.GetCameraActor(); + if(camera) + { + Rect viewportExtent = {0.f, 0.f, 0.f, 0.f}; + if(!GetViewportExtentsFromRenderTask(renderTask, viewportExtent)) + { + return success; + } + + constexpr uint32_t BOX_POINT_COUNT = 8; + const Vector3 BBOffset[BOX_POINT_COUNT] = { + Vector3(-currentSize.width * 0.5f, -currentSize.height * 0.5f, -currentSize.depth * 0.5f), + Vector3(-currentSize.width * 0.5f, currentSize.height * 0.5f, -currentSize.depth * 0.5f), + Vector3(currentSize.width * 0.5f, -currentSize.height * 0.5f, -currentSize.depth * 0.5f), + Vector3(currentSize.width * 0.5f, currentSize.height * 0.5f, -currentSize.depth * 0.5f), + Vector3(-currentSize.width * 0.5f, -currentSize.height * 0.5f, currentSize.depth * 0.5f), + Vector3(-currentSize.width * 0.5f, currentSize.height * 0.5f, currentSize.depth * 0.5f), + Vector3(currentSize.width * 0.5f, -currentSize.height * 0.5f, currentSize.depth * 0.5f), + Vector3(currentSize.width * 0.5f, currentSize.height * 0.5f, currentSize.depth * 0.5f), + }; + + float minScreenX = 0.0f; + float minScreenY = 0.0f; + float maxScreenX = 0.0f; + float maxScreenY = 0.0f; + + const auto& viewMatrix = camera->GetViewMatrix(); + const auto& projectionMatrix = camera->GetProjectionMatrix(); + + success = ConvertLocalToScreen(viewMatrix, projectionMatrix, worldMatrix, viewportExtent, BBOffset[0], minScreenX, minScreenY); + if(success) + { + maxScreenX = minScreenX; + maxScreenY = minScreenY; + for(uint32_t i = 1; i < BOX_POINT_COUNT; ++i) + { + float screenX = 0.0f; + float screenY = 0.0f; + Vector3 localPosition = BBOffset[i]; + if(DALI_UNLIKELY(!ConvertLocalToScreen(viewMatrix, projectionMatrix, worldMatrix, viewportExtent, localPosition, screenX, screenY))) + { + success = false; + break; + } + minScreenX = std::min(minScreenX, screenX); + maxScreenX = std::max(maxScreenX, screenX); + minScreenY = std::min(minScreenY, screenY); + maxScreenY = std::max(maxScreenY, screenY); + } + if(success) + { + screenExtent.x = minScreenX; + screenExtent.y = minScreenY; + screenExtent.width = maxScreenX - minScreenX; + screenExtent.height = maxScreenY - minScreenY; + } + } + } + return success; +} + +bool ConvertLocalToScreenExtentRenderTaskList( + const RenderTaskList& renderTaskList, + const Actor& actor, + const Matrix& worldMatrix, + const Vector3& currentSize, + Rect<>& screenExtent) +{ + // do a reverse traversal of all lists (as the default onscreen one is typically the last one) + uint32_t taskCount = renderTaskList.GetTaskCount(); + for(uint32_t i = taskCount; i > 0; --i) + { + RenderTaskPtr task = renderTaskList.GetTask(i - 1); + if(ConvertLocalToScreenExtentRenderTask(*task, actor, worldMatrix, currentSize, screenExtent)) + { + // found a task where this conversion was ok so return + return true; + } + } + return false; +} + +Rect<> CalculateActorScreenExtentsRenderTaskList(const Actor& actor, BufferIndex bufferIndex) +{ + Rect<> result = {0.0f, 0.0f, 0.0f, 0.0f}; + + if(actor.OnScene()) + { + const auto& node = actor.GetNode(); + Scene& scene = actor.GetScene(); + + auto worldMatrix = node.GetWorldMatrix(bufferIndex); + const auto& renderTaskList = scene.GetRenderTaskList(); + ConvertLocalToScreenExtentRenderTaskList(renderTaskList, actor, worldMatrix, node.GetSize(bufferIndex), result); + } + return result; +} + +/** + * @brief Computes and center position by using transform properties. + * @param[in] anchorPoint anchorPoint of an actor. + * @param[in] positionUsesAnchorPoint positionUsesAnchorPoint of an actor. + * @param[in] size size of an actor. + * @param[in] scale scale of an actor. + * @param[in] orientation orientation of an actor. + */ +Vector3 CalculateCenterPosition( + const Vector3& anchorPoint, + const bool positionUsesAnchorPoint, + const Vector3& size, + const Vector3& scale, + const Quaternion& orientation) +{ + Vector3 centerPosition; + const Vector3 half(0.5f, 0.5f, 0.5f); + const Vector3 topLeft(0.0f, 0.0f, 0.5f); + // Calculate the center-point by applying the scale and rotation on the anchor point. + centerPosition = (half - anchorPoint) * size * scale; + centerPosition *= orientation; + + // If the position is ignoring the anchor-point, then remove the anchor-point shift from the position. + if(!positionUsesAnchorPoint) + { + centerPosition -= (topLeft - anchorPoint) * size; + } + return centerPosition; +} + +Matrix CalculateActorWorldTransform(const Actor& actor) +{ + enum InheritanceMode + { + DONT_INHERIT_TRANSFORM = 0, + INHERIT_POSITION = 1, + INHERIT_SCALE = 2, + INHERIT_ORIENTATION = 4, + INHERIT_ALL = INHERIT_POSITION | INHERIT_SCALE | INHERIT_ORIENTATION, + }; + + std::vector descentList; + std::vector inheritanceModeList; + Dali::Actor currentActor(const_cast(&actor)); + int inheritance = 0; + do + { + inheritance = (static_cast(currentActor.GetProperty(Dali::Actor::Property::INHERIT_ORIENTATION)) << 2) + + (static_cast(currentActor.GetProperty(Dali::Actor::Property::INHERIT_SCALE)) << 1) + + static_cast(currentActor.GetProperty(Dali::Actor::Property::INHERIT_POSITION)); + inheritanceModeList.push_back(static_cast(inheritance)); + descentList.push_back(currentActor); + currentActor = currentActor.GetParent(); + } while(inheritance != DONT_INHERIT_TRANSFORM && currentActor); + + Matrix worldMatrix; + Vector3 localPosition; + // descentList is leaf first, so traverse from root (end) to leaf (beginning) + for(unsigned int i(descentList.size() - 1); i < descentList.size(); --i) + { + Vector3 anchorPoint = descentList[i].GetProperty(Dali::Actor::Property::ANCHOR_POINT); + Vector3 parentOrigin = descentList[i].GetProperty(Dali::Actor::Property::PARENT_ORIGIN); + bool positionUsesAnchorPoint = descentList[i].GetProperty(Dali::Actor::Property::POSITION_USES_ANCHOR_POINT); + Vector3 size = descentList[i].GetProperty(Dali::Actor::Property::SIZE); + Vector3 actorPosition = descentList[i].GetProperty(Dali::Actor::Property::POSITION); + Quaternion localOrientation = descentList[i].GetProperty(Dali::Actor::Property::ORIENTATION); + Vector3 localScale = descentList[i].GetProperty(Dali::Actor::Property::SCALE); + + Vector3 centerPosition = CalculateCenterPosition(anchorPoint, positionUsesAnchorPoint, size, localScale, localOrientation); + if(inheritanceModeList[i] != DONT_INHERIT_TRANSFORM && descentList[i].GetParent()) + { + Matrix localMatrix; + Vector3 parentSize = descentList[i + 1].GetProperty(Dali::Actor::Property::SIZE); + if(inheritanceModeList[i] == INHERIT_ALL) + { + localPosition = actorPosition + centerPosition + (parentOrigin - Vector3(0.5f, 0.5f, 0.5f)) * parentSize; + localMatrix.SetTransformComponents(localScale, localOrientation, localPosition); + + //Update the world matrix + Matrix tempMatrix; + MatrixUtils::Multiply(tempMatrix, localMatrix, worldMatrix); + worldMatrix = tempMatrix; + } + else + { + Vector3 parentPosition, parentScale; + Quaternion parentOrientation; + worldMatrix.GetTransformComponents(parentPosition, parentOrientation, parentScale); + + if((inheritanceModeList[i] & INHERIT_SCALE) == 0) + { + //Don't inherit scale + localScale /= parentScale; + } + + if((inheritanceModeList[i] & INHERIT_ORIENTATION) == 0) + { + //Don't inherit orientation + parentOrientation.Invert(); + localOrientation = parentOrientation * localOrientation; + } + + if((inheritanceModeList[i] & INHERIT_POSITION) == 0) + { + localMatrix.SetTransformComponents(localScale, localOrientation, Vector3::ZERO); + Matrix tempMatrix; + MatrixUtils::Multiply(tempMatrix, localMatrix, worldMatrix); + worldMatrix = tempMatrix; + worldMatrix.SetTranslation(actorPosition + centerPosition); + } + else + { + localPosition = actorPosition + centerPosition + (parentOrigin - Vector3(0.5f, 0.5f, 0.5f)) * parentSize; + localMatrix.SetTransformComponents(localScale, localOrientation, localPosition); + Matrix tempMatrix; + MatrixUtils::Multiply(tempMatrix, localMatrix, worldMatrix); + worldMatrix = tempMatrix; + } + } + } + else + { + localPosition = actorPosition + centerPosition; + worldMatrix.SetTransformComponents(localScale, localOrientation, localPosition); + } + } + + return worldMatrix; +} + +Vector4 CalculateActorWorldColor(const Actor& actor) +{ + std::vector descentList; + std::vector inheritanceModeList; + Dali::Actor currentActor(const_cast(&actor)); + Dali::ColorMode inheritance = Dali::ColorMode::USE_OWN_MULTIPLY_PARENT_ALPHA; + do + { + inheritance = currentActor.GetProperty(Dali::Actor::Property::COLOR_MODE); + inheritanceModeList.push_back(inheritance); + descentList.push_back(currentActor); + currentActor = currentActor.GetParent(); + } while(inheritance != Dali::ColorMode::USE_OWN_COLOR && currentActor); + + Vector4 worldColor; + for(unsigned int i(descentList.size() - 1); i < descentList.size(); --i) + { + if(inheritanceModeList[i] == USE_OWN_COLOR || i == descentList.size() - 1) + { + worldColor = descentList[i].GetProperty(Dali::Actor::Property::COLOR); + } + else if(inheritanceModeList[i] == USE_OWN_MULTIPLY_PARENT_ALPHA) + { + Vector4 ownColor = descentList[i].GetProperty(Dali::Actor::Property::COLOR); + worldColor = Vector4(ownColor.r, ownColor.g, ownColor.b, ownColor.a * worldColor.a); + } + else if(inheritanceModeList[i] == USE_OWN_MULTIPLY_PARENT_COLOR) + { + Vector4 ownColor = descentList[i].GetProperty(Dali::Actor::Property::COLOR); + worldColor *= ownColor; + } + } + + return worldColor; +} + } // namespace Dali::Internal