1"use strict"; 2/* 3 * Copyright (c) 2022-2025 Huawei Device Co., Ltd. 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16Object.defineProperty(exports, "__esModule", { value: true }); 17exports.Matrix44 = exports.mat44 = void 0; 18const compat_1 = require("#koalaui/compat"); 19const Matrix33_1 = require("./Matrix33"); 20const Point3_1 = require("./Point3"); 21// TODO: this is because ArkTS doesn allow interface literal instances. 22class TranslateOptionsImpl { 23 get x() { return this._x; } 24 get y() { return this._y; } 25 get z() { return this._z; } 26 set x(x) { this._x = x; } 27 set y(y) { this._y = y; } 28 set z(z) { this._z = z; } 29 constructor(x, y, z) { 30 this._x = x; 31 this._y = y; 32 this._z = z; 33 } 34} 35function mat44(array) { 36 return (array == undefined) ? new Matrix44() : new Matrix44(array); 37} 38exports.mat44 = mat44; 39/** 40 * 4x4 matrix with right-handed coordinate system: 41 * +x goes to the right 42 * +y goes down 43 * +z goes into the screen (away from the viewer) 44 */ 45class Matrix44 { 46 constructor(array = new Float32Array((0, compat_1.Array_from_number)([ 47 1.0, 0.0, 0.0, 0.0, 48 0.0, 1.0, 0.0, 0.0, 49 0.0, 0.0, 1.0, 0.0, 50 0.0, 0.0, 0.0, 1.0 51 ]))) { 52 this.array = array.slice(); 53 } 54 static identity() { 55 return mat44(); 56 } 57 static zero() { 58 return mat44(new Float32Array((0, compat_1.Array_from_number)([ 59 0.0, 0.0, 0.0, 0.0, 60 0.0, 0.0, 0.0, 0.0, 61 0.0, 0.0, 0.0, 0.0, 62 0.0, 0.0, 0.0, 0.0, 63 ]))); 64 } 65 static lookAt(eye, center, up) { 66 const f = center.subtract(eye).normalize(); 67 const u = up.normalize(); 68 const s = f.cross(u).normalize(); 69 const sf = s.cross(f); 70 return new Matrix44(new Float32Array((0, compat_1.Array_from_number)([ 71 s.x, sf.x, -f.x, eye.x, 72 s.y, sf.y, -f.y, eye.y, 73 s.z, sf.z, -f.z, eye.z, 74 0, 0, 0, 1, 75 ]))).invert(); 76 } 77 static perspective(depth) { 78 return new Matrix44(new Float32Array((0, compat_1.Array_from_number)([ 79 1.0, 0.0, 0.0, 0.0, 80 0.0, 1.0, 0.0, 0.0, 81 0.0, 0.0, 1.0, 0.0, 82 0.0, 0.0, -1.0 / depth, 1.0, 83 ]))); 84 } 85 static perspectiveFov(fov, near, far) { 86 const denomInv = (far - near); 87 const halfAngle = fov * 0.5; 88 const cot = Math.cos(halfAngle) / Math.sin(halfAngle); 89 return new Matrix44(new Float32Array((0, compat_1.Array_from_number)([ 90 cot, 0.0, 0.0, 0.0, 91 0.0, cot, 0.0, 0.0, 92 0.0, 0.0, (far + near) * denomInv, 2 * far * near * denomInv, 93 0.0, 0.0, -1.0, 0.0, 94 ]))); 95 } 96 /** 97 * Returns new matrix, made from Matrix33. 98 * 99 * @param matrix - 3x3 matrix 100 * @returns the new instance of Matrix44 101 * 102 */ 103 static makeFromMatrix33(matrix) { 104 return new Matrix44(new Float32Array((0, compat_1.Array_from_number)([ 105 matrix.array[0], matrix.array[1], 0.0, matrix.array[2], 106 matrix.array[3], matrix.array[4], 0.0, matrix.array[5], 107 0.0, 0.0, 1.0, 0.0, 108 matrix.array[6], matrix.array[7], 0.0, matrix.array[8] 109 ]))); 110 } 111 /** 112 * Returns new 3x3 matrix, made from this matrix by dropping the third row and the third column. 113 * 114 * @returns the new instance of Matrix33 115 * 116 */ 117 asMatrix33() { 118 return new Matrix33_1.Matrix33(new Float32Array((0, compat_1.Array_from_number)([ 119 this.array[0], this.array[1], this.array[3], 120 this.array[4], this.array[5], this.array[7], 121 this.array[12], this.array[13], this.array[15] 122 ]))); 123 } 124 copy() { 125 return new Matrix44(new Float32Array((0, compat_1.Array_from_number)([ 126 this.array[0], this.array[1], this.array[2], this.array[3], 127 this.array[4], this.array[5], this.array[6], this.array[7], 128 this.array[8], this.array[9], this.array[10], this.array[11], 129 this.array[12], this.array[13], this.array[14], this.array[15] 130 ]))); 131 } 132 concat(matrix) { 133 const result = new Float32Array((0, compat_1.Array_from_number)([ 134 1.0, 0.0, 0.0, 0.0, 135 0.0, 1.0, 0.0, 0.0, 136 0.0, 0.0, 1.0, 0.0, 137 0.0, 0.0, 0.0, 1.0, 138 ])); 139 for (let row = 0; row < 4; row++) { 140 for (let col = 0; col < 4; col++) { 141 let num = 0; 142 for (let k = 0; k < 4; k++) { 143 num += this.array[row * 4 + k] * matrix.array[col + 4 * k]; 144 } 145 result[row * 4 + col] = num; 146 } 147 } 148 for (let i = 0; i < this.array.length; i++) { 149 this.array[i] = result[i]; 150 } 151 return this; 152 } 153 scale(options) { 154 var _a, _b, _c, _d, _e, _f, _g, _h, _j; 155 const scaled = new Matrix44(); 156 scaled.array[0] = (_a = options.x) !== null && _a !== void 0 ? _a : 1.0; 157 scaled.array[5] = (_b = options.y) !== null && _b !== void 0 ? _b : 1.0; 158 scaled.array[10] = (_c = options.z) !== null && _c !== void 0 ? _c : 1.0; 159 this.translate(new TranslateOptionsImpl(-((_d = options.pivotX) !== null && _d !== void 0 ? _d : 0.0) * ((_e = options.x) !== null && _e !== void 0 ? _e : 1.0) + ((_f = options.pivotX) !== null && _f !== void 0 ? _f : 0.0), -((_g = options.pivotY) !== null && _g !== void 0 ? _g : 0.0) * ((_h = options.y) !== null && _h !== void 0 ? _h : 1.0) + ((_j = options.pivotY) !== null && _j !== void 0 ? _j : 0.0), undefined)).concat(scaled); 160 return this; 161 } 162 rotate(options) { 163 var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k; 164 const translationToPivot = mat44().translate(new TranslateOptionsImpl(((_a = options.pivotX) !== null && _a !== void 0 ? _a : 0.0), ((_b = options.pivotY) !== null && _b !== void 0 ? _b : 0.0), ((_c = options.pivotZ) !== null && _c !== void 0 ? _c : 0.0))); 165 const translationToBack = mat44().translate(new TranslateOptionsImpl(-((_d = options.pivotX) !== null && _d !== void 0 ? _d : 0.0), -((_e = options.pivotY) !== null && _e !== void 0 ? _e : 0.0), -((_f = options.pivotZ) !== null && _f !== void 0 ? _f : 0.0))); 166 const vec = new Point3_1.Point3((_g = options.x) !== null && _g !== void 0 ? _g : 0.0, (_h = options.y) !== null && _h !== void 0 ? _h : 0.0, (_j = options.z) !== null && _j !== void 0 ? _j : 0.0).normalize(); 167 const rads = ((_k = options.angle) !== null && _k !== void 0 ? _k : 0.0) * Math.PI / 180; 168 let c = Math.cos(rads); 169 let s = Math.sin(rads); 170 const tolerance = (1.0 / (1 << 12)); 171 if (Math.abs(s) <= tolerance) 172 s = 0.0; 173 if (Math.abs(c) <= tolerance) 174 c = 0.0; 175 let t = 1 - c; 176 const x = vec.x; 177 const y = vec.y; 178 const z = vec.z; 179 const rotation = mat44(); 180 rotation.array[0] = t * x * x + c; 181 rotation.array[1] = t * x * y - s * z; 182 rotation.array[2] = t * x * z + s * y; 183 rotation.array[3] = 0; 184 rotation.array[4] = t * x * y + s * z; 185 rotation.array[5] = t * y * y + c; 186 rotation.array[6] = t * y * z - s * x; 187 rotation.array[7] = 0; 188 rotation.array[8] = t * x * z - s * y; 189 rotation.array[9] = t * y * z + s * x; 190 rotation.array[10] = t * z * z + c; 191 rotation.array[11] = 0; 192 rotation.array[12] = 0; 193 rotation.array[13] = 0; 194 rotation.array[14] = 0; 195 rotation.array[15] = 1; 196 this.concat(translationToPivot).concat(rotation).concat(translationToBack); 197 return this; 198 } 199 translate(options) { 200 var _a, _b, _c; 201 this.array[3] = (_a = options.x) !== null && _a !== void 0 ? _a : 0.0; 202 this.array[7] = (_b = options.y) !== null && _b !== void 0 ? _b : 0.0; 203 this.array[11] = (_c = options.z) !== null && _c !== void 0 ? _c : 0.0; 204 return this; 205 } 206 invert() { 207 const result = new Float32Array(16); 208 let a00 = this.array[0]; 209 let a01 = this.array[1]; 210 let a02 = this.array[2]; 211 let a03 = this.array[3]; 212 let a10 = this.array[4]; 213 let a11 = this.array[5]; 214 let a12 = this.array[6]; 215 let a13 = this.array[7]; 216 let a20 = this.array[8]; 217 let a21 = this.array[9]; 218 let a22 = this.array[10]; 219 let a23 = this.array[11]; 220 let a30 = this.array[12]; 221 let a31 = this.array[13]; 222 let a32 = this.array[14]; 223 let a33 = this.array[15]; 224 let b00 = a00 * a11 - a01 * a10; 225 let b01 = a00 * a12 - a02 * a10; 226 let b02 = a00 * a13 - a03 * a10; 227 let b03 = a01 * a12 - a02 * a11; 228 let b04 = a01 * a13 - a03 * a11; 229 let b05 = a02 * a13 - a03 * a12; 230 let b06 = a20 * a31 - a21 * a30; 231 let b07 = a20 * a32 - a22 * a30; 232 let b08 = a20 * a33 - a23 * a30; 233 let b09 = a21 * a32 - a22 * a31; 234 let b10 = a21 * a33 - a23 * a31; 235 let b11 = a22 * a33 - a23 * a32; 236 let determinant = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; 237 let invdet = 1.0 / determinant; 238 b00 *= invdet; 239 b01 *= invdet; 240 b02 *= invdet; 241 b03 *= invdet; 242 b04 *= invdet; 243 b05 *= invdet; 244 b06 *= invdet; 245 b07 *= invdet; 246 b08 *= invdet; 247 b09 *= invdet; 248 b10 *= invdet; 249 b11 *= invdet; 250 result[0] = a11 * b11 - a12 * b10 + a13 * b09; 251 result[1] = a02 * b10 - a01 * b11 - a03 * b09; 252 result[2] = a31 * b05 - a32 * b04 + a33 * b03; 253 result[3] = a22 * b04 - a21 * b05 - a23 * b03; 254 result[4] = a12 * b08 - a10 * b11 - a13 * b07; 255 result[5] = a00 * b11 - a02 * b08 + a03 * b07; 256 result[6] = a32 * b02 - a30 * b05 - a33 * b01; 257 result[7] = a20 * b05 - a22 * b02 + a23 * b01; 258 result[8] = a10 * b10 - a11 * b08 + a13 * b06; 259 result[9] = a01 * b08 - a00 * b10 - a03 * b06; 260 result[10] = a30 * b04 - a31 * b02 + a33 * b00; 261 result[11] = a21 * b02 - a20 * b04 - a23 * b00; 262 result[12] = a11 * b07 - a10 * b09 - a12 * b06; 263 result[13] = a00 * b09 - a01 * b07 + a02 * b06; 264 result[14] = a31 * b01 - a30 * b03 - a32 * b00; 265 result[15] = a20 * b03 - a21 * b01 + a22 * b00; 266 // If 1/det overflows to infinity (i.e. det is denormalized) or any of the inverted matrix 267 // values is non-finite, return zero to indicate a non-invertible matrix. 268 let prod = 0; 269 for (let i = 0; i < result.length; ++i) { 270 prod *= result[i]; 271 } 272 // At this point, prod will either be NaN or 0 273 // if prod is NaN, this check will return false 274 if (prod == 0) { 275 for (let i = 0; i < this.array.length; i++) { 276 this.array[i] = result[i]; 277 } 278 } 279 return this; 280 } 281 transpose() { 282 const result = new Float32Array(16); 283 result[0] = this.array[0]; 284 result[1] = this.array[4]; 285 result[2] = this.array[8]; 286 result[3] = this.array[12]; 287 result[4] = this.array[1]; 288 result[5] = this.array[5]; 289 result[6] = this.array[9]; 290 result[7] = this.array[13]; 291 result[8] = this.array[2]; 292 result[9] = this.array[6]; 293 result[10] = this.array[10]; 294 result[11] = this.array[14]; 295 result[12] = this.array[3]; 296 result[13] = this.array[7]; 297 result[14] = this.array[11]; 298 result[15] = this.array[15]; 299 for (let i = 0; i < this.array.length; i++) { 300 this.array[i] = result[i]; 301 } 302 return this; 303 } 304 skew(x, y) { 305 this.array[1] += x !== null && x !== void 0 ? x : 0.0; 306 this.array[4] += y !== null && y !== void 0 ? y : 0.0; 307 return this; 308 } 309} 310exports.Matrix44 = Matrix44; 311//# sourceMappingURL=Matrix44.js.map