File size: 7,849 Bytes
a550c4e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
/*
 * SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
 * SPDX-License-Identifier: Apache-2.0
 */

#pragma once

#include "Matrix.h"

namespace Math
{
    //
    // VQS Transform
    //

    class Transform
    {
    public:

        static Transform const Identity;

        static Transform FromRotation(const Quaternion& rotation);
        static Transform FromTranslation(const Vector& translation);
        static Transform FromScale(float uniformScale);
        static Transform FromTranslationAndScale(const Vector& translation, float uniformScale);
        static Transform FromRotationBetweenVectors(const Vector sourceVector, const Vector targetVector);

        // Linearly interpolate between two transforms - uses NLerp for rotations
        static Transform Lerp(const Transform& from, const Transform& to, float t);

        // Spherically interpolate between two transforms - uses SLerp for rotations
        static Transform Slerp(const Transform& from, const Transform& to, float t);

        // Spherically interpolate between two transforms - uses FastSLerp (SLerp approximation) for rotations
        static Transform FastSlerp(const Transform& from, const Transform& to, float t);

        // Calculate a delta transform that you can concatenate to the
        // 'from' transform to get the 'to' transform. Properly handles the non-uniform scaling case.
        static Transform Delta(const Transform& from, const Transform& to);

        // Calculates a delta transform that you can concatenate to the
        // 'from' transform to get the 'to' transform (ignoring scale)
        static Transform DeltaNoScale(const Transform& from, const Transform& to);

        static void DirectlySetRotation(Transform& transform, Quaternion&& rotation);
        static void DirectlySetRotation(Transform& transform, const Quaternion& rotation);
        static void DirectlySetTranslationScale(Transform& transform, Vector&& translationScale);
        static void DirectlySetTranslationScale(Transform& transform, const Vector& translationScale);

    public:

        Transform() = default;

        explicit Transform(NoInit_t);
        explicit Transform(const Matrix& m);
        explicit Transform(
            const Quaternion& rotation,
                const Vector& translation = Vector(0, 0, 0, 0),
                    float scale = 1.0f);
        explicit Transform(const AxisAngle& rotation);

        Matrix ToMatrix() const;
        Matrix ToMatrixNoScale() const;
        EulerAngles ToEulerAngles() const;

        Vector GetAxisX() const;
        Vector GetAxisY() const;
        Vector GetAxisZ() const;

        Vector GetRightVector() const;
        Vector GetForwardVector() const;
        Vector GetUpVector() const;

        bool IsIdentity() const;
        bool IsRigidTransform() const;
        void MakeRigidTransform();

        //
        // Inverse and Deltas
        //

        // Invert this transform.
        // If you want a delta transform that you can
        // concatenate, then you should use the 'Delta' functions
        Transform& Inverse();

        // Get the inverse of this transform.
        // If you want a delta transform that you can
        // concatenate, then you should use the 'Delta' functions
        Transform GetInverse() const;

        // Return the delta required to a given target
        // transform (i.e., what do we need to add to reach that transform)
        Transform GetDeltaToOther(const Transform& targetTransform) const;

        // Return the delta relative from a given a start
        // transform (i.e., how much do we differ from it)
        Transform GetDeltaFromOther(const Transform& startTransform) const;

        //
        // Rotation

        const Quaternion& GetRotation() const;
        void SetRotation(const Quaternion& rotation);
        void AddRotation(const Quaternion& delta);

        //
        // Translation
        //

        // Get the translation for this transform
        // NOTE: you cannot rely on the W value as that will be the scale
        const Vector& GetTranslation() const;

        // Get the translation and scale for this transform
        const Vector& GetTranslationAndScale() const;

        // Set the translation
        void SetTranslation(const Vector& newTranslation);

        // Set the translation and scale simultaneously
        void SetTranslationAndScale(const Vector& newTranslationScale);

        // Add an offset to the current translation
        void AddTranslation(const Vector& translationDelta);

        // Get the translation as a homogeneous coordinates' vector (W=0)
        Vector GetTranslationAsVector() const;

        // Get the translation as a homogeneous coordinates' point (W=1)
        Vector GetTranslationAsPoint() const;

        //
        // Scale
        //

        float GetScale() const;
        Vector GetScaleVector() const;
        Vector GetInverseScaleVector() const;
        void SetScale(float uniformScale);
        bool HasScale() const;
        bool HasNegativeScale() const;

        // This function will sanitize the scale values to remove any
        // trailing values from scale factors i.e. 1.000000012 will be converted to 1
        // This is primarily needed in import steps where scale values
        // might be sampled from curves or have multiple conversions applied resulting in variance.
        void SanitizeScaleValue();

        //
        // Transformations
        //

        Vector TranslateVector(const Vector& vector) const;
        Vector ScaleVector(const Vector& vector) const;
        Vector TransformPoint(const Vector& vector) const;
        Vector TransformPointNoScale(const Vector& vector) const;

        // Rotate a vector (same as TransformVectorNoScale)
        Vector RotateVector(const Vector& vector) const;

        // Rotate a vector (same as TransformVectorNoScale)
        Vector TransformNormal(const Vector& vector) const;

        // Unrotate a vector (same as InverseTransformVectorNoScale)
        Vector InverseRotateVector(const Vector& vector) const;

        // Invert the operation order when doing inverse transformation: first translation then rotation then scale
        Vector InverseTransformPoint(const Vector& point) const;

        // Invert the operation order when doing inverse transformation: first translation then rotation
        Vector InverseTransformPointNoScale(const Vector& point) const;

        // Applies scale and rotation to a vector (no translation)
        Vector TransformVector(const Vector& vector) const;

        // Rotate a vector
        Vector TransformVectorNoScale(const Vector& vector) const;

        // Invert the operation order when performing inverse transformation: first rotation then scale
        Vector InverseTransformVector(const Vector& vector) const;

        // Unrotate a vector
        Vector InverseTransformVectorNoScale(const Vector& vector) const;

        // WARNING: The results from multiplying transforms with shear or skew is ill-defined
        Transform operator*(const Transform& rhs) const;

        // WARNING: The results from multiplying transforms with shear or skew is ill-defined
        Transform& operator*=(const Transform& rhs);

        //
        // Operators
        //

        bool IsNearEqual(
            const Transform& rhs,
                const Radians angleThreshold = Math::DegreesToRadians,
                    float translationScaleThreshold = Math::Epsilon) const;

        // Exact equality
        bool operator==(const Transform& rhs) const;

        bool operator!=(const Transform& rhs) const;

    private:

        Quaternion m_rotation = Quaternion(0, 0, 0, 1);
        Vector m_translationScale = Vector(0, 0, 0, 1);
    };
}

#include "Transform.inl"