• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "wm_math.h"
16 #include <cstdlib>
17 
18 namespace OHOS::Rosen {
19 namespace TransformHelper {
20 const Matrix3 Matrix3::Identity = { {
21     { 1, 0, 0 },
22     { 0, 1, 0 },
23     { 0, 0, 1 },
24 } };
25 const Matrix4 Matrix4::Identity = { {
26     { 1, 0, 0, 0 },
27     { 0, 1, 0, 0 },
28     { 0, 0, 1, 0 },
29     { 0, 0, 0, 1 },
30 } };
31 
operator *(const Matrix3 & left,const Matrix3 & right)32 Matrix3 operator*(const Matrix3& left, const Matrix3& right)
33 {
34     return  { {
35         // row 0
36         { left.mat_[0][0] * right.mat_[0][0] + left.mat_[0][1] * right.mat_[1][0] + left.mat_[0][2] * right.mat_[2][0],
37         left.mat_[0][0] * right.mat_[0][1] + left.mat_[0][1] * right.mat_[1][1] + left.mat_[0][2] * right.mat_[2][1],
38         left.mat_[0][0] * right.mat_[0][2] + left.mat_[0][1] * right.mat_[1][2] + left.mat_[0][2] * right.mat_[2][2] },
39 
40         // row 1
41         { left.mat_[1][0] * right.mat_[0][0] + left.mat_[1][1] * right.mat_[1][0] + left.mat_[1][2] * right.mat_[2][0],
42         left.mat_[1][0] * right.mat_[0][1] + left.mat_[1][1] * right.mat_[1][1] + left.mat_[1][2] * right.mat_[2][1],
43         left.mat_[1][0] * right.mat_[0][2] + left.mat_[1][1] * right.mat_[1][2] + left.mat_[1][2] * right.mat_[2][2] },
44 
45         // row 2
46         { left.mat_[2][0] * right.mat_[0][0] + left.mat_[2][1] * right.mat_[1][0] + left.mat_[2][2] * right.mat_[2][0],
47         left.mat_[2][0] * right.mat_[0][1] + left.mat_[2][1] * right.mat_[1][1] + left.mat_[2][2] * right.mat_[2][1],
48         left.mat_[2][0] * right.mat_[0][2] + left.mat_[2][1] * right.mat_[1][2] + left.mat_[2][2] * right.mat_[2][2] }
49     } };
50 }
51 
operator *=(const Matrix3 & right)52 Matrix3& Matrix3::operator*=(const Matrix3& right)
53 {
54     *this = *this * right;
55     return *this;
56 }
57 
operator *(const Matrix4 & left,const Matrix4 & right)58 Matrix4 operator*(const Matrix4& left, const Matrix4& right)
59 {
60     return { {
61         // row 0
62         { left.mat_[0][0] * right.mat_[0][0] + left.mat_[0][1] * right.mat_[1][0] +
63         left.mat_[0][2] * right.mat_[2][0] + left.mat_[0][3] * right.mat_[3][0],
64         left.mat_[0][0] * right.mat_[0][1] + left.mat_[0][1] * right.mat_[1][1] +
65         left.mat_[0][2] * right.mat_[2][1] + left.mat_[0][3] * right.mat_[3][1],
66         left.mat_[0][0] * right.mat_[0][2] + left.mat_[0][1] * right.mat_[1][2] +
67         left.mat_[0][2] * right.mat_[2][2] + left.mat_[0][3] * right.mat_[3][2],
68         left.mat_[0][0] * right.mat_[0][3] + left.mat_[0][1] * right.mat_[1][3] +
69         left.mat_[0][2] * right.mat_[2][3] + left.mat_[0][3] * right.mat_[3][3] },
70 
71         // row 1
72         { left.mat_[1][0] * right.mat_[0][0] + left.mat_[1][1] * right.mat_[1][0] +
73         left.mat_[1][2] * right.mat_[2][0] + left.mat_[1][3] * right.mat_[3][0],
74         left.mat_[1][0] * right.mat_[0][1] + left.mat_[1][1] * right.mat_[1][1] +
75         left.mat_[1][2] * right.mat_[2][1] + left.mat_[1][3] * right.mat_[3][1],
76         left.mat_[1][0] * right.mat_[0][2] + left.mat_[1][1] * right.mat_[1][2] +
77         left.mat_[1][2] * right.mat_[2][2] + left.mat_[1][3] * right.mat_[3][2],
78         left.mat_[1][0] * right.mat_[0][3] + left.mat_[1][1] * right.mat_[1][3] +
79         left.mat_[1][2] * right.mat_[2][3] + left.mat_[1][3] * right.mat_[3][3] },
80 
81         // row 2
82         { left.mat_[2][0] * right.mat_[0][0] + left.mat_[2][1] * right.mat_[1][0] +
83         left.mat_[2][2] * right.mat_[2][0] + left.mat_[2][3] * right.mat_[3][0],
84         left.mat_[2][0] * right.mat_[0][1] + left.mat_[2][1] * right.mat_[1][1] +
85         left.mat_[2][2] * right.mat_[2][1] + left.mat_[2][3] * right.mat_[3][1],
86         left.mat_[2][0] * right.mat_[0][2] + left.mat_[2][1] * right.mat_[1][2] +
87         left.mat_[2][2] * right.mat_[2][2] + left.mat_[2][3] * right.mat_[3][2],
88         left.mat_[2][0] * right.mat_[0][3] + left.mat_[2][1] * right.mat_[1][3] +
89         left.mat_[2][2] * right.mat_[2][3] + left.mat_[2][3] * right.mat_[3][3] },
90 
91         // row 3
92         { left.mat_[3][0] * right.mat_[0][0] + left.mat_[3][1] * right.mat_[1][0] +
93         left.mat_[3][2] * right.mat_[2][0] + left.mat_[3][3] * right.mat_[3][0],
94         left.mat_[3][0] * right.mat_[0][1] + left.mat_[3][1] * right.mat_[1][1] +
95         left.mat_[3][2] * right.mat_[2][1] + left.mat_[3][3] * right.mat_[3][1],
96         left.mat_[3][0] * right.mat_[0][2] + left.mat_[3][1] * right.mat_[1][2] +
97         left.mat_[3][2] * right.mat_[2][2] + left.mat_[3][3] * right.mat_[3][2],
98         left.mat_[3][0] * right.mat_[0][3] + left.mat_[3][1] * right.mat_[1][3] +
99         left.mat_[3][2] * right.mat_[2][3] + left.mat_[3][3] * right.mat_[3][3] }
100     } };
101 }
102 
operator *=(const Matrix4 & right)103 Matrix4& Matrix4::operator*=(const Matrix4& right)
104 {
105     *this = *this * right;
106     return *this;
107 }
108 
SwapRow(int row1,int row2)109 void Matrix4::SwapRow(int row1, int row2)
110 {
111     float *p = mat_[row1];
112     float *q = mat_[row2];
113     float tmp = p[0];
114     p[0] = q[0];
115     q[0] = tmp;
116 
117     tmp = p[1];
118     p[1] = q[1];
119     q[1] = tmp;
120 
121     tmp = p[2];
122     p[2] = q[2];
123     q[2] = tmp;
124 
125     tmp = p[3];
126     p[3] = q[3];
127     q[3] = tmp;
128 }
129 
Invert()130 void Matrix4::Invert()
131 {
132     // Inverse matrix with Gauss-Jordan method
133     Matrix4 tmp = Matrix4::Identity;
134     int i, j, k;
135     for (k = 0; k < MAT_SIZE; k++) {
136         float t = mat_[k][k];
137         if (t < MathHelper::POS_ZERO && t > MathHelper::NAG_ZERO) {
138             for (i = k + 1; i < MAT_SIZE; i++) {
139                 if (mat_[i][k] < MathHelper::NAG_ZERO || mat_[i][k] > MathHelper::POS_ZERO) {
140                     SwapRow(k, i);
141                     tmp.SwapRow(k, i);
142                     break;
143                 }
144             }
145             t = mat_[k][k];
146         }
147         for (j = 0; j <= k; j++) {
148             tmp.mat_[k][j] /= t;
149         }
150         for (; j < MAT_SIZE; j++) {
151             mat_[k][j] /= t;
152             tmp.mat_[k][j] /= t;
153         }
154         for (i = 0; i < MAT_SIZE; i++) {
155             if (i == k) {
156                 continue;
157             }
158             float u = mat_[i][k];
159             for (j = 0; j <= k; j++) {
160                 tmp.mat_[i][j] -= tmp.mat_[k][j] * u;
161             }
162             for (; j < MAT_SIZE; j++) {
163                 mat_[i][j] -= mat_[k][j] * u;
164                 tmp.mat_[i][j] -= tmp.mat_[k][j] * u;
165             }
166         }
167     }
168     *this = tmp;
169 }
170 
GetScale() const171 Vector3 Matrix4::GetScale() const
172 {
173     Vector3 retVal;
174     retVal.x_ = Vector3(mat_[0][0], mat_[0][1], mat_[0][2]).Length();
175     retVal.y_ = Vector3(mat_[1][0], mat_[1][1], mat_[1][2]).Length();
176     retVal.z_ = Vector3(mat_[2][0], mat_[2][1], mat_[2][2]).Length();
177     return retVal;
178 }
179 
GetTranslation() const180 Vector3 Matrix4::GetTranslation() const
181 {
182     return Vector3(mat_[3][0], mat_[3][1], mat_[3][2]);
183 }
184 
185 // Create a scale matrix with x and y scales
CreateScale(float xScale,float yScale)186 Matrix3 CreateScale(float xScale, float yScale)
187 {
188     return { {
189         { xScale, 0.0f, 0.0f },
190         { 0.0f, yScale, 0.0f },
191         { 0.0f, 0.0f, 1.0f },
192     } };
193 }
194 
195 // Create a rotation matrix about the Z axis
196 // theta is in radians
CreateRotation(float theta)197 Matrix3 CreateRotation(float theta)
198 {
199     return { {
200         { std::cos(theta), std::sin(theta), 0.0f },
201         { -std::sin(theta), std::cos(theta), 0.0f },
202         { 0.0f, 0.0f, 1.0f },
203     } };
204 }
205 
206 // Create a translation matrix (on the xy-plane)
CreateTranslation(const Vector2 & trans)207 Matrix3 CreateTranslation(const Vector2& trans)
208 {
209     return { {
210         { 1.0f, 0.0f, 0.0f },
211         { 0.0f, 1.0f, 0.0f },
212         { trans.x_, trans.y_, 1.0f },
213     } };
214 }
215 
216 // Create a scale matrix with x, y, and z scales
CreateScale(float xScale,float yScale,float zScale)217 Matrix4 CreateScale(float xScale, float yScale, float zScale)
218 {
219     return { {
220         { xScale, 0.0f, 0.0f, 0.0f },
221         { 0.0f, yScale, 0.0f, 0.0f },
222         { 0.0f, 0.0f, zScale, 0.0f },
223         { 0.0f, 0.0f, 0.0f, 1.0f },
224     } };
225 }
226 
227 // Create a rotation matrix about X axis
228 // theta is in radians
CreateRotationX(float theta)229 Matrix4 CreateRotationX(float theta)
230 {
231     return { {
232         { 1.0f, 0.0f, 0.0f, 0.0f },
233         { 0.0f, std::cos(theta), std::sin(theta), 0.0f },
234         { 0.0f, -std::sin(theta), std::cos(theta), 0.0f },
235         { 0.0f, 0.0f, 0.0f, 1.0f },
236     } };
237 }
238 
239 // Create a rotation matrix about Y axis
240 // theta is in radians
CreateRotationY(float theta)241 Matrix4 CreateRotationY(float theta)
242 {
243     return { {
244         { std::cos(theta), 0.0f, -std::sin(theta), 0.0f },
245         { 0.0f, 1.0f, 0.0f, 0.0f },
246         { std::sin(theta), 0.0f, std::cos(theta), 0.0f },
247         { 0.0f, 0.0f, 0.0f, 1.0f },
248     } };
249 }
250 
251 // Create a rotation matrix about Z axis
252 // theta is in radians
CreateRotationZ(float theta)253 Matrix4 CreateRotationZ(float theta)
254 {
255     return { {
256         { std::cos(theta), std::sin(theta), 0.0f, 0.0f },
257         { -std::sin(theta), std::cos(theta), 0.0f, 0.0f },
258         { 0.0f, 0.0f, 1.0f, 0.0f },
259         { 0.0f, 0.0f, 0.0f, 1.0f },
260     } };
261 }
262 
263 // Create a 3D translation matrix
CreateTranslation(const Vector3 & trans)264 Matrix4 CreateTranslation(const Vector3& trans)
265 {
266     return { {
267         { 1.0f, 0.0f, 0.0f, 0.0f },
268         { 0.0f, 1.0f, 0.0f, 0.0f },
269         { 0.0f, 0.0f, 1.0f, 0.0f },
270         { trans.x_, trans.y_, trans.z_, 1.0f },
271     } };
272 }
273 
CreateLookAt(const Vector3 & eye,const Vector3 & target,const Vector3 & up)274 Matrix4 CreateLookAt(const Vector3& eye, const Vector3& target, const Vector3& up)
275 {
276     Vector3 zaxis = Vector3::Normalize(target - eye);
277     Vector3 xaxis = Vector3::Normalize(Vector3::Cross(up, zaxis));
278     Vector3 yaxis = Vector3::Normalize(Vector3::Cross(zaxis, xaxis));
279     Vector3 trans;
280     trans.x_ = -Vector3::Dot(xaxis, eye);
281     trans.y_ = -Vector3::Dot(yaxis, eye);
282     trans.z_ = -Vector3::Dot(zaxis, eye);
283 
284     return { {
285         { xaxis.x_, yaxis.x_, zaxis.x_, 0.0f },
286         { xaxis.y_, yaxis.y_, zaxis.y_, 0.0f },
287         { xaxis.z_, yaxis.z_, zaxis.z_, 0.0f },
288         { trans.x_, trans.y_, trans.z_, 1.0f }
289     } };
290 }
291 
CreatePerspective(const Vector3 & camera)292 Matrix4 CreatePerspective(const Vector3& camera)
293 {
294     return { {
295         { std::abs(camera.z_), 0.0f,                0.0f, 0.0f },
296         { 0.0f,                std::abs(camera.z_), 0.0f, 0.0f },
297         { camera.x_,           camera.y_,           0.0f, 1.0f },
298         { 0.0f,                0.0f,                1.0f, 0.0f },
299     } };
300 }
301 
302 // Transform a Vector2 in xy-plane by matrix3
Transform(const Vector2 & vec,const Matrix3 & mat)303 Vector2 Transform(const Vector2& vec, const Matrix3& mat)
304 {
305     Vector2 retVal;
306     retVal.x_ = vec.x_ * mat.mat_[0][0] + vec.y_ * mat.mat_[1][0] + mat.mat_[2][0];
307     retVal.y_ = vec.x_ * mat.mat_[0][1] + vec.y_ * mat.mat_[1][1] + mat.mat_[2][1];
308     return retVal;
309 }
310 
311 // Transform a Vector3 in 3D world by matrix4
Transform(const Vector3 & vec,const Matrix4 & mat)312 Vector3 Transform(const Vector3& vec, const Matrix4& mat)
313 {
314     Vector3 retVal;
315     retVal.x_ = vec.x_ * mat.mat_[0][0] + vec.y_ * mat.mat_[1][0] +
316         vec.z_ * mat.mat_[2][0] + mat.mat_[3][0]; // 2: row2, 3: row3
317     retVal.y_ = vec.x_ * mat.mat_[0][1] + vec.y_ * mat.mat_[1][1] +
318         vec.z_ * mat.mat_[2][1] + mat.mat_[3][1];
319     retVal.z_ = vec.x_ * mat.mat_[0][2] + vec.y_ * mat.mat_[1][2] +
320         vec.z_ * mat.mat_[2][2] + mat.mat_[3][2];
321     return retVal;
322 }
323 
324 // Transform the vector and renormalize the w component
TransformWithPerspDiv(const Vector3 & vec,const Matrix4 & mat,float w)325 Vector3 TransformWithPerspDiv(const Vector3& vec, const Matrix4& mat, float w)
326 {
327     Vector3 retVal;
328     retVal.x_ = vec.x_ * mat.mat_[0][0] + vec.y_ * mat.mat_[1][0] +
329         vec.z_ * mat.mat_[2][0] + w * mat.mat_[3][0]; // 2: row2, 3: row3
330     retVal.y_ = vec.x_ * mat.mat_[0][1] + vec.y_ * mat.mat_[1][1] +
331         vec.z_ * mat.mat_[2][1] + w * mat.mat_[3][1]; // 2: row2, 3: row3
332     retVal.z_ = vec.x_ * mat.mat_[0][2] + vec.y_ * mat.mat_[1][2] +
333         vec.z_ * mat.mat_[2][2] + w * mat.mat_[3][2]; // 2: row2, 3: row3
334     float transformedW = vec.x_ * mat.mat_[0][3] + vec.y_ * mat.mat_[1][3] +
335         vec.z_ * mat.mat_[2][3] + w * mat.mat_[3][3]; // 2: row2, 3: row3
336     if (!MathHelper::NearZero(transformedW)) {
337         transformedW = 1.0f / transformedW;
338         retVal *= transformedW;
339     }
340     return retVal;
341 }
342 
343 // Given a screen point, unprojects it into origin position at screen,
344 // based on the current transform matrix
GetOriginScreenPoint(const Vector2 & p,const Matrix4 & mat)345 Vector2 GetOriginScreenPoint(const Vector2& p, const Matrix4& mat)
346 {
347     Matrix4 invertMat = mat;
348     invertMat.Invert();
349     // Get start point
350     Vector3 screenPoint(p.x_, p.y_, 0.1f);
351     Vector3 start = TransformWithPerspDiv(screenPoint, invertMat);
352     // Get end point
353     screenPoint.z_ = 0.9f;
354     Vector3 end = TransformWithPerspDiv(screenPoint, invertMat);
355     // Get the intersection point of line start-end and xy plane
356     float t = end.z_ / (end.z_ - start.z_);
357     return Vector2(t * start.x_ + (1 - t) * end.x_, t * start.y_ + (1 - t) * end.y_);
358 }
359 } // namespace TransformHelper
360 } // namespace OHOS::Rosen
361