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