@woosh/meep-engine 2.87.6 → 2.88.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 (58) hide show
  1. package/build/meep.cjs +26 -4
  2. package/build/meep.min.js +1 -1
  3. package/build/meep.module.js +26 -4
  4. package/editor/view/ecs/HierarchicalEntityListView.js +1 -1
  5. package/editor/view/v2/prototypeEditor.js +1 -1
  6. package/package.json +1 -1
  7. package/src/core/bvh2/bvh3/BVH.d.ts.map +1 -1
  8. package/src/core/bvh2/bvh3/BVH.js +4 -2
  9. package/src/core/bvh2/bvh3/BVH.spec.js +15 -3
  10. package/src/core/geom/2d/aabb/aabb2_clip_line_cohen_sutherland.d.ts +16 -0
  11. package/src/core/geom/2d/aabb/aabb2_clip_line_cohen_sutherland.d.ts.map +1 -0
  12. package/src/core/geom/2d/aabb/aabb2_clip_line_cohen_sutherland.js +149 -0
  13. package/src/core/geom/2d/aabb/aabb2_intersects_circle.d.ts +13 -0
  14. package/src/core/geom/2d/aabb/aabb2_intersects_circle.d.ts.map +1 -0
  15. package/src/core/geom/2d/aabb/aabb2_intersects_circle.js +27 -0
  16. package/src/core/geom/2d/hash-grid/SpatialHashGrid.d.ts +41 -6
  17. package/src/core/geom/2d/hash-grid/SpatialHashGrid.d.ts.map +1 -1
  18. package/src/core/geom/2d/hash-grid/SpatialHashGrid.js +92 -22
  19. package/src/core/geom/2d/hash-grid/SpatialHashGrid.spec.js +98 -2
  20. package/src/core/geom/2d/hash-grid/prototypeGridQueries.d.ts +2 -0
  21. package/src/core/geom/2d/hash-grid/prototypeGridQueries.d.ts.map +1 -0
  22. package/src/core/geom/2d/hash-grid/prototypeGridQueries.js +387 -0
  23. package/src/core/geom/2d/hash-grid/shg_query_elements_circle.d.ts +12 -0
  24. package/src/core/geom/2d/hash-grid/shg_query_elements_circle.d.ts.map +1 -0
  25. package/src/core/geom/2d/hash-grid/shg_query_elements_circle.js +160 -0
  26. package/src/core/geom/2d/hash-grid/shg_query_elements_circle.spec.d.ts +2 -0
  27. package/src/core/geom/2d/hash-grid/shg_query_elements_circle.spec.d.ts.map +1 -0
  28. package/src/core/geom/2d/hash-grid/shg_query_elements_circle.spec.js +85 -0
  29. package/src/core/geom/2d/hash-grid/shg_query_elements_line.d.ts +14 -0
  30. package/src/core/geom/2d/hash-grid/shg_query_elements_line.d.ts.map +1 -0
  31. package/src/core/geom/2d/hash-grid/shg_query_elements_line.js +132 -0
  32. package/src/core/geom/2d/hash-grid/shg_query_elements_line.spec.d.ts +2 -0
  33. package/src/core/geom/2d/hash-grid/shg_query_elements_line.spec.d.ts.map +1 -0
  34. package/src/core/geom/2d/hash-grid/shg_query_elements_line.spec.js +102 -0
  35. package/src/core/geom/2d/line/line2_distance_to_point_sqr.d.ts +11 -0
  36. package/src/core/geom/2d/line/line2_distance_to_point_sqr.d.ts.map +1 -0
  37. package/src/core/geom/2d/line/line2_distance_to_point_sqr.js +39 -0
  38. package/src/core/geom/2d/quad-tree/QuadTreeNode.spec.js +53 -0
  39. package/src/core/geom/2d/quad-tree/qt_match_data_by_circle.spec.d.ts +2 -0
  40. package/src/core/geom/2d/quad-tree/qt_match_data_by_circle.spec.d.ts.map +1 -0
  41. package/src/core/geom/2d/quad-tree/qt_match_data_by_circle.spec.js +86 -0
  42. package/src/core/model/ObservedString.d.ts.map +1 -1
  43. package/src/core/model/ObservedString.js +1 -1
  44. package/src/engine/animation/curve/ecd_bind_animation_curve.js +1 -1
  45. package/src/engine/ecs/name/Name.d.ts +25 -0
  46. package/src/engine/ecs/name/Name.d.ts.map +1 -0
  47. package/src/engine/ecs/name/Name.js +42 -0
  48. package/src/engine/ecs/name/NameSerializationAdapter.d.ts +18 -0
  49. package/src/engine/ecs/name/NameSerializationAdapter.d.ts.map +1 -0
  50. package/src/engine/ecs/name/NameSerializationAdapter.js +29 -0
  51. package/src/engine/ecs/transform/Transform.d.ts +2 -2
  52. package/src/engine/graphics/canvas/canvas2d_draw_grid.js +1 -1
  53. package/src/engine/graphics/ecs/mesh-v2/aggregate/SGMesh.d.ts.map +1 -1
  54. package/src/engine/graphics/ecs/mesh-v2/aggregate/SGMesh.js +17 -1
  55. package/src/engine/graphics/ecs/mesh-v2/three_object_to_entity_composition.js +1 -1
  56. package/src/core/geom/2d/hash-grid/shg_query_raycast.d.ts +0 -14
  57. package/src/core/geom/2d/hash-grid/shg_query_raycast.d.ts.map +0 -1
  58. package/src/core/geom/2d/hash-grid/shg_query_raycast.js +0 -21
@@ -0,0 +1,85 @@
1
+ import { randomFloatBetween } from "../../../math/random/randomFloatBetween.js";
2
+ import { seededRandom } from "../../../math/random/seededRandom.js";
3
+ import { shg_query_elements_circle } from "./shg_query_elements_circle.js";
4
+ import { SpatialHashGrid } from "./SpatialHashGrid.js";
5
+
6
+ test("performance, 10k objects, 1m queries", () => {
7
+ const OBJECT_COUNT = 30000;
8
+ const QUERY_COUNT = 1e6;
9
+
10
+ const QUERY_DISTANCE_MIN = 0.1;
11
+ const QUERY_DISTANCE_MAX = 0.2;
12
+
13
+ const grid = new SpatialHashGrid(128, 128, 2);
14
+
15
+ const grid_bounds_x1 = grid.size_x * grid.scale;
16
+ const grid_bounds_y1 = grid.size_y * grid.scale;
17
+
18
+ const random = seededRandom();
19
+
20
+ // fill
21
+ for (let i = 0; i < OBJECT_COUNT; i++) {
22
+ const el = grid.element_allocate();
23
+
24
+ grid.element_set_user_data(el, i);
25
+
26
+ const width = randomFloatBetween(random, 0.2, 1);
27
+ const height = randomFloatBetween(random, 0.2, 1);
28
+ const x0 = randomFloatBetween(random, 0, grid_bounds_x1 - width);
29
+ const y0 = randomFloatBetween(random, 0, grid_bounds_y1 - height);
30
+
31
+ grid.element_set_bounds_primitive(el,
32
+ x0,
33
+ y0,
34
+ x0 + width,
35
+ y0 + height
36
+ );
37
+
38
+ grid.element_insert(el);
39
+ }
40
+
41
+
42
+ const queries = new Float32Array(QUERY_COUNT * 3);
43
+
44
+ // build queries
45
+ for (let i = 0; i < QUERY_COUNT; i++) {
46
+
47
+ const offset = i * 3;
48
+
49
+ // pick radius
50
+ const radius = randomFloatBetween(random, QUERY_DISTANCE_MIN, QUERY_DISTANCE_MAX);
51
+
52
+ // pick starting point
53
+ const ax = randomFloatBetween(random, radius, grid_bounds_x1 - radius);
54
+ const ay = randomFloatBetween(random, radius, grid_bounds_y1 - radius);
55
+
56
+ queries[offset] = ax;
57
+ queries[offset + 1] = ay;
58
+
59
+ queries[offset + 2] = radius;
60
+ }
61
+
62
+ // execute
63
+ const t0 = performance.now();
64
+
65
+ const result = [];
66
+
67
+ for (let i = 0; i < QUERY_COUNT; i++) {
68
+
69
+ const offset = i * 3;
70
+
71
+ shg_query_elements_circle(
72
+ result, 0, grid,
73
+ queries[offset],
74
+ queries[offset + 1],
75
+ queries[offset + 2],
76
+ );
77
+ }
78
+
79
+ const duration = performance.now() - t0;
80
+
81
+ const duration_seconds = duration * 1e-3;
82
+
83
+ console.log(`Duration ${duration_seconds}s, ${(QUERY_COUNT / duration_seconds).toFixed(2)} cycles per second`);
84
+
85
+ });
@@ -0,0 +1,14 @@
1
+ /**
2
+ *
3
+ * Note that line coordinates MUST lie within the grid
4
+ * @param {number[]} result
5
+ * @param {number} result_offset
6
+ * @param {SpatialHashGrid} grid
7
+ * @param {number} x0 first line point X
8
+ * @param {number} y0 first line point Y
9
+ * @param {number} x1 second line point X
10
+ * @param {number} y1 second line point Y
11
+ * @returns {number} number of elements added to result array
12
+ */
13
+ export function shg_query_elements_line(result: number[], result_offset: number, grid: SpatialHashGrid, x0: number, y0: number, x1: number, y1: number): number;
14
+ //# sourceMappingURL=shg_query_elements_line.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shg_query_elements_line.d.ts","sourceRoot":"","sources":["../../../../../../src/core/geom/2d/hash-grid/shg_query_elements_line.js"],"names":[],"mappings":"AAaA;;;;;;;;;;;GAWG;AACH,gDATW,MAAM,EAAE,iBACR,MAAM,6BAEN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,GACJ,MAAM,CA0GlB"}
@@ -0,0 +1,132 @@
1
+ import { assert } from "../../../assert.js";
2
+ import { aabb2_clip_line_cohen_sutherland } from "../aabb/aabb2_clip_line_cohen_sutherland.js";
3
+ import { line2_distance_to_point_sqr } from "../line/line2_distance_to_point_sqr.js";
4
+ import {
5
+ COLUMN_ELEMENT_X0,
6
+ COLUMN_ELEMENT_X1,
7
+ COLUMN_ELEMENT_Y0,
8
+ COLUMN_ELEMENT_Y1,
9
+ NULL_POINTER
10
+ } from "./SpatialHashGrid.js";
11
+
12
+ const scratch_float32 = new Float32Array(4);
13
+
14
+ /**
15
+ *
16
+ * Note that line coordinates MUST lie within the grid
17
+ * @param {number[]} result
18
+ * @param {number} result_offset
19
+ * @param {SpatialHashGrid} grid
20
+ * @param {number} x0 first line point X
21
+ * @param {number} y0 first line point Y
22
+ * @param {number} x1 second line point X
23
+ * @param {number} y1 second line point Y
24
+ * @returns {number} number of elements added to result array
25
+ */
26
+ export function shg_query_elements_line(
27
+ result, result_offset,
28
+ grid,
29
+ x0, y0,
30
+ x1, y1
31
+ ) {
32
+
33
+ // shg_query_elements_line.visited.splice(0, shg_query_elements_line.visited.length); // DEBUG
34
+
35
+ assert.ok(x0 <= grid.size_x * grid.scale && x0 >= 0, `x0(=${x0}) out of bounds`);
36
+ assert.ok(x1 <= grid.size_x * grid.scale && x1 >= 0, `x1(=${x1}) out of bounds`);
37
+ assert.ok(y0 <= grid.size_y * grid.scale && y0 >= 0, `y0(=${y0}) out of bounds`);
38
+ assert.ok(y1 <= grid.size_y * grid.scale && y1 >= 0, `y1(=${y1}) out of bounds`);
39
+
40
+ // rasterize line
41
+ const scale_inverse = grid.scale_inverse;
42
+
43
+ // below is a modified version of Bresenham's line algorithm
44
+ const grid_x0 = x0 * scale_inverse;
45
+ const grid_y0 = y0 * scale_inverse;
46
+ const grid_x1 = x1 * scale_inverse;
47
+ const grid_y1 = y1 * scale_inverse;
48
+
49
+ let igrid_x0 = Math.floor(grid_x0);
50
+ let igrid_y0 = Math.floor(grid_y0);
51
+ let igrid_x1 = Math.floor(grid_x1);
52
+ let igrid_y1 = Math.floor(grid_y1);
53
+
54
+ const step_x = igrid_x0 < igrid_x1 ? 1 : -1;
55
+ const step_y = igrid_y0 < igrid_y1 ? 1 : -1;
56
+
57
+ const element_pool = grid.element_pool;
58
+ const element_float32 = element_pool.data_float32;
59
+
60
+ let result_count = 0;
61
+
62
+ let x = igrid_x0;
63
+ let y = igrid_y0;
64
+
65
+ for (; ;) {
66
+
67
+ const cell_index = grid.cell_position_to_index(x, y);
68
+
69
+ // shg_query_elements_line.visited.push(x, y); // DEBUG
70
+
71
+ let node = grid.cell_get_first_node(cell_index);
72
+
73
+ while (node !== NULL_POINTER) {
74
+
75
+ const element = grid.node_get_element(node);
76
+
77
+ // check element bounds
78
+ const element_address = element_pool.element_word(element);
79
+
80
+ const element_x0 = element_float32[element_address + COLUMN_ELEMENT_X0];
81
+ const element_y0 = element_float32[element_address + COLUMN_ELEMENT_Y0];
82
+ const element_x1 = element_float32[element_address + COLUMN_ELEMENT_X1];
83
+ const element_y1 = element_float32[element_address + COLUMN_ELEMENT_Y1];
84
+
85
+ if (aabb2_clip_line_cohen_sutherland(
86
+ scratch_float32, 0,
87
+ element_x0, element_y0,
88
+ element_x1, element_y1,
89
+ x0, y0, x1, y1
90
+ )) {
91
+ // intersection with the element
92
+ result[result_offset + result_count] = element;
93
+
94
+ result_count++;
95
+ }
96
+
97
+
98
+ // read out next element in the linked list
99
+ node = grid.node_get_same_cell_next_node(node);
100
+
101
+ }
102
+
103
+ if (x === igrid_x1 && y === igrid_y1) {
104
+ // we're done
105
+ break;
106
+ }
107
+
108
+ // check moves forward
109
+ const move_x_distance = line2_distance_to_point_sqr(
110
+ grid_x0, grid_y0, grid_x1, grid_y1,
111
+ x + step_x + 0.5, y + 0.5
112
+ );
113
+
114
+ const move_y_distance = line2_distance_to_point_sqr(
115
+ grid_x0, grid_y0, grid_x1, grid_y1,
116
+ x + 0.5, y + step_y + 0.5
117
+ );
118
+
119
+ if (move_x_distance <= move_y_distance && x !== igrid_x1) {
120
+ x += step_x;
121
+ } else if (y !== igrid_y1) {
122
+ y += step_y;
123
+ } else {
124
+ // unexpected, or we just reached the end
125
+ break;
126
+ }
127
+ }
128
+
129
+ return result_count;
130
+ }
131
+
132
+ // shg_query_elements_line.visited = []; // DEBUG
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=shg_query_elements_line.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shg_query_elements_line.spec.d.ts","sourceRoot":"","sources":["../../../../../../src/core/geom/2d/hash-grid/shg_query_elements_line.spec.js"],"names":[],"mappings":""}
@@ -0,0 +1,102 @@
1
+ import { randomFloatBetween } from "../../../math/random/randomFloatBetween.js";
2
+ import { seededRandom } from "../../../math/random/seededRandom.js";
3
+ import { shg_query_elements_line } from "./shg_query_elements_line.js";
4
+ import { SpatialHashGrid } from "./SpatialHashGrid.js";
5
+
6
+ test.skip("performance, 10k objects, 100k queries", () => {
7
+ const OBJECT_COUNT = 30000;
8
+ const QUERY_COUNT = 100000;
9
+
10
+ const QUERY_DISTANCE_MIN = 0.1;
11
+ const QUERY_DISTANCE_MAX = 0.2;
12
+
13
+ const grid = new SpatialHashGrid(128, 128, 1);
14
+
15
+ const grid_bounds_x1 = grid.size_x * grid.scale;
16
+ const grid_bounds_y1 = grid.size_y * grid.scale;
17
+
18
+ const random = seededRandom();
19
+
20
+ // fill
21
+ for (let i = 0; i < OBJECT_COUNT; i++) {
22
+ const el = grid.element_allocate();
23
+
24
+ grid.element_set_user_data(el, i);
25
+
26
+ const width = randomFloatBetween(random, 0.2, 1);
27
+ const height = randomFloatBetween(random, 0.2, 1);
28
+ const x0 = randomFloatBetween(random, 0, grid_bounds_x1 - width);
29
+ const y0 = randomFloatBetween(random, 0, grid_bounds_y1 - height);
30
+
31
+ grid.element_set_bounds_primitive(el,
32
+ x0,
33
+ y0,
34
+ x0 + width,
35
+ y0 + height
36
+ );
37
+
38
+ grid.element_insert(el);
39
+ }
40
+
41
+
42
+ const queries = new Float32Array(QUERY_COUNT * 4);
43
+
44
+ // build queries
45
+ for (let i = 0; i < QUERY_COUNT; i++) {
46
+
47
+ const offset = i * 4;
48
+
49
+ // pick starting point
50
+ const ax = randomFloatBetween(random, 0.001, grid_bounds_x1 - 0.001);
51
+ const ay = randomFloatBetween(random, 0.001, grid_bounds_y1 - 0.001);
52
+
53
+
54
+ const angle = randomFloatBetween(random, -Math.PI, Math.PI);
55
+
56
+ let direction_x = Math.cos(angle);
57
+ let direction_y = Math.sin(angle);
58
+
59
+ if (direction_x * (ax - grid_bounds_x1 * 0.5) > 0) {
60
+ direction_x = -direction_x;
61
+ }
62
+ if (direction_y * (ay - grid_bounds_y1 * 0.5) > 0) {
63
+ direction_y = -direction_y;
64
+ }
65
+
66
+ const query_distance = randomFloatBetween(random, QUERY_DISTANCE_MIN, QUERY_DISTANCE_MAX);
67
+
68
+ const bx = ax + direction_x * query_distance;
69
+ const by = ay + direction_y * query_distance;
70
+
71
+ queries[offset] = ax;
72
+ queries[offset + 1] = ay;
73
+
74
+ queries[offset + 2] = bx;
75
+ queries[offset + 3] = by;
76
+ }
77
+
78
+ // execute
79
+ const t0 = performance.now();
80
+
81
+ const result = [];
82
+
83
+ for (let i = 0; i < QUERY_COUNT; i++) {
84
+
85
+ const offset = i * 4;
86
+
87
+ shg_query_elements_line(
88
+ result, 0, grid,
89
+ queries[offset],
90
+ queries[offset + 1],
91
+ queries[offset + 2],
92
+ queries[offset + 3],
93
+ );
94
+ }
95
+
96
+ const duration = performance.now() - t0;
97
+
98
+ const duration_seconds = duration * 1e-3;
99
+
100
+ console.log(`Duration ${duration_seconds}s, ${(QUERY_COUNT / duration_seconds).toFixed(2)} cycles per second`);
101
+
102
+ });
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Computes squared shortest distance between a line segment(defined by 2 points) and a point
3
+ * @param {number} x0
4
+ * @param {number} y0
5
+ * @param {number} x1
6
+ * @param {number} y1
7
+ * @param {number} px
8
+ * @param {number} py
9
+ */
10
+ export function line2_distance_to_point_sqr(x0: number, y0: number, x1: number, y1: number, px: number, py: number): number;
11
+ //# sourceMappingURL=line2_distance_to_point_sqr.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"line2_distance_to_point_sqr.d.ts","sourceRoot":"","sources":["../../../../../../src/core/geom/2d/line/line2_distance_to_point_sqr.js"],"names":[],"mappings":"AAGA;;;;;;;;GAQG;AACH,gDAPW,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,UA4BhB"}
@@ -0,0 +1,39 @@
1
+ import { clamp01 } from "../../../math/clamp01.js";
2
+ import { v2_distance_sqr } from "../../vec2/v2_distance_sqr.js";
3
+
4
+ /**
5
+ * Computes squared shortest distance between a line segment(defined by 2 points) and a point
6
+ * @param {number} x0
7
+ * @param {number} y0
8
+ * @param {number} x1
9
+ * @param {number} y1
10
+ * @param {number} px
11
+ * @param {number} py
12
+ */
13
+ export function line2_distance_to_point_sqr(
14
+ x0, y0,
15
+ x1, y1,
16
+ px, py
17
+ ) {
18
+ // get line delta
19
+ const line_delta_x = x1 - x0;
20
+ const line_delta_y = y1 - y0;
21
+
22
+ // find closest point
23
+ const sp0_x = px - x0;
24
+ const sp0_y = py - y0;
25
+
26
+ //
27
+ const d2 = line_delta_x * line_delta_x + line_delta_y * line_delta_y;
28
+
29
+ const d3 = line_delta_x * sp0_x + line_delta_y * sp0_y;
30
+
31
+ const t = clamp01(d3 / d2);
32
+
33
+ // compute point on the line
34
+ const lp_x = line_delta_x * t + x0;
35
+ const lp_y = line_delta_y * t + y0;
36
+
37
+ // compute distance from the point in question to the point on the line
38
+ return v2_distance_sqr(px, py, lp_x, lp_y);
39
+ }
@@ -1,4 +1,6 @@
1
1
  import { jest } from "@jest/globals";
2
+ import { randomFloatBetween } from "../../../math/random/randomFloatBetween.js";
3
+ import { seededRandom } from "../../../math/random/seededRandom.js";
2
4
  import { QuadTreeDatum } from "./QuadTreeDatum.js";
3
5
  import { QuadTreeNode } from "./QuadTreeNode.js";
4
6
 
@@ -180,3 +182,54 @@ test('test traverseRectangleIntersections', () => {
180
182
  expect(visitor0).toHaveBeenCalledWith(d, 0, 0, 3, 3);
181
183
  expect(visitor0).toHaveBeenCalledWith(e, 0, 0, 3, 3);
182
184
  });
185
+
186
+ test.skip("performance, insertion 1m random", () => {
187
+ const tree = new QuadTreeNode(0, 0, 100, 100);
188
+
189
+ const random = seededRandom(42);
190
+
191
+ const N = 1000000;
192
+
193
+ const boxes = new Float32Array(N * 4);
194
+
195
+ for (let i = 0; i < N; i++) {
196
+
197
+ const position_x = randomFloatBetween(random, 0, 98);
198
+ const position_y = randomFloatBetween(random, 0, 98);
199
+
200
+ const size_x = randomFloatBetween(random, 0.1, 2);
201
+ const size_y = randomFloatBetween(random, 0.1, 2);
202
+
203
+
204
+ const i4 = i * 4;
205
+ boxes[i4] = position_x;
206
+ boxes[i4 + 1] = position_y;
207
+ boxes[i4 + 2] = position_x + size_x;
208
+ boxes[i4 + 3] = position_y + size_y;
209
+ }
210
+
211
+ // perform insertion
212
+ const t0 = performance.now();
213
+
214
+ for (let i = 0; i < N; i++) {
215
+ const i4 = i * 4;
216
+
217
+ const x0 = boxes[i4];
218
+ const y0 = boxes[i4 + 1];
219
+ const x1 = boxes[i4 + 2];
220
+ const y1 = boxes[i4 + 3];
221
+
222
+ tree.add(i,
223
+ x0,
224
+ y0,
225
+ x1,
226
+ y1
227
+ );
228
+ }
229
+
230
+ const duration = performance.now() - t0;
231
+
232
+ const duration_seconds = duration * 1e-3;
233
+
234
+ console.log(`Duration ${duration_seconds}s, ${(N / duration_seconds).toFixed(2)} records per second`);
235
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=qt_match_data_by_circle.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qt_match_data_by_circle.spec.d.ts","sourceRoot":"","sources":["../../../../../../src/core/geom/2d/quad-tree/qt_match_data_by_circle.spec.js"],"names":[],"mappings":""}
@@ -0,0 +1,86 @@
1
+ import { returnTrue } from "../../../function/returnTrue.js";
2
+ import { randomFloatBetween } from "../../../math/random/randomFloatBetween.js";
3
+ import { seededRandom } from "../../../math/random/seededRandom.js";
4
+ import { qt_match_data_by_circle } from "./qt_match_data_by_circle.js";
5
+ import { QuadTreeNode } from "./QuadTreeNode.js";
6
+
7
+ test.skip("performance, 10k objects, 1m queries", () => {
8
+ const OBJECT_COUNT = 30000;
9
+ const QUERY_COUNT = 1e6;
10
+
11
+ const QUERY_DISTANCE_MIN = 0.1;
12
+ const QUERY_DISTANCE_MAX = 0.2;
13
+
14
+ const grid_bounds_x1 = 256;
15
+ const grid_bounds_y1 = 256;
16
+
17
+ const tree = new QuadTreeNode(0, 0, grid_bounds_x1, grid_bounds_y1);
18
+
19
+
20
+ const random = seededRandom();
21
+
22
+ // fill
23
+ for (let i = 0; i < OBJECT_COUNT; i++) {
24
+
25
+ const width = randomFloatBetween(random, 0.2, 1);
26
+ const height = randomFloatBetween(random, 0.2, 1);
27
+ const x0 = randomFloatBetween(random, 0, grid_bounds_x1 - width);
28
+ const y0 = randomFloatBetween(random, 0, grid_bounds_y1 - height);
29
+
30
+ tree.add(i,
31
+ x0,
32
+ y0,
33
+ x0 + width,
34
+ y0 + height
35
+ )
36
+
37
+ }
38
+
39
+
40
+ const queries = new Float32Array(QUERY_COUNT * 3);
41
+
42
+ // build queries
43
+ for (let i = 0; i < QUERY_COUNT; i++) {
44
+
45
+ const offset = i * 3;
46
+
47
+ // pick radius
48
+ const radius = randomFloatBetween(random, QUERY_DISTANCE_MIN, QUERY_DISTANCE_MAX);
49
+
50
+ // pick starting point
51
+ const ax = randomFloatBetween(random, radius, grid_bounds_x1 - radius);
52
+ const ay = randomFloatBetween(random, radius, grid_bounds_y1 - radius);
53
+
54
+ queries[offset] = ax;
55
+ queries[offset + 1] = ay;
56
+
57
+ queries[offset + 2] = radius;
58
+ }
59
+
60
+ // execute
61
+ const t0 = performance.now();
62
+
63
+ const result = [];
64
+
65
+ for (let i = 0; i < QUERY_COUNT; i++) {
66
+
67
+ const offset = i * 3;
68
+
69
+ qt_match_data_by_circle(
70
+ result,
71
+ 0,
72
+ tree,
73
+ queries[offset],
74
+ queries[offset + 1],
75
+ queries[offset + 2],
76
+ returnTrue
77
+ );
78
+ }
79
+
80
+ const duration = performance.now() - t0;
81
+
82
+ const duration_seconds = duration * 1e-3;
83
+
84
+ console.log(`Duration ${duration_seconds}s, ${(QUERY_COUNT / duration_seconds).toFixed(2)} cycles per second`);
85
+
86
+ });
@@ -1 +1 @@
1
- {"version":3,"file":"ObservedString.d.ts","sourceRoot":"","sources":["../../../../src/core/model/ObservedString.js"],"names":[],"mappings":";AASA;IACI;;;;OAIG;IACH,4BAaC;IARG;;;;OAIG;IACH,gBAAoB;IAEpB,0DAA6B;IAmBjC;;;;OAIG;IACH,oBAFa,cAAc,CAa1B;IAED;;;OAGG;IACH,YAFW,cAAc,QAIxB;IAED;;;;OAIG;IACH,cAHW,cAAc,GACZ,OAAO,CAInB;IAED;;;OAGG;IACH,mBAEC;IAED;;;OAGG;IACH,2BAIC;IAED,iBAEC;IAED,yBAEC;IAED;;;OAGG;IACH,2CAEC;IAED;;;OAGG;IACH,6CAIC;IAED,eAEC;IAGL;;;;OAIG;IACH,2BAFU,OAAO,CAEwB;CAPxC;mBA1HkB,4BAA4B"}
1
+ {"version":3,"file":"ObservedString.d.ts","sourceRoot":"","sources":["../../../../src/core/model/ObservedString.js"],"names":[],"mappings":";AASA;IACI;;;;OAIG;IACH,oBAHW,MAAM,EAgBhB;IARG;;;;OAIG;IACH,gBAAoB;IAEpB,0DAA6B;IAmBjC;;;;OAIG;IACH,oBAFa,cAAc,CAa1B;IAED;;;OAGG;IACH,YAFW,cAAc,QAIxB;IAED;;;;OAIG;IACH,cAHW,cAAc,GACZ,OAAO,CAInB;IAED;;;OAGG;IACH,mBAEC;IAED;;;OAGG;IACH,2BAIC;IAED,iBAEC;IAED,yBAEC;IAED;;;OAGG;IACH,2CAEC;IAED;;;OAGG;IACH,6CAIC;IAED,eAEC;IAGL;;;;OAIG;IACH,2BAFU,OAAO,CAEwB;CAPxC;mBA1HkB,4BAA4B"}
@@ -10,7 +10,7 @@ import { computeStringHash } from "../primitives/strings/computeStringHash.js";
10
10
  class ObservedString extends String {
11
11
  /**
12
12
  *
13
- * @param {String} [value]
13
+ * @param {string} [value]
14
14
  * @constructor
15
15
  */
16
16
  constructor(value = "") {
@@ -1,4 +1,4 @@
1
- import Name from "../../../../../model/game/ecs/component/Name.js";
1
+ import Name from "../../ecs/name/Name.js";
2
2
  import { AnimatedValueBinding } from "../../graphics/ecs/mesh-v2/aggregate/animation/AnimatedValueBinding.js";
3
3
  import { BoundQuaternionWriter } from "../../graphics/ecs/mesh-v2/aggregate/animation/BoundQuaternionWriter.js";
4
4
  import { BoundValueWriter } from "../../graphics/ecs/mesh-v2/aggregate/animation/BoundValueWriter.js";
@@ -0,0 +1,25 @@
1
+ export default Name;
2
+ declare class Name extends ObservedString {
3
+ /**
4
+ *
5
+ * @param {string} [value]
6
+ */
7
+ constructor(value?: string);
8
+ /**
9
+ *
10
+ * @returns {string}
11
+ */
12
+ getLocalizationKey(): string;
13
+ /**
14
+ *
15
+ * @param {Localization} localization
16
+ * @returns {string}
17
+ */
18
+ getLocalizedValue(localization: Localization): string;
19
+ clone(): Name;
20
+ }
21
+ declare namespace Name {
22
+ let typeName: string;
23
+ }
24
+ import ObservedString from "../../../core/model/ObservedString.js";
25
+ //# sourceMappingURL=Name.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Name.d.ts","sourceRoot":"","sources":["../../../../../src/engine/ecs/name/Name.js"],"names":[],"mappings":";AAEA;IACI;;;OAGG;IACH,oBAFW,MAAM,EAIhB;IAED;;;OAGG;IACH,sBAFa,MAAM,CAIlB;IAED;;;;OAIG;IACH,+CAFa,MAAM,CAIlB;IAED,cAMC;CACJ;;;;2BAnC0B,uCAAuC"}
@@ -0,0 +1,42 @@
1
+ import ObservedString from "../../../core/model/ObservedString.js";
2
+
3
+ class Name extends ObservedString {
4
+ /**
5
+ *
6
+ * @param {string} [value]
7
+ */
8
+ constructor(value = "") {
9
+ super(value);
10
+ }
11
+
12
+ /**
13
+ *
14
+ * @returns {string}
15
+ */
16
+ getLocalizationKey() {
17
+ return `component.name.${this.getValue()}`;
18
+ }
19
+
20
+ /**
21
+ *
22
+ * @param {Localization} localization
23
+ * @returns {string}
24
+ */
25
+ getLocalizedValue(localization) {
26
+ return localization.getString(this.getLocalizationKey());
27
+ }
28
+
29
+ clone() {
30
+ const clone = new Name();
31
+
32
+ clone.copy(this);
33
+
34
+ return clone;
35
+ }
36
+ }
37
+
38
+ Name.typeName = "Name";
39
+
40
+
41
+ export default Name;
42
+
@@ -0,0 +1,18 @@
1
+ export class NameSerializationAdapter extends BinaryClassSerializationAdapter {
2
+ klass: typeof Name;
3
+ /**
4
+ *
5
+ * @param {BinaryBuffer} buffer
6
+ * @param {Name} value
7
+ */
8
+ serialize(buffer: BinaryBuffer, value: Name): void;
9
+ /**
10
+ *
11
+ * @param {BinaryBuffer} buffer
12
+ * @param {Name} value
13
+ */
14
+ deserialize(buffer: BinaryBuffer, value: Name): void;
15
+ }
16
+ import { BinaryClassSerializationAdapter } from "../storage/binary/BinaryClassSerializationAdapter.js";
17
+ import Name from "./Name.js";
18
+ //# sourceMappingURL=NameSerializationAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NameSerializationAdapter.d.ts","sourceRoot":"","sources":["../../../../../src/engine/ecs/name/NameSerializationAdapter.js"],"names":[],"mappings":"AAGA;IACI,mBAAa;IAGb;;;;OAIG;IACH,uCAFW,IAAI,QAId;IAGD;;;;OAIG;IACH,yCAFW,IAAI,QAMd;CAEJ;gDA5B+C,sDAAsD;iBACrF,WAAW"}