1/*
2 * Copyright (c) 2022 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#ifndef OHOS_ROSEN_WM_MATH_H
17#define OHOS_ROSEN_WM_MATH_H
18
19#include <cmath>
20#include <limits>
21
22namespace OHOS::Rosen {
23namespace MathHelper {
24constexpr float PI = 3.14159265f;
25constexpr float INF = std::numeric_limits<float>::infinity();
26constexpr float NAG_INF = -std::numeric_limits<float>::infinity();
27constexpr float POS_ZERO = 0.001f;
28constexpr float NAG_ZERO = -POS_ZERO;
29inline bool NearZero(float val)
30{
31    return val < POS_ZERO && val > NAG_ZERO;
32}
33
34inline float ToRadians(float degrees)
35{
36    return degrees * PI / 180.0f;
37}
38
39inline float ToDegrees(float radians)
40{
41    return radians * 180.0f / PI;
42}
43
44inline bool LessNotEqual(double left, double right)
45{
46    static constexpr double eps = -0.001f;
47    return (left - right) < eps;
48}
49
50inline bool GreatNotEqual(double left, double right)
51{
52    static constexpr double eps = 0.001f;
53    return (left - right) > eps;
54}
55
56template <typename T>
57T Max(const T& a, const T& b)
58{
59    return (a < b ? b : a);
60}
61
62template <typename T, typename... Ts>
63T Max(const T& a, const Ts&... bs)
64{
65    return Max(a, Max(bs...));
66}
67
68template <typename T>
69T Min(const T& a, const T& b)
70{
71    return (a < b ? a : b);
72}
73
74template <typename T, typename... Ts>
75T Min(const T& a, const Ts&... bs)
76{
77    return Min(a, Min(bs...));
78}
79
80template <typename T>
81T Clamp(const T& value, const T& lower, const T& upper)
82{
83    return Min(upper, Max(lower, value));
84}
85} // namespace MathHelper
86
87namespace TransformHelper {
88struct Vector2 {
89    float x_, y_;
90    Vector2() : x_(0.0f), y_(0.0f) {}
91    Vector2(float inX, float inY)
92        : x_(inX), y_(inY) {}
93    friend Vector2 operator-(const Vector2& v)
94    {
95        return Vector2 { -v.x_, -v.y_ };
96    }
97    friend Vector2 operator+(const Vector2& a, const Vector2& b)
98    {
99        return Vector2 { a.x_ + b.x_, a.y_ + b.y_ };
100    }
101    friend Vector2 operator-(const Vector2& a, const Vector2& b)
102    {
103        return Vector2 { a.x_ - b.x_, a.y_ - b.y_ };
104    }
105    float LengthSq() const
106    {
107        return (x_ * x_ + y_ * y_);
108    }
109    float Length() const
110    {
111        return (std::sqrt(LengthSq()));
112    }
113};
114
115struct Vector3 {
116    float x_, y_, z_;
117    Vector3() : x_(0.0f), y_(0.0f), z_(0.0f) {}
118    Vector3(float inX, float inY, float inZ)
119        : x_(inX), y_(inY), z_(inZ) {}
120    friend Vector3 operator-(const Vector3& v)
121    {
122        return Vector3 { -v.x_, -v.y_, -v.z_ };
123    }
124    friend Vector3 operator+(const Vector3& a, const Vector3& b)
125    {
126        return Vector3 { a.x_ + b.x_, a.y_ + b.y_, a.z_ + b.z_ };
127    }
128    friend Vector3 operator-(const Vector3& a, const Vector3& b)
129    {
130        return Vector3 { a.x_ - b.x_, a.y_ - b.y_, a.z_ - b.z_ };
131    }
132    // Scalar multiplication
133    friend Vector3 operator*(const Vector3& vec, float scalar)
134    {
135        return Vector3(vec.x_ * scalar, vec.y_ * scalar, vec.z_ * scalar);
136    }
137    // Scalar multiplication
138    friend Vector3 operator*(float scalar, const Vector3& vec)
139    {
140        return Vector3(vec.x_ * scalar, vec.y_ * scalar, vec.z_ * scalar);
141    }
142    // Scalar *=
143    Vector3& operator*=(float scalar)
144    {
145        x_ *= scalar;
146        y_ *= scalar;
147        z_ *= scalar;
148        return *this;
149    }
150    float LengthSq() const
151    {
152        return (x_ * x_ + y_ * y_ + z_ * z_);
153    }
154    float Length() const
155    {
156        return (std::sqrt(LengthSq()));
157    }
158    void Normalize()
159    {
160        float length = Length();
161        if (length > MathHelper::POS_ZERO) {
162            x_ /= length;
163            y_ /= length;
164            z_ /= length;
165        }
166    }
167    static Vector3 Normalize(const Vector3& vec)
168    {
169        Vector3 temp = vec;
170        temp.Normalize();
171        return temp;
172    }
173    static float Dot(const Vector3& a, const Vector3& b)
174    {
175        return (a.x_ * b.x_ + a.y_ * b.y_ + a.z_ * b.z_);
176    }
177    static Vector3 Cross(const Vector3& a, const Vector3& b)
178    {
179        Vector3 temp;
180        temp.x_ = a.y_ * b.z_ - a.z_ * b.y_;
181        temp.y_ = a.z_ * b.x_ - a.x_ * b.z_;
182        temp.z_ = a.x_ * b.y_ - a.y_ * b.x_;
183        return temp;
184    }
185};
186
187struct Matrix3 {
188    float mat_[3][3];
189
190    friend Matrix3 operator*(const Matrix3& left, const Matrix3& right);
191    Matrix3& operator*=(const Matrix3& right);
192    static const Matrix3 Identity;
193};
194
195struct Matrix4 {
196    float mat_[4][4];
197
198    friend Matrix4 operator*(const Matrix4& left, const Matrix4& right);
199    Matrix4& operator*=(const Matrix4& right);
200    void SwapRow(int row1, int row2);
201    // Inverse matrix with Gauss-Jordan method
202    void Invert();
203    // Extract the scale component from the matrix
204    Vector3 GetScale() const;
205    // Get the translation component of the matrix
206    Vector3 GetTranslation() const;
207    static const Matrix4 Identity;
208    static constexpr int MAT_SIZE = 4;
209};
210
211// Create a scale matrix with x and y scales(in xy-plane)
212Matrix3 CreateScale(float xScale, float yScale);
213// Create a rotation matrix about the Z axis
214// theta is in radians
215Matrix3 CreateRotation(float theta);
216// Create a translation matrix (on the xy-plane)
217Matrix3 CreateTranslation(const Vector2& trans);
218// Create a scale matrix with x, y, and z scales
219Matrix4 CreateScale(float xScale, float yScale, float zScale);
220// Create a rotation matrix about X axis
221// theta is in radians
222Matrix4 CreateRotationX(float theta);
223// Create a rotation matrix about Y axis
224// theta is in radians
225Matrix4 CreateRotationY(float theta);
226// Create a rotation matrix about Z axis
227// theta is in radians
228Matrix4 CreateRotationZ(float theta);
229// Create a 3D translation matrix
230Matrix4 CreateTranslation(const Vector3& trans);
231Matrix4 CreateLookAt(const Vector3& eye, const Vector3& target, const Vector3& up);
232Matrix4 CreatePerspective(const Vector3& camera);
233// Transform a Vector2 in xy-plane by matrix3
234Vector2 Transform(const Vector2& vec, const Matrix3& mat);
235// Transform a Vector3 in 3D world by matrix4
236Vector3 Transform(const Vector3& vec, const Matrix4& mat);
237// Transform the vector and renormalize the w component
238Vector3 TransformWithPerspDiv(const Vector3& vec, const Matrix4& mat, float w = 1.0f);
239// Given a screen point, unprojects it into origin position at screen,
240// based on the current transform matrix
241Vector2 GetOriginScreenPoint(const Vector2& p, const Matrix4& mat);
242} // namespace TransformHelper
243} // namespace OHOS::Rosen
244#endif // OHOS_ROSEN_WM_MATH_H