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