1 /*
2 * Copyright (c) 2020-2021 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 /**
17 * @addtogroup UI_Utils
18 * @{
19 *
20 * @brief Defines basic UI utils.
21 *
22 * @since 1.0
23 * @version 1.0
24 */
25
26 /**
27 * @file graphic_math.h
28 *
29 * @brief Defines mathematical operation functions and types, including trigonometric functions, two-dimensional
30 * vectors, three-dimensional vectors, and matrices.
31 *
32 * @since 1.0
33 * @version 1.0
34 */
35
36 #ifndef GRAPHIC_LITE_GRAPHIC_MATH_H
37 #define GRAPHIC_LITE_GRAPHIC_MATH_H
38
39 #include "gfx_utils/heap_base.h"
40 #include <cstdint>
41
42 namespace OHOS {
43 /**
44 * @brief Larger of a and b.
45 */
46 #define MATH_MAX(a, b) ((a) > (b) ? (a) : (b))
47 /**
48 * @brief Smaller of a and b.
49 */
50 #define MATH_MIN(a, b) ((a) < (b) ? (a) : (b))
51 /**
52 * @brief Absolute value of x.
53 */
54 #define MATH_ABS(x) ((x) > 0 ? (x) : (-(x)))
55 /**
56 * @brief Difference between a and b.
57 */
58 #define MATH_MINUS(a, b) ((a) < (b) ? ((b) - (a)) : ((a) - (b)))
59
60 #define MATH_ROUND(x) ((x) > 0 ? (int16_t)((x) + 0.5f) : (int16_t)((x) - 0.5f))
61
62 #define MATH_ROUND32(x) ((x) > 0 ? (int32_t)((x) + 0.5f) : (int32_t)((x) - 0.5f))
63
64 #define MATH_UROUND MATH_ROUND32
65
66 #define MATH_FLT_EQUAL(a, b) (MATH_ABS((a) - (b)) <= UI_FLT_EPSILON)
67
68 /** A quarter of a rotation: 90 degrees */
69 static constexpr uint16_t QUARTER_IN_DEGREE = 90;
70 /** A half of a rotation: 180 degrees */
71 static constexpr uint16_t SEMICIRCLE_IN_DEGREE = 180;
72 /** Three fourths of a rotation: 270 degrees */
73 static constexpr uint16_t THREE_QUARTER_IN_DEGREE = 270;
74 /** A full rotation: 360 degrees */
75 static constexpr uint16_t CIRCLE_IN_DEGREE = 360;
76 /** Pi value */
77 static constexpr double UI_PI = 3.14159265358979;
78 static constexpr float ATAN2_P3 = -0.3258775;
79 static constexpr float ATAN2_P5 = 0.1556117;
80 static constexpr float ATAN2_P7 = -0.0443360;
81 static constexpr float RADIAN_TO_ANGLE = 57.295779513;
82 static constexpr float UI_FLT_EPSILON = 1E-5;
83 static constexpr int16_t ORDER_MATRIX_4 = 4;
84
85 float Sin(float angle);
86 float Cos(float angle);
87 float Acos(float value);
88 float Fmod(float x, float y);
89 uint16_t FastAtan2(int16_t x, int16_t y);
90 float FastAtan2F(float x, float y);
91 float Sqrt(float x);
92
93 /**
94 * @brief Defines the two-dimensional vector, and provides basic mathematical operations such as vector assignment,
95 * scalar product, cross product, addition, and subtraction.
96 *
97 * @since 1.0
98 * @version 1.0
99 */
100 template<typename T>
101 class Vector2 : public HeapBase {
102 public:
103 /**
104 * @brief A constructor used to create a <b>Vector2</b> instance.
105 *
106 * @since 1.0
107 * @version 1.0
108 */
Vector2()109 Vector2() : x_(0), y_(0) {}
110
111 /**
112 * @brief A constructor used to create a <b>Vector2</b> instance based on the X and Y coordinates.
113 * @param x Indicates the X coordinate.
114 * @param y Indicates the Y coordinate.
115 * @since 1.0
116 * @version 1.0
117 */
Vector2(T x,T y)118 Vector2(T x, T y)
119 {
120 x_ = x;
121 y_ = y;
122 }
123
124 /**
125 * @brief A destructor used to delete the <b>Vector2</b> instance.
126 *
127 * @since 1.0
128 * @version 1.0
129 */
~Vector2()130 ~Vector2() {}
131
132 /**
133 * @brief Calculates the scalar product of the two-dimensional vector and another two-dimensional vector.
134 * @param other Indicates the two-dimensional vector to be used for calculation.
135 * @return Returns the scalar product.
136 * @since 1.0
137 * @version 1.0
138 */
Dot(const Vector2<T> & other)139 T Dot(const Vector2<T>& other) const
140 {
141 T sum = x_ * other.x_;
142 sum += y_ * other.y_;
143 return sum;
144 }
145
146 /**
147 * @brief Calculates the cross product of the two-dimensional vector and another two-dimensional vector.
148 * @param other Indicates the two-dimensional vector to be used for calculation.
149 * @return Returns the cross product.
150 * @since 1.0
151 * @version 1.0
152 */
Cross(const Vector2<T> & other)153 T Cross(const Vector2<T>& other) const
154 {
155 return x_ * other.y_ - y_ * other.x_;
156 }
157
158 Vector2 operator-() const
159 {
160 return Vector2(-x_, -y_);
161 }
162
163 Vector2 operator-(const Vector2<T>& other) const
164 {
165 return Vector2(x_ - other.x_, y_ - other.y_);
166 }
167
168 Vector2 operator+(const Vector2<T>& other) const
169 {
170 return Vector2(x_ + other.x_, y_ + other.y_);
171 }
172
173 Vector2 operator*(T scale) const
174 {
175 return Vector2(x_ * scale, y_ * scale);
176 }
177
178 bool operator==(const Vector2& other) const
179 {
180 return (x_ == other.x_) && (y_ == other.y_);
181 }
182
183 Vector2& operator=(const Vector2& other)
184 {
185 x_ = other.x_;
186 y_ = other.y_;
187 return *this;
188 }
189
190 Vector2& operator+=(const Vector2& other)
191 {
192 x_ += other.x_;
193 y_ += other.y_;
194 return *this;
195 }
196
197 Vector2& operator-=(const Vector2& other)
198 {
199 x_ -= other.x_;
200 y_ -= other.y_;
201 return *this;
202 }
203
204 T x_;
205 T y_;
206 };
207
208 /**
209 * @brief Defines the 3-dimensional vector, and provides basic operators such as [] and ==.
210 *
211 * @since 1.0
212 * @version 1.0
213 */
214 template<typename T>
215 class Vector3 : public HeapBase {
216 public:
217 union {
218 struct {
219 T x_;
220 T y_;
221 T z_;
222 };
223 T data_[3]; // 3: size for x,y,z
224 };
225
226 /**
227 * @brief A constructor used to create a <b>Vector3</b> instance.
228 * @since 1.0
229 * @version 1.0
230 */
Vector3()231 Vector3() : x_(0), y_(0), z_(1) {}
232
233 /**
234 * @brief Defines a <b>Vector3</b> instance and initializes the values of <b>x</b>, <b>y</b>, and <b>z</b>.
235 * @param x Indicates the X coordinate.
236 * @param y Indicates the Y coordinate.
237 * @param z Indicates the Z coordinate.
238 * @since 1.0
239 * @version 1.0
240 */
Vector3(T x,T y,T z)241 Vector3(T x, T y, T z)
242 {
243 data_[0] = x;
244 data_[1] = y;
245 data_[2] = z; // 2: index of z
246 }
247
248 /**
249 * @brief A destructor used to delete the <b>Vector3</b> instance.
250 * @since 1.0
251 * @version 1.0
252 */
~Vector3()253 ~Vector3() {}
254
255 T operator[](uint8_t index) const
256 {
257 return data_[index];
258 }
259
260 T& operator[](uint8_t index)
261 {
262 return data_[index];
263 }
264
265 bool operator==(const Vector3& other) const
266 {
267 return (x_ == other.x_) && (y_ == other.y_) && (z_ == other.z_);
268 }
269 };
270
271 /**
272 * @brief Defines the 4-dimensional vector, and provides basic operators such as [] and ==.
273 *
274 * @since 5.0
275 * @version 3.0
276 */
277 template<typename T>
278 class Vector4 : public HeapBase {
279 public:
280 union {
281 struct {
282 T x_;
283 T y_;
284 T z_;
285 T w_;
286 };
287 T data_[4]; // 4: size for x,y,z,w
288 };
289
290 /**
291 * @brief A constructor used to create a <b>Vector4</b> instance.
292 * @since 5.0
293 * @version 3.0
294 */
Vector4()295 Vector4() : x_(0), y_(0), z_(0), w_(1) {}
296
Vector4(T x,T y,T z,T w)297 Vector4(T x, T y, T z, T w)
298 {
299 data_[0] = x;
300 data_[1] = y;
301 data_[2] = z; // 2: index of z
302 data_[3] = w; // 3: index of w
303 }
304
305 /**
306 * @brief A destructor used to delete the <b>Vector4</b> instance.
307 * @since 5.0
308 * @version 3.0
309 */
~Vector4()310 ~Vector4() {}
311
312 T operator[](uint8_t index) const
313 {
314 return data_[index];
315 }
316
317 T& operator[](uint8_t index)
318 {
319 return data_[index];
320 }
321
322 bool operator==(const Vector4& other) const
323 {
324 return (x_ == other.x_) && (y_ == other.y_) && (z_ == other.z_) && (w_ == other.w_);
325 }
326 };
327
328 /**
329 * @brief Defines a 3 x 3 matrix.
330 *
331 * @since 1.0
332 * @version 1.0
333 */
334 template<typename T>
335 class Matrix3 : public HeapBase {
336 public:
337 /**
338 * @brief Defines a <b>Matrix3</b> instance and initializes the 3 x 3 matrix data.
339 *
340 * @since 1.0
341 * @version 1.0
342 */
343 Matrix3();
344
345 /**
346 * @brief Defines a <b>Matrix3</b> instance and initializes the 3 x 3 matrix data.
347 *
348 * @param m00 Indicates the element in row 1 and column 1 of the matrix.
349 * @param m01 Indicates the element in row 1 and column 2 of the matrix.
350 * @param m02 Indicates the element in row 1 and column 3 of the matrix.
351 * @param m10 Indicates the element in row 2 and column 1 of the matrix.
352 * @param m11 Indicates the element in row 2 and column 2 of the matrix.
353 * @param m12 Indicates the element in row 2 and column 3 of the matrix.
354 * @param m20 Indicates the element in row 3 and column 1 of the matrix.
355 * @param m21 Indicates the element in row 3 and column 2 of the matrix.
356 * @param m22 Indicates the element in row 3 and column 3 of the matrix.
357 * @since 1.0
358 * @version 1.0
359 */
360 Matrix3(T m00, T m01, T m02, T m10, T m11, T m12, T m20, T m21, T m22);
361
362 /**
363 * @brief A destructor used to delete the <b>Matrix3</b> instance.
364 * @since 1.0
365 * @version 1.0
366 */
~Matrix3()367 ~Matrix3() {}
368
369 /**
370 * @brief Obtains the 3 x 3 matrix data.
371 * @return Returns the 3 x 3 matrix data.
372 * @since 1.0
373 * @version 1.0
374 */
GetData()375 const T* GetData() const
376 {
377 return data_;
378 }
379
380 /**
381 * @brief Obtains the determinant of the matrix.
382 * @return Returns the determinant.
383 * @since 1.0
384 * @version 1.0
385 */
386 T Determinant() const;
387
388 /**
389 * @brief Obtains the inverse matrix.
390 * @return Returns the inverse matrix.
391 * @since 1.0
392 * @version 1.0
393 */
394 Matrix3 Inverse() const;
395
396 /**
397 * @brief Obtains a rotation matrix. After a matrix is rotated, its data is shifted leftwards by 15 bits. Therefore,
398 * the result data needs to be shifted rightwards by 15 bits.
399 * @param angle Indicates the angle to rotate.
400 * @param pivot Indicates the rotation pivot.
401 * @return Returns the matrix after rotation.
402 * @since 1.0
403 * @version 1.0
404 */
405 static Matrix3 Rotate(T angle, const Vector2<T>& pivot);
406
407 /**
408 * @brief Obtains the scaling matrix. After a matrix is scaled, its data is shifted leftwards by 8 bits. Therefore,
409 * the result data needs to be shifted rightwards by 8 bits.
410 * @param scale Indicates the scaling factors of the x-axis and y-axis.
411 * @param fixed Indicates the fixed scaling point.
412 * @return Returns the matrix after scaling.
413 * @since 1.0
414 * @version 1.0
415 */
416 static Matrix3 Scale(const Vector2<T>& scale, const Vector2<T>& fixed);
417
418 /**
419 * @brief Obtains a matrix translation.
420 * @param trans Indicates the distances to translate along the x-axis and y-axis.
421 * @return Returns the matrix after translation.
422 * @since 1.0
423 * @version 1.0
424 */
425 static Matrix3<T> Translate(const Vector2<T>& trans);
426
427 Matrix3 operator*(const Matrix3& other) const;
428
429 Vector3<T> operator*(const Vector3<T>& other) const;
430
431 T* operator[](uint8_t col)
432 {
433 return &data_[col * 3]; // 3: size of point
434 }
435
436 Matrix3& operator=(const Matrix3& other)
437 {
438 // 9: data_ value number
439 data_[0] = other.data_[0];
440 data_[1] = other.data_[1];
441 data_[2] = other.data_[2];
442 data_[3] = other.data_[3];
443 data_[4] = other.data_[4];
444 data_[5] = other.data_[5];
445 data_[6] = other.data_[6];
446 data_[7] = other.data_[7];
447 data_[8] = other.data_[8];
448 return *this;
449 }
450
451 bool operator==(const Matrix3& other) const;
452
453 protected:
454 T data_[9]; // 9: 3 point with x,y,z
455 };
456
457 template<typename T>
Matrix3()458 Matrix3<T>::Matrix3()
459 {
460 data_[1] = 0;
461 data_[2] = 0;
462 data_[3] = 0;
463 data_[5] = 0;
464 data_[6] = 0;
465 data_[7] = 0;
466 data_[0] = 1;
467 data_[4] = 1;
468 data_[8] = 1;
469 }
470
471 template<typename T>
Matrix3(T m00,T m01,T m02,T m10,T m11,T m12,T m20,T m21,T m22)472 Matrix3<T>::Matrix3(T m00, T m01, T m02, T m10, T m11, T m12, T m20, T m21, T m22)
473 {
474 data_[0] = m00;
475 data_[1] = m01;
476 data_[2] = m02;
477
478 data_[3] = m10;
479 data_[4] = m11;
480 data_[5] = m12;
481
482 data_[6] = m20;
483 data_[7] = m21;
484 data_[8] = m22;
485 }
486
487 template<typename T>
488 Matrix3<T> Matrix3<T>::operator*(const Matrix3<T>& other) const
489 {
490 Matrix3<T> rMulti;
491 T* rData = rMulti.data_;
492 const T* oData = other.data_;
493
494 rData[0] = data_[0] * oData[0] + data_[3] * oData[1] + data_[6] * oData[2];
495 rData[3] = data_[0] * oData[3] + data_[3] * oData[4] + data_[6] * oData[5];
496 rData[6] = data_[0] * oData[6] + data_[3] * oData[7] + data_[6] * oData[8];
497
498 rData[1] = data_[1] * oData[0] + data_[4] * oData[1] + data_[7] * oData[2];
499 rData[4] = data_[1] * oData[3] + data_[4] * oData[4] + data_[7] * oData[5];
500 rData[7] = data_[1] * oData[6] + data_[4] * oData[7] + data_[7] * oData[8];
501
502 rData[2] = data_[2] * oData[0] + data_[5] * oData[1] + data_[8] * oData[2];
503 rData[5] = data_[2] * oData[3] + data_[5] * oData[4] + data_[8] * oData[5];
504 rData[8] = data_[2] * oData[6] + data_[5] * oData[7] + data_[8] * oData[8];
505 return rMulti;
506 }
507
508 template<typename T>
509 Vector3<T> Matrix3<T>::operator*(const Vector3<T>& other) const
510 {
511 Vector3<T> rMulti;
512 T* rData = rMulti.data_;
513 const T* oData = other.data_;
514 rData[0] = data_[0] * oData[0] + data_[3] * oData[1] + data_[6] * oData[2];
515 rData[1] = data_[1] * oData[0] + data_[4] * oData[1] + data_[7] * oData[2];
516 rData[2] = data_[2] * oData[0] + data_[5] * oData[1] + data_[8] * oData[2];
517 return rMulti;
518 }
519
520 template<typename T>
Determinant()521 T Matrix3<T>::Determinant() const
522 {
523 T x = data_[0] * ((data_[4] * data_[8]) - (data_[5] * data_[7]));
524 T y = data_[1] * ((data_[3] * data_[8]) - (data_[5] * data_[6]));
525 T z = data_[2] * ((data_[3] * data_[7]) - (data_[4] * data_[6]));
526 return (x - y) + z;
527 }
528
529 template<typename T>
Inverse()530 Matrix3<T> Matrix3<T>::Inverse() const
531 {
532 T det = this->Determinant();
533 if (det == 0) {
534 return Matrix3<T>(*this);
535 }
536
537 T invDet = 1.0f / det;
538 const T* data = this->data_;
539
540 T iX = invDet * (data[4] * data[8] - data[5] * data[7]);
541 T iY = invDet * (data[2] * data[7] - data[1] * data[8]);
542 T iZ = invDet * (data[1] * data[5] - data[2] * data[4]);
543 T jX = invDet * (data[5] * data[6] - data[3] * data[8]);
544 T jY = invDet * (data[0] * data[8] - data[2] * data[6]);
545 T jZ = invDet * (data[2] * data[3] - data[0] * data[5]);
546 T kX = invDet * (data[3] * data[7] - data[4] * data[6]);
547 T kY = invDet * (data[1] * data[6] - data[0] * data[7]);
548 T kZ = invDet * (data[0] * data[4] - data[1] * data[3]);
549
550 return Matrix3<T>(iX, iY, iZ, jX, jY, jZ, kX, kY, kZ);
551 }
552
553 template<typename T>
554 bool Matrix3<T>::operator==(const Matrix3& other) const
555 {
556 const T* oData = other.data_;
557
558 return (data_[0] == oData[0]) && (data_[1] == oData[1]) && (data_[2] == oData[2]) && (data_[3] == oData[3]) &&
559 (data_[4] == oData[4]) && (data_[5] == oData[5]) && (data_[6] == oData[6]) && (data_[7] == oData[7]) &&
560 (data_[8] == oData[8]);
561 }
562
563 template<typename T>
Rotate(T angle,const Vector2<T> & pivot)564 Matrix3<T> Matrix3<T>::Rotate(T angle, const Vector2<T>& pivot)
565 {
566 T s = static_cast<T>(Sin(angle));
567 T c = static_cast<T>(Sin(angle + QUARTER_IN_DEGREE));
568
569 Matrix3<T> rotateMat3;
570 T* rData = rotateMat3.data_;
571 rData[0] = c;
572 rData[1] = s;
573
574 rData[3] = -s;
575 rData[4] = c;
576
577 rData[6] = pivot.x_ * (1 - c) + pivot.y_ * s;
578 rData[7] = pivot.y_ * (1 - c) - pivot.x_ * s;
579
580 rData[8] = 1;
581
582 return rotateMat3;
583 }
584
585 template<typename T>
Scale(const Vector2<T> & scale,const Vector2<T> & fixed)586 Matrix3<T> Matrix3<T>::Scale(const Vector2<T>& scale, const Vector2<T>& fixed)
587 {
588 Matrix3<T> scaleMat3;
589 T* rData = scaleMat3.data_;
590 rData[0] = scale.x_;
591
592 rData[4] = scale.y_;
593 rData[6] = fixed.x_ * (1 - scale.x_);
594 rData[7] = fixed.y_ * (1 - scale.y_);
595
596 rData[8] = 1;
597
598 return scaleMat3;
599 }
600
601 template<typename T>
Translate(const Vector2<T> & trans)602 Matrix3<T> Matrix3<T>::Translate(const Vector2<T>& trans)
603 {
604 Matrix3 transMat3;
605 T* rData = transMat3.data_;
606
607 rData[6] = trans.x_;
608 rData[7] = trans.y_;
609
610 return transMat3;
611 }
612
613 /**
614 * @brief Defines a 4 x 4 matrix.
615 *
616 * @since 5.0
617 * @version 3.0
618 */
619 template<typename T>
620 class Matrix4 : public HeapBase {
621 public:
622 /**
623 * @brief Defines a <b>Matrix4</b> instance and initializes the 4 x 4 matrix data.
624 *
625 * @since 5.0
626 * @version 3.0
627 */
628 Matrix4();
629
630 Matrix4(T m00, T m01, T m02, T m03, T m10, T m11, T m12, T m13,
631 T m20, T m21, T m22, T m23, T m30, T m31, T m32, T m33);
632
633 /**
634 * @brief A destructor used to delete the <b>Matrix3</b> instance.
635 * @since 5.0
636 * @version 3.0
637 */
~Matrix4()638 ~Matrix4() {}
639
640 /**
641 * @brief Obtains the 4 x 4 matrix data.
642 * @return Returns the 4 x 4 matrix data.
643 * @since 5.0
644 * @version 3.0
645 */
GetData()646 const T* GetData() const
647 {
648 return data_;
649 }
650
651 /**
652 * @brief Obtains the determinant of the matrix.
653 * @return Returns the determinant.
654 * @since 5.0
655 * @version 3.0
656 */
657 T Determinant() const;
658
659 /**
660 * @brief Obtains the inverse matrix.
661 * @return Returns the inverse matrix.
662 * @since 5.0
663 * @version 3.0
664 */
665 Matrix4<T> Inverse() const;
666
667 /**
668 * @brief Obtains a rotation matrix.
669 *
670 * @param angle Indicates the angle to rotate.
671 * @param pivot1 Indicates the rotation pivot.
672 * @param pivot2 Indicates the rotation pivot.
673 * @return Returns the matrix after rotation.
674 * @since 5.0
675 * @version 3.0
676 */
677 static Matrix4<T> Rotate(T angle, const Vector3<T>& pivot1, const Vector3<T>& pivot2);
678
679 /**
680 * @brief Obtains the scaling matrix.
681 *
682 * @param scale Indicates the scaling factors of the x-axis and y-axis.
683 * @param fixed Indicates the fixed scaling point.
684 * @return Returns the matrix after scaling.
685 * @since 5.0
686 * @version 3.0
687 */
688 static Matrix4<T> Scale(const Vector3<T>& scale, const Vector3<T>& fixed);
689
690 /**
691 * @brief Obtains a matrix translation.
692 *
693 * @param trans Indicates the distances to translate along the x-axis and y-axis and z-axis.
694 * @return Returns the matrix after translation.
695 * @since 5.0
696 * @version 3.0
697 */
698 static Matrix4<T> Translate(const Vector3<T>& trans);
699
700 static Matrix4<T> Shear(const Vector2<T>& shearX, const Vector2<T>& shearY, const Vector2<T>& shearZ);
701
702 Matrix4 operator*(const Matrix4& other) const;
703
704 Vector4<T> operator*(const Vector4<T>& other) const;
705
706 T* operator[](uint8_t col)
707 {
708 return &data_[col * 4]; // 4: size of point
709 }
710
711 Matrix4& operator=(const Matrix4& other)
712 {
713 // 16: data_ value number
714 for (int16_t i = 0; i < 16; i++) {
715 data_[i] = other.data_[i];
716 }
717 return *this;
718 }
719
720 bool operator==(const Matrix4& other) const;
721
722 protected:
723 Matrix3<T> ConomialMatrix(int16_t row, int16_t col) const;
724 T data_[16]; // 16: 4 point with x,y,z,w
725 };
726
727 template<typename T>
Matrix4()728 Matrix4<T>::Matrix4()
729 {
730 for (int16_t row = 0; row < ORDER_MATRIX_4; row++) {
731 for (int16_t col = 0; col < ORDER_MATRIX_4; col++) {
732 data_[row * ORDER_MATRIX_4 + col] = (row == col) ? 1 : 0;
733 }
734 }
735 }
736
737 template<typename T>
Matrix4(T m00,T m01,T m02,T m03,T m10,T m11,T m12,T m13,T m20,T m21,T m22,T m23,T m30,T m31,T m32,T m33)738 Matrix4<T>::Matrix4(T m00, T m01, T m02, T m03, T m10, T m11, T m12, T m13,
739 T m20, T m21, T m22, T m23, T m30, T m31, T m32, T m33)
740 {
741 data_[0] = m00; // 0 : index
742 data_[1] = m01; // 1 : index
743 data_[2] = m02; // 2 : index
744 data_[3] = m03; // 3 : index
745
746 data_[4] = m10; // 4 : index
747 data_[5] = m11; // 5 : index
748 data_[6] = m12; // 6 : index
749 data_[7] = m13; // 7 : index
750
751 data_[8] = m20; // 8 : index
752 data_[9] = m21; // 9 : index
753 data_[10] = m22; // 10 : index
754 data_[11] = m23; // 11 : index
755
756 data_[12] = m30; // 12 : index
757 data_[13] = m31; // 13 : index
758 data_[14] = m32; // 14 : index
759 data_[15] = m33; // 15 : index
760 }
761
762 template<typename T>
763 Matrix4<T> Matrix4<T>::operator*(const Matrix4& other) const
764 {
765 Matrix4<T> rMulti;
766 T* rData = rMulti.data_;
767 const T* oData = other.data_;
768 for (int16_t row = 0; row < ORDER_MATRIX_4; row++) {
769 for (int16_t col = 0; col < ORDER_MATRIX_4; col++) {
770 /* 1 2 3 4 8 12 : offset */
771 rData[row * 4 + col] = oData[row * 4] * data_[col] + oData[row * 4 + 1] * data_[4 + col] +
772 oData[row * 4 + 2] * data_[8 + col] + oData[row * 4 + 3] * data_[12 + col];
773 }
774 }
775 return rMulti;
776 }
777
778 template<typename T>
779 Vector4<T> Matrix4<T>::operator*(const Vector4<T>& other) const
780 {
781 Vector4<T> rMulti;
782 T* rData = rMulti.data_;
783 const T* oData = other.data_;
784 for (int16_t i = 0; i < ORDER_MATRIX_4; i++) {
785 /* 1 2 3 4 8 12 : offset */
786 rData[i] = data_[i] * oData[0] + data_[i + 4] * oData[1] + data_[i + 8] * oData[2] + data_[i + 12] * oData[3];
787 }
788 return rMulti;
789 }
790
791 template<typename T>
ConomialMatrix(int16_t row,int16_t col)792 Matrix3<T> Matrix4<T>::ConomialMatrix(int16_t row, int16_t col) const
793 {
794 T tmpData[9]; // 9: 3 * 3
795 int index = 0;
796 for (int16_t i = 0; i < ORDER_MATRIX_4; i++) {
797 if (row == i) {
798 continue;
799 }
800 for (int16_t j = 0; j < ORDER_MATRIX_4; j++) {
801 if (col != j) {
802 tmpData[index++] = data_[i * ORDER_MATRIX_4 + j];
803 }
804 }
805 }
806 /* 0 1 2 3 4 5 6 7 8 : index */
807 return Matrix3<T>(tmpData[0], tmpData[1], tmpData[2],
808 tmpData[3], tmpData[4], tmpData[5],
809 tmpData[6], tmpData[7], tmpData[8]);
810 }
811
812 template<typename T>
Determinant()813 T Matrix4<T>::Determinant() const
814 {
815 T tmpData[ORDER_MATRIX_4];
816 for (int16_t i = 0; i < ORDER_MATRIX_4; i++) {
817 tmpData[i] = ConomialMatrix(0, i).Determinant() * data_[i];
818 }
819 // 0 1 2 3 : index
820 return tmpData[0] - tmpData[1] + tmpData[2] - tmpData[3];
821 }
822
823 template<typename T>
Inverse()824 Matrix4<T> Matrix4<T>::Inverse() const
825 {
826 T det = this->Determinant();
827 if (det == 0) {
828 return Matrix4<T>(*this);
829 }
830 T invDet = 1.0f / det;
831 // algebraic conomial matrix;
832 Matrix4<T> matrix;
833 T* tmpData = matrix.data_;
834 int16_t negative = 1;
835 for (int16_t row = 0; row < ORDER_MATRIX_4; row++) {
836 for (int16_t col = 0; col < ORDER_MATRIX_4; col++) {
837 if ((row + col) % 2 == 0) { // 2 : half
838 negative = 1;
839 } else {
840 negative = -1;
841 }
842 tmpData[row * ORDER_MATRIX_4 + col] = ConomialMatrix(row, col).Determinant() * negative * invDet;
843 }
844 }
845 // transpose matrix
846 for (int16_t row = 0; row < ORDER_MATRIX_4; row++) {
847 for (int16_t col = row + 1; col < ORDER_MATRIX_4; col++) {
848 T tmp = tmpData[row * ORDER_MATRIX_4 + col];
849 tmpData[row * ORDER_MATRIX_4 + col] = tmpData[row + col * ORDER_MATRIX_4];
850 tmpData[row + col * ORDER_MATRIX_4] = tmp;
851 }
852 }
853 return matrix;
854 }
855
856 template<typename T>
857 bool Matrix4<T>::operator==(const Matrix4& other) const
858 {
859 const T* oData = other.data_;
860 // 16 : 4 * 4 points
861 for (int16_t i = 0; i < 16; i++) {
862 if (data_[i] != oData[i]) {
863 return false;
864 }
865 }
866 return true;
867 }
868
869 template<typename T>
Rotate(T angle,const Vector3<T> & pivot1,const Vector3<T> & pivot2)870 Matrix4<T> Matrix4<T>::Rotate(T angle, const Vector3<T>& pivot1, const Vector3<T>& pivot2)
871 {
872 Matrix4<T> rotateMat4;
873 T* rData = rotateMat4.data_;
874 T length = Sqrt((pivot2.x_ - pivot1.x_) * (pivot2.x_ - pivot1.x_) +
875 (pivot2.y_ - pivot1.y_) * (pivot2.y_ - pivot1.y_) +
876 (pivot2.z_ - pivot1.z_) * (pivot2.z_ - pivot1.z_));
877 if (length == 0) {
878 return rotateMat4;
879 }
880 T cosA = static_cast<T>(Sin(angle + QUARTER_IN_DEGREE));
881 T sinA = static_cast<T>(Sin(angle));
882 T diff = 1 - cosA;
883 T ux = (pivot2.x_ - pivot1.x_) / length;
884 T uy = (pivot2.y_ - pivot1.y_) / length;
885 T uz = (pivot2.z_ - pivot1.z_) / length;
886 Matrix4<T> transToOrigin = Matrix4<T>::Translate(Vector3<T> { -pivot1.x_, -pivot1.y_, -pivot1.z_ });
887
888 rData[0] = ux * ux * diff + cosA; // 0 : index
889 rData[1] = uy * ux * diff + uz * sinA; // 1 : index
890 rData[2] = uz * ux * diff - uy * sinA; // 2 : index
891
892 rData[4] = ux * uy * diff - uz * sinA; // 4 : index
893 rData[5] = uy * uy * diff + cosA; // 5 : index
894 rData[6] = uz * uy * diff + ux * sinA; // 6 : index
895
896 rData[8] = ux * uz * diff + uy * sinA; // 8 : index
897 rData[9] = uy * uz * diff - ux * sinA; // 9 : index
898 rData[10] = uz * uz * diff + cosA; // 10 : index
899
900 Matrix4<T> transToPivot = Matrix4<T>::Translate(pivot1);
901 return transToPivot * (rotateMat4 * transToOrigin);
902 }
903
904 template<typename T>
Scale(const Vector3<T> & scale,const Vector3<T> & fixed)905 Matrix4<T> Matrix4<T>::Scale(const Vector3<T>& scale, const Vector3<T>& fixed)
906 {
907 Matrix4<T> scaleMat4;
908 T* sData = scaleMat4.data_;
909
910 sData[0] = scale.x_; // 0 : index
911 sData[5] = scale.y_; // 5 : index
912 sData[10] = scale.z_; // 10 : index
913 sData[12] = (1 - scale.x_) * fixed.x_; // 12 : index
914 sData[13] = (1 - scale.y_) * fixed.y_; // 13 : index
915 sData[14] = (1 - scale.z_) * fixed.z_; // 14 : index
916
917 return scaleMat4;
918 }
919
920 template<typename T>
Translate(const Vector3<T> & trans)921 Matrix4<T> Matrix4<T>::Translate(const Vector3<T>& trans)
922 {
923 Matrix4<T> rotateMat4;
924 T* rData = rotateMat4.data_;
925
926 rData[12] = trans.x_; // 12 : index
927 rData[13] = trans.y_; // 13 : index
928 rData[14] = trans.z_; // 14 : index
929
930 return rotateMat4;
931 }
932
933 template<typename T>
Shear(const Vector2<T> & shearX,const Vector2<T> & shearY,const Vector2<T> & shearZ)934 Matrix4<T> Matrix4<T>::Shear(const Vector2<T>& shearX, const Vector2<T>& shearY, const Vector2<T>& shearZ)
935 {
936 Matrix4<T> shearMat4;
937 shearMat4[1][0] = shearX.x_; // 1 0 : index
938 shearMat4[2][0] = shearX.y_; // 2 0 : index
939 shearMat4[0][1] = shearY.x_; // 0 1 : index
940 shearMat4[2][1] = shearY.y_; // 2 1 : index
941 shearMat4[0][2] = shearZ.x_; // 0 2 : index
942 shearMat4[1][2] = shearZ.y_; // 1 2 : index
943 return shearMat4;
944 }
945
FloatToInt64(float f)946 inline int64_t FloatToInt64(float f)
947 {
948 if (f > 127.0f) { // 127.0: 2^7
949 return 0x7FFF;
950 }
951
952 if (f < -127.0f) { // 127.0: 2^7
953 return -0x7FFF;
954 }
955
956 // 256.0: 2^8 left move 8 bit. 0.5: round up
957 return static_cast<int64_t>(f * 256.0f + ((f < 0) ? -0.5f : 0.5f));
958 }
959
960 inline bool FloatEqual(float lhs, float rhs, float precision = 0.00001f)
961 {
962 return (MATH_ABS(lhs - rhs) < precision) ? true : false;
963 }
964
965 bool IsIdentity(Matrix3<float>& matrix);
966
967 bool IsIdentity(Matrix4<float>& matrix);
968 } // namespace OHOS
969 #endif // GRAPHIC_LITE_GRAPHIC_MATH_H
970