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