@woosh/meep-engine 2.74.0 → 2.75.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 (36) hide show
  1. package/build/bundle-worker-image-decoder.js +1 -1
  2. package/build/meep.cjs +183 -187
  3. package/build/meep.min.js +1 -1
  4. package/build/meep.module.js +183 -187
  5. package/package.json +1 -1
  6. package/src/core/binary/UINT32_MAX.js +5 -0
  7. package/src/core/bvh2/bvh3/BVH.js +44 -2
  8. package/src/core/bvh2/bvh3/BVH.spec.js +45 -0
  9. package/src/core/bvh2/bvh3/build_triangle_morton_codes.js +73 -0
  10. package/src/core/bvh2/bvh3/ebvh_build_for_geometry_morton.js +5 -101
  11. package/src/core/bvh2/bvh3/ebvh_build_hierarchy.js +59 -0
  12. package/src/core/bvh2/bvh3/query/bvh_query_user_data_nearest_to_point.js +31 -32
  13. package/src/core/bvh2/bvh3/query/bvh_query_user_data_nearest_to_point.spec.js +64 -0
  14. package/src/core/collection/SCRATCH_UINT32_TRAVERSAL_STACK.js +1 -0
  15. package/src/core/geom/3d/aabb/aabb3_signed_distance_sqr_to_point.js +1 -0
  16. package/src/core/geom/3d/aabb/aabb3_unsigned_distance_sqr_to_point.js +36 -0
  17. package/src/core/process/worker/OnDemandWorkerManager.js +5 -1
  18. package/src/engine/asset/loaders/ArrayBufferLoader.js +13 -15
  19. package/src/engine/asset/loaders/image/ImageDecoderWorker.js +1 -1
  20. package/src/engine/asset/loaders/image/ImageRGBADataLoader.js +5 -7
  21. package/src/engine/asset/loaders/image/codec/ThreadedImageDecoder.js +1 -1
  22. package/src/engine/asset/loaders/image/png/PNG.js +339 -332
  23. package/src/engine/asset/loaders/image/png/PNGReader.js +59 -16
  24. package/src/engine/asset/loaders/image/png/prototypePNG.js +13 -4
  25. package/src/engine/graphics/texture/virtual/v2/{SparseTexture.js → PageTexture.js} +62 -18
  26. package/src/engine/graphics/texture/virtual/v2/ResidentTileTexture.js +46 -0
  27. package/src/engine/graphics/texture/virtual/v2/{TileLoader.js → VirtualTextureTileLoader.js} +11 -8
  28. package/src/engine/graphics/texture/virtual/v2/{UsageMetadata.js → VirtualTextureUsage.js} +2 -8
  29. package/src/engine/graphics/texture/virtual/v2/{VirtualTextureManager.js → VirtualTextureUsageUpdater.js} +7 -5
  30. package/src/engine/graphics/texture/virtual/v2/debug/ResidencyDebugView.js +17 -5
  31. package/src/engine/graphics/texture/virtual/v2/debug/UsageDebugView.js +1 -1
  32. package/src/engine/graphics/texture/virtual/v2/debug/UsagePyramidDebugView.js +1 -1
  33. package/src/engine/graphics/texture/virtual/v2/prototype.js +78 -59
  34. package/src/engine/graphics/texture/virtual/v2/tile/{TextureTile.js → VirtualTextureTile.js} +2 -2
  35. package/src/engine/graphics/texture/virtual/v2/tile/compose_tile_address.js +4 -0
  36. /package/src/engine/graphics/texture/virtual/v2/{ShaderUsage.js → VirtualTextureUsageShader.js} +0 -0
@@ -1,3 +1,5 @@
1
+ import { randomFloatBetween } from "../../math/random/randomFloatBetween.js";
2
+ import { seededRandom } from "../../math/random/seededRandom.js";
1
3
  import { BVH, NULL_NODE } from "./BVH.js";
2
4
 
3
5
  test("constructor doesn't throw", () => {
@@ -302,3 +304,46 @@ test("move leaf node", () => {
302
304
 
303
305
  expect(actual_bounds).toEqual(a_new_bounds);
304
306
  });
307
+
308
+ test.skip("performance, insert 10k random nodes", () => {
309
+
310
+ const random = seededRandom(1);
311
+
312
+ const bvh = new BVH();
313
+
314
+ const min_bound = -1000;
315
+ const max_bound = 1000;
316
+
317
+ const OBJECT_COUNT = 1000000;
318
+
319
+
320
+ for (let i = 0; i < OBJECT_COUNT; i++) {
321
+ const node = bvh.allocate_node();
322
+
323
+ bvh.node_set_user_data(node, i);
324
+
325
+ const x = randomFloatBetween(random, min_bound, max_bound);
326
+ const y = randomFloatBetween(random, min_bound, max_bound);
327
+ const z = randomFloatBetween(random, min_bound, max_bound);
328
+
329
+ const extents = randomFloatBetween(random, 1, 10);
330
+
331
+ const x0 = x - extents;
332
+ const y0 = y - extents;
333
+ const z0 = z - extents;
334
+
335
+ const x1 = x + extents;
336
+ const y1 = y + extents;
337
+ const z1 = z + extents;
338
+
339
+ // console.log([x0, y0, z0, x1, y1, z1].join(', '))
340
+
341
+ bvh.node_set_aabb_primitive(
342
+ node,
343
+ x0, y0, z0,
344
+ x1, y1, z1
345
+ );
346
+
347
+ bvh.insert_leaf(node);
348
+ }
349
+ });
@@ -0,0 +1,73 @@
1
+ import morton from "../../geom/3d/morton/Morton.js";
2
+
3
+ /**
4
+ * Compute morton codes for each triangle
5
+ * @param {number[]|Uint32Array} morton_codes
6
+ * @param {number} tri_count
7
+ * @param {number[]|Uint8Array|Uint16Array|Uint32Array} index_array
8
+ * @param {number[]|Float32Array} position_array
9
+ * @param {number} aabb_x0
10
+ * @param {number} aabb_y0
11
+ * @param {number} aabb_z0
12
+ * @param {number} aabb_x1
13
+ * @param {number} aabb_y1
14
+ * @param {number} aabb_z1
15
+ */
16
+ export function build_triangle_morton_codes(
17
+ morton_codes,
18
+ tri_count,
19
+ index_array,
20
+ position_array,
21
+ aabb_x0, aabb_y0, aabb_z0,
22
+ aabb_x1, aabb_y1, aabb_z1
23
+ ) {
24
+
25
+ const aabb_size_x = aabb_x1 - aabb_x0;
26
+ const aabb_size_y = aabb_y1 - aabb_y0;
27
+ const aabb_size_z = aabb_z1 - aabb_z0;
28
+
29
+ const morton_scale_x = aabb_size_x === 0 ? 0 : 1023 / aabb_size_x;
30
+ const morton_scale_y = aabb_size_y === 0 ? 0 : 1023 / aabb_size_y;
31
+ const morton_scale_z = aabb_size_z === 0 ? 0 : 1023 / aabb_size_z;
32
+
33
+ // compute morton codes
34
+ for (let i = 0; i < tri_count; i++) {
35
+
36
+
37
+ const i3 = i * 3;
38
+
39
+ const a = index_array[i3];
40
+ const b = index_array[i3 + 1];
41
+ const c = index_array[i3 + 2];
42
+
43
+ const a_address = a * 3;
44
+ const ax = position_array[a_address];
45
+ const ay = position_array[a_address + 1];
46
+ const az = position_array[a_address + 2];
47
+
48
+ const b_address = b * 3;
49
+ const bx = position_array[b_address];
50
+ const by = position_array[b_address + 1];
51
+ const bz = position_array[b_address + 2];
52
+
53
+ const c_address = c * 3;
54
+ const cx = position_array[c_address];
55
+ const cy = position_array[c_address + 1];
56
+ const cz = position_array[c_address + 2];
57
+
58
+ const center_x = (ax + bx + cx) * 0.333333333;
59
+ const center_y = (ay + by + cy) * 0.333333333;
60
+ const center_z = (az + bz + cz) * 0.333333333;
61
+
62
+ // normalize to bounds
63
+ const ncx = (center_x - aabb_x0) * morton_scale_x;
64
+ const ncy = (center_y - aabb_y0) * morton_scale_y;
65
+ const ncz = (center_z - aabb_z0) * morton_scale_z;
66
+
67
+ morton_codes[i] = morton(
68
+ Math.round(ncx),
69
+ Math.round(ncy),
70
+ Math.round(ncz)
71
+ );
72
+ }
73
+ }
@@ -2,9 +2,10 @@ import { compute_triangle_group_aabb3 } from "../../../engine/graphics/sh3/path_
2
2
  import { arrayQuickSort } from "../../collection/array/arrayQuickSort.js";
3
3
  import { AABB3 } from "../../geom/3d/aabb/AABB3.js";
4
4
  import { aabb3_from_v3_array } from "../../geom/3d/aabb/aabb3_from_v3_array.js";
5
- import morton from "../../geom/3d/morton/Morton.js";
6
5
  import { max2 } from "../../math/max2.js";
6
+ import { build_triangle_morton_codes } from "./build_triangle_morton_codes.js";
7
7
  import { NULL_NODE } from "./BVH.js";
8
+ import { ebvh_build_hierarchy } from "./ebvh_build_hierarchy.js";
8
9
 
9
10
  /**
10
11
  * Build the BVH bottom-up using spatial hash sorting
@@ -22,18 +23,6 @@ export function ebvh_build_for_geometry_morton(bvh, index_array, position_array)
22
23
  // get bounds for the entire geometry
23
24
  aabb3_from_v3_array(aabb3, position_array, position_array.length);
24
25
 
25
- const aabb_x0 = aabb3.x0;
26
- const aabb_y0 = aabb3.y0;
27
- const aabb_z0 = aabb3.z0;
28
-
29
- const aabb_size_x = aabb3.getExtentsX();
30
- const aabb_size_y = aabb3.getExtentsY();
31
- const aabb_size_z = aabb3.getExtentsZ();
32
-
33
- const morton_scale_x = aabb_size_x === 0 ? 0 : 1023 / aabb_size_x;
34
- const morton_scale_y = aabb_size_y === 0 ? 0 : 1023 / aabb_size_y;
35
- const morton_scale_z = aabb_size_z === 0 ? 0 : 1023 / aabb_size_z;
36
-
37
26
  // allocate nodes
38
27
  const tri_count = index_array.length / 3;
39
28
  const node_leaf_count = tri_count;
@@ -52,59 +41,15 @@ export function ebvh_build_for_geometry_morton(bvh, index_array, position_array)
52
41
  nodes[i] = (node_total_count - 1) - i;
53
42
  }
54
43
 
55
- // for (let i = node_total_count - 1; i >= 0; i--) {
56
- // // store nodes in reverse order so that top-level nodes end up on top
57
- // nodes[i] = bvh.allocate_node();
58
- // }
59
-
60
44
  const morton_codes = new Uint32Array(tri_count);
61
45
  const sorted_triangle_order = new Uint32Array(tri_count);
62
46
 
63
- // compute morton codes
64
47
  for (let i = 0; i < tri_count; i++) {
65
-
66
48
  sorted_triangle_order[i] = i;
67
-
68
- const i3 = i * 3;
69
-
70
- const a = index_array[i3];
71
- const b = index_array[i3 + 1];
72
- const c = index_array[i3 + 2];
73
-
74
- const a_address = a * 3;
75
- const ax = position_array[a_address];
76
- const ay = position_array[a_address + 1];
77
- const az = position_array[a_address + 2];
78
-
79
- const b_address = b * 3;
80
- const bx = position_array[b_address];
81
- const by = position_array[b_address + 1];
82
- const bz = position_array[b_address + 2];
83
-
84
- const c_address = c * 3;
85
- const cx = position_array[c_address];
86
- const cy = position_array[c_address + 1];
87
- const cz = position_array[c_address + 2];
88
-
89
- const center_x = (ax + bx + cx) * 0.333333333;
90
- const center_y = (ay + by + cy) * 0.333333333;
91
- const center_z = (az + bz + cz) * 0.333333333;
92
-
93
-
94
- // normalize to bounds
95
- const ncx = (center_x - aabb_x0) * morton_scale_x;
96
- const ncy = (center_y - aabb_y0) * morton_scale_y;
97
- const ncz = (center_z - aabb_z0) * morton_scale_z;
98
-
99
- const morton_code = morton(
100
- Math.round(ncx),
101
- Math.round(ncy),
102
- Math.round(ncz)
103
- );
104
-
105
- morton_codes[i] = morton_code;
106
49
  }
107
50
 
51
+ build_triangle_morton_codes(morton_codes, tri_count, index_array, position_array, aabb3.x0, aabb3.y0, aabb3.z0, aabb3.x1, aabb3.y1, aabb3.z1);
52
+
108
53
  // sort leaves by morton codes
109
54
  arrayQuickSort(sorted_triangle_order, (triangle_index) => morton_codes[triangle_index], null, 0, tri_count - 1);
110
55
 
@@ -129,47 +74,6 @@ export function ebvh_build_for_geometry_morton(bvh, index_array, position_array)
129
74
  unprocessed_nodes[i] = node;
130
75
  }
131
76
 
132
- // Assemble hierarchy
133
- let unprocessed_node_count = tri_count;
134
-
135
-
136
- while (used_index < node_total_count && unprocessed_node_count > 1) {
137
-
138
- let added_nodes = 0;
139
- let cursor = 0;
140
-
141
- while (cursor + 1 < unprocessed_node_count) {
142
- const child_1 = unprocessed_nodes[cursor++];
143
- const child_2 = unprocessed_nodes[cursor++];
144
-
145
- const parent = nodes[used_index++];
146
-
147
- bvh.node_set_combined_aabb(parent, child_1, child_2);
148
-
149
- bvh.node_set_parent(child_1, parent);
150
- bvh.node_set_parent(child_2, parent);
151
-
152
- bvh.node_set_child1(parent, child_1);
153
- bvh.node_set_child2(parent, child_2);
154
-
155
- bvh.node_set_height(parent,
156
- 1 + max2(
157
- bvh.node_get_height(child_1),
158
- bvh.node_get_height(child_2)
159
- )
160
- );
161
-
162
- unprocessed_nodes[added_nodes++] = parent;
163
- }
164
-
165
- while (cursor < unprocessed_node_count) {
166
- // dangling nodes, push them onto the next level
167
- unprocessed_nodes[added_nodes++] = unprocessed_nodes[cursor++];
168
- }
169
-
170
- unprocessed_node_count = added_nodes;
171
- }
172
-
173
77
  // assign root
174
- bvh.__root = nodes[nodes.length - 1];
78
+ bvh.__root = ebvh_build_hierarchy(bvh,unprocessed_nodes,tri_count,nodes,used_index);
175
79
  }
@@ -0,0 +1,59 @@
1
+ import { max2 } from "../../math/max2.js";
2
+
3
+ /**
4
+ * Assumes nodes are spatially sorted
5
+ * NOTE: {@link unprocessed_nodes} will be modified during execution to save memory
6
+ * @param {BVH} bvh
7
+ * @param {number[]|Uint32Array} unprocessed_nodes contains nodes that need to be built into a hierarchy, these must not be present in the BVH hierarchy
8
+ * @param {number} input_node_count
9
+ * @param {number[]|Uint32Array} node_pool Contains node indices that can be used to build ancestry hierarchy, need to be pre-allocated before calling this method
10
+ * @param {number} node_pool_offset
11
+ * @returns {number} new root
12
+ */
13
+ export function ebvh_build_hierarchy(bvh, unprocessed_nodes, input_node_count, node_pool, node_pool_offset) {
14
+
15
+ let used_index = node_pool_offset;
16
+
17
+ // Assemble hierarchy
18
+ let unprocessed_node_count = input_node_count;
19
+
20
+
21
+ while (unprocessed_node_count > 1) {
22
+
23
+ let added_nodes = 0;
24
+ let cursor = 0;
25
+
26
+ while (cursor + 1 < unprocessed_node_count) {
27
+ const child_1 = unprocessed_nodes[cursor++];
28
+ const child_2 = unprocessed_nodes[cursor++];
29
+
30
+ const parent = node_pool[used_index++];
31
+
32
+ bvh.node_set_combined_aabb(parent, child_1, child_2);
33
+
34
+ bvh.node_set_parent(child_1, parent);
35
+ bvh.node_set_parent(child_2, parent);
36
+
37
+ bvh.node_set_child1(parent, child_1);
38
+ bvh.node_set_child2(parent, child_2);
39
+
40
+ bvh.node_set_height(parent,
41
+ 1 + max2(
42
+ bvh.node_get_height(child_1),
43
+ bvh.node_get_height(child_2)
44
+ )
45
+ );
46
+
47
+ unprocessed_nodes[added_nodes++] = parent;
48
+ }
49
+
50
+ while (cursor < unprocessed_node_count) {
51
+ // dangling nodes, push them onto the next level
52
+ unprocessed_nodes[added_nodes++] = unprocessed_nodes[cursor++];
53
+ }
54
+
55
+ unprocessed_node_count = added_nodes;
56
+ }
57
+
58
+ return unprocessed_nodes[0];
59
+ }
@@ -1,13 +1,6 @@
1
1
  import { SCRATCH_UINT32_TRAVERSAL_STACK } from "../../../collection/SCRATCH_UINT32_TRAVERSAL_STACK.js";
2
- import { aabb3_signed_distance_sqr_to_point } from "../../../geom/3d/aabb/aabb3_signed_distance_sqr_to_point.js";
3
- import { max2 } from "../../../math/max2.js";
4
- import { NULL_NODE } from "../BVH.js";
5
-
6
- /**
7
- *
8
- * @type {number[]}
9
- */
10
- const scratch_aabb = [];
2
+ import { aabb3_unsigned_distance_sqr_to_point } from "../../../geom/3d/aabb/aabb3_unsigned_distance_sqr_to_point.js";
3
+ import { COLUMN_CHILD_1, COLUMN_CHILD_2, ELEMENT_WORD_COUNT, NULL_NODE } from "../BVH.js";
11
4
 
12
5
  const stack = SCRATCH_UINT32_TRAVERSAL_STACK;
13
6
 
@@ -21,7 +14,7 @@ const stack = SCRATCH_UINT32_TRAVERSAL_STACK;
21
14
  * @returns {number} user data of the leaf, or -1 if not found
22
15
  */
23
16
  export function bvh_query_user_data_nearest_to_point(bvh, x, y, z, max_distance = Infinity) {
24
- const root = bvh.root;
17
+ const root = bvh.root;
25
18
 
26
19
  if (root === NULL_NODE) {
27
20
  return -1;
@@ -35,10 +28,17 @@ export function bvh_query_user_data_nearest_to_point(bvh, x, y, z, max_distance
35
28
 
36
29
  stack[stack_top] = root;
37
30
 
38
- let best_leaf_data = -1;
31
+ let best_leaf = -1;
39
32
  let best_distance_sqr = max_distance * max_distance;
40
33
 
41
- while (stack.pointer > stack_top) {
34
+
35
+ /*
36
+ For performance, we bind data directly to avoid extra copies required to read out AABB
37
+ */
38
+ const float32 = bvh.__data_float32;
39
+ const uint32 = bvh.__data_uint32;
40
+
41
+ do {
42
42
  stack.pointer--;
43
43
 
44
44
  /**
@@ -47,42 +47,41 @@ export function bvh_query_user_data_nearest_to_point(bvh, x, y, z, max_distance
47
47
  */
48
48
  const node = stack[stack.pointer];
49
49
 
50
- bvh.node_get_aabb(node, scratch_aabb);
50
+ const address = node * ELEMENT_WORD_COUNT;
51
51
 
52
52
  // compute distance to box
53
- const distance_sqr = max2(0, aabb3_signed_distance_sqr_to_point(
54
- scratch_aabb[0], scratch_aabb[1], scratch_aabb[2],
55
- scratch_aabb[3], scratch_aabb[4], scratch_aabb[5],
53
+ const distance_sqr = aabb3_unsigned_distance_sqr_to_point(
54
+ float32[address], float32[address + 1], float32[address + 2],
55
+ float32[address + 3], float32[address + 4], float32[address + 5],
56
56
  x, y, z
57
- ));
57
+ );
58
58
 
59
- if (distance_sqr > best_distance_sqr) {
59
+ if (distance_sqr >= best_distance_sqr) {
60
60
  // node is too far
61
61
  continue;
62
62
  }
63
63
 
64
- const node_is_leaf = bvh.node_is_leaf(node);
65
-
66
- if (!node_is_leaf) {
64
+ // get fist child to check if this is a leaf node or not
65
+ const child_1 = uint32[address + COLUMN_CHILD_1];
67
66
 
68
- // read in-order
69
- const child1 = bvh.node_get_child1(node);
70
- const child2 = bvh.node_get_child2(node);
67
+ if (child_1 !== NULL_NODE) {
71
68
 
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;
69
+ // this is not a leaf node, push children onto traversal stack
70
+ stack[stack.pointer++] = child_1;
71
+ stack[stack.pointer++] = uint32[address + COLUMN_CHILD_2];
75
72
 
76
73
  } else {
77
74
 
78
75
  // leaf node
79
- if (distance_sqr < best_distance_sqr) {
80
- best_distance_sqr = distance_sqr;
81
- best_leaf_data = bvh.node_get_user_data(node);
82
- }
76
+ best_distance_sqr = distance_sqr;
77
+ best_leaf = node;
83
78
 
84
79
  }
80
+ } while (stack.pointer > stack_top)
81
+
82
+ if (best_leaf === -1) {
83
+ return -1;
85
84
  }
86
85
 
87
- return best_leaf_data;
86
+ return bvh.node_get_user_data(best_leaf);
88
87
  }
@@ -1,3 +1,5 @@
1
+ import { randomFloatBetween } from "../../../math/random/randomFloatBetween.js";
2
+ import { seededRandom } from "../../../math/random/seededRandom.js";
1
3
  import { BVH } from "../BVH.js";
2
4
  import { bvh_query_user_data_nearest_to_point } from "./bvh_query_user_data_nearest_to_point.js";
3
5
 
@@ -68,3 +70,65 @@ test('two point, distance sufficient to both', () => {
68
70
 
69
71
  expect(result).toBe(0);
70
72
  });
73
+
74
+
75
+ test.skip("performance, 1M random boxes, 10k queries", () => {
76
+
77
+ const random = seededRandom(1);
78
+
79
+ const bvh = new BVH();
80
+
81
+ const min_bound = -1000;
82
+ const max_bound = 1000;
83
+
84
+ const OBJECT_COUNT = 1000000;
85
+
86
+ for (let i = 0; i < OBJECT_COUNT; i++) {
87
+ const node = bvh.allocate_node();
88
+
89
+ bvh.node_set_user_data(node, i);
90
+
91
+ const x = randomFloatBetween(random, min_bound, max_bound);
92
+ const y = randomFloatBetween(random, min_bound, max_bound);
93
+ const z = randomFloatBetween(random, min_bound, max_bound);
94
+
95
+ const extents = randomFloatBetween(random, 1, 50);
96
+
97
+ const x0 = x - extents;
98
+ const y0 = y - extents;
99
+ const z0 = z - extents;
100
+
101
+ const x1 = x + extents;
102
+ const y1 = y + extents;
103
+ const z1 = z + extents;
104
+
105
+ bvh.node_set_aabb_primitive(
106
+ node,
107
+ x0, y0, z0,
108
+ x1, y1, z1
109
+ );
110
+
111
+ bvh.insert_leaf(node);
112
+ }
113
+
114
+ const SAMPLE_POINT_COUNT = 10000;
115
+
116
+ const t0 = performance.now();
117
+
118
+ for (let i = 0; i < SAMPLE_POINT_COUNT; i++) {
119
+
120
+ const x = randomFloatBetween(random, min_bound, max_bound);
121
+ const y = randomFloatBetween(random, min_bound, max_bound);
122
+ const z = randomFloatBetween(random, min_bound, max_bound);
123
+
124
+ bvh_query_user_data_nearest_to_point(
125
+ bvh, x, y, z
126
+ );
127
+ }
128
+
129
+ const t1 = performance.now();
130
+
131
+ const duration = (t1 - t0);
132
+
133
+ console.log(`${duration / SAMPLE_POINT_COUNT}ms/query`);
134
+ });
@@ -8,6 +8,7 @@ export const SCRATCH_UINT32_TRAVERSAL_STACK = new Uint32Array(781250);
8
8
 
9
9
  /**
10
10
  * Pointer used to track current top of the stack, make sure to unwind once your traversal is done
11
+ * Must be a positive integer
11
12
  * @type {number}
12
13
  */
13
14
  SCRATCH_UINT32_TRAVERSAL_STACK.pointer = 0;
@@ -45,3 +45,4 @@ export function aabb3_signed_distance_sqr_to_point(
45
45
  return -(dx * dx + dy * dy + dz * dz);
46
46
  }
47
47
  }
48
+
@@ -0,0 +1,36 @@
1
+ import { max3 } from "../../../math/max3.js";
2
+
3
+ /**
4
+ * Compute squared distance to point, value is negative if the point is inside the box
5
+ * @param {number} x0
6
+ * @param {number} y0
7
+ * @param {number} z0
8
+ * @param {number} x1
9
+ * @param {number} y1
10
+ * @param {number} z1
11
+ * @param {number} point_x
12
+ * @param {number} point_y
13
+ * @param {number} point_z
14
+ * @returns {number}
15
+ */
16
+ export function aabb3_unsigned_distance_sqr_to_point(
17
+ x0, y0, z0,
18
+ x1, y1, z1,
19
+ point_x, point_y, point_z
20
+ ) {
21
+ //do projection
22
+ const xp0 = x0 - point_x;
23
+ const xp1 = point_x - x1;
24
+ const yp0 = y0 - point_y;
25
+ const yp1 = point_y - y1;
26
+ const zp0 = z0 - point_z;
27
+ const zp1 = point_z - z1;
28
+
29
+ //calculate separation in each axis
30
+ const dx = max3(0, xp0, xp1);
31
+ const dy = max3(0, yp0, yp1);
32
+ const dz = max3(0, zp0, zp1);
33
+
34
+ //straight-line distance
35
+ return dx * dx + dy * dy + dz * dz;
36
+ }
@@ -1,4 +1,4 @@
1
- import {assert} from "../../assert.js";
1
+ import { assert } from "../../assert.js";
2
2
 
3
3
  export class OnDemandWorkerManager {
4
4
 
@@ -35,6 +35,10 @@ export class OnDemandWorkerManager {
35
35
  this.worker = worker;
36
36
  }
37
37
 
38
+ /**
39
+ * In milliseconds
40
+ * @param {number} v
41
+ */
38
42
  setTimeout(v) {
39
43
  assert.isNonNegativeInteger(v, 'v');
40
44
 
@@ -1,8 +1,8 @@
1
+ import { noop } from "../../../core/function/Functions.js";
1
2
  import { Asset } from "../Asset.js";
2
- import { AssetLoader } from "./AssetLoader.js";
3
- import { CrossOriginKind } from "../CORS/CrossOriginKind.js";
4
3
  import { CrossOriginConfig } from "../CORS/CrossOriginConfig.js";
5
- import { noop } from "../../../core/function/Functions.js";
4
+ import { CrossOriginKind } from "../CORS/CrossOriginKind.js";
5
+ import { AssetLoader } from "./AssetLoader.js";
6
6
 
7
7
  export class ArrayBufferLoader extends AssetLoader {
8
8
  /**
@@ -90,33 +90,31 @@ export class ArrayBufferLoader extends AssetLoader {
90
90
  const reader = response.body.getReader();
91
91
  const contentLength = response.headers.get('Content-Length');
92
92
  const total = contentLength ? parseInt(contentLength) : 0;
93
- const lengthComputable = total !== 0;
94
93
  let loaded = 0;
95
94
 
96
95
  // periodically read data into the new stream tracking while download progress
97
96
  const stream = new ReadableStream({
97
+ type: "bytes",
98
98
  start(controller) {
99
99
 
100
- readData();
100
+ pump();
101
101
 
102
- function readData() {
102
+ function pump() {
103
103
 
104
104
  reader.read().then(({ done, value }) => {
105
105
 
106
106
  if (done) {
107
-
107
+ // no more data, we're done
108
108
  controller.close();
109
+ return;
110
+ }
109
111
 
110
- } else {
111
-
112
- loaded += value.byteLength;
113
-
114
- progress(loaded, length);
112
+ loaded += value.byteLength;
115
113
 
116
- controller.enqueue(value);
117
- readData();
114
+ progress(loaded, total);
118
115
 
119
- }
116
+ controller.enqueue(value);
117
+ pump();
120
118
 
121
119
  });
122
120
 
@@ -23,7 +23,7 @@ async function decode_png(png_bytes) {
23
23
  width,
24
24
  height,
25
25
  itemSize: uint_channels.itemSize,
26
- bitDepth: png.bitDepth
26
+ bitDepth: 8
27
27
  });
28
28
  });
29
29
  }
@@ -1,12 +1,11 @@
1
- import { AssetLoader } from "../AssetLoader.js";
2
- import { GameAssetType } from "../../GameAssetType.js";
1
+ import { computeFileExtension } from "../../../../core/path/computeFileExtension.js";
3
2
  import { convertTexture2Sampler2D } from "../../../graphics/texture/sampler/convertTexture2Sampler2D.js";
4
- import { ImageRGBADataAsset } from "./ImageRGBADataAsset.js";
3
+ import { GameAssetType } from "../../GameAssetType.js";
5
4
  import { ArrayBufferLoader } from "../ArrayBufferLoader.js";
5
+ import { AssetLoader } from "../AssetLoader.js";
6
6
  import { CodecWithFallback } from "./codec/CodecWithFallback.js";
7
7
  import { ThreadedImageDecoder } from "./codec/ThreadedImageDecoder.js";
8
- import { NativeImageDecoder } from "./codec/NativeImageDecoder.js";
9
- import { computeFileExtension } from "../../../../core/path/computeFileExtension.js";
8
+ import { ImageRGBADataAsset } from "./ImageRGBADataAsset.js";
10
9
 
11
10
  const ASSET_TYPE_ARRAY_BUFFER = "arraybuffer";
12
11
 
@@ -16,7 +15,7 @@ export class ImageRGBADataLoader extends AssetLoader {
16
15
 
17
16
  this.decoder = new CodecWithFallback(
18
17
  new ThreadedImageDecoder(),
19
- new NativeImageDecoder()
18
+ // new NativeImageDecoder()
20
19
  );
21
20
  }
22
21
 
@@ -58,7 +57,6 @@ export class ImageRGBADataLoader extends AssetLoader {
58
57
 
59
58
  const bitmap = await this.__decode_via_worker(path, scope);
60
59
 
61
-
62
60
  let data;
63
61
 
64
62
  const bitDepth = bitmap.bitDepth;
@@ -21,7 +21,7 @@ export class ThreadedImageDecoder extends Codec {
21
21
  */
22
22
  this.worker = new OnDemandWorkerManager(workerBuilder.build());
23
23
 
24
- this.worker.setTimeout(200);
24
+ this.worker.setTimeout(1200);
25
25
  }
26
26
 
27
27
  async test(data) {