@woosh/meep-engine 2.34.48 → 2.35.1

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 (54) hide show
  1. package/core/binary/BitSet.js +7 -2
  2. package/core/bvh2/BinaryNode.js +19 -35
  3. package/core/bvh2/aabb3/aabb3_intersects_frustum_array.js +5 -5
  4. package/core/bvh2/aabb3_combined_surface_area.js +21 -0
  5. package/core/bvh2/traversal/queryBinaryNode_FrustumIntersections.js +24 -12
  6. package/core/cache/Cache.d.ts +2 -0
  7. package/core/cache/Cache.js +27 -23
  8. package/core/geom/3d/frustum/frustum_from_projection_matrix_array.js +29 -24
  9. package/core/math/max2.js +2 -6
  10. package/core/math/min2.js +2 -6
  11. package/engine/asset/loaders/geometry/geometry/computeGeometryEquality.js +3 -2
  12. package/engine/asset/loaders/geometry/geometry/computeGeometryHash.js +9 -1
  13. package/engine/ecs/EntityComponentDataset.js +7 -2
  14. package/engine/ecs/foliage/ViewState.js +13 -3
  15. package/engine/ecs/parent/EntityNode.js +23 -11
  16. package/engine/ecs/transform/Transform.js +15 -13
  17. package/engine/graphics/ecs/mesh-v2/ShadedGeometry.js +63 -26
  18. package/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js +63 -3
  19. package/engine/graphics/ecs/mesh-v2/render/AbstractRenderAdapter.js +67 -0
  20. package/engine/graphics/ecs/mesh-v2/render/GenericRendererAdapter.js +48 -0
  21. package/engine/graphics/ecs/mesh-v2/render/InstancedRendererAdapter.js +110 -0
  22. package/engine/graphics/ecs/mesh-v2/render/ShadedGeometryRendererContext.js +98 -0
  23. package/engine/graphics/ecs/mesh-v2/sample/load_gltf.js +5 -0
  24. package/engine/graphics/ecs/mesh-v2/sample/prototypeShadedGeometry.js +23 -5
  25. package/engine/graphics/ecs/mesh-v2/three_object_to_entity_composition.js +8 -3
  26. package/engine/graphics/geometry/instancing/InstancedMeshGroup.js +23 -85
  27. package/engine/graphics/geometry/instancing/rewriteMaterial.js +9 -45
  28. package/engine/graphics/material/optimization/BUFFER_GEOMETRY_UVS.js +10 -0
  29. package/engine/graphics/material/optimization/MaterialDescriptor.js +46 -0
  30. package/engine/graphics/material/optimization/MaterialOptimizationContext.js +470 -201
  31. package/engine/graphics/material/optimization/UvContext.js +18 -0
  32. package/engine/graphics/material/optimization/is_compliant_mesh.js +71 -0
  33. package/engine/graphics/material/optimization/prepare_atlas_texture.js +23 -0
  34. package/engine/graphics/material/optimization/prototypeMaterialOptimizer.js +127 -0
  35. package/engine/graphics/micron/convert_three_object_to_micron.js +0 -2
  36. package/engine/graphics/micron/format/MicronGeometryPatch.js +34 -24
  37. package/engine/graphics/micron/format/VirtualGeometry.js +47 -11
  38. package/engine/graphics/micron/format/serialization/MicronGeometryBinarySerializationAdapter.js +22 -0
  39. package/engine/graphics/micron/prototypeVirtualGeometry.js +6 -3
  40. package/engine/graphics/micron/render/VirtualGeometryBuilder.js +9 -18
  41. package/engine/graphics/micron/render/instanced/AttributeDataTexture.js +1 -45
  42. package/engine/graphics/micron/render/instanced/ThreeInstancedAdapter.js +18 -7
  43. package/engine/graphics/micron/render/refinement/RefinementSpec.js +0 -12
  44. package/engine/graphics/micron/render/refinement/get_geometry_patch_cut.js +19 -24
  45. package/engine/graphics/micron/render/v1/MaterialContext.js +3 -2
  46. package/engine/graphics/micron/render/v1/VGThreeRenderer.js +19 -4
  47. package/engine/graphics/render/utils/ThreeBypassRenderer.js +3 -2
  48. package/engine/graphics/render/visibility/IncrementalDeltaSet.js +1 -0
  49. package/engine/graphics/texture/normalized_internal_format.js +48 -0
  50. package/engine/graphics/texture/sampler/Sampler2D.js +6 -0
  51. package/engine/graphics/texture/sampler/sampler2d_copy_channel_data.js +25 -0
  52. package/engine/graphics/texture/sampler/scaleSampler2D.js +3 -0
  53. package/engine/graphics/texture/sampler/util/drawSamplerHTML.js +14 -1
  54. package/package.json +1 -1
@@ -59,7 +59,6 @@ const SHRINK_FACTOR = 0.5;
59
59
  */
60
60
  const RESIZE_COUNT_THRESHOLD = 128;
61
61
 
62
-
63
62
  /**
64
63
  * Dynamically sized bit field
65
64
  * @constructor
@@ -389,6 +388,7 @@ BitSet.prototype.set = function (bitIndex, value) {
389
388
  const bitIndexInc = bitIndex + 1;
390
389
 
391
390
  if (bitIndexInc > this.__length) {
391
+ // ensure capacity
392
392
  this.__setLength(bitIndexInc);
393
393
  }
394
394
 
@@ -401,6 +401,7 @@ BitSet.prototype.set = function (bitIndex, value) {
401
401
  this.__data_uint32[word_offset] &= ~word_mask;
402
402
 
403
403
  if (bitIndex === this.__length - 1) {
404
+ // trim down set size potentially
404
405
  const newLastSetBit = this.previousSetBit(bitIndex);
405
406
 
406
407
  this.__setLength(newLastSetBit + 1);
@@ -538,9 +539,13 @@ BitSet.prototype.reset = function () {
538
539
  if (current_length <= 0) {
539
540
  // no action required
540
541
  return;
542
+ } else if (current_length <= 32) {
543
+ // one word, set first word to 0 manually
544
+ this.__data_uint32[0] = 0;
545
+ } else {
546
+ this.__data_uint32.fill(0, 0, Math.ceil(current_length / 32));
541
547
  }
542
548
 
543
- this.__data_uint32.fill(0, 0, Math.ceil(current_length / 32));
544
549
  this.__length = 0;
545
550
  };
546
551
 
@@ -15,7 +15,7 @@ import { BVHVisitor } from "./traversal/BVHVisitor.js";
15
15
  import { traverseBinaryNodeUsingVisitor } from "./traversal/traverseBinaryNodeUsingVisitor.js";
16
16
  import { aabb3_intersect_aabb3 } from "./aabb3/aabb3_intersect_aabb3.js";
17
17
  import { aabb3_box_surface_area_2 } from "./aabb3/aabb3_box_surface_area_2.js";
18
- import { aabb3_compute_half_surface_area } from "./aabb3/aabb3_compute_half_surface_area.js";
18
+ import { aabb3_combined_surface_area } from "./aabb3_combined_surface_area.js";
19
19
 
20
20
 
21
21
  /**
@@ -206,6 +206,7 @@ export class BinaryNode extends Node {
206
206
  /**
207
207
  * For incremental insertion, a sibling needs to be found, newly inserted node will be parented together with this sibling
208
208
  * @see https://github.com/erincatto/box2d/blob/9dc24a6fd4f32442c4bcf80791de47a0a7d25afb/src/collision/b2_dynamic_tree.cpp#L197
209
+ * @private
209
210
  * @param {AABB3} box
210
211
  * @returns {BinaryNode|LeafNode}
211
212
  */
@@ -215,13 +216,13 @@ export class BinaryNode extends Node {
215
216
  let cost_left = 0;
216
217
  let cost_right = 0;
217
218
 
218
- while (node.isBinaryNode) {
219
+ while (node.isBinaryNode === true) {
219
220
  const left = node.left;
220
221
  const right = node.right;
221
222
 
222
223
  const area = aabb3_box_surface_area_2(node);
223
224
 
224
- const combined_area = combined_surface_area(node, box);
225
+ const combined_area = aabb3_combined_surface_area(node, box);
225
226
 
226
227
  //cost of creating a new parent for this node and the new leaf
227
228
  const cost = combined_area;
@@ -231,10 +232,11 @@ export class BinaryNode extends Node {
231
232
 
232
233
  // cost of descending left
233
234
  if (left !== null) {
235
+ const combined_left = aabb3_combined_surface_area(left, box);
234
236
  if (left.isLeafNode) {
235
- cost_left = combined_surface_area(left, box) + inheritance_cost;
237
+ cost_left = combined_left + inheritance_cost;
236
238
  } else {
237
- cost_left = combined_surface_area(left, box) - aabb3_box_surface_area_2(left) + inheritance_cost;
239
+ cost_left = combined_left - aabb3_box_surface_area_2(left) + inheritance_cost;
238
240
  }
239
241
  } else {
240
242
  cost_left = Infinity;
@@ -243,10 +245,11 @@ export class BinaryNode extends Node {
243
245
  // cost of descending right
244
246
  if (right !== null) {
245
247
 
248
+ const combined_right = aabb3_combined_surface_area(right, box);
246
249
  if (right.isLeafNode) {
247
- cost_right = combined_surface_area(right, box) + inheritance_cost;
250
+ cost_right = combined_right + inheritance_cost;
248
251
  } else {
249
- cost_right = combined_surface_area(right, box) - aabb3_box_surface_area_2(right) + inheritance_cost;
252
+ cost_right = combined_right - aabb3_box_surface_area_2(right) + inheritance_cost;
250
253
  }
251
254
  } else {
252
255
  cost_right = Infinity;
@@ -1045,10 +1048,9 @@ export class BinaryNode extends Node {
1045
1048
 
1046
1049
  const sibling = this.__insertion_findSiblingFor(child);
1047
1050
 
1048
- const sibling_parent = sibling.parentNode;
1049
- let parent = sibling_parent;
1051
+ let parent = sibling.parentNode;
1050
1052
 
1051
- if (sibling_parent === null) {
1053
+ if (parent === null) {
1052
1054
  // "sibling" is the root node
1053
1055
 
1054
1056
  parent = sibling;
@@ -1069,15 +1071,15 @@ export class BinaryNode extends Node {
1069
1071
 
1070
1072
  // non-root
1071
1073
 
1072
- if (sibling_parent.left === sibling && sibling_parent.right === null) {
1074
+ if (parent.left === sibling && parent.right === null) {
1073
1075
 
1074
1076
  // right node is free, take it
1075
- sibling_parent.setChildRight(child);
1077
+ parent.setChildRight(child);
1076
1078
 
1077
- } else if (sibling_parent.right === sibling && sibling_parent.left === null) {
1079
+ } else if (parent.right === sibling && parent.left === null) {
1078
1080
 
1079
1081
  // left node is free, take it
1080
- sibling_parent.setChildLeft(child);
1082
+ parent.setChildLeft(child);
1081
1083
 
1082
1084
  } else {
1083
1085
 
@@ -1088,7 +1090,7 @@ export class BinaryNode extends Node {
1088
1090
  }
1089
1091
 
1090
1092
  // walk back up the tree fixing heights and bounds
1091
- while (parent !== null) {
1093
+ do {
1092
1094
  // parent = this.balance();
1093
1095
 
1094
1096
  const left = parent.left;
@@ -1098,7 +1100,7 @@ export class BinaryNode extends Node {
1098
1100
  parent.refit();
1099
1101
 
1100
1102
  parent = parent.parentNode;
1101
- }
1103
+ } while (parent !== null);
1102
1104
  }
1103
1105
 
1104
1106
  /**
@@ -1152,25 +1154,7 @@ BinaryNode.prototype.isBinaryNode = true;
1152
1154
  * @returns {number}
1153
1155
  */
1154
1156
  function inclusion_surface_area_heuristic(node, addition) {
1155
- return combined_surface_area(node, addition) - aabb3_box_surface_area_2(node);
1156
- }
1157
-
1158
- /**
1159
- *
1160
- * @param {AABB3} node
1161
- * @param {AABB3} addition
1162
- * @returns {number}
1163
- */
1164
- function combined_surface_area(node, addition) {
1165
- const x0 = min2(node.x0, addition.x0);
1166
- const y0 = min2(node.y0, addition.y0);
1167
- const z0 = min2(node.z0, addition.z0);
1168
-
1169
- const x1 = max2(node.x1, addition.x1);
1170
- const y1 = max2(node.y1, addition.y1);
1171
- const z1 = max2(node.z1, addition.z1);
1172
-
1173
- return aabb3_compute_half_surface_area(x0, y0, z0, x1, y1, z1);
1157
+ return aabb3_combined_surface_area(node, addition) - aabb3_box_surface_area_2(node);
1174
1158
  }
1175
1159
 
1176
1160
  /**
@@ -32,13 +32,13 @@ export function aabb3_intersects_frustum_array(aabb, frustum) {
32
32
  export function aabb3_intersects_frustum(x0, y0, z0, x1, y1, z1, frustum) {
33
33
  for (let i = 0; i < 24; i += 4) {
34
34
 
35
- const plane_n_x = frustum[i];
36
- const plane_n_y = frustum[i + 1];
37
- const plane_n_z = frustum[i + 2];
38
- const plane_constant = frustum[i + 3];
35
+ const plane_x = frustum[i];
36
+ const plane_y = frustum[i + 1];
37
+ const plane_z = frustum[i + 2];
38
+ const plane_w = frustum[i + 3];
39
39
 
40
40
  const plane_distance = aabb3_computeDistanceAbovePlane(
41
- plane_n_x, plane_n_y, plane_n_z, plane_constant,
41
+ plane_x, plane_y, plane_z, plane_w,
42
42
  x0, y0, z0,
43
43
  x1, y1, z1
44
44
  );
@@ -0,0 +1,21 @@
1
+ import { min2 } from "../math/min2.js";
2
+ import { max2 } from "../math/max2.js";
3
+ import { aabb3_compute_half_surface_area } from "./aabb3/aabb3_compute_half_surface_area.js";
4
+
5
+ /**
6
+ *
7
+ * @param {AABB3} a
8
+ * @param {AABB3} b
9
+ * @returns {number}
10
+ */
11
+ export function aabb3_combined_surface_area(a, b) {
12
+ const x0 = min2(a.x0, b.x0);
13
+ const y0 = min2(a.y0, b.y0);
14
+ const z0 = min2(a.z0, b.z0);
15
+
16
+ const x1 = max2(a.x1, b.x1);
17
+ const y1 = max2(a.y1, b.y1);
18
+ const z1 = max2(a.z1, b.z1);
19
+
20
+ return aabb3_compute_half_surface_area(x0, y0, z0, x1, y1, z1);
21
+ }
@@ -8,45 +8,57 @@ const stack = [];
8
8
  /**
9
9
  * @template T
10
10
  * @param {T[]} destination
11
- * @param {number} destinationOffset
11
+ * @param {number} destination_offset
12
12
  * @param {BinaryNode<T>} root
13
13
  * @param {ArrayLike<number>|number[]|Float32Array} frustum
14
14
  * @returns {number} Number of results
15
15
  */
16
- export function queryBinaryNode_FrustumIntersections_Data(destination, destinationOffset, root, frustum) {
16
+ export function queryBinaryNode_FrustumIntersections_Data(destination, destination_offset, root, frustum) {
17
+
18
+ /**
19
+ * @type {BinaryNode<T>|LeafNode<T>}
20
+ */
17
21
  let n;
18
- let i = 0;
22
+ let offset = destination_offset;
19
23
  let stackPointer = 1;
20
24
 
21
25
  stack[0] = root;
22
26
 
23
27
  while (stackPointer > 0) {
28
+
24
29
  stackPointer--;
25
30
 
26
31
  n = stack[stackPointer];
27
32
 
28
- if (!n.intersectFrustum_array(frustum)) {
33
+ const node_intersects_frustum = n.intersectFrustum_array(frustum);
34
+
35
+ if (!node_intersects_frustum) {
29
36
  continue;
30
37
  }
31
38
 
32
- if (n.isBinaryNode) {
39
+ if (n.isBinaryNode === true) {
33
40
 
34
- if (n.right !== null) {
35
- stack[stackPointer++] = n.right;
41
+ const right = n.right;
42
+
43
+ if (right !== null) {
44
+ stack[stackPointer++] = right;
36
45
  }
37
46
 
38
- if (n.left !== null) {
39
- stack[stackPointer++] = n.left;
47
+ const left = n.left;
48
+
49
+ if (left !== null) {
50
+ stack[stackPointer++] = left;
40
51
  }
41
52
 
42
53
  } else {
54
+ // leaf node
43
55
 
44
- destination[destinationOffset + i] = n.object;
56
+ destination[offset] = n.object;
45
57
 
46
- i++;
58
+ offset++;
47
59
  }
48
60
 
49
61
  }
50
62
 
51
- return i;
63
+ return offset - destination_offset;
52
64
  }
@@ -28,4 +28,6 @@ export class Cache<K, V> {
28
28
  clear(): void
29
29
 
30
30
  drop(): void
31
+
32
+ getOrCompute(key: K, compute: (key: K) => V, compute_context?: any): V
31
33
  }
@@ -1,7 +1,7 @@
1
1
  import { assert } from "../assert.js";
2
2
  import { HashMap } from "../collection/HashMap.js";
3
3
  import Signal from "../events/signal/Signal.js";
4
- import { noop, returnOne, returnZero, strictEquals } from "../function/Functions.js";
4
+ import { returnOne, returnZero, strictEquals } from "../function/Functions.js";
5
5
  import { CacheElement } from "./CacheElement.js";
6
6
 
7
7
  /**
@@ -14,33 +14,25 @@ export class Cache {
14
14
  * @param {number} [maxWeight=Number.POSITIVE_INFINITY]
15
15
  * @param {function(key:Key):number} [keyWeigher= key=>0]
16
16
  * @param {function(value:Value):number} [valueWeigher= value=>1]
17
- * @param {function(key:Key, value:Value)} [removeListener] will be notified when element is either explicitly removed or evicted
18
17
  * @param {function(Key):number} [keyHashFunction]
19
18
  * @param {function(Key, Key):boolean} [keyEqualityFunction]
20
19
  * @param {number} capacity initial capacity for the cache, helps prevent early resizing
21
20
  * @constructor
22
- * @template Key, Value
23
21
  */
24
22
  constructor({
25
23
  maxWeight = Number.POSITIVE_INFINITY,
26
24
  keyWeigher = returnZero,
27
25
  valueWeigher = returnOne,
28
- removeListener = noop,
29
26
  keyHashFunction = returnZero,
30
27
  keyEqualityFunction = strictEquals,
31
28
  capacity
32
29
  } = {}) {
33
30
 
34
31
  assert.isNumber(maxWeight, 'maxWeight');
35
- assert.typeOf(keyWeigher, 'function', 'keyWeigher');
36
- assert.typeOf(valueWeigher, 'function', 'valueWeigher');
37
- assert.typeOf(removeListener, 'function', 'removeListener');
38
- assert.typeOf(keyHashFunction, 'function', 'keyHashFunction');
39
- assert.typeOf(keyEqualityFunction, 'function', 'keyEqualityFunction');
40
-
41
- if (removeListener !== noop) {
42
- console.warn('removalListener is deprecated, use onRemoved signal instead');
43
- }
32
+ assert.isFunction(keyWeigher, 'keyWeigher');
33
+ assert.isFunction(valueWeigher, 'valueWeigher');
34
+ assert.isFunction(keyHashFunction, 'keyHashFunction');
35
+ assert.isFunction(keyEqualityFunction, 'keyEqualityFunction');
44
36
 
45
37
  /**
46
38
  *
@@ -70,13 +62,6 @@ export class Cache {
70
62
  */
71
63
  this.valueWeigher = valueWeigher;
72
64
 
73
- /**
74
- *
75
- * @type {function(Key, Value)}
76
- * @private
77
- */
78
- this.removeListener = removeListener;
79
-
80
65
  /**
81
66
  *
82
67
  * @type {CacheElement<Key,Value>|null}
@@ -93,7 +78,7 @@ export class Cache {
93
78
 
94
79
  /**
95
80
  *
96
- * @type {HashMap<Key, CacheElement<Key,Value>t>}
81
+ * @type {HashMap<Key, CacheElement<Key,Value>>}
97
82
  * @private
98
83
  */
99
84
  this.data = new HashMap({
@@ -398,13 +383,32 @@ export class Cache {
398
383
  this.__removeElement(element);
399
384
 
400
385
  //notify
401
- this.removeListener(key, element.value);
402
-
403
386
  this.onRemoved.send2(key, element.value);
404
387
 
405
388
  return true;
406
389
  }
407
390
 
391
+ /**
392
+ *
393
+ * @param {Key} key
394
+ * @param {function(Key):Value} compute
395
+ * @param {*} [compute_context]
396
+ * @return {Value}
397
+ */
398
+ getOrCompute(key, compute, compute_context) {
399
+ const existing = this.get(key);
400
+
401
+ if (existing !== null) {
402
+ return existing;
403
+ }
404
+
405
+ const value = compute.call(compute_context, key);
406
+
407
+ this.set(key, value);
408
+
409
+ return value;
410
+ }
411
+
408
412
  /**
409
413
  * Remove all elements from the cache
410
414
  */
@@ -7,53 +7,58 @@
7
7
  * @param {number} z
8
8
  * @param {number} w
9
9
  */
10
- function array_set_plane_normalized(destination, destination_offset, x, y, z, w) {
10
+ function array_set_plane_normalized(
11
+ destination, destination_offset,
12
+ x, y, z, w
13
+ ) {
11
14
  // compute vector length
12
15
  const length = Math.hypot(x, y, z);
13
16
 
14
- const inverseNormalLength = 1.0 / length;
17
+ const inverse_length = 1.0 / length;
15
18
 
16
19
  // apply normalization
17
- destination[destination_offset] = x * inverseNormalLength;
18
- destination[destination_offset + 1] = y * inverseNormalLength;
19
- destination[destination_offset + 2] = z * inverseNormalLength;
20
- destination[destination_offset + 3] = w * inverseNormalLength;
20
+ destination[destination_offset] = x * inverse_length;
21
+ destination[destination_offset + 1] = y * inverse_length;
22
+ destination[destination_offset + 2] = z * inverse_length;
23
+ destination[destination_offset + 3] = w * inverse_length;
21
24
  }
22
25
 
23
26
  /**
24
27
  * Set frustum from projection matrix
28
+ * NOTE: uses Gribb/Hartmann method
29
+ * @see "Fast Extraction of Viewing Frustum Planes from the WorldView-Projection Matrix", 2001 by Gribb & Hartmann
25
30
  * @param {number[]|Float32Array} frustum_planes
26
- * @param {number[]} me
31
+ * @param {number[]} m4
27
32
  */
28
- export function frustum_from_projection_matrix_array(frustum_planes, me) {
33
+ export function frustum_from_projection_matrix_array(frustum_planes, m4) {
29
34
 
30
- const me0 = me[0];
31
- const me3 = me[3];
35
+ const me0 = m4[0];
36
+ const me3 = m4[3];
32
37
 
33
- const me4 = me[4];
34
- const me7 = me[7];
38
+ const me4 = m4[4];
39
+ const me7 = m4[7];
35
40
 
36
- const me8 = me[8];
37
- const me11 = me[11];
41
+ const me8 = m4[8];
42
+ const me11 = m4[11];
38
43
 
39
- const me12 = me[12];
40
- const me15 = me[15];
44
+ const me12 = m4[12];
45
+ const me15 = m4[15];
41
46
 
42
47
  array_set_plane_normalized(frustum_planes, 0, me3 - me0, me7 - me4, me11 - me8, me15 - me12);
43
48
  array_set_plane_normalized(frustum_planes, 4, me3 + me0, me7 + me4, me11 + me8, me15 + me12);
44
49
 
45
- const me1 = me[1];
46
- const me5 = me[5];
47
- const me9 = me[9];
48
- const me13 = me[13];
50
+ const me1 = m4[1];
51
+ const me5 = m4[5];
52
+ const me9 = m4[9];
53
+ const me13 = m4[13];
49
54
 
50
55
  array_set_plane_normalized(frustum_planes, 8, me3 + me1, me7 + me5, me11 + me9, me15 + me13);
51
56
  array_set_plane_normalized(frustum_planes, 12, me3 - me1, me7 - me5, me11 - me9, me15 - me13);
52
57
 
53
- const me2 = me[2];
54
- const me6 = me[6];
55
- const me10 = me[10];
56
- const me14 = me[14];
58
+ const me2 = m4[2];
59
+ const me6 = m4[6];
60
+ const me10 = m4[10];
61
+ const me14 = m4[14];
57
62
 
58
63
  array_set_plane_normalized(frustum_planes, 16, me3 - me2, me7 - me6, me11 - me10, me15 - me14);
59
64
  array_set_plane_normalized(frustum_planes, 20, me3 + me2, me7 + me6, me11 + me10, me15 + me14);
package/core/math/max2.js CHANGED
@@ -6,9 +6,5 @@
6
6
  * @returns {number}
7
7
  */
8
8
  export function max2(a, b) {
9
- if (a < b) {
10
- return b;
11
- } else {
12
- return a;
13
- }
14
- }
9
+ return a < b ? b : a;
10
+ }
package/core/math/min2.js CHANGED
@@ -5,9 +5,5 @@
5
5
  * @returns {number}
6
6
  */
7
7
  export function min2(a, b) {
8
- if (a < b) {
9
- return a;
10
- } else {
11
- return b;
12
- }
13
- }
8
+ return a < b ? a : b;
9
+ }
@@ -1,4 +1,5 @@
1
1
  import { isArrayEqualStrict } from "../../../../../core/collection/array/isArrayEqualStrict.js";
2
+ import { is_typed_array_equals } from "../../../../../core/collection/array/typed/is_typed_array_equals.js";
2
3
 
3
4
 
4
5
  /**
@@ -17,7 +18,7 @@ export function computeGeometryEquality(a, b) {
17
18
  return false;
18
19
  }
19
20
 
20
- if (!isArrayEqualStrict(a_index.array, b_index.array)) {
21
+ if (!is_typed_array_equals(a_index.array, b_index.array)) {
21
22
  return false;
22
23
  }
23
24
  }
@@ -46,7 +47,7 @@ export function computeGeometryEquality(a, b) {
46
47
  const a_attribute = a.attributes[key];
47
48
  const b_attribute = b.attributes[key];
48
49
 
49
- if (!isArrayEqualStrict(a_attribute.array, b_attribute.array)) {
50
+ if (!is_typed_array_equals(a_attribute.array, b_attribute.array)) {
50
51
  return false;
51
52
  }
52
53
  }
@@ -1,4 +1,5 @@
1
1
  import { computeBufferAttributeHash } from "./computeBufferAttributeHash.js";
2
+ import { computeStringHash } from "../../../../../core/primitives/strings/computeStringHash.js";
2
3
 
3
4
  /**
4
5
  *
@@ -6,7 +7,14 @@ import { computeBufferAttributeHash } from "./computeBufferAttributeHash.js";
6
7
  * @returns {number}
7
8
  */
8
9
  export function computeGeometryHash(geometry) {
9
- let hash = computeBufferAttributeHash(geometry.getIndex());
10
+ let hash = 0;
11
+ const attributes = geometry.attributes;
12
+
13
+ for (const attributesKey in attributes) {
14
+ hash = hash * 31 + computeStringHash(attributesKey);
15
+ }
16
+
17
+ hash ^= computeBufferAttributeHash(geometry.getIndex());
10
18
 
11
19
  const position_attribute = geometry.getAttribute('position');
12
20
 
@@ -1319,11 +1319,16 @@ export class EntityComponentDataset {
1319
1319
 
1320
1320
  const numObservers = observersStore.length;
1321
1321
 
1322
- let i;
1322
+ if (numObservers === 0) {
1323
+ // no observers
1324
+ return;
1325
+ }
1326
+
1327
+ let i = 0;
1323
1328
 
1324
1329
  const args = [];
1325
1330
 
1326
- for (i = 0; i < numObservers; i++) {
1331
+ for (; i < numObservers; i++) {
1327
1332
  const observer = observersStore[i];
1328
1333
 
1329
1334
  const match = matchComponentMask(this.componentOccupancy, entityIndex, this.componentTypeCount, observer.componentMask);
@@ -2,6 +2,8 @@ import { BitSet } from "../../../core/binary/BitSet.js";
2
2
  import { InstancedMeshGroup } from "../../graphics/geometry/instancing/InstancedMeshGroup.js";
3
3
  import { queryBinaryNode_FrustumIntersections_Data } from "../../../core/bvh2/traversal/queryBinaryNode_FrustumIntersections.js";
4
4
  import Quaternion from "../../../core/geom/Quaternion.js";
5
+ import { compose_matrix4_array } from "../../graphics/util/composeMatrix4.js";
6
+ import Vector3 from "../../../core/geom/Vector3.js";
5
7
 
6
8
  /**
7
9
  *
@@ -153,13 +155,21 @@ export class ViewState {
153
155
 
154
156
  tempQuaternion.decodeFromUint32(encodedRotation);
155
157
 
158
+ scratch_v3_0.set(positionX, positionY, positionZ);
159
+ scratch_v3_1.set(scaleX, scaleY, scaleZ);
160
+
161
+ // compose transform
162
+ compose_matrix4_array(scratch_transform, scratch_v3_0, tempQuaternion, scratch_v3_1);
163
+
156
164
  //apply instance transforms
157
- instances.setPositionAt(i, positionX, positionY, positionZ);
158
- instances.setRotationAt(i, tempQuaternion.x, tempQuaternion.y, tempQuaternion.z, tempQuaternion.w);
159
- instances.setScaleAt(i, scaleX, scaleY, scaleZ);
165
+ instances.setTransformAt(i, scratch_transform);
166
+ instances.requestAttributeUpdate();
160
167
  }
161
168
  }
162
169
  }
163
170
 
164
171
  const tempQuaternion = new Quaternion();
172
+ const scratch_v3_0 = new Vector3();
173
+ const scratch_v3_1 = new Vector3();
165
174
  const rowData = [];
175
+ const scratch_transform = new Float32Array(16);