@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.
Files changed (50) hide show
  1. package/package.json +34 -0
  2. package/src/Abstractions/Drivers/DummyScene.ts +79 -0
  3. package/src/Abstractions/IScene.ts +18 -0
  4. package/src/GLTFJson.ts +34 -0
  5. package/src/Nodes/Actions/EaseSceneProperty.ts +162 -0
  6. package/src/Nodes/Actions/SetSceneProperty.ts +35 -0
  7. package/src/Nodes/Events/OnSceneNodeClick.ts +66 -0
  8. package/src/Nodes/Logic/ColorNodes.ts +121 -0
  9. package/src/Nodes/Logic/EulerNodes.ts +115 -0
  10. package/src/Nodes/Logic/Mat3Nodes.ts +202 -0
  11. package/src/Nodes/Logic/Mat4Nodes.ts +257 -0
  12. package/src/Nodes/Logic/QuatNodes.ts +178 -0
  13. package/src/Nodes/Logic/Vec2Nodes.ts +111 -0
  14. package/src/Nodes/Logic/Vec3Nodes.ts +121 -0
  15. package/src/Nodes/Logic/Vec4Nodes.ts +112 -0
  16. package/src/Nodes/Logic/VecElements.ts +34 -0
  17. package/src/Nodes/Queries/GetSceneProperty.ts +35 -0
  18. package/src/Values/ColorValue.ts +22 -0
  19. package/src/Values/EulerValue.ts +22 -0
  20. package/src/Values/Internal/Mat2.ts +214 -0
  21. package/src/Values/Internal/Mat3.ts +422 -0
  22. package/src/Values/Internal/Mat4.ts +831 -0
  23. package/src/Values/Internal/Vec2.ts +97 -0
  24. package/src/Values/Internal/Vec3.ts +244 -0
  25. package/src/Values/Internal/Vec4.ts +350 -0
  26. package/src/Values/Mat3Value.ts +20 -0
  27. package/src/Values/Mat4Value.ts +20 -0
  28. package/src/Values/QuatValue.ts +22 -0
  29. package/src/Values/Vec2Value.ts +14 -0
  30. package/src/Values/Vec3Value.ts +22 -0
  31. package/src/Values/Vec4Value.ts +21 -0
  32. package/src/buildScene.ts +479 -0
  33. package/src/index.ts +38 -0
  34. package/src/loadScene.ts +81 -0
  35. package/src/registerSceneProfile.ts +105 -0
  36. package/tests/graphs/logic/Color.json +53 -0
  37. package/tests/graphs/logic/Euler.json +53 -0
  38. package/tests/graphs/logic/Quaternion.json +56 -0
  39. package/tests/graphs/logic/Vector2.json +50 -0
  40. package/tests/graphs/logic/Vector3.json +53 -0
  41. package/tests/graphs/logic/Vector4.json +56 -0
  42. package/tests/readSceneGraphs.test.ts +57 -0
  43. package/tests/registerSceneProfile.test.ts +62 -0
  44. package/tests/tsconfig.json +11 -0
  45. package/tests/values/internal/Vec2.test.ts +74 -0
  46. package/tests/values/internal/Vec3.test.ts +83 -0
  47. package/tests/values/internal/Vec4.test.ts +91 -0
  48. package/tsconfig.json +55 -0
  49. package/tsdown.config.ts +13 -0
  50. package/vitest.config.ts +15 -0
@@ -0,0 +1,422 @@
1
+ import {
2
+ EPSILON,
3
+ equalsTolerance,
4
+ parseSafeFloats,
5
+ toSafeString
6
+ } from '@kiberon-labs/behave-graph';
7
+
8
+ import { Mat4 } from './Mat4.js';
9
+ import { Vec2 } from './Vec2.js';
10
+ import { Vec3 } from './Vec3.js';
11
+ import { Vec4 } from './Vec4.js';
12
+
13
+ // uses OpenGL matrix layout where each column is specified subsequently in order from left to right.
14
+ // ( x, y, 1 ) x [ 0 3 6 ] = ( x', y', 1 )
15
+ // [ 1 4 7 ]
16
+ // [ 2 5 8 ]
17
+ // where elements 2 and 5 would be translation in 2D, as they would multiplied
18
+ // by the last virtual element of the 2D vector.
19
+
20
+ const NUM_ROWS = 3;
21
+ const NUM_COLUMNS = 3;
22
+ const NUM_ELEMENTS = NUM_ROWS * NUM_COLUMNS;
23
+
24
+ type Mat3Elements = [
25
+ number,
26
+ number,
27
+ number,
28
+ number,
29
+ number,
30
+ number,
31
+ number,
32
+ number,
33
+ number
34
+ ];
35
+ export type Mat3JSON = Mat3Elements;
36
+
37
+ export class Mat3 {
38
+ public elements: Mat3Elements;
39
+ constructor(elements: Mat3Elements = [1, 0, 0, 0, 1, 0, 0, 0, 1]) {
40
+ if (elements.length !== NUM_ELEMENTS) {
41
+ throw new Error(
42
+ `elements must have length ${NUM_ELEMENTS}, got ${elements.length}`
43
+ );
44
+ }
45
+ this.elements = elements;
46
+ }
47
+
48
+ clone(result = new Mat3()): Mat3 {
49
+ return result.set(this.elements);
50
+ }
51
+ set(elements: Mat3Elements): this {
52
+ if (elements.length !== NUM_ELEMENTS) {
53
+ throw new Error(
54
+ `elements must have length ${NUM_ELEMENTS}, got ${elements.length}`
55
+ );
56
+ }
57
+ this.elements = [...elements];
58
+ return this;
59
+ }
60
+ }
61
+
62
+ export function mat3SetColumn3(
63
+ m: Mat3,
64
+ columnIndex: number,
65
+ column: Vec3,
66
+ result = new Mat3()
67
+ ): Mat3 {
68
+ const re = result.set(m.elements).elements;
69
+ const base = columnIndex * NUM_ROWS;
70
+ re[base + 0] = column.x;
71
+ re[base + 1] = column.y;
72
+ re[base + 2] = column.z;
73
+ return result;
74
+ }
75
+
76
+ export function mat3SetRow3(
77
+ m: Mat3,
78
+ rowIndex: number,
79
+ row: Vec3,
80
+ result = new Mat3()
81
+ ): Mat3 {
82
+ const re = result.set(m.elements).elements;
83
+ re[rowIndex + NUM_COLUMNS * 0] = row.x;
84
+ re[rowIndex + NUM_COLUMNS * 1] = row.y;
85
+ re[rowIndex + NUM_COLUMNS * 2] = row.z;
86
+ return result;
87
+ }
88
+
89
+ export function column3ToMat3(
90
+ a: Vec3,
91
+ b: Vec3,
92
+ c: Vec3,
93
+ result = new Mat3()
94
+ ): Mat3 {
95
+ const re = result.elements;
96
+ const columns = [a, b, c];
97
+ for (let c = 0; c < columns.length; c++) {
98
+ const base = c * NUM_ROWS;
99
+ const column = columns[c]!;
100
+ re[base + 0] = column.x;
101
+ re[base + 1] = column.y;
102
+ re[base + 2] = column.z;
103
+ }
104
+ return result;
105
+ }
106
+
107
+ export function mat3Equals(a: Mat3, b: Mat3, tolerance = EPSILON): boolean {
108
+ for (let i = 0; i < NUM_ELEMENTS; i++) {
109
+ if (!equalsTolerance(a.elements[i]!, b.elements[i]!, tolerance))
110
+ return false;
111
+ }
112
+ return true;
113
+ }
114
+ export function mat3Add(a: Mat3, b: Mat3, result: Mat3 = new Mat3()): Mat3 {
115
+ for (let i = 0; i < NUM_ELEMENTS; i++) {
116
+ result.elements[i] = a.elements[i]! + b.elements[i]!;
117
+ }
118
+ return result;
119
+ }
120
+ export function mat3Subtract(
121
+ a: Mat3,
122
+ b: Mat3,
123
+ result: Mat3 = new Mat3()
124
+ ): Mat3 {
125
+ result.elements = a.elements.map(
126
+ (a, i) => a - b.elements[i]!
127
+ ) as Mat3Elements;
128
+ return result;
129
+ }
130
+ export function mat3MultiplyByScalar(
131
+ a: Mat3,
132
+ b: number,
133
+ result: Mat3 = new Mat3()
134
+ ): Mat3 {
135
+ result.elements = a.elements.map((x) => x * b) as Mat3Elements;
136
+ return result;
137
+ }
138
+ export function mat3Negate(a: Mat3, result: Mat3 = new Mat3()): Mat3 {
139
+ result.elements = a.elements.map((x) => -x) as Mat3Elements;
140
+ return result;
141
+ }
142
+
143
+ export function mat3Multiply(a: Mat3, b: Mat3, result = new Mat3()): Mat3 {
144
+ const ae = a.elements;
145
+ const be = b.elements;
146
+ const te = result.elements;
147
+
148
+ const a11 = ae[0],
149
+ a12 = ae[3],
150
+ a13 = ae[6];
151
+ const a21 = ae[1],
152
+ a22 = ae[4],
153
+ a23 = ae[7];
154
+ const a31 = ae[2],
155
+ a32 = ae[5],
156
+ a33 = ae[8];
157
+
158
+ const b11 = be[0],
159
+ b12 = be[3],
160
+ b13 = be[6];
161
+ const b21 = be[1],
162
+ b22 = be[4],
163
+ b23 = be[7];
164
+ const b31 = be[2],
165
+ b32 = be[5],
166
+ b33 = be[8];
167
+
168
+ te[0] = a11 * b11 + a12 * b21 + a13 * b31;
169
+ te[3] = a11 * b12 + a12 * b22 + a13 * b32;
170
+ te[6] = a11 * b13 + a12 * b23 + a13 * b33;
171
+
172
+ te[1] = a21 * b11 + a22 * b21 + a23 * b31;
173
+ te[4] = a21 * b12 + a22 * b22 + a23 * b32;
174
+ te[7] = a21 * b13 + a22 * b23 + a23 * b33;
175
+
176
+ te[2] = a31 * b11 + a32 * b21 + a33 * b31;
177
+ te[5] = a31 * b12 + a32 * b22 + a33 * b32;
178
+ te[8] = a31 * b13 + a32 * b23 + a33 * b33;
179
+
180
+ return result;
181
+ }
182
+
183
+ export function mat3Determinant(m: Mat3): number {
184
+ const me = m.elements;
185
+
186
+ const a = me[0],
187
+ b = me[1],
188
+ c = me[2],
189
+ d = me[3],
190
+ e = me[4],
191
+ f = me[5],
192
+ g = me[6],
193
+ h = me[7],
194
+ i = me[8];
195
+
196
+ return a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g;
197
+ }
198
+
199
+ export function mat3Transpose(m: Mat3, result = new Mat3()): Mat3 {
200
+ const me = m.elements;
201
+ const te = result.elements;
202
+
203
+ te[0] = me[0];
204
+ te[4] = me[4];
205
+ te[8] = me[8];
206
+
207
+ te[1] = me[3];
208
+ te[3] = me[1];
209
+
210
+ te[2] = me[6];
211
+ te[6] = me[2];
212
+
213
+ te[5] = me[7];
214
+ te[7] = me[5];
215
+
216
+ return result;
217
+ }
218
+
219
+ export function mat3Inverse(m: Mat3, result = new Mat3()): Mat3 {
220
+ const e = m.elements;
221
+
222
+ const n11 = e[0],
223
+ n21 = e[1],
224
+ n31 = e[2],
225
+ n12 = e[3],
226
+ n22 = e[4],
227
+ n32 = e[5],
228
+ n13 = e[6],
229
+ n23 = e[7],
230
+ n33 = e[8],
231
+ t11 = n33 * n22 - n32 * n23,
232
+ t12 = n32 * n13 - n33 * n12,
233
+ t13 = n23 * n12 - n22 * n13,
234
+ det = n11 * t11 + n21 * t12 + n31 * t13;
235
+
236
+ if (det === 0) {
237
+ throw new Error('can not invert degenerate matrix');
238
+ }
239
+
240
+ const detInv = 1 / det;
241
+
242
+ const re = result.elements;
243
+
244
+ // TODO: replace with a set
245
+ re[0] = t11 * detInv;
246
+ re[1] = (n31 * n23 - n33 * n21) * detInv;
247
+ re[2] = (n32 * n21 - n31 * n22) * detInv;
248
+
249
+ re[3] = t12 * detInv;
250
+ re[4] = (n33 * n11 - n31 * n13) * detInv;
251
+ re[5] = (n31 * n12 - n32 * n11) * detInv;
252
+
253
+ re[6] = t13 * detInv;
254
+ re[7] = (n21 * n13 - n23 * n11) * detInv;
255
+ re[8] = (n22 * n11 - n21 * n12) * detInv;
256
+
257
+ return result;
258
+ }
259
+
260
+ export function mat3Mix(
261
+ a: Mat3,
262
+ b: Mat3,
263
+ t: number,
264
+ result = new Mat3()
265
+ ): Mat3 {
266
+ const s = 1 - t;
267
+ for (let i = 0; i < NUM_ELEMENTS; i++) {
268
+ result.elements[i] = a.elements[i]! * s + b.elements[i]! * t;
269
+ }
270
+ return result;
271
+ }
272
+ export function mat3FromArray(
273
+ array: Float32Array | number[],
274
+ offset = 0,
275
+ result: Mat3 = new Mat3()
276
+ ): Mat3 {
277
+ for (let i = 0; i < NUM_ELEMENTS; i++) {
278
+ result.elements[i] = array[offset + i]!;
279
+ }
280
+ return result;
281
+ }
282
+ export function mat3ToArray(
283
+ a: Mat3,
284
+ array: Float32Array | number[],
285
+ offset = 0
286
+ ): void {
287
+ for (let i = 0; i < NUM_ELEMENTS; i++) {
288
+ array[offset + i] = a.elements[i]!;
289
+ }
290
+ }
291
+
292
+ export function mat3ToString(a: Mat3): string {
293
+ return toSafeString(a.elements);
294
+ }
295
+ export function mat3Parse(text: string, result = new Mat3()): Mat3 {
296
+ return mat3FromArray(parseSafeFloats(text), 0, result);
297
+ }
298
+
299
+ export function eulerToMat3(euler: Vec3, result = new Mat3()): Mat3 {
300
+ const te = result.elements;
301
+
302
+ const x = euler.x,
303
+ y = euler.y,
304
+ z = euler.z;
305
+ const a = Math.cos(x),
306
+ b = Math.sin(x);
307
+ const c = Math.cos(y),
308
+ d = Math.sin(y);
309
+ const e = Math.cos(z),
310
+ f = Math.sin(z);
311
+
312
+ const ae = a * e,
313
+ af = a * f,
314
+ be = b * e,
315
+ bf = b * f;
316
+
317
+ te[0] = c * e;
318
+ te[3] = -c * f;
319
+ te[6] = d;
320
+
321
+ te[1] = af + be * d;
322
+ te[4] = ae - bf * d;
323
+ te[7] = -b * c;
324
+
325
+ te[2] = bf - ae * d;
326
+ te[5] = be + af * d;
327
+ te[8] = a * c;
328
+
329
+ return result;
330
+ }
331
+
332
+ export function quatToMat3(q: Vec4, result = new Mat3()): Mat3 {
333
+ const x = q.x,
334
+ y = q.y,
335
+ z = q.z,
336
+ w = q.w;
337
+ const x2 = x + x,
338
+ y2 = y + y,
339
+ z2 = z + z;
340
+ const xx = x * x2,
341
+ xy = x * y2,
342
+ xz = x * z2;
343
+ const yy = y * y2,
344
+ yz = y * z2,
345
+ zz = z * z2;
346
+ const wx = w * x2,
347
+ wy = w * y2,
348
+ wz = w * z2;
349
+
350
+ return result.set([
351
+ 1 - (yy + zz),
352
+ xy - wz,
353
+ xz + wy,
354
+ xy + wz,
355
+ 1 - (xx + zz),
356
+ yz - wx,
357
+ xz - wy,
358
+ yz + wx,
359
+ 1 - (xx + yy)
360
+ ]);
361
+ }
362
+
363
+ export function scale2ToMat3(s: Vec2, result = new Mat3()): Mat3 {
364
+ return result.set([s.x, 0, 0, 0, s.y, 0, 0, 0, 1]);
365
+ }
366
+ // from gl-matrix
367
+ export function mat3ToScale2(m: Mat4, result = new Vec2()): Vec2 {
368
+ const mat = m.elements;
369
+ const m11 = mat[0];
370
+ const m12 = mat[1];
371
+ const m21 = mat[3];
372
+ const m22 = mat[4];
373
+
374
+ return result.set(
375
+ Math.sqrt(m11 * m11 + m12 * m12),
376
+ Math.sqrt(m21 * m21 + m22 * m22)
377
+ );
378
+ }
379
+
380
+ export function translation2ToMat3(t: Vec2, result = new Mat3()): Mat3 {
381
+ return result.set([1, 0, t.x, 0, 1, t.y, 0, 0, 1]);
382
+ }
383
+ export function mat3ToTranslation2(m: Mat3, result = new Vec2()): Vec2 {
384
+ return result.set(m.elements[2], m.elements[5]);
385
+ }
386
+
387
+ export function scale3ToMat3(s: Vec3, result = new Mat3()): Mat3 {
388
+ return result.set([s.x, 0, 0, 0, s.y, 0, 0, 0, s.z]);
389
+ }
390
+ // from gl-matrix
391
+ export function mat3ToScale3(m: Mat4, result = new Vec3()): Vec3 {
392
+ const me = m.elements;
393
+ const m11 = me[0];
394
+ const m12 = me[1];
395
+ const m13 = me[2];
396
+ const m21 = me[3];
397
+ const m22 = me[4];
398
+ const m23 = me[5];
399
+ const m31 = me[6];
400
+ const m32 = me[7];
401
+ const m33 = me[8];
402
+
403
+ return result.set(
404
+ Math.sqrt(m11 * m11 + m12 * m12 + m13 * m13),
405
+ Math.sqrt(m21 * m21 + m22 * m22 + m23 * m23),
406
+ Math.sqrt(m31 * m31 + m32 * m32 + m33 * m33)
407
+ );
408
+ }
409
+ export function mat4ToMat3(a: Mat4, result = new Mat3()): Mat3 {
410
+ const ae = a.elements;
411
+ return result.set([
412
+ ae[0],
413
+ ae[1],
414
+ ae[2],
415
+ ae[4],
416
+ ae[5],
417
+ ae[6],
418
+ ae[8],
419
+ ae[9],
420
+ ae[10]
421
+ ]);
422
+ }