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