Make LookAt API for common Actor.
Note, this isn't follow target position. Just calculate Quaternion
and apply instancely.
Change-Id: I0fb107f954034fb5aa410cc607122b4e61988e9b
Signed-off-by: Eunki, Hong <eunkiki.hong@samsung.com>
END_TEST;
}
+
+int UtcDaliActorCalculateLookAt(void)
+{
+ TestApplication application;
+
+ tet_infoline("Test that actor rotate right value of orientation");
+
+ Actor actor = Actor::New();
+
+ actor[Actor::Property::POSITION] = Vector3(100.0f, 0.0f, 0.0f);
+ actor[Actor::Property::ANCHOR_POINT] = AnchorPoint::CENTER;
+ actor[Actor::Property::PARENT_ORIGIN] = ParentOrigin::CENTER;
+
+ application.GetScene().Add(actor);
+
+ application.SendNotification();
+ application.Render(0);
+
+ Quaternion actorQuaternion;
+
+ tet_printf("Test with target only\n");
+ Dali::DevelActor::LookAt(actor, Vector3::ZERO);
+ actorQuaternion = actor.GetProperty<Quaternion>(Actor::Property::ORIENTATION);
+ DALI_TEST_EQUALS(actorQuaternion, Quaternion(Radian(Degree(90.0f)), Vector3::NEGATIVE_YAXIS), TEST_LOCATION);
+
+ tet_printf("Test with target + up\n");
+ Dali::DevelActor::LookAt(actor, Vector3::ZERO, Vector3::ZAXIS);
+ actorQuaternion = actor.GetProperty<Quaternion>(Actor::Property::ORIENTATION);
+ DALI_TEST_EQUALS(actorQuaternion, Quaternion(Radian(Degree(90.0f)), Vector3::XAXIS) * Quaternion(Radian(Degree(90.0f)), Vector3::NEGATIVE_YAXIS), TEST_LOCATION);
+
+ tet_printf("Test with target + up + localForward\n");
+ Dali::DevelActor::LookAt(actor, Vector3::ZERO, Vector3::NEGATIVE_YAXIS, Vector3::NEGATIVE_XAXIS);
+ actorQuaternion = actor.GetProperty<Quaternion>(Actor::Property::ORIENTATION);
+ DALI_TEST_EQUALS(actorQuaternion, Quaternion(Radian(Degree(180.0f)), Vector3::XAXIS), TEST_LOCATION);
+
+ tet_printf("Test with target + up + localForward + localUp\n");
+ Dali::DevelActor::LookAt(actor, Vector3::ZERO, Vector3::NEGATIVE_YAXIS, Vector3::NEGATIVE_YAXIS, Vector3::XAXIS);
+ actorQuaternion = actor.GetProperty<Quaternion>(Actor::Property::ORIENTATION);
+ DALI_TEST_EQUALS(actorQuaternion, Quaternion(Radian(Degree(90.0f)), Vector3::NEGATIVE_ZAXIS), TEST_LOCATION);
+
+ // Reset quaternion
+ actor[Actor::Property::ORIENTATION] = Quaternion();
+
+ Actor actor2 = Actor::New();
+ actor2[Actor::Property::POSITION] = Vector3(0.0f, 50.0f, -10.0f);
+ actor2[Actor::Property::ANCHOR_POINT] = AnchorPoint::CENTER;
+ actor2[Actor::Property::PARENT_ORIGIN] = ParentOrigin::CENTER;
+ actor.Add(actor2);
+
+ tet_printf("Test whether lookat calculate well by using event side values only\n");
+ Dali::DevelActor::LookAt(actor2, Vector3(100.0f, 50.0f, 1.0f));
+ actorQuaternion = actor2.GetProperty<Quaternion>(Actor::Property::ORIENTATION);
+ DALI_TEST_EQUALS(actorQuaternion, Quaternion(), TEST_LOCATION);
+
+ actor[Actor::Property::ORIENTATION] = Quaternion(Radian(Degree(90.0f)), Vector3::ZAXIS);
+
+ DALI_TEST_EQUALS(Dali::DevelActor::GetWorldTransform(actor2).GetTranslation3(), Vector3(50.0f, 0.0f, -10.0f), TEST_LOCATION);
+
+ tet_printf("Test whether lookat calculate well inherit by parent orientation\n");
+ Dali::DevelActor::LookAt(actor2, Vector3(50.0f, 0.0f, 1.0f), Vector3::NEGATIVE_XAXIS);
+ actorQuaternion = actor2.GetProperty<Quaternion>(Actor::Property::ORIENTATION);
+ DALI_TEST_EQUALS(actorQuaternion, Quaternion(), TEST_LOCATION);
+
+ END_TEST;
+}
\ No newline at end of file
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
return CalculateActorWorldColor(GetImplementation(actor));
}
+void LookAt(Actor actor, Vector3 target, Vector3 up, Vector3 localForward, Vector3 localUp)
+{
+ auto orientation = CalculateActorLookAtOrientation(GetImplementation(actor), target, up, localForward, localUp);
+ GetImplementation(actor).SetOrientation(orientation);
+}
+
} // namespace DevelActor
} // namespace Dali
#define DALI_ACTOR_DEVEL_H
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*/
DALI_CORE_API Vector4 GetWorldColor(Actor actor);
+/**
+ * Rotate the actor look at specific position.
+ * It will change the actor's orientation property.
+ *
+ * This calculates the world transform from scratch using only event
+ * side properties - it does not rely on the update thread to have
+ * already calculated the transform.
+ *
+ * @note Target position should be setup by world coordinates.
+ * @note The result of invalid input is not determined.
+ * (ex : forward vector or actor-to-target vector has same direction with up, One of them is ZERO)
+ *
+ * @param[in] actor The actor for which to calculate the look at orientation.
+ * @param[in] target The target world position to look at.
+ * @param[in] up The up vector after target look at. Default is +Y axis.
+ * @param[in] localForward The forward vector of actor when it's orientation is not applied. Default is +Z axis.
+ * @param[in] localUp The up vector of actor when it's orientation is not applied. Default is +Y axis.
+ */
+DALI_CORE_API void LookAt(Actor actor, Vector3 target, Vector3 up = Vector3::YAXIS, Vector3 localForward = Vector3::ZAXIS, Vector3 localUp = Vector3::YAXIS);
+
} // namespace DevelActor
} // namespace Dali
}
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);
+}
} // namespace
bool ConvertScreenToLocal(
const Matrix& viewMatrix,
return worldColor;
}
+Quaternion CalculateActorLookAtOrientation(const Actor& actor, Vector3 target, Vector3 up, Vector3 localForward, Vector3 localUp)
+{
+ Vector3 currentWorldPosition = 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 = CalculateActorWorldTransform(*actor.GetParent());
+ parentMatrix.GetTransformComponents(parentPosition, parentOrientation, parentScale);
+
+ ret = ret / parentOrientation;
+ }
+
+ return ret;
+}
+
} // namespace Dali::Internal
#define DALI_INTERNAL_EVENT_ACTORS_ACTOR_COORDS_H
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*/
Vector4 CalculateActorWorldColor(const Actor& actor);
+/**
+ * @brief Get the rotate of the actor look at specific position.
+ *
+ * @param[in] actor The actor for which to calculate the look at orientation.
+ * @param[in] target The target world position to look at.
+ * @param[in] up The up vector after target look at.
+ * @param[in] localForward The forward vector of actor when it's orientation is not applied.
+ * @param[in] localUp The up vector of actor when it's orientation is not applied.
+ * @return The orientation result of this lookAt result.
+ */
+Quaternion CalculateActorLookAtOrientation(const Actor& actor, Vector3 target, Vector3 up, Vector3 localForward, Vector3 localUp);
+
} // namespace Dali::Internal
#endif // DALI_INTERNAL_EVENT_ACTORS_ACTOR_COORDS_H