@woosh/meep-engine 2.134.5 → 2.135.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 (155) hide show
  1. package/build/bundle-worker-image-decoder.js +1 -1
  2. package/build/bundle-worker-terrain.js +1 -1
  3. package/editor/tools/v2/TransformControlsGizmo.js +1 -1
  4. package/editor/view/node-graph/NodeGraphEditorView.js +2 -2
  5. package/package.json +1 -1
  6. package/src/core/assert.d.ts +0 -2
  7. package/src/core/assert.d.ts.map +1 -1
  8. package/src/core/assert.js +0 -6
  9. package/src/core/color/Color.d.ts +0 -5
  10. package/src/core/color/Color.d.ts.map +1 -1
  11. package/src/core/color/Color.js +1 -7
  12. package/src/core/geom/2d/hash-grid/SpatialHashGrid.js +386 -386
  13. package/src/core/geom/2d/line/line_segment_compute_line_segment_intersection_2d.js +1 -1
  14. package/src/core/geom/2d/quad-tree-binary/QuadTree.js +714 -714
  15. package/src/core/geom/3d/triangle/computeTriangleRayIntersection.js +160 -160
  16. package/src/core/geom/3d/triangle/computeTriangleRayIntersectionBarycentric.js +96 -96
  17. package/src/core/geom/packing/max-rect/MaxRectanglesPacker.js +1 -1
  18. package/src/core/geom/packing/max-rect/findBestContainer.js +4 -4
  19. package/src/core/geom/packing/max-rect/packOneBox.js +2 -2
  20. package/src/core/geom/vec3/v3_rigid_align_paired_unit_vectors.js +1 -1
  21. package/src/core/graph/layout/box/BoxLayouter.js +7 -7
  22. package/src/core/graph/layout/box/position_box_next_to_box.js +6 -6
  23. package/src/core/math/computeWholeDivisorLow.js +33 -33
  24. package/src/core/math/linalg/eigen/eigen_values_find_spectral_gap.d.ts.map +1 -0
  25. package/src/core/math/linalg/eigen/matrix_eigenvalues_in_place.d.ts +10 -0
  26. package/src/core/math/linalg/eigen/matrix_eigenvalues_in_place.d.ts.map +1 -0
  27. package/src/core/{graph → math/linalg}/eigen/matrix_eigenvalues_in_place.js +8 -7
  28. package/src/core/math/linalg/eigen/matrix_householder_in_place.d.ts.map +1 -0
  29. package/src/core/{graph → math/linalg}/eigen/matrix_householder_in_place.js +11 -5
  30. package/src/core/math/linalg/eigen/matrix_qr_in_place.d.ts +15 -0
  31. package/src/core/math/linalg/eigen/matrix_qr_in_place.d.ts.map +1 -0
  32. package/src/core/{graph → math/linalg}/eigen/matrix_qr_in_place.js +8 -2
  33. package/src/core/{graph → math/linalg}/eigen/matrix_top_eigenvector_power_iteration.d.ts +0 -3
  34. package/src/core/math/linalg/eigen/matrix_top_eigenvector_power_iteration.d.ts.map +1 -0
  35. package/src/core/{graph → math/linalg}/eigen/matrix_top_eigenvector_power_iteration.js +0 -3
  36. package/src/core/math/linalg/polynomial_complex_roots_aberth_ehrlich.d.ts +19 -0
  37. package/src/core/math/linalg/polynomial_complex_roots_aberth_ehrlich.d.ts.map +1 -0
  38. package/src/core/math/linalg/polynomial_complex_roots_aberth_ehrlich.js +161 -0
  39. package/src/core/math/linalg/polynomial_real_roots_in_interval.d.ts +15 -0
  40. package/src/core/math/linalg/polynomial_real_roots_in_interval.d.ts.map +1 -0
  41. package/src/core/math/linalg/polynomial_real_roots_in_interval.js +200 -0
  42. package/src/core/math/solveCubic.d.ts +15 -0
  43. package/src/core/math/solveCubic.d.ts.map +1 -0
  44. package/src/core/math/solveCubic.js +82 -0
  45. package/src/core/math/spline/spline3_hermite_bounds_t.d.ts +23 -0
  46. package/src/core/math/spline/spline3_hermite_bounds_t.d.ts.map +1 -0
  47. package/src/core/math/spline/spline3_hermite_bounds_t.js +109 -0
  48. package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite.d.ts +25 -0
  49. package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite.d.ts.map +1 -0
  50. package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite.js +44 -0
  51. package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite_1d.d.ts +16 -0
  52. package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite_1d.d.ts.map +1 -0
  53. package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite_1d.js +120 -0
  54. package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite_2d.d.ts +11 -0
  55. package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite_2d.d.ts.map +1 -0
  56. package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite_2d.js +451 -0
  57. package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite_nd.d.ts +12 -0
  58. package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite_nd.d.ts.map +1 -0
  59. package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite_nd.js +339 -0
  60. package/src/core/math/spline/spline3_hermite_intersects_spline3_hermite.d.ts +15 -0
  61. package/src/core/math/spline/spline3_hermite_intersects_spline3_hermite.d.ts.map +1 -0
  62. package/src/core/math/spline/spline3_hermite_intersects_spline3_hermite.js +21 -0
  63. package/src/core/math/spline/spline3_hermite_to_monomial.d.ts +24 -0
  64. package/src/core/math/spline/spline3_hermite_to_monomial.d.ts.map +1 -0
  65. package/src/core/math/spline/spline3_hermite_to_monomial.js +37 -0
  66. package/src/core/math/spline/v3_computeCatmullRomSplineUniformDistance.js +1 -1
  67. package/src/core/model/node-graph/visual/NodeGraphVisualData.js +1 -1
  68. package/src/core/model/reactive/model/util/createRandomReactiveExpression.js +185 -185
  69. package/src/core/process/delay.js +16 -16
  70. package/src/engine/animation/async/TimeSeries.js +300 -300
  71. package/src/engine/animation/curve/AnimationCurve.d.ts +0 -4
  72. package/src/engine/animation/curve/AnimationCurve.d.ts.map +1 -1
  73. package/src/engine/animation/curve/AnimationCurve.js +1 -6
  74. package/src/engine/animation/curve/draw/position_canvas_to_curve.js +2 -2
  75. package/src/engine/animation/curve/draw/position_curve_to_canvas.js +2 -2
  76. package/src/engine/ecs/fow/shader/FogOfWarRenderer.js +145 -145
  77. package/src/engine/ecs/gui/position/ViewportPositionSystem.js +2 -2
  78. package/src/engine/ecs/parent/entity_node_compute_bounding_box.js +1 -1
  79. package/src/engine/ecs/transform/Transform.d.ts +0 -10
  80. package/src/engine/ecs/transform/Transform.d.ts.map +1 -1
  81. package/src/engine/ecs/transform/Transform.js +0 -12
  82. package/src/engine/graphics/composit/CompositLayer.js +254 -254
  83. package/src/engine/graphics/ecs/mesh-v2/sg_hierarchy_compute_bounding_box_via_parent_entity.js +1 -1
  84. package/src/engine/graphics/ecs/path/tube/build/build_geometry_linear.js +2 -2
  85. package/src/engine/graphics/material/optimization/MaterialOptimizationContext.js +3 -3
  86. package/src/engine/graphics/particles/particular/engine/utils/volume/AttributeValue.js +201 -201
  87. package/src/engine/graphics/particles/particular/engine/utils/volume/prototypeParticleVolume.js +1 -1
  88. package/src/engine/graphics/render/buffer/slot/parameter/ProgramValueSlotParameterSet.js +2 -2
  89. package/src/engine/graphics/render/forward_plus/LightManager.js +1226 -1226
  90. package/src/engine/graphics/render/forward_plus/model/PointLight.js +1 -1
  91. package/src/engine/graphics/sh3/lpv/lpv_obtain_storage_cached_volume.js +1 -1
  92. package/src/engine/graphics/sh3/path_tracer/texture/sample_material.js +2 -2
  93. package/src/engine/graphics/texture/atlas/TextureAtlasDebugger.js +1 -1
  94. package/src/engine/graphics/texture/sampler/HarmonicDiffusionGrid.js +145 -145
  95. package/src/engine/graphics/texture/sampler/serialization/TextureBinaryBufferSerializer.js +2 -2
  96. package/src/engine/intelligence/behavior/ecs/BehaviorComponent.d.ts +2 -6
  97. package/src/engine/intelligence/behavior/ecs/BehaviorComponent.d.ts.map +1 -1
  98. package/src/engine/intelligence/behavior/ecs/BehaviorComponent.js +0 -10
  99. package/src/engine/intelligence/mcts/MonteCarlo.js +275 -275
  100. package/src/engine/navigation/ecs/path_following/PathFollower.js +222 -222
  101. package/src/generation/grid/GridData.js +220 -220
  102. package/src/generation/grid/generation/GridTaskDensityMarkerDistribution.js +385 -385
  103. package/src/view/elements/image/SvgImageView.js +1 -1
  104. package/src/view/elements/windrose/WindRoseDiagram.js +369 -369
  105. package/src/view/minimap/gl/MinimapFogOfWar.js +3 -3
  106. package/src/view/util/DomSizeObserver.js +1 -1
  107. package/src/core/binary/clz32.d.ts +0 -6
  108. package/src/core/binary/clz32.d.ts.map +0 -1
  109. package/src/core/binary/clz32.js +0 -5
  110. package/src/core/binary/type/dataTypeFromTypedArray.d.ts +0 -8
  111. package/src/core/binary/type/dataTypeFromTypedArray.d.ts.map +0 -1
  112. package/src/core/binary/type/dataTypeFromTypedArray.js +0 -11
  113. package/src/core/collection/array/computeHashIntegerArray.d.ts +0 -1
  114. package/src/core/collection/array/computeHashIntegerArray.d.ts.map +0 -1
  115. package/src/core/collection/array/computeHashIntegerArray.js +0 -7
  116. package/src/core/collection/array/typed/typedArrayToDataType.d.ts +0 -6
  117. package/src/core/collection/array/typed/typedArrayToDataType.d.ts.map +0 -1
  118. package/src/core/collection/array/typed/typedArrayToDataType.js +0 -6
  119. package/src/core/geom/3d/mat4/MATRIX_4_IDENTITY.d.ts +0 -6
  120. package/src/core/geom/3d/mat4/MATRIX_4_IDENTITY.d.ts.map +0 -1
  121. package/src/core/geom/3d/mat4/MATRIX_4_IDENTITY.js +0 -7
  122. package/src/core/graph/eigen/eigen_values_find_spectral_gap.d.ts.map +0 -1
  123. package/src/core/graph/eigen/matrix_eigenvalues_in_place.d.ts +0 -8
  124. package/src/core/graph/eigen/matrix_eigenvalues_in_place.d.ts.map +0 -1
  125. package/src/core/graph/eigen/matrix_householder_in_place.d.ts.map +0 -1
  126. package/src/core/graph/eigen/matrix_qr_in_place.d.ts +0 -9
  127. package/src/core/graph/eigen/matrix_qr_in_place.d.ts.map +0 -1
  128. package/src/core/graph/eigen/matrix_top_eigenvector_power_iteration.d.ts.map +0 -1
  129. package/src/core/math/spline/cubicCurve.d.ts +0 -6
  130. package/src/core/math/spline/cubicCurve.d.ts.map +0 -1
  131. package/src/core/math/spline/cubicCurve.js +0 -6
  132. package/src/core/math/spline/spline_bezier2.d.ts +0 -6
  133. package/src/core/math/spline/spline_bezier2.d.ts.map +0 -1
  134. package/src/core/math/spline/spline_bezier2.js +0 -6
  135. package/src/core/math/spline/spline_bezier3.d.ts +0 -6
  136. package/src/core/math/spline/spline_bezier3.d.ts.map +0 -1
  137. package/src/core/math/spline/spline_bezier3.js +0 -6
  138. package/src/core/math/spline/spline_bezier3_bounds.d.ts +0 -6
  139. package/src/core/math/spline/spline_bezier3_bounds.d.ts.map +0 -1
  140. package/src/core/math/spline/spline_bezier3_bounds.js +0 -6
  141. package/src/core/math/spline/spline_hermite3.d.ts +0 -6
  142. package/src/core/math/spline/spline_hermite3.d.ts.map +0 -1
  143. package/src/core/math/spline/spline_hermite3.js +0 -6
  144. package/src/core/math/spline/spline_hermite3_bounds.d.ts +0 -6
  145. package/src/core/math/spline/spline_hermite3_bounds.d.ts.map +0 -1
  146. package/src/core/math/spline/spline_hermite3_bounds.js +0 -6
  147. package/src/core/math/spline/spline_hermite3_to_bezier.d.ts +0 -2
  148. package/src/core/math/spline/spline_hermite3_to_bezier.d.ts.map +0 -1
  149. package/src/core/math/spline/spline_hermite3_to_bezier.js +0 -6
  150. package/src/engine/intelligence/behavior/decorator/RepeatUntilFailureBehavior.d.ts +0 -37
  151. package/src/engine/intelligence/behavior/decorator/RepeatUntilFailureBehavior.d.ts.map +0 -1
  152. package/src/engine/intelligence/behavior/decorator/RepeatUntilFailureBehavior.js +0 -70
  153. /package/src/core/{graph → math/linalg}/eigen/eigen_values_find_spectral_gap.d.ts +0 -0
  154. /package/src/core/{graph → math/linalg}/eigen/eigen_values_find_spectral_gap.js +0 -0
  155. /package/src/core/{graph → math/linalg}/eigen/matrix_householder_in_place.d.ts +0 -0
@@ -1,387 +1,387 @@
1
- import { assert } from "../../../assert.js";
2
- import { UINT32_MAX } from "../../../binary/UINT32_MAX.js";
3
- import { clamp } from "../../../math/clamp.js";
4
- import { BinaryElementPool } from "../../3d/topology/struct/binary/BinaryElementPool.js";
5
-
6
-
7
- export const NULL_POINTER = UINT32_MAX;
8
- /**
9
- * Single-linked list
10
- * Pointer to next NODE in the same grid cell
11
- * @type {number}
12
- */
13
- const COLUMN_NODE_SAME_NODE_NEXT = 0;
14
- /**
15
- * Single-linked list
16
- * Pointer to next NODE containing the same element
17
- * @type {number}
18
- */
19
- const COLUMN_NODE_SAME_ELEMENT_NEXT = 1;
20
- /**
21
- * Pointer to ELEMENT
22
- * @type {number}
23
- */
24
- const COLUMN_NODE_ELEMENT = 2;
25
-
26
- /**
27
- * Points to grid cell that stores this node
28
- * @type {number}
29
- */
30
- const COLUMN_NODE_GRID_INDEX = 3;
31
-
32
- const COLUMN_ELEMENT_DATA = 0;
33
- const COLUMN_ELEMENT_NODE_FIRST = 1;
34
- export const COLUMN_ELEMENT_X0 = 2;
35
- export const COLUMN_ELEMENT_Y0 = 3;
36
- export const COLUMN_ELEMENT_X1 = 4;
37
- export const COLUMN_ELEMENT_Y1 = 5;
38
-
39
- export class SpatialHashGrid {
40
- #element_pool = new BinaryElementPool(24)
41
- #node_pool = new BinaryElementPool(16);
42
- #grid_data = new Uint32Array(0);
43
-
44
- #size_x = 0;
45
- #size_y = 0;
46
-
47
- #scale = 1;
48
- #scale_inverse = 1;
49
-
50
- get size_x() {
51
- return this.#size_x;
52
- }
53
-
54
- get size_y() {
55
- return this.#size_y;
56
- }
57
-
58
- get node_pool() {
59
- return this.#node_pool;
60
- }
61
-
62
- /**
63
- *
64
- * @return {BinaryElementPool}
65
- */
66
- get element_pool() {
67
- return this.#element_pool;
68
- }
69
-
70
- get scale() {
71
- return this.#scale;
72
- }
73
-
74
- get scale_inverse() {
75
- return this.#scale_inverse;
76
- }
77
-
78
- constructor(size_x = 1, size_y = 1, scale = 8) {
79
-
80
- assert.notNaN(scale, "scale");
81
- assert.isFiniteNumber(scale, 'scale');
82
- assert.greaterThan(scale, 0, 'scale must be greater than 0');
83
-
84
- this.#size_x = size_x;
85
- this.#size_y = size_y;
86
- this.#scale = scale;
87
- this.#scale_inverse = 1 / scale;
88
-
89
- this.#build();
90
- }
91
-
92
- #build() {
93
- this.#grid_data = new Uint32Array(this.#size_x * this.#size_y);
94
-
95
- this.#grid_data.fill(NULL_POINTER);
96
- }
97
-
98
- element_allocate() {
99
- const element = this.#element_pool.allocate();
100
-
101
- return element;
102
- }
103
-
104
- element_set_user_data(element, user_data) {
105
- const pool = this.#element_pool;
106
- const address = pool.element_word(element);
107
-
108
- pool.data_uint32[address + COLUMN_ELEMENT_DATA] = user_data;
109
- }
110
-
111
- element_get_user_data(element) {
112
- const pool = this.#element_pool;
113
- const address = pool.element_word(element);
114
-
115
- return pool.data_uint32[address + COLUMN_ELEMENT_DATA];
116
- }
117
-
118
- /**
119
- * You have to remove the element from the grid before changing its bounds
120
- * @param {number} element
121
- * @param {number} x0
122
- * @param {number} y0
123
- * @param {number} x1
124
- * @param {number} y1
125
- */
126
- element_set_bounds_primitive(element, x0, y0, x1, y1) {
127
- const pool = this.#element_pool;
128
- const address = pool.element_word(element);
129
-
130
- const float32 = pool.data_float32;
131
-
132
- float32[address + COLUMN_ELEMENT_X0] = x0;
133
- float32[address + COLUMN_ELEMENT_Y0] = y0;
134
- float32[address + COLUMN_ELEMENT_X1] = x1;
135
- float32[address + COLUMN_ELEMENT_Y1] = y1;
136
- }
137
-
138
- /**
139
- *
140
- * @param {number} element
141
- */
142
- element_release(element) {
143
- this.#element_pool.release(element);
144
- }
145
-
146
- /**
147
- *
148
- * @param {number} element
149
- */
150
- element_insert(element) {
151
- const pool = this.#element_pool;
152
- const address = pool.element_word(element);
153
-
154
- const uint32 = pool.data_uint32;
155
-
156
- // make sure that we don't point at anything yet
157
- uint32[address + COLUMN_ELEMENT_NODE_FIRST] = NULL_POINTER;
158
-
159
- const float32 = pool.data_float32;
160
-
161
- const x0 = float32[address + COLUMN_ELEMENT_X0];
162
- const y0 = float32[address + COLUMN_ELEMENT_Y0];
163
- const x1 = float32[address + COLUMN_ELEMENT_X1];
164
- const y1 = float32[address + COLUMN_ELEMENT_Y1];
165
-
166
- // convert to grid coordinates
167
- const grid_x0 = Math.floor(x0 * this.#scale_inverse);
168
- const grid_y0 = Math.floor(y0 * this.#scale_inverse);
169
-
170
- const grid_x1 = Math.floor(x1 * this.#scale_inverse);
171
- const grid_y1 = Math.floor(y1 * this.#scale_inverse);
172
-
173
- for (let y = grid_y0; y <= grid_y1; y++) {
174
- for (let x = grid_x0; x <= grid_x1; x++) {
175
- this.#element_insert_into_cell(element, x, y);
176
- }
177
- }
178
- }
179
-
180
- /**
181
- *
182
- * @param {number} node
183
- * @return {number}
184
- */
185
- node_get_element(node) {
186
- const address = this.#node_pool.element_word(node);
187
- return this.#node_pool.data_uint32[address + COLUMN_NODE_ELEMENT];
188
- }
189
-
190
- /**
191
- * Next element in the linked list of cell's nodes
192
- * @param {number} node
193
- * @return {number}
194
- */
195
- node_get_same_cell_next_node(node) {
196
- const address = this.#node_pool.element_word(node);
197
-
198
- return this.#node_pool.data_uint32[address + COLUMN_NODE_SAME_NODE_NEXT];
199
- }
200
-
201
- /**
202
- *
203
- * @param {number} cell_index
204
- * @return {number}
205
- */
206
- cell_get_first_node(cell_index) {
207
- assert.lessThan(cell_index, this.#size_x * this.#size_y);
208
-
209
- return this.#grid_data[cell_index]
210
- }
211
-
212
- /**
213
- *
214
- * @param {number} x
215
- * @param {number} y
216
- * @return {number}
217
- */
218
- world_position_to_cell_index(x, y) {
219
- const grid_x = clamp(Math.floor(x * this.#scale_inverse), 0, this.#size_x - 1);
220
- const grid_y = clamp(Math.floor(y * this.#scale_inverse), 0, this.#size_y - 1);
221
-
222
- return this.cell_position_to_index(grid_x, grid_y);
223
- }
224
-
225
- /**
226
- *
227
- * @param {number} x
228
- * @param {number} y
229
- * @returns {number}
230
- */
231
- cell_position_to_index(x, y) {
232
- assert.isNonNegativeInteger(x, 'x');
233
- assert.isNonNegativeInteger(y, 'y');
234
-
235
- return y * this.#size_x + x;
236
-
237
- // const cell_count = this.#size_x * this.#size_y;
238
- //
239
- // const _x = split_by_2(x);
240
- // const _y = split_by_2(y);
241
- //
242
- // const hash = _x | (_y << 1);
243
- //
244
- // return hash % cell_count;
245
- }
246
-
247
- /**
248
- *
249
- * @param {number} cell_x
250
- * @param {number} cell_y
251
- * @return {boolean}
252
- */
253
- is_cell_empty(cell_x, cell_y) {
254
- assert.isNonNegativeInteger(cell_x, 'cell_x');
255
- assert.lessThan(cell_x, this.#size_x, 'cell_x overflow');
256
-
257
- assert.isNonNegativeInteger(cell_y, 'cell_y');
258
- assert.lessThan(cell_y, this.#size_y, 'cell_y overflow');
259
-
260
- const index = this.cell_position_to_index(cell_x, cell_y);
261
-
262
- const grid = this.#grid_data;
263
-
264
- return grid[index] === NULL_POINTER;
265
- }
266
-
267
- /**
268
- *
269
- * @param {number} element
270
- * @param {number} grid_x
271
- * @param {number} grid_y
272
- */
273
- #element_insert_into_cell(element, grid_x, grid_y) {
274
-
275
- // create a node
276
- const node_pool = this.#node_pool;
277
- const node = node_pool.allocate();
278
-
279
- const node_address = node_pool.element_word(node);
280
- const node_data_uint32 = node_pool.data_uint32;
281
-
282
- node_data_uint32[node_address + COLUMN_NODE_ELEMENT] = element;
283
-
284
- // link node to the element
285
- const element_pool = this.#element_pool;
286
- const element_address = element_pool.element_word(element);
287
-
288
- const element_data_uint32 = element_pool.data_uint32;
289
-
290
- const element_first_node = element_data_uint32[element_address + COLUMN_ELEMENT_NODE_FIRST];
291
-
292
- // point to previous first
293
- node_data_uint32[node_address + COLUMN_NODE_SAME_ELEMENT_NEXT] = element_first_node;
294
-
295
-
296
- element_data_uint32[element_address + COLUMN_ELEMENT_NODE_FIRST] = node;
297
-
298
- // link node to the cell
299
- const cell_index = this.cell_position_to_index(grid_x, grid_y);
300
-
301
- node_data_uint32[node_address + COLUMN_NODE_GRID_INDEX] = cell_index;
302
-
303
- const grid_data = this.#grid_data;
304
-
305
- const cell_first_node = grid_data[cell_index];
306
-
307
- node_data_uint32[node_address + COLUMN_NODE_SAME_NODE_NEXT] = cell_first_node;
308
-
309
- grid_data[cell_index] = node;
310
- }
311
-
312
- /**
313
- *
314
- * @param {number} cell_index
315
- * @param {number} node
316
- * @returns {boolean}
317
- */
318
- #grid_cell_remove_node(cell_index, node) {
319
- assert.isNonNegativeInteger(cell_index, 'cell_index');
320
- assert.isNonNegativeInteger(node, 'node');
321
-
322
- const pool = this.#node_pool;
323
- const node_data_uint32 = pool.data_uint32;
324
-
325
- const grid_data = this.#grid_data;
326
- let n = grid_data[cell_index]
327
- let previous = NULL_POINTER;
328
-
329
- while (n !== NULL_POINTER) {
330
- const address = pool.element_word(n);
331
- const next = node_data_uint32[address + COLUMN_NODE_SAME_NODE_NEXT];
332
-
333
- if (n === node) {
334
- // found the node to cut
335
-
336
- if (previous === NULL_POINTER) {
337
- // first element in the list
338
- grid_data[cell_index] = next;
339
- } else {
340
- const previous_address = pool.element_word(previous);
341
-
342
- node_data_uint32[previous_address + COLUMN_NODE_SAME_NODE_NEXT] = next;
343
- }
344
-
345
- return true;
346
- }
347
-
348
- previous = n;
349
- n = next;
350
- }
351
-
352
- return false;
353
- }
354
-
355
- /**
356
- *
357
- * @param {number} element
358
- */
359
- element_remove(element) {
360
- assert.isNonNegativeInteger(element, 'element');
361
-
362
- const element_pool = this.#element_pool;
363
- const address = element_pool.element_word(element);
364
-
365
- let node = element_pool.data_uint32[address + COLUMN_ELEMENT_NODE_FIRST];
366
-
367
- const node_pool = this.#node_pool;
368
- const node_data_uint32 = node_pool.data_uint32;
369
-
370
- do {
371
-
372
- const node_address = node_pool.element_word(node);
373
-
374
- const next = node_data_uint32[node_address + COLUMN_NODE_SAME_ELEMENT_NEXT];
375
-
376
- const grid_index = node_data_uint32[node_address + COLUMN_NODE_GRID_INDEX];
377
-
378
- // cut this node from CELL list
379
- this.#grid_cell_remove_node(grid_index, node);
380
-
381
-
382
- // advance onto next
383
- node = next;
384
- } while (node !== NULL_POINTER)
385
-
386
- }
1
+ import { assert } from "../../../assert.js";
2
+ import { UINT32_MAX } from "../../../binary/UINT32_MAX.js";
3
+ import { clamp } from "../../../math/clamp.js";
4
+ import { BinaryElementPool } from "../../3d/topology/struct/binary/BinaryElementPool.js";
5
+
6
+
7
+ export const NULL_POINTER = UINT32_MAX;
8
+ /**
9
+ * Single-linked list
10
+ * Pointer to next NODE in the same grid cell
11
+ * @type {number}
12
+ */
13
+ const COLUMN_NODE_SAME_NODE_NEXT = 0;
14
+ /**
15
+ * Single-linked list
16
+ * Pointer to next NODE containing the same element
17
+ * @type {number}
18
+ */
19
+ const COLUMN_NODE_SAME_ELEMENT_NEXT = 1;
20
+ /**
21
+ * Pointer to ELEMENT
22
+ * @type {number}
23
+ */
24
+ const COLUMN_NODE_ELEMENT = 2;
25
+
26
+ /**
27
+ * Points to grid cell that stores this node
28
+ * @type {number}
29
+ */
30
+ const COLUMN_NODE_GRID_INDEX = 3;
31
+
32
+ const COLUMN_ELEMENT_DATA = 0;
33
+ const COLUMN_ELEMENT_NODE_FIRST = 1;
34
+ export const COLUMN_ELEMENT_X0 = 2;
35
+ export const COLUMN_ELEMENT_Y0 = 3;
36
+ export const COLUMN_ELEMENT_X1 = 4;
37
+ export const COLUMN_ELEMENT_Y1 = 5;
38
+
39
+ export class SpatialHashGrid {
40
+ #element_pool = new BinaryElementPool(24)
41
+ #node_pool = new BinaryElementPool(16);
42
+ #grid_data = new Uint32Array(0);
43
+
44
+ #size_x = 0;
45
+ #size_y = 0;
46
+
47
+ #scale = 1;
48
+ #scale_inverse = 1;
49
+
50
+ get size_x() {
51
+ return this.#size_x;
52
+ }
53
+
54
+ get size_y() {
55
+ return this.#size_y;
56
+ }
57
+
58
+ get node_pool() {
59
+ return this.#node_pool;
60
+ }
61
+
62
+ /**
63
+ *
64
+ * @return {BinaryElementPool}
65
+ */
66
+ get element_pool() {
67
+ return this.#element_pool;
68
+ }
69
+
70
+ get scale() {
71
+ return this.#scale;
72
+ }
73
+
74
+ get scale_inverse() {
75
+ return this.#scale_inverse;
76
+ }
77
+
78
+ constructor(size_x = 1, size_y = 1, scale = 8) {
79
+
80
+ assert.notNaN(scale, "scale");
81
+ assert.isFinite(scale, 'scale');
82
+ assert.greaterThan(scale, 0, 'scale must be greater than 0');
83
+
84
+ this.#size_x = size_x;
85
+ this.#size_y = size_y;
86
+ this.#scale = scale;
87
+ this.#scale_inverse = 1 / scale;
88
+
89
+ this.#build();
90
+ }
91
+
92
+ #build() {
93
+ this.#grid_data = new Uint32Array(this.#size_x * this.#size_y);
94
+
95
+ this.#grid_data.fill(NULL_POINTER);
96
+ }
97
+
98
+ element_allocate() {
99
+ const element = this.#element_pool.allocate();
100
+
101
+ return element;
102
+ }
103
+
104
+ element_set_user_data(element, user_data) {
105
+ const pool = this.#element_pool;
106
+ const address = pool.element_word(element);
107
+
108
+ pool.data_uint32[address + COLUMN_ELEMENT_DATA] = user_data;
109
+ }
110
+
111
+ element_get_user_data(element) {
112
+ const pool = this.#element_pool;
113
+ const address = pool.element_word(element);
114
+
115
+ return pool.data_uint32[address + COLUMN_ELEMENT_DATA];
116
+ }
117
+
118
+ /**
119
+ * You have to remove the element from the grid before changing its bounds
120
+ * @param {number} element
121
+ * @param {number} x0
122
+ * @param {number} y0
123
+ * @param {number} x1
124
+ * @param {number} y1
125
+ */
126
+ element_set_bounds_primitive(element, x0, y0, x1, y1) {
127
+ const pool = this.#element_pool;
128
+ const address = pool.element_word(element);
129
+
130
+ const float32 = pool.data_float32;
131
+
132
+ float32[address + COLUMN_ELEMENT_X0] = x0;
133
+ float32[address + COLUMN_ELEMENT_Y0] = y0;
134
+ float32[address + COLUMN_ELEMENT_X1] = x1;
135
+ float32[address + COLUMN_ELEMENT_Y1] = y1;
136
+ }
137
+
138
+ /**
139
+ *
140
+ * @param {number} element
141
+ */
142
+ element_release(element) {
143
+ this.#element_pool.release(element);
144
+ }
145
+
146
+ /**
147
+ *
148
+ * @param {number} element
149
+ */
150
+ element_insert(element) {
151
+ const pool = this.#element_pool;
152
+ const address = pool.element_word(element);
153
+
154
+ const uint32 = pool.data_uint32;
155
+
156
+ // make sure that we don't point at anything yet
157
+ uint32[address + COLUMN_ELEMENT_NODE_FIRST] = NULL_POINTER;
158
+
159
+ const float32 = pool.data_float32;
160
+
161
+ const x0 = float32[address + COLUMN_ELEMENT_X0];
162
+ const y0 = float32[address + COLUMN_ELEMENT_Y0];
163
+ const x1 = float32[address + COLUMN_ELEMENT_X1];
164
+ const y1 = float32[address + COLUMN_ELEMENT_Y1];
165
+
166
+ // convert to grid coordinates
167
+ const grid_x0 = Math.floor(x0 * this.#scale_inverse);
168
+ const grid_y0 = Math.floor(y0 * this.#scale_inverse);
169
+
170
+ const grid_x1 = Math.floor(x1 * this.#scale_inverse);
171
+ const grid_y1 = Math.floor(y1 * this.#scale_inverse);
172
+
173
+ for (let y = grid_y0; y <= grid_y1; y++) {
174
+ for (let x = grid_x0; x <= grid_x1; x++) {
175
+ this.#element_insert_into_cell(element, x, y);
176
+ }
177
+ }
178
+ }
179
+
180
+ /**
181
+ *
182
+ * @param {number} node
183
+ * @return {number}
184
+ */
185
+ node_get_element(node) {
186
+ const address = this.#node_pool.element_word(node);
187
+ return this.#node_pool.data_uint32[address + COLUMN_NODE_ELEMENT];
188
+ }
189
+
190
+ /**
191
+ * Next element in the linked list of cell's nodes
192
+ * @param {number} node
193
+ * @return {number}
194
+ */
195
+ node_get_same_cell_next_node(node) {
196
+ const address = this.#node_pool.element_word(node);
197
+
198
+ return this.#node_pool.data_uint32[address + COLUMN_NODE_SAME_NODE_NEXT];
199
+ }
200
+
201
+ /**
202
+ *
203
+ * @param {number} cell_index
204
+ * @return {number}
205
+ */
206
+ cell_get_first_node(cell_index) {
207
+ assert.lessThan(cell_index, this.#size_x * this.#size_y);
208
+
209
+ return this.#grid_data[cell_index]
210
+ }
211
+
212
+ /**
213
+ *
214
+ * @param {number} x
215
+ * @param {number} y
216
+ * @return {number}
217
+ */
218
+ world_position_to_cell_index(x, y) {
219
+ const grid_x = clamp(Math.floor(x * this.#scale_inverse), 0, this.#size_x - 1);
220
+ const grid_y = clamp(Math.floor(y * this.#scale_inverse), 0, this.#size_y - 1);
221
+
222
+ return this.cell_position_to_index(grid_x, grid_y);
223
+ }
224
+
225
+ /**
226
+ *
227
+ * @param {number} x
228
+ * @param {number} y
229
+ * @returns {number}
230
+ */
231
+ cell_position_to_index(x, y) {
232
+ assert.isNonNegativeInteger(x, 'x');
233
+ assert.isNonNegativeInteger(y, 'y');
234
+
235
+ return y * this.#size_x + x;
236
+
237
+ // const cell_count = this.#size_x * this.#size_y;
238
+ //
239
+ // const _x = split_by_2(x);
240
+ // const _y = split_by_2(y);
241
+ //
242
+ // const hash = _x | (_y << 1);
243
+ //
244
+ // return hash % cell_count;
245
+ }
246
+
247
+ /**
248
+ *
249
+ * @param {number} cell_x
250
+ * @param {number} cell_y
251
+ * @return {boolean}
252
+ */
253
+ is_cell_empty(cell_x, cell_y) {
254
+ assert.isNonNegativeInteger(cell_x, 'cell_x');
255
+ assert.lessThan(cell_x, this.#size_x, 'cell_x overflow');
256
+
257
+ assert.isNonNegativeInteger(cell_y, 'cell_y');
258
+ assert.lessThan(cell_y, this.#size_y, 'cell_y overflow');
259
+
260
+ const index = this.cell_position_to_index(cell_x, cell_y);
261
+
262
+ const grid = this.#grid_data;
263
+
264
+ return grid[index] === NULL_POINTER;
265
+ }
266
+
267
+ /**
268
+ *
269
+ * @param {number} element
270
+ * @param {number} grid_x
271
+ * @param {number} grid_y
272
+ */
273
+ #element_insert_into_cell(element, grid_x, grid_y) {
274
+
275
+ // create a node
276
+ const node_pool = this.#node_pool;
277
+ const node = node_pool.allocate();
278
+
279
+ const node_address = node_pool.element_word(node);
280
+ const node_data_uint32 = node_pool.data_uint32;
281
+
282
+ node_data_uint32[node_address + COLUMN_NODE_ELEMENT] = element;
283
+
284
+ // link node to the element
285
+ const element_pool = this.#element_pool;
286
+ const element_address = element_pool.element_word(element);
287
+
288
+ const element_data_uint32 = element_pool.data_uint32;
289
+
290
+ const element_first_node = element_data_uint32[element_address + COLUMN_ELEMENT_NODE_FIRST];
291
+
292
+ // point to previous first
293
+ node_data_uint32[node_address + COLUMN_NODE_SAME_ELEMENT_NEXT] = element_first_node;
294
+
295
+
296
+ element_data_uint32[element_address + COLUMN_ELEMENT_NODE_FIRST] = node;
297
+
298
+ // link node to the cell
299
+ const cell_index = this.cell_position_to_index(grid_x, grid_y);
300
+
301
+ node_data_uint32[node_address + COLUMN_NODE_GRID_INDEX] = cell_index;
302
+
303
+ const grid_data = this.#grid_data;
304
+
305
+ const cell_first_node = grid_data[cell_index];
306
+
307
+ node_data_uint32[node_address + COLUMN_NODE_SAME_NODE_NEXT] = cell_first_node;
308
+
309
+ grid_data[cell_index] = node;
310
+ }
311
+
312
+ /**
313
+ *
314
+ * @param {number} cell_index
315
+ * @param {number} node
316
+ * @returns {boolean}
317
+ */
318
+ #grid_cell_remove_node(cell_index, node) {
319
+ assert.isNonNegativeInteger(cell_index, 'cell_index');
320
+ assert.isNonNegativeInteger(node, 'node');
321
+
322
+ const pool = this.#node_pool;
323
+ const node_data_uint32 = pool.data_uint32;
324
+
325
+ const grid_data = this.#grid_data;
326
+ let n = grid_data[cell_index]
327
+ let previous = NULL_POINTER;
328
+
329
+ while (n !== NULL_POINTER) {
330
+ const address = pool.element_word(n);
331
+ const next = node_data_uint32[address + COLUMN_NODE_SAME_NODE_NEXT];
332
+
333
+ if (n === node) {
334
+ // found the node to cut
335
+
336
+ if (previous === NULL_POINTER) {
337
+ // first element in the list
338
+ grid_data[cell_index] = next;
339
+ } else {
340
+ const previous_address = pool.element_word(previous);
341
+
342
+ node_data_uint32[previous_address + COLUMN_NODE_SAME_NODE_NEXT] = next;
343
+ }
344
+
345
+ return true;
346
+ }
347
+
348
+ previous = n;
349
+ n = next;
350
+ }
351
+
352
+ return false;
353
+ }
354
+
355
+ /**
356
+ *
357
+ * @param {number} element
358
+ */
359
+ element_remove(element) {
360
+ assert.isNonNegativeInteger(element, 'element');
361
+
362
+ const element_pool = this.#element_pool;
363
+ const address = element_pool.element_word(element);
364
+
365
+ let node = element_pool.data_uint32[address + COLUMN_ELEMENT_NODE_FIRST];
366
+
367
+ const node_pool = this.#node_pool;
368
+ const node_data_uint32 = node_pool.data_uint32;
369
+
370
+ do {
371
+
372
+ const node_address = node_pool.element_word(node);
373
+
374
+ const next = node_data_uint32[node_address + COLUMN_NODE_SAME_ELEMENT_NEXT];
375
+
376
+ const grid_index = node_data_uint32[node_address + COLUMN_NODE_GRID_INDEX];
377
+
378
+ // cut this node from CELL list
379
+ this.#grid_cell_remove_node(grid_index, node);
380
+
381
+
382
+ // advance onto next
383
+ node = next;
384
+ } while (node !== NULL_POINTER)
385
+
386
+ }
387
387
  }