[dali_2.3.33] Merge branch 'devel/master'
[platform/core/uifw/dali-core.git] / dali / public-api / math / matrix3.cpp
1 /*
2  * Copyright (c) 2022 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
18 // CLASS HEADER
19 #include <dali/public-api/math/matrix3.h>
20
21 // EXTERNAL INCLUDES
22 #include <cstdint> // uint32_t
23 #include <cstring> // memcpy
24 #include <ostream>
25
26 // INTERNAL INCLUDES
27 #include <dali/internal/common/matrix-utils.h>
28 #include <dali/public-api/math/math-utils.h>
29
30 #define S00 0
31 #define S01 1
32 #define S02 2
33 #define S10 3
34 #define S11 4
35 #define S12 5
36 #define S20 6
37 #define S21 7
38 #define S22 8
39
40 /*
41  * S00 S10 S20
42  * S01 S11 S21
43  * S02 S12 S22
44  */
45
46 namespace
47 {
48 const uint32_t NUM_BYTES_IN_ROW    = 3 * sizeof(float);
49 const uint32_t NUM_BYTES_IN_MATRIX = 9 * sizeof(float);
50 } // namespace
51
52 namespace Dali
53 {
54 const Matrix3 Matrix3::IDENTITY(1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f);
55
56 Matrix3::Matrix3()
57 {
58   float* m = AsFloat();
59   memset(m, 0, NUM_BYTES_IN_MATRIX);
60 }
61
62 Matrix3::Matrix3(const Matrix3& m)
63 {
64   memcpy(mElements, m.mElements, NUM_BYTES_IN_MATRIX);
65 }
66
67 Matrix3::Matrix3(const Matrix& matrix)
68 {
69   const float* m4 = matrix.AsFloat();
70   memcpy(&mElements[S00], m4, NUM_BYTES_IN_ROW);
71   memcpy(&mElements[S10], m4 + 4, NUM_BYTES_IN_ROW);
72   memcpy(&mElements[S20], m4 + 8, NUM_BYTES_IN_ROW);
73 }
74
75 Matrix3::Matrix3(float s00, float s01, float s02, float s10, float s11, float s12, float s20, float s21, float s22)
76 {
77   mElements[S00] = s00;
78   mElements[S01] = s01;
79   mElements[S02] = s02;
80   mElements[S10] = s10;
81   mElements[S11] = s11;
82   mElements[S12] = s12;
83   mElements[S20] = s20;
84   mElements[S21] = s21;
85   mElements[S22] = s22;
86 }
87
88 void Matrix3::SetIdentity()
89 {
90   memset(mElements, 0, NUM_BYTES_IN_MATRIX);
91   mElements[S00] = 1.0f;
92   mElements[S11] = 1.0f;
93   mElements[S22] = 1.0f;
94 }
95
96 Matrix3::Matrix3(Matrix3&& matrix) noexcept
97 {
98   memcpy(mElements, matrix.mElements, NUM_BYTES_IN_MATRIX);
99 }
100
101 Matrix3& Matrix3::operator=(Matrix3&& matrix) noexcept
102 {
103   if(this != &matrix)
104   {
105     memcpy(AsFloat(), matrix.AsFloat(), NUM_BYTES_IN_MATRIX);
106   }
107   return *this;
108 }
109
110 Matrix3& Matrix3::operator=(const Matrix3& matrix)
111 {
112   // no point copying if self assigning
113   if(this != &matrix)
114   {
115     memcpy(AsFloat(), matrix.AsFloat(), NUM_BYTES_IN_MATRIX);
116   }
117   return *this;
118 }
119
120 Matrix3& Matrix3::operator=(const Matrix& matrix)
121 {
122   const float* m4 = matrix.AsFloat();
123   memcpy(&mElements[S00], m4, NUM_BYTES_IN_ROW);
124   memcpy(&mElements[S10], m4 + 4, NUM_BYTES_IN_ROW);
125   memcpy(&mElements[S20], m4 + 8, NUM_BYTES_IN_ROW);
126   return *this;
127 }
128
129 bool Matrix3::Invert()
130 {
131   bool succeeded = false;
132
133   float cof[9];
134   cof[S00] = (mElements[S11] * mElements[S22] - mElements[S12] * mElements[S21]);
135   cof[S01] = (mElements[S02] * mElements[S21] - mElements[S01] * mElements[S22]);
136   cof[S02] = (mElements[S01] * mElements[S12] - mElements[S02] * mElements[S11]);
137
138   cof[S10] = (mElements[S12] * mElements[S20] - mElements[S10] * mElements[S22]);
139   cof[S11] = (mElements[S00] * mElements[S22] - mElements[S02] * mElements[S20]);
140   cof[S12] = (mElements[S02] * mElements[S10] - mElements[S00] * mElements[S12]);
141
142   cof[S20] = (mElements[S10] * mElements[S21] - mElements[S11] * mElements[S20]);
143   cof[S21] = (mElements[S01] * mElements[S20] - mElements[S00] * mElements[S21]);
144   cof[S22] = (mElements[S00] * mElements[S11] - mElements[S01] * mElements[S10]);
145
146   float det = mElements[S00] * cof[S00] + mElements[S01] * cof[S10] + mElements[S02] * cof[S20];
147
148   // In the case where the determinant is exactly zero, the matrix is non-invertible
149   if(!EqualsZero(det))
150   {
151     det = 1.0f / det;
152     for(int32_t i = 0; i < 9; i++)
153     {
154       mElements[i] = cof[i] * det;
155     }
156     succeeded = true;
157   }
158   return succeeded;
159 }
160
161 bool Matrix3::Transpose()
162 {
163   float tmp;
164   tmp            = mElements[S01];
165   mElements[S01] = mElements[S10];
166   mElements[S10] = tmp;
167   tmp            = mElements[S02];
168   mElements[S02] = mElements[S20];
169   mElements[S20] = tmp;
170   tmp            = mElements[S21];
171   mElements[S21] = mElements[S12];
172   mElements[S12] = tmp;
173   return true;
174 }
175
176 bool Matrix3::ScaledInverseTranspose()
177 {
178   bool succeeded = false;
179
180   float cof[9];
181   cof[S00] = (mElements[S11] * mElements[S22] - mElements[S12] * mElements[S21]);
182   cof[S01] = (mElements[S02] * mElements[S21] - mElements[S01] * mElements[S22]);
183   cof[S02] = (mElements[S01] * mElements[S12] - mElements[S02] * mElements[S11]);
184
185   cof[S10] = (mElements[S12] * mElements[S20] - mElements[S10] * mElements[S22]);
186   cof[S11] = (mElements[S00] * mElements[S22] - mElements[S02] * mElements[S20]);
187   cof[S12] = (mElements[S02] * mElements[S10] - mElements[S00] * mElements[S12]);
188
189   cof[S20] = (mElements[S10] * mElements[S21] - mElements[S11] * mElements[S20]);
190   cof[S21] = (mElements[S01] * mElements[S20] - mElements[S00] * mElements[S21]);
191   cof[S22] = (mElements[S00] * mElements[S11] - mElements[S01] * mElements[S10]);
192
193   float det = mElements[S00] * cof[S00] + mElements[S01] * cof[S10] + mElements[S02] * cof[S20];
194
195   // In the case where the determinant is exactly zero, the matrix is non-invertible
196   if(!EqualsZero(det))
197   {
198     // Use average rather than determinant to remove rounding to zero errors in further multiplication
199     float sum = 0;
200     for(uint32_t i = 0; i < 9; i++)
201     {
202       sum += fabsf(cof[i]);
203     }
204     float scale = 9.0f / sum; // Inverse of the average values
205     if(det < 0)
206     {
207       // Ensure the signs of the inverse are correct
208       scale = -scale;
209     }
210
211     mElements[S00] = cof[S00] * scale;
212     mElements[S01] = cof[S10] * scale;
213     mElements[S02] = cof[S20] * scale;
214
215     mElements[S10] = cof[S01] * scale;
216     mElements[S11] = cof[S11] * scale;
217     mElements[S12] = cof[S21] * scale;
218
219     mElements[S20] = cof[S02] * scale;
220     mElements[S21] = cof[S12] * scale;
221     mElements[S22] = cof[S22] * scale;
222
223     succeeded = true;
224   }
225   return succeeded;
226 }
227
228 void Matrix3::Scale(float scale)
229 {
230   mElements[S00] *= scale;
231   mElements[S01] *= scale;
232   mElements[S02] *= scale;
233   mElements[S10] *= scale;
234   mElements[S11] *= scale;
235   mElements[S12] *= scale;
236   mElements[S20] *= scale;
237   mElements[S21] *= scale;
238   mElements[S22] *= scale;
239 }
240
241 float Matrix3::Magnitude() const
242 {
243   float avg = 0;
244   for(uint32_t i = 0; i < 9; i++)
245   {
246     avg += fabsf(mElements[i]);
247   }
248   return avg / 3.0f;
249 }
250
251 void Matrix3::Multiply(Matrix3& result, const Matrix3& lhs, const Matrix3& rhs)
252 {
253   Internal::MatrixUtils::Multiply(result, lhs, rhs);
254 }
255
256 Matrix3 Matrix3::operator*(const Matrix3& rhs) const
257 {
258   Matrix3 result;
259   Internal::MatrixUtils::Multiply(result, rhs, *this);
260   return result;
261 }
262
263 Matrix3& Matrix3::operator*=(const Matrix3& rhs)
264 {
265   Internal::MatrixUtils::MultiplyAssign(*this, rhs);
266   return *this;
267 }
268
269 Vector3 Matrix3::operator*(const Vector3& rhs) const
270 {
271   return Vector3(rhs.x * mElements[S00] + rhs.y * mElements[S10] + rhs.z * mElements[S20],
272                  rhs.x * mElements[S01] + rhs.y * mElements[S11] + rhs.z * mElements[S21],
273                  rhs.x * mElements[S02] + rhs.y * mElements[S12] + rhs.z * mElements[S22]);
274 }
275
276 bool Matrix3::operator==(const Matrix3& rhs) const
277 {
278   return (
279     Equals(mElements[0], rhs.mElements[0]) &&
280     Equals(mElements[1], rhs.mElements[1]) &&
281     Equals(mElements[2], rhs.mElements[2]) &&
282     Equals(mElements[3], rhs.mElements[3]) &&
283     Equals(mElements[4], rhs.mElements[4]) &&
284     Equals(mElements[5], rhs.mElements[5]) &&
285     Equals(mElements[6], rhs.mElements[6]) &&
286     Equals(mElements[7], rhs.mElements[7]) &&
287     Equals(mElements[8], rhs.mElements[8]));
288 }
289
290 bool Matrix3::operator!=(const Matrix3& rhs) const
291 {
292   return !(*this == rhs);
293 }
294
295 std::ostream& operator<<(std::ostream& o, const Matrix3& matrix)
296 {
297   return o << "[ " << matrix.mElements[0] << ", " << matrix.mElements[1] << ", " << matrix.mElements[2] << ", "
298            << matrix.mElements[3] << ", " << matrix.mElements[4] << ", " << matrix.mElements[5] << ", "
299            << matrix.mElements[6] << ", " << matrix.mElements[7] << ", " << matrix.mElements[8] << " ]";
300 }
301
302 } // namespace Dali