1/*
2 * Copyright (c) 2022-2023 Shenzhen Kaihong Digital Industry Development 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
16const NO_INITIAL_VAL = -1;
17
18export class XMat4 {
19  constructor() {
20    this.unit();
21  }
22
23  Get() {
24    return this.mat;
25  }
26  unit() {
27    this.mat = [
28      [1, 0, 0, 0],
29      [0, 1, 0, 0],
30      [0, 0, 1, 0],
31      [0, 0, 0, 1],
32    ];
33    return this;
34  }
35  copy(m) {
36    for (let i = 0; i < 4; i++) {
37      for (let j = 0; j < 4; j++) {
38        this.mat[i][j] = m.mat[i][j];
39      }
40    }
41  }
42  initRotateMatX(hd) {
43    this.unit();
44    let _cos = Math.cos(hd);
45    let _sin = Math.sin(hd);
46    this.mat[1][1] = _cos;
47    this.mat[1][2] = -_sin;
48    this.mat[2][1] = _sin;
49    this.mat[2][2] = _cos;
50  }
51  initRotateMatY(hd) {
52    this.unit();
53    let _cos = Math.cos(hd);
54    let _sin = Math.sin(hd);
55    this.mat[0][0] = _cos;
56    this.mat[0][2] = -_sin;
57    this.mat[2][0] = _sin;
58    this.mat[2][2] = _cos;
59  }
60
61  initRotateMatZ(hd) {
62    this.unit();
63    let _cos = Math.cos(hd);
64    let _sin = Math.sin(hd);
65    this.mat[0][0] = _cos;
66    this.mat[0][1] = -_sin;
67    this.mat[1][0] = _sin;
68    this.mat[1][1] = _cos;
69  }
70  initScaleMat(x, y, z) {
71    this.unit();
72    this.mat[0][0] = x;
73    this.mat[1][1] = y;
74    this.mat[2][2] = z;
75  }
76  move(x, y, z = 0) {
77    this.mat[3][0] += x;
78    this.mat[3][1] += y;
79    this.mat[3][2] += z;
80    return this;
81  }
82  rotate(x, y, z) {
83    if (x !== 0) {
84      tmpmat.initRotateMatX((x * Math.PI) / 180);
85      this.mult(tmpmat);
86    }
87    if (y !== 0) {
88      tmpmat.initRotateMatY((y * Math.PI) / 180);
89      this.mult(tmpmat);
90    }
91    if (z !== 0) {
92      tmpmat.initRotateMatZ((z * Math.PI) / 180);
93      this.mult(tmpmat);
94    }
95    return this;
96  }
97
98  scale(x, y, z = 1) {
99    tmpmat.initScaleMat(x, y, z);
100    this.mult(tmpmat);
101    return this;
102  }
103
104  mult(m4) {
105    let tmp = [
106      [1, 0, 0, 0],
107      [0, 1, 0, 0],
108      [0, 0, 1, 0],
109      [0, 0, 0, 1],
110    ];
111    for (let i = 0; i < 4; i++) {
112      for (let j = 0; j < 4; j++) {
113        tmp[i][j] =
114          this.mat[i][0] * m4.mat[0][j] +
115          this.mat[i][1] * m4.mat[1][j] +
116          this.mat[i][2] * m4.mat[2][j] +
117          this.mat[i][3] * m4.mat[3][j];
118      }
119    }
120    this.mat = tmp;
121    return this;
122  }
123
124  MultRight(m4) {
125    this.mat = np.dot(m4.mat, this.mat);
126    return this;
127  }
128
129  PerspectiveMatrix(n, f, w = NO_INITIAL_VAL, h = NO_INITIAL_VAL) {
130    if (w === NO_INITIAL_VAL) {
131      w = Scr.logicw;
132    }
133    if (h === NO_INITIAL_VAL) {
134      h = Scr.logich;
135    }
136    let ret = w / (tan((30 * pi) / 180) * 2);
137    this.unit();
138    this.mat[0][0] = 2 / w;
139    this.mat[1][1] = 2 / h;
140
141    this.mat[2][2] = 1 / (f - n);
142    this.mat[2][3] = 1 / ret; //#2 / f
143    this.mat[3][2] = -n / (f - n);
144    this.mat[3][3] = 1;
145    return ret;
146  }
147
148  orthoMat(x, y, w, h) {
149    this.move(-w / 2 - x, -h / 2 - y, 0);
150    this.scale(2 / w, -2 / h, 0);
151  }
152
153  Make2DTransformMat(mx = 0, my = 0, sw = 1, sh = 1, ra = 0, ox = 0, oy = 0, realw = 0, realh = 0) {
154    const LEFT = -1;
155    const MIDDLE = -2;
156    const RIGHT = -3;
157    const UP = -1;
158    const DOWN = -3;
159    const BY_MIDDLE = 2;
160    this.unit();
161    if (ox === LEFT) {
162      ox = 0;
163    }
164    if (ox === MIDDLE) {
165      ox = realw / BY_MIDDLE;
166    }
167    if (ox === RIGHT) {
168      ox = realw;
169    }
170    if (oy === UP) {
171      oy = 0;
172    }
173    if (oy === MIDDLE) {
174      oy = realh / BY_MIDDLE;
175    }
176    if (oy === DOWN) {
177      oy = realh;
178    }
179    if (ox !== 0 || oy !== 0) {
180      this.move(-ox, -oy, 0);
181    }
182    if (sw !== 1 || sh !== 1) {
183      this.scale(sw, sh, 1);
184    }
185    if (ra !== 0) {
186      this.rotate(0, 0, ra);
187    }
188    if (mx !== 0 || my !== 0) {
189      this.move(mx, my, 0);
190    }
191  }
192
193  Make2DTransformMat_(mx, my, sw, sh, ra, ox = 0, oy = 0) {
194    this.unit();
195    if (mx !== 0 || my !== 0) {
196      this.move(-mx, -my, 0);
197    }
198    if (ra !== 0) {
199      this.rotate(0, 0, -ra);
200    }
201    if (sw !== 1 || sh !== 1) {
202      this.scale(1 / sw, 1 / sh, 1);
203    }
204    return this;
205  }
206}
207
208var tmpmat = new XMat4();
209