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