Remove duplicate codes for screen position
[platform/core/uifw/dali-core.git] / dali / internal / event / actors / actor-coords.cpp
1 /*
2  * Copyright (c) 2023 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <dali/internal/common/matrix-utils.h>
18 #include <dali/internal/event/actors/actor-coords.h>
19 #include <dali/internal/event/common/event-thread-services.h>
20 #include <dali/internal/event/common/projection.h>
21 #include <dali/internal/event/common/scene-impl.h>
22 #include <dali/internal/update/nodes/node.h>
23
24 namespace Dali::Internal
25 {
26 namespace
27 {
28 /**
29  * @brief Get the Viewport Extents from RenderTask
30  *
31  * @param[in] renderTask RenderTask what we want to get viewport.
32  * @param[out] viewportExtent Calculated extent by renderTask.
33  * @return True if we success to get viewports. False otherwise
34  */
35 bool GetViewportExtentsFromRenderTask(const RenderTask& renderTask, Rect<float>& viewportExtent)
36 {
37   if(renderTask.GetFrameBuffer())
38   {
39     Dali::Actor mappingActor = renderTask.GetScreenToFrameBufferMappingActor();
40     if(mappingActor)
41     {
42       // NOTE : We will assume that mapping actor always use default camera.
43       Vector2 screenPosition    = mappingActor.GetProperty<Vector2>(Dali::Actor::Property::SCREEN_POSITION);
44       Vector3 size              = mappingActor.GetCurrentProperty<Vector3>(Dali::Actor::Property::SIZE) * mappingActor.GetCurrentProperty<Vector3>(Dali::Actor::Property::WORLD_SCALE);
45       Vector3 anchorPointOffSet = size * GetImplementation(mappingActor).GetAnchorPointForPosition();
46       Vector2 position          = Vector2(screenPosition.x - anchorPointOffSet.x, screenPosition.y - anchorPointOffSet.y);
47       viewportExtent.x          = position.x;
48       viewportExtent.y          = position.y;
49       viewportExtent.width      = size.x;
50       viewportExtent.height     = size.y;
51     }
52     else
53     {
54       return false;
55     }
56   }
57   else
58   {
59     Viewport viewport;
60     renderTask.GetViewport(viewport);
61     viewportExtent.x      = viewport.x;
62     viewportExtent.y      = viewport.y;
63     viewportExtent.width  = viewport.width;
64     viewportExtent.height = viewport.height;
65   }
66   return true;
67 }
68
69 /**
70  * @brief Get the Orientation from Forward vector and Up vector
71  * If vectors are valid, return Quaternion to make forward direction as +Z, and up direction near as -Y axis.
72  * If some invalid vector inputed (like Zero length, or parallel vector), return identity quaternion
73  *
74  * @param[in] forward The vector that want to be +Z axis.
75  * @param[in] up The vector that want to be -Y axis.
76  * @return Quaternion to make forward direction as +Z, and up direction near as -Y axis.
77  */
78 Quaternion GetOrientationFromForwardAndUpVector(Vector3 forward, Vector3 up)
79 {
80   Vector3 vZ = forward;
81   vZ.Normalize();
82
83   Vector3 vX = up.Cross(vZ);
84   vX.Normalize();
85
86   // If something invalid input comes, vX length become zero.
87   if(DALI_UNLIKELY(Dali::EqualsZero(vX.Length())))
88   {
89     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);
90     return Quaternion();
91   }
92
93   Vector3 vY = vZ.Cross(vX);
94   vY.Normalize();
95
96   return Quaternion(vX, vY, vZ);
97 }
98
99 // Common API for calculating screen position
100
101 /**
102  * @brief Retrieve actor's world position by Event related properties after calculating the world transform matrix.
103  *
104  * @param[in] actor The actor that wants to get WorldPosition
105  * @param[out] worldTransformMatrix Calculated world matrix as output. We can reuse this value in other logics.
106  * @return Calculated world position
107  */
108 Vector3 RetrieveCalculatedWorldPosition(const Actor& actor, Matrix& worldTransformMatrix)
109 {
110   worldTransformMatrix = Dali::Internal::CalculateActorWorldTransform(actor);
111
112   Scene& scene = actor.GetScene();
113
114   Vector3 worldPosition  = worldTransformMatrix.GetTranslation3();
115   Vector3 cameraPosition = Dali::Internal::CalculateActorWorldTransform(scene.GetDefaultCameraActor()).GetTranslation3();
116   worldPosition -= cameraPosition;
117
118   return worldPosition;
119 }
120
121 /**
122  * @brief Calculate actor's current world position by Update related properties.
123  *
124  * @param[in] actor The actor that wants to get WorldPosition
125  * @param[in] bufferIndex Buffer index of update
126  * @return Calculated world position
127  */
128 Vector3 CalculateCurrentWorldPosition(const Actor& actor, BufferIndex bufferIndex)
129 {
130   Scene& scene = actor.GetScene();
131
132   Vector3 worldPosition  = actor.GetNode().GetWorldPosition(bufferIndex);
133   Vector3 cameraPosition = scene.GetDefaultCameraActor().GetNode().GetWorldPosition(bufferIndex);
134   worldPosition -= cameraPosition;
135
136   return worldPosition;
137 }
138
139 /**
140  * @brief Calculate actor's scaled size by world scale.
141  *
142  * @param[in] actor The actor that wants to get scaled size
143  * @param[in] worldTransformMatrix The actor's world matrix
144  * @return The size scaled by world scale
145  */
146 Vector3 CalculateScaledActorSize(const Actor& actor, const Matrix& worldTransformMatrix)
147 {
148   return actor.GetTargetSize() * worldTransformMatrix.GetScale();
149 }
150
151 /**
152  * @brief Calculate actor's current scaled size by world scale.
153  *
154  * @param[in] actor The actor that wants to get scaled size
155  * @param[in] bufferIndex Buffer index of update
156  * @return The size scaled by world scale
157  */
158 Vector3 CalculateCurrentScaledActorSize(const Actor& actor, BufferIndex bufferIndex)
159 {
160   auto& node = actor.GetNode();
161   return node.GetSize(bufferIndex) * node.GetWorldScale(bufferIndex);
162 }
163
164 /**
165  * @brief Calculate screen extents top-left point position
166  *
167  * @param[in] sceneSize The scene size
168  * @param[in] actorSize The actor size
169  * @param[in] worldPosition The actor's world position
170  * @return The size scaled by world scale
171  */
172 template<typename SceneSizeType, typename ActorSizeType, typename WorldPositionType>
173 Vector2 CalculateActorTopLeftScreenPosition(const SceneSizeType& sceneSize, const ActorSizeType& actorSize, const WorldPositionType& worldPosition)
174 {
175   const Vector2 halfSceneSize(sceneSize.width * 0.5f, sceneSize.height * 0.5f);
176   const Vector2 halfActorSize(actorSize.width * 0.5f, actorSize.height * 0.5f);
177
178   return Vector2(halfSceneSize.width - halfActorSize.width + worldPosition.x, halfSceneSize.height - halfActorSize.height + worldPosition.y);
179 }
180 } // namespace
181
182 bool ConvertScreenToLocal(
183   const Matrix&   viewMatrix,
184   const Matrix&   projectionMatrix,
185   const Matrix&   worldMatrix,
186   const Vector3&  currentSize,
187   const Viewport& viewport,
188   float&          localX,
189   float&          localY,
190   float           screenX,
191   float           screenY)
192 {
193   // Get the ModelView matrix
194   Matrix modelView;
195   MatrixUtils::MultiplyTransformMatrix(modelView, worldMatrix, viewMatrix);
196
197   // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
198   Matrix invertedMvp(false /*don't init*/);
199   MatrixUtils::MultiplyProjectionMatrix(invertedMvp, modelView, projectionMatrix);
200   bool success = invertedMvp.Invert();
201
202   // Convert to GL coordinates
203   Vector4 screenPos(screenX - static_cast<float>(viewport.x), static_cast<float>(viewport.height) - screenY - static_cast<float>(viewport.y), 0.f, 1.f);
204
205   Vector4 nearPos;
206   if(success)
207   {
208     success = Unproject(screenPos, invertedMvp, static_cast<float>(viewport.width), static_cast<float>(viewport.height), nearPos);
209   }
210
211   Vector4 farPos;
212   if(success)
213   {
214     screenPos.z = 1.0f;
215     success     = Unproject(screenPos, invertedMvp, static_cast<float>(viewport.width), static_cast<float>(viewport.height), farPos);
216   }
217
218   if(success)
219   {
220     Vector4 local;
221     if(XyPlaneIntersect(nearPos, farPos, local))
222     {
223       Vector3 size = currentSize;
224       localX       = local.x + size.x * 0.5f;
225       localY       = local.y + size.y * 0.5f;
226     }
227     else
228     {
229       success = false;
230     }
231   }
232
233   return success;
234 }
235
236 bool ConvertScreenToLocalRenderTask(
237   const RenderTask& renderTask,
238   const Matrix&     worldMatrix,
239   const Vector3&    currentSize,
240   float&            localX,
241   float&            localY,
242   float             screenX,
243   float             screenY)
244 {
245   bool         success = false;
246   CameraActor* camera  = renderTask.GetCameraActor();
247   if(camera)
248   {
249     Viewport viewport;
250     renderTask.GetViewport(viewport);
251
252     // need to translate coordinates to render tasks coordinate space
253     Vector2 converted(screenX, screenY);
254     if(renderTask.TranslateCoordinates(converted))
255     {
256       success = ConvertScreenToLocal(camera->GetViewMatrix(), camera->GetProjectionMatrix(), worldMatrix, currentSize, viewport, localX, localY, converted.x, converted.y);
257     }
258   }
259   return success;
260 }
261
262 bool ConvertScreenToLocalRenderTaskList(
263   const RenderTaskList& renderTaskList,
264   const Matrix&         worldMatrix,
265   const Vector3&        currentSize,
266   float&                localX,
267   float&                localY,
268   float                 screenX,
269   float                 screenY)
270 {
271   // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
272   uint32_t taskCount = renderTaskList.GetTaskCount();
273   for(uint32_t i = taskCount; i > 0; --i)
274   {
275     RenderTaskPtr task = renderTaskList.GetTask(i - 1);
276     if(ConvertScreenToLocalRenderTask(*task, worldMatrix, currentSize, localX, localY, screenX, screenY))
277     {
278       // found a task where this conversion was ok so return
279       return true;
280     }
281   }
282   return false;
283 }
284
285 const Vector2 CalculateActorScreenPosition(const Actor& actor)
286 {
287   Vector2 result;
288   if(actor.OnScene())
289   {
290     Matrix worldTransformMatrix(false); // Do not initialize. It will be calculated in RetrieveCalculatedWorldPosition API.
291
292     Vector3 worldPosition = RetrieveCalculatedWorldPosition(actor, worldTransformMatrix);
293     Vector3 actorSize     = CalculateScaledActorSize(actor, worldTransformMatrix);
294
295     auto sceneSize = actor.GetScene().GetSize();
296
297     Vector2 screenPositionTopLeft = CalculateActorTopLeftScreenPosition(sceneSize, actorSize, worldPosition);
298     Vector2 anchorPointOffSet     = (actorSize * actor.GetAnchorPointForPosition()).GetVectorXY();
299
300     result = screenPositionTopLeft + anchorPointOffSet;
301   }
302   return result;
303 }
304
305 const Vector2 CalculateCurrentActorScreenPosition(const Actor& actor, BufferIndex bufferIndex)
306 {
307   Vector2 result;
308   if(actor.OnScene())
309   {
310     Vector3 worldPosition = CalculateCurrentWorldPosition(actor, bufferIndex);
311     Vector3 actorSize     = CalculateCurrentScaledActorSize(actor, bufferIndex);
312
313     auto sceneSize = actor.GetScene().GetCurrentSurfaceRect(); // Use the update object's size
314
315     Vector2 screenPositionTopLeft = CalculateActorTopLeftScreenPosition(sceneSize, actorSize, worldPosition);
316     Vector2 anchorPointOffSet     = (actorSize * actor.GetAnchorPointForPosition()).GetVectorXY();
317
318     result = screenPositionTopLeft + anchorPointOffSet;
319   }
320   return result;
321 }
322
323 Rect<> CalculateActorScreenExtents(const Actor& actor)
324 {
325   Vector2 position2;
326   Vector2 size2;
327   if(actor.OnScene())
328   {
329     Matrix worldTransformMatrix(false); // Do not initialize. It will be calculated in RetrieveCalculatedWorldPosition API.
330
331     Vector3 worldPosition = RetrieveCalculatedWorldPosition(actor, worldTransformMatrix);
332     Vector3 actorSize     = CalculateScaledActorSize(actor, worldTransformMatrix);
333
334     auto sceneSize = actor.GetScene().GetSize();
335
336     position2 = CalculateActorTopLeftScreenPosition(sceneSize, actorSize, worldPosition);
337     size2     = Vector2(actorSize.width, actorSize.height);
338   }
339   return {position2.x, position2.y, size2.x, size2.y};
340 }
341
342 Rect<> CalculateCurrentActorScreenExtents(const Actor& actor, BufferIndex bufferIndex)
343 {
344   Vector2 position2;
345   Vector2 size2;
346   if(actor.OnScene())
347   {
348     Vector3 worldPosition = CalculateCurrentWorldPosition(actor, bufferIndex);
349     Vector3 actorSize     = CalculateCurrentScaledActorSize(actor, bufferIndex);
350
351     auto sceneSize = actor.GetScene().GetCurrentSurfaceRect(); // Use the update object's size
352
353     position2 = CalculateActorTopLeftScreenPosition(sceneSize, actorSize, worldPosition);
354     size2     = Vector2(actorSize.width, actorSize.height);
355   }
356   return {position2.x, position2.y, size2.x, size2.y};
357 }
358
359 bool ConvertLocalToScreen(
360   const Matrix&  viewMatrix,
361   const Matrix&  projectionMatrix,
362   const Matrix&  worldMatrix,
363   const Rect<>&  viewportExtent,
364   const Vector3& localPosition,
365   float&         screenX,
366   float&         screenY)
367 {
368   bool success = false;
369
370   // Convert local to projection coordinates
371   // note, P*(V*(M*pos))) is faster than (P*V*M)*pos
372   Vector4 mvpPos(localPosition.x, localPosition.y, localPosition.z, 1.0f);
373
374   mvpPos = worldMatrix * mvpPos;
375   mvpPos = viewMatrix * mvpPos;
376   mvpPos = projectionMatrix * mvpPos;
377
378   if(DALI_LIKELY(!EqualsZero(mvpPos.w)))
379   {
380     success = true;
381     screenX = viewportExtent.x + (mvpPos.x + mvpPos.w) * viewportExtent.width * 0.5f / mvpPos.w;
382     screenY = viewportExtent.y + (-mvpPos.y + mvpPos.w) * viewportExtent.height * 0.5f / mvpPos.w;
383   }
384   return success;
385 }
386
387 bool ConvertLocalToScreenRenderTask(
388   const RenderTask& renderTask,
389   const Actor&      actor,
390   const Matrix&     worldMatrix,
391   const Vector3&    localPosition,
392   float&            screenX,
393   float&            screenY)
394 {
395   bool         success     = false;
396   const Actor* sourceActor = renderTask.GetSourceActor();
397   if(sourceActor == nullptr)
398   {
399     return success;
400   }
401
402   // Check whether current actor is in this rendertask.
403   bool         actorInRendertask = false;
404   const Actor* targetActor       = &actor;
405   while(targetActor)
406   {
407     if(sourceActor == targetActor)
408     {
409       actorInRendertask = true;
410       break;
411     }
412     targetActor = targetActor->GetParent();
413   }
414   if(!actorInRendertask)
415   {
416     return success;
417   }
418
419   CameraActor* camera = renderTask.GetCameraActor();
420   if(camera)
421   {
422     Rect<float> viewportExtent = {0.f, 0.f, 0.f, 0.f};
423     if(!GetViewportExtentsFromRenderTask(renderTask, viewportExtent))
424     {
425       return success;
426     }
427
428     if(ConvertLocalToScreen(camera->GetViewMatrix(), camera->GetProjectionMatrix(), worldMatrix, viewportExtent, localPosition, screenX, screenY))
429     {
430       success = true;
431     }
432   }
433   return success;
434 }
435
436 bool ConvertLocalToScreenRenderTaskList(
437   const RenderTaskList& renderTaskList,
438   const Actor&          actor,
439   const Matrix&         worldMatrix,
440   const Vector3&        localPosition,
441   float&                screenX,
442   float&                screenY)
443 {
444   // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
445   uint32_t taskCount = renderTaskList.GetTaskCount();
446   for(uint32_t i = taskCount; i > 0; --i)
447   {
448     RenderTaskPtr task = renderTaskList.GetTask(i - 1);
449     if(ConvertLocalToScreenRenderTask(*task, actor, worldMatrix, localPosition, screenX, screenY))
450     {
451       // found a task where this conversion was ok so return
452       return true;
453     }
454   }
455   return false;
456 }
457
458 const Vector2 CalculateActorScreenPositionRenderTaskList(const Actor& actor)
459 {
460   Vector2 result;
461   if(actor.OnScene())
462   {
463     auto worldMatrix = Dali::Internal::CalculateActorWorldTransform(actor);
464     const auto& renderTaskList = actor.GetScene().GetRenderTaskList();
465
466     ConvertLocalToScreenRenderTaskList(renderTaskList, actor, worldMatrix, actor.GetTargetSize() * (actor.GetAnchorPointForPosition() - Vector3(0.5f, 0.5f, 0.5f)), result.x, result.y);
467   }
468   return result;
469 }
470
471 const Vector2 CalculateCurrentActorScreenPositionRenderTaskList(const Actor& actor, BufferIndex bufferIndex)
472 {
473   Vector2 result;
474   if(actor.OnScene())
475   {
476     const auto& node = actor.GetNode();
477     const auto& worldMatrix = node.GetWorldMatrix(bufferIndex);
478     const auto& renderTaskList = actor.GetScene().GetRenderTaskList();
479
480     ConvertLocalToScreenRenderTaskList(renderTaskList, actor, worldMatrix, node.GetSize(bufferIndex) * (actor.GetAnchorPointForPosition() - Vector3(0.5f, 0.5f, 0.5f)), result.x, result.y);
481   }
482   return result;
483 }
484
485 bool ConvertLocalToScreenExtentRenderTask(
486   const RenderTask& renderTask,
487   const Actor&      actor,
488   const Matrix&     worldMatrix,
489   const Vector3&    currentSize,
490   Rect<>&           screenExtent)
491 {
492   bool         success     = false;
493   const Actor* sourceActor = renderTask.GetSourceActor();
494   if(sourceActor == nullptr)
495   {
496     return success;
497   }
498
499   // Check whether current actor is in this rendertask.
500   bool         actorInRendertask = false;
501   const Actor* targetActor       = &actor;
502   while(targetActor)
503   {
504     if(sourceActor == targetActor)
505     {
506       actorInRendertask = true;
507       break;
508     }
509     targetActor = targetActor->GetParent();
510   }
511   if(!actorInRendertask)
512   {
513     return success;
514   }
515
516   CameraActor* camera = renderTask.GetCameraActor();
517   if(camera)
518   {
519     Rect<float> viewportExtent = {0.f, 0.f, 0.f, 0.f};
520     if(!GetViewportExtentsFromRenderTask(renderTask, viewportExtent))
521     {
522       return success;
523     }
524
525     constexpr uint32_t BOX_POINT_COUNT           = 8;
526     const Vector3      BBOffset[BOX_POINT_COUNT] = {
527       Vector3(-currentSize.width * 0.5f, -currentSize.height * 0.5f, -currentSize.depth * 0.5f),
528       Vector3(-currentSize.width * 0.5f, currentSize.height * 0.5f, -currentSize.depth * 0.5f),
529       Vector3(currentSize.width * 0.5f, -currentSize.height * 0.5f, -currentSize.depth * 0.5f),
530       Vector3(currentSize.width * 0.5f, currentSize.height * 0.5f, -currentSize.depth * 0.5f),
531       Vector3(-currentSize.width * 0.5f, -currentSize.height * 0.5f, currentSize.depth * 0.5f),
532       Vector3(-currentSize.width * 0.5f, currentSize.height * 0.5f, currentSize.depth * 0.5f),
533       Vector3(currentSize.width * 0.5f, -currentSize.height * 0.5f, currentSize.depth * 0.5f),
534       Vector3(currentSize.width * 0.5f, currentSize.height * 0.5f, currentSize.depth * 0.5f),
535     };
536
537     float minScreenX = 0.0f;
538     float minScreenY = 0.0f;
539     float maxScreenX = 0.0f;
540     float maxScreenY = 0.0f;
541
542     const auto& viewMatrix       = camera->GetViewMatrix();
543     const auto& projectionMatrix = camera->GetProjectionMatrix();
544
545     success = ConvertLocalToScreen(viewMatrix, projectionMatrix, worldMatrix, viewportExtent, BBOffset[0], minScreenX, minScreenY);
546     if(success)
547     {
548       maxScreenX = minScreenX;
549       maxScreenY = minScreenY;
550       for(uint32_t i = 1; i < BOX_POINT_COUNT; ++i)
551       {
552         float   screenX       = 0.0f;
553         float   screenY       = 0.0f;
554         Vector3 localPosition = BBOffset[i];
555         if(DALI_UNLIKELY(!ConvertLocalToScreen(viewMatrix, projectionMatrix, worldMatrix, viewportExtent, localPosition, screenX, screenY)))
556         {
557           success = false;
558           break;
559         }
560         minScreenX = std::min(minScreenX, screenX);
561         maxScreenX = std::max(maxScreenX, screenX);
562         minScreenY = std::min(minScreenY, screenY);
563         maxScreenY = std::max(maxScreenY, screenY);
564       }
565       if(success)
566       {
567         screenExtent.x      = minScreenX;
568         screenExtent.y      = minScreenY;
569         screenExtent.width  = maxScreenX - minScreenX;
570         screenExtent.height = maxScreenY - minScreenY;
571       }
572     }
573   }
574   return success;
575 }
576
577 bool ConvertLocalToScreenExtentRenderTaskList(
578   const RenderTaskList& renderTaskList,
579   const Actor&          actor,
580   const Matrix&         worldMatrix,
581   const Vector3&        currentSize,
582   Rect<>&               screenExtent)
583 {
584   // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
585   uint32_t taskCount = renderTaskList.GetTaskCount();
586   for(uint32_t i = taskCount; i > 0; --i)
587   {
588     RenderTaskPtr task = renderTaskList.GetTask(i - 1);
589     if(ConvertLocalToScreenExtentRenderTask(*task, actor, worldMatrix, currentSize, screenExtent))
590     {
591       // found a task where this conversion was ok so return
592       return true;
593     }
594   }
595   return false;
596 }
597
598 Rect<> CalculateActorScreenExtentsRenderTaskList(const Actor& actor)
599 {
600   Rect<> result = {0.0f, 0.0f, 0.0f, 0.0f};
601
602   if(actor.OnScene())
603   {
604     Scene& scene = actor.GetScene();
605
606     auto        worldMatrix    = Dali::Internal::CalculateActorWorldTransform(actor);
607     const auto& renderTaskList = scene.GetRenderTaskList();
608     ConvertLocalToScreenExtentRenderTaskList(renderTaskList, actor, worldMatrix, actor.GetTargetSize(), result);
609   }
610   return result;
611 }
612
613 Rect<> CalculateCurrentActorScreenExtentsRenderTaskList(const Actor& actor, BufferIndex bufferIndex)
614 {
615   Rect<> result = {0.0f, 0.0f, 0.0f, 0.0f};
616
617   if(actor.OnScene())
618   {
619     const auto& node = actor.GetNode();
620     const auto& worldMatrix = node.GetWorldMatrix(bufferIndex);
621     const auto& renderTaskList = actor.GetScene().GetRenderTaskList();
622
623     ConvertLocalToScreenExtentRenderTaskList(renderTaskList, actor, worldMatrix, node.GetSize(bufferIndex), result);
624   }
625   return result;
626 }
627
628 /**
629  * @brief Computes and center position by using transform properties.
630  * @param[in] anchorPoint anchorPoint of an actor.
631  * @param[in] positionUsesAnchorPoint positionUsesAnchorPoint of an actor.
632  * @param[in] size size of an actor.
633  * @param[in] scale scale of an actor.
634  * @param[in] orientation orientation of an actor.
635  */
636 Vector3 CalculateCenterPosition(
637   const Vector3&    anchorPoint,
638   const bool        positionUsesAnchorPoint,
639   const Vector3&    size,
640   const Vector3&    scale,
641   const Quaternion& orientation)
642 {
643   Vector3       centerPosition;
644   const Vector3 half(0.5f, 0.5f, 0.5f);
645   const Vector3 topLeft(0.0f, 0.0f, 0.5f);
646   // Calculate the center-point by applying the scale and rotation on the anchor point.
647   centerPosition = (half - anchorPoint) * size * scale;
648   centerPosition *= orientation;
649
650   // If the position is ignoring the anchor-point, then remove the anchor-point shift from the position.
651   if(!positionUsesAnchorPoint)
652   {
653     centerPosition -= (topLeft - anchorPoint) * size;
654   }
655   return centerPosition;
656 }
657
658 Matrix CalculateActorWorldTransform(const Actor& actor)
659 {
660   enum InheritanceMode
661   {
662     DONT_INHERIT_TRANSFORM = 0,
663     INHERIT_POSITION       = 1,
664     INHERIT_SCALE          = 2,
665     INHERIT_ORIENTATION    = 4,
666     INHERIT_ALL            = INHERIT_POSITION | INHERIT_SCALE | INHERIT_ORIENTATION,
667   };
668
669   std::vector<Dali::Actor>     descentList;
670   std::vector<InheritanceMode> inheritanceModeList;
671   Dali::Actor                  currentActor(const_cast<Actor*>(&actor));
672   int                          inheritance = 0;
673   do
674   {
675     inheritance = (static_cast<int>(currentActor.GetProperty<bool>(Dali::Actor::Property::INHERIT_ORIENTATION)) << 2) +
676                   (static_cast<int>(currentActor.GetProperty<bool>(Dali::Actor::Property::INHERIT_SCALE)) << 1) +
677                   static_cast<int>(currentActor.GetProperty<bool>(Dali::Actor::Property::INHERIT_POSITION));
678     inheritanceModeList.push_back(static_cast<InheritanceMode>(inheritance));
679     descentList.push_back(currentActor);
680     currentActor = currentActor.GetParent();
681   } while(inheritance != DONT_INHERIT_TRANSFORM && currentActor);
682
683   Matrix  worldMatrix;
684   Vector3 localPosition;
685
686   // descentList is leaf first, so traverse from root (end) to leaf (beginning)
687   const size_t descentCount = descentList.size();
688   for(size_t iter = 0u; iter < descentCount; ++iter)
689   {
690     auto       i                       = descentCount - iter - 1u;
691     Vector3    anchorPoint             = descentList[i].GetProperty<Vector3>(Dali::Actor::Property::ANCHOR_POINT);
692     Vector3    parentOrigin            = descentList[i].GetProperty<Vector3>(Dali::Actor::Property::PARENT_ORIGIN);
693     bool       positionUsesAnchorPoint = descentList[i].GetProperty<bool>(Dali::Actor::Property::POSITION_USES_ANCHOR_POINT);
694     Vector3    size                    = descentList[i].GetProperty<Vector3>(Dali::Actor::Property::SIZE);
695     Vector3    actorPosition           = descentList[i].GetProperty<Vector3>(Dali::Actor::Property::POSITION);
696     Quaternion localOrientation        = descentList[i].GetProperty<Quaternion>(Dali::Actor::Property::ORIENTATION);
697     Vector3    localScale              = descentList[i].GetProperty<Vector3>(Dali::Actor::Property::SCALE);
698
699     Vector3 centerPosition = CalculateCenterPosition(anchorPoint, positionUsesAnchorPoint, size, localScale, localOrientation);
700     if(inheritanceModeList[i] != DONT_INHERIT_TRANSFORM && descentList[i].GetParent())
701     {
702       Matrix  localMatrix;
703       Vector3 parentSize = descentList[i + 1].GetProperty<Vector3>(Dali::Actor::Property::SIZE);
704       if(inheritanceModeList[i] == INHERIT_ALL)
705       {
706         localPosition = actorPosition + centerPosition + (parentOrigin - Vector3(0.5f, 0.5f, 0.5f)) * parentSize;
707         localMatrix.SetTransformComponents(localScale, localOrientation, localPosition);
708
709         //Update the world matrix
710         Matrix tempMatrix;
711         MatrixUtils::MultiplyTransformMatrix(tempMatrix, localMatrix, worldMatrix);
712         worldMatrix = tempMatrix;
713       }
714       else
715       {
716         // Get Parent information.
717         Vector3       parentPosition, parentScale;
718         Quaternion    parentOrientation;
719         const Matrix& parentMatrix = worldMatrix;
720         parentMatrix.GetTransformComponents(parentPosition, parentOrientation, parentScale);
721
722         // Compute intermediate Local information
723         centerPosition                    = CalculateCenterPosition(anchorPoint, positionUsesAnchorPoint, size, localScale, localOrientation);
724         Vector3 intermediateLocalPosition = actorPosition + centerPosition + (parentOrigin - Vector3(0.5f, 0.5f, 0.5f)) * parentSize;
725         Matrix  intermediateLocalMatrix;
726         intermediateLocalMatrix.SetTransformComponents(localScale, localOrientation, intermediateLocalPosition);
727
728         // Compute intermediate world information
729         Matrix intermediateWorldMatrix;
730         MatrixUtils::MultiplyTransformMatrix(intermediateWorldMatrix, intermediateLocalMatrix, parentMatrix);
731
732         Vector3    intermediateWorldPosition, intermediateWorldScale;
733         Quaternion intermediateWorldOrientation;
734         intermediateWorldMatrix.GetTransformComponents(intermediateWorldPosition, intermediateWorldOrientation, intermediateWorldScale);
735
736         // Compute final world information
737         Vector3    finalWorldPosition    = intermediateWorldPosition;
738         Vector3    finalWorldScale       = intermediateWorldScale;
739         Quaternion finalWorldOrientation = intermediateWorldOrientation;
740         // worldScale includes the influence of local scale, local rotation, and parent scale.
741         // So, for the final world matrix, if this node inherits its parent scale, use worldScale.
742         // If not, use local scale for the final world matrix.
743         if((inheritanceModeList[i] & INHERIT_SCALE) == 0)
744         {
745           finalWorldScale = localScale;
746         }
747
748         // For the final world matrix, if this node inherits its parent orientation, use worldOrientation.
749         // If not, use local orientation for the final world matrix.
750         if((inheritanceModeList[i] & INHERIT_ORIENTATION) == 0)
751         {
752           finalWorldOrientation = localOrientation;
753         }
754
755         // The final world position of this node is computed as a sum of
756         // parent origin position in world space and relative position of center from parent origin.
757         // If this node doesn't inherit its parent position, simply use the relative position as a final world position.
758         Vector3 localCenterPosition = CalculateCenterPosition(anchorPoint, positionUsesAnchorPoint, size, finalWorldScale, finalWorldOrientation);
759         finalWorldPosition          = actorPosition * finalWorldScale;
760         finalWorldPosition *= finalWorldOrientation;
761         finalWorldPosition += localCenterPosition;
762         if((inheritanceModeList[i] & INHERIT_POSITION) != 0)
763         {
764           Vector4 parentOriginPosition((parentOrigin - Vector3(0.5f, 0.5f, 0.5f)) * parentSize);
765           parentOriginPosition.w = 1.0f;
766           finalWorldPosition += Vector3(parentMatrix * parentOriginPosition);
767         }
768
769         worldMatrix.SetTransformComponents(finalWorldScale, finalWorldOrientation, finalWorldPosition);
770       }
771     }
772     else
773     {
774       localPosition = actorPosition + centerPosition;
775       worldMatrix.SetTransformComponents(localScale, localOrientation, localPosition);
776     }
777   }
778
779   return worldMatrix;
780 }
781
782 Vector4 CalculateActorWorldColor(const Actor& actor)
783 {
784   std::vector<Dali::Actor>     descentList;
785   std::vector<Dali::ColorMode> inheritanceModeList;
786   Dali::Actor                  currentActor(const_cast<Actor*>(&actor));
787   Dali::ColorMode              inheritance = Dali::ColorMode::USE_OWN_MULTIPLY_PARENT_ALPHA;
788   do
789   {
790     inheritance = currentActor.GetProperty<Dali::ColorMode>(Dali::Actor::Property::COLOR_MODE);
791     inheritanceModeList.push_back(inheritance);
792     descentList.push_back(currentActor);
793     currentActor = currentActor.GetParent();
794   } while(inheritance != Dali::ColorMode::USE_OWN_COLOR && currentActor);
795
796   Vector4      worldColor;
797   const size_t descentCount = descentList.size();
798   for(size_t iter = 0u; iter < descentCount; ++iter)
799   {
800     auto i = descentCount - iter - 1u;
801     if(inheritanceModeList[i] == USE_OWN_COLOR || i == descentList.size() - 1)
802     {
803       worldColor = descentList[i].GetProperty<Vector4>(Dali::Actor::Property::COLOR);
804     }
805     else if(inheritanceModeList[i] == USE_OWN_MULTIPLY_PARENT_ALPHA)
806     {
807       Vector4 ownColor = descentList[i].GetProperty<Vector4>(Dali::Actor::Property::COLOR);
808       worldColor       = Vector4(ownColor.r, ownColor.g, ownColor.b, ownColor.a * worldColor.a);
809     }
810     else if(inheritanceModeList[i] == USE_OWN_MULTIPLY_PARENT_COLOR)
811     {
812       Vector4 ownColor = descentList[i].GetProperty<Vector4>(Dali::Actor::Property::COLOR);
813       worldColor *= ownColor;
814     }
815   }
816
817   return worldColor;
818 }
819
820 Quaternion CalculateActorLookAtOrientation(const Actor& actor, Vector3 target, Vector3 up, Vector3 localForward, Vector3 localUp)
821 {
822   Vector3 currentWorldPosition = Dali::Internal::CalculateActorWorldTransform(actor).GetTranslation3();
823
824   Quaternion worldToTarget = GetOrientationFromForwardAndUpVector(target - currentWorldPosition, up);
825   Quaternion worldToLocal  = GetOrientationFromForwardAndUpVector(localForward, localUp);
826
827   // Rotate by this order : Local --> World --> Target
828   Quaternion ret = worldToTarget / worldToLocal;
829
830   // If we inherit orientation, get parent's world orientation, and revert it.
831   if(actor.IsOrientationInherited() && actor.GetParent())
832   {
833     // Get Parent information.
834     Vector3       parentPosition, parentScale;
835     Quaternion    parentOrientation;
836     const Matrix& parentMatrix = Dali::Internal::CalculateActorWorldTransform(*actor.GetParent());
837     parentMatrix.GetTransformComponents(parentPosition, parentOrientation, parentScale);
838
839     ret = ret / parentOrientation;
840   }
841
842   return ret;
843 }
844
845 } // namespace Dali::Internal