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