@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.
- package/package.json +1 -1
- package/src/core/geom/3d/mat4/m4_decompose.d.ts +5 -9
- package/src/core/geom/3d/mat4/m4_decompose.d.ts.map +1 -1
- package/src/core/geom/3d/mat4/m4_decompose.js +40 -60
- package/src/core/geom/3d/mat4/m4_decompose_array.d.ts +28 -0
- package/src/core/geom/3d/mat4/m4_decompose_array.d.ts.map +1 -0
- package/src/core/geom/3d/mat4/m4_decompose_array.js +157 -0
- package/src/core/primitives/strings/string_jaro_distance.d.ts +2 -2
- package/src/core/primitives/strings/string_jaro_distance.js +4 -4
- package/src/engine/Engine.d.ts.map +1 -1
- package/src/engine/Engine.js +0 -2
- package/src/engine/asset/loaders/SoundAssetLoader.d.ts.map +1 -1
- package/src/engine/asset/loaders/SoundAssetLoader.js +12 -1
- package/src/engine/ecs/gui/GUIElementSystem.d.ts +9 -0
- package/src/engine/ecs/gui/GUIElementSystem.d.ts.map +1 -1
- package/src/engine/ecs/gui/GUIElementSystem.js +23 -3
- package/src/engine/ecs/gui/position/ViewportPositionSystem.d.ts.map +1 -1
- package/src/engine/ecs/gui/position/ViewportPositionSystem.js +4 -2
- package/src/engine/ecs/transform/Transform64.d.ts +306 -0
- package/src/engine/ecs/transform/Transform64.d.ts.map +1 -0
- package/src/engine/ecs/transform/Transform64.js +591 -0
- package/src/engine/graphics/ecs/mesh/SkeletonUtils.d.ts +3 -3
- package/src/engine/graphics/ecs/mesh/SkeletonUtils.js +4 -4
- package/src/engine/graphics/ecs/mesh-v2/DeferredBoundsQueue.d.ts +48 -0
- package/src/engine/graphics/ecs/mesh-v2/DeferredBoundsQueue.d.ts.map +1 -0
- package/src/engine/graphics/ecs/mesh-v2/DeferredBoundsQueue.js +88 -0
- package/src/engine/graphics/ecs/mesh-v2/ShadedGeometry.d.ts +28 -0
- package/src/engine/graphics/ecs/mesh-v2/ShadedGeometry.d.ts.map +1 -1
- package/src/engine/graphics/ecs/mesh-v2/ShadedGeometry.js +79 -0
- package/src/engine/graphics/ecs/mesh-v2/ShadedGeometryFlags.js +21 -3
- package/src/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.d.ts +13 -1
- package/src/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.d.ts.map +1 -1
- package/src/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js +47 -10
- package/src/engine/graphics/geometry/instancing/InstancedMeshGroup.d.ts +7 -0
- package/src/engine/graphics/geometry/instancing/InstancedMeshGroup.d.ts.map +1 -1
- package/src/engine/graphics/geometry/instancing/InstancedMeshGroup.js +28 -4
- package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
- package/src/engine/physics/fluid/ecs/FluidSystem.d.ts +3 -3
- package/src/view/minimap/gl/MinimapMarkersGL.d.ts.map +1 -1
- 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"}
|