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