}
return true;
}
+
+/**
+ * @brief Get the Orientation from Forward vector and Up vector
+ * If vectors are valid, return Quaternion to make forward direction as +Z, and up direction near as -Y axis.
+ * If some invalid vector inputed (like Zero length, or parallel vector), return identity quaternion
+ *
+ * @param[in] forward The vector that want to be +Z axis.
+ * @param[in] up The vector that want to be -Y axis.
+ * @return Quaternion to make forward direction as +Z, and up direction near as -Y axis.
+ */
+Quaternion GetOrientationFromForwardAndUpVector(Vector3 forward, Vector3 up)
+{
+ Vector3 vZ = forward;
+ vZ.Normalize();
+
+ Vector3 vX = up.Cross(vZ);
+ vX.Normalize();
+
+ // If something invalid input comes, vX length become zero.
+ if(DALI_UNLIKELY(Dali::EqualsZero(vX.Length())))
+ {
+ DALI_LOG_ERROR("Invalid value inputed, forward : %f %f %f , up : %f %f %f\n", forward.x, forward.y, forward.z, up.x, up.y, up.z);
+ return Quaternion();
+ }
+
+ Vector3 vY = vZ.Cross(vX);
+ vY.Normalize();
+
+ return Quaternion(vX, vY, vZ);
+}
+
+// Common API for calculating screen position
+
+/**
+ * @brief Retrieve actor's world position by Event related properties after calculating the world transform matrix.
+ *
+ * @param[in] actor The actor that wants to get WorldPosition
+ * @param[out] worldTransformMatrix Calculated world matrix as output. We can reuse this value in other logics.
+ * @return Calculated world position
+ */
+Vector3 RetrieveCalculatedWorldPosition(const Actor& actor, Matrix& worldTransformMatrix)
+{
+ worldTransformMatrix = Dali::Internal::CalculateActorWorldTransform(actor);
+
+ Scene& scene = actor.GetScene();
+
+ Vector3 worldPosition = worldTransformMatrix.GetTranslation3();
+ Vector3 cameraPosition = Dali::Internal::CalculateActorWorldTransform(scene.GetDefaultCameraActor()).GetTranslation3();
+ worldPosition -= cameraPosition;
+
+ return worldPosition;
+}
+
+/**
+ * @brief Calculate actor's current world position by Update related properties.
+ *
+ * @param[in] actor The actor that wants to get WorldPosition
+ * @param[in] bufferIndex Buffer index of update
+ * @return Calculated world position
+ */
+Vector3 CalculateCurrentWorldPosition(const Actor& actor, BufferIndex bufferIndex)
+{
+ Scene& scene = actor.GetScene();
+
+ Vector3 worldPosition = actor.GetNode().GetWorldPosition(bufferIndex);
+ Vector3 cameraPosition = scene.GetDefaultCameraActor().GetNode().GetWorldPosition(bufferIndex);
+ worldPosition -= cameraPosition;
+
+ return worldPosition;
+}
+
+/**
+ * @brief Calculate actor's scaled size by world scale.
+ *
+ * @param[in] actor The actor that wants to get scaled size
+ * @param[in] worldTransformMatrix The actor's world matrix
+ * @return The size scaled by world scale
+ */
+Vector3 CalculateScaledActorSize(const Actor& actor, const Matrix& worldTransformMatrix)
+{
+ return actor.GetTargetSize() * worldTransformMatrix.GetScale();
+}
+
+/**
+ * @brief Calculate actor's current scaled size by world scale.
+ *
+ * @param[in] actor The actor that wants to get scaled size
+ * @param[in] bufferIndex Buffer index of update
+ * @return The size scaled by world scale
+ */
+Vector3 CalculateCurrentScaledActorSize(const Actor& actor, BufferIndex bufferIndex)
+{
+ auto& node = actor.GetNode();
+ return node.GetSize(bufferIndex) * node.GetWorldScale(bufferIndex);
+}
+
+/**
+ * @brief Calculate screen extents top-left point position
+ *
+ * @param[in] sceneSize The scene size
+ * @param[in] actorSize The actor size
+ * @param[in] worldPosition The actor's world position
+ * @return The size scaled by world scale
+ */
+template<typename SceneSizeType, typename ActorSizeType, typename WorldPositionType>
+Vector2 CalculateActorTopLeftScreenPosition(const SceneSizeType& sceneSize, const ActorSizeType& actorSize, const WorldPositionType& worldPosition)
+{
+ const Vector2 halfSceneSize(sceneSize.width * 0.5f, sceneSize.height * 0.5f);
+ const Vector2 halfActorSize(actorSize.width * 0.5f, actorSize.height * 0.5f);
+
+ return Vector2(halfSceneSize.width - halfActorSize.width + worldPosition.x, halfSceneSize.height - halfActorSize.height + worldPosition.y);
+}
} // namespace
+
bool ConvertScreenToLocal(
const Matrix& viewMatrix,
const Matrix& projectionMatrix,
{
// Get the ModelView matrix
Matrix modelView;
- MatrixUtils::Multiply(modelView, worldMatrix, viewMatrix);
+ MatrixUtils::MultiplyTransformMatrix(modelView, worldMatrix, viewMatrix);
// Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
Matrix invertedMvp(false /*don't init*/);
}
}
return false;
-};
+}
-const Vector2 CalculateActorScreenPosition(const Actor& actor, BufferIndex bufferIndex)
+const Vector2 CalculateActorScreenPosition(const Actor& actor)
{
- Scene& scene = actor.GetScene();
+ Vector2 result;
if(actor.OnScene())
{
- const auto& node = actor.GetNode();
- Vector3 worldPosition = node.GetWorldPosition(bufferIndex);
- Vector3 cameraPosition = scene.GetDefaultCameraActor().GetNode().GetWorldPosition(bufferIndex);
- worldPosition -= cameraPosition;
-
- Vector3 actorSize = node.GetSize(bufferIndex) * node.GetWorldScale(bufferIndex);
- 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();
- return Vector2(halfSceneSize.width + worldPosition.x - anchorPointOffSet.x,
- halfSceneSize.height + worldPosition.y - anchorPointOffSet.y);
+ Matrix worldTransformMatrix(false); // Do not initialize. It will be calculated in RetrieveCalculatedWorldPosition API.
+
+ Vector3 worldPosition = RetrieveCalculatedWorldPosition(actor, worldTransformMatrix);
+ Vector3 actorSize = CalculateScaledActorSize(actor, worldTransformMatrix);
+
+ auto sceneSize = actor.GetScene().GetSize();
+
+ Vector2 screenPositionTopLeft = CalculateActorTopLeftScreenPosition(sceneSize, actorSize, worldPosition);
+ Vector2 anchorPointOffSet = (actorSize * actor.GetAnchorPointForPosition()).GetVectorXY();
+
+ result = screenPositionTopLeft + anchorPointOffSet;
+ }
+ return result;
+}
+
+const Vector2 CalculateCurrentActorScreenPosition(const Actor& actor, BufferIndex bufferIndex)
+{
+ Vector2 result;
+ if(actor.OnScene())
+ {
+ Vector3 worldPosition = CalculateCurrentWorldPosition(actor, bufferIndex);
+ Vector3 actorSize = CalculateCurrentScaledActorSize(actor, bufferIndex);
+
+ auto sceneSize = actor.GetScene().GetCurrentSurfaceRect(); // Use the update object's size
+
+ Vector2 screenPositionTopLeft = CalculateActorTopLeftScreenPosition(sceneSize, actorSize, worldPosition);
+ Vector2 anchorPointOffSet = (actorSize * actor.GetAnchorPointForPosition()).GetVectorXY();
+
+ result = screenPositionTopLeft + anchorPointOffSet;
+ }
+ return result;
+}
+
+Rect<> CalculateActorScreenExtents(const Actor& actor)
+{
+ Vector2 position2;
+ Vector2 size2;
+ if(actor.OnScene())
+ {
+ Matrix worldTransformMatrix(false); // Do not initialize. It will be calculated in RetrieveCalculatedWorldPosition API.
+
+ Vector3 worldPosition = RetrieveCalculatedWorldPosition(actor, worldTransformMatrix);
+ Vector3 actorSize = CalculateScaledActorSize(actor, worldTransformMatrix);
+
+ auto sceneSize = actor.GetScene().GetSize();
+
+ position2 = CalculateActorTopLeftScreenPosition(sceneSize, actorSize, worldPosition);
+ size2 = Vector2(actorSize.width, actorSize.height);
}
- return Vector2::ZERO;
+ return {position2.x, position2.y, size2.x, size2.y};
}
-Rect<> CalculateActorScreenExtents(const Actor& actor, const Vector2& screenPosition, BufferIndex bufferIndex)
+Rect<> CalculateCurrentActorScreenExtents(const Actor& actor, BufferIndex bufferIndex)
{
- const auto& node = actor.GetNode();
- Vector3 size = node.GetSize(bufferIndex) * node.GetWorldScale(bufferIndex);
- Vector3 anchorPointOffSet = size * actor.GetAnchorPointForPosition();
- Vector2 position = Vector2(screenPosition.x - anchorPointOffSet.x, screenPosition.y - anchorPointOffSet.y);
- return {position.x, position.y, size.x, size.y};
+ Vector2 position2;
+ Vector2 size2;
+ if(actor.OnScene())
+ {
+ Vector3 worldPosition = CalculateCurrentWorldPosition(actor, bufferIndex);
+ Vector3 actorSize = CalculateCurrentScaledActorSize(actor, bufferIndex);
+
+ auto sceneSize = actor.GetScene().GetCurrentSurfaceRect(); // Use the update object's size
+
+ position2 = CalculateActorTopLeftScreenPosition(sceneSize, actorSize, worldPosition);
+ size2 = Vector2(actorSize.width, actorSize.height);
+ }
+ return {position2.x, position2.y, size2.x, size2.y};
}
bool ConvertLocalToScreen(
return false;
}
-const Vector2 CalculateActorScreenPositionRenderTaskList(const Actor& actor, BufferIndex bufferIndex)
+const Vector2 CalculateActorScreenPositionRenderTaskList(const Actor& actor)
{
+ Vector2 result;
if(actor.OnScene())
{
- const auto& node = actor.GetNode();
- Scene& scene = actor.GetScene();
+ auto worldMatrix = Dali::Internal::CalculateActorWorldTransform(actor);
+ const auto& renderTaskList = actor.GetScene().GetRenderTaskList();
+
+ ConvertLocalToScreenRenderTaskList(renderTaskList, actor, worldMatrix, actor.GetTargetSize() * (actor.GetAnchorPointForPosition() - Vector3(0.5f, 0.5f, 0.5f)), result.x, result.y);
+ }
+ return result;
+}
- Vector2 result;
+const Vector2 CalculateCurrentActorScreenPositionRenderTaskList(const Actor& actor, BufferIndex bufferIndex)
+{
+ Vector2 result;
+ if(actor.OnScene())
+ {
+ const auto& node = actor.GetNode();
+ const auto& worldMatrix = node.GetWorldMatrix(bufferIndex);
+ const auto& renderTaskList = actor.GetScene().GetRenderTaskList();
- 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;
+ return result;
}
bool ConvertLocalToScreenExtentRenderTask(
return false;
}
-Rect<> CalculateActorScreenExtentsRenderTaskList(const Actor& actor, BufferIndex bufferIndex)
+Rect<> CalculateActorScreenExtentsRenderTaskList(const Actor& actor)
{
Rect<> result = {0.0f, 0.0f, 0.0f, 0.0f};
if(actor.OnScene())
{
- const auto& node = actor.GetNode();
- Scene& scene = actor.GetScene();
+ Scene& scene = actor.GetScene();
- auto worldMatrix = node.GetWorldMatrix(bufferIndex);
+ auto worldMatrix = Dali::Internal::CalculateActorWorldTransform(actor);
const auto& renderTaskList = scene.GetRenderTaskList();
+ ConvertLocalToScreenExtentRenderTaskList(renderTaskList, actor, worldMatrix, actor.GetTargetSize(), result);
+ }
+ return result;
+}
+
+Rect<> CalculateCurrentActorScreenExtentsRenderTaskList(const Actor& actor, BufferIndex bufferIndex)
+{
+ Rect<> result = {0.0f, 0.0f, 0.0f, 0.0f};
+
+ if(actor.OnScene())
+ {
+ const auto& node = actor.GetNode();
+ const auto& worldMatrix = node.GetWorldMatrix(bufferIndex);
+ const auto& renderTaskList = actor.GetScene().GetRenderTaskList();
+
ConvertLocalToScreenExtentRenderTaskList(renderTaskList, actor, worldMatrix, node.GetSize(bufferIndex), result);
}
return result;
//Update the world matrix
Matrix tempMatrix;
- MatrixUtils::Multiply(tempMatrix, localMatrix, worldMatrix);
+ MatrixUtils::MultiplyTransformMatrix(tempMatrix, localMatrix, worldMatrix);
worldMatrix = tempMatrix;
}
else
// Compute intermediate world information
Matrix intermediateWorldMatrix;
- MatrixUtils::Multiply(intermediateWorldMatrix, intermediateLocalMatrix, parentMatrix);
+ MatrixUtils::MultiplyTransformMatrix(intermediateWorldMatrix, intermediateLocalMatrix, parentMatrix);
Vector3 intermediateWorldPosition, intermediateWorldScale;
Quaternion intermediateWorldOrientation;
return worldColor;
}
+Quaternion CalculateActorLookAtOrientation(const Actor& actor, Vector3 target, Vector3 up, Vector3 localForward, Vector3 localUp)
+{
+ Vector3 currentWorldPosition = Dali::Internal::CalculateActorWorldTransform(actor).GetTranslation3();
+
+ Quaternion worldToTarget = GetOrientationFromForwardAndUpVector(target - currentWorldPosition, up);
+ Quaternion worldToLocal = GetOrientationFromForwardAndUpVector(localForward, localUp);
+
+ // Rotate by this order : Local --> World --> Target
+ Quaternion ret = worldToTarget / worldToLocal;
+
+ // If we inherit orientation, get parent's world orientation, and revert it.
+ if(actor.IsOrientationInherited() && actor.GetParent())
+ {
+ // Get Parent information.
+ Vector3 parentPosition, parentScale;
+ Quaternion parentOrientation;
+ const Matrix& parentMatrix = Dali::Internal::CalculateActorWorldTransform(*actor.GetParent());
+ parentMatrix.GetTransformComponents(parentPosition, parentOrientation, parentScale);
+
+ ret = ret / parentOrientation;
+ }
+
+ return ret;
+}
+
} // namespace Dali::Internal