@kiberon-labs/behave-graph-scene 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +34 -0
- package/src/Abstractions/Drivers/DummyScene.ts +79 -0
- package/src/Abstractions/IScene.ts +18 -0
- package/src/GLTFJson.ts +34 -0
- package/src/Nodes/Actions/EaseSceneProperty.ts +162 -0
- package/src/Nodes/Actions/SetSceneProperty.ts +35 -0
- package/src/Nodes/Events/OnSceneNodeClick.ts +66 -0
- package/src/Nodes/Logic/ColorNodes.ts +121 -0
- package/src/Nodes/Logic/EulerNodes.ts +115 -0
- package/src/Nodes/Logic/Mat3Nodes.ts +202 -0
- package/src/Nodes/Logic/Mat4Nodes.ts +257 -0
- package/src/Nodes/Logic/QuatNodes.ts +178 -0
- package/src/Nodes/Logic/Vec2Nodes.ts +111 -0
- package/src/Nodes/Logic/Vec3Nodes.ts +121 -0
- package/src/Nodes/Logic/Vec4Nodes.ts +112 -0
- package/src/Nodes/Logic/VecElements.ts +34 -0
- package/src/Nodes/Queries/GetSceneProperty.ts +35 -0
- package/src/Values/ColorValue.ts +22 -0
- package/src/Values/EulerValue.ts +22 -0
- package/src/Values/Internal/Mat2.ts +214 -0
- package/src/Values/Internal/Mat3.ts +422 -0
- package/src/Values/Internal/Mat4.ts +831 -0
- package/src/Values/Internal/Vec2.ts +97 -0
- package/src/Values/Internal/Vec3.ts +244 -0
- package/src/Values/Internal/Vec4.ts +350 -0
- package/src/Values/Mat3Value.ts +20 -0
- package/src/Values/Mat4Value.ts +20 -0
- package/src/Values/QuatValue.ts +22 -0
- package/src/Values/Vec2Value.ts +14 -0
- package/src/Values/Vec3Value.ts +22 -0
- package/src/Values/Vec4Value.ts +21 -0
- package/src/buildScene.ts +479 -0
- package/src/index.ts +38 -0
- package/src/loadScene.ts +81 -0
- package/src/registerSceneProfile.ts +105 -0
- package/tests/graphs/logic/Color.json +53 -0
- package/tests/graphs/logic/Euler.json +53 -0
- package/tests/graphs/logic/Quaternion.json +56 -0
- package/tests/graphs/logic/Vector2.json +50 -0
- package/tests/graphs/logic/Vector3.json +53 -0
- package/tests/graphs/logic/Vector4.json +56 -0
- package/tests/readSceneGraphs.test.ts +57 -0
- package/tests/registerSceneProfile.test.ts +62 -0
- package/tests/tsconfig.json +11 -0
- package/tests/values/internal/Vec2.test.ts +74 -0
- package/tests/values/internal/Vec3.test.ts +83 -0
- package/tests/values/internal/Vec4.test.ts +91 -0
- package/tsconfig.json +55 -0
- package/tsdown.config.ts +13 -0
- package/vitest.config.ts +15 -0
|
@@ -0,0 +1,831 @@
|
|
|
1
|
+
import {
|
|
2
|
+
EPSILON,
|
|
3
|
+
equalsTolerance,
|
|
4
|
+
parseSafeFloats,
|
|
5
|
+
toSafeString
|
|
6
|
+
} from '@kiberon-labs/behave-graph';
|
|
7
|
+
|
|
8
|
+
import { eulerToMat3, Mat3, quatToMat3 } from './Mat3.js';
|
|
9
|
+
import { Vec2 } from './Vec2.js';
|
|
10
|
+
import {
|
|
11
|
+
Vec3,
|
|
12
|
+
vec3Cross,
|
|
13
|
+
vec3Length,
|
|
14
|
+
vec3MultiplyByScalar,
|
|
15
|
+
vec3Normalize,
|
|
16
|
+
vec3Subtract
|
|
17
|
+
} from './Vec3.js';
|
|
18
|
+
import { Vec4 } from './Vec4.js';
|
|
19
|
+
|
|
20
|
+
// uses OpenGL matrix layout where each column is specified subsequently in order from left to right.
|
|
21
|
+
// ( x, y, z, 1 ) x [ 0 4 8 12] = ( x', y', z', 1 )
|
|
22
|
+
// [ 1 5 9 13]
|
|
23
|
+
// [ 2 6 10 14]
|
|
24
|
+
// [ 3 7 11 15]
|
|
25
|
+
// where elements 3, 7, 11 would be translation in 3D, as they would multiplied
|
|
26
|
+
// by the last virtual element of the 3D vector.
|
|
27
|
+
|
|
28
|
+
const NUM_ROWS = 4;
|
|
29
|
+
const NUM_COLUMNS = 4;
|
|
30
|
+
const NUM_ELEMENTS = NUM_ROWS * NUM_COLUMNS;
|
|
31
|
+
|
|
32
|
+
type Mat4Elements = [
|
|
33
|
+
number,
|
|
34
|
+
number,
|
|
35
|
+
number,
|
|
36
|
+
number,
|
|
37
|
+
number,
|
|
38
|
+
number,
|
|
39
|
+
number,
|
|
40
|
+
number,
|
|
41
|
+
number,
|
|
42
|
+
number,
|
|
43
|
+
number,
|
|
44
|
+
number,
|
|
45
|
+
number,
|
|
46
|
+
number,
|
|
47
|
+
number,
|
|
48
|
+
number
|
|
49
|
+
];
|
|
50
|
+
export type Mat4JSON = Mat4Elements;
|
|
51
|
+
|
|
52
|
+
export class Mat4 {
|
|
53
|
+
public elements: Mat4Elements;
|
|
54
|
+
constructor(
|
|
55
|
+
elements: Mat4Elements = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]
|
|
56
|
+
) {
|
|
57
|
+
if (elements.length !== NUM_ELEMENTS) {
|
|
58
|
+
throw new Error(
|
|
59
|
+
`elements must have length ${NUM_ELEMENTS}, got ${elements.length}`
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
this.elements = elements;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
clone(result = new Mat4()): Mat4 {
|
|
66
|
+
return result.set(this.elements);
|
|
67
|
+
}
|
|
68
|
+
set(elements: Mat4Elements): this {
|
|
69
|
+
if (elements.length !== NUM_ELEMENTS) {
|
|
70
|
+
throw new Error(
|
|
71
|
+
`elements must have length ${NUM_ELEMENTS}, got ${elements.length}`
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
this.elements = [...elements];
|
|
75
|
+
return this;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function mat4SetColumn4(
|
|
80
|
+
m: Mat4,
|
|
81
|
+
columnIndex: bigint,
|
|
82
|
+
column: Vec4,
|
|
83
|
+
result = new Mat4()
|
|
84
|
+
): Mat4 {
|
|
85
|
+
const re = result.set(m.elements).elements;
|
|
86
|
+
const base = Number(columnIndex) * NUM_ROWS;
|
|
87
|
+
re[base + 0] = column.x;
|
|
88
|
+
re[base + 1] = column.y;
|
|
89
|
+
re[base + 2] = column.z;
|
|
90
|
+
re[base + 3] = column.w;
|
|
91
|
+
return result;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export function mat4SetRow4(
|
|
95
|
+
m: Mat4,
|
|
96
|
+
rowIndex: bigint,
|
|
97
|
+
row: Vec4,
|
|
98
|
+
result = new Mat4()
|
|
99
|
+
): Mat4 {
|
|
100
|
+
const re = result.set(m.elements).elements;
|
|
101
|
+
const base = Number(rowIndex);
|
|
102
|
+
re[base + NUM_COLUMNS * 0] = row.x;
|
|
103
|
+
re[base + NUM_COLUMNS * 1] = row.y;
|
|
104
|
+
re[base + NUM_COLUMNS * 2] = row.z;
|
|
105
|
+
re[base + NUM_COLUMNS * 3] = row.w;
|
|
106
|
+
return result;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export function column4ToMat4(
|
|
110
|
+
a: Vec4,
|
|
111
|
+
b: Vec4,
|
|
112
|
+
c: Vec4,
|
|
113
|
+
d: Vec4,
|
|
114
|
+
result = new Mat4()
|
|
115
|
+
): Mat4 {
|
|
116
|
+
const re = result.elements;
|
|
117
|
+
const columns = [a, b, c, d];
|
|
118
|
+
for (let c = 0; c < columns.length; c++) {
|
|
119
|
+
const base = c * NUM_ROWS;
|
|
120
|
+
const column = columns[c]!;
|
|
121
|
+
re[base + 0] = column.x;
|
|
122
|
+
re[base + 1] = column.y;
|
|
123
|
+
re[base + 2] = column.z;
|
|
124
|
+
re[base + 3] = column.w;
|
|
125
|
+
}
|
|
126
|
+
return result;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export function mat4Equals(
|
|
130
|
+
a: Mat4,
|
|
131
|
+
b: Mat4,
|
|
132
|
+
tolerance: number = EPSILON
|
|
133
|
+
): boolean {
|
|
134
|
+
for (let i = 0; i < NUM_ELEMENTS; i++) {
|
|
135
|
+
if (!equalsTolerance(a.elements[i]!, b.elements[i]!, tolerance))
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
138
|
+
return true;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export function mat4Add(a: Mat4, b: Mat4, result: Mat4 = new Mat4()): Mat4 {
|
|
142
|
+
result.elements = a.elements.map(
|
|
143
|
+
(a, i) => a + b.elements[i]!
|
|
144
|
+
) as Mat4Elements;
|
|
145
|
+
return result;
|
|
146
|
+
}
|
|
147
|
+
export function mat4Subtract(
|
|
148
|
+
a: Mat4,
|
|
149
|
+
b: Mat4,
|
|
150
|
+
result: Mat4 = new Mat4()
|
|
151
|
+
): Mat4 {
|
|
152
|
+
result.elements = a.elements.map(
|
|
153
|
+
(a, i) => a - b.elements[i]!
|
|
154
|
+
) as Mat4Elements;
|
|
155
|
+
return result;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export function mat4MultiplyByScalar(
|
|
159
|
+
a: Mat4,
|
|
160
|
+
b: number,
|
|
161
|
+
result: Mat4 = new Mat4()
|
|
162
|
+
): Mat4 {
|
|
163
|
+
result.elements = a.elements.map((a) => a * b) as Mat4Elements;
|
|
164
|
+
return result;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export function mat4Negate(a: Mat4, result: Mat4 = new Mat4()): Mat4 {
|
|
168
|
+
result.elements = a.elements.map((a) => -a) as Mat4Elements;
|
|
169
|
+
return result;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
export function mat4Multiply(a: Mat4, b: Mat4, result = new Mat4()): Mat4 {
|
|
173
|
+
const ae = a.elements;
|
|
174
|
+
const be = b.elements;
|
|
175
|
+
const te = result.elements;
|
|
176
|
+
|
|
177
|
+
const a11 = ae[0],
|
|
178
|
+
a12 = ae[4],
|
|
179
|
+
a13 = ae[8],
|
|
180
|
+
a14 = ae[12];
|
|
181
|
+
const a21 = ae[1],
|
|
182
|
+
a22 = ae[5],
|
|
183
|
+
a23 = ae[9],
|
|
184
|
+
a24 = ae[13];
|
|
185
|
+
const a31 = ae[2],
|
|
186
|
+
a32 = ae[6],
|
|
187
|
+
a33 = ae[10],
|
|
188
|
+
a34 = ae[14];
|
|
189
|
+
const a41 = ae[3],
|
|
190
|
+
a42 = ae[7],
|
|
191
|
+
a43 = ae[11],
|
|
192
|
+
a44 = ae[15];
|
|
193
|
+
|
|
194
|
+
const b11 = be[0],
|
|
195
|
+
b12 = be[4],
|
|
196
|
+
b13 = be[8],
|
|
197
|
+
b14 = be[12];
|
|
198
|
+
const b21 = be[1],
|
|
199
|
+
b22 = be[5],
|
|
200
|
+
b23 = be[9],
|
|
201
|
+
b24 = be[13];
|
|
202
|
+
const b31 = be[2],
|
|
203
|
+
b32 = be[6],
|
|
204
|
+
b33 = be[10],
|
|
205
|
+
b34 = be[14];
|
|
206
|
+
const b41 = be[3],
|
|
207
|
+
b42 = be[7],
|
|
208
|
+
b43 = be[11],
|
|
209
|
+
b44 = be[15];
|
|
210
|
+
|
|
211
|
+
// TODO: Replace with set(...)
|
|
212
|
+
te[0] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;
|
|
213
|
+
te[4] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;
|
|
214
|
+
te[8] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;
|
|
215
|
+
te[12] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;
|
|
216
|
+
|
|
217
|
+
te[1] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;
|
|
218
|
+
te[5] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;
|
|
219
|
+
te[9] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;
|
|
220
|
+
te[13] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;
|
|
221
|
+
|
|
222
|
+
te[2] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;
|
|
223
|
+
te[6] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;
|
|
224
|
+
te[10] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;
|
|
225
|
+
te[14] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;
|
|
226
|
+
|
|
227
|
+
te[3] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;
|
|
228
|
+
te[7] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;
|
|
229
|
+
te[11] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;
|
|
230
|
+
te[15] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;
|
|
231
|
+
|
|
232
|
+
return result;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
export function mat4Determinant(m: Mat4): number {
|
|
236
|
+
// based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm
|
|
237
|
+
const me = m.elements,
|
|
238
|
+
n11 = me[0],
|
|
239
|
+
n21 = me[1],
|
|
240
|
+
n31 = me[2],
|
|
241
|
+
n41 = me[3],
|
|
242
|
+
n12 = me[4],
|
|
243
|
+
n22 = me[5],
|
|
244
|
+
n32 = me[6],
|
|
245
|
+
n42 = me[7],
|
|
246
|
+
n13 = me[8],
|
|
247
|
+
n23 = me[9],
|
|
248
|
+
n33 = me[10],
|
|
249
|
+
n43 = me[11],
|
|
250
|
+
n14 = me[12],
|
|
251
|
+
n24 = me[13],
|
|
252
|
+
n34 = me[14],
|
|
253
|
+
n44 = me[15],
|
|
254
|
+
t11 =
|
|
255
|
+
n23 * n34 * n42 -
|
|
256
|
+
n24 * n33 * n42 +
|
|
257
|
+
n24 * n32 * n43 -
|
|
258
|
+
n22 * n34 * n43 -
|
|
259
|
+
n23 * n32 * n44 +
|
|
260
|
+
n22 * n33 * n44,
|
|
261
|
+
t12 =
|
|
262
|
+
n14 * n33 * n42 -
|
|
263
|
+
n13 * n34 * n42 -
|
|
264
|
+
n14 * n32 * n43 +
|
|
265
|
+
n12 * n34 * n43 +
|
|
266
|
+
n13 * n32 * n44 -
|
|
267
|
+
n12 * n33 * n44,
|
|
268
|
+
t13 =
|
|
269
|
+
n13 * n24 * n42 -
|
|
270
|
+
n14 * n23 * n42 +
|
|
271
|
+
n14 * n22 * n43 -
|
|
272
|
+
n12 * n24 * n43 -
|
|
273
|
+
n13 * n22 * n44 +
|
|
274
|
+
n12 * n23 * n44,
|
|
275
|
+
t14 =
|
|
276
|
+
n14 * n23 * n32 -
|
|
277
|
+
n13 * n24 * n32 -
|
|
278
|
+
n14 * n22 * n33 +
|
|
279
|
+
n12 * n24 * n33 +
|
|
280
|
+
n13 * n22 * n34 -
|
|
281
|
+
n12 * n23 * n34;
|
|
282
|
+
|
|
283
|
+
return n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14;
|
|
284
|
+
}
|
|
285
|
+
export function mat4Adjoint(m: Mat4, result = new Mat4()): Mat4 {
|
|
286
|
+
// from gl-matrix
|
|
287
|
+
const a = m.elements;
|
|
288
|
+
const out = result.elements;
|
|
289
|
+
const a00 = a[0],
|
|
290
|
+
a01 = a[1],
|
|
291
|
+
a02 = a[2],
|
|
292
|
+
a03 = a[3];
|
|
293
|
+
const a10 = a[4],
|
|
294
|
+
a11 = a[5],
|
|
295
|
+
a12 = a[6],
|
|
296
|
+
a13 = a[7];
|
|
297
|
+
const a20 = a[8],
|
|
298
|
+
a21 = a[9],
|
|
299
|
+
a22 = a[10],
|
|
300
|
+
a23 = a[11];
|
|
301
|
+
const a30 = a[12],
|
|
302
|
+
a31 = a[13],
|
|
303
|
+
a32 = a[14],
|
|
304
|
+
a33 = a[15];
|
|
305
|
+
|
|
306
|
+
const b00 = a00 * a11 - a01 * a10;
|
|
307
|
+
const b01 = a00 * a12 - a02 * a10;
|
|
308
|
+
const b02 = a00 * a13 - a03 * a10;
|
|
309
|
+
const b03 = a01 * a12 - a02 * a11;
|
|
310
|
+
const b04 = a01 * a13 - a03 * a11;
|
|
311
|
+
const b05 = a02 * a13 - a03 * a12;
|
|
312
|
+
const b06 = a20 * a31 - a21 * a30;
|
|
313
|
+
const b07 = a20 * a32 - a22 * a30;
|
|
314
|
+
const b08 = a20 * a33 - a23 * a30;
|
|
315
|
+
const b09 = a21 * a32 - a22 * a31;
|
|
316
|
+
const b10 = a21 * a33 - a23 * a31;
|
|
317
|
+
const b11 = a22 * a33 - a23 * a32;
|
|
318
|
+
|
|
319
|
+
out[0] = a11 * b11 - a12 * b10 + a13 * b09;
|
|
320
|
+
out[1] = a02 * b10 - a01 * b11 - a03 * b09;
|
|
321
|
+
out[2] = a31 * b05 - a32 * b04 + a33 * b03;
|
|
322
|
+
out[3] = a22 * b04 - a21 * b05 - a23 * b03;
|
|
323
|
+
out[4] = a12 * b08 - a10 * b11 - a13 * b07;
|
|
324
|
+
out[5] = a00 * b11 - a02 * b08 + a03 * b07;
|
|
325
|
+
out[6] = a32 * b02 - a30 * b05 - a33 * b01;
|
|
326
|
+
out[7] = a20 * b05 - a22 * b02 + a23 * b01;
|
|
327
|
+
out[8] = a10 * b10 - a11 * b08 + a13 * b06;
|
|
328
|
+
out[9] = a01 * b08 - a00 * b10 - a03 * b06;
|
|
329
|
+
out[10] = a30 * b04 - a31 * b02 + a33 * b00;
|
|
330
|
+
out[11] = a21 * b02 - a20 * b04 - a23 * b00;
|
|
331
|
+
out[12] = a11 * b07 - a10 * b09 - a12 * b06;
|
|
332
|
+
out[13] = a00 * b09 - a01 * b07 + a02 * b06;
|
|
333
|
+
out[14] = a31 * b01 - a30 * b03 - a32 * b00;
|
|
334
|
+
out[15] = a20 * b03 - a21 * b01 + a22 * b00;
|
|
335
|
+
return result;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
export function mat4Transpose(m: Mat4, result = new Mat4()): Mat4 {
|
|
339
|
+
const re = m.clone(result).elements;
|
|
340
|
+
let tmp;
|
|
341
|
+
|
|
342
|
+
// TODO: replace this with just reading from me and setting re, no need for a temporary
|
|
343
|
+
tmp = re[1];
|
|
344
|
+
re[1] = re[4];
|
|
345
|
+
re[4] = tmp;
|
|
346
|
+
tmp = re[2];
|
|
347
|
+
re[2] = re[8];
|
|
348
|
+
re[8] = tmp;
|
|
349
|
+
tmp = re[6];
|
|
350
|
+
re[6] = re[9];
|
|
351
|
+
re[9] = tmp;
|
|
352
|
+
|
|
353
|
+
tmp = re[3];
|
|
354
|
+
re[3] = re[12];
|
|
355
|
+
re[12] = tmp;
|
|
356
|
+
tmp = re[7];
|
|
357
|
+
re[7] = re[13];
|
|
358
|
+
re[13] = tmp;
|
|
359
|
+
tmp = re[11];
|
|
360
|
+
re[11] = re[14];
|
|
361
|
+
re[14] = tmp;
|
|
362
|
+
|
|
363
|
+
return result;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
export function mat4Inverse(m: Mat4, result = new Mat4()): Mat4 {
|
|
367
|
+
// based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm
|
|
368
|
+
const me = m.elements,
|
|
369
|
+
n11 = me[0],
|
|
370
|
+
n21 = me[1],
|
|
371
|
+
n31 = me[2],
|
|
372
|
+
n41 = me[3],
|
|
373
|
+
n12 = me[4],
|
|
374
|
+
n22 = me[5],
|
|
375
|
+
n32 = me[6],
|
|
376
|
+
n42 = me[7],
|
|
377
|
+
n13 = me[8],
|
|
378
|
+
n23 = me[9],
|
|
379
|
+
n33 = me[10],
|
|
380
|
+
n43 = me[11],
|
|
381
|
+
n14 = me[12],
|
|
382
|
+
n24 = me[13],
|
|
383
|
+
n34 = me[14],
|
|
384
|
+
n44 = me[15],
|
|
385
|
+
t11 =
|
|
386
|
+
n23 * n34 * n42 -
|
|
387
|
+
n24 * n33 * n42 +
|
|
388
|
+
n24 * n32 * n43 -
|
|
389
|
+
n22 * n34 * n43 -
|
|
390
|
+
n23 * n32 * n44 +
|
|
391
|
+
n22 * n33 * n44,
|
|
392
|
+
t12 =
|
|
393
|
+
n14 * n33 * n42 -
|
|
394
|
+
n13 * n34 * n42 -
|
|
395
|
+
n14 * n32 * n43 +
|
|
396
|
+
n12 * n34 * n43 +
|
|
397
|
+
n13 * n32 * n44 -
|
|
398
|
+
n12 * n33 * n44,
|
|
399
|
+
t13 =
|
|
400
|
+
n13 * n24 * n42 -
|
|
401
|
+
n14 * n23 * n42 +
|
|
402
|
+
n14 * n22 * n43 -
|
|
403
|
+
n12 * n24 * n43 -
|
|
404
|
+
n13 * n22 * n44 +
|
|
405
|
+
n12 * n23 * n44,
|
|
406
|
+
t14 =
|
|
407
|
+
n14 * n23 * n32 -
|
|
408
|
+
n13 * n24 * n32 -
|
|
409
|
+
n14 * n22 * n33 +
|
|
410
|
+
n12 * n24 * n33 +
|
|
411
|
+
n13 * n22 * n34 -
|
|
412
|
+
n12 * n23 * n34;
|
|
413
|
+
|
|
414
|
+
const det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14;
|
|
415
|
+
|
|
416
|
+
if (det === 0) {
|
|
417
|
+
throw new Error('can not invert degenerate matrix');
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
const detInv = 1 / det;
|
|
421
|
+
|
|
422
|
+
// TODO: replace with a set
|
|
423
|
+
const re = result.elements;
|
|
424
|
+
re[0] = t11 * detInv;
|
|
425
|
+
re[1] =
|
|
426
|
+
(n24 * n33 * n41 -
|
|
427
|
+
n23 * n34 * n41 -
|
|
428
|
+
n24 * n31 * n43 +
|
|
429
|
+
n21 * n34 * n43 +
|
|
430
|
+
n23 * n31 * n44 -
|
|
431
|
+
n21 * n33 * n44) *
|
|
432
|
+
detInv;
|
|
433
|
+
re[2] =
|
|
434
|
+
(n22 * n34 * n41 -
|
|
435
|
+
n24 * n32 * n41 +
|
|
436
|
+
n24 * n31 * n42 -
|
|
437
|
+
n21 * n34 * n42 -
|
|
438
|
+
n22 * n31 * n44 +
|
|
439
|
+
n21 * n32 * n44) *
|
|
440
|
+
detInv;
|
|
441
|
+
re[3] =
|
|
442
|
+
(n23 * n32 * n41 -
|
|
443
|
+
n22 * n33 * n41 -
|
|
444
|
+
n23 * n31 * n42 +
|
|
445
|
+
n21 * n33 * n42 +
|
|
446
|
+
n22 * n31 * n43 -
|
|
447
|
+
n21 * n32 * n43) *
|
|
448
|
+
detInv;
|
|
449
|
+
|
|
450
|
+
re[4] = t12 * detInv;
|
|
451
|
+
re[5] =
|
|
452
|
+
(n13 * n34 * n41 -
|
|
453
|
+
n14 * n33 * n41 +
|
|
454
|
+
n14 * n31 * n43 -
|
|
455
|
+
n11 * n34 * n43 -
|
|
456
|
+
n13 * n31 * n44 +
|
|
457
|
+
n11 * n33 * n44) *
|
|
458
|
+
detInv;
|
|
459
|
+
re[6] =
|
|
460
|
+
(n14 * n32 * n41 -
|
|
461
|
+
n12 * n34 * n41 -
|
|
462
|
+
n14 * n31 * n42 +
|
|
463
|
+
n11 * n34 * n42 +
|
|
464
|
+
n12 * n31 * n44 -
|
|
465
|
+
n11 * n32 * n44) *
|
|
466
|
+
detInv;
|
|
467
|
+
re[7] =
|
|
468
|
+
(n12 * n33 * n41 -
|
|
469
|
+
n13 * n32 * n41 +
|
|
470
|
+
n13 * n31 * n42 -
|
|
471
|
+
n11 * n33 * n42 -
|
|
472
|
+
n12 * n31 * n43 +
|
|
473
|
+
n11 * n32 * n43) *
|
|
474
|
+
detInv;
|
|
475
|
+
|
|
476
|
+
re[8] = t13 * detInv;
|
|
477
|
+
re[9] =
|
|
478
|
+
(n14 * n23 * n41 -
|
|
479
|
+
n13 * n24 * n41 -
|
|
480
|
+
n14 * n21 * n43 +
|
|
481
|
+
n11 * n24 * n43 +
|
|
482
|
+
n13 * n21 * n44 -
|
|
483
|
+
n11 * n23 * n44) *
|
|
484
|
+
detInv;
|
|
485
|
+
re[10] =
|
|
486
|
+
(n12 * n24 * n41 -
|
|
487
|
+
n14 * n22 * n41 +
|
|
488
|
+
n14 * n21 * n42 -
|
|
489
|
+
n11 * n24 * n42 -
|
|
490
|
+
n12 * n21 * n44 +
|
|
491
|
+
n11 * n22 * n44) *
|
|
492
|
+
detInv;
|
|
493
|
+
re[11] =
|
|
494
|
+
(n13 * n22 * n41 -
|
|
495
|
+
n12 * n23 * n41 -
|
|
496
|
+
n13 * n21 * n42 +
|
|
497
|
+
n11 * n23 * n42 +
|
|
498
|
+
n12 * n21 * n43 -
|
|
499
|
+
n11 * n22 * n43) *
|
|
500
|
+
detInv;
|
|
501
|
+
|
|
502
|
+
re[12] = t14 * detInv;
|
|
503
|
+
re[13] =
|
|
504
|
+
(n13 * n24 * n31 -
|
|
505
|
+
n14 * n23 * n31 +
|
|
506
|
+
n14 * n21 * n33 -
|
|
507
|
+
n11 * n24 * n33 -
|
|
508
|
+
n13 * n21 * n34 +
|
|
509
|
+
n11 * n23 * n34) *
|
|
510
|
+
detInv;
|
|
511
|
+
re[14] =
|
|
512
|
+
(n14 * n22 * n31 -
|
|
513
|
+
n12 * n24 * n31 -
|
|
514
|
+
n14 * n21 * n32 +
|
|
515
|
+
n11 * n24 * n32 +
|
|
516
|
+
n12 * n21 * n34 -
|
|
517
|
+
n11 * n22 * n34) *
|
|
518
|
+
detInv;
|
|
519
|
+
re[15] =
|
|
520
|
+
(n12 * n23 * n31 -
|
|
521
|
+
n13 * n22 * n31 +
|
|
522
|
+
n13 * n21 * n32 -
|
|
523
|
+
n11 * n23 * n32 -
|
|
524
|
+
n12 * n21 * n33 +
|
|
525
|
+
n11 * n22 * n33) *
|
|
526
|
+
detInv;
|
|
527
|
+
|
|
528
|
+
return result;
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
export function mat4Mix(
|
|
532
|
+
a: Mat4,
|
|
533
|
+
b: Mat4,
|
|
534
|
+
t: number,
|
|
535
|
+
result = new Mat4()
|
|
536
|
+
): Mat4 {
|
|
537
|
+
const s = 1 - t;
|
|
538
|
+
for (let i = 0; i < NUM_ELEMENTS; i++) {
|
|
539
|
+
result.elements[i] = a.elements[i]! * s + b.elements[i]! * t;
|
|
540
|
+
}
|
|
541
|
+
return result;
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
export function mat4FromArray(
|
|
545
|
+
array: Float32Array | number[],
|
|
546
|
+
offset = 0,
|
|
547
|
+
result: Mat4 = new Mat4()
|
|
548
|
+
): Mat4 {
|
|
549
|
+
for (let i = 0; i < NUM_ELEMENTS; i++) {
|
|
550
|
+
result.elements[i] = array[offset + i]!;
|
|
551
|
+
}
|
|
552
|
+
return result;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
export function mat4ToArray(
|
|
556
|
+
a: Mat4,
|
|
557
|
+
array: Float32Array | number[],
|
|
558
|
+
offset = 0
|
|
559
|
+
): void {
|
|
560
|
+
for (let i = 0; i < NUM_ELEMENTS; i++) {
|
|
561
|
+
array[offset + i] = a.elements[i]!;
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
export function mat4ToString(a: Mat4): string {
|
|
566
|
+
return toSafeString(a.elements);
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
export function mat4Parse(text: string, result = new Mat4()): Mat4 {
|
|
570
|
+
return mat4FromArray(parseSafeFloats(text), 0, result);
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
export function mat3ToMat4(a: Mat3, result = new Mat4()): Mat4 {
|
|
574
|
+
const ae = a.elements;
|
|
575
|
+
return result.set([
|
|
576
|
+
ae[0],
|
|
577
|
+
ae[1],
|
|
578
|
+
ae[2],
|
|
579
|
+
0,
|
|
580
|
+
ae[3],
|
|
581
|
+
ae[4],
|
|
582
|
+
ae[5],
|
|
583
|
+
0,
|
|
584
|
+
ae[6],
|
|
585
|
+
ae[7],
|
|
586
|
+
ae[8],
|
|
587
|
+
0,
|
|
588
|
+
0,
|
|
589
|
+
0,
|
|
590
|
+
0,
|
|
591
|
+
1
|
|
592
|
+
]);
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
export function eulerToMat4(e: Vec3, result = new Mat4()): Mat4 {
|
|
596
|
+
return mat3ToMat4(eulerToMat3(e), result);
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
export function quatToMat4(q: Vec4, result = new Mat4()): Mat4 {
|
|
600
|
+
return mat3ToMat4(quatToMat3(q), result);
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
export function scale3ToMat4(s: Vec3, result = new Mat4()): Mat4 {
|
|
604
|
+
return result.set([s.x, 0, 0, 0, 0, s.y, 0, 0, 0, 0, s.z, 0, 0, 0, 0, 1]);
|
|
605
|
+
}
|
|
606
|
+
// from gl-matrix
|
|
607
|
+
export function mat4ToScale3(m: Mat4, result = new Vec3()): Vec3 {
|
|
608
|
+
const mat = m.elements;
|
|
609
|
+
const m11 = mat[0];
|
|
610
|
+
const m12 = mat[1];
|
|
611
|
+
const m13 = mat[2];
|
|
612
|
+
const m21 = mat[4];
|
|
613
|
+
const m22 = mat[5];
|
|
614
|
+
const m23 = mat[6];
|
|
615
|
+
const m31 = mat[8];
|
|
616
|
+
const m32 = mat[9];
|
|
617
|
+
const m33 = mat[10];
|
|
618
|
+
|
|
619
|
+
return result.set(
|
|
620
|
+
Math.sqrt(m11 * m11 + m12 * m12 + m13 * m13),
|
|
621
|
+
Math.sqrt(m21 * m21 + m22 * m22 + m23 * m23),
|
|
622
|
+
Math.sqrt(m31 * m31 + m32 * m32 + m33 * m33)
|
|
623
|
+
);
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
export function translation3ToMat4(t: Vec3, result = new Mat4()): Mat4 {
|
|
627
|
+
return result.set([1, 0, 0, t.x, 0, 1, 0, t.y, 0, 0, 1, t.z, 0, 0, 0, 1]);
|
|
628
|
+
}
|
|
629
|
+
export function mat4ToTranslation3(m: Mat4, result = new Vec3()): Vec3 {
|
|
630
|
+
const me = m.elements;
|
|
631
|
+
return result.set(me[3], me[7], me[11]);
|
|
632
|
+
}
|
|
633
|
+
export function mat4Translate(m: Mat4, t: Vec3, result = new Mat4()): Mat4 {
|
|
634
|
+
return mat4Multiply(m, translation3ToMat4(t), result);
|
|
635
|
+
}
|
|
636
|
+
export function mat4Scale(m: Mat4, s: Vec3, result = new Mat4()): Mat4 {
|
|
637
|
+
return mat4Multiply(m, scale3ToMat4(s), result);
|
|
638
|
+
}
|
|
639
|
+
export function mat4RotateByQuat(m: Mat4, q: Vec4, result = new Mat4()): Mat4 {
|
|
640
|
+
return mat4Multiply(m, quatToMat4(q), result);
|
|
641
|
+
}
|
|
642
|
+
export function mat4RotateByEuler(m: Mat4, e: Vec3, result = new Mat4()): Mat4 {
|
|
643
|
+
return mat4Multiply(m, eulerToMat4(e), result);
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
export function mat4TransformPoint3(
|
|
647
|
+
m: Mat4,
|
|
648
|
+
v: Vec4,
|
|
649
|
+
result = new Vec3()
|
|
650
|
+
): Vec3 {
|
|
651
|
+
const x = v.x,
|
|
652
|
+
y = v.y,
|
|
653
|
+
z = v.z;
|
|
654
|
+
const e = m.elements;
|
|
655
|
+
|
|
656
|
+
const w = 1 / (e[3] * x + e[7] * y + e[11] * z + e[15]);
|
|
657
|
+
|
|
658
|
+
result.x = (e[0] * x + e[4] * y + e[8] * z + e[12]) * w;
|
|
659
|
+
result.y = (e[1] * x + e[5] * y + e[9] * z + e[13]) * w;
|
|
660
|
+
result.z = (e[2] * x + e[6] * y + e[10] * z + e[14]) * w;
|
|
661
|
+
|
|
662
|
+
return result;
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
export function mat4TransformNormal3(
|
|
666
|
+
v: Vec3,
|
|
667
|
+
m: Mat4,
|
|
668
|
+
result = new Vec3()
|
|
669
|
+
): Vec3 {
|
|
670
|
+
const x = v.x,
|
|
671
|
+
y = v.y,
|
|
672
|
+
z = v.z;
|
|
673
|
+
const e = m.elements;
|
|
674
|
+
|
|
675
|
+
result.x = e[0] * x + e[4] * y + e[8] * z;
|
|
676
|
+
result.y = e[1] * x + e[5] * y + e[9] * z;
|
|
677
|
+
result.z = e[2] * x + e[6] * y + e[10] * z;
|
|
678
|
+
|
|
679
|
+
return vec3Normalize(result, result);
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
export function mat4Perspective(
|
|
683
|
+
left: number,
|
|
684
|
+
right: number,
|
|
685
|
+
top: number,
|
|
686
|
+
bottom: number,
|
|
687
|
+
near: number,
|
|
688
|
+
far: number,
|
|
689
|
+
result = new Mat4()
|
|
690
|
+
): Mat4 {
|
|
691
|
+
const x = (2 * near) / (right - left);
|
|
692
|
+
const y = (2 * near) / (top - bottom);
|
|
693
|
+
|
|
694
|
+
const a = (right + left) / (right - left);
|
|
695
|
+
const b = (top + bottom) / (top - bottom);
|
|
696
|
+
const c = -(far + near) / (far - near);
|
|
697
|
+
const d = (-2 * far * near) / (far - near);
|
|
698
|
+
|
|
699
|
+
return result.set([x, 0, a, 0, 0, y, b, 0, 0, 0, c, d, 0, 0, -1, 0]);
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
export function mat4PerspectiveFov(
|
|
703
|
+
verticalFov: number,
|
|
704
|
+
near: number,
|
|
705
|
+
far: number,
|
|
706
|
+
zoom: number,
|
|
707
|
+
aspectRatio: number,
|
|
708
|
+
result = new Mat4()
|
|
709
|
+
): Mat4 {
|
|
710
|
+
const height = (2 * near * Math.tan((verticalFov * Math.PI) / 180)) / zoom;
|
|
711
|
+
const width = height * aspectRatio;
|
|
712
|
+
|
|
713
|
+
// NOTE: OpenGL screen coordinates are -bottomt to +top, -left to +right.
|
|
714
|
+
|
|
715
|
+
const right = width * 0.5;
|
|
716
|
+
const left = right - width;
|
|
717
|
+
|
|
718
|
+
const top = height * 0.5;
|
|
719
|
+
const bottom = top - height;
|
|
720
|
+
|
|
721
|
+
return mat4Perspective(left, right, top, bottom, near, far, result);
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
// TODO: Replace with a Box3?
|
|
725
|
+
export function mat4Orthogonal(
|
|
726
|
+
left: number,
|
|
727
|
+
right: number,
|
|
728
|
+
top: number,
|
|
729
|
+
bottom: number,
|
|
730
|
+
near: number,
|
|
731
|
+
far: number,
|
|
732
|
+
result = new Mat4()
|
|
733
|
+
): Mat4 {
|
|
734
|
+
const w = 1 / (right - left);
|
|
735
|
+
const h = 1 / (top - bottom);
|
|
736
|
+
const p = 1 / (far - near);
|
|
737
|
+
|
|
738
|
+
const x = (right + left) * w;
|
|
739
|
+
const y = (top + bottom) * h;
|
|
740
|
+
const z = (far + near) * p;
|
|
741
|
+
|
|
742
|
+
return result.set([
|
|
743
|
+
2 * w,
|
|
744
|
+
0,
|
|
745
|
+
0,
|
|
746
|
+
-x,
|
|
747
|
+
0,
|
|
748
|
+
2 * h,
|
|
749
|
+
0,
|
|
750
|
+
-y,
|
|
751
|
+
0,
|
|
752
|
+
0,
|
|
753
|
+
-2 * p,
|
|
754
|
+
-z,
|
|
755
|
+
0,
|
|
756
|
+
0,
|
|
757
|
+
0,
|
|
758
|
+
1
|
|
759
|
+
]);
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
export function mat4OrthogonalSimple(
|
|
763
|
+
height: number,
|
|
764
|
+
center: Vec2,
|
|
765
|
+
near: number,
|
|
766
|
+
far: number,
|
|
767
|
+
zoom: number,
|
|
768
|
+
aspectRatio = 1,
|
|
769
|
+
result = new Mat4()
|
|
770
|
+
): Mat4 {
|
|
771
|
+
height /= zoom;
|
|
772
|
+
const width = height * aspectRatio;
|
|
773
|
+
|
|
774
|
+
const left = -width * 0.5 + center.x;
|
|
775
|
+
const right = left + width;
|
|
776
|
+
|
|
777
|
+
const top = -height * 0.5 + center.y;
|
|
778
|
+
const bottom = top + height;
|
|
779
|
+
|
|
780
|
+
return mat4Orthogonal(left, right, top, bottom, near, far, result);
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
export function mat4LookAt(
|
|
784
|
+
eye: Vec3,
|
|
785
|
+
target: Vec3,
|
|
786
|
+
up: Vec3,
|
|
787
|
+
result = new Mat4()
|
|
788
|
+
): Mat4 {
|
|
789
|
+
const te = result.elements;
|
|
790
|
+
|
|
791
|
+
const look = vec3Subtract(eye, target);
|
|
792
|
+
|
|
793
|
+
const lookLength = vec3Length(look);
|
|
794
|
+
if (lookLength === 0) {
|
|
795
|
+
look.z = 1;
|
|
796
|
+
} else {
|
|
797
|
+
vec3MultiplyByScalar(look, 1 / lookLength, look);
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
const right = vec3Cross(up, look);
|
|
801
|
+
|
|
802
|
+
const rightLength = vec3Length(right);
|
|
803
|
+
if (rightLength === 0) {
|
|
804
|
+
// up and z are parallel
|
|
805
|
+
|
|
806
|
+
if (Math.abs(up.z) === 1) {
|
|
807
|
+
up.x += 0.0001;
|
|
808
|
+
} else {
|
|
809
|
+
up.z += 0.0001;
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
vec3Normalize(up, up);
|
|
813
|
+
vec3Cross(right, up, right);
|
|
814
|
+
} else {
|
|
815
|
+
vec3MultiplyByScalar(right, 1 / rightLength, right);
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
const up2 = vec3Cross(look, right);
|
|
819
|
+
|
|
820
|
+
te[0] = right.x;
|
|
821
|
+
te[4] = up2.x;
|
|
822
|
+
te[8] = look.x;
|
|
823
|
+
te[1] = right.y;
|
|
824
|
+
te[5] = up2.y;
|
|
825
|
+
te[9] = look.y;
|
|
826
|
+
te[2] = right.z;
|
|
827
|
+
te[6] = up2.z;
|
|
828
|
+
te[10] = look.z;
|
|
829
|
+
|
|
830
|
+
return result;
|
|
831
|
+
}
|