// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved. #pragma once #include "Engine/Platform/Platform.h" #include "Vector3.h" #include "Quaternion.h" struct Matrix; /// /// Describes transformation in a 3D space. /// API_STRUCT() struct FLAXENGINE_API Transform { DECLARE_SCRIPTING_TYPE_MINIMAL(Transform); /// /// The translation vector of the transform. /// API_FIELD(Attributes="EditorOrder(10), EditorDisplay(null, \"Position\"), ValueCategory(Utils.ValueCategory.Distance)") Vector3 Translation; /// /// The rotation of the transform. /// API_FIELD(Attributes="EditorOrder(20), EditorDisplay(null, \"Rotation\"), ValueCategory(Utils.ValueCategory.Angle)") Quaternion Orientation; /// /// The scale vector of the transform. /// API_FIELD(Attributes="EditorOrder(30), Limit(float.MinValue, float.MaxValue, 0.01f)") Float3 Scale; public: /// /// An identity transform. /// static Transform Identity; public: /// /// Empty constructor. /// Transform() = default; /// /// Initializes a new instance of the struct. /// /// 3D position Transform(const Vector3& position) : Translation(position) , Orientation(0.0f, 0.0f, 0.0f, 1.0f) , Scale(1.0f) { } /// /// Initializes a new instance of the struct. /// /// 3D position /// Transform rotation Transform(const Vector3& position, const Quaternion& rotation) : Translation(position) , Orientation(rotation) , Scale(1.0f) { } /// /// Initializes a new instance of the struct. /// /// 3D position /// Transform rotation /// Transform scale Transform(const Vector3& position, const Quaternion& rotation, const Float3& scale) : Translation(position) , Orientation(rotation) , Scale(scale) { } Transform(const Vector3& position, const Matrix3x3& rotationScale); public: String ToString() const; public: /// /// Checks if transform is an identity transformation. /// bool IsIdentity() const; /// /// Returns true if transform has one or more components equal to +/- infinity or NaN. /// bool IsNanOrInfinity() const; /// /// Calculates the determinant of this transformation. /// FORCE_INLINE float GetDeterminant() const { return Scale.X * Scale.Y * Scale.Z; } public: /// /// Gets rotation matrix (from Orientation). /// /// Rotation matrix Matrix GetRotation() const; /// /// Gets rotation matrix (from Orientation). /// /// Matrix to set void GetRotation(Matrix& result) const; /// /// Sets rotation matrix (from Orientation). /// /// Rotation matrix void SetRotation(const Matrix& value); /// /// Gets world matrix that describes transformation as a 4 by 4 matrix. /// /// World matrix Matrix GetWorld() const; /// /// Gets world matrix that describes transformation as a 4 by 4 matrix. /// /// World matrix void GetWorld(Matrix& result) const; /// /// Gets world matrix that describes transformation as a 4 by 4 matrix. /// /// World matrix void GetWorld(Double4x4& result) const; public: /// /// Adds translation to this transform. /// /// The translation. /// The result. Transform Add(const Vector3& translation) const; /// /// Adds transformation to this transform. /// /// The other transformation. /// The sum of two transformations. Transform Add(const Transform& other) const; /// /// Subtracts transformation from this transform. /// /// The other transformation. /// The different of two transformations. Transform Subtract(const Transform& other) const; /// /// Performs transformation of the given transform in local space to the world space of this transform. /// /// The local space transformation. /// The world space transformation. Transform LocalToWorld(const Transform& other) const { Transform result; LocalToWorld(other, result); return result; } /// /// Performs transformation of the given transform in local space to the world space of this transform. /// /// The local space transformation. /// The world space transformation. void LocalToWorld(const Transform& other, Transform& result) const; /// /// Performs transformation of the given point in local space to the world space of this transform. /// /// The local space point. /// The world space point. Vector3 LocalToWorld(const Vector3& point) const { Vector3 result; LocalToWorld(point, result); return result; } /// /// Performs transformation of the given vector in local space to the world space of this transform. /// /// The local space vector. /// The world space vector. void LocalToWorldVector(const Vector3& vector, Vector3& result) const; /// /// Performs transformation of the given vector in local space to the world space of this transform. /// /// The local space vector. /// The world space vector. Vector3 LocalToWorldVector(const Vector3& vector) const { Vector3 result; LocalToWorldVector(vector, result); return result; } /// /// Performs transformation of the given point in local space to the world space of this transform. /// /// The local space point. /// The world space point. void LocalToWorld(const Vector3& point, Vector3& result) const; /// /// Performs transformation of the given transform in local space to the world space of this transform. /// /// The world space transformation. /// The local space transformation. Transform WorldToLocal(const Transform& other) const { Transform result; WorldToLocal(other, result); return result; } /// /// Performs transformation of the given transform in world space to the local space of this transform. /// /// The world space transformation. /// The local space transformation. void WorldToLocal(const Transform& other, Transform& result) const; /// /// Performs transformation of the given point in world space to the local space of this transform. /// /// The world space point. /// The local space point. void WorldToLocal(const Vector3& point, Vector3& result) const; /// /// Performs transformation of the given point in world space to the local space of this transform. /// /// The world space point. /// The local space point. Vector3 WorldToLocal(const Vector3& point) const { Vector3 result; WorldToLocal(point, result); return result; } /// /// Performs transformation of the given vector in world space to the local space of this transform. /// /// The world space vector. /// The local space vector. void WorldToLocalVector(const Vector3& vector, Vector3& result) const; /// /// Performs transformation of the given vector in world space to the local space of this transform. /// /// The world space vector. /// The local space vector. Vector3 WorldToLocalVector(const Vector3& vector) const { Vector3 result; WorldToLocalVector(vector, result); return result; } /// /// Performs transformation of the given rotation in world space to the local space of this transform. /// /// The world space rotation. /// The local space rotation. void WorldToLocal(const Quaternion& rotation, Quaternion& result) const; /// /// Performs transformation of the given rotation in world space to the local space of this transform. /// /// The world space rotation. /// The local space rotation. Quaternion WorldToLocal(const Quaternion& rotation) const { Quaternion result; WorldToLocal(rotation, result); return result; } /// /// Combines the functions:
/// ,
/// . ///
/// The position to snap. /// The size of the grid. /// The local grid offset to apply after snapping. /// The normal vector. /// The relative transform. /// The scale to apply to the transform. /// The rotated and snapped transform. static Transform AlignRotationToNormalAndSnapToGrid(const Vector3& point, const Vector3& normal, const Vector3& normalOffset, const Transform& relativeTo, const Vector3& gridSize, const Float3& scale = Float3::One); public: FORCE_INLINE Transform operator*(const Transform& other) const { return LocalToWorld(other); } FORCE_INLINE Transform operator+(const Transform& other) const { return Add(other); } FORCE_INLINE Transform operator-(const Transform& other) const { return Subtract(other); } FORCE_INLINE Transform operator+(const Vector3& other) const { return Add(other); } FORCE_INLINE bool operator==(const Transform& other) const { return Translation == other.Translation && Orientation == other.Orientation && Scale == other.Scale; } FORCE_INLINE bool operator!=(const Transform& other) const { return Translation != other.Translation || Orientation != other.Orientation || Scale != other.Scale; } static bool NearEqual(const Transform& a, const Transform& b) { return Vector3::NearEqual(a.Translation, b.Translation) && Quaternion::NearEqual(a.Orientation, b.Orientation) && Float3::NearEqual(a.Scale, b.Scale); } static bool NearEqual(const Transform& a, const Transform& b, float epsilon) { return Vector3::NearEqual(a.Translation, b.Translation, epsilon) && Quaternion::NearEqual(a.Orientation, b.Orientation, epsilon) && Float3::NearEqual(a.Scale, b.Scale, epsilon); } public: Float3 GetRight() const; Float3 GetLeft() const; Float3 GetUp() const; Float3 GetDown() const; Float3 GetForward() const; Float3 GetBackward() const; public: static Transform Lerp(const Transform& t1, const Transform& t2, float amount); static void Lerp(const Transform& t1, const Transform& t2, float amount, Transform& result); }; namespace Math { FORCE_INLINE static bool NearEqual(const Transform& a, const Transform& b) { return Transform::NearEqual(a, b); } } template<> struct TIsPODType { enum { Value = true }; }; DEFINE_DEFAULT_FORMATTING(Transform, "Translation:{0} Orientation:{1} Scale:{2}", v.Translation, v.Orientation, v.Scale);