@woosh/meep-engine 2.169.2 → 2.169.4

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 (40) hide show
  1. package/package.json +1 -1
  2. package/src/core/geom/3d/mat4/m4_decompose.d.ts +5 -9
  3. package/src/core/geom/3d/mat4/m4_decompose.d.ts.map +1 -1
  4. package/src/core/geom/3d/mat4/m4_decompose.js +40 -60
  5. package/src/core/geom/3d/mat4/m4_decompose_array.d.ts +28 -0
  6. package/src/core/geom/3d/mat4/m4_decompose_array.d.ts.map +1 -0
  7. package/src/core/geom/3d/mat4/m4_decompose_array.js +157 -0
  8. package/src/core/primitives/strings/string_jaro_distance.d.ts +2 -2
  9. package/src/core/primitives/strings/string_jaro_distance.js +4 -4
  10. package/src/engine/Engine.d.ts.map +1 -1
  11. package/src/engine/Engine.js +0 -2
  12. package/src/engine/asset/loaders/SoundAssetLoader.d.ts.map +1 -1
  13. package/src/engine/asset/loaders/SoundAssetLoader.js +12 -1
  14. package/src/engine/ecs/gui/GUIElementSystem.d.ts +9 -0
  15. package/src/engine/ecs/gui/GUIElementSystem.d.ts.map +1 -1
  16. package/src/engine/ecs/gui/GUIElementSystem.js +23 -3
  17. package/src/engine/ecs/gui/position/ViewportPositionSystem.d.ts.map +1 -1
  18. package/src/engine/ecs/gui/position/ViewportPositionSystem.js +4 -2
  19. package/src/engine/ecs/transform/Transform64.d.ts +306 -0
  20. package/src/engine/ecs/transform/Transform64.d.ts.map +1 -0
  21. package/src/engine/ecs/transform/Transform64.js +591 -0
  22. package/src/engine/graphics/ecs/mesh/SkeletonUtils.d.ts +3 -3
  23. package/src/engine/graphics/ecs/mesh/SkeletonUtils.js +4 -4
  24. package/src/engine/graphics/ecs/mesh-v2/DeferredBoundsQueue.d.ts +48 -0
  25. package/src/engine/graphics/ecs/mesh-v2/DeferredBoundsQueue.d.ts.map +1 -0
  26. package/src/engine/graphics/ecs/mesh-v2/DeferredBoundsQueue.js +88 -0
  27. package/src/engine/graphics/ecs/mesh-v2/ShadedGeometry.d.ts +28 -0
  28. package/src/engine/graphics/ecs/mesh-v2/ShadedGeometry.d.ts.map +1 -1
  29. package/src/engine/graphics/ecs/mesh-v2/ShadedGeometry.js +79 -0
  30. package/src/engine/graphics/ecs/mesh-v2/ShadedGeometryFlags.js +21 -3
  31. package/src/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.d.ts +13 -1
  32. package/src/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.d.ts.map +1 -1
  33. package/src/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js +47 -10
  34. package/src/engine/graphics/geometry/instancing/InstancedMeshGroup.d.ts +7 -0
  35. package/src/engine/graphics/geometry/instancing/InstancedMeshGroup.d.ts.map +1 -1
  36. package/src/engine/graphics/geometry/instancing/InstancedMeshGroup.js +28 -4
  37. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  38. package/src/engine/physics/fluid/ecs/FluidSystem.d.ts +3 -3
  39. package/src/view/minimap/gl/MinimapMarkersGL.d.ts.map +1 -1
  40. package/src/view/minimap/gl/MinimapMarkersGL.js +3 -1
@@ -0,0 +1,591 @@
1
+ import { assert } from "../../../core/assert.js";
2
+ import { array_copy } from "../../../core/collection/array/array_copy.js";
3
+ import { array_range_equal_strict } from "../../../core/collection/array/array_range_equal_strict.js";
4
+ import { m4_decompose_array } from "../../../core/geom/3d/mat4/m4_decompose_array.js";
5
+ import { m4_from_rotation_translation_scale_scalar } from "../../../core/geom/3d/mat4/m4_from_rotation_translation_scale_scalar.js";
6
+ import { m4_multiply } from "../../../core/geom/3d/mat4/m4_multiply.js";
7
+
8
+ /**
9
+ * Index of the first element of the 4x4 affine matrix inside a {@link Transform64}.
10
+ *
11
+ * It is 0, which means a `Transform64` can be passed to any `mat4` function directly,
12
+ * in place of the matrix - `m4_multiply(out, a_transform, b_transform)` and the like.
13
+ * @type {number}
14
+ */
15
+ export const TRANSFORM64_MATRIX_OFFSET = 0;
16
+
17
+ /**
18
+ * Index of the first element of the translation (x, y, z) inside a {@link Transform64}
19
+ * @type {number}
20
+ */
21
+ export const TRANSFORM64_TRANSLATION_OFFSET = 16;
22
+
23
+ /**
24
+ * Index of the first element of the rotation quaternion (x, y, z, w) inside a {@link Transform64}
25
+ * @type {number}
26
+ */
27
+ export const TRANSFORM64_ROTATION_OFFSET = 19;
28
+
29
+ /**
30
+ * Index of the first element of the scale (x, y, z) inside a {@link Transform64}
31
+ * @type {number}
32
+ */
33
+ export const TRANSFORM64_SCALE_OFFSET = 23;
34
+
35
+ /**
36
+ * Number of elements in a {@link Transform64}
37
+ * @type {number}
38
+ */
39
+ export const TRANSFORM64_SIZE = 26;
40
+
41
+ /**
42
+ * Position, rotation and scale of an object in 3D space, along with the affine matrix they compose into,
43
+ * packed into a single `Float64Array`.
44
+ *
45
+ * This is the passive counterpart of {@link Transform}. There are no signals, no flags and no change
46
+ * detection: setting the translation, rotation or scale does **not** refresh {@link matrix}, you call
47
+ * {@link updateMatrix} yourself once you are done mutating. What you get for that is one allocation of one
48
+ * contiguous buffer per transform, plain array stores instead of setter dispatch, and double precision
49
+ * throughout.
50
+ *
51
+ * Every element is addressable directly, and the layout is part of the contract, so hot code can read and
52
+ * write the buffer without going through the accessors:
53
+ * ```
54
+ * [ 0..15] matrix, column-major
55
+ * [16..18] translation x, y, z
56
+ * [19..22] rotation x, y, z, w
57
+ * [23..25] scale x, y, z
58
+ * ```
59
+ *
60
+ * @example
61
+ * const t = new Transform64();
62
+ *
63
+ * t.setTranslation(1, 2, 3);
64
+ * t.setScale(2, 2, 2);
65
+ *
66
+ * // nothing has touched the matrix up to this point
67
+ * t.updateMatrix();
68
+ *
69
+ * @example
70
+ * // reading a component in a hot loop, without the accessors
71
+ * const x = t[TRANSFORM64_TRANSLATION_OFFSET];
72
+ *
73
+ * @author Alex Goldring
74
+ * @copyright Company Named Limited (c) 2026
75
+ */
76
+ export class Transform64 extends Float64Array {
77
+
78
+ /**
79
+ * Arrays derived from a transform (`slice`, `subarray`, `map`, ...) are plain `Float64Array`s
80
+ * @returns {Float64ArrayConstructor}
81
+ */
82
+ static get [Symbol.species]() {
83
+ // without this the derived array would be built by our own constructor, which takes no length,
84
+ // so it would silently come back sized as a whole transform
85
+ return Float64Array;
86
+ }
87
+
88
+ constructor() {
89
+ super(TRANSFORM64_SIZE);
90
+
91
+ this.makeIdentity();
92
+ }
93
+
94
+ /**
95
+ * Affine transform matrix, column-major.
96
+ *
97
+ * Unlike {@link Transform}, this is not maintained for you - it holds whatever {@link updateMatrix},
98
+ * {@link fromMatrix} or {@link multiply} last wrote, and goes stale the moment you set a component.
99
+ *
100
+ * NOTE: the returned array is a live view over the transform's own buffer, but a freshly allocated
101
+ * view on every access. Hold on to it rather than reading this property in a loop, or index the
102
+ * transform itself - the matrix starts at element 0.
103
+ * @returns {Float64Array}
104
+ */
105
+ get matrix() {
106
+ return new Float64Array(this.buffer, this.byteOffset, 16);
107
+ }
108
+
109
+ /**
110
+ * Position in 3D space.
111
+ * NOTE: live view over the transform's own buffer, freshly allocated on every access
112
+ * @returns {Float64Array}
113
+ */
114
+ get translation() {
115
+ return new Float64Array(this.buffer, this.byteOffset + TRANSFORM64_TRANSLATION_OFFSET * 8, 3);
116
+ }
117
+
118
+ /**
119
+ * Reads 3 elements, does not update {@link matrix}
120
+ * @param {number[]|Float32Array|Float64Array} v
121
+ */
122
+ set translation(v) {
123
+ array_copy(v, 0, this, TRANSFORM64_TRANSLATION_OFFSET, 3);
124
+ }
125
+
126
+ get translation_x() {
127
+ return this[TRANSFORM64_TRANSLATION_OFFSET];
128
+ }
129
+
130
+ get translation_y() {
131
+ return this[TRANSFORM64_TRANSLATION_OFFSET + 1];
132
+ }
133
+
134
+ get translation_z() {
135
+ return this[TRANSFORM64_TRANSLATION_OFFSET + 2];
136
+ }
137
+
138
+ /**
139
+ * Does not update {@link matrix}
140
+ * @param {number} x
141
+ * @param {number} y
142
+ * @param {number} z
143
+ */
144
+ setTranslation(x, y, z) {
145
+ assert.isNumber(x, 'x');
146
+ assert.isNumber(y, 'y');
147
+ assert.isNumber(z, 'z');
148
+
149
+ this[TRANSFORM64_TRANSLATION_OFFSET] = x;
150
+ this[TRANSFORM64_TRANSLATION_OFFSET + 1] = y;
151
+ this[TRANSFORM64_TRANSLATION_OFFSET + 2] = z;
152
+ }
153
+
154
+ /**
155
+ * Orientation, as a quaternion (x, y, z, w).
156
+ * NOTE: live view over the transform's own buffer, freshly allocated on every access
157
+ * @returns {Float64Array}
158
+ */
159
+ get rotation() {
160
+ return new Float64Array(this.buffer, this.byteOffset + TRANSFORM64_ROTATION_OFFSET * 8, 4);
161
+ }
162
+
163
+ /**
164
+ * Reads 4 elements, does not update {@link matrix}
165
+ * @param {number[]|Float32Array|Float64Array} q
166
+ */
167
+ set rotation(q) {
168
+ array_copy(q, 0, this, TRANSFORM64_ROTATION_OFFSET, 4);
169
+ }
170
+
171
+ get rotation_x() {
172
+ return this[TRANSFORM64_ROTATION_OFFSET];
173
+ }
174
+
175
+ get rotation_y() {
176
+ return this[TRANSFORM64_ROTATION_OFFSET + 1];
177
+ }
178
+
179
+ get rotation_z() {
180
+ return this[TRANSFORM64_ROTATION_OFFSET + 2];
181
+ }
182
+
183
+ get rotation_w() {
184
+ return this[TRANSFORM64_ROTATION_OFFSET + 3];
185
+ }
186
+
187
+ /**
188
+ * The quaternion is expected to be of unit length, nothing here normalizes it.
189
+ * Does not update {@link matrix}.
190
+ * @param {number} x
191
+ * @param {number} y
192
+ * @param {number} z
193
+ * @param {number} w
194
+ */
195
+ setRotation(x, y, z, w) {
196
+ assert.isNumber(x, 'x');
197
+ assert.isNumber(y, 'y');
198
+ assert.isNumber(z, 'z');
199
+ assert.isNumber(w, 'w');
200
+
201
+ this[TRANSFORM64_ROTATION_OFFSET] = x;
202
+ this[TRANSFORM64_ROTATION_OFFSET + 1] = y;
203
+ this[TRANSFORM64_ROTATION_OFFSET + 2] = z;
204
+ this[TRANSFORM64_ROTATION_OFFSET + 3] = w;
205
+ }
206
+
207
+ /**
208
+ * Size along each local axis.
209
+ * NOTE: live view over the transform's own buffer, freshly allocated on every access
210
+ * @returns {Float64Array}
211
+ */
212
+ get scale() {
213
+ return new Float64Array(this.buffer, this.byteOffset + TRANSFORM64_SCALE_OFFSET * 8, 3);
214
+ }
215
+
216
+ /**
217
+ * Reads 3 elements, does not update {@link matrix}
218
+ * @param {number[]|Float32Array|Float64Array} v
219
+ */
220
+ set scale(v) {
221
+ array_copy(v, 0, this, TRANSFORM64_SCALE_OFFSET, 3);
222
+ }
223
+
224
+ get scale_x() {
225
+ return this[TRANSFORM64_SCALE_OFFSET];
226
+ }
227
+
228
+ get scale_y() {
229
+ return this[TRANSFORM64_SCALE_OFFSET + 1];
230
+ }
231
+
232
+ get scale_z() {
233
+ return this[TRANSFORM64_SCALE_OFFSET + 2];
234
+ }
235
+
236
+ /**
237
+ * Does not update {@link matrix}
238
+ * @param {number} x
239
+ * @param {number} y
240
+ * @param {number} z
241
+ */
242
+ setScale(x, y, z) {
243
+ assert.isNumber(x, 'x');
244
+ assert.isNumber(y, 'y');
245
+ assert.isNumber(z, 'z');
246
+
247
+ this[TRANSFORM64_SCALE_OFFSET] = x;
248
+ this[TRANSFORM64_SCALE_OFFSET + 1] = y;
249
+ this[TRANSFORM64_SCALE_OFFSET + 2] = z;
250
+ }
251
+
252
+ /**
253
+ * Uniform scale. Does not update {@link matrix}.
254
+ * @param {number} s
255
+ */
256
+ setScaleScalar(s) {
257
+ this.setScale(s, s, s);
258
+ }
259
+
260
+ /**
261
+ * Write {@link matrix} from the current {@link translation}, {@link rotation} and {@link scale}.
262
+ * Nothing calls this for you, and until you do, the matrix is whatever it was before.
263
+ */
264
+ updateMatrix() {
265
+ m4_from_rotation_translation_scale_scalar(
266
+ this,
267
+ this[TRANSFORM64_ROTATION_OFFSET],
268
+ this[TRANSFORM64_ROTATION_OFFSET + 1],
269
+ this[TRANSFORM64_ROTATION_OFFSET + 2],
270
+ this[TRANSFORM64_ROTATION_OFFSET + 3],
271
+
272
+ this[TRANSFORM64_TRANSLATION_OFFSET],
273
+ this[TRANSFORM64_TRANSLATION_OFFSET + 1],
274
+ this[TRANSFORM64_TRANSLATION_OFFSET + 2],
275
+
276
+ this[TRANSFORM64_SCALE_OFFSET],
277
+ this[TRANSFORM64_SCALE_OFFSET + 1],
278
+ this[TRANSFORM64_SCALE_OFFSET + 2]
279
+ );
280
+ }
281
+
282
+ /**
283
+ * Write {@link translation}, {@link rotation} and {@link scale} from the current {@link matrix}.
284
+ * The inverse of {@link updateMatrix}; call it after writing the matrix in place.
285
+ *
286
+ * A matrix carrying shear cannot be described by a translation, a rotation and a scale, so shear is
287
+ * dropped from the components. It survives in {@link matrix} until the next {@link updateMatrix}.
288
+ */
289
+ updateComponents() {
290
+ m4_decompose_array(
291
+ this,
292
+ this, TRANSFORM64_TRANSLATION_OFFSET,
293
+ this, TRANSFORM64_ROTATION_OFFSET,
294
+ this, TRANSFORM64_SCALE_OFFSET
295
+ );
296
+ }
297
+
298
+ /**
299
+ * Set the whole transform, matrix and components both, from an affine matrix.
300
+ * See {@link updateComponents} for how shear is handled.
301
+ * @param {number[]|Float32Array|Float64Array|mat4} m4 4x4 affine matrix, column-major
302
+ * @returns {this}
303
+ */
304
+ fromMatrix(m4) {
305
+ assert.isArrayLike(m4, 'm4');
306
+ assert.greaterThanOrEqual(m4.length, 16, 'm4.length');
307
+
308
+ array_copy(m4, 0, this, TRANSFORM64_MATRIX_OFFSET, 16);
309
+
310
+ this.updateComponents();
311
+
312
+ return this;
313
+ }
314
+
315
+ /**
316
+ * Post-multiplication, `this = this * other`. See {@link multiplyTransforms}.
317
+ * @param {Transform64} other
318
+ * @returns {this}
319
+ */
320
+ multiply(other) {
321
+ return this.multiplyTransforms(this, other);
322
+ }
323
+
324
+ /**
325
+ * Multiply two transforms, writing the result into this one. Either operand may be this transform.
326
+ *
327
+ * Both operands are read through their matrices, not their components, so a stale matrix on either
328
+ * side produces a stale result - {@link updateMatrix} them first if you have been setting components.
329
+ * Both the matrix and the components of the result are left up to date.
330
+ *
331
+ * @param {Transform64} a
332
+ * @param {Transform64} b
333
+ * @returns {this}
334
+ */
335
+ multiplyTransforms(a, b) {
336
+ assert.equal(a.isTransform64, true, 'a.isTransform64 !== true');
337
+ assert.equal(b.isTransform64, true, 'b.isTransform64 !== true');
338
+
339
+ // both operands are fully read into locals before the first write, so aliasing is safe
340
+ m4_multiply(this, a, b);
341
+
342
+ this.updateComponents();
343
+
344
+ return this;
345
+ }
346
+
347
+ /**
348
+ * Reset to the identity transform, matrix included:
349
+ * - translation: [0,0,0]
350
+ * - rotation: [0,0,0,1]
351
+ * - scale: [1,1,1]
352
+ */
353
+ makeIdentity() {
354
+ this.fill(0);
355
+
356
+ // matrix diagonal
357
+ this[0] = 1;
358
+ this[5] = 1;
359
+ this[10] = 1;
360
+ this[15] = 1;
361
+
362
+ this[TRANSFORM64_ROTATION_OFFSET + 3] = 1;
363
+
364
+ this[TRANSFORM64_SCALE_OFFSET] = 1;
365
+ this[TRANSFORM64_SCALE_OFFSET + 1] = 1;
366
+ this[TRANSFORM64_SCALE_OFFSET + 2] = 1;
367
+ }
368
+
369
+ /**
370
+ * Whether the translation is exactly [0,0,0], the rotation exactly [0,0,0,1] and the scale exactly
371
+ * [1,1,1]. Says nothing about {@link matrix}, which only agrees after an {@link updateMatrix}.
372
+ * @returns {boolean}
373
+ */
374
+ isIdentity() {
375
+ return this[TRANSFORM64_TRANSLATION_OFFSET] === 0
376
+ && this[TRANSFORM64_TRANSLATION_OFFSET + 1] === 0
377
+ && this[TRANSFORM64_TRANSLATION_OFFSET + 2] === 0
378
+ && this[TRANSFORM64_ROTATION_OFFSET] === 0
379
+ && this[TRANSFORM64_ROTATION_OFFSET + 1] === 0
380
+ && this[TRANSFORM64_ROTATION_OFFSET + 2] === 0
381
+ && this[TRANSFORM64_ROTATION_OFFSET + 3] === 1
382
+ && this[TRANSFORM64_SCALE_OFFSET] === 1
383
+ && this[TRANSFORM64_SCALE_OFFSET + 1] === 1
384
+ && this[TRANSFORM64_SCALE_OFFSET + 2] === 1;
385
+ }
386
+
387
+ /**
388
+ * Set this transform to match `other`, matrix included. The `other` is left unchanged.
389
+ * @param {Transform64} other
390
+ */
391
+ copy(other) {
392
+ this.set(other);
393
+ }
394
+
395
+ /**
396
+ * A new transform equal to this one
397
+ * @returns {Transform64}
398
+ */
399
+ clone() {
400
+ const r = new Transform64();
401
+
402
+ r.copy(this);
403
+
404
+ return r;
405
+ }
406
+
407
+ /**
408
+ * Strict equality across the whole transform, {@link matrix} included. Two transforms whose components
409
+ * match but whose matrices do not - because one of them is stale - are not equal.
410
+ * @param {Transform64} other
411
+ * @returns {boolean}
412
+ */
413
+ equals(other) {
414
+ return array_range_equal_strict(this, 0, other, 0, TRANSFORM64_SIZE);
415
+ }
416
+
417
+ /**
418
+ * Only the translation contributes, for speed - in most applications it is what varies the most.
419
+ *
420
+ * This is weaker than {@link equals}: transforms differing only in rotation, scale or matrix collide.
421
+ * Legal for a hash, but a poor key if your set varies along those axes alone.
422
+ * @returns {number}
423
+ */
424
+ hash() {
425
+ const x = this[TRANSFORM64_TRANSLATION_OFFSET];
426
+ const y = this[TRANSFORM64_TRANSLATION_OFFSET + 1];
427
+ const z = this[TRANSFORM64_TRANSLATION_OFFSET + 2];
428
+
429
+ // Same arithmetic as `computeHashFloat`, written out by hand so that this is a straight line with
430
+ // no calls and no loop. Per component: split into whole and fractional parts, scale the fraction
431
+ // into uint32 range and flip it so that tiny fractions land in the high bits, then XOR the two.
432
+ const x_whole = x >> 0;
433
+ const y_whole = y >> 0;
434
+ const z_whole = z >> 0;
435
+
436
+ const x_hash = (4294967295 - (((x - x_whole) * 4294967295) >>> 0)) ^ x_whole;
437
+ const y_hash = (4294967295 - (((y - y_whole) * 4294967295) >>> 0)) ^ y_whole;
438
+ const z_hash = (4294967295 - (((z - z_whole) * 4294967295) >>> 0)) ^ z_whole;
439
+
440
+ // mix, `h*31 + v` expressed as a shift so it stays in integer arithmetic
441
+ let hash = ((x_hash << 5) - x_hash + y_hash) | 0;
442
+
443
+ hash = ((hash << 5) - hash + z_hash) | 0;
444
+
445
+ return hash;
446
+ }
447
+
448
+ /**
449
+ * Read the components from `{translation, rotation, scale}`, each of them optional and defaulting to
450
+ * identity. Composes {@link matrix} from the result.
451
+ *
452
+ * NOTE: the translation is keyed `translation`, where {@link Transform} keys the same thing
453
+ * `position`. The two JSON forms are not interchangeable.
454
+ * @param json
455
+ */
456
+ fromJSON(json) {
457
+ const t = json.translation;
458
+
459
+ if (t !== undefined) {
460
+ this.setTranslation(t.x, t.y, t.z);
461
+ } else {
462
+ this.setTranslation(0, 0, 0);
463
+ }
464
+
465
+ const r = json.rotation;
466
+
467
+ if (r !== undefined) {
468
+ this.setRotation(r.x, r.y, r.z, r.w);
469
+ } else {
470
+ this.setRotation(0, 0, 0, 1);
471
+ }
472
+
473
+ const s = json.scale;
474
+
475
+ if (s !== undefined) {
476
+ this.setScale(s.x, s.y, s.z);
477
+ } else {
478
+ this.setScale(1, 1, 1);
479
+ }
480
+
481
+ this.updateMatrix();
482
+ }
483
+
484
+ /**
485
+ * Writes out the components only; {@link matrix} is recomposed from them on the way back in
486
+ * @returns {{translation:{x:number,y:number,z:number}, rotation:{x:number,y:number,z:number,w:number}, scale:{x:number,y:number,z:number}}}
487
+ */
488
+ toJSON() {
489
+ return {
490
+ translation: {
491
+ x: this[TRANSFORM64_TRANSLATION_OFFSET],
492
+ y: this[TRANSFORM64_TRANSLATION_OFFSET + 1],
493
+ z: this[TRANSFORM64_TRANSLATION_OFFSET + 2]
494
+ },
495
+ rotation: {
496
+ x: this[TRANSFORM64_ROTATION_OFFSET],
497
+ y: this[TRANSFORM64_ROTATION_OFFSET + 1],
498
+ z: this[TRANSFORM64_ROTATION_OFFSET + 2],
499
+ w: this[TRANSFORM64_ROTATION_OFFSET + 3]
500
+ },
501
+ scale: {
502
+ x: this[TRANSFORM64_SCALE_OFFSET],
503
+ y: this[TRANSFORM64_SCALE_OFFSET + 1],
504
+ z: this[TRANSFORM64_SCALE_OFFSET + 2]
505
+ }
506
+ };
507
+ }
508
+
509
+ /**
510
+ * Human-readable form, components only
511
+ * @returns {string}
512
+ */
513
+ toString() {
514
+ return `Transform64{ translation: [${this.translation_x}, ${this.translation_y}, ${this.translation_z}]`
515
+ + `, rotation: [${this.rotation_x}, ${this.rotation_y}, ${this.rotation_z}, ${this.rotation_w}]`
516
+ + `, scale: [${this.scale_x}, ${this.scale_y}, ${this.scale_z}] }`;
517
+ }
518
+
519
+ /**
520
+ * Build a transform from loose components, with {@link matrix} already composed from them
521
+ * @param {number} translation_x
522
+ * @param {number} translation_y
523
+ * @param {number} translation_z
524
+ * @param {number} rotation_x
525
+ * @param {number} rotation_y
526
+ * @param {number} rotation_z
527
+ * @param {number} rotation_w
528
+ * @param {number} scale_x
529
+ * @param {number} scale_y
530
+ * @param {number} scale_z
531
+ * @returns {Transform64}
532
+ */
533
+ static from(
534
+ translation_x, translation_y, translation_z,
535
+ rotation_x, rotation_y, rotation_z, rotation_w,
536
+ scale_x, scale_y, scale_z
537
+ ) {
538
+ const r = new Transform64();
539
+
540
+ r.setTranslation(translation_x, translation_y, translation_z);
541
+ r.setRotation(rotation_x, rotation_y, rotation_z, rotation_w);
542
+ r.setScale(scale_x, scale_y, scale_z);
543
+
544
+ r.updateMatrix();
545
+
546
+ return r;
547
+ }
548
+
549
+ /**
550
+ * Build a transform from an affine matrix, see {@link fromMatrix}
551
+ * @param {number[]|Float32Array|Float64Array|mat4} m4 4x4 affine matrix, column-major
552
+ * @returns {Transform64}
553
+ */
554
+ static fromMatrix(m4) {
555
+ const r = new Transform64();
556
+
557
+ r.fromMatrix(m4);
558
+
559
+ return r;
560
+ }
561
+
562
+ /**
563
+ * Build a transform from its JSON form, see {@link fromJSON}
564
+ * @param json
565
+ * @returns {Transform64}
566
+ */
567
+ static fromJSON(json) {
568
+ const r = new Transform64();
569
+
570
+ r.fromJSON(json);
571
+
572
+ return r;
573
+ }
574
+ }
575
+
576
+ /**
577
+ * @readonly
578
+ * @type {string}
579
+ */
580
+ Transform64.typeName = "Transform64";
581
+
582
+ /**
583
+ * Enables a fast type check, without having to import the class separately.
584
+ * @readonly
585
+ * @type {boolean}
586
+ * @example
587
+ * if(t.isTransform64){
588
+ * // t is a Transform64, do stuff
589
+ * }
590
+ */
591
+ Transform64.prototype.isTransform64 = true;
@@ -1,5 +1,5 @@
1
1
  /**
2
- *
2
+ * @deprecated
3
3
  * @param {Mesh} component
4
4
  * @param {string} boneName
5
5
  * @returns {THREE.Bone | null}
@@ -26,14 +26,14 @@ export function findSkeletonBoneByType(skeleton: Skeleton, boneType: HumanoidBon
26
26
  */
27
27
  export function getSkeletonBoneByType(component: Mesh, boneType: HumanoidBoneType | string): Bone | null;
28
28
  /**
29
- *
29
+ * @deprecated
30
30
  * @param {Mesh} component
31
31
  * @param {String} name
32
32
  * @returns {Bone | null}
33
33
  */
34
34
  export function getSkeletonBoneByName_old(component: Mesh, name: string): Bone | null;
35
35
  /**
36
- *
36
+ * @deprecated
37
37
  * @param {Mesh} component
38
38
  * @param {String} name
39
39
  * @returns {Bone | null}
@@ -6,7 +6,7 @@ import { BoneMapping } from "./skeleton/BoneMapping.js";
6
6
 
7
7
 
8
8
  /**
9
- *
9
+ * @deprecated
10
10
  * @param {Mesh} component
11
11
  * @param {string} boneName
12
12
  * @returns {THREE.Bone | null}
@@ -160,7 +160,7 @@ export function getSkeletonBoneByType(component, boneType) {
160
160
 
161
161
 
162
162
  /**
163
- *
163
+ * @deprecated
164
164
  * @param {Mesh} component
165
165
  * @param {String} name
166
166
  * @returns {Bone | null}
@@ -199,7 +199,7 @@ export function getSkeletonBoneByName_old(component, name) {
199
199
  const stack = [];
200
200
 
201
201
  /**
202
- *
202
+ * @deprecated
203
203
  * @param {Mesh} component
204
204
  * @param {String} name
205
205
  * @returns {Bone | null}
@@ -235,7 +235,7 @@ export function getSkeletonBoneByName(component, name) {
235
235
  }
236
236
 
237
237
  /**
238
- *
238
+ * @deprecated
239
239
  * @param {Mesh} mesh
240
240
  * @returns {Array}
241
241
  */
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Collects {@link ShadedGeometry} components whose bounding box has gone stale under
3
+ * {@link ShadedGeometryFlags.DeferredBoundsUpdate}, until the owner of the BVH is ready
4
+ * to take the updates.
5
+ *
6
+ * WHY THIS EXISTS
7
+ *
8
+ * A {@link Transform} signals `position`, `rotation` and `scale` separately, so one
9
+ * logical move produces several change notifications: two when a caller sets position
10
+ * and rotation, three when the transform is written as a matrix (which is what
11
+ * {@link TransformAttachmentSystem} does for every entity in a hierarchy, and what
12
+ * `Transform.copy` does). Updating bounds on each of those recomputes the same box and
13
+ * walks the same path to the BVH root several times over. Parking the component here
14
+ * instead collapses the batch into one update per component per flush.
15
+ *
16
+ * Entries are appended without a membership test; {@link ShadedGeometry} carries the
17
+ * "already queued" bit so enqueueing stays O(1) and a component appears at most once.
18
+ */
19
+ export class DeferredBoundsQueue {
20
+ /**
21
+ * Number of components waiting for their bounds to be applied.
22
+ * @returns {number}
23
+ */
24
+ get size(): number;
25
+ /**
26
+ * Park a component whose bounds have gone stale.
27
+ *
28
+ * The caller must not add a component that is already queued — see
29
+ * {@link ShadedGeometry.updateTransform}, which owns that bit.
30
+ * @param {ShadedGeometry} sg
31
+ * @returns {void}
32
+ */
33
+ add(sg: ShadedGeometry): void;
34
+ /**
35
+ * Apply every parked update, leaving the BVH consistent with the current transforms.
36
+ *
37
+ * Components that were unlinked while queued, or whose bounds were already settled by
38
+ * a read, are skipped.
39
+ *
40
+ * Must not be re-entered: nothing reached from here writes to a {@link Transform},
41
+ * so no component can go dirty while the batch is being applied.
42
+ * @returns {number} how many components actually had an update applied, which is a
43
+ * useful profiling signal — it is the number of BVH refits the batch cost
44
+ */
45
+ flush(): number;
46
+ #private;
47
+ }
48
+ //# sourceMappingURL=DeferredBoundsQueue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DeferredBoundsQueue.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/graphics/ecs/mesh-v2/DeferredBoundsQueue.js"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH;IAaI;;;OAGG;IACH,mBAEC;IAED;;;;;;;OAOG;IACH,yBAFa,IAAI,CAIhB;IAED;;;;;;;;;;OAUG;IACH,SAHa,MAAM,CA2BlB;;CACJ"}