@woosh/meep-engine 2.63.0 → 2.64.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 (34) hide show
  1. package/build/meep.cjs +30 -23
  2. package/build/meep.min.js +1 -1
  3. package/build/meep.module.js +30 -23
  4. package/package.json +1 -1
  5. package/src/core/binary/UINT16_MAX.js +5 -0
  6. package/src/core/bvh2/bvh3/ExplicitBinaryBoundingVolumeHierarchy.js +5 -5
  7. package/src/core/bvh2/bvh3/query/BVHQueryIntersectsFrustum.js +8 -10
  8. package/src/core/bvh2/bvh3/query/BVHQueryIntersectsRay.js +7 -7
  9. package/src/core/bvh2/bvh3/query/BVHQueryIntersectsSphere.js +37 -0
  10. package/src/core/bvh2/bvh3/query/bvh_query_user_data_generic.js +12 -4
  11. package/src/core/bvh2/bvh3/query/bvh_query_user_data_generic.spec.js +29 -0
  12. package/src/core/collection/list/List.js +9 -3
  13. package/src/core/geom/3d/aabb/aabb3_from_v3_array.js +11 -4
  14. package/src/core/geom/Vector2.js +6 -4
  15. package/src/engine/graphics/particles/particular/engine/emitter/ParticleEmitter.js +49 -86
  16. package/src/engine/graphics/particles/particular/engine/emitter/ParticlePool.js +41 -72
  17. package/src/engine/graphics/particles/particular/engine/emitter/write_particle_patch_uv.js +28 -0
  18. package/src/engine/sound/ecs/emitter/SoundEmitterSystem.js +17 -17
  19. package/src/core/bvh2/bvh3/query/bvh_query_user_data_overlaps_sphere.js +0 -81
  20. package/src/engine/ecs/foliage/Foliage.js +0 -151
  21. package/src/engine/ecs/foliage/FoliageLoader.js +0 -39
  22. package/src/engine/ecs/foliage/FoliageVisibilitySetBuilder.js +0 -27
  23. package/src/engine/ecs/foliage/ImpostorFoliage.js +0 -106
  24. package/src/engine/ecs/foliage/InstancedFoliage.js +0 -395
  25. package/src/engine/ecs/foliage/ViewState.js +0 -181
  26. package/src/engine/ecs/foliage/ecs/Foliage2System.js +0 -333
  27. package/src/engine/ecs/foliage/ecs/InstancedMeshComponent.js +0 -70
  28. package/src/engine/ecs/foliage/ecs/InstancedMeshLayer.js +0 -138
  29. package/src/engine/ecs/foliage/ecs/InstancedMeshSerializationAdapter.js +0 -28
  30. package/src/engine/ecs/foliage/ecs/convertInstancedMeshComponents2Entities.js +0 -64
  31. package/src/engine/ecs/foliage/ecs/optimizeIndividualMeshesEntitiesToInstances.js +0 -233
  32. package/src/engine/save/storage/GooglePlayStorage.js +0 -47
  33. package/src/engine/save/storage/JsonStringCodec.js +0 -24
  34. /package/src/engine/sound/ecs/emitter/{SoundEmitter.spec.js → SoundEmitterSerializationAdapter.spec.js} +0 -0
@@ -53506,8 +53506,8 @@ class Vector2 {
53506
53506
  * @returns {number}
53507
53507
  */
53508
53508
  hash() {
53509
- const x = Math.sin(this.x) * 1367130550;
53510
- const y = Math.sin(this.y) * 1367130550;
53509
+ const x = computeHashFloat(this.x);
53510
+ const y = computeHashFloat(this.y);
53511
53511
 
53512
53512
  let hash = ((x << 5) - x) + y;
53513
53513
 
@@ -53644,6 +53644,7 @@ Vector2.one = Object.freeze(new Vector2(1, 1));
53644
53644
  * @type {boolean}
53645
53645
  */
53646
53646
  Vector2.prototype.isVector2 = true;
53647
+
53647
53648
  /**
53648
53649
  *
53649
53650
  * @param {number} x0
@@ -62093,9 +62094,12 @@ class List {
62093
62094
  /**
62094
62095
  * Retrieve element at a given position in the list
62095
62096
  * @param {number} index
62096
- * @returns {T}
62097
+ * @returns {T|undefined}
62097
62098
  */
62098
62099
  get(index) {
62100
+ assert.isNumber(index, 'index');
62101
+ assert.isNonNegativeInteger(index, 'index');
62102
+
62099
62103
  return this.data[index];
62100
62104
  }
62101
62105
 
@@ -62105,6 +62109,9 @@ class List {
62105
62109
  * @param {T} value
62106
62110
  */
62107
62111
  set(index, value) {
62112
+ assert.isNumber(index, 'index');
62113
+ assert.isNonNegativeInteger(index, 'index');
62114
+
62108
62115
  const oldValue = this.data[index];
62109
62116
 
62110
62117
  if (oldValue !== undefined) {
@@ -62225,7 +62232,7 @@ class List {
62225
62232
  /**
62226
62233
  * Replace the data, replacements is performed surgically, meaning that diff is computed and add/remove operations are performed on the set
62227
62234
  * This method is tailored to work well with visualisation as only elements that's missing from the new set is removed, and only elements that are new to are added
62228
- * Conversely, relevant events are dispatched that a visualisation can observe. This results in fewer changes required to the visualisation
62235
+ * Conversely, relevant events are dispatched that can observe. This results in fewer changes required to the visualisation
62229
62236
  * @param {T[]} newOutput
62230
62237
  */
62231
62238
  patch(newOutput) {
@@ -79040,7 +79047,7 @@ class ExplicitBinaryBoundingVolumeHierarchy {
79040
79047
  /**
79041
79048
  *
79042
79049
  * @param {number} id
79043
- * @param {number[]} result
79050
+ * @param {number[]|Float32Array} result
79044
79051
  */
79045
79052
  node_get_aabb(id, result) {
79046
79053
  assert.isNonNegativeInteger(id, 'id');
@@ -80199,18 +80206,6 @@ function bvh_query_leaves_generic(
80199
80206
  return result_cursor - result_offset;
80200
80207
  }
80201
80208
 
80202
- class BVHQuery {
80203
- /**
80204
- *
80205
- * @param {number} node
80206
- * @param {ExplicitBinaryBoundingVolumeHierarchy} tree
80207
- * @returns {boolean}
80208
- */
80209
- evaluate(node, tree) {
80210
- throw new Error('Not Implemented');
80211
- }
80212
- }
80213
-
80214
80209
  /**
80215
80210
  *
80216
80211
  * @param {ArrayLike<number>|number[]|Float32Array} aabb bounding box, order: x0,y0,z0,x1,y1,z1
@@ -80225,21 +80220,33 @@ function aabb3_array_intersects_ray_array(aabb, ray) {
80225
80220
  );
80226
80221
  }
80227
80222
 
80223
+ class BVHQuery {
80224
+ /**
80225
+ *
80226
+ * @param {number} node
80227
+ * @param {ExplicitBinaryBoundingVolumeHierarchy} tree
80228
+ * @returns {boolean}
80229
+ */
80230
+ evaluate(node, tree) {
80231
+ throw new Error('Not Implemented');
80232
+ }
80233
+ }
80234
+
80228
80235
  const scratch_aabb = [];
80229
80236
 
80230
80237
  class BVHQueryIntersectsRay extends BVHQuery {
80231
- constructor() {
80232
- super();
80233
-
80234
- this.ray = [];
80235
- }
80238
+ /**
80239
+ *
80240
+ * @type {number[]}
80241
+ */
80242
+ ray = [];
80236
80243
 
80237
80244
  /**
80238
80245
  *
80239
80246
  * @param {number[]|ArrayLike<number>} ray
80240
80247
  * @returns {BVHQueryIntersectsRay}
80241
80248
  */
80242
- static from(ray){
80249
+ static from(ray) {
80243
80250
  const r = new BVHQueryIntersectsRay();
80244
80251
 
80245
80252
  r.ray = ray;
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "description": "Fully featured ECS game engine written in JavaScript",
6
6
  "type": "module",
7
7
  "author": "Alexander Goldring",
8
- "version": "2.63.0",
8
+ "version": "2.64.0",
9
9
  "main": "build/meep.module.js",
10
10
  "module": "build/meep.module.js",
11
11
  "exports": {
@@ -0,0 +1,5 @@
1
+ /**
2
+ * equal to `Math.pow(2,16) - 1`
3
+ * @type {number}
4
+ */
5
+ export const UINT16_MAX = 65535;
@@ -1,9 +1,9 @@
1
- import { aabb3_compute_surface_area } from "../../geom/3d/aabb/aabb3_compute_surface_area.js";
2
- import { min2 } from "../../math/min2.js";
3
- import { max2 } from "../../math/max2.js";
4
1
  import { assert } from "../../assert.js";
5
- import { typed_array_copy } from "../../collection/array/typed/typed_array_copy.js";
6
2
  import { array_copy } from "../../collection/array/array_copy.js";
3
+ import { typed_array_copy } from "../../collection/array/typed/typed_array_copy.js";
4
+ import { aabb3_compute_surface_area } from "../../geom/3d/aabb/aabb3_compute_surface_area.js";
5
+ import { max2 } from "../../math/max2.js";
6
+ import { min2 } from "../../math/min2.js";
7
7
 
8
8
  export const COLUMN_PARENT = 6;
9
9
  export const COLUMN_CHILD_1 = 7;
@@ -373,7 +373,7 @@ export class ExplicitBinaryBoundingVolumeHierarchy {
373
373
  /**
374
374
  *
375
375
  * @param {number} id
376
- * @param {number[]} result
376
+ * @param {number[]|Float32Array} result
377
377
  */
378
378
  node_get_aabb(id, result) {
379
379
  assert.isNonNegativeInteger(id, 'id');
@@ -1,18 +1,16 @@
1
- import { BVHQuery } from "./BVHQuery.js";
2
1
  import { aabb3_array_intersects_frustum_array } from "../../../geom/3d/aabb/aabb3_array_intersects_frustum_array.js";
2
+ import { BVHQuery } from "./BVHQuery.js";
3
3
 
4
4
  const scratch_aabb = [];
5
5
 
6
6
  export class BVHQueryIntersectsFrustum extends BVHQuery {
7
- constructor() {
8
- super();
9
-
10
- /**
11
- * Collection of 6 planes: normal_x, normal_y, normal_z, offset
12
- * @type {number[]}
13
- */
14
- this.frustum = [];
15
- }
7
+
8
+ /**
9
+ * Collection of 6 planes: normal_x, normal_y, normal_z, offset
10
+ * @type {number[]}
11
+ */
12
+ frustum = [];
13
+
16
14
 
17
15
  /**
18
16
  *
@@ -1,21 +1,21 @@
1
- import { BVHQuery } from "./BVHQuery.js";
2
1
  import { aabb3_array_intersects_ray_array } from "../../../geom/3d/aabb/aabb3_array_intersects_ray_array.js";
2
+ import { BVHQuery } from "./BVHQuery.js";
3
3
 
4
4
  const scratch_aabb = [];
5
5
 
6
6
  export class BVHQueryIntersectsRay extends BVHQuery {
7
- constructor() {
8
- super();
9
-
10
- this.ray = [];
11
- }
7
+ /**
8
+ *
9
+ * @type {number[]}
10
+ */
11
+ ray = [];
12
12
 
13
13
  /**
14
14
  *
15
15
  * @param {number[]|ArrayLike<number>} ray
16
16
  * @returns {BVHQueryIntersectsRay}
17
17
  */
18
- static from(ray){
18
+ static from(ray) {
19
19
  const r = new BVHQueryIntersectsRay();
20
20
 
21
21
  r.ray = ray;
@@ -0,0 +1,37 @@
1
+ import { aabb3_array_intersects_sphere_array } from "../../../geom/3d/aabb/aabb3_array_intersects_sphere_array.js";
2
+ import { BVHQuery } from "./BVHQuery.js";
3
+
4
+ const scratch_aabb = [];
5
+
6
+ export class BVHQueryIntersectsSphere extends BVHQuery {
7
+
8
+ /**
9
+ *
10
+ * @type {number[]}
11
+ */
12
+ sphere = [];
13
+
14
+ /**
15
+ *
16
+ * @param {number[]|ArrayLike<number>} sphere
17
+ * @returns {BVHQueryIntersectsRay}
18
+ */
19
+ static from(sphere) {
20
+ const r = new BVHQueryIntersectsSphere();
21
+
22
+ r.sphere = sphere;
23
+
24
+ return r;
25
+ }
26
+
27
+ evaluate(node, tree) {
28
+
29
+ tree.node_get_aabb(node, scratch_aabb);
30
+
31
+ // test node against the ray
32
+ return aabb3_array_intersects_sphere_array(
33
+ scratch_aabb,
34
+ this.sphere
35
+ );
36
+ }
37
+ }
@@ -1,5 +1,6 @@
1
- import { NULL_NODE } from "../ExplicitBinaryBoundingVolumeHierarchy.js";
1
+ import { assert } from "../../../assert.js";
2
2
  import { SCRATCH_UINT32_TRAVERSAL_STACK } from "../../../collection/SCRATCH_UINT32_TRAVERSAL_STACK.js";
3
+ import { NULL_NODE } from "../ExplicitBinaryBoundingVolumeHierarchy.js";
3
4
 
4
5
  const stack = SCRATCH_UINT32_TRAVERSAL_STACK;
5
6
 
@@ -15,9 +16,15 @@ const stack = SCRATCH_UINT32_TRAVERSAL_STACK;
15
16
  */
16
17
  export function bvh_query_user_data_generic(
17
18
  result, result_offset,
18
- bvh,root, query
19
+ bvh, root, query
19
20
  ) {
20
21
 
22
+ assert.isArrayLike(result, 'result');
23
+ assert.isNonNegativeInteger(result_offset, 'result_offset');
24
+ assert.defined(bvh, 'bvh');
25
+ assert.isNonNegativeInteger(root, 'root');
26
+ assert.defined(query, 'query');
27
+
21
28
  if (root === NULL_NODE) {
22
29
  return 0;
23
30
  }
@@ -44,13 +51,14 @@ export function bvh_query_user_data_generic(
44
51
  // test node against the query
45
52
  const pass = query.evaluate(node, bvh);
46
53
 
47
- if (!pass) {
54
+ if (pass === false) {
48
55
  continue;
49
56
  }
50
57
 
51
58
  const node_is_leaf = bvh.node_is_leaf(node);
52
59
 
53
- if (!node_is_leaf) {
60
+ if (node_is_leaf === false) {
61
+ // binary-node
54
62
 
55
63
  // read in-order
56
64
  const child1 = bvh.node_get_child1(node);
@@ -0,0 +1,29 @@
1
+ import { ExplicitBinaryBoundingVolumeHierarchy } from "../ExplicitBinaryBoundingVolumeHierarchy.js";
2
+ import { bvh_query_user_data_generic } from "./bvh_query_user_data_generic.js";
3
+ import { BVHQueryAny } from "./BVHQueryAny.js";
4
+
5
+ test("all-accepting query", () => {
6
+ const bvh = new ExplicitBinaryBoundingVolumeHierarchy();
7
+
8
+ const leaf_a = bvh.allocate_node();
9
+ const leaf_b = bvh.allocate_node();
10
+
11
+ bvh.node_set_user_data(leaf_a, 7);
12
+ bvh.node_set_user_data(leaf_b, 13);
13
+
14
+ bvh.insert_leaf(leaf_a);
15
+ bvh.insert_leaf(leaf_b);
16
+
17
+ const result = [];
18
+
19
+ const count = bvh_query_user_data_generic(
20
+ result, 1,
21
+ bvh, bvh.root,
22
+ BVHQueryAny.INSTANCE
23
+ );
24
+
25
+ expect(count).toBe(2);
26
+ expect(result).toContain(7);
27
+ expect(result).toContain(13);
28
+
29
+ });
@@ -6,8 +6,8 @@
6
6
  import { assert } from "../../assert.js";
7
7
  import Signal from "../../events/signal/Signal.js";
8
8
  import { invokeObjectEquals } from "../../model/object/invokeObjectEquals.js";
9
- import { arraySetDiff } from "../array/arraySetDiff.js";
10
9
  import { arrayIndexByEquality } from "../array/arrayIndexByEquality.js";
10
+ import { arraySetDiff } from "../array/arraySetDiff.js";
11
11
 
12
12
 
13
13
  /**
@@ -51,9 +51,12 @@ class List {
51
51
  /**
52
52
  * Retrieve element at a given position in the list
53
53
  * @param {number} index
54
- * @returns {T}
54
+ * @returns {T|undefined}
55
55
  */
56
56
  get(index) {
57
+ assert.isNumber(index, 'index');
58
+ assert.isNonNegativeInteger(index, 'index');
59
+
57
60
  return this.data[index];
58
61
  }
59
62
 
@@ -63,6 +66,9 @@ class List {
63
66
  * @param {T} value
64
67
  */
65
68
  set(index, value) {
69
+ assert.isNumber(index, 'index');
70
+ assert.isNonNegativeInteger(index, 'index');
71
+
66
72
  const oldValue = this.data[index];
67
73
 
68
74
  if (oldValue !== undefined) {
@@ -183,7 +189,7 @@ class List {
183
189
  /**
184
190
  * Replace the data, replacements is performed surgically, meaning that diff is computed and add/remove operations are performed on the set
185
191
  * This method is tailored to work well with visualisation as only elements that's missing from the new set is removed, and only elements that are new to are added
186
- * Conversely, relevant events are dispatched that a visualisation can observe. This results in fewer changes required to the visualisation
192
+ * Conversely, relevant events are dispatched that can observe. This results in fewer changes required to the visualisation
187
193
  * @param {T[]} newOutput
188
194
  */
189
195
  patch(newOutput) {
@@ -1,10 +1,10 @@
1
- import { min2 } from "../../../math/min2.js";
2
- import { max2 } from "../../../math/max2.js";
3
1
  import { assert } from "../../../assert.js";
2
+ import { max2 } from "../../../math/max2.js";
3
+ import { min2 } from "../../../math/min2.js";
4
4
 
5
5
  /**
6
6
  *
7
- * @param {AABB3} result
7
+ * @param {ArrayLike<number>|number[]|Float32Array|AABB3} result
8
8
  * @param {number[]|ArrayLike<number>|Float32Array} input
9
9
  * @param {number} input_length length of the input array
10
10
  */
@@ -33,5 +33,12 @@ export function aabb3_from_v3_array(result, input, input_length) {
33
33
  z1 = max2(z, z1);
34
34
  }
35
35
 
36
- result.setBounds(x0, y0, z0, x1, y1, z1);
36
+ // read out
37
+ result[0] = x0;
38
+ result[1] = y0;
39
+ result[2] = z0;
40
+
41
+ result[3] = x1;
42
+ result[4] = y1;
43
+ result[5] = z1;
37
44
  }
@@ -6,11 +6,12 @@
6
6
  import { assert } from "../assert.js";
7
7
  import Signal from "../events/signal/Signal.js";
8
8
  import { clamp } from "../math/clamp.js";
9
+ import { EPSILON } from "../math/EPSILON.js";
10
+ import { epsilonEquals } from "../math/epsilonEquals.js";
9
11
  import { lerp } from "../math/lerp.js";
10
12
  import { max2 } from "../math/max2.js";
11
13
  import { min2 } from "../math/min2.js";
12
- import { EPSILON } from "../math/EPSILON.js";
13
- import { epsilonEquals } from "../math/epsilonEquals.js";
14
+ import { computeHashFloat } from "../primitives/numbers/computeHashFloat.js";
14
15
 
15
16
  class Vector2 {
16
17
  /**
@@ -542,8 +543,8 @@ class Vector2 {
542
543
  * @returns {number}
543
544
  */
544
545
  hash() {
545
- const x = Math.sin(this.x) * 1367130550;
546
- const y = Math.sin(this.y) * 1367130550;
546
+ const x = computeHashFloat(this.x);
547
+ const y = computeHashFloat(this.y);
547
548
 
548
549
  let hash = ((x << 5) - x) + y;
549
550
 
@@ -680,6 +681,7 @@ Vector2.one = Object.freeze(new Vector2(1, 1));
680
681
  * @type {boolean}
681
682
  */
682
683
  Vector2.prototype.isVector2 = true;
684
+
683
685
  /**
684
686
  *
685
687
  * @param {number} x0