@woosh/meep-engine 2.61.0 → 2.63.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 (56) hide show
  1. package/build/meep.cjs +1277 -1259
  2. package/build/meep.min.js +1 -1
  3. package/build/meep.module.js +1277 -1259
  4. package/package.json +1 -1
  5. package/src/core/binary/EncodingBinaryBuffer.js +7 -43
  6. package/src/core/binary/EncodingBinaryBuffer.spec.js +16 -0
  7. package/src/core/bvh2/BinaryNode.js +16 -13
  8. package/src/core/bvh2/LeafNode.js +6 -3
  9. package/src/core/bvh2/bvh3/EBBVHLeafProxy.js +4 -2
  10. package/src/core/bvh2/bvh3/query/bvh_query_user_data_overlaps_sphere.js +81 -0
  11. package/src/core/cache/LoadingCache.js +4 -1
  12. package/src/core/collection/map/BiMap.js +49 -0
  13. package/src/core/geom/3d/aabb/AABB3.js +24 -36
  14. package/src/core/geom/3d/aabb/aabb3_array_compute_from_sphere.js +22 -0
  15. package/src/core/geom/3d/aabb/aabb3_array_intersects_sphere.js +22 -0
  16. package/src/core/geom/3d/aabb/aabb3_array_intersects_sphere_array.js +11 -0
  17. package/src/core/geom/3d/aabb/aabb3_signed_distance_to_aabb3.js +28 -0
  18. package/src/core/geom/3d/aabb/serializeAABB3Quantized16Uint.js +19 -10
  19. package/src/core/geom/3d/tetrahedra/delaunay/Cavity.js +3 -4
  20. package/src/engine/ecs/components/Tag.d.ts +2 -0
  21. package/src/engine/ecs/components/Tag.js +19 -28
  22. package/src/engine/ecs/components/Tag.spec.js +47 -0
  23. package/src/engine/ecs/foliage/ecs/Foliage2System.js +3 -0
  24. package/src/engine/ecs/foliage/ecs/InstancedMeshComponent.js +4 -1
  25. package/src/engine/ecs/foliage/ecs/convertInstancedMeshComponents2Entities.js +64 -0
  26. package/src/engine/ecs/foliage/ecs/{InstancedMeshUtils.js → optimizeIndividualMeshesEntitiesToInstances.js} +11 -70
  27. package/src/engine/ecs/fow/FogOfWar.js +4 -0
  28. package/src/engine/ecs/fow/FogOfWarEditor.js +3 -0
  29. package/src/engine/ecs/terrain/TerrainPreview.js +45 -44
  30. package/src/engine/ecs/terrain/ecs/cling/ClingToTerrain.js +22 -4
  31. package/src/engine/ecs/terrain/tiles/TerrainTile.js +17 -12
  32. package/src/engine/graphics/camera/testClippingPlaneComputation.js +25 -27
  33. package/src/engine/graphics/ecs/mesh/Mesh.d.ts +0 -4
  34. package/src/engine/graphics/ecs/mesh/Mesh.js +0 -11
  35. package/src/engine/graphics/ecs/mesh/MeshSystem.js +57 -67
  36. package/src/engine/graphics/ecs/path/testPathDisplaySystem.js +49 -52
  37. package/src/engine/graphics/ecs/path/tube/prototypeAnimatedPathMask.js +40 -42
  38. package/src/engine/graphics/particles/ecs/ParticleEmitterSystem.js +43 -25
  39. package/src/engine/graphics/particles/particular/engine/ParticularEngine.js +10 -6
  40. package/src/engine/graphics/particles/particular/engine/emitter/ParticleEmitter.js +37 -41
  41. package/src/engine/graphics/particles/particular/engine/utils/volume/prototypeParticleVolume.js +44 -46
  42. package/src/engine/graphics/render/buffer/buffers/prototypeNormalFrameBuffer.js +24 -26
  43. package/src/engine/graphics/render/forward_plus/plugin/ptototypeFPPlugin.js +40 -42
  44. package/src/engine/graphics/render/visibility/hiz/prototypeHiZ.js +36 -38
  45. package/src/engine/graphics/shadows/testShadowMapRendering.js +19 -19
  46. package/src/engine/grid/ORTHOGONAL_NEIGHBOURHOOD_MASK.js +11 -0
  47. package/src/engine/sound/dB2Volume.js +8 -0
  48. package/src/engine/sound/ecs/emitter/SoundEmitter.js +125 -99
  49. package/src/engine/sound/ecs/emitter/SoundEmitterComponentContext.js +4 -42
  50. package/src/engine/sound/ecs/emitter/SoundEmitterSystem.js +31 -121
  51. package/src/engine/sound/volume2dB.js +8 -0
  52. package/src/generation/theme/ThemeEngine.js +19 -53
  53. package/src/core/binary/stringToByteArray.js +0 -24
  54. package/src/engine/graphics/geometry/bvh/buffered/BVHFromBufferGeometry.js +0 -133
  55. package/src/engine/save/storage/LocalStorage.js +0 -148
  56. package/src/engine/save/storage/MsgPackCodec.js +0 -22
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.61.0",
8
+ "version": "2.63.0",
9
9
  "main": "build/meep.module.js",
10
10
  "module": "build/meep.module.js",
11
11
  "exports": {
@@ -1,58 +1,22 @@
1
+ import { BiMap } from "../collection/map/BiMap.js";
1
2
  import { BinaryBuffer } from "./BinaryBuffer.js";
2
3
 
3
- class Dictionary {
4
- constructor() {
5
- this.forward = new Map();
6
- this.backward = new Map();
7
- }
8
-
9
- /**
10
- *
11
- * @param {*} value
12
- * @param {number} address
13
- */
14
- add(value, address) {
15
- this.forward.set(address, value);
16
- this.backward.set(value, address);
17
- }
18
-
19
- /**
20
- *
21
- * @param {*} value
22
- * @returns {number|undefined}
23
- */
24
- getAddress(value) {
25
- return this.backward.get(value);
26
- }
27
-
28
- /**
29
- *
30
- * @param {number} address
31
- * @returns {*}
32
- */
33
- getValue(address) {
34
- return this.forward.get(address);
35
- }
36
- }
4
+ export class EncodingBinaryBuffer extends BinaryBuffer {
37
5
 
6
+ __dictionary = new BiMap();
38
7
 
39
- export class EncodingBinaryBuffer extends BinaryBuffer {
40
- constructor() {
41
- super();
42
- this.__dictionary = new Dictionary();
43
- }
44
8
 
45
9
  writeUTF8String(value) {
46
- const address = this.__dictionary.getAddress(value);
10
+ const address = this.__dictionary.getKeyByValue(value);
47
11
 
48
12
  if (address === undefined) {
49
13
  this.writeUint8(0); //mark as complete value
50
14
 
51
- const address1 = this.position;
15
+ const current_address = this.position;
52
16
 
53
17
  super.writeUTF8String(value);
54
18
 
55
- this.__dictionary.add(value, address1);
19
+ this.__dictionary.add(value, current_address);
56
20
  } else {
57
21
  //write as reference
58
22
  this.writeUint32LE(1 | (address << 1));
@@ -72,7 +36,7 @@ export class EncodingBinaryBuffer extends BinaryBuffer {
72
36
 
73
37
  const address = header >> 1;
74
38
 
75
- let value = this.__dictionary.getValue(address);
39
+ let value = this.__dictionary.getValueByKey(address);
76
40
 
77
41
  if (value === undefined) {
78
42
  //remember position
@@ -0,0 +1,16 @@
1
+ import { EncodingBinaryBuffer } from "./EncodingBinaryBuffer.js";
2
+
3
+ test("read/write strings", () => {
4
+
5
+ const buffer = new EncodingBinaryBuffer();
6
+
7
+ buffer.writeUTF8String("hello world");
8
+ buffer.writeUTF8String("cat");
9
+ buffer.writeUTF8String("hello world");
10
+
11
+ buffer.position = 0;
12
+
13
+ expect(buffer.readUTF8String()).toEqual("hello world");
14
+ expect(buffer.readUTF8String()).toEqual("cat");
15
+ expect(buffer.readUTF8String()).toEqual("hello world");
16
+ });
@@ -3,19 +3,19 @@
3
3
  */
4
4
 
5
5
 
6
- import { assert } from "../assert.js";
7
- import { arrayQuickSort } from "../collection/array/arrayQuickSort.js";
8
- import { max2 } from "../math/max2.js";
9
- import { min2 } from "../math/min2.js";
10
- import { computeSampleStandardDeviation } from "../math/statistics/computeSampleStandardDeviation.js";
11
- import { isLeaf, LeafNode } from "./LeafNode.js";
12
- import { Node } from "./Node.js";
13
- import { surfaceAreaHeuristic } from "./sah/surfaceAreaHeuristic.js";
14
- import { BVHVisitor } from "./traversal/BVHVisitor.js";
15
- import { traverseBinaryNodeUsingVisitor } from "./traversal/traverseBinaryNodeUsingVisitor.js";
16
- import { aabb3_intersects_aabb3 } from "../geom/3d/aabb/aabb3_intersects_aabb3.js";
17
- import { aabb3_box_surface_area_2 } from "../geom/3d/aabb/aabb3_box_surface_area_2.js";
18
- import { aabb3_combined_surface_area } from "../geom/3d/aabb/aabb3_combined_surface_area.js";
6
+ import {assert} from "../assert.js";
7
+ import {arrayQuickSort} from "../collection/array/arrayQuickSort.js";
8
+ import {aabb3_box_surface_area_2} from "../geom/3d/aabb/aabb3_box_surface_area_2.js";
9
+ import {aabb3_combined_surface_area} from "../geom/3d/aabb/aabb3_combined_surface_area.js";
10
+ import {aabb3_intersects_aabb3} from "../geom/3d/aabb/aabb3_intersects_aabb3.js";
11
+ import {max2} from "../math/max2.js";
12
+ import {min2} from "../math/min2.js";
13
+ import {computeSampleStandardDeviation} from "../math/statistics/computeSampleStandardDeviation.js";
14
+ import {isLeaf, LeafNode} from "./LeafNode.js";
15
+ import {Node} from "./Node.js";
16
+ import {surfaceAreaHeuristic} from "./sah/surfaceAreaHeuristic.js";
17
+ import {BVHVisitor} from "./traversal/BVHVisitor.js";
18
+ import {traverseBinaryNodeUsingVisitor} from "./traversal/traverseBinaryNodeUsingVisitor.js";
19
19
 
20
20
 
21
21
  /**
@@ -36,6 +36,9 @@ let stackPointer = 0;
36
36
  */
37
37
  const stack = [];
38
38
 
39
+ /**
40
+ * @deprecated use {@link ExplicitBinaryBoundingVolumeHierarchy} instead
41
+ */
39
42
  export class BinaryNode extends Node {
40
43
  constructor() {
41
44
  super();
@@ -1,9 +1,9 @@
1
1
  /**
2
2
  * Created by Alex on 17/11/2014.
3
3
  */
4
- import { Node } from "./Node.js";
5
- import { serializeAABB3 } from "../geom/3d/aabb/serializeAABB3.js";
6
- import { deserializeAABB3 } from "../geom/3d/aabb/deserializeAABB3.js";
4
+ import {deserializeAABB3} from "../geom/3d/aabb/deserializeAABB3.js";
5
+ import {serializeAABB3} from "../geom/3d/aabb/serializeAABB3.js";
6
+ import {Node} from "./Node.js";
7
7
 
8
8
 
9
9
  /**
@@ -15,6 +15,9 @@ function isLeaf(node) {
15
15
  return node.isLeafNode;
16
16
  }
17
17
 
18
+ /**
19
+ * @deprecated use {@link ExplicitBinaryBoundingVolumeHierarchy} and {@link EBBVHLeafProxy} respectively
20
+ */
18
21
  export class LeafNode extends Node {
19
22
  /**
20
23
  *
@@ -50,8 +50,10 @@ export class EBBVHLeafProxy {
50
50
  unlink() {
51
51
  assert.equal(this.is_linked, true, 'not linked');
52
52
 
53
- this.#tree.remove_leaf(this.#node_id);
54
- this.#tree.release_node(this.#node_id);
53
+ const node_id = this.#node_id;
54
+
55
+ this.#tree.remove_leaf(node_id);
56
+ this.#tree.release_node(node_id);
55
57
 
56
58
  this.#node_id = -1;
57
59
  this.#tree = null;
@@ -0,0 +1,81 @@
1
+ import {SCRATCH_UINT32_TRAVERSAL_STACK} from "../../../collection/SCRATCH_UINT32_TRAVERSAL_STACK.js";
2
+ import {aabb3_array_intersects_sphere_array} from "../../../geom/3d/aabb/aabb3_array_intersects_sphere_array.js";
3
+ import {NULL_NODE} from "../ExplicitBinaryBoundingVolumeHierarchy.js";
4
+ import {bvh_collect_user_data} from "./bvh_collect_user_data.js";
5
+
6
+ const stack = SCRATCH_UINT32_TRAVERSAL_STACK;
7
+
8
+ const scratch_aabb = new Float32Array(6);
9
+
10
+ /**
11
+ *
12
+ * @param {number[]} result
13
+ * @param {number} result_offset
14
+ * @param {ExplicitBinaryBoundingVolumeHierarchy} bvh
15
+ * @param {number[]|Float32Array} sphere
16
+ */
17
+ export function bvh_query_user_data_overlaps_sphere(
18
+ result,
19
+ result_offset,
20
+ bvh,
21
+ sphere
22
+ ) {
23
+ const root = bvh.root;
24
+
25
+ if (root === NULL_NODE) {
26
+ return 0;
27
+ }
28
+
29
+ /**
30
+ *
31
+ * @type {number}
32
+ */
33
+ const stack_top = stack.pointer++;
34
+
35
+ stack[stack_top] = root;
36
+
37
+ let result_cursor = result_offset;
38
+
39
+ while (stack.pointer > stack_top) {
40
+ stack.pointer--;
41
+
42
+ /**
43
+ *
44
+ * @type {number}
45
+ */
46
+ const node = stack[stack.pointer];
47
+
48
+ // test node against the ray
49
+ bvh.node_get_aabb(node, scratch_aabb);
50
+ const intersection = aabb3_array_intersects_sphere_array(scratch_aabb, sphere);
51
+
52
+ if (intersection === 0) {
53
+ // fully outside
54
+ continue;
55
+ }
56
+
57
+ const node_is_leaf = bvh.node_is_leaf(node);
58
+
59
+ if (node_is_leaf) {
60
+ // leaf node
61
+ result[result_cursor++] = bvh.node_get_user_data(node);
62
+
63
+ } else if (intersection === 2) {
64
+ // fully inside, fast collection path
65
+ result_cursor += bvh_collect_user_data(result, result_cursor, bvh, node);
66
+ } else {
67
+ // partially inside
68
+ // read in-order
69
+ const child1 = bvh.node_get_child1(node);
70
+ const child2 = bvh.node_get_child2(node);
71
+
72
+ // write to stack in reverse order, so that fist child ends up being visited first
73
+ stack[stack.pointer++] = child1;
74
+ stack[stack.pointer++] = child2;
75
+ }
76
+ }
77
+
78
+ // drop stack frame
79
+
80
+ return result_cursor - result_offset;
81
+ }
@@ -1,7 +1,8 @@
1
1
  //
2
2
 
3
- import { Cache } from "./Cache.js";
3
+ import { assert } from "../assert.js";
4
4
  import { current_time_in_seconds } from "../time/current_time_in_seconds.js";
5
+ import { Cache } from "./Cache.js";
5
6
 
6
7
  /**
7
8
  * @template R
@@ -79,6 +80,8 @@ export class LoadingCache {
79
80
  retryFailed = true
80
81
  }) {
81
82
 
83
+ assert.isFunction(load, 'load');
84
+
82
85
  this.#internal = new Cache({
83
86
  maxWeight,
84
87
  keyWeigher,
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Bi-directional map
3
+ * @template K,V
4
+ */
5
+ export class BiMap {
6
+
7
+ /**
8
+ *
9
+ * @type {Map<K, V>}
10
+ */
11
+ forward = new Map();
12
+ /**
13
+ *
14
+ * @type {Map<V, K>}
15
+ */
16
+ backward = new Map();
17
+
18
+
19
+ /**
20
+ *
21
+ * @param {K} key
22
+ * @param {V} value
23
+ */
24
+ add(key, value) {
25
+ this.forward.set(value, key);
26
+ this.backward.set(key, value);
27
+ }
28
+
29
+ /**
30
+ *
31
+ * @param {V} value
32
+ * @returns {K|undefined}
33
+ */
34
+ getKeyByValue(value) {
35
+ return this.backward.get(value);
36
+ }
37
+
38
+ /**
39
+ *
40
+ * @param {K} address
41
+ * @returns {V|undefined}
42
+ */
43
+ getValueByKey(address) {
44
+ return this.forward.get(address);
45
+ }
46
+ }
47
+
48
+ BiMap.prototype.get = BiMap.prototype.getValueByKey;
49
+ BiMap.prototype.set = BiMap.prototype.add;
@@ -3,22 +3,24 @@
3
3
  */
4
4
 
5
5
 
6
- import { aabb3_compute_distance_above_plane_max } from "./aabb3_compute_distance_above_plane_max.js";
7
- import { aabb3_compute_plane_side } from "./aabb3_compute_plane_side.js";
6
+ import {assert} from "../../../assert.js";
8
7
  import computeMortonCode from "../morton/Morton.js";
9
- import { aabb3_build_corners } from "./aabb3_build_corners.js";
10
- import { assert } from "../../../assert.js";
11
- import { aabb3_intersects_frustum_degree } from "./aabb3_intersects_frustum_degree.js";
12
- import { aabb3_intersects_line_segment } from "./aabb3_intersects_line_segment.js";
13
- import { aabb3_intersects_ray } from "./aabb3_intersects_ray.js";
14
- import { aabb3_compute_surface_area } from "./aabb3_compute_surface_area.js";
15
- import { aabb3_intersects_frustum_array } from "./aabb3_intersects_frustum_array.js";
16
- import { aabb3_matrix4_project } from "./aabb3_matrix4_project.js";
17
- import { aabb3_signed_distance_sqr_to_point } from "./aabb3_signed_distance_sqr_to_point.js";
18
- import { aabb3_array_intersects_point } from "./aabb3_array_intersects_point.js";
8
+ import {aabb3_array_intersects_point} from "./aabb3_array_intersects_point.js";
9
+ import {aabb3_build_corners} from "./aabb3_build_corners.js";
10
+ import {aabb3_compute_distance_above_plane_max} from "./aabb3_compute_distance_above_plane_max.js";
11
+ import {aabb3_compute_plane_side} from "./aabb3_compute_plane_side.js";
12
+ import {aabb3_compute_surface_area} from "./aabb3_compute_surface_area.js";
13
+ import {aabb3_intersects_frustum_array} from "./aabb3_intersects_frustum_array.js";
14
+ import {aabb3_intersects_frustum_degree} from "./aabb3_intersects_frustum_degree.js";
15
+ import {aabb3_intersects_line_segment} from "./aabb3_intersects_line_segment.js";
16
+ import {aabb3_intersects_ray} from "./aabb3_intersects_ray.js";
17
+ import {aabb3_matrix4_project} from "./aabb3_matrix4_project.js";
18
+ import {aabb3_signed_distance_sqr_to_point} from "./aabb3_signed_distance_sqr_to_point.js";
19
+ import {aabb3_signed_distance_to_aabb3} from "./aabb3_signed_distance_to_aabb3.js";
19
20
 
20
21
  /**
21
22
  * Axis-Aligned bounding box in 3D
23
+ * NOTE: In cases where all you want is raw performance - prefer to use typed arrays instead along with `aabb3_` functions
22
24
  */
23
25
  export class AABB3 {
24
26
  /**
@@ -238,7 +240,12 @@ export class AABB3 {
238
240
  * @returns {boolean}
239
241
  */
240
242
  _equals(x0, y0, z0, x1, y1, z1) {
241
- return this.x0 === x0 && this.y0 === y0 && this.z0 === z0 && this.x1 === x1 && this.y1 === y1 && this.z1 === z1;
243
+ return this.x0 === x0
244
+ && this.y0 === y0
245
+ && this.z0 === z0
246
+ && this.x1 === x1
247
+ && this.y1 === y1
248
+ && this.z1 === z1;
242
249
  }
243
250
 
244
251
  /**
@@ -332,28 +339,10 @@ export class AABB3 {
332
339
  const _y1 = this.y1;
333
340
  const _z1 = this.z1;
334
341
 
335
- //do projection
336
- const xp0 = _x0 - x1;
337
- const xp1 = x0 - _x1;
338
- const yp0 = _y0 - y1;
339
- const yp1 = y0 - _y1;
340
- const zp0 = _z0 - z1;
341
- const zp1 = z0 - _z1;
342
-
343
- //calculate separation in each axis
344
- const dx = Math.max(xp0, xp1);
345
- const dy = Math.max(yp0, yp1);
346
- const dz = Math.max(zp0, zp1);
347
-
348
- //straight-line distance
349
- let distance = Math.sqrt(dx * dx + dy * dy + dz * dz);
350
-
351
- if (dx < 0 && dy < 0 && dz < 0) {
352
- //penetration
353
- return -distance;
354
- } else {
355
- return distance;
356
- }
342
+ return aabb3_signed_distance_to_aabb3(
343
+ _x0, _y0, _z0, _x1, _y1, _z1,
344
+ x0, y0, z0, x1, y1, z1
345
+ );
357
346
  }
358
347
 
359
348
  /**
@@ -778,7 +767,6 @@ export class AABB3 {
778
767
  }
779
768
 
780
769
  /**
781
- *
782
770
  * @param {Plane[]} clippingPlanes
783
771
  * @returns {boolean}
784
772
  */
@@ -0,0 +1,22 @@
1
+ /**
2
+ *
3
+ * @param {number[]} output
4
+ * @param {number} output_offset
5
+ * @param {number} x
6
+ * @param {number} y
7
+ * @param {number} z
8
+ * @param {number} radius
9
+ */
10
+ export function aabb3_array_compute_from_sphere(
11
+ output, output_offset,
12
+ x, y, z, radius
13
+ ) {
14
+
15
+ output[output_offset] = x - radius;
16
+ output[output_offset + 1] = y - radius;
17
+ output[output_offset + 2] = z - radius;
18
+ output[output_offset + 3] = x + radius;
19
+ output[output_offset + 4] = y + radius;
20
+ output[output_offset + 5] = z + radius;
21
+
22
+ }
@@ -0,0 +1,22 @@
1
+ import {aabb3_signed_distance_sqr_to_point} from "./aabb3_signed_distance_sqr_to_point.js";
2
+
3
+ /**
4
+ *
5
+ * @param {number[]} aabb
6
+ * @param {number} x
7
+ * @param {number} y
8
+ * @param {number} z
9
+ * @param {number} radius
10
+ * @returns {boolean}
11
+ */
12
+ export function aabb3_array_intersects_sphere(aabb, x, y, z, radius) {
13
+ const distance_sqr = aabb3_signed_distance_sqr_to_point(
14
+ aabb[0], aabb[1], aabb[2],
15
+ aabb[3], aabb[4], aabb[5],
16
+ x, y, z
17
+ );
18
+
19
+ const radius2 = radius * radius;
20
+
21
+ return distance_sqr <= radius2;
22
+ }
@@ -0,0 +1,11 @@
1
+ import {aabb3_array_intersects_sphere} from "./aabb3_array_intersects_sphere.js";
2
+
3
+ /**
4
+ *
5
+ * @param {number[]|Float32Array} aabb
6
+ * @param {number[]|Float32Array} sphere [x,y,z, radius]
7
+ * @returns {boolean}
8
+ */
9
+ export function aabb3_array_intersects_sphere_array(aabb, sphere) {
10
+ return aabb3_array_intersects_sphere(aabb, sphere[0], sphere[1], sphere[2], sphere[3]);
11
+ }
@@ -0,0 +1,28 @@
1
+ export function aabb3_signed_distance_to_aabb3(
2
+ ax0,ay0,az0,ax1,ay1,az1,
3
+ bx0,by0,bz0, bx1,by1,bz1
4
+ ){
5
+
6
+ //do projection
7
+ const xp0 = bx0 - ax1;
8
+ const xp1 = ax0 - bx1;
9
+ const yp0 = by0 - ay1;
10
+ const yp1 = ay0 - by1;
11
+ const zp0 = bz0 - az1;
12
+ const zp1 = az0 - bz1;
13
+
14
+ //calculate separation in each axis
15
+ const dx = Math.max(xp0, xp1);
16
+ const dy = Math.max(yp0, yp1);
17
+ const dz = Math.max(zp0, zp1);
18
+
19
+ //straight-line distance
20
+ let distance = Math.sqrt(dx * dx + dy * dy + dz * dz);
21
+
22
+ if (dx < 0 && dy < 0 && dz < 0) {
23
+ //penetration
24
+ return -distance;
25
+ } else {
26
+ return distance;
27
+ }
28
+ }
@@ -9,20 +9,29 @@
9
9
  * @param {number} y1
10
10
  * @param {number} z1
11
11
  */
12
- export function serializeAABB3Quantized16Uint(buffer, box, x0, y0, z0, x1, y1, z1) {
12
+ export function serializeAABB3Quantized16Uint(
13
+ buffer, box,
14
+ x0, y0, z0, x1, y1, z1
15
+ ) {
16
+
13
17
  //compute value ranges
14
- const xD = x1 - x0;
15
- const yD = y1 - y0;
16
- const zD = z1 - z0;
18
+ const dx = x1 - x0;
19
+ const dy = y1 - y0;
20
+ const dz = z1 - z0;
21
+
22
+ // scale delta to Uin16 range, and avoid division by 0
23
+ const mx = dx > 0 ? 65535 / dx : 0;
24
+ const my = dy > 0 ? 65535 / dy : 0;
25
+ const mz = dz > 0 ? 65535 / dz : 0;
17
26
 
18
27
  //quantize all values
19
- const _x0 = (((box.x0 - x0) / xD) * 65535) | 0;
20
- const _y0 = (((box.y0 - y0) / yD) * 65535) | 0;
21
- const _z0 = (((box.z0 - z0) / zD) * 65535) | 0;
28
+ const _x0 = Math.floor((box.x0 - x0) * mx);
29
+ const _y0 = Math.floor((box.y0 - y0) * my);
30
+ const _z0 = Math.floor((box.z0 - z0) * mz);
22
31
 
23
- const _x1 = (((box.x1 - x0) / xD) * 65535) | 0;
24
- const _y1 = (((box.y1 - y0) / yD) * 65535) | 0;
25
- const _z1 = (((box.z1 - z0) / zD) * 65535) | 0;
32
+ const _x1 = Math.ceil((box.x1 - x0) * mx);
33
+ const _y1 = Math.ceil((box.y1 - y0) * my);
34
+ const _z1 = Math.ceil((box.z1 - z0) * mz);
26
35
 
27
36
  buffer.writeUint16(_x0);
28
37
  buffer.writeUint16(_y0);
@@ -1,5 +1,8 @@
1
1
  import { assert } from "../../../../assert.js";
2
2
 
3
+ /**
4
+ * Represents cavity or "ball" formed when carving out "triangles" to accommodate inserted point
5
+ */
3
6
  export class Cavity {
4
7
  constructor() {
5
8
  /**
@@ -52,10 +55,6 @@ export class Cavity {
52
55
  this.__boundary_size++;
53
56
  }
54
57
 
55
- update() {
56
- // compute in/out state for each side of each tetra
57
- }
58
-
59
58
  /**
60
59
  *
61
60
  * @param {number} i
@@ -17,6 +17,8 @@ export class Tag {
17
17
 
18
18
  containsOneOf(values: string[]): boolean
19
19
 
20
+ hash(): number
21
+
20
22
  equals(other: Tag): boolean
21
23
 
22
24
  static find(tags: string[], ecd: EntityComponentDataset): number[]
@@ -3,8 +3,9 @@
3
3
  */
4
4
 
5
5
 
6
- import { computeStringHash } from "../../../core/primitives/strings/computeStringHash.js";
7
6
  import { assert } from "../../../core/assert.js";
7
+ import { isArrayEqualStrict } from "../../../core/collection/array/isArrayEqualStrict.js";
8
+ import { computeStringHash } from "../../../core/primitives/strings/computeStringHash.js";
8
9
 
9
10
  /**
10
11
  * Stores textual tags, useful for marking entities
@@ -12,7 +13,7 @@ import { assert } from "../../../core/assert.js";
12
13
  export class Tag {
13
14
  /**
14
15
  * @private
15
- * @type {String[]}
16
+ * @type {string[]}
16
17
  */
17
18
  values = [];
18
19
 
@@ -194,41 +195,31 @@ export class Tag {
194
195
  * @return {boolean}
195
196
  */
196
197
  equals(other) {
197
-
198
- const s0 = this.values;
199
-
200
- const s1 = other.values;
201
-
202
- const n0 = s0.length;
203
- const n1 = s1.length;
204
-
205
- if (n0 !== n1) {
206
- //wrong length
207
- return false;
208
- }
209
-
210
- for (let i = 0; i < n0; i++) {
211
- const v0 = s0[i];
212
- const v1 = s1[i];
213
-
214
- if (v0 !== v1) {
215
- return false;
216
- }
217
- }
218
-
219
- return true;
198
+ return isArrayEqualStrict(this.values, other.values);
220
199
  }
221
200
 
222
201
  toJSON() {
223
202
  return this.values;
224
203
  }
225
204
 
205
+ /**
206
+ *
207
+ * @param {string[]|string} json
208
+ */
226
209
  fromJSON(json) {
210
+
211
+ this.clear();
212
+
227
213
  if (typeof json === "string") {
228
- this.clear();
229
214
  this.add(json);
230
- } else if (Array.isArray(json)) {
231
- this.values = json;
215
+ } else {
216
+ assert.isArray(json, 'json');
217
+
218
+ const n = json.length;
219
+
220
+ for (let i = 0; i < n; i++) {
221
+ this.add(json[i]);
222
+ }
232
223
  }
233
224
  }
234
225