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