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