1 /*
2 * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #ifndef RENDER_SERVICE_CLIENT_CORE_COMMON_RS_MATRIX3_H
17 #define RENDER_SERVICE_CLIENT_CORE_COMMON_RS_MATRIX3_H
18
19 #define USE_MATH_DEFINES
20 #include <cmath>
21
22 #include "common/rs_macros.h"
23 #include "common/rs_vector2.h"
24 #include "common/rs_vector3.h"
25
26 // column-major order
27 namespace OHOS {
28 namespace Rosen {
29 template<typename T>
30 class Matrix3 {
31 public:
32 static const Matrix3 ZERO;
33 static const Matrix3 IDENTITY;
34 Matrix3();
35 Matrix3(T m00, T m01, T m02, T m10, T m11, T m12, T m20, T m21, T m22);
36
37 Matrix3(const Matrix3& matrix) noexcept = default;
38
39 explicit Matrix3(const T* v);
40
41 ~Matrix3();
42 T Trace() const;
43 static int Index(int row, int col);
44 void SetIdentity();
45 void SetZero();
46 bool IsIdentity() const;
47 Matrix3 Inverse() const;
48 Matrix3 Multiply(const Matrix3& other) const;
49
50 Matrix3 operator+(const Matrix3& other) const;
51 Matrix3 operator-(const Matrix3& other) const;
52 Matrix3 operator-() const;
53 Matrix3 operator*(const Matrix3& other) const;
54 Vector3<T> operator*(const Vector3<T>& other) const;
55 Matrix3 operator*(T scale) const;
56 T* operator[](int col);
57 Matrix3& operator=(const Matrix3& other);
58 Matrix3& operator+=(const Matrix3& other);
59 Matrix3& operator-=(const Matrix3& other);
60 Matrix3& operator*=(const Matrix3& other);
61 Matrix3& operator*=(T scale);
62 bool operator==(const Matrix3& other) const;
63 bool operator!=(const Matrix3& other) const;
64 bool IsNearEqual(const Matrix3& other, T threshold = std::numeric_limits<T>::epsilon()) const;
65 T* GetData();
66 const T* GetConstData() const;
67 T Determinant() const;
68 Matrix3 Transpose() const;
69 Matrix3 Translate(const Vector2<T>& vec) const;
70 Matrix3 Rotate(T angle) const;
71 Matrix3 Rotate(T angle, T pivotx, T pivoty) const;
72 Matrix3 Scale(const Vector2<T>& vec) const;
73 Matrix3 Scale(const Vector2<T>& vec, T pivotx, T pivoty) const;
74 Matrix3 ShearX(T y) const;
75 Matrix3 ShearY(T x) const;
76
77 protected:
78 T data_[9] = { 0 };
79 };
80
81 typedef Matrix3<float> Matrix3f;
82 typedef Matrix3<double> Matrix3d;
83
84 template<typename T>
85 const Matrix3<T> Matrix3<T>::ZERO(0, 0, 0, 0, 0, 0, 0, 0, 0);
86
87 template<typename T>
88 const Matrix3<T> Matrix3<T>::IDENTITY(1, 0, 0, 0, 1, 0, 0, 0, 1);
89
90 template<typename T>
Matrix3()91 Matrix3<T>::Matrix3()
92 {}
93
94 template<typename T>
Matrix3(T m00,T m01,T m02,T m10,T m11,T m12,T m20,T m21,T m22)95 Matrix3<T>::Matrix3(T m00, T m01, T m02, T m10, T m11, T m12, T m20, T m21, T m22)
96 {
97 data_[0] = m00;
98 data_[1] = m01;
99 data_[2] = m02;
100
101 data_[3] = m10;
102 data_[4] = m11;
103 data_[5] = m12;
104
105 data_[6] = m20;
106 data_[7] = m21;
107 data_[8] = m22;
108 }
109
110 template<typename T>
Matrix3(const T * v)111 Matrix3<T>::Matrix3(const T* v)
112 {
113 std::copy_n(v, std::size(data_), data_);
114 }
115
116 template<typename T>
~Matrix3()117 Matrix3<T>::~Matrix3()
118 {}
119
120 template<typename T>
Trace()121 T Matrix3<T>::Trace() const
122 {
123 T rTrace = 0.0;
124 rTrace += data_[0];
125 rTrace += data_[4];
126 rTrace += data_[8];
127 return rTrace;
128 }
129
130 template<typename T>
Index(int row,int col)131 int Matrix3<T>::Index(int row, int col)
132 {
133 return (col * 3) + row;
134 }
135
136 template<typename T>
SetIdentity()137 void Matrix3<T>::SetIdentity()
138 {
139 *this = IDENTITY;
140 }
141
142 template<typename T>
SetZero()143 void Matrix3<T>::SetZero()
144 {
145 *this = ZERO;
146 }
147
148 template<typename T>
IsIdentity()149 bool Matrix3<T>::IsIdentity() const
150 {
151 return (ROSEN_EQ<T>(data_[0], 1.0)) && (ROSEN_EQ<T>(data_[1], 0.0)) && (ROSEN_EQ<T>(data_[2], 0.0)) &&
152 (ROSEN_EQ<T>(data_[3], 0.0)) && (ROSEN_EQ<T>(data_[4], 1.0)) && (ROSEN_EQ<T>(data_[5], 0.0)) &&
153 (ROSEN_EQ<T>(data_[6], 0.0)) && (ROSEN_EQ<T>(data_[7], 0.0)) && (ROSEN_EQ<T>(data_[8], 1.0));
154 }
155
156 template<typename T>
Inverse()157 Matrix3<T> Matrix3<T>::Inverse() const
158 {
159 T det = Determinant();
160 if (ROSEN_EQ<T>(det, 0.0)) {
161 return Matrix3<T>(*this);
162 }
163
164 const T invDet = 1.0f / det;
165 const T* data = data_;
166
167 T iX = invDet * (data[4] * data[8] - data[5] * data[7]);
168 T iY = invDet * (data[2] * data[7] - data[1] * data[8]);
169 T iZ = invDet * (data[1] * data[5] - data[2] * data[4]);
170 T jX = invDet * (data[5] * data[6] - data[3] * data[8]);
171 T jY = invDet * (data[0] * data[8] - data[2] * data[6]);
172 T jZ = invDet * (data[2] * data[3] - data[0] * data[5]);
173 T kX = invDet * (data[3] * data[7] - data[4] * data[6]);
174 T kY = invDet * (data[1] * data[6] - data[0] * data[7]);
175 T kZ = invDet * (data[0] * data[4] - data[1] * data[3]);
176
177 return Matrix3<T>(iX, iY, iZ, jX, jY, jZ, kX, kY, kZ);
178 }
179
180 template<typename T>
Multiply(const Matrix3<T> & other)181 Matrix3<T> Matrix3<T>::Multiply(const Matrix3<T>& other) const
182 {
183 Matrix3<T> rMulti;
184 T* rData = rMulti.data_;
185 const T* oData = other.data_;
186
187 rData[0] = data_[0] * oData[0] + data_[3] * oData[1] + data_[6] * oData[2];
188 rData[3] = data_[0] * oData[3] + data_[3] * oData[4] + data_[6] * oData[5];
189 rData[6] = data_[0] * oData[6] + data_[3] * oData[7] + data_[6] * oData[8];
190
191 rData[1] = data_[1] * oData[0] + data_[4] * oData[1] + data_[7] * oData[2];
192 rData[4] = data_[1] * oData[3] + data_[4] * oData[4] + data_[7] * oData[5];
193 rData[7] = data_[1] * oData[6] + data_[4] * oData[7] + data_[7] * oData[8];
194
195 rData[2] = data_[2] * oData[0] + data_[5] * oData[1] + data_[8] * oData[2];
196 rData[5] = data_[2] * oData[3] + data_[5] * oData[4] + data_[8] * oData[5];
197 rData[8] = data_[2] * oData[6] + data_[5] * oData[7] + data_[8] * oData[8];
198 return rMulti;
199 }
200
201 template<typename T>
202 Matrix3<T> Matrix3<T>::operator+(const Matrix3<T>& other) const
203 {
204 Matrix3<T> rMat3Add;
205 T* rMat3Data = rMat3Add.data_;
206 const T* oData = other.data_;
207
208 rMat3Data[0] = data_[0] + oData[0];
209 rMat3Data[1] = data_[1] + oData[1];
210 rMat3Data[2] = data_[2] + oData[2];
211 rMat3Data[3] = data_[3] + oData[3];
212 rMat3Data[4] = data_[4] + oData[4];
213 rMat3Data[5] = data_[5] + oData[5];
214 rMat3Data[6] = data_[6] + oData[6];
215 rMat3Data[7] = data_[7] + oData[7];
216 rMat3Data[8] = data_[8] + oData[8];
217
218 return rMat3Add;
219 }
220
221 template<typename T>
222 Matrix3<T> Matrix3<T>::operator-(const Matrix3<T>& other) const
223 {
224 return *this + (-other);
225 }
226
227 template<typename T>
228 Matrix3<T> Matrix3<T>::operator-() const
229 {
230 Matrix3<T> rMat3Sub;
231 T* rMat3Data = rMat3Sub.data_;
232
233 rMat3Data[0] = -data_[0];
234 rMat3Data[1] = -data_[1];
235 rMat3Data[2] = -data_[2];
236 rMat3Data[3] = -data_[3];
237 rMat3Data[4] = -data_[4];
238 rMat3Data[5] = -data_[5];
239 rMat3Data[6] = -data_[6];
240 rMat3Data[7] = -data_[7];
241 rMat3Data[8] = -data_[8];
242
243 return rMat3Sub;
244 }
245
246 template<typename T>
247 Matrix3<T> Matrix3<T>::operator*(const Matrix3<T>& other) const
248 {
249 return Multiply(other);
250 }
251
252 template<typename T>
253 Vector3<T> Matrix3<T>::operator*(const Vector3<T>& other) const
254 {
255 Vector3<T> rMulti;
256 T* rData = rMulti.data_;
257 const T* oData = other.data_;
258 rData[0] = data_[0] * oData[0] + data_[3] * oData[1] + data_[6] * oData[2];
259
260 rData[1] = data_[1] * oData[0] + data_[4] * oData[1] + data_[7] * oData[2];
261
262 rData[2] = data_[2] * oData[0] + data_[5] * oData[1] + data_[8] * oData[2];
263 return rMulti;
264 }
265
266 template<typename T>
267 Matrix3<T> Matrix3<T>::operator*(T scale) const
268 {
269 Matrix3<T> rMulti;
270 T* rData = rMulti.data_;
271 rData[0] = data_[0] * scale;
272 rData[1] = data_[1] * scale;
273 rData[2] = data_[2] * scale;
274 rData[3] = data_[3] * scale;
275 rData[4] = data_[4] * scale;
276 rData[5] = data_[5] * scale;
277 rData[6] = data_[6] * scale;
278 rData[7] = data_[7] * scale;
279 rData[8] = data_[8] * scale;
280
281 return rMulti;
282 }
283
284 template<typename T>
285 T* Matrix3<T>::operator[](int col)
286 {
287 return &data_[col * 3];
288 }
289
290 template<typename T>
291 Matrix3<T>& Matrix3<T>::operator=(const Matrix3<T>& other)
292 {
293 const T* oMat3Data = other.data_;
294 // Tell the compiler there is no alias and to select wider load/store
295 // instructions.
296 T data0 = oMat3Data[0];
297 T data1 = oMat3Data[1];
298 T data2 = oMat3Data[2];
299 T data3 = oMat3Data[3];
300 T data4 = oMat3Data[4];
301 T data5 = oMat3Data[5];
302 T data6 = oMat3Data[6];
303 T data7 = oMat3Data[7];
304 T data8 = oMat3Data[8];
305 data_[0] = data0;
306 data_[1] = data1;
307 data_[2] = data2;
308 data_[3] = data3;
309 data_[4] = data4;
310 data_[5] = data5;
311 data_[6] = data6;
312 data_[7] = data7;
313 data_[8] = data8;
314
315 return *this;
316 }
317
318 template<typename T>
319 Matrix3<T>& Matrix3<T>::operator+=(const Matrix3<T>& other)
320 {
321 const T* oData = other.data_;
322
323 data_[0] += oData[0];
324 data_[1] += oData[1];
325 data_[2] += oData[2];
326 data_[3] += oData[3];
327 data_[4] += oData[4];
328 data_[5] += oData[5];
329 data_[6] += oData[6];
330 data_[7] += oData[7];
331 data_[8] += oData[8];
332
333 return *this;
334 }
335
336 template<typename T>
337 Matrix3<T>& Matrix3<T>::operator-=(const Matrix3<T>& other)
338 {
339 const T* oData = other.data_;
340
341 data_[0] -= oData[0];
342 data_[1] -= oData[1];
343 data_[2] -= oData[2];
344 data_[3] -= oData[3];
345 data_[4] -= oData[4];
346 data_[5] -= oData[5];
347 data_[6] -= oData[6];
348 data_[7] -= oData[7];
349 data_[8] -= oData[8];
350
351 return *this;
352 }
353
354 template<typename T>
355 Matrix3<T>& Matrix3<T>::operator*=(const Matrix3<T>& other)
356 {
357 return (*this = *this * other);
358 }
359
360 template<typename T>
361 Matrix3<T>& Matrix3<T>::operator*=(T scale)
362 {
363 data_[0] *= scale;
364 data_[1] *= scale;
365 data_[2] *= scale;
366 data_[3] *= scale;
367 data_[4] *= scale;
368 data_[5] *= scale;
369 data_[6] *= scale;
370 data_[7] *= scale;
371 data_[8] *= scale;
372 return *this;
373 }
374
375 template<typename T>
376 bool Matrix3<T>::operator==(const Matrix3& other) const
377 {
378 const T* oData = other.data_;
379
380 return (ROSEN_EQ<T>(data_[0], oData[0])) && (ROSEN_EQ<T>(data_[1], oData[1])) &&
381 (ROSEN_EQ<T>(data_[2], oData[2])) && (ROSEN_EQ<T>(data_[3], oData[3])) &&
382 (ROSEN_EQ<T>(data_[4], oData[4])) && (ROSEN_EQ<T>(data_[5], oData[5])) &&
383 (ROSEN_EQ<T>(data_[6], oData[6])) && (ROSEN_EQ<T>(data_[7], oData[7])) && (ROSEN_EQ<T>(data_[8], oData[8]));
384 }
385
386 template<typename T>
387 bool Matrix3<T>::operator!=(const Matrix3& other) const
388 {
389 return !operator==(other);
390 }
391
392 template<typename T>
IsNearEqual(const Matrix3 & other,T threshold)393 bool Matrix3<T>::IsNearEqual(const Matrix3& other, T threshold) const
394 {
395 const T* otherData = other.data_;
396 auto result = std::equal(data_, data_ + 8, otherData,
397 [&threshold](const T& left, const T& right) { return ROSEN_EQ<T>(left, right, threshold); });
398 return result;
399 }
400
401 template<typename T>
GetData()402 inline T* Matrix3<T>::GetData()
403 {
404 return data_;
405 }
406
407 template<typename T>
GetConstData()408 const T* Matrix3<T>::GetConstData() const
409 {
410 return data_;
411 }
412
413 template<typename T>
Determinant()414 T Matrix3<T>::Determinant() const
415 {
416 T x = data_[0] * ((data_[4] * data_[8]) - (data_[5] * data_[7]));
417 T y = data_[1] * ((data_[3] * data_[8]) - (data_[5] * data_[6]));
418 T z = data_[2] * ((data_[3] * data_[7]) - (data_[4] * data_[6]));
419 return x - y + z;
420 }
421
422 template<typename T>
Transpose()423 Matrix3<T> Matrix3<T>::Transpose() const
424 {
425 Matrix3<T> rTrans;
426 T* rData = rTrans.data_;
427 rData[0] = data_[0];
428 rData[1] = data_[3];
429 rData[2] = data_[6];
430 rData[3] = data_[1];
431 rData[4] = data_[4];
432 rData[5] = data_[7];
433 rData[6] = data_[2];
434 rData[7] = data_[5];
435 rData[8] = data_[8];
436 return rTrans;
437 }
438
439 template<typename T>
Translate(const Vector2<T> & vec)440 Matrix3<T> Matrix3<T>::Translate(const Vector2<T>& vec) const
441 {
442 Matrix3<T> rTrans(*this);
443 T* rData = rTrans.data_;
444
445 rData[6] = data_[0] * vec[0] + data_[3] * vec[1] + data_[6];
446 rData[7] = data_[1] * vec[0] + data_[4] * vec[1] + data_[7];
447 rData[8] = data_[2] * vec[0] + data_[5] * vec[1] + data_[8];
448 return rTrans;
449 }
450
451 template<typename T>
Rotate(T angle)452 Matrix3<T> Matrix3<T>::Rotate(T angle) const
453 {
454 T a = angle;
455 T c = cos(a);
456 T s = sin(a);
457
458 Matrix3<T> rRotate(*this);
459 T* rData = rRotate.data_;
460 rData[0] = data_[0] * c + data_[3] * s;
461 rData[1] = data_[1] * c + data_[4] * s;
462 rData[2] = data_[2] * c + data_[5] * s;
463
464 rData[3] = data_[0] * -s + data_[3] * c;
465 rData[4] = data_[1] * -s + data_[4] * c;
466 rData[5] = data_[2] * -s + data_[5] * c;
467 return rRotate;
468 }
469
470 template<typename T>
Rotate(T angle,T pivotx,T pivoty)471 Matrix3<T> Matrix3<T>::Rotate(T angle, T pivotx, T pivoty) const
472 {
473 T a = angle;
474 T c = cos(a);
475 T s = sin(a);
476 T dx = s * pivoty + (1 - c) * pivotx;
477 T dy = -s * pivotx + (1 - c) * pivoty;
478
479 Matrix3<T> rRotate(*this);
480 T* rData = rRotate.data_;
481 rData[0] = data_[0] * c + data_[3] * s;
482 rData[1] = data_[1] * c + data_[4] * s;
483 rData[2] = data_[2] * c + data_[5] * s;
484
485 rData[3] = data_[0] * -s + data_[3] * c;
486 rData[4] = data_[1] * -s + data_[4] * c;
487 rData[5] = data_[2] * -s + data_[5] * c;
488
489 rData[6] = data_[0] * dx + data_[3] * dy + data_[6];
490 rData[7] = data_[1] * dx + data_[4] * dy + data_[7];
491 rData[8] = data_[2] * dx + data_[5] * dy + data_[8];
492 return rRotate;
493 }
494
495 template<typename T>
Scale(const Vector2<T> & vec)496 Matrix3<T> Matrix3<T>::Scale(const Vector2<T>& vec) const
497 {
498 Matrix3<T> rScale(*this);
499 T* rData = rScale.data_;
500 rData[0] = data_[0] * vec[0];
501 rData[1] = data_[1] * vec[0];
502 rData[2] = data_[2] * vec[0];
503
504 rData[3] = data_[3] * vec[1];
505 rData[4] = data_[4] * vec[1];
506 rData[5] = data_[5] * vec[1];
507 return rScale;
508 }
509
510 template<typename T>
Scale(const Vector2<T> & vec,T pivotx,T pivoty)511 Matrix3<T> Matrix3<T>::Scale(const Vector2<T>& vec, T pivotx, T pivoty) const
512 {
513 T dx = pivotx - vec[0] * pivotx;
514 T dy = pivoty - vec[1] * pivoty;
515
516 Matrix3<T> rScale(*this);
517 T* rData = rScale.data_;
518 rData[0] = data_[0] * vec[0];
519 rData[1] = data_[1] * vec[0];
520 rData[2] = data_[2] * vec[0];
521
522 rData[3] = data_[3] * vec[1];
523 rData[4] = data_[4] * vec[1];
524 rData[5] = data_[5] * vec[1];
525
526 rData[6] = data_[0] * dx + data_[3] * dy + data_[6];
527 rData[7] = data_[1] * dx + data_[4] * dy + data_[7];
528 rData[8] = data_[2] * dx + data_[5] * dy + data_[8];
529 return rScale;
530 }
531
532 template<typename T>
ShearX(T y)533 Matrix3<T> Matrix3<T>::ShearX(T y) const
534 {
535 Matrix3<T> rShear(Matrix3<T>::IDENTITY);
536 rShear.data_[1] = y;
537 return (*this) * rShear;
538 }
539
540 template<typename T>
ShearY(T x)541 Matrix3<T> Matrix3<T>::ShearY(T x) const
542 {
543 Matrix3<T> rShear(Matrix3<T>::IDENTITY);
544 rShear.data_[3] = x;
545 return (*this) * rShear;
546 }
547 } // namespace Rosen
548 } // namespace OHOS
549 #endif // RENDER_SERVICE_CLIENT_CORE_COMMON_RS_MATRIX3_H
550