• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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